
Hi Simon,
On Fri, Nov 7, 2014 at 4:20 AM, Simon Glass sjg@chromium.org wrote:
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
arch/x86/Kconfig | 16 ++++ arch/x86/cpu/ivybridge/car.S | 156 ++++++++++++++++++++++++++++++++++- arch/x86/cpu/ivybridge/cpu.c | 2 + arch/x86/include/asm/mtrr.h | 121 +++++++++++++++++++++++++++ arch/x86/include/asm/post.h | 13 ++- board/google/chromebook_link/Kconfig | 12 +++ 6 files changed, 318 insertions(+), 2 deletions(-) create mode 100644 arch/x86/include/asm/mtrr.h
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index d9ce129..73fe8b2 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -34,6 +34,22 @@ config TARGET_CHROMEBOOK_LINK
endchoice
+config RAMBASE
hex
default 0x100000
+config RAMTOP
hex
default 0x200000
+config XIP_ROM_SIZE
hex
default 0x10000
+config CPU_ADDR_BITS
int
default 36
config ROM_SIZE hex default 0x800000 diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S index 0480813..391f6df 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -12,9 +12,163 @@ */
#include <common.h> +#include <asm/mtrr.h> +#include <asm/post.h> +#include <asm/processor-flags.h>
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) +#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
Should these macros be all capital?
+#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
Ditto.
/* Note: ebp must not be touched in this code */
I think mentioning ebp holds the value of BIST would help more?
.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)
/* All CPUs need to be in Wait for SIPI state */
+wait_for_sipi:
movl (%esi), %eax
bt $12, %eax
jc wait_for_sipi
Is this a must to send INIT IPI before CAR initialization?
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 $(MTRRphysBase_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 $(MTRRphysMask_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 $MTRRphysBase_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 $MTRRphysMask_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 $MTRRphysBase_MSR(2), %ecx
movl $(CACHE_MRC_BASE | MTRR_TYPE_WRPROT), %eax
xorl %edx, %edx
wrmsr
movl $MTRRphysMask_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)
/* 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 7e77be6..a9884ca 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -11,6 +11,7 @@ */
#include <common.h> +#include <asm/post.h> #include <asm/processor.h>
DECLARE_GLOBAL_DATA_PTR; @@ -19,6 +20,7 @@ int arch_cpu_init(void) { int ret;
post_code(POST_CPU_INIT); timer_set_base(rdtsc()); ret = x86_cpu_init_f();
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h new file mode 100644 index 0000000..5f05a48 --- /dev/null +++ b/arch/x86/include/asm/mtrr.h @@ -0,0 +1,121 @@ +/*
- Copyright (c) 2014 Google, Inc
- From Coreboot file of the same name
- SPDX-License-Identifier: GPL-2.0+
- */
+#ifndef _ASM_MTRR_H +#define _ASM_MTRR_H
+/* These are the region types */ +#define MTRR_TYPE_UNCACHEABLE 0 +#define MTRR_TYPE_WRCOMB 1 +/*#define MTRR_TYPE_ 2*/ +/*#define MTRR_TYPE_ 3*/ +#define MTRR_TYPE_WRTHROUGH 4 +#define MTRR_TYPE_WRPROT 5 +#define MTRR_TYPE_WRBACK 6 +#define MTRR_NUM_TYPES 7
+#define MTRRcap_MSR 0x0fe +#define MTRRdefType_MSR 0x2ff
+#define MTRRdefTypeEn (1 << 11) +#define MTRRdefTypeFixEn (1 << 10)
+#define SMRRphysBase_MSR 0x1f2 +#define SMRRphysMask_MSR 0x1f3
+#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) +#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
+#define MTRRphysMaskValid (1 << 11)
+#define NUM_FIXED_RANGES 88 +#define RANGES_PER_FIXED_MTRR 8 +#define MTRRfix64K_00000_MSR 0x250 +#define MTRRfix16K_80000_MSR 0x258 +#define MTRRfix16K_A0000_MSR 0x259 +#define MTRRfix4K_C0000_MSR 0x268 +#define MTRRfix4K_C8000_MSR 0x269 +#define MTRRfix4K_D0000_MSR 0x26a +#define MTRRfix4K_D8000_MSR 0x26b +#define MTRRfix4K_E0000_MSR 0x26c +#define MTRRfix4K_E8000_MSR 0x26d +#define MTRRfix4K_F0000_MSR 0x26e +#define MTRRfix4K_F8000_MSR 0x26f
Ditto.
+#if !defined(__ASSEMBLER__)
+/*
- The MTRR code has some side effects that the callers should be aware for.
- The call sequence matters. x86_setup_mtrrs() calls
- x86_setup_fixed_mtrrs_no_enable() then enable_fixed_mtrrs() (equivalent
- of x86_setup_fixed_mtrrs()) then x86_setup_var_mtrrs(). If the callers
- want to call the components of x86_setup_mtrrs() because of other
- rquirements the ordering should still preserved.
- enable_fixed_mtrr() will enable both variable and fixed MTRRs because
- of the nature of the global MTRR enable flag. Therefore, all direct
- or indirect callers of enable_fixed_mtrr() should ensure that the
- variable MTRR MSRs do not contain bad ranges.
- If CONFIG_CACHE_ROM is selected an MTRR is allocated for enabling
- the caching of the ROM. However, it is set to uncacheable (UC). It
- is the responsiblity of the caller to enable it by calling
- x86_mtrr_enable_rom_caching().
- */
+void x86_setup_mtrrs(void); +/*
- x86_setup_var_mtrrs() parameters:
- address_bits - number of physical address bits supported by cpu
- above4gb - 2 means dynamically detect number of variable MTRRs available.
non-zero means handle memory ranges above 4GiB.
0 means ignore memory ranges above 4GiB
- */
+void x86_setup_var_mtrrs(unsigned int address_bits, unsigned int above4gb); +void enable_fixed_mtrr(void); +void x86_setup_fixed_mtrrs(void); +/* Set up fixed MTRRs but do not enable them. */ +void x86_setup_fixed_mtrrs_no_enable(void); +int x86_mtrr_check(void); +/* ROM caching can be used after variable MTRRs are set up. Beware that
- enabling CONFIG_CACHE_ROM will eat through quite a few MTRRs based on
- one's IO hole size and WRCOMB resources. Be sure to check the console
- log when enabling CONFIG_CACHE_ROM or adding WRCOMB resources. Beware that
- on CPUs with core-scoped MTRR registers such as hyperthreaded CPUs the
- rom caching will be disabled if all threads run the MTRR code. Therefore,
- one needs to call x86_mtrr_enable_rom_caching() after all threads of the
- same core have run the MTRR code. */
+#if CONFIG_CACHE_ROM +void x86_mtrr_enable_rom_caching(void); +void x86_mtrr_disable_rom_caching(void); +/* Return the variable range MTRR index of the ROM cache. */ +long x86_mtrr_rom_cache_var_index(void); +#else +static inline void x86_mtrr_enable_rom_caching(void) {} +static inline void x86_mtrr_disable_rom_caching(void) {} +static inline long x86_mtrr_rom_cache_var_index(void) { return -1; } +#endif /* CONFIG_CACHE_ROM */
+#endif
+#if !defined(CONFIG_RAMTOP) +# error "CONFIG_RAMTOP not defined" +#endif
+#if ((CONFIG_XIP_ROM_SIZE & (CONFIG_XIP_ROM_SIZE - 1)) != 0) +# error "CONFIG_XIP_ROM_SIZE is not a power of 2" +#endif
+#if ((CONFIG_CACHE_ROM_SIZE & (CONFIG_CACHE_ROM_SIZE - 1)) != 0) +# error "CONFIG_CACHE_ROM_SIZE is not a power of 2" +#endif
+#define CACHE_ROM_BASE (((1 << 20) - (CONFIG_CACHE_ROM_SIZE >> 12)) << 12)
+#if (CONFIG_RAMTOP & (CONFIG_RAMTOP - 1)) != 0 +# error "CONFIG_RAMTOP must be a power of 2" +#endif
+#endif diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h index 3371185..b203dc9 100644 --- a/arch/x86/include/asm/post.h +++ b/arch/x86/include/asm/post.h @@ -13,9 +13,18 @@ /* post codes which represent various stages of init */ #define POST_START 0x1e #define POST_CAR_START 0x1f
+#define POST_CAR_SIPI 0x20 +#define POST_CAR_MTRR 0x21 +#define POST_CAR_UNCACHEABLE 0x22 +#define POST_CAR_BASE_ADDRESS 0x23 +#define POST_CAR_MASK 0x24 +#define POST_CAR_FILL 0x25 +#define POST_CAR_ROM_CACHE 0x26 +#define POST_CAR_MRC_CACHE 0x27 +#define POST_CAR_CPU_CACHE 0x28 #define POST_START_STACK 0x29 #define POST_START_DONE 0x2a +#define POST_CPU_INIT 0x2b
/* Output a post code using al - value must be 0 to 0xff */ #ifdef __ASSEMBLY__ @@ -23,6 +32,8 @@ movb $value, %al; \ outb %al, $POST_PORT #else +#include <asm/io.h>
static inline void post_code(int code) { outb(code, POST_PORT); diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig index 9c715ba..3a4f557 100644 --- a/board/google/chromebook_link/Kconfig +++ b/board/google/chromebook_link/Kconfig @@ -12,6 +12,18 @@ config SYS_SOC config SYS_CONFIG_NAME default "chromebook_link"
+config BOARD_SPECIFIC_OPTIONS # dummy
def_bool y
select CPU_INTEL_SOCKET_RPGA989
select NORTHBRIDGE_INTEL_IVYBRIDGE
select SOUTHBRIDGE_INTEL_C216
select HAVE_ACPI_RESUME
select MARK_GRAPHICS_MEM_WRCOMB
+config MMCONF_BASE_ADDRESS
hex
default 0xf0000000
config EARLY_POST_CROS_EC bool "Enable early post to Chrome OS EC" default y --
Regards, Bin