Hi Simon, On Fri, Nov 7, 2014 at 4:20 AM, Simon Glass <s...@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 <s...@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. > + * 1. 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. > + * 2. 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. > + * 3. 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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot