diff options
author | Simon Glass <sjg@chromium.org> | 2014-11-12 22:42:10 -0700 |
---|---|---|
committer | Simon Glass <sjg@chromium.org> | 2014-11-21 07:34:11 +0100 |
commit | 70a09c6c3dc25b200a9d0475afcf5dfc9836b18e (patch) | |
tree | 8b4433ebbbbd7e558b4a291cb2ccd2aec14ab710 /arch/x86/cpu | |
parent | d1cd045982b1e1e4db2c1cc2b2b932f739b78a11 (diff) | |
download | u-boot-imx-70a09c6c3dc25b200a9d0475afcf5dfc9836b18e.zip u-boot-imx-70a09c6c3dc25b200a9d0475afcf5dfc9836b18e.tar.gz u-boot-imx-70a09c6c3dc25b200a9d0475afcf5dfc9836b18e.tar.bz2 |
x86: chromebook_link: Implement CAR support (cache as RAM)
Add support for CAR so that we have memory to use prior to DRAM init.
On link there is a total of 128KB of CAR available, although some is
used for the memory reference code.
Signed-off-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'arch/x86/cpu')
-rw-r--r-- | arch/x86/cpu/ivybridge/car.S | 162 | ||||
-rw-r--r-- | arch/x86/cpu/ivybridge/cpu.c | 2 |
2 files changed, 162 insertions, 2 deletions
diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S index 0480813..dca68e4 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -12,9 +12,167 @@ */ #include <common.h> +#include <asm/mtrr.h> +#include <asm/post.h> +#include <asm/processor-flags.h> - /* Note: ebp must not be touched in this code */ +#define MTRR_PHYS_BASE_MSR(reg) (0x200 + 2 * (reg)) +#define MTRR_PHYS_MASK_MSR(reg) (0x200 + 2 * (reg) + 1) + +#define CACHE_AS_RAM_SIZE CONFIG_DCACHE_RAM_SIZE +#define CACHE_AS_RAM_BASE CONFIG_DCACHE_RAM_BASE + +/* Cache 4GB - MRC_SIZE_KB for MRC */ +#define CACHE_MRC_BYTES ((CONFIG_CACHE_MRC_SIZE_KB << 10) - 1) +#define CACHE_MRC_BASE (0xFFFFFFFF - CACHE_MRC_BYTES) +#define CACHE_MRC_MASK (~CACHE_MRC_BYTES) + +#define CPU_PHYSMASK_HI (1 << (CONFIG_CPU_ADDR_BITS - 32) - 1) + +#define NOEVICTMOD_MSR 0x2e0 + + /* + * Note: ebp must not be touched in this code as it holds the BIST + * value (built-in self test). We preserve this value until it can + * be written to global_data when CAR is ready for use. + */ .globl car_init car_init: - /* TODO: Add cache-as-RAM init here */ + post_code(POST_CAR_START) + + /* Send INIT IPI to all excluding ourself */ + movl $0x000C4500, %eax + movl $0xFEE00300, %esi + movl %eax, (%esi) + + post_code(POST_CAR_SIPI) + /* Zero out all fixed range and variable range MTRRs */ + movl $mtrr_table, %esi + movl $((mtrr_table_end - mtrr_table) / 2), %edi + xorl %eax, %eax + xorl %edx, %edx +clear_mtrrs: + movw (%esi), %bx + movzx %bx, %ecx + wrmsr + add $2, %esi + dec %edi + jnz clear_mtrrs + + post_code(POST_CAR_MTRR) + /* Configure the default memory type to uncacheable */ + movl $MTRRdefType_MSR, %ecx + rdmsr + andl $(~0x00000cff), %eax + wrmsr + + post_code(POST_CAR_UNCACHEABLE) + /* Set Cache-as-RAM base address */ + movl $(MTRR_PHYS_BASE_MSR(0)), %ecx + movl $(CACHE_AS_RAM_BASE | MTRR_TYPE_WRBACK), %eax + xorl %edx, %edx + wrmsr + + 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 $CPU_PHYSMASK_HI, %edx + wrmsr + + post_code(POST_CAR_MASK) + + /* Enable MTRR */ + movl $MTRRdefType_MSR, %ecx + rdmsr + orl $MTRRdefTypeEn, %eax + wrmsr + + /* Enable cache (CR0.CD = 0, CR0.NW = 0) */ + movl %cr0, %eax + andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax + invd + movl %eax, %cr0 + + /* enable the 'no eviction' mode */ + movl $NOEVICTMOD_MSR, %ecx + rdmsr + orl $1, %eax + andl $~2, %eax + wrmsr + + /* Clear the cache memory region. This will also fill up the cache */ + movl $CACHE_AS_RAM_BASE, %esi + movl %esi, %edi + movl $(CACHE_AS_RAM_SIZE / 4), %ecx + xorl %eax, %eax + rep stosl + + /* enable the 'no eviction run' state */ + movl $NOEVICTMOD_MSR, %ecx + rdmsr + orl $3, %eax + wrmsr + + post_code(POST_CAR_FILL) + /* Enable Cache-as-RAM mode by disabling cache */ + movl %cr0, %eax + orl $X86_CR0_CD, %eax + movl %eax, %cr0 + + /* Enable cache for our code in Flash because we do XIP here */ + movl $MTRR_PHYS_BASE_MSR(1), %ecx + xorl %edx, %edx + movl $car_init_ret, %eax + andl $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax + orl $MTRR_TYPE_WRPROT, %eax + wrmsr + + movl $MTRR_PHYS_MASK_MSR(1), %ecx + movl $CPU_PHYSMASK_HI, %edx + movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax + wrmsr + + post_code(POST_CAR_ROM_CACHE) +#ifdef CONFIG_CACHE_MRC_BIN + /* Enable caching for ram init code to run faster */ + movl $MTRR_PHYS_BASE_MSR(2), %ecx + movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax + xorl %edx, %edx + wrmsr + movl $MTRR_PHYS_MASK_MSR(2), %ecx + movl $(CACHE_MRC_MASK | MTRRphysMaskValid), %eax + movl $CPU_PHYSMASK_HI, %edx + wrmsr +#endif + + post_code(POST_CAR_MRC_CACHE) + /* Enable cache */ + movl %cr0, %eax + andl $(~(X86_CR0_CD | X86_CR0_NW)), %eax + movl %eax, %cr0 + + post_code(POST_CAR_CPU_CACHE) + + /* All CPUs need to be in Wait for SIPI state */ +wait_for_sipi: + movl (%esi), %eax + bt $12, %eax + jc wait_for_sipi + + /* return */ jmp car_init_ret + +mtrr_table: + /* Fixed MTRRs */ + .word 0x250, 0x258, 0x259 + .word 0x268, 0x269, 0x26A + .word 0x26B, 0x26C, 0x26D + .word 0x26E, 0x26F + /* Variable MTRRs */ + .word 0x200, 0x201, 0x202, 0x203 + .word 0x204, 0x205, 0x206, 0x207 + .word 0x208, 0x209, 0x20A, 0x20B + .word 0x20C, 0x20D, 0x20E, 0x20F + .word 0x210, 0x211, 0x212, 0x213 +mtrr_table_end: diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 1cbdaaf..5863811 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -12,6 +12,7 @@ #include <common.h> #include <asm/cpu.h> +#include <asm/post.h> #include <asm/processor.h> DECLARE_GLOBAL_DATA_PTR; @@ -20,6 +21,7 @@ int arch_cpu_init(void) { int ret; + post_code(POST_CPU_INIT); timer_set_base(rdtsc()); ret = x86_cpu_init_f(); |