diff options
Diffstat (limited to 'arch/x86/cpu/ivybridge')
-rw-r--r-- | arch/x86/cpu/ivybridge/car.S | 74 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/cpu.c | 27 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/gma.c | 16 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/microcode_intel.c | 26 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/sdram.c | 10 |
5 files changed, 111 insertions, 42 deletions
diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S index dca68e4144..9441666f5a 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -12,9 +12,11 @@ */ #include <common.h> +#include <asm/msr-index.h> #include <asm/mtrr.h> #include <asm/post.h> #include <asm/processor-flags.h> +#include <asm/arch/microcode.h> #define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg)) #define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1) @@ -45,6 +47,14 @@ car_init: movl $0xFEE00300, %esi movl %eax, (%esi) + /* TODO: Load microcode later - the 'no eviction' mode breaks this */ + movl $MSR_IA32_UCODE_WRITE, %ecx + xorl %edx, %edx + movl $_dt_ucode_base_size, %eax + movl (%eax), %eax + addl $UCODE_HEADER_LEN, %eax + wrmsr + post_code(POST_CAR_SIPI) /* Zero out all fixed range and variable range MTRRs */ movl $mtrr_table, %esi @@ -61,7 +71,7 @@ clear_mtrrs: post_code(POST_CAR_MTRR) /* Configure the default memory type to uncacheable */ - movl $MTRRdefType_MSR, %ecx + movl $MTRR_DEF_TYPE_MSR, %ecx rdmsr andl $(~0x00000cff), %eax wrmsr @@ -76,16 +86,16 @@ clear_mtrrs: post_code(POST_CAR_BASE_ADDRESS) /* Set Cache-as-RAM mask */ movl $(MTRR_PHYS_MASK_MSR(0)), %ecx - movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRRphysMaskValid), %eax + movl $(~(CACHE_AS_RAM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax movl $CPU_PHYSMASK_HI, %edx wrmsr post_code(POST_CAR_MASK) /* Enable MTRR */ - movl $MTRRdefType_MSR, %ecx + movl $MTRR_DEF_TYPE_MSR, %ecx rdmsr - orl $MTRRdefTypeEn, %eax + orl $MTRR_DEF_TYPE_EN, %eax wrmsr /* Enable cache (CR0.CD = 0, CR0.NW = 0) */ @@ -130,7 +140,7 @@ clear_mtrrs: movl $MTRR_PHYS_MASK_MSR(1), %ecx movl $CPU_PHYSMASK_HI, %edx - movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax + movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID), %eax wrmsr post_code(POST_CAR_ROM_CACHE) @@ -141,7 +151,7 @@ clear_mtrrs: xorl %edx, %edx wrmsr movl $MTRR_PHYS_MASK_MSR(2), %ecx - movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax + movl $(CACHE_MRC_MASK | MTRR_PHYS_MASK_VALID), %eax movl $CPU_PHYSMASK_HI, %edx wrmsr #endif @@ -163,6 +173,52 @@ wait_for_sipi: /* return */ jmp car_init_ret +.globl car_uninit +car_uninit: + /* Disable cache */ + movl %cr0, %eax + orl $X86_CR0_CD, %eax + movl %eax, %cr0 + + /* Disable MTRRs */ + movl $MTRR_DEF_TYPE_MSR, %ecx + rdmsr + andl $(~MTRR_DEF_TYPE_EN), %eax + wrmsr + + /* Disable the no-eviction run state */ + movl NOEVICTMOD_MSR, %ecx + rdmsr + andl $~2, %eax + wrmsr + + invd + + /* Disable the no-eviction mode */ + rdmsr + andl $~1, %eax + wrmsr + +#ifdef CONFIG_CACHE_MRC_BIN + /* Clear the MTRR that was used to cache MRC */ + xorl %eax, %eax + xorl %edx, %edx + movl $MTRR_PHYS_BASE_MSR(2), %ecx + wrmsr + movl $MTRR_PHYS_MASK_MSR(2), %ecx + wrmsr +#endif + + /* Enable MTRRs */ + movl $MTRR_DEF_TYPE_MSR, %ecx + rdmsr + orl $MTRR_DEF_TYPE_EN, %eax + wrmsr + + invd + + ret + mtrr_table: /* Fixed MTRRs */ .word 0x250, 0x258, 0x259 @@ -176,3 +232,9 @@ mtrr_table: .word 0x20C, 0x20D, 0x20E, 0x20F .word 0x210, 0x211, 0x212, 0x213 mtrr_table_end: + + .align 4 +_dt_ucode_base_size: + /* These next two fields are filled in by ifdtool */ + .long 0 /* microcode base */ + .long 0 /* microcode size */ diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 969b07b059..e9253100f6 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -49,27 +49,6 @@ static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev) pci_hose_write_config_byte(hose, dev, 0xdc, reg8); } -static void set_var_mtrr( - unsigned reg, unsigned base, unsigned size, unsigned type) - -{ - /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */ - /* FIXME: It only support 4G less range */ - wrmsr(MTRRphysBase_MSR(reg), base | type, 0); - wrmsr(MTRRphysMask_MSR(reg), ~(size - 1) | MTRRphysMaskValid, - (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1); -} - -static void enable_rom_caching(void) -{ - disable_caches(); - set_var_mtrr(1, 0xffc00000, 4 << 20, MTRR_TYPE_WRPROT); - enable_caches(); - - /* Enable Variable MTRRs */ - wrmsr(MTRRdefType_MSR, 0x800, 0); -} - static int set_flex_ratio_to_tdp_nominal(void) { msr_t flex_ratio, msr; @@ -165,10 +144,6 @@ int arch_cpu_init(void) /* This is already done in start.S, but let's do it in C */ enable_port80_on_lpc(hose, PCH_LPC_DEV); - /* already done in car.S */ - if (false) - enable_rom_caching(); - set_spi_speed(); /* @@ -288,7 +263,7 @@ int print_cpuinfo(void) enable_lapic(); ret = microcode_update_intel(); - if (ret && ret != -ENOENT && ret != -EEXIST) + if (ret) return ret; /* Enable upper 128bytes of CMOS */ diff --git a/arch/x86/cpu/ivybridge/gma.c b/arch/x86/cpu/ivybridge/gma.c index 3d7f740273..6cf9654e02 100644 --- a/arch/x86/cpu/ivybridge/gma.c +++ b/arch/x86/cpu/ivybridge/gma.c @@ -12,9 +12,11 @@ #include <fdtdec.h> #include <pci_rom.h> #include <asm/io.h> +#include <asm/mtrr.h> #include <asm/pci.h> #include <asm/arch/pch.h> #include <asm/arch/sandybridge.h> +#include <linux/kconfig.h> struct gt_powermeter { u16 reg; @@ -730,7 +732,11 @@ static int int15_handler(void) int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, const void *blob, int node) { +#ifdef CONFIG_VIDEO + ulong start; +#endif void *gtt_bar; + ulong base; u32 reg32; int ret; @@ -739,14 +745,22 @@ int gma_func0_init(pci_dev_t dev, struct pci_controller *hose, reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; pci_write_config32(dev, PCI_COMMAND, reg32); + /* Use write-combining for the graphics memory, 256MB */ + base = pci_read_bar32(hose, dev, 2); + mtrr_add_request(MTRR_TYPE_WRCOMB, base, 256 << 20); + mtrr_commit(true); + gtt_bar = (void *)pci_read_bar32(pci_bus_to_hose(0), dev, 0); debug("GT bar %p\n", gtt_bar); ret = gma_pm_init_pre_vbios(gtt_bar); if (ret) return ret; +#ifdef CONFIG_VIDEO + start = get_timer(0); ret = pci_run_vga_bios(dev, int15_handler, false); - + debug("BIOS ran in %lums\n", get_timer(start)); +#endif /* Post VBIOS init */ ret = gma_pm_init_post_vbios(gtt_bar, blob, node); if (ret) diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c index 08177510ab..2440a97c48 100644 --- a/arch/x86/cpu/ivybridge/microcode_intel.c +++ b/arch/x86/cpu/ivybridge/microcode_intel.c @@ -13,7 +13,9 @@ #include <libfdt.h> #include <asm/cpu.h> #include <asm/msr.h> +#include <asm/msr-index.h> #include <asm/processor.h> +#include <asm/arch/microcode.h> /** * struct microcode_update - standard microcode header from Intel @@ -40,8 +42,8 @@ static int microcode_decode_node(const void *blob, int node, update->data = fdt_getprop(blob, node, "data", &update->size); if (!update->data) return -EINVAL; - update->data += 48; - update->size -= 48; + update->data += UCODE_HEADER_LEN; + update->size -= UCODE_HEADER_LEN; update->header_version = fdtdec_get_int(blob, node, "intel,header-version", 0); @@ -71,15 +73,16 @@ static inline uint32_t microcode_read_rev(void) asm volatile ( "xorl %%eax, %%eax\n" "xorl %%edx, %%edx\n" - "movl $0x8b, %%ecx\n" + "movl %2, %%ecx\n" "wrmsr\n" "movl $0x01, %%eax\n" "cpuid\n" - "movl $0x8b, %%ecx\n" + "movl %2, %%ecx\n" "rdmsr\n" : /* outputs */ "=a" (low), "=d" (high) : /* inputs */ + "i" (MSR_IA32_UCODE_REV) : /* clobbers */ "ebx", "ecx" ); @@ -94,9 +97,9 @@ static void microcode_read_cpu(struct microcode_update *cpu) struct cpuid_result result; uint32_t low, high; - wrmsr(0x8b, 0, 0); + wrmsr(MSR_IA32_UCODE_REV, 0, 0); result = cpuid(1); - rdmsr(0x8b, low, cpu->update_revision); + rdmsr(MSR_IA32_UCODE_REV, low, cpu->update_revision); x86_model = (result.eax >> 4) & 0x0f; x86_family = (result.eax >> 8) & 0x0f; cpu->processor_signature = result.eax; @@ -120,6 +123,7 @@ int microcode_update_intel(void) int count; int node; int ret; + int rev; microcode_read_cpu(&cpu); node = 0; @@ -147,12 +151,16 @@ int microcode_update_intel(void) skipped++; continue; } - ret = microcode_read_rev(); - wrmsr(0x79, (ulong)update.data, 0); + wrmsr(MSR_IA32_UCODE_WRITE, (ulong)update.data, 0); + rev = microcode_read_rev(); debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n", - microcode_read_rev(), update.date_code & 0xffff, + rev, update.date_code & 0xffff, (update.date_code >> 24) & 0xff, (update.date_code >> 16) & 0xff); + if (update.update_revision != rev) { + printf("Microcode update failed\n"); + return -EFAULT; + } count++; } while (1); } diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index b95e781bbf..95047359ff 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -17,6 +17,7 @@ #include <asm/processor.h> #include <asm/gpio.h> #include <asm/global_data.h> +#include <asm/mtrr.h> #include <asm/pci.h> #include <asm/arch/me.h> #include <asm/arch/pei_data.h> @@ -430,6 +431,15 @@ static int sdram_find(pci_dev_t dev) add_memory_area(info, (2 << 28) + (2 << 20), 4 << 28); add_memory_area(info, (4 << 28) + (2 << 20), tseg_base); add_memory_area(info, 1ULL << 32, touud); + + /* Add MTRRs for memory */ + mtrr_add_request(MTRR_TYPE_WRBACK, 0, 2ULL << 30); + mtrr_add_request(MTRR_TYPE_WRBACK, 2ULL << 30, 512 << 20); + mtrr_add_request(MTRR_TYPE_WRBACK, 0xaULL << 28, 256 << 20); + mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base, 16 << 20); + mtrr_add_request(MTRR_TYPE_UNCACHEABLE, tseg_base + (16 << 20), + 32 << 20); + /* * If >= 4GB installed then memory from TOLUD to 4GB * is remapped above TOM, TOUUD will account for both |