summaryrefslogtreecommitdiff
path: root/arch/x86/cpu
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2014-11-12 22:42:10 -0700
committerSimon Glass <sjg@chromium.org>2014-11-21 07:34:11 +0100
commit70a09c6c3dc25b200a9d0475afcf5dfc9836b18e (patch)
tree8b4433ebbbbd7e558b4a291cb2ccd2aec14ab710 /arch/x86/cpu
parentd1cd045982b1e1e4db2c1cc2b2b932f739b78a11 (diff)
downloadu-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.S162
-rw-r--r--arch/x86/cpu/ivybridge/cpu.c2
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();