From bc4880616187e4cda0e74ac55f3423ebb84048e1 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 6 Nov 2014 13:20:00 -0700 Subject: x86: Remove REALMODE_BASE which is no longer used This was missed when the real mode support was dropped. Remove it. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/config.mk b/arch/x86/config.mk index 3e7fedb..bb2da46 100644 --- a/arch/x86/config.mk +++ b/arch/x86/config.mk @@ -15,7 +15,6 @@ PF_CPPFLAGS_X86 := $(call cc-option, -fno-toplevel-reorder, \ $(call cc-option, -mpreferred-stack-boundary=2) PLATFORM_CPPFLAGS += $(PF_CPPFLAGS_X86) PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm -PLATFORM_CPPFLAGS += -DREALMODE_BASE=0x7c0 PLATFORM_CPPFLAGS += -march=i386 -m32 # Support generic board on x86 -- cgit v0.10.2 From 85d87328ea3d16b8e099854684166732e1954c71 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 6 Nov 2014 13:20:01 -0700 Subject: x86: Remove board_init16() call which is not used This allows a board to do very early init, but no boards need to do this. We may as well drop this feature. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S index 6968fda..e718d4b 100644 --- a/arch/x86/cpu/start16.S +++ b/arch/x86/cpu/start16.S @@ -24,15 +24,7 @@ start16: /* Set the Cold Boot / Hard Reset flag */ movl $GD_FLG_COLD_BOOT, %ebx - /* - * First we let the BSP do some early initialization - * this code have to map the flash to its final position - */ - jmp board_init16 -.globl board_init16_ret -board_init16_ret: - - /* Turn of cache (this might require a 486-class CPU) */ + /* Turn off cache (this might require a 486-class CPU) */ movl %cr0, %eax orl $(X86_CR0_NW | X86_CR0_CD), %eax movl %eax, %cr0 -- cgit v0.10.2 From 3c00695ee1d73ef52eadd7d4a1de9ecaab4f7be4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 6 Nov 2014 13:20:03 -0700 Subject: x86: Invalidate TLB as early as possible We should invalidate the TLB right at the start to ensure that we don't get false address translations even though paging is disabled. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S index e718d4b..445d5a1 100644 --- a/arch/x86/cpu/start16.S +++ b/arch/x86/cpu/start16.S @@ -24,6 +24,9 @@ start16: /* Set the Cold Boot / Hard Reset flag */ movl $GD_FLG_COLD_BOOT, %ebx + xorl %eax, %eax + movl %eax, %cr3 /* Invalidate TLB */ + /* Turn off cache (this might require a 486-class CPU) */ movl %cr0, %eax orl $(X86_CR0_NW | X86_CR0_CD), %eax -- cgit v0.10.2 From 76f90f3020433a2d06d9ebf897f65862d6248c8e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 6 Nov 2014 13:20:04 -0700 Subject: x86: Tidy up global descriptor table setup This code is a little muddled, so tidy it up. Make sure that we put the GDT in the right place and set it up properly. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 338bab1..781d324 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -74,6 +74,16 @@ car_init_ret: * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, * or fully initialised SDRAM - we really don't care which) * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack + * and early malloc area. + * + * Stack grows down from top of CAR. We have: + * + * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE + * global_data + * x86 global descriptor table + * early malloc area + * stack + * bottom-> CONFIG_SYS_CAR_ADDR */ /* Stack grows down from top of CAR */ @@ -91,12 +101,16 @@ car_init_ret: movl %esp, %edi rep stosb - /* Setup first parameter to setup_gdt */ + /* Setup first parameter to setup_gdt, pointer to global_data */ movl %esp, %eax /* Reserve space for global descriptor table */ subl $X86_GDT_SIZE, %esp + /* Align temporary global descriptor table to 16-byte boundary */ + andl $0xfffffff0, %esp + movl %esp, %ecx + #if defined(CONFIG_SYS_MALLOC_F_LEN) subl $CONFIG_SYS_MALLOC_F_LEN, %esp movl %eax, %edx @@ -108,14 +122,13 @@ car_init_ret: andl $0xfffffff0, %esp /* Set second parameter to setup_gdt */ - movl %esp, %edx + movl %ecx, %edx /* Setup global descriptor table so gd->xyz works */ call setup_gdt /* Set parameter to board_init_f() to boot flags */ xorl %eax, %eax - movw %bx, %ax /* Enter, U-boot! */ call board_init_f -- cgit v0.10.2 From 07387d1769c7cc29ff2402117148477263c4c5ce Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 6 Nov 2014 13:20:05 -0700 Subject: x86: Use the standard dram_init() function Instead of having an x86-specific DRAM init function, adjust things so we can use the normal one. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index 959feaa..ca651c7 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -79,7 +80,7 @@ ulong board_get_usable_ram_top(ulong total_size) return (ulong)dest_addr; } -int dram_init_f(void) +int dram_init(void) { int i; phys_size_t ram_size = 0; @@ -94,7 +95,8 @@ int dram_init_f(void) gd->ram_size = ram_size; if (ram_size == 0) return -1; - return 0; + + return calculate_relocation_address(); } int dram_init_banksize(void) @@ -116,8 +118,3 @@ int dram_init_banksize(void) } return 0; } - -int dram_init(void) -{ - return dram_init_banksize(); -} diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 9e525dd..89618c7 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -27,8 +27,8 @@ unsigned long get_tbclk_mhz(void); void timer_set_base(uint64_t base); int pcat_timer_init(void); -/* Architecture specific - can be in arch/x86/cpu/, arch/x86/lib/, or $(BOARD)/ */ -int dram_init_f(void); +/* Architecture specific DRAM init */ +int dram_init(void); /* cpu/.../interrupts.c */ int cpu_init_interrupts(void); diff --git a/common/board_f.c b/common/board_f.c index b5bebc9..1d81ed7 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -903,13 +903,9 @@ static init_fnc_t init_sequence_f[] = { #if defined(CONFIG_HARD_SPI) init_func_spi, #endif -#ifdef CONFIG_X86 - dram_init_f, /* configure available RAM banks */ - calculate_relocation_address, -#endif announce_dram_init, /* TODO: unify all these dram functions? */ -#ifdef CONFIG_ARM +#if defined(CONFIG_ARM) || defined(CONFIG_X86) dram_init, /* configure available RAM banks */ #endif #if defined(CONFIG_MIPS) || defined(CONFIG_PPC) -- cgit v0.10.2 From 8b37c7694f1eace82626d00fbfb85311ebf0d220 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 6 Nov 2014 13:20:06 -0700 Subject: x86: Use the standard arch_cpu_init() function Instead of an x86-specific cpu_init_f() function, use the normal U-Boot one for this purpose. Also remove a useless/misleading comment. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index e24f13a..4e1349f 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -20,18 +20,17 @@ DECLARE_GLOBAL_DATA_PTR; -/* - * Miscellaneous platform dependent initializations - */ -int cpu_init_f(void) +int arch_cpu_init(void) { int ret = get_coreboot_info(&lib_sysinfo); - if (ret != 0) + if (ret != 0) { printf("Failed to parse coreboot tables.\n"); + return ret; + } timestamp_init(); - return ret; + return x86_cpu_init_f(); } int board_early_init_f(void) diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 2e25253..d6ba246 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -130,7 +130,6 @@ int x86_cpu_init_f(void) return 0; } -int cpu_init_f(void) __attribute__((weak, alias("x86_cpu_init_f"))); int x86_cpu_init_r(void) { diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 89618c7..fdb8a6c 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -9,6 +9,7 @@ #define _U_BOOT_I386_H_ 1 /* cpu/.../cpu.c */ +int arch_cpu_init(void); int x86_cpu_init_r(void); int cpu_init_r(void); int x86_cpu_init_f(void); diff --git a/common/board_f.c b/common/board_f.c index 1d81ed7..23d8f64 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -818,7 +818,6 @@ static init_fnc_t init_sequence_f[] = { #endif arch_cpu_init, /* basic arch cpu dependent setup */ #ifdef CONFIG_X86 - cpu_init_f, /* TODO(sjg@chromium.org): remove */ # ifdef CONFIG_OF_CONTROL find_fdt, /* TODO(sjg@chromium.org): remove */ # endif -- cgit v0.10.2 From e1ffd81797d59652124bd9cda813a58644f5dea9 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 6 Nov 2014 13:20:08 -0700 Subject: x86: Fix up some missing prototypes Some functions are missing prototypes. Fix those that are specific to x86. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 4e1349f..5527183 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -97,7 +97,7 @@ int board_eth_init(bd_t *bis) #define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) #define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) -int board_final_cleanup(void) +void board_final_cleanup(void) { /* Un-cache the ROM so the kernel has one * more MTRR available. @@ -119,8 +119,6 @@ int board_final_cleanup(void) /* Issue SMI to Coreboot to lock down ME and registers */ printf("Finalizing Coreboot\n"); outb(0xcb, 0xb2); - - return 0; } void panic_puts(const char *str) diff --git a/arch/x86/cpu/coreboot/sdram.c b/arch/x86/cpu/coreboot/sdram.c index ca651c7..342ff30 100644 --- a/arch/x86/cpu/coreboot/sdram.c +++ b/arch/x86/cpu/coreboot/sdram.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -99,7 +100,7 @@ int dram_init(void) return calculate_relocation_address(); } -int dram_init_banksize(void) +void dram_init_banksize(void) { int i, j; @@ -116,5 +117,4 @@ int dram_init_banksize(void) } } } - return 0; } diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index d6ba246..6441dde 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -197,14 +197,13 @@ asm(".globl generate_gpf\n" "generate_gpf:\n" "ljmp $0x70, $0x47114711\n"); -void __reset_cpu(ulong addr) +__weak void reset_cpu(ulong addr) { printf("Resetting using x86 Triple Fault\n"); set_vector(13, generate_gpf); /* general protection fault handler */ set_vector(8, generate_gpf); /* double fault handler */ generate_gpf(); /* start the show */ } -void reset_cpu(ulong addr) __attribute__((weak, alias("__reset_cpu"))); int dcache_status(void) { diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c index 6f3d85f..51e2c59 100644 --- a/arch/x86/cpu/interrupts.c +++ b/arch/x86/cpu/interrupts.c @@ -31,7 +31,7 @@ DECLARE_GLOBAL_DATA_PTR; "pushl $"#x"\n" \ "jmp irq_common_entry\n" -void dump_regs(struct irq_regs *regs) +static void dump_regs(struct irq_regs *regs) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; unsigned long d0, d1, d2, d3, d6, d7; diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index fdb8a6c..8d5b438 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -37,6 +37,15 @@ int cpu_init_interrupts(void); /* board/.../... */ int dram_init(void); +int cleanup_before_linux(void); +int x86_cleanup_before_linux(void); +void x86_enable_caches(void); +void x86_disable_caches(void); +int x86_init_cache(void); +void reset_cpu(ulong addr); +ulong board_get_usable_ram_top(ulong total_size); +void dram_init_banksize(void); + void setup_pcat_compatibility(void); void isa_unmap_rom(u32 addr); -- cgit v0.10.2 From f67cd51e654ba6498230314b6e82b4dbbd4bfca7 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Thu, 6 Nov 2014 13:20:10 -0700 Subject: x86: Save the BIST value on reset The built in self test value is available in register eax on start-up. Save it so that it can be accessed later. Unfortunately we must wait until the global_data is available before we can do this, so there is a little bit of shuffling to keep it around. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 781d324..b18f320 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -49,6 +49,8 @@ _start: */ movw $GD_FLG_COLD_BOOT, %bx 1: + /* Save BIST */ + movl %eax, %ebp /* Load the segement registes to match the gdt loaded in start16.S */ movl $(X86_GDT_ENTRY_32BIT_DS * X86_GDT_ENTRY_SIZE), %eax @@ -117,9 +119,10 @@ car_init_ret: addl $GD_MALLOC_BASE, %edx movl %esp, (%edx) #endif - - /* Align temporary global descriptor table to 16-byte boundary */ - andl $0xfffffff0, %esp + /* Store BIST */ + movl %eax, %edx + addl $GD_BIST, %edx + movl %ebp, (%edx) /* Set second parameter to setup_gdt */ movl %ecx, %edx diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S index 445d5a1..9550502 100644 --- a/arch/x86/cpu/start16.S +++ b/arch/x86/cpu/start16.S @@ -21,6 +21,9 @@ .code16 .globl start16 start16: + /* Save BIST */ + movl %eax, %ecx + /* Set the Cold Boot / Hard Reset flag */ movl $GD_FLG_COLD_BOOT, %ebx @@ -45,9 +48,11 @@ o32 cs lgdt gdt_ptr /* Flush the prefetch queue */ jmp ff ff: - /* Finally jump to the 32bit initialization code */ + + /* Finally restore BIST and jump to the 32bit initialization code */ movw $code32start, %ax movw %ax, %bp + movl %ecx, %eax o32 cs ljmp *(%bp) /* 48-bit far pointer */ diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 3e8e2cd..9eae228 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -17,6 +17,7 @@ struct arch_global_data { uint32_t tsc_base_kclocks; /* Initial tsc as a kclocks value */ uint32_t tsc_prev; /* For show_boot_progress() */ void *new_fdt; /* Relocated FDT */ + uint32_t bist; /* Built-in self test value */ }; #endif diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c index 129bc3e..580f763 100644 --- a/lib/asm-offsets.c +++ b/lib/asm-offsets.c @@ -31,6 +31,9 @@ int main(void) #ifdef CONFIG_SYS_MALLOC_F_LEN DEFINE(GD_MALLOC_BASE, offsetof(struct global_data, malloc_base)); #endif +#ifdef CONFIG_X86 + DEFINE(GD_BIST, offsetof(struct global_data, arch.bist)); +#endif #if defined(CONFIG_ARM) -- cgit v0.10.2 From 52f952bf5ecebc1de01269557591bad4ac62a01a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 9 Nov 2014 22:18:56 +0800 Subject: x86: Do CPU identification in the early phase The CPU identification happens in x86_cpu_init_f() and corresponding fields are saved in the global data for later use. Signed-off-by: Bin Meng diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 6441dde..a4e639d 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -13,6 +13,9 @@ * Sysgo Real-Time Solutions, GmbH * Alex Zuepke * + * Part of this file is adapted from coreboot + * src/arch/x86/lib/cpu.c + * * SPDX-License-Identifier: GPL-2.0+ */ @@ -27,6 +30,8 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + /* * Constructor for a conventional segment GDT (or LDT) entry * This is a macro so it can be used in initialisers @@ -43,6 +48,52 @@ struct gdt_ptr { u32 ptr; } __packed; +struct cpu_device_id { + unsigned vendor; + unsigned device; +}; + +struct cpuinfo_x86 { + uint8_t x86; /* CPU family */ + uint8_t x86_vendor; /* CPU vendor */ + uint8_t x86_model; + uint8_t x86_mask; +}; + +/* + * List of cpu vendor strings along with their normalized + * id values. + */ +static struct { + int vendor; + const char *name; +} x86_vendors[] = { + { X86_VENDOR_INTEL, "GenuineIntel", }, + { X86_VENDOR_CYRIX, "CyrixInstead", }, + { X86_VENDOR_AMD, "AuthenticAMD", }, + { X86_VENDOR_UMC, "UMC UMC UMC ", }, + { X86_VENDOR_NEXGEN, "NexGenDriven", }, + { X86_VENDOR_CENTAUR, "CentaurHauls", }, + { X86_VENDOR_RISE, "RiseRiseRise", }, + { X86_VENDOR_TRANSMETA, "GenuineTMx86", }, + { X86_VENDOR_TRANSMETA, "TransmetaCPU", }, + { X86_VENDOR_NSC, "Geode by NSC", }, + { X86_VENDOR_SIS, "SiS SiS SiS ", }, +}; + +static const char *const x86_vendor_name[] = { + [X86_VENDOR_INTEL] = "Intel", + [X86_VENDOR_CYRIX] = "Cyrix", + [X86_VENDOR_AMD] = "AMD", + [X86_VENDOR_UMC] = "UMC", + [X86_VENDOR_NEXGEN] = "NexGen", + [X86_VENDOR_CENTAUR] = "Centaur", + [X86_VENDOR_RISE] = "Rise", + [X86_VENDOR_TRANSMETA] = "Transmeta", + [X86_VENDOR_NSC] = "NSC", + [X86_VENDOR_SIS] = "SiS", +}; + static void load_ds(u32 segment) { asm volatile("movl %0, %%ds" : : "r" (segment * X86_GDT_ENTRY_SIZE)); @@ -115,6 +166,128 @@ int __weak x86_cleanup_before_linux(void) return 0; } +/* + * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected + * by the fact that they preserve the flags across the division of 5/2. + * PII and PPro exhibit this behavior too, but they have cpuid available. + */ + +/* + * Perform the Cyrix 5/2 test. A Cyrix won't change + * the flags, while other 486 chips will. + */ +static inline int test_cyrix_52div(void) +{ + unsigned int test; + + __asm__ __volatile__( + "sahf\n\t" /* clear flags (%eax = 0x0005) */ + "div %b2\n\t" /* divide 5 by 2 */ + "lahf" /* store flags into %ah */ + : "=a" (test) + : "0" (5), "q" (2) + : "cc"); + + /* AH is 0x02 on Cyrix after the divide.. */ + return (unsigned char) (test >> 8) == 0x02; +} + +/* + * Detect a NexGen CPU running without BIOS hypercode new enough + * to have CPUID. (Thanks to Herbert Oppmann) + */ + +static int deep_magic_nexgen_probe(void) +{ + int ret; + + __asm__ __volatile__ ( + " movw $0x5555, %%ax\n" + " xorw %%dx,%%dx\n" + " movw $2, %%cx\n" + " divw %%cx\n" + " movl $0, %%eax\n" + " jnz 1f\n" + " movl $1, %%eax\n" + "1:\n" + : "=a" (ret) : : "cx", "dx"); + return ret; +} + +static bool has_cpuid(void) +{ + return flag_is_changeable_p(X86_EFLAGS_ID); +} + +static int build_vendor_name(char *vendor_name) +{ + struct cpuid_result result; + result = cpuid(0x00000000); + unsigned int *name_as_ints = (unsigned int *)vendor_name; + + name_as_ints[0] = result.ebx; + name_as_ints[1] = result.edx; + name_as_ints[2] = result.ecx; + + return result.eax; +} + +static void identify_cpu(struct cpu_device_id *cpu) +{ + char vendor_name[16]; + int i; + + vendor_name[0] = '\0'; /* Unset */ + + /* Find the id and vendor_name */ + if (!has_cpuid()) { + /* Its a 486 if we can modify the AC flag */ + if (flag_is_changeable_p(X86_EFLAGS_AC)) + cpu->device = 0x00000400; /* 486 */ + else + cpu->device = 0x00000300; /* 386 */ + if ((cpu->device == 0x00000400) && test_cyrix_52div()) { + memcpy(vendor_name, "CyrixInstead", 13); + /* If we ever care we can enable cpuid here */ + } + /* Detect NexGen with old hypercode */ + else if (deep_magic_nexgen_probe()) + memcpy(vendor_name, "NexGenDriven", 13); + } + if (has_cpuid()) { + int cpuid_level; + + cpuid_level = build_vendor_name(vendor_name); + vendor_name[12] = '\0'; + + /* Intel-defined flags: level 0x00000001 */ + if (cpuid_level >= 0x00000001) { + cpu->device = cpuid_eax(0x00000001); + } else { + /* Have CPUID level 0 only unheard of */ + cpu->device = 0x00000400; + } + } + cpu->vendor = X86_VENDOR_UNKNOWN; + for (i = 0; i < ARRAY_SIZE(x86_vendors); i++) { + if (memcmp(vendor_name, x86_vendors[i].name, 12) == 0) { + cpu->vendor = x86_vendors[i].vendor; + break; + } + } +} + +static inline void get_fms(struct cpuinfo_x86 *c, uint32_t tfms) +{ + c->x86 = (tfms >> 8) & 0xf; + c->x86_model = (tfms >> 4) & 0xf; + c->x86_mask = tfms & 0xf; + if (c->x86 == 0xf) + c->x86 += (tfms >> 20) & 0xff; + if (c->x86 >= 0x6) + c->x86_model += ((tfms >> 16) & 0xF) << 4; +} + int x86_cpu_init_f(void) { const u32 em_rst = ~X86_CR0_EM; @@ -128,6 +301,20 @@ int x86_cpu_init_f(void) "movl %%eax, %%cr0\n" \ : : "i" (em_rst), "i" (mp_ne_set) : "eax"); + /* identify CPU via cpuid and store the decoded info into gd->arch */ + if (has_cpuid()) { + struct cpu_device_id cpu; + struct cpuinfo_x86 c; + + identify_cpu(&cpu); + get_fms(&c, cpu.device); + gd->arch.x86 = c.x86; + gd->arch.x86_vendor = cpu.vendor; + gd->arch.x86_model = c.x86_model; + gd->arch.x86_mask = c.x86_mask; + gd->arch.x86_device = cpu.device; + } + return 0; } @@ -277,66 +464,65 @@ void cpu_disable_paging_pae(void) : "eax"); } -static bool has_cpuid(void) +static bool can_detect_long_mode(void) { - unsigned long flag; - - asm volatile("pushf\n" \ - "pop %%eax\n" - "mov %%eax, %%ecx\n" /* ecx = flags */ - "xor %1, %%eax\n" - "push %%eax\n" - "popf\n" /* flags ^= $2 */ - "pushf\n" - "pop %%eax\n" /* eax = flags */ - "push %%ecx\n" - "popf\n" /* flags = ecx */ - "xor %%ecx, %%eax\n" - "mov %%eax, %0" - : "=r" (flag) - : "i" (1 << 21) - : "eax", "ecx", "memory"); + return cpuid_eax(0x80000000) > 0x80000000UL; +} - return flag != 0; +static bool has_long_mode(void) +{ + return cpuid_edx(0x80000001) & (1 << 29) ? true : false; } -static bool can_detect_long_mode(void) +int cpu_has_64bit(void) { - unsigned long flag; + return has_cpuid() && can_detect_long_mode() && + has_long_mode(); +} - asm volatile("mov $0x80000000, %%eax\n" - "cpuid\n" - "mov %%eax, %0" - : "=r" (flag) - : - : "eax", "ebx", "ecx", "edx", "memory"); +const char *cpu_vendor_name(int vendor) +{ + const char *name; + name = ""; + if ((vendor < (ARRAY_SIZE(x86_vendor_name))) && + (x86_vendor_name[vendor] != 0)) + name = x86_vendor_name[vendor]; - return flag > 0x80000000UL; + return name; } -static bool has_long_mode(void) +void fill_processor_name(char *processor_name) { - unsigned long flag; + struct cpuid_result regs; + char temp_processor_name[49]; + char *processor_name_start; + unsigned int *name_as_ints = (unsigned int *)temp_processor_name; + int i; - asm volatile("mov $0x80000001, %%eax\n" - "cpuid\n" - "mov %%edx, %0" - : "=r" (flag) - : - : "eax", "ebx", "ecx", "edx", "memory"); + for (i = 0; i < 3; i++) { + regs = cpuid(0x80000002 + i); + name_as_ints[i * 4 + 0] = regs.eax; + name_as_ints[i * 4 + 1] = regs.ebx; + name_as_ints[i * 4 + 2] = regs.ecx; + name_as_ints[i * 4 + 3] = regs.edx; + } - return flag & (1 << 29) ? true : false; -} + temp_processor_name[48] = 0; -int cpu_has_64bit(void) -{ - return has_cpuid() && can_detect_long_mode() && - has_long_mode(); + /* Skip leading spaces. */ + processor_name_start = temp_processor_name; + while (*processor_name_start == ' ') + processor_name_start++; + + memset(processor_name, 0, 49); + strcpy(processor_name, processor_name_start); } int print_cpuinfo(void) { - printf("CPU: %s\n", cpu_has_64bit() ? "x86_64" : "x86"); + printf("CPU: %s, vendor %s, device %xh\n", + cpu_has_64bit() ? "x86_64" : "x86", + cpu_vendor_name(gd->arch.x86_vendor), gd->arch.x86_device); return 0; } diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 6c6774a..89b748b 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -1,16 +1,160 @@ /* * Copyright (c) 2014 The Chromium OS Authors. * + * Part of this file is adapted from coreboot + * src/arch/x86/include/arch/cpu.h and + * src/arch/x86/lib/cpu.c + * * SPDX-License-Identifier: GPL-2.0+ */ -#ifndef __X86_CPU_H -#define __X86_CPU_H +#ifndef _ASM_CPU_H +#define _ASM_CPU_H + +enum { + X86_VENDOR_INVALID = 0, + X86_VENDOR_INTEL, + X86_VENDOR_CYRIX, + X86_VENDOR_AMD, + X86_VENDOR_UMC, + X86_VENDOR_NEXGEN, + X86_VENDOR_CENTAUR, + X86_VENDOR_RISE, + X86_VENDOR_TRANSMETA, + X86_VENDOR_NSC, + X86_VENDOR_SIS, + X86_VENDOR_ANY = 0xfe, + X86_VENDOR_UNKNOWN = 0xff +}; + +struct cpuid_result { + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; +}; + +/* + * Generic CPUID function + */ +static inline struct cpuid_result cpuid(int op) +{ + struct cpuid_result result; + asm volatile( + "mov %%ebx, %%edi;" + "cpuid;" + "mov %%ebx, %%esi;" + "mov %%edi, %%ebx;" + : "=a" (result.eax), + "=S" (result.ebx), + "=c" (result.ecx), + "=d" (result.edx) + : "0" (op) + : "edi"); + return result; +} + +/* + * Generic Extended CPUID function + */ +static inline struct cpuid_result cpuid_ext(int op, unsigned ecx) +{ + struct cpuid_result result; + asm volatile( + "mov %%ebx, %%edi;" + "cpuid;" + "mov %%ebx, %%esi;" + "mov %%edi, %%ebx;" + : "=a" (result.eax), + "=S" (result.ebx), + "=c" (result.ecx), + "=d" (result.edx) + : "0" (op), "2" (ecx) + : "edi"); + return result; +} + +/* + * CPUID functions returning a single datum + */ +static inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int eax; + + __asm__("mov %%ebx, %%edi;" + "cpuid;" + "mov %%edi, %%ebx;" + : "=a" (eax) + : "0" (op) + : "ecx", "edx", "edi"); + return eax; +} + +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int eax, ebx; + + __asm__("mov %%ebx, %%edi;" + "cpuid;" + "mov %%ebx, %%esi;" + "mov %%edi, %%ebx;" + : "=a" (eax), "=S" (ebx) + : "0" (op) + : "ecx", "edx", "edi"); + return ebx; +} + +static inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int eax, ecx; - /** + __asm__("mov %%ebx, %%edi;" + "cpuid;" + "mov %%edi, %%ebx;" + : "=a" (eax), "=c" (ecx) + : "0" (op) + : "edx", "edi"); + return ecx; +} + +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int eax, edx; + + __asm__("mov %%ebx, %%edi;" + "cpuid;" + "mov %%edi, %%ebx;" + : "=a" (eax), "=d" (edx) + : "0" (op) + : "ecx", "edi"); + return edx; +} + +/* Standard macro to see if a specific flag is changeable */ +static inline int flag_is_changeable_p(uint32_t flag) +{ + uint32_t f1, f2; + + asm( + "pushfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "movl %0,%1\n\t" + "xorl %2,%0\n\t" + "pushl %0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl %0\n\t" + "popfl\n\t" + : "=&r" (f1), "=&r" (f2) + : "ir" (flag)); + return ((f1^f2) & flag) != 0; +} + +/** * cpu_enable_paging_pae() - Enable PAE-paging * - * @pdpt: Value to set in cr3 (PDPT or PML4T) + * @cr3: Value to set in cr3 (PDPT or PML4T) */ void cpu_enable_paging_pae(ulong cr3); @@ -27,6 +171,22 @@ void cpu_disable_paging_pae(void); int cpu_has_64bit(void); /** + * cpu_vendor_name() - Get CPU vendor name + * + * @vendor: CPU vendor enumeration number + * + * @return: Address to hold the CPU vendor name string + */ +const char *cpu_vendor_name(int vendor); + +/** + * fill_processor_name() - Get processor name + * + * @processor_name: Address to hold the processor name string + */ +void fill_processor_name(char *processor_name); + +/** * cpu_call64() - Jump to a 64-bit Linux kernel (internal function) * * The kernel is uncompressed and the 64-bit entry point is expected to be diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 9eae228..3e3073a 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -13,6 +13,11 @@ /* Architecture-specific global data */ struct arch_global_data { struct global_data *gd_addr; /* Location of Global Data */ + uint8_t x86; /* CPU family */ + uint8_t x86_vendor; /* CPU vendor */ + uint8_t x86_model; + uint8_t x86_mask; + uint32_t x86_device; uint64_t tsc_base; /* Initial value returned by rdtsc() */ uint32_t tsc_base_kclocks; /* Initial tsc as a kclocks value */ uint32_t tsc_prev; /* For show_boot_progress() */ -- cgit v0.10.2 From 076bb44b0ef85747fec786a930335956614fb7d6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 9 Nov 2014 22:19:13 +0800 Subject: x86: Do TSC MSR calibration only for known/supported CPUs Using MSR_PLATFORM_INFO (0xCE) to calibrate TSR will cause #GP on processors which do not have this MSR. Instead only doing the MSR calibration for known/supported CPUs. Signed-off-by: Bin Meng Acked-by: Simon Glass Tested-by: Simon Glass diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c index 8b38702..7cdde4a 100644 --- a/arch/x86/lib/tsc_timer.c +++ b/arch/x86/lib/tsc_timer.c @@ -1,6 +1,9 @@ /* * Copyright (c) 2012 The Chromium OS Authors. * + * TSC calibration codes are adapted from Linux kernel + * arch/x86/kernel/tsc_msr.c and arch/x86/kernel/tsc.c + * * SPDX-License-Identifier: GPL-2.0+ */ @@ -12,8 +15,107 @@ #include #include +/* CPU reference clock frequency: in KHz */ +#define FREQ_83 83200 +#define FREQ_100 99840 +#define FREQ_133 133200 +#define FREQ_166 166400 + +#define MAX_NUM_FREQS 8 + DECLARE_GLOBAL_DATA_PTR; +/* + * According to Intel 64 and IA-32 System Programming Guide, + * if MSR_PERF_STAT[31] is set, the maximum resolved bus ratio can be + * read in MSR_PLATFORM_ID[12:8], otherwise in MSR_PERF_STAT[44:40]. + * Unfortunately some Intel Atom SoCs aren't quite compliant to this, + * so we need manually differentiate SoC families. This is what the + * field msr_plat does. + */ +struct freq_desc { + u8 x86_family; /* CPU family */ + u8 x86_model; /* model */ + u8 msr_plat; /* 1: use MSR_PLATFORM_INFO, 0: MSR_IA32_PERF_STATUS */ + u32 freqs[MAX_NUM_FREQS]; +}; + +static struct freq_desc freq_desc_tables[] = { + /* PNW */ + { 6, 0x27, 0, { 0, 0, 0, 0, 0, FREQ_100, 0, FREQ_83 } }, + /* CLV+ */ + { 6, 0x35, 0, { 0, FREQ_133, 0, 0, 0, FREQ_100, 0, FREQ_83 } }, + /* TNG */ + { 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } }, + /* VLV2 */ + { 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } }, + /* ANN */ + { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } }, +}; + +static int match_cpu(u8 family, u8 model) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(freq_desc_tables); i++) { + if ((family == freq_desc_tables[i].x86_family) && + (model == freq_desc_tables[i].x86_model)) + return i; + } + + return -1; +} + +/* Map CPU reference clock freq ID(0-7) to CPU reference clock freq(KHz) */ +#define id_to_freq(cpu_index, freq_id) \ + (freq_desc_tables[cpu_index].freqs[freq_id]) + +/* + * Do MSR calibration only for known/supported CPUs. + * + * Returns the calibration value or 0 if MSR calibration failed. + */ +static unsigned long try_msr_calibrate_tsc(void) +{ + u32 lo, hi, ratio, freq_id, freq; + unsigned long res; + int cpu_index; + + cpu_index = match_cpu(gd->arch.x86, gd->arch.x86_model); + if (cpu_index < 0) + return 0; + + if (freq_desc_tables[cpu_index].msr_plat) { + rdmsr(MSR_PLATFORM_INFO, lo, hi); + ratio = (lo >> 8) & 0x1f; + } else { + rdmsr(MSR_IA32_PERF_STATUS, lo, hi); + ratio = (hi >> 8) & 0x1f; + } + debug("Maximum core-clock to bus-clock ratio: 0x%x\n", ratio); + + if (!ratio) + goto fail; + + /* Get FSB FREQ ID */ + rdmsr(MSR_FSB_FREQ, lo, hi); + freq_id = lo & 0x7; + freq = id_to_freq(cpu_index, freq_id); + debug("Resolved frequency ID: %u, frequency: %u KHz\n", freq_id, freq); + if (!freq) + goto fail; + + /* TSC frequency = maximum resolved freq * maximum resolved bus ratio */ + res = freq * ratio / 1000; + debug("TSC runs at %lu MHz\n", res); + + return res; + +fail: + debug("Fast TSC calibration using MSR failed\n"); + return 0; +} + void timer_set_base(u64 base) { gd->arch.tsc_base = base; @@ -34,17 +136,16 @@ u64 __attribute__((no_instrument_function)) get_ticks(void) return now_tick - gd->arch.tsc_base; } -#define PLATFORM_INFO_MSR 0xce - /* Get the speed of the TSC timer in MHz */ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void) { - u32 ratio; - u64 platform_info = native_read_msr(PLATFORM_INFO_MSR); + unsigned long fast_calibrate; + + fast_calibrate = try_msr_calibrate_tsc(); + if (!fast_calibrate) + panic("TSC frequency is ZERO"); - /* 100MHz times Max Non Turbo ratio */ - ratio = (platform_info >> 8) & 0xff; - return 100 * ratio; + return fast_calibrate; } unsigned long get_tbclk(void) -- cgit v0.10.2 From 80de049561f4d560c50341562b7e93ff45a1d8a0 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 9 Nov 2014 22:19:25 +0800 Subject: x86: Add quick TSC calibration via PIT Use the same way that Linux does for quick TSC calibration via PIT when calibration via MSR fails. Signed-off-by: Bin Meng Acked-by: Simon Glass diff --git a/arch/x86/include/asm/i8254.h b/arch/x86/include/asm/i8254.h index c3ccd4f..4116de1 100644 --- a/arch/x86/include/asm/i8254.h +++ b/arch/x86/include/asm/i8254.h @@ -36,4 +36,7 @@ #define PIT_CMD_MODE4 0x08 /* Select mode 4 */ #define PIT_CMD_MODE5 0x0A /* Select mode 5 */ +/* The clock frequency of the i8253/i8254 PIT */ +#define PIT_TICK_RATE 1193182ul + #endif diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c index 7cdde4a..ceff60c 100644 --- a/arch/x86/lib/tsc_timer.c +++ b/arch/x86/lib/tsc_timer.c @@ -116,6 +116,158 @@ fail: return 0; } +/* + * This reads the current MSB of the PIT counter, and + * checks if we are running on sufficiently fast and + * non-virtualized hardware. + * + * Our expectations are: + * + * - the PIT is running at roughly 1.19MHz + * + * - each IO is going to take about 1us on real hardware, + * but we allow it to be much faster (by a factor of 10) or + * _slightly_ slower (ie we allow up to a 2us read+counter + * update - anything else implies a unacceptably slow CPU + * or PIT for the fast calibration to work. + * + * - with 256 PIT ticks to read the value, we have 214us to + * see the same MSB (and overhead like doing a single TSC + * read per MSB value etc). + * + * - We're doing 2 reads per loop (LSB, MSB), and we expect + * them each to take about a microsecond on real hardware. + * So we expect a count value of around 100. But we'll be + * generous, and accept anything over 50. + * + * - if the PIT is stuck, and we see *many* more reads, we + * return early (and the next caller of pit_expect_msb() + * then consider it a failure when they don't see the + * next expected value). + * + * These expectations mean that we know that we have seen the + * transition from one expected value to another with a fairly + * high accuracy, and we didn't miss any events. We can thus + * use the TSC value at the transitions to calculate a pretty + * good value for the TSC frequencty. + */ +static inline int pit_verify_msb(unsigned char val) +{ + /* Ignore LSB */ + inb(0x42); + return inb(0x42) == val; +} + +static inline int pit_expect_msb(unsigned char val, u64 *tscp, + unsigned long *deltap) +{ + int count; + u64 tsc = 0, prev_tsc = 0; + + for (count = 0; count < 50000; count++) { + if (!pit_verify_msb(val)) + break; + prev_tsc = tsc; + tsc = rdtsc(); + } + *deltap = rdtsc() - prev_tsc; + *tscp = tsc; + + /* + * We require _some_ success, but the quality control + * will be based on the error terms on the TSC values. + */ + return count > 5; +} + +/* + * How many MSB values do we want to see? We aim for + * a maximum error rate of 500ppm (in practice the + * real error is much smaller), but refuse to spend + * more than 50ms on it. + */ +#define MAX_QUICK_PIT_MS 50 +#define MAX_QUICK_PIT_ITERATIONS (MAX_QUICK_PIT_MS * PIT_TICK_RATE / 1000 / 256) + +static unsigned long quick_pit_calibrate(void) +{ + int i; + u64 tsc, delta; + unsigned long d1, d2; + + /* Set the Gate high, disable speaker */ + outb((inb(0x61) & ~0x02) | 0x01, 0x61); + + /* + * Counter 2, mode 0 (one-shot), binary count + * + * NOTE! Mode 2 decrements by two (and then the + * output is flipped each time, giving the same + * final output frequency as a decrement-by-one), + * so mode 0 is much better when looking at the + * individual counts. + */ + outb(0xb0, 0x43); + + /* Start at 0xffff */ + outb(0xff, 0x42); + outb(0xff, 0x42); + + /* + * The PIT starts counting at the next edge, so we + * need to delay for a microsecond. The easiest way + * to do that is to just read back the 16-bit counter + * once from the PIT. + */ + pit_verify_msb(0); + + if (pit_expect_msb(0xff, &tsc, &d1)) { + for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) { + if (!pit_expect_msb(0xff-i, &delta, &d2)) + break; + + /* + * Iterate until the error is less than 500 ppm + */ + delta -= tsc; + if (d1+d2 >= delta >> 11) + continue; + + /* + * Check the PIT one more time to verify that + * all TSC reads were stable wrt the PIT. + * + * This also guarantees serialization of the + * last cycle read ('d2') in pit_expect_msb. + */ + if (!pit_verify_msb(0xfe - i)) + break; + goto success; + } + } + debug("Fast TSC calibration failed\n"); + return 0; + +success: + /* + * Ok, if we get here, then we've seen the + * MSB of the PIT decrement 'i' times, and the + * error has shrunk to less than 500 ppm. + * + * As a result, we can depend on there not being + * any odd delays anywhere, and the TSC reads are + * reliable (within the error). + * + * kHz = ticks / time-in-seconds / 1000; + * kHz = (t2 - t1) / (I * 256 / PIT_TICK_RATE) / 1000 + * kHz = ((t2 - t1) * PIT_TICK_RATE) / (I * 256 * 1000) + */ + delta *= PIT_TICK_RATE; + delta /= (i*256*1000); + debug("Fast TSC calibration using PIT\n"); + return delta / 1000; +} + void timer_set_base(u64 base) { gd->arch.tsc_base = base; @@ -142,6 +294,10 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void) unsigned long fast_calibrate; fast_calibrate = try_msr_calibrate_tsc(); + if (fast_calibrate) + return fast_calibrate; + + fast_calibrate = quick_pit_calibrate(); if (!fast_calibrate) panic("TSC frequency is ZERO"); -- cgit v0.10.2 From 258b1357c6b324b0a45ca0c1cf3dfd1ef1b4c5c4 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 9 Nov 2014 22:19:35 +0800 Subject: x86: Save TSC frequency in the global data Return the saved TSC frequency in get_tbclk_mhz(). Signed-off-by: Bin Meng Acked-by: Simon Glass Tested-by: Simon Glass diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 3e3073a..186b97e 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -21,6 +21,7 @@ struct arch_global_data { uint64_t tsc_base; /* Initial value returned by rdtsc() */ uint32_t tsc_base_kclocks; /* Initial tsc as a kclocks value */ uint32_t tsc_prev; /* For show_boot_progress() */ + uint32_t tsc_mhz; /* TSC frequency in MHz */ void *new_fdt; /* Relocated FDT */ uint32_t bist; /* Built-in self test value */ }; diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c index ceff60c..f091c91 100644 --- a/arch/x86/lib/tsc_timer.c +++ b/arch/x86/lib/tsc_timer.c @@ -293,6 +293,9 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void) { unsigned long fast_calibrate; + if (gd->arch.tsc_mhz) + return gd->arch.tsc_mhz; + fast_calibrate = try_msr_calibrate_tsc(); if (fast_calibrate) return fast_calibrate; @@ -301,6 +304,7 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void) if (!fast_calibrate) panic("TSC frequency is ZERO"); + gd->arch.tsc_mhz = fast_calibrate; return fast_calibrate; } -- cgit v0.10.2 From 6cba6b9209723bde06251bd996fda4ffce705d3f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 20:27:55 -0700 Subject: x86: Fix a warning with gcc 4.4.4 This warning appears even though it seems that the compiler could work it out. Fix it. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index a4e639d..3583619 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -238,6 +238,7 @@ static void identify_cpu(struct cpu_device_id *cpu) int i; vendor_name[0] = '\0'; /* Unset */ + cpu->device = 0; /* fix gcc 4.4.4 warning */ /* Find the id and vendor_name */ if (!has_cpuid()) { -- cgit v0.10.2 From 768e0f52f2d1a9d19842c8d1ded22a96b080a266 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 18:00:18 -0700 Subject: Move early malloc() to before arch_cpu_init() For some CPUs, having malloc() available very early is useful. There is no reason to delay this since early malloc is allocated before board_init_f() is called. Move early malloc() init nearer to the start of the init sequence. Signed-off-by: Simon Glass diff --git a/common/board_f.c b/common/board_f.c index 23d8f64..f81f70d 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -812,6 +812,7 @@ static init_fnc_t init_sequence_f[] = { setup_mon_len, setup_fdt, trace_early_init, + initf_malloc, #if defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) /* TODO: can this go into arch_cpu_init()? */ probecpu, @@ -826,7 +827,6 @@ static init_fnc_t init_sequence_f[] = { #ifdef CONFIG_OF_CONTROL fdtdec_check_fdt, #endif - initf_malloc, initf_dm, #if defined(CONFIG_BOARD_EARLY_INIT_F) board_early_init_f, -- cgit v0.10.2 From a9f04d49e519383f98689d603facdee227a2f94d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 18:00:19 -0700 Subject: fdt: Add a function to decode a variable-sized u32 array Sometimes an array can be of variable size up to a maximum. Add a helper function to decode this. Signed-off-by: Simon Glass diff --git a/include/fdtdec.h b/include/fdtdec.h index 4ae77be..6b40006 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -445,6 +445,22 @@ int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, u32 *array, int count); /** + * Look up a property in a node and return its contents in an integer + * array of given length. The property must exist but may have less data that + * expected (4*count bytes). It may have more, but this will be ignored. + * + * @param blob FDT blob + * @param node node to examine + * @param prop_name name of property to find + * @param array array to fill with data + * @param count number of array elements + * @return number of array elements if ok, or -FDT_ERR_NOTFOUND if the + * property is not found + */ +int fdtdec_get_int_array_count(const void *blob, int node, + const char *prop_name, u32 *array, int count); + +/** * Look up a property in a node and return a pointer to its contents as a * unsigned int array of given length. The property must have at least enough * data for the array ('count' cells). It may have more, but this will be diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 9714620..4aa227a 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -485,6 +485,26 @@ int fdtdec_get_int_array(const void *blob, int node, const char *prop_name, return err; } +int fdtdec_get_int_array_count(const void *blob, int node, + const char *prop_name, u32 *array, int count) +{ + const u32 *cell; + int len, elems; + int i; + + debug("%s: %s\n", __func__, prop_name); + cell = fdt_getprop(blob, node, prop_name, &len); + if (!cell) + return -FDT_ERR_NOTFOUND; + elems = len / sizeof(u32); + if (count > elems) + count = elems; + for (i = 0; i < count; i++) + array[i] = fdt32_to_cpu(cell[i]); + + return count; +} + const u32 *fdtdec_locate_array(const void *blob, int node, const char *prop_name, int count) { -- cgit v0.10.2 From 469a579df2907a421afec06e37d50e61b7d80227 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 18:00:20 -0700 Subject: dm: serial: Move current serial port pointer to global_data In general we can't store things in the data section until we have inited SDRAM. Some platforms allow this (e.g. those with SPL) but some don't. Move the pointer to global_data so that it will work on all platforms. Without this fix the serial port will not work prior to relocation with driver model on some platforms. Signed-off-by: Simon Glass diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 71f1a5c..0f019c8 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -19,15 +19,14 @@ DECLARE_GLOBAL_DATA_PTR; -/* The currently-selected console serial device */ -struct udevice *cur_dev __attribute__ ((section(".data"))); - #ifndef CONFIG_SYS_MALLOC_F_LEN #error "Serial is required before relocation - define CONFIG_SYS_MALLOC_F_LEN to make this work" #endif static void serial_find_console_or_panic(void) { + struct udevice *dev; + #ifdef CONFIG_OF_CONTROL int node; @@ -35,18 +34,21 @@ static void serial_find_console_or_panic(void) node = fdtdec_get_chosen_node(gd->fdt_blob, "stdout-path"); if (node < 0) node = fdtdec_get_alias_node(gd->fdt_blob, "console"); - if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &cur_dev)) + if (!uclass_get_device_by_of_offset(UCLASS_SERIAL, node, &dev)) { + gd->cur_serial_dev = dev; return; + } /* * If the console is not marked to be bound before relocation, bind * it anyway. */ if (node > 0 && - !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &cur_dev)) { - if (!device_probe(cur_dev)) + !lists_bind_fdt(gd->dm_root, gd->fdt_blob, node, &dev)) { + if (!device_probe(dev)) { + gd->cur_serial_dev = dev; return; - cur_dev = NULL; + } } #endif /* @@ -61,11 +63,12 @@ static void serial_find_console_or_panic(void) #else #define INDEX 0 #endif - if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &cur_dev) && - uclass_get_device(UCLASS_SERIAL, INDEX, &cur_dev) && - (uclass_first_device(UCLASS_SERIAL, &cur_dev) || !cur_dev)) + if (uclass_get_device_by_seq(UCLASS_SERIAL, INDEX, &dev) && + uclass_get_device(UCLASS_SERIAL, INDEX, &dev) && + (uclass_first_device(UCLASS_SERIAL, &dev) || !dev)) panic("No serial driver found"); #undef INDEX + gd->cur_serial_dev = dev; } /* Called prior to relocation */ @@ -127,30 +130,30 @@ static int _serial_tstc(struct udevice *dev) void serial_putc(char ch) { - _serial_putc(cur_dev, ch); + _serial_putc(gd->cur_serial_dev, ch); } void serial_puts(const char *str) { - _serial_puts(cur_dev, str); + _serial_puts(gd->cur_serial_dev, str); } int serial_getc(void) { - return _serial_getc(cur_dev); + return _serial_getc(gd->cur_serial_dev); } int serial_tstc(void) { - return _serial_tstc(cur_dev); + return _serial_tstc(gd->cur_serial_dev); } void serial_setbrg(void) { - struct dm_serial_ops *ops = serial_get_ops(cur_dev); + struct dm_serial_ops *ops = serial_get_ops(gd->cur_serial_dev); if (ops->setbrg) - ops->setbrg(cur_dev, gd->baudrate); + ops->setbrg(gd->cur_serial_dev, gd->baudrate); } void serial_stdio_init(void) diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h index 74df210..f61acbc 100644 --- a/include/asm-generic/global_data.h +++ b/include/asm-generic/global_data.h @@ -91,6 +91,7 @@ typedef struct global_data { unsigned long malloc_limit; /* limit address */ unsigned long malloc_ptr; /* current address */ #endif + struct udevice *cur_serial_dev; /* current serial device */ struct arch_global_data arch; /* architecture-specific data */ } gd_t; #endif -- cgit v0.10.2 From e5901c94e32b3533c35511d1acfb7f1587e324ee Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 18:00:21 -0700 Subject: dm: gpio: Add a function to read an ID from a list of GPIOs For board IDs a common approach is to set aside several GPIOs for use in determining the board ID. This can provide information about board features and the revision. Add a function that turns a list of GPIOs into an integer by assigning each GPIO to a single bit. Signed-off-by: Simon Glass diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 45e9a5a..255700a 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -390,6 +390,25 @@ int gpio_get_status(struct udevice *dev, int offset, char *buf, int buffsize) return 0; } +/* + * get a number comprised of multiple GPIO values. gpio_num_array points to + * the array of gpio pin numbers to scan, terminated by -1. + */ +unsigned gpio_get_values_as_int(const int *gpio_num_array) +{ + int gpio; + unsigned bitmask = 1; + unsigned vector = 0; + + while (bitmask && + ((gpio = *gpio_num_array++) != -1)) { + if (gpio_get_value(gpio)) + vector |= bitmask; + bitmask <<= 1; + } + return vector; +} + /* We need to renumber the GPIOs when any driver is probed/removed */ static int gpio_renumber(struct udevice *removed_dev) { diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index f81b51a..36a36c6 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -257,6 +257,15 @@ const char *gpio_get_bank_info(struct udevice *dev, int *offset_count); int gpio_lookup_name(const char *name, struct udevice **devp, unsigned int *offsetp, unsigned int *gpiop); -int name_to_gpio(const char *name); +/** + * get_gpios() - Turn the values of a list of GPIOs into an integer + * + * This puts the value of the first GPIO into bit 0, the second into bit 1, + * etc. then returns the resulting integer. + * + * @gpio_list: List of GPIOs to collect + * @return resulting integer value + */ +unsigned gpio_get_values_as_int(const int *gpio_list); #endif /* _ASM_GENERIC_GPIO_H_ */ -- cgit v0.10.2 From cd392fe8a0b2d37f11c9224b1c979603d7abca48 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 18:00:22 -0700 Subject: x86: Add ifdtool for working with Intel Flash Descriptor ROM images Newer Intel chips require a Management Engine which requires a particular format for the SPI flash that contains the boot loader. Add a tool that supports creating and modifying these ROM images. This tool is from Chrome OS but has been cleaned up to use U-Boot style and to add comments. A few features have been added also. Signed-off-by: Simon Glass diff --git a/tools/Makefile b/tools/Makefile index c422b76..a4216a1 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -126,6 +126,8 @@ hostprogs-$(CONFIG_EXYNOS5250) += mkexynosspl hostprogs-$(CONFIG_EXYNOS5420) += mkexynosspl HOSTCFLAGS_mkexynosspl.o := -pedantic +hostprogs-$(CONFIG_X86) += ifdtool + hostprogs-$(CONFIG_MX23) += mxsboot hostprogs-$(CONFIG_MX28) += mxsboot HOSTCFLAGS_mxsboot.o := -pedantic diff --git a/tools/ifdtool.c b/tools/ifdtool.c new file mode 100644 index 0000000..2c9bbda --- /dev/null +++ b/tools/ifdtool.c @@ -0,0 +1,1039 @@ +/* + * ifdtool - Manage Intel Firmware Descriptor information + * + * Copyright 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0 + * + * From Coreboot project, but it got a serious code clean-up + * and a few new features + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ifdtool.h" + +#undef DEBUG + +#ifdef DEBUG +#define debug(fmt, args...) printf(fmt, ##args) +#else +#define debug(fmt, args...) +#endif + +#define FD_SIGNATURE 0x0FF0A55A +#define FLREG_BASE(reg) ((reg & 0x00000fff) << 12); +#define FLREG_LIMIT(reg) (((reg & 0x0fff0000) >> 4) | 0xfff); + +/** + * find_fd() - Find the flash description in the ROM image + * + * @image: Pointer to image + * @size: Size of image in bytes + * @return pointer to structure, or NULL if not found + */ +static struct fdbar_t *find_fd(char *image, int size) +{ + uint32_t *ptr, *end; + + /* Scan for FD signature */ + for (ptr = (uint32_t *)image, end = ptr + size / 4; ptr < end; ptr++) { + if (*ptr == FD_SIGNATURE) + break; + } + + if (ptr == end) { + printf("No Flash Descriptor found in this image\n"); + return NULL; + } + + debug("Found Flash Descriptor signature at 0x%08x\n", i); + + return (struct fdbar_t *)ptr; +} + +/** + * get_region() - Get information about the selected region + * + * @frba: Flash region list + * @region_type: Type of region (0..MAX_REGIONS-1) + * @region: Region information is written here + * @return 0 if OK, else -ve + */ +static int get_region(struct frba_t *frba, int region_type, + struct region_t *region) +{ + if (region_type >= MAX_REGIONS) { + fprintf(stderr, "Invalid region type.\n"); + return -1; + } + + region->base = FLREG_BASE(frba->flreg[region_type]); + region->limit = FLREG_LIMIT(frba->flreg[region_type]); + region->size = region->limit - region->base + 1; + + return 0; +} + +static const char *region_name(int region_type) +{ + static const char *const regions[] = { + "Flash Descriptor", + "BIOS", + "Intel ME", + "GbE", + "Platform Data" + }; + + assert(region_type < MAX_REGIONS); + + return regions[region_type]; +} + +static const char *region_filename(int region_type) +{ + static const char *const region_filenames[] = { + "flashregion_0_flashdescriptor.bin", + "flashregion_1_bios.bin", + "flashregion_2_intel_me.bin", + "flashregion_3_gbe.bin", + "flashregion_4_platform_data.bin" + }; + + assert(region_type < MAX_REGIONS); + + return region_filenames[region_type]; +} + +static int dump_region(int num, struct frba_t *frba) +{ + struct region_t region; + int ret; + + ret = get_region(frba, num, ®ion); + if (ret) + return ret; + + printf(" Flash Region %d (%s): %08x - %08x %s\n", + num, region_name(num), region.base, region.limit, + region.size < 1 ? "(unused)" : ""); + + return ret; +} + +static void dump_frba(struct frba_t *frba) +{ + int i; + + printf("Found Region Section\n"); + for (i = 0; i < MAX_REGIONS; i++) { + printf("FLREG%d: 0x%08x\n", i, frba->flreg[i]); + dump_region(i, frba); + } +} + +static void decode_spi_frequency(unsigned int freq) +{ + switch (freq) { + case SPI_FREQUENCY_20MHZ: + printf("20MHz"); + break; + case SPI_FREQUENCY_33MHZ: + printf("33MHz"); + break; + case SPI_FREQUENCY_50MHZ: + printf("50MHz"); + break; + default: + printf("unknown<%x>MHz", freq); + } +} + +static void decode_component_density(unsigned int density) +{ + switch (density) { + case COMPONENT_DENSITY_512KB: + printf("512KiB"); + break; + case COMPONENT_DENSITY_1MB: + printf("1MiB"); + break; + case COMPONENT_DENSITY_2MB: + printf("2MiB"); + break; + case COMPONENT_DENSITY_4MB: + printf("4MiB"); + break; + case COMPONENT_DENSITY_8MB: + printf("8MiB"); + break; + case COMPONENT_DENSITY_16MB: + printf("16MiB"); + break; + default: + printf("unknown<%x>MiB", density); + } +} + +static void dump_fcba(struct fcba_t *fcba) +{ + printf("\nFound Component Section\n"); + printf("FLCOMP 0x%08x\n", fcba->flcomp); + printf(" Dual Output Fast Read Support: %ssupported\n", + (fcba->flcomp & (1 << 30)) ? "" : "not "); + printf(" Read ID/Read Status Clock Frequency: "); + decode_spi_frequency((fcba->flcomp >> 27) & 7); + printf("\n Write/Erase Clock Frequency: "); + decode_spi_frequency((fcba->flcomp >> 24) & 7); + printf("\n Fast Read Clock Frequency: "); + decode_spi_frequency((fcba->flcomp >> 21) & 7); + printf("\n Fast Read Support: %ssupported", + (fcba->flcomp & (1 << 20)) ? "" : "not "); + printf("\n Read Clock Frequency: "); + decode_spi_frequency((fcba->flcomp >> 17) & 7); + printf("\n Component 2 Density: "); + decode_component_density((fcba->flcomp >> 3) & 7); + printf("\n Component 1 Density: "); + decode_component_density(fcba->flcomp & 7); + printf("\n"); + printf("FLILL 0x%08x\n", fcba->flill); + printf(" Invalid Instruction 3: 0x%02x\n", + (fcba->flill >> 24) & 0xff); + printf(" Invalid Instruction 2: 0x%02x\n", + (fcba->flill >> 16) & 0xff); + printf(" Invalid Instruction 1: 0x%02x\n", + (fcba->flill >> 8) & 0xff); + printf(" Invalid Instruction 0: 0x%02x\n", + fcba->flill & 0xff); + printf("FLPB 0x%08x\n", fcba->flpb); + printf(" Flash Partition Boundary Address: 0x%06x\n\n", + (fcba->flpb & 0xfff) << 12); +} + +static void dump_fpsba(struct fpsba_t *fpsba) +{ + int i; + + printf("Found PCH Strap Section\n"); + for (i = 0; i < MAX_STRAPS; i++) + printf("PCHSTRP%-2d: 0x%08x\n", i, fpsba->pchstrp[i]); +} + +static const char *get_enabled(int flag) +{ + return flag ? "enabled" : "disabled"; +} + +static void decode_flmstr(uint32_t flmstr) +{ + printf(" Platform Data Region Write Access: %s\n", + get_enabled(flmstr & (1 << 28))); + printf(" GbE Region Write Access: %s\n", + get_enabled(flmstr & (1 << 27))); + printf(" Intel ME Region Write Access: %s\n", + get_enabled(flmstr & (1 << 26))); + printf(" Host CPU/BIOS Region Write Access: %s\n", + get_enabled(flmstr & (1 << 25))); + printf(" Flash Descriptor Write Access: %s\n", + get_enabled(flmstr & (1 << 24))); + + printf(" Platform Data Region Read Access: %s\n", + get_enabled(flmstr & (1 << 20))); + printf(" GbE Region Read Access: %s\n", + get_enabled(flmstr & (1 << 19))); + printf(" Intel ME Region Read Access: %s\n", + get_enabled(flmstr & (1 << 18))); + printf(" Host CPU/BIOS Region Read Access: %s\n", + get_enabled(flmstr & (1 << 17))); + printf(" Flash Descriptor Read Access: %s\n", + get_enabled(flmstr & (1 << 16))); + + printf(" Requester ID: 0x%04x\n\n", + flmstr & 0xffff); +} + +static void dump_fmba(struct fmba_t *fmba) +{ + printf("Found Master Section\n"); + printf("FLMSTR1: 0x%08x (Host CPU/BIOS)\n", fmba->flmstr1); + decode_flmstr(fmba->flmstr1); + printf("FLMSTR2: 0x%08x (Intel ME)\n", fmba->flmstr2); + decode_flmstr(fmba->flmstr2); + printf("FLMSTR3: 0x%08x (GbE)\n", fmba->flmstr3); + decode_flmstr(fmba->flmstr3); +} + +static void dump_fmsba(struct fmsba_t *fmsba) +{ + int i; + + printf("Found Processor Strap Section\n"); + for (i = 0; i < 4; i++) + printf("????: 0x%08x\n", fmsba->data[0]); +} + +static void dump_jid(uint32_t jid) +{ + printf(" SPI Component Device ID 1: 0x%02x\n", + (jid >> 16) & 0xff); + printf(" SPI Component Device ID 0: 0x%02x\n", + (jid >> 8) & 0xff); + printf(" SPI Component Vendor ID: 0x%02x\n", + jid & 0xff); +} + +static void dump_vscc(uint32_t vscc) +{ + printf(" Lower Erase Opcode: 0x%02x\n", + vscc >> 24); + printf(" Lower Write Enable on Write Status: 0x%02x\n", + vscc & (1 << 20) ? 0x06 : 0x50); + printf(" Lower Write Status Required: %s\n", + vscc & (1 << 19) ? "Yes" : "No"); + printf(" Lower Write Granularity: %d bytes\n", + vscc & (1 << 18) ? 64 : 1); + printf(" Lower Block / Sector Erase Size: "); + switch ((vscc >> 16) & 0x3) { + case 0: + printf("256 Byte\n"); + break; + case 1: + printf("4KB\n"); + break; + case 2: + printf("8KB\n"); + break; + case 3: + printf("64KB\n"); + break; + } + + printf(" Upper Erase Opcode: 0x%02x\n", + (vscc >> 8) & 0xff); + printf(" Upper Write Enable on Write Status: 0x%02x\n", + vscc & (1 << 4) ? 0x06 : 0x50); + printf(" Upper Write Status Required: %s\n", + vscc & (1 << 3) ? "Yes" : "No"); + printf(" Upper Write Granularity: %d bytes\n", + vscc & (1 << 2) ? 64 : 1); + printf(" Upper Block / Sector Erase Size: "); + switch (vscc & 0x3) { + case 0: + printf("256 Byte\n"); + break; + case 1: + printf("4KB\n"); + break; + case 2: + printf("8KB\n"); + break; + case 3: + printf("64KB\n"); + break; + } +} + +static void dump_vtba(struct vtba_t *vtba, int vtl) +{ + int i; + int num = (vtl >> 1) < 8 ? (vtl >> 1) : 8; + + printf("ME VSCC table:\n"); + for (i = 0; i < num; i++) { + printf(" JID%d: 0x%08x\n", i, vtba->entry[i].jid); + dump_jid(vtba->entry[i].jid); + printf(" VSCC%d: 0x%08x\n", i, vtba->entry[i].vscc); + dump_vscc(vtba->entry[i].vscc); + } + printf("\n"); +} + +static void dump_oem(uint8_t *oem) +{ + int i, j; + printf("OEM Section:\n"); + for (i = 0; i < 4; i++) { + printf("%02x:", i << 4); + for (j = 0; j < 16; j++) + printf(" %02x", oem[(i<<4)+j]); + printf("\n"); + } + printf("\n"); +} + +/** + * dump_fd() - Display a dump of the full flash description + * + * @image: Pointer to image + * @size: Size of image in bytes + * @return 0 if OK, -1 on error + */ +static int dump_fd(char *image, int size) +{ + struct fdbar_t *fdb = find_fd(image, size); + + if (!fdb) + return -1; + + printf("FLMAP0: 0x%08x\n", fdb->flmap0); + printf(" NR: %d\n", (fdb->flmap0 >> 24) & 7); + printf(" FRBA: 0x%x\n", ((fdb->flmap0 >> 16) & 0xff) << 4); + printf(" NC: %d\n", ((fdb->flmap0 >> 8) & 3) + 1); + printf(" FCBA: 0x%x\n", ((fdb->flmap0) & 0xff) << 4); + + printf("FLMAP1: 0x%08x\n", fdb->flmap1); + printf(" ISL: 0x%02x\n", (fdb->flmap1 >> 24) & 0xff); + printf(" FPSBA: 0x%x\n", ((fdb->flmap1 >> 16) & 0xff) << 4); + printf(" NM: %d\n", (fdb->flmap1 >> 8) & 3); + printf(" FMBA: 0x%x\n", ((fdb->flmap1) & 0xff) << 4); + + printf("FLMAP2: 0x%08x\n", fdb->flmap2); + printf(" PSL: 0x%04x\n", (fdb->flmap2 >> 8) & 0xffff); + printf(" FMSBA: 0x%x\n", ((fdb->flmap2) & 0xff) << 4); + + printf("FLUMAP1: 0x%08x\n", fdb->flumap1); + printf(" Intel ME VSCC Table Length (VTL): %d\n", + (fdb->flumap1 >> 8) & 0xff); + printf(" Intel ME VSCC Table Base Address (VTBA): 0x%06x\n\n", + (fdb->flumap1 & 0xff) << 4); + dump_vtba((struct vtba_t *) + (image + ((fdb->flumap1 & 0xff) << 4)), + (fdb->flumap1 >> 8) & 0xff); + dump_oem((uint8_t *)image + 0xf00); + dump_frba((struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) + << 4))); + dump_fcba((struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4))); + dump_fpsba((struct fpsba_t *) + (image + (((fdb->flmap1 >> 16) & 0xff) << 4))); + dump_fmba((struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4))); + dump_fmsba((struct fmsba_t *)(image + (((fdb->flmap2) & 0xff) << 4))); + + return 0; +} + +/** + * write_regions() - Write each region from an image to its own file + * + * The filename to use in each case is fixed - see region_filename() + * + * @image: Pointer to image + * @size: Size of image in bytes + * @return 0 if OK, -ve on error + */ +static int write_regions(char *image, int size) +{ + struct fdbar_t *fdb; + struct frba_t *frba; + int ret = 0; + int i; + + fdb = find_fd(image, size); + if (!fdb) + return -1; + + frba = (struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) << 4)); + + for (i = 0; i < MAX_REGIONS; i++) { + struct region_t region; + int region_fd; + + ret = get_region(frba, i, ®ion); + if (ret) + return ret; + dump_region(i, frba); + if (region.size == 0) + continue; + region_fd = open(region_filename(i), + O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | + S_IWUSR | S_IRGRP | S_IROTH); + if (write(region_fd, image + region.base, region.size) != + region.size) { + perror("Error while writing"); + ret = -1; + } + close(region_fd); + } + + return ret; +} + +/** + * write_image() - Write the image to a file + * + * @filename: Filename to use for the image + * @image: Pointer to image + * @size: Size of image in bytes + * @return 0 if OK, -ve on error + */ +static int write_image(char *filename, char *image, int size) +{ + int new_fd; + + debug("Writing new image to %s\n", filename); + + new_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | + S_IWUSR | S_IRGRP | S_IROTH); + if (write(new_fd, image, size) != size) { + perror("Error while writing"); + return -1; + } + close(new_fd); + + return 0; +} + +/** + * set_spi_frequency() - Set the SPI frequency to use when booting + * + * Several frequencies are supported, some of which work with fast devices. + * For SPI emulators, the slowest (SPI_FREQUENCY_20MHZ) is often used. The + * Intel boot system uses this information somehow on boot. + * + * The image is updated with the supplied value + * + * @image: Pointer to image + * @size: Size of image in bytes + * @freq: SPI frequency to use + */ +static void set_spi_frequency(char *image, int size, enum spi_frequency freq) +{ + struct fdbar_t *fdb = find_fd(image, size); + struct fcba_t *fcba; + + fcba = (struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4)); + + /* clear bits 21-29 */ + fcba->flcomp &= ~0x3fe00000; + /* Read ID and Read Status Clock Frequency */ + fcba->flcomp |= freq << 27; + /* Write and Erase Clock Frequency */ + fcba->flcomp |= freq << 24; + /* Fast Read Clock Frequency */ + fcba->flcomp |= freq << 21; +} + +/** + * set_em100_mode() - Set a SPI frequency that will work with Dediprog EM100 + * + * @image: Pointer to image + * @size: Size of image in bytes + */ +static void set_em100_mode(char *image, int size) +{ + struct fdbar_t *fdb = find_fd(image, size); + struct fcba_t *fcba; + + fcba = (struct fcba_t *)(image + (((fdb->flmap0) & 0xff) << 4)); + fcba->flcomp &= ~(1 << 30); + set_spi_frequency(image, size, SPI_FREQUENCY_20MHZ); +} + +/** + * lock_descriptor() - Lock the NE descriptor so it cannot be updated + * + * @image: Pointer to image + * @size: Size of image in bytes + */ +static void lock_descriptor(char *image, int size) +{ + struct fdbar_t *fdb = find_fd(image, size); + struct fmba_t *fmba; + + /* + * TODO: Dynamically take Platform Data Region and GbE Region into + * account. + */ + fmba = (struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4)); + fmba->flmstr1 = 0x0a0b0000; + fmba->flmstr2 = 0x0c0d0000; + fmba->flmstr3 = 0x08080118; +} + +/** + * unlock_descriptor() - Lock the NE descriptor so it can be updated + * + * @image: Pointer to image + * @size: Size of image in bytes + */ +static void unlock_descriptor(char *image, int size) +{ + struct fdbar_t *fdb = find_fd(image, size); + struct fmba_t *fmba; + + fmba = (struct fmba_t *)(image + (((fdb->flmap1) & 0xff) << 4)); + fmba->flmstr1 = 0xffff0000; + fmba->flmstr2 = 0xffff0000; + fmba->flmstr3 = 0x08080118; +} + +/** + * open_for_read() - Open a file for reading + * + * @fname: Filename to open + * @sizep: Returns file size in bytes + * @return 0 if OK, -1 on error + */ +int open_for_read(const char *fname, int *sizep) +{ + int fd = open(fname, O_RDONLY); + struct stat buf; + + if (fd == -1) { + perror("Could not open file"); + return -1; + } + if (fstat(fd, &buf) == -1) { + perror("Could not stat file"); + return -1; + } + *sizep = buf.st_size; + debug("File %s is %d bytes\n", fname, *sizep); + + return fd; +} + +/** + * inject_region() - Add a file to an image region + * + * This puts a file into a particular region of the flash. Several pre-defined + * regions are used. + * + * @image: Pointer to image + * @size: Size of image in bytes + * @region_type: Region where the file should be added + * @region_fname: Filename to add to the image + * @return 0 if OK, -ve on error + */ +int inject_region(char *image, int size, int region_type, char *region_fname) +{ + struct fdbar_t *fdb = find_fd(image, size); + struct region_t region; + struct frba_t *frba; + int region_size; + int offset = 0; + int region_fd; + int ret; + + if (!fdb) + exit(EXIT_FAILURE); + frba = (struct frba_t *)(image + (((fdb->flmap0 >> 16) & 0xff) << 4)); + + ret = get_region(frba, region_type, ®ion); + if (ret) + return -1; + if (region.size <= 0xfff) { + fprintf(stderr, "Region %s is disabled in target. Not injecting.\n", + region_name(region_type)); + return -1; + } + + region_fd = open_for_read(region_fname, ®ion_size); + if (region_fd < 0) + return region_fd; + + if ((region_size > region.size) || + ((region_type != 1) && (region_size > region.size))) { + fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x) bytes. Not injecting.\n", + region_name(region_type), region.size, + region.size, region_size, region_size); + return -1; + } + + if ((region_type == 1) && (region_size < region.size)) { + fprintf(stderr, "Region %s is %d(0x%x) bytes. File is %d(0x%x) bytes. Padding before injecting.\n", + region_name(region_type), region.size, + region.size, region_size, region_size); + offset = region.size - region_size; + memset(image + region.base, 0xff, offset); + } + + if (size < region.base + offset + region_size) { + fprintf(stderr, "Output file is too small. (%d < %d)\n", + size, region.base + offset + region_size); + return -1; + } + + if (read(region_fd, image + region.base + offset, region_size) + != region_size) { + perror("Could not read file"); + return -1; + } + + close(region_fd); + + debug("Adding %s as the %s section\n", region_fname, + region_name(region_type)); + + return 0; +} + +/** + * write_data() - Write some raw data into a region + * + * This puts a file into a particular place in the flash, ignoring the + * regions. Be careful not to overwrite something important. + * + * @image: Pointer to image + * @size: Size of image in bytes + * @addr: x86 ROM address to put file. The ROM ends at + * 0xffffffff so use an address relative to that. For an + * 8MB ROM the start address is 0xfff80000. + * @write_fname: Filename to add to the image + * @return 0 if OK, -ve on error + */ +static int write_data(char *image, int size, unsigned int addr, + const char *write_fname) +{ + int write_fd, write_size; + int offset; + + write_fd = open_for_read(write_fname, &write_size); + if (write_fd < 0) + return write_fd; + + offset = addr + size; + debug("Writing %s to offset %#x\n", write_fname, offset); + + if (offset < 0 || offset + write_size > size) { + fprintf(stderr, "Output file is too small. (%d < %d)\n", + size, offset + write_size); + return -1; + } + + if (read(write_fd, image + offset, write_size) != write_size) { + perror("Could not read file"); + return -1; + } + + close(write_fd); + + return 0; +} + +static void print_version(void) +{ + printf("ifdtool v%s -- ", IFDTOOL_VERSION); + printf("Copyright (C) 2014 Google Inc.\n\n"); + printf("SPDX-License-Identifier: GPL-2.0+\n"); +} + +static void print_usage(const char *name) +{ + printf("usage: %s [-vhdix?] []\n", name); + printf("\n" + " -d | --dump: dump intel firmware descriptor\n" + " -x | --extract: extract intel fd modules\n" + " -i | --inject : inject file into region \n" + " -w | --write : write file to appear at memory address \n" + " -s | --spifreq <20|33|50> set the SPI frequency\n" + " -e | --em100 set SPI frequency to 20MHz and disable\n" + " Dual Output Fast Read Support\n" + " -l | --lock Lock firmware descriptor and ME region\n" + " -u | --unlock Unlock firmware descriptor and ME region\n" + " -r | --romsize Specify ROM size\n" + " -D | --write-descriptor Write descriptor at base\n" + " -c | --create Create a new empty image\n" + " -v | --version: print the version\n" + " -h | --help: print this help\n\n" + " is one of Descriptor, BIOS, ME, GbE, Platform\n" + "\n"); +} + +/** + * get_two_words() - Convert a string into two words separated by : + * + * The supplied string is split at ':', two substrings are allocated and + * returned. + * + * @str: String to split + * @firstp: Returns first string + * @secondp: Returns second string + * @return 0 if OK, -ve if @str does not have a : + */ +static int get_two_words(const char *str, char **firstp, char **secondp) +{ + const char *p; + + p = strchr(str, ':'); + if (!p) + return -1; + *firstp = strdup(str); + (*firstp)[p - str] = '\0'; + *secondp = strdup(p + 1); + + return 0; +} + +int main(int argc, char *argv[]) +{ + int opt, option_index = 0; + int mode_dump = 0, mode_extract = 0, mode_inject = 0; + int mode_spifreq = 0, mode_em100 = 0, mode_locked = 0; + int mode_unlocked = 0, mode_write = 0, mode_write_descriptor = 0; + int create = 0; + char *region_type_string = NULL, *src_fname = NULL; + char *addr_str = NULL; + int region_type = -1, inputfreq = 0; + enum spi_frequency spifreq = SPI_FREQUENCY_20MHZ; + unsigned int addr = 0; + int rom_size = -1; + bool write_it; + char *filename; + char *outfile = NULL; + struct stat buf; + int size = 0; + int bios_fd; + char *image; + int ret; + static struct option long_options[] = { + {"create", 0, NULL, 'c'}, + {"dump", 0, NULL, 'd'}, + {"descriptor", 1, NULL, 'D'}, + {"em100", 0, NULL, 'e'}, + {"extract", 0, NULL, 'x'}, + {"inject", 1, NULL, 'i'}, + {"lock", 0, NULL, 'l'}, + {"romsize", 1, NULL, 'r'}, + {"spifreq", 1, NULL, 's'}, + {"unlock", 0, NULL, 'u'}, + {"write", 1, NULL, 'w'}, + {"version", 0, NULL, 'v'}, + {"help", 0, NULL, 'h'}, + {0, 0, 0, 0} + }; + + while ((opt = getopt_long(argc, argv, "cdD:ehi:lr:s:uvw:x?", + long_options, &option_index)) != EOF) { + switch (opt) { + case 'c': + create = 1; + break; + case 'd': + mode_dump = 1; + break; + case 'D': + mode_write_descriptor = 1; + src_fname = optarg; + break; + case 'e': + mode_em100 = 1; + break; + case 'i': + if (get_two_words(optarg, ®ion_type_string, + &src_fname)) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + if (!strcasecmp("Descriptor", region_type_string)) + region_type = 0; + else if (!strcasecmp("BIOS", region_type_string)) + region_type = 1; + else if (!strcasecmp("ME", region_type_string)) + region_type = 2; + else if (!strcasecmp("GbE", region_type_string)) + region_type = 3; + else if (!strcasecmp("Platform", region_type_string)) + region_type = 4; + if (region_type == -1) { + fprintf(stderr, "No such region type: '%s'\n\n", + region_type_string); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + mode_inject = 1; + break; + case 'l': + mode_locked = 1; + break; + case 'r': + rom_size = strtol(optarg, NULL, 0); + debug("ROM size %d\n", rom_size); + break; + case 's': + /* Parse the requested SPI frequency */ + inputfreq = strtol(optarg, NULL, 0); + switch (inputfreq) { + case 20: + spifreq = SPI_FREQUENCY_20MHZ; + break; + case 33: + spifreq = SPI_FREQUENCY_33MHZ; + break; + case 50: + spifreq = SPI_FREQUENCY_50MHZ; + break; + default: + fprintf(stderr, "Invalid SPI Frequency: %d\n", + inputfreq); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + mode_spifreq = 1; + break; + case 'u': + mode_unlocked = 1; + break; + case 'v': + print_version(); + exit(EXIT_SUCCESS); + break; + case 'w': + mode_write = 1; + if (get_two_words(optarg, &addr_str, &src_fname)) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + addr = strtol(optarg, NULL, 0); + break; + case 'x': + mode_extract = 1; + break; + case 'h': + case '?': + default: + print_usage(argv[0]); + exit(EXIT_SUCCESS); + break; + } + } + + if (mode_locked == 1 && mode_unlocked == 1) { + fprintf(stderr, "Locking/Unlocking FD and ME are mutually exclusive\n"); + exit(EXIT_FAILURE); + } + + if (mode_inject == 1 && mode_write == 1) { + fprintf(stderr, "Inject/Write are mutually exclusive\n"); + exit(EXIT_FAILURE); + } + + if ((mode_dump + mode_extract + mode_inject + + (mode_spifreq | mode_em100 | mode_unlocked | + mode_locked)) > 1) { + fprintf(stderr, "You may not specify more than one mode.\n\n"); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + if ((mode_dump + mode_extract + mode_inject + mode_spifreq + + mode_em100 + mode_locked + mode_unlocked + mode_write + + mode_write_descriptor) == 0) { + fprintf(stderr, "You need to specify a mode.\n\n"); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + if (create && rom_size == -1) { + fprintf(stderr, "You need to specify a rom size when creating.\n\n"); + exit(EXIT_FAILURE); + } + + if (optind + 1 != argc) { + fprintf(stderr, "You need to specify a file.\n\n"); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + filename = argv[optind]; + if (optind + 2 != argc) + outfile = argv[optind + 1]; + + if (create) + bios_fd = open(filename, O_WRONLY | O_CREAT, 0666); + else + bios_fd = open(filename, outfile ? O_RDONLY : O_RDWR); + + if (bios_fd == -1) { + perror("Could not open file"); + exit(EXIT_FAILURE); + } + + if (!create) { + if (fstat(bios_fd, &buf) == -1) { + perror("Could not stat file"); + exit(EXIT_FAILURE); + } + size = buf.st_size; + } + + debug("File %s is %d bytes\n", filename, size); + + if (rom_size == -1) + rom_size = size; + + image = malloc(rom_size); + if (!image) { + printf("Out of memory.\n"); + exit(EXIT_FAILURE); + } + + memset(image, '\xff', rom_size); + if (!create && read(bios_fd, image, size) != size) { + perror("Could not read file"); + exit(EXIT_FAILURE); + } + if (size != rom_size) { + debug("ROM size changed to %d bytes\n", rom_size); + size = rom_size; + } + + write_it = true; + ret = 0; + if (mode_dump) { + ret = dump_fd(image, size); + write_it = false; + } + + if (mode_extract) { + ret = write_regions(image, size); + write_it = false; + } + + if (mode_write_descriptor) + ret = write_data(image, size, -size, src_fname); + + if (mode_inject) + ret = inject_region(image, size, region_type, src_fname); + + if (mode_write) + ret = write_data(image, size, addr, src_fname); + + if (mode_spifreq) + set_spi_frequency(image, size, spifreq); + + if (mode_em100) + set_em100_mode(image, size); + + if (mode_locked) + lock_descriptor(image, size); + + if (mode_unlocked) + unlock_descriptor(image, size); + + if (write_it) { + if (outfile) { + ret = write_image(outfile, image, size); + } else { + if (lseek(bios_fd, 0, SEEK_SET)) { + perror("Error while seeking"); + ret = -1; + } + if (write(bios_fd, image, size) != size) { + perror("Error while writing"); + ret = -1; + } + } + } + + free(image); + close(bios_fd); + + return ret ? 1 : 0; +} diff --git a/tools/ifdtool.h b/tools/ifdtool.h new file mode 100644 index 0000000..fbec421 --- /dev/null +++ b/tools/ifdtool.h @@ -0,0 +1,88 @@ +/* + * ifdtool - Manage Intel Firmware Descriptor information + * + * Copyright (C) 2011 The ChromiumOS Authors. + * + * SPDX-License-Identifier: GPL-2.0 + * + * From Coreboot project + */ + +#include + +#define __packed __attribute__((packed)) + +#define IFDTOOL_VERSION "1.1-U-Boot" + +enum spi_frequency { + SPI_FREQUENCY_20MHZ = 0, + SPI_FREQUENCY_33MHZ = 1, + SPI_FREQUENCY_50MHZ = 4, +}; + +enum component_density { + COMPONENT_DENSITY_512KB = 0, + COMPONENT_DENSITY_1MB = 1, + COMPONENT_DENSITY_2MB = 2, + COMPONENT_DENSITY_4MB = 3, + COMPONENT_DENSITY_8MB = 4, + COMPONENT_DENSITY_16MB = 5, +}; + +/* flash descriptor */ +struct __packed fdbar_t { + uint32_t flvalsig; + uint32_t flmap0; + uint32_t flmap1; + uint32_t flmap2; + uint8_t reserved[0xefc - 0x20]; + uint32_t flumap1; +}; + +#define MAX_REGIONS 5 + +/* regions */ +struct __packed frba_t { + uint32_t flreg[MAX_REGIONS]; +}; + +/* component section */ +struct __packed fcba_t { + uint32_t flcomp; + uint32_t flill; + uint32_t flpb; +}; + +#define MAX_STRAPS 18 + +/* pch strap */ +struct __packed fpsba_t { + uint32_t pchstrp[MAX_STRAPS]; +}; + +/* master */ +struct __packed fmba_t { + uint32_t flmstr1; + uint32_t flmstr2; + uint32_t flmstr3; +}; + +/* processor strap */ +struct __packed fmsba_t { + uint32_t data[8]; +}; + +/* ME VSCC */ +struct vscc_t { + uint32_t jid; + uint32_t vscc; +}; + +struct vtba_t { + /* Actual number of entries specified in vtl */ + struct vscc_t entry[8]; +}; + +struct region_t { + int base, limit, size; +}; -- cgit v0.10.2 From 880a3cc4381ac0e2e39ce3313e267fb3e297bc3f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 18:00:23 -0700 Subject: x86: config: Move common x86 configs to a common file Many of the x86 CONFIG options will be common across different boards. Move them to a common file. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/include/configs/coreboot.h b/include/configs/coreboot.h index fef267f..2581380 100644 --- a/include/configs/coreboot.h +++ b/include/configs/coreboot.h @@ -6,7 +6,6 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include /* * board/config.h - configuration options, board specific */ @@ -14,27 +13,23 @@ #ifndef __CONFIG_H #define __CONFIG_H +#include + /* * High Level Configuration Options * (easy to change) */ #define CONFIG_SYS_COREBOOT -#define CONFIG_SHOW_BOOT_PROGRESS #define CONFIG_LAST_STAGE_INIT -#define CONFIG_SYS_VSNPRINTF -#define CONFIG_ZBOOT_32 -#define CONFIG_PHYSMEM #define CONFIG_SYS_EARLY_PCI_INIT -#define CONFIG_DISPLAY_BOARDINFO_LATE -#define CONFIG_DISPLAY_CPUINFO -#define CONFIG_DM -#define CONFIG_CMD_DM -#define CONFIG_DM_GPIO -#define CONFIG_DM_SERIAL +#define CONFIG_SYS_CAR_ADDR 0x19200000 +#define CONFIG_SYS_CAR_SIZE (16 * 1024) +#define CONFIG_SYS_MONITOR_LEN (256 * 1024) -#define CONFIG_LMB -#define CONFIG_OF_LIBFDT +#define CONFIG_TRACE_EARLY_SIZE (8 << 20) +#define CONFIG_TRACE_EARLY +#define CONFIG_TRACE_EARLY_ADDR 0x01400000 #define CONFIG_BOOTSTAGE #define CONFIG_BOOTSTAGE_REPORT @@ -45,26 +40,6 @@ #define CONFIG_BOOTSTAGE_STASH_SIZE 0x7fc #define CONFIG_BOOTSTAGE_USER_COUNT 60 -#define CONFIG_LZO -#define CONFIG_FIT -#undef CONFIG_ZLIB -#undef CONFIG_GZIP -#define CONFIG_SYS_BOOTM_LEN (16 << 20) - -/*----------------------------------------------------------------------- - * Watchdog Configuration - */ -#undef CONFIG_WATCHDOG -#undef CONFIG_HW_WATCHDOG - -/* SATA AHCI storage */ - -#define CONFIG_SCSI_AHCI - -#ifdef CONFIG_SCSI_AHCI -#define CONFIG_LIBATA -#define CONFIG_SYS_64BIT_LBA -#define CONFIG_SATA_INTEL 1 #define CONFIG_SCSI_DEV_LIST {PCI_VENDOR_ID_INTEL, \ PCI_DEVICE_ID_INTEL_NM10_AHCI}, \ {PCI_VENDOR_ID_INTEL, \ @@ -74,249 +49,27 @@ {PCI_VENDOR_ID_INTEL, \ PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE} -#define CONFIG_SYS_SCSI_MAX_SCSI_ID 2 -#define CONFIG_SYS_SCSI_MAX_LUN 1 -#define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ - CONFIG_SYS_SCSI_MAX_LUN) -#endif - -/* Generic TPM interfaced through LPC bus */ -#define CONFIG_TPM -#define CONFIG_TPM_TIS_LPC -#define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000 - -/*----------------------------------------------------------------------- - * Real Time Clock Configuration - */ -#define CONFIG_RTC_MC146818 -#define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0 -#define CONFIG_SYS_ISA_IO CONFIG_SYS_ISA_IO_BASE_ADDRESS - -/*----------------------------------------------------------------------- - * Serial Configuration - */ #define CONFIG_COREBOOT_SERIAL -#define CONFIG_SYS_NS16550 -#define CONFIG_BAUDRATE 115200 -#define CONFIG_SYS_BAUDRATE_TABLE {300, 600, 1200, 2400, 4800, \ - 9600, 19200, 38400, 115200} -#define CONFIG_SYS_NS16550_PORT_MAPPED #define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \ "stdout=vga,serial,cbmem\0" \ "stderr=vga,serial,cbmem\0" -#define CONFIG_CONSOLE_MUX -#define CONFIG_SYS_CONSOLE_IS_IN_ENV -#define CONFIG_SYS_STDIO_DEREGISTER #define CONFIG_CBMEM_CONSOLE -#define CONFIG_CMDLINE_EDITING -#define CONFIG_COMMAND_HISTORY -#define CONFIG_AUTO_COMPLETE -#define CONFIG_SYS_HUSH_PARSER - -#define CONFIG_SUPPORT_VFAT -/************************************************************ - * ATAPI support (experimental) - ************************************************************/ -#define CONFIG_ATAPI - -/************************************************************ - * DISK Partition support - ************************************************************/ -#define CONFIG_EFI_PARTITION -#define CONFIG_DOS_PARTITION -#define CONFIG_MAC_PARTITION -#define CONFIG_ISO_PARTITION /* Experimental */ - -#define CONFIG_CMD_PART -#define CONFIG_CMD_CBFS -#define CONFIG_CMD_EXT4 -#define CONFIG_CMD_EXT4_WRITE -#define CONFIG_PARTITION_UUIDS - -/*----------------------------------------------------------------------- - * Video Configuration - */ -#define CONFIG_VIDEO #define CONFIG_VIDEO_COREBOOT -#define CONFIG_VIDEO_SW_CURSOR -#define VIDEO_FB_16BPP_WORD_SWAP -#define CONFIG_I8042_KBD -#define CONFIG_CFB_CONSOLE -#define CONFIG_SYS_CONSOLE_INFO_QUIET -/* x86 GPIOs are accessed through a PCI device */ -#define CONFIG_INTEL_ICH6_GPIO - -/*----------------------------------------------------------------------- - * Command line configuration. - */ -#include +#define CONFIG_NR_DRAM_BANKS 4 #define CONFIG_TRACE #define CONFIG_CMD_TRACE #define CONFIG_TRACE_BUFFER_SIZE (16 << 20) -#define CONFIG_TRACE_EARLY_SIZE (8 << 20) -#define CONFIG_TRACE_EARLY -#define CONFIG_TRACE_EARLY_ADDR 0x01400000 - -#define CONFIG_CMD_BDI -#define CONFIG_CMD_BOOTD -#define CONFIG_CMD_CONSOLE -#define CONFIG_CMD_DATE -#define CONFIG_CMD_ECHO -#undef CONFIG_CMD_FLASH -#define CONFIG_CMD_FPGA -#define CONFIG_CMD_FPGA_LOADMK -#define CONFIG_CMD_GPIO -#define CONFIG_CMD_IMI -#undef CONFIG_CMD_IMLS -#define CONFIG_CMD_IO -#define CONFIG_CMD_IRQ -#define CONFIG_CMD_ITEST -#define CONFIG_CMD_LOADB -#define CONFIG_CMD_LOADS -#define CONFIG_CMD_MEMORY -#define CONFIG_CMD_MISC -#define CONFIG_CMD_NET -#undef CONFIG_CMD_NFS -#define CONFIG_CMD_PCI -#define CONFIG_CMD_PING -#define CONFIG_CMD_RUN -#define CONFIG_CMD_SAVEENV -#define CONFIG_CMD_SETGETDCR -#define CONFIG_CMD_SOURCE -#define CONFIG_CMD_TIME -#define CONFIG_CMD_GETTIME -#define CONFIG_CMD_XIMG -#define CONFIG_CMD_SCSI - -#define CONFIG_CMD_FAT -#define CONFIG_CMD_EXT2 - -#define CONFIG_CMD_ZBOOT -#define CONFIG_CMD_ELF #define CONFIG_BOOTDELAY 2 -#define CONFIG_BOOTARGS \ - "root=/dev/sdb3 init=/sbin/init rootwait ro" -#define CONFIG_BOOTCOMMAND \ - "ext2load scsi 0:3 01000000 /boot/vmlinuz; zboot 01000000" - - -#if defined(CONFIG_CMD_KGDB) -#define CONFIG_KGDB_BAUDRATE 115200 -#endif - -/* - * Miscellaneous configurable options - */ -#define CONFIG_SYS_LONGHELP -#define CONFIG_SYS_CBSIZE 512 -#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ - sizeof(CONFIG_SYS_PROMPT) + \ - 16) -#define CONFIG_SYS_MAXARGS 16 -#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE - -#define CONFIG_SYS_MEMTEST_START 0x00100000 -#define CONFIG_SYS_MEMTEST_END 0x01000000 -#define CONFIG_SYS_LOAD_ADDR 0x20000000 - -/*----------------------------------------------------------------------- - * SDRAM Configuration - */ -#define CONFIG_NR_DRAM_BANKS 4 - -/* CONFIG_SYS_SDRAM_DRCTMCTL Overrides the following*/ -#undef CONFIG_SYS_SDRAM_PRECHARGE_DELAY -#undef CONFIG_SYS_SDRAM_RAS_CAS_DELAY -#undef CONFIG_SYS_SDRAM_CAS_LATENCY_2T -#undef CONFIG_SYS_SDRAM_CAS_LATENCY_3T - -/*----------------------------------------------------------------------- - * CPU Features - */ - -#define CONFIG_SYS_X86_TSC_TIMER -#define CONFIG_SYS_PCAT_INTERRUPTS -#define CONFIG_SYS_PCAT_TIMER -#define CONFIG_SYS_NUM_IRQS 16 - -/*----------------------------------------------------------------------- - * Memory organization: - * 32kB Stack - * 16kB Cache-As-RAM @ 0x19200000 - * 256kB Monitor - * (128kB + Environment Sector Size) malloc pool - */ -#define CONFIG_SYS_STACK_SIZE (32 * 1024) -#define CONFIG_SYS_CAR_ADDR 0x19200000 -#define CONFIG_SYS_CAR_SIZE (16 * 1024) -#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE -#define CONFIG_SYS_MONITOR_LEN (256 * 1024) -#define CONFIG_SYS_MALLOC_LEN (0x20000 + 128 * 1024) -#define CONFIG_SYS_MALLOC_F_LEN (1 << 10) - -/* allow to overwrite serial and ethaddr */ -#define CONFIG_ENV_OVERWRITE - -/*----------------------------------------------------------------------- - * FLASH configuration - */ -#define CONFIG_ICH_SPI -#define CONFIG_SPI_FLASH -#define CONFIG_SPI_FLASH_MACRONIX -#define CONFIG_SPI_FLASH_WINBOND -#define CONFIG_SPI_FLASH_GIGADEVICE -#define CONFIG_SYS_NO_FLASH -#define CONFIG_CMD_SF -#define CONFIG_CMD_SF_TEST -#define CONFIG_CMD_SPI -#define CONFIG_SPI - -/*----------------------------------------------------------------------- - * Environment configuration - */ -#define CONFIG_ENV_IS_NOWHERE -#define CONFIG_ENV_SIZE 0x01000 - -/*----------------------------------------------------------------------- - * PCI configuration - */ -#define CONFIG_PCI #define CONFIG_CROS_EC #define CONFIG_CROS_EC_LPC #define CONFIG_CMD_CROS_EC #define CONFIG_ARCH_EARLY_INIT_R -/*----------------------------------------------------------------------- - * USB configuration - */ -#define CONFIG_USB_EHCI -#define CONFIG_USB_EHCI_PCI -#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 12 -#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 -#define CONFIG_USB_STORAGE -#define CONFIG_USB_KEYBOARD -#define CONFIG_SYS_USB_EVENT_POLL - -#define CONFIG_USB_HOST_ETHER -#define CONFIG_USB_ETHER_ASIX -#define CONFIG_USB_ETHER_SMSC95XX -#define CONFIG_TFTP_TSIZE -#define CONFIG_CMD_DHCP -#define CONFIG_BOOTP_BOOTFILESIZE -#define CONFIG_BOOTP_BOOTPATH -#define CONFIG_BOOTP_GATEWAY -#define CONFIG_BOOTP_HOSTNAME - -#define CONFIG_CMD_USB - -#define CONFIG_EXTRA_ENV_SETTINGS \ - CONFIG_STD_DEVICES_SETTINGS - #endif /* __CONFIG_H */ diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h new file mode 100644 index 0000000..825e9f7 --- /dev/null +++ b/include/configs/x86-common.h @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2008 + * Graeme Russ, graeme.russ@gmail.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +#ifndef __CONFIG_X86_COMMON_H +#define __CONFIG_X86_COMMON_H + +/* + * High Level Configuration Options + * (easy to change) + */ +#define CONFIG_SHOW_BOOT_PROGRESS +#define CONFIG_SYS_VSNPRINTF +#define CONFIG_ZBOOT_32 +#define CONFIG_PHYSMEM +#define CONFIG_DISPLAY_BOARDINFO_LATE +#define CONFIG_DISPLAY_CPUINFO + +#define CONFIG_DM +#define CONFIG_CMD_DM +#define CONFIG_DM_GPIO +#define CONFIG_DM_SERIAL + +#define CONFIG_LMB +#define CONFIG_OF_LIBFDT + +#define CONFIG_LZO +#define CONFIG_FIT +#undef CONFIG_ZLIB +#undef CONFIG_GZIP +#define CONFIG_SYS_BOOTM_LEN (16 << 20) + +/* SATA AHCI storage */ + +#define CONFIG_SCSI_AHCI +#define CONFIG_SATA_INTEL +#ifdef CONFIG_SCSI_AHCI +#define CONFIG_LIBATA +#define CONFIG_SYS_64BIT_LBA + +#define CONFIG_SYS_SCSI_MAX_SCSI_ID 2 +#define CONFIG_SYS_SCSI_MAX_LUN 1 +#define CONFIG_SYS_SCSI_MAX_DEVICE (CONFIG_SYS_SCSI_MAX_SCSI_ID * \ + CONFIG_SYS_SCSI_MAX_LUN) +#endif + +/* Generic TPM interfaced through LPC bus */ +#define CONFIG_TPM +#define CONFIG_TPM_TIS_LPC +#define CONFIG_TPM_TIS_BASE_ADDRESS 0xfed40000 + +/*----------------------------------------------------------------------- + * Real Time Clock Configuration + */ +#define CONFIG_RTC_MC146818 +#define CONFIG_SYS_ISA_IO_BASE_ADDRESS 0 +#define CONFIG_SYS_ISA_IO CONFIG_SYS_ISA_IO_BASE_ADDRESS + +/*----------------------------------------------------------------------- + * Serial Configuration + */ +#define CONFIG_SYS_NS16550 +#define CONFIG_BAUDRATE 115200 +#define CONFIG_SYS_BAUDRATE_TABLE {300, 600, 1200, 2400, 4800, \ + 9600, 19200, 38400, 115200} +#define CONFIG_SYS_NS16550_PORT_MAPPED + +#define CONFIG_CONSOLE_MUX +#define CONFIG_SYS_CONSOLE_IS_IN_ENV +#define CONFIG_SYS_STDIO_DEREGISTER + +#define CONFIG_CMDLINE_EDITING +#define CONFIG_COMMAND_HISTORY +#define CONFIG_AUTO_COMPLETE +#define CONFIG_SYS_HUSH_PARSER + +#define CONFIG_SUPPORT_VFAT +/************************************************************ + * ATAPI support (experimental) + ************************************************************/ +#define CONFIG_ATAPI + +/************************************************************ + * DISK Partition support + ************************************************************/ +#define CONFIG_EFI_PARTITION +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION /* Experimental */ + +#define CONFIG_CMD_PART +#define CONFIG_CMD_CBFS +#define CONFIG_CMD_EXT4 +#define CONFIG_CMD_EXT4_WRITE +#define CONFIG_PARTITION_UUIDS + +#define CONFIG_SYS_CONSOLE_INFO_QUIET + +/* x86 GPIOs are accessed through a PCI device */ +#define CONFIG_INTEL_ICH6_GPIO + +/*----------------------------------------------------------------------- + * Command line configuration. + */ +#include + +#define CONFIG_CMD_BDI +#define CONFIG_CMD_BOOTD +#define CONFIG_CMD_CONSOLE +#define CONFIG_CMD_DATE +#define CONFIG_CMD_ECHO +#undef CONFIG_CMD_FLASH +#define CONFIG_CMD_FPGA +#define CONFIG_CMD_FPGA_LOADMK +#define CONFIG_CMD_GPIO +#define CONFIG_CMD_IMI +#undef CONFIG_CMD_IMLS +#define CONFIG_CMD_IO +#define CONFIG_CMD_IRQ +#define CONFIG_CMD_ITEST +#define CONFIG_CMD_LOADB +#define CONFIG_CMD_LOADS +#define CONFIG_CMD_MEMORY +#define CONFIG_CMD_MISC +#define CONFIG_CMD_NET +#undef CONFIG_CMD_NFS +#define CONFIG_CMD_PCI +#define CONFIG_CMD_PING +#define CONFIG_CMD_RUN +#define CONFIG_CMD_SAVEENV +#define CONFIG_CMD_SETGETDCR +#define CONFIG_CMD_SOURCE +#define CONFIG_CMD_TIME +#define CONFIG_CMD_GETTIME +#define CONFIG_CMD_XIMG +#define CONFIG_CMD_SCSI + +#define CONFIG_CMD_FAT +#define CONFIG_CMD_EXT2 + +#define CONFIG_CMD_ZBOOT +#define CONFIG_CMD_ELF + +#define CONFIG_BOOTARGS \ + "root=/dev/sdb3 init=/sbin/init rootwait ro" +#define CONFIG_BOOTCOMMAND \ + "ext2load scsi 0:3 01000000 /boot/vmlinuz; zboot 01000000" + +#if defined(CONFIG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE 115200 +#endif + +/* + * Miscellaneous configurable options + */ +#define CONFIG_SYS_LONGHELP +#define CONFIG_SYS_CBSIZE 512 +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + \ + 16) +#define CONFIG_SYS_MAXARGS 16 +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE + +#define CONFIG_SYS_MEMTEST_START 0x00100000 +#define CONFIG_SYS_MEMTEST_END 0x01000000 +#define CONFIG_SYS_LOAD_ADDR 0x20000000 + +/*----------------------------------------------------------------------- + * Video Configuration + */ +#define CONFIG_VIDEO +#define CONFIG_VIDEO_SW_CURSOR +#define VIDEO_FB_16BPP_WORD_SWAP +#define CONFIG_I8042_KBD +#define CONFIG_CFB_CONSOLE + +/*----------------------------------------------------------------------- + * CPU Features + */ + +#define CONFIG_SYS_X86_TSC_TIMER +#define CONFIG_SYS_PCAT_INTERRUPTS +#define CONFIG_SYS_PCAT_TIMER +#define CONFIG_SYS_NUM_IRQS 16 + +#define CONFIG_SYS_STACK_SIZE (32 * 1024) +#define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE +#define CONFIG_SYS_MALLOC_LEN 0x200000 +#define CONFIG_SYS_MALLOC_F_LEN (1 << 10) + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE + +/*----------------------------------------------------------------------- + * FLASH configuration + */ +#define CONFIG_ICH_SPI +#define CONFIG_SPI_FLASH +#define CONFIG_SPI_FLASH_MACRONIX +#define CONFIG_SPI_FLASH_WINBOND +#define CONFIG_SPI_FLASH_GIGADEVICE +#define CONFIG_SYS_NO_FLASH +#define CONFIG_CMD_SF +#define CONFIG_CMD_SF_TEST +#define CONFIG_CMD_SPI +#define CONFIG_SPI + +/*----------------------------------------------------------------------- + * Environment configuration + */ +#define CONFIG_ENV_IS_NOWHERE +#define CONFIG_ENV_SIZE 0x01000 + +/*----------------------------------------------------------------------- + * PCI configuration + */ +#define CONFIG_PCI + +/*----------------------------------------------------------------------- + * USB configuration + */ +#define CONFIG_USB_EHCI +#define CONFIG_USB_EHCI_PCI +#define CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS 12 +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 +#define CONFIG_USB_STORAGE +#define CONFIG_USB_KEYBOARD +#define CONFIG_SYS_USB_EVENT_POLL + +#define CONFIG_USB_HOST_ETHER +#define CONFIG_USB_ETHER_ASIX +#define CONFIG_USB_ETHER_SMSC95XX +#define CONFIG_TFTP_TSIZE +#define CONFIG_CMD_DHCP +#define CONFIG_BOOTP_BOOTFILESIZE +#define CONFIG_BOOTP_BOOTPATH +#define CONFIG_BOOTP_GATEWAY +#define CONFIG_BOOTP_HOSTNAME + +#define CONFIG_CMD_USB + +#define CONFIG_EXTRA_ENV_SETTINGS \ + CONFIG_STD_DEVICES_SETTINGS + +#endif /* __CONFIG_H */ -- cgit v0.10.2 From 21b9b14b49b742c3ee70f819aab3918f517bf0b8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 18:00:24 -0700 Subject: x86: Add processor functions to halt and get stack pointer Add a function to get the stack pointer and another to halt the CPU. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index bb3172f..b2854a9 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -30,4 +30,23 @@ enum { #define X86_GDT_SIZE (X86_GDT_NUM_ENTRIES * X86_GDT_ENTRY_SIZE) +#ifndef __ASSEMBLY__ + +static inline __attribute__((always_inline)) void cpu_hlt(void) +{ + asm("hlt"); +} + +static inline ulong cpu_get_sp(void) +{ + ulong result; + + asm volatile( + "mov %%esp, %%eax" + : "=a" (result)); + return result; +} + +#endif /* __ASSEMBLY__ */ + #endif -- cgit v0.10.2 From 003504b6fe2296f581191b77fd2f1e98c4f4720c Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 18:00:25 -0700 Subject: x86: Remove unnecessary find_fdt(), prepare_fdt() functions These are no-longer needed so drop them. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/include/asm/init_helpers.h b/arch/x86/include/asm/init_helpers.h index b07887e..8cbe08e 100644 --- a/arch/x86/include/asm/init_helpers.h +++ b/arch/x86/include/asm/init_helpers.h @@ -13,7 +13,5 @@ int calculate_relocation_address(void); int init_cache_f_r(void); int init_bd_struct_r(void); int init_func_spi(void); -int find_fdt(void); -int prepare_fdt(void); #endif /* !_INIT_HELPERS_H_ */ diff --git a/arch/x86/lib/init_helpers.c b/arch/x86/lib/init_helpers.c index b5d937f..be4eb12 100644 --- a/arch/x86/lib/init_helpers.c +++ b/arch/x86/lib/init_helpers.c @@ -87,30 +87,3 @@ int init_func_spi(void) puts("ready\n"); return 0; } - -int find_fdt(void) -{ -#ifdef CONFIG_OF_EMBED - /* Get a pointer to the FDT */ - gd->fdt_blob = __dtb_dt_begin; -#elif defined CONFIG_OF_SEPARATE - /* FDT is at end of image */ - gd->fdt_blob = (ulong *)&_end; -#endif - /* Allow the early environment to override the fdt address */ - gd->fdt_blob = (void *)getenv_ulong("fdtcontroladdr", 16, - (uintptr_t)gd->fdt_blob); - - return 0; -} - -int prepare_fdt(void) -{ - /* For now, put this check after the console is ready */ - if (fdtdec_prepare_fdt()) { - panic("** CONFIG_OF_CONTROL defined but no FDT - please see " - "doc/README.fdt-control"); - } - - return 0; -} diff --git a/common/board_f.c b/common/board_f.c index f81f70d..6e6a1a2 100644 --- a/common/board_f.c +++ b/common/board_f.c @@ -818,11 +818,6 @@ static init_fnc_t init_sequence_f[] = { probecpu, #endif arch_cpu_init, /* basic arch cpu dependent setup */ -#ifdef CONFIG_X86 -# ifdef CONFIG_OF_CONTROL - find_fdt, /* TODO(sjg@chromium.org): remove */ -# endif -#endif mark_bootstage, #ifdef CONFIG_OF_CONTROL fdtdec_check_fdt, -- cgit v0.10.2 From 727c1a987147bb55ff41ab62f7e01293a38910b8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Mon, 10 Nov 2014 18:00:26 -0700 Subject: x86: Replace fill_processor_name() with cpu_get_name() This implementation has a 'cpu' prefix and returns a pointer to the string, avoiding the need for copying. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 5527183..c9f83b0 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -72,6 +72,11 @@ void show_boot_progress(int val) outb(val, 0x80); } +int print_cpuinfo(void) +{ + return default_print_cpuinfo(); +} + int last_stage_init(void) { if (gd->flags & GD_FLG_COLD_BOOT) diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 3583619..97c77ba 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -492,14 +492,14 @@ const char *cpu_vendor_name(int vendor) return name; } -void fill_processor_name(char *processor_name) +char *cpu_get_name(char *name) { + unsigned int *name_as_ints = (unsigned int *)name; struct cpuid_result regs; - char temp_processor_name[49]; - char *processor_name_start; - unsigned int *name_as_ints = (unsigned int *)temp_processor_name; + char *ptr; int i; + /* This bit adds up to 48 bytes */ for (i = 0; i < 3; i++) { regs = cpuid(0x80000002 + i); name_as_ints[i * 4 + 0] = regs.eax; @@ -507,19 +507,17 @@ void fill_processor_name(char *processor_name) name_as_ints[i * 4 + 2] = regs.ecx; name_as_ints[i * 4 + 3] = regs.edx; } - - temp_processor_name[48] = 0; + name[CPU_MAX_NAME_LEN - 1] = '\0'; /* Skip leading spaces. */ - processor_name_start = temp_processor_name; - while (*processor_name_start == ' ') - processor_name_start++; + ptr = name; + while (*ptr == ' ') + ptr++; - memset(processor_name, 0, 49); - strcpy(processor_name, processor_name_start); + return ptr; } -int print_cpuinfo(void) +int default_print_cpuinfo(void) { printf("CPU: %s, vendor %s, device %xh\n", cpu_has_64bit() ? "x86_64" : "x86", diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h index 89b748b..c839291 100644 --- a/arch/x86/include/asm/cpu.h +++ b/arch/x86/include/asm/cpu.h @@ -179,12 +179,17 @@ int cpu_has_64bit(void); */ const char *cpu_vendor_name(int vendor); +#define CPU_MAX_NAME_LEN 49 + /** - * fill_processor_name() - Get processor name + * cpu_get_name() - Get the name of the current cpu * - * @processor_name: Address to hold the processor name string + * @name: Place to put name, which must be CPU_MAX_NAME_LEN bytes including + * @return pointer to name, which will likely be a few bytes after the start + * of @name + * \0 terminator */ -void fill_processor_name(char *processor_name); +char *cpu_get_name(char *name); /** * cpu_call64() - Jump to a 64-bit Linux kernel (internal function) diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 8d5b438..0399417 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -45,6 +45,7 @@ int x86_init_cache(void); void reset_cpu(ulong addr); ulong board_get_usable_ram_top(ulong total_size); void dram_init_banksize(void); +int default_print_cpuinfo(void); void setup_pcat_compatibility(void); -- cgit v0.10.2 From a5eb04db1a8fac8c7691c87cbbb890c8174ab906 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 13 Nov 2014 12:28:41 +0900 Subject: x86: use CONFIG_SYS_COREBOOT to descend into coreboot/ directory The references of CONFIG_SYS_COREBOOT in arch/x86/cpu/coreboot/Makefile are redundant because the build system descends into the directory only when CONFIG_SYS_COREBOOT is defined. Signed-off-by: Masahiro Yamada Cc: Simon Glass Acked-by: Simon Glass diff --git a/arch/x86/cpu/coreboot/Makefile b/arch/x86/cpu/coreboot/Makefile index cd0bf4e..35e6cdd 100644 --- a/arch/x86/cpu/coreboot/Makefile +++ b/arch/x86/cpu/coreboot/Makefile @@ -13,10 +13,10 @@ # SPDX-License-Identifier: GPL-2.0+ # -obj-$(CONFIG_SYS_COREBOOT) += car.o -obj-$(CONFIG_SYS_COREBOOT) += coreboot.o -obj-$(CONFIG_SYS_COREBOOT) += tables.o -obj-$(CONFIG_SYS_COREBOOT) += ipchecksum.o -obj-$(CONFIG_SYS_COREBOOT) += sdram.o -obj-$(CONFIG_SYS_COREBOOT) += timestamp.o +obj-y += car.o +obj-y += coreboot.o +obj-y += tables.o +obj-y += ipchecksum.o +obj-y += sdram.o +obj-y += timestamp.o obj-$(CONFIG_PCI) += pci.o -- cgit v0.10.2 From 5c1b685e46756dc9504b919336321dad27dbcd9e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:04 -0700 Subject: x86: Allow timer calibration to work on ivybridge Unfortunately MSR_FSB_FREQ is not available on this CPU, and the PIT method seems to take up to 50ms which is much too long. For this CPU we know the frequency, so add another special case for now. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/lib/tsc_timer.c b/arch/x86/lib/tsc_timer.c index f091c91..fb9afed 100644 --- a/arch/x86/lib/tsc_timer.c +++ b/arch/x86/lib/tsc_timer.c @@ -36,7 +36,8 @@ DECLARE_GLOBAL_DATA_PTR; struct freq_desc { u8 x86_family; /* CPU family */ u8 x86_model; /* model */ - u8 msr_plat; /* 1: use MSR_PLATFORM_INFO, 0: MSR_IA32_PERF_STATUS */ + /* 2: use 100MHz, 1: use MSR_PLATFORM_INFO, 0: MSR_IA32_PERF_STATUS */ + u8 msr_plat; u32 freqs[MAX_NUM_FREQS]; }; @@ -49,6 +50,8 @@ static struct freq_desc freq_desc_tables[] = { { 6, 0x4a, 1, { 0, FREQ_100, FREQ_133, 0, 0, 0, 0, 0 } }, /* VLV2 */ { 6, 0x37, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_166, 0, 0, 0, 0 } }, + /* Ivybridge */ + { 6, 0x3a, 2, { 0, 0, 0, 0, 0, 0, 0, 0 } }, /* ANN */ { 6, 0x5a, 1, { FREQ_83, FREQ_100, FREQ_133, FREQ_100, 0, 0, 0, 0 } }, }; @@ -97,11 +100,18 @@ static unsigned long try_msr_calibrate_tsc(void) if (!ratio) goto fail; - /* Get FSB FREQ ID */ - rdmsr(MSR_FSB_FREQ, lo, hi); - freq_id = lo & 0x7; - freq = id_to_freq(cpu_index, freq_id); - debug("Resolved frequency ID: %u, frequency: %u KHz\n", freq_id, freq); + if (freq_desc_tables[cpu_index].msr_plat == 2) { + /* TODO: Figure out how best to deal with this */ + freq = FREQ_100; + debug("Using frequency: %u KHz\n", freq); + } else { + /* Get FSB FREQ ID */ + rdmsr(MSR_FSB_FREQ, lo, hi); + freq_id = lo & 0x7; + freq = id_to_freq(cpu_index, freq_id); + debug("Resolved frequency ID: %u, frequency: %u KHz\n", + freq_id, freq); + } if (!freq) goto fail; @@ -297,12 +307,12 @@ unsigned __attribute__((no_instrument_function)) long get_tbclk_mhz(void) return gd->arch.tsc_mhz; fast_calibrate = try_msr_calibrate_tsc(); - if (fast_calibrate) - return fast_calibrate; + if (!fast_calibrate) { - fast_calibrate = quick_pit_calibrate(); - if (!fast_calibrate) - panic("TSC frequency is ZERO"); + fast_calibrate = quick_pit_calibrate(); + if (!fast_calibrate) + panic("TSC frequency is ZERO"); + } gd->arch.tsc_mhz = fast_calibrate; return fast_calibrate; -- cgit v0.10.2 From c03c951b065f2b9f98caf913192a41a8f8200fd4 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:06 -0700 Subject: x86: ifdtool: Allow creation of an empty ROM Allow an empty ROM to be created, without needing to provide a descriptor. The descriptor is not needed on some x86 boards. Signed-off-by: Simon Glass diff --git a/tools/ifdtool.c b/tools/ifdtool.c index 2c9bbda..a4b481f 100644 --- a/tools/ifdtool.c +++ b/tools/ifdtool.c @@ -924,7 +924,7 @@ int main(int argc, char *argv[]) if ((mode_dump + mode_extract + mode_inject + mode_spifreq + mode_em100 + mode_locked + mode_unlocked + mode_write + - mode_write_descriptor) == 0) { + mode_write_descriptor) == 0 && !create) { fprintf(stderr, "You need to specify a mode.\n\n"); print_usage(argv[0]); exit(EXIT_FAILURE); -- cgit v0.10.2 From 8ef07571a0300e6ae84931c63d5eb3b2310c8aba Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:07 -0700 Subject: x86: Add chromebook_link board This board is a 'bare' version of the existing 'link 'board. It does not require coreboot to run, but is intended to start directly from the reset vector. This initial commit has place holders for a wide range of features. These will be added in follow-on patches and series. So far it cannot be booted as there is no ROM image produced, but it does build without errors. Signed-off-by: Simon Glass diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 0dba8ac..a5f24d0 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -12,9 +12,32 @@ choice config TARGET_COREBOOT bool "Support coreboot" + help + This target is used for running U-Boot on top of Coreboot. In + this case Coreboot does the early inititalisation, and U-Boot + takes over once the RAM, video and CPU are fully running. + U-Boot is loaded as a fallback payload from Coreboot, in + Coreboot terminology. This method was used for the Chromebook + Pixel when launched. + +config TARGET_CHROMEBOOK_LINK + bool "Support Chromebook link" + help + This is the Chromebook Pixel released in 2013. It uses an Intel + i5 Ivybridge which is a die-shrink of Sandybridge, with 4GB of + SDRAM. It has a Panther Point platform controller hub, PCIe + WiFi and Bluetooth. It also includes a 720p webcam, USB SD + reader, microphone and speakers, display port and 32GB SATA + solid state drive. There is a Chrome OS EC connected on LPC, + and it provides a 2560x1700 high resolution touch-enabled LCD + display. endchoice +source "arch/x86/cpu/ivybridge/Kconfig" + source "board/chromebook-x86/coreboot/Kconfig" +source "board/google/chromebook_link/Kconfig" + endmenu diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index c9f83b0..8501716 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig new file mode 100644 index 0000000..177247e --- /dev/null +++ b/arch/x86/cpu/ivybridge/Kconfig @@ -0,0 +1,171 @@ +# +# From Coreboot src/northbridge/intel/sandybridge/Kconfig +# +# Copyright (C) 2010 Google Inc. +# +# SPDX-License-Identifier: GPL-2.0 + + +config NORTHBRIDGE_INTEL_SANDYBRIDGE + bool + select CACHE_MRC_BIN + select CPU_INTEL_MODEL_206AX + +config NORTHBRIDGE_INTEL_IVYBRIDGE + bool + select CACHE_MRC_BIN + select CPU_INTEL_MODEL_306AX + +if NORTHBRIDGE_INTEL_SANDYBRIDGE + +config VGA_BIOS_ID + string + default "8086,0106" + +config CACHE_MRC_SIZE_KB + int + default 256 + +config MRC_CACHE_BASE + hex + default 0xff800000 + +config MRC_CACHE_LOCATION + hex + depends on !CHROMEOS + default 0x1ec000 + +config MRC_CACHE_SIZE + hex + depends on !CHROMEOS + default 0x10000 + +config DCACHE_RAM_BASE + hex + default 0xff7f0000 + +config DCACHE_RAM_SIZE + hex + default 0x10000 + +endif + +if NORTHBRIDGE_INTEL_IVYBRIDGE + +config VGA_BIOS_ID + string + default "8086,0166" + +config EXTERNAL_MRC_BLOB + bool + default n + +config CACHE_MRC_SIZE_KB + int + default 512 + +config MRC_CACHE_BASE + hex + default 0xff800000 + +config MRC_CACHE_LOCATION + hex + depends on !CHROMEOS + default 0x370000 + +config MRC_CACHE_SIZE + hex + depends on !CHROMEOS + default 0x10000 + +config DCACHE_RAM_BASE + hex + default 0xff7e0000 + +config DCACHE_RAM_SIZE + hex + default 0x20000 + +endif + +if NORTHBRIDGE_INTEL_SANDYBRIDGE || NORTHBRIDGE_INTEL_IVYBRIDGE + +config HAVE_MRC + bool "Add a System Agent binary" + help + Select this option to add a System Agent binary to + the resulting U-Boot image. MRC stands for Memory Reference Code. + It is a binary blob which U-Boot uses to set up SDRAM. + + Note: Without this binary U-Boot will not be able to set up its + SDRAM so will not boot. + +config DCACHE_RAM_MRC_VAR_SIZE + hex + default 0x4000 + help + This is the amount of CAR (Cache as RAM) reserved for use by the + memory reference code. This should be set to 16KB (0x4000 hex) + so that MRC has enough space to run. + +config MRC_FILE + string "Intel System Agent path and filename" + depends on HAVE_MRC + default "systemagent-ivybridge.bin" if NORTHBRIDGE_INTEL_IVYBRIDGE + default "systemagent-sandybridge.bin" if NORTHBRIDGE_INTEL_SANDYBRIDGE + help + The path and filename of the file to use as System Agent + binary. + +config CPU_SPECIFIC_OPTIONS + def_bool y + select SMM_TSEG + select ARCH_BOOTBLOCK_X86_32 + select ARCH_ROMSTAGE_X86_32 + select ARCH_RAMSTAGE_X86_32 + select SMP + select SSE2 + select UDELAY_LAPIC + select CPU_MICROCODE_IN_CBFS + select TSC_SYNC_MFENCE + select HAVE_INTEL_ME + +config SMM_TSEG_SIZE + hex + default 0x800000 + +config ENABLE_VMX + bool "Enable VMX for virtualization" + default n + help + Virtual Machine Extensions are provided in many x86 CPUs. These + provide various facilities for allowing a host OS to provide an + environment where potentially several guest OSes have only + limited access to the underlying hardware. This is achieved + without resorting to software trapping and/or instruction set + emulation (which would be very slow). + + Intel's implementation of this is called VT-x. This option enables + VT-x this so that the OS that is booted by U-Boot can make use of + these facilities. If this option is not enabled, then the host OS + will be unable to support virtualisation, or it will run very + slowly. + +endif + +config CPU_INTEL_SOCKET_RPGA989 + bool + +if CPU_INTEL_SOCKET_RPGA989 + +config SOCKET_SPECIFIC_OPTIONS # dummy + def_bool y + select MMX + select SSE + select CACHE_AS_RAM + +config CACHE_MRC_BIN + bool + default n + +endif diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile new file mode 100644 index 0000000..dbcd4bd --- /dev/null +++ b/arch/x86/cpu/ivybridge/Makefile @@ -0,0 +1,9 @@ +# +# Copyright (c) 2014 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += car.o +obj-y += cpu.o +obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/car.S b/arch/x86/cpu/ivybridge/car.S new file mode 100644 index 0000000..0480813 --- /dev/null +++ b/arch/x86/cpu/ivybridge/car.S @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * From Coreboot file cpu/intel/model_206ax/cache_as_ram.inc + * + * Copyright (C) 2000,2007 Ronald G. Minnich + * Copyright (C) 2005 Tyan (written by Yinghai Lu for Tyan) + * Copyright (C) 2007-2008 coresystems GmbH + * Copyright (C) 2012 Kyösti Mälkki + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include + + /* Note: ebp must not be touched in this code */ +.globl car_init +car_init: + /* TODO: Add cache-as-RAM init here */ + jmp car_init_ret diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c new file mode 100644 index 0000000..1cbdaaf --- /dev/null +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014 Google, Inc + * (C) Copyright 2008 + * Graeme Russ, graeme.russ@gmail.com. + * + * Some portions from coreboot src/mainboard/google/link/romstage.c + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int arch_cpu_init(void) +{ + int ret; + + timer_set_base(rdtsc()); + + ret = x86_cpu_init_f(); + if (ret) + return ret; + + return 0; +} + +int print_cpuinfo(void) +{ + char processor_name[CPU_MAX_NAME_LEN]; + const char *name; + + /* Print processor name */ + name = cpu_get_name(processor_name); + printf("CPU: %s\n", name); + + return 0; +} diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c new file mode 100644 index 0000000..5f9ae5e --- /dev/null +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2010,2011 + * Graeme Russ, + * + * Portions from Coreboot mainboard/google/link/romstage.c + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include + +int dram_init(void) +{ + /* TODO: Set up DRAM */ + + return 0; +} diff --git a/arch/x86/dts/Makefile b/arch/x86/dts/Makefile index 48265ef..bb3b116 100644 --- a/arch/x86/dts/Makefile +++ b/arch/x86/dts/Makefile @@ -1,4 +1,5 @@ dtb-y += link.dtb \ + chromebook_link.dtb \ alex.dtb targets += $(dtb-y) diff --git a/arch/x86/dts/chromebook_link.dts b/arch/x86/dts/chromebook_link.dts new file mode 120000 index 0000000..6f8c5cd --- /dev/null +++ b/arch/x86/dts/chromebook_link.dts @@ -0,0 +1 @@ +link.dts \ No newline at end of file diff --git a/arch/x86/include/asm/arch-ivybridge/gpio.h b/arch/x86/include/asm/arch-ivybridge/gpio.h new file mode 100644 index 0000000..4951a8c --- /dev/null +++ b/arch/x86/include/asm/arch-ivybridge/gpio.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2014, Google Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _X86_ARCH_GPIO_H_ +#define _X86_ARCH_GPIO_H_ + +#endif /* _X86_ARCH_GPIO_H_ */ diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig new file mode 100644 index 0000000..975d557 --- /dev/null +++ b/board/google/chromebook_link/Kconfig @@ -0,0 +1,15 @@ +if TARGET_CHROMEBOOK_LINK + +config SYS_BOARD + default "chromebook_link" + +config SYS_VENDOR + default "google" + +config SYS_SOC + default "ivybridge" + +config SYS_CONFIG_NAME + default "chromebook_link" + +endif diff --git a/board/google/chromebook_link/MAINTAINERS b/board/google/chromebook_link/MAINTAINERS new file mode 100644 index 0000000..bc253a2 --- /dev/null +++ b/board/google/chromebook_link/MAINTAINERS @@ -0,0 +1,6 @@ +CHROMEBOOK LINK BOARD +M: Simon Glass +S: Maintained +F: board/google/chromebook_link/ +F: include/configs/chromebook_link.h +F: configs/chromebook_link_defconfig diff --git a/board/google/chromebook_link/Makefile b/board/google/chromebook_link/Makefile new file mode 100644 index 0000000..a133c2e --- /dev/null +++ b/board/google/chromebook_link/Makefile @@ -0,0 +1,15 @@ +# +# Copyright (c) 2011 The Chromium OS Authors. +# (C) Copyright 2008 +# Graeme Russ, graeme.russ@gmail.com. +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2002 +# Daniel Engström, Omicron Ceti AB, daniel@omicron.se. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += link.o diff --git a/board/google/chromebook_link/link.c b/board/google/chromebook_link/link.c new file mode 100644 index 0000000..ffa9d60 --- /dev/null +++ b/board/google/chromebook_link/link.c @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include + +int arch_early_init_r(void) +{ + return 0; +} + +int board_early_init_r(void) +{ + return 0; +} diff --git a/board/google/common/Makefile b/board/google/common/Makefile new file mode 100644 index 0000000..b38bc14 --- /dev/null +++ b/board/google/common/Makefile @@ -0,0 +1,7 @@ +# +# Copyright (c) 2014 Google, Inc +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += early_init.o diff --git a/board/google/common/early_init.S b/board/google/common/early_init.S new file mode 100644 index 0000000..cf70ae4 --- /dev/null +++ b/board/google/common/early_init.S @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +.globl early_board_init +early_board_init: + /* No 32-bit board specific initialisation */ + jmp early_board_init_ret diff --git a/configs/chromebook_link_defconfig b/configs/chromebook_link_defconfig new file mode 100644 index 0000000..b83803e --- /dev/null +++ b/configs/chromebook_link_defconfig @@ -0,0 +1,10 @@ +CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xfff00000" +CONFIG_X86=y +CONFIG_TARGET_CHROMEBOOK_LINK=y +CONFIG_OF_CONTROL=y +CONFIG_OF_SEPARATE=y +CONFIG_DEFAULT_DEVICE_TREE="chromebook_link" +CONFIG_HAVE_MRC=y +CONFIG_SMM_TSEG_SIZE=0x800000 +CONFIG_FRAMEBUFFER_SET_VESA_MODE=y +CONFIG_FRAMEBUFFER_VESA_MODE_11A=y diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h new file mode 100644 index 0000000..394e27b --- /dev/null +++ b/include/configs/chromebook_link.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2008 + * Graeme Russ, graeme.russ@gmail.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include + +#define CONFIG_SYS_CAR_ADDR 0xff7e0000 +#define CONFIG_SYS_CAR_SIZE (128 * 1024) +#define CONFIG_SYS_MONITOR_LEN (1 << 20) +#define CONFIG_BOARD_EARLY_INIT_R + +#define CONFIG_NR_DRAM_BANKS 8 + +#define CONFIG_COREBOOT_SERIAL + +#define CONFIG_SCSI_DEV_LIST {PCI_VENDOR_ID_INTEL, \ + PCI_DEVICE_ID_INTEL_NM10_AHCI}, \ + {PCI_VENDOR_ID_INTEL, \ + PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_MOBILE}, \ + {PCI_VENDOR_ID_INTEL, \ + PCI_DEVICE_ID_INTEL_COUGARPOINT_AHCI_SERIES6}, \ + {PCI_VENDOR_ID_INTEL, \ + PCI_DEVICE_ID_INTEL_PANTHERPOINT_AHCI_MOBILE} + +/* + * These common x86 features are not yet supported, but are added in + * follow-on patches in this series. Add undefs here to avoid every patch + * having to put things back into x86-common.h + */ +#undef CONFIG_INTEL_ICH6_GPIO +#undef CONFIG_DM_GPIO +#undef CONFIG_CMD_GPIO +#undef CONFIG_VIDEO +#undef CONFIG_CFB_CONSOLE +#undef CONFIG_SYS_EARLY_PCI_INIT +#undef CONFIG_PCI +#undef CONFIG_ICH_SPI +#undef CONFIG_SPI +#undef CONFIG_CMD_SPI +#undef CONFIG_CMD_SF +#undef CONFIG_USB_EHCI +#undef CONFIG_CMD_USB +#undef CONFIG_CMD_SCSI + +#define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \ + "stdout=vga,serial\0" \ + "stderr=vga,serial\0" + +#endif /* __CONFIG_H */ -- cgit v0.10.2 From fce7b2768364366bd4c4af9188186f6b3f9c2fe8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:08 -0700 Subject: x86: Build a .rom file which can be flashed to an x86 machine On x86 machines U-Boot needs to be added to a large ROM image which is then flashed onto the target board. The ROM has a particular format so it makes sense for U-Boot to build this image automatically. Unfortunately it relies on binary blobs so we cannot require this for the default build as yet. Create a u-boot.rom output file for this purpose. Signed-off-by: Simon Glass diff --git a/Makefile b/Makefile index ddea534..23590d9 100644 --- a/Makefile +++ b/Makefile @@ -749,6 +749,9 @@ ALL-$(CONFIG_SPL) += $(CONFIG_SPL_TARGET:"%"=%) endif ALL-$(CONFIG_REMAKE_ELF) += u-boot.elf +# We can't do this yet due to the need for binary blobs +# ALL-$(CONFIG_X86_RESET_VECTOR) += u-boot.rom + # enable combined SPL/u-boot/dtb rules for tegra ifneq ($(CONFIG_TEGRA),) ifeq ($(CONFIG_SPL),y) @@ -817,7 +820,8 @@ OBJCOPYFLAGS_u-boot.srec := -O srec u-boot.hex u-boot.srec: u-boot FORCE $(call if_changed,objcopy) -OBJCOPYFLAGS_u-boot.bin := -O binary +OBJCOPYFLAGS_u-boot.bin := -O binary \ + $(if $(CONFIG_X86_RESET_VECTOR),-R .start16 -R .resetvec) binary_size_check: u-boot.bin FORCE @file_size=$(shell wc -c u-boot.bin | awk '{print $$1}') ; \ @@ -956,6 +960,36 @@ u-boot-nand.gph: u-boot.bin FORCE $(call if_changed,mkimage) @dd if=/dev/zero bs=8 count=1 2>/dev/null >> $@ +# x86 uses a large ROM. We fill it with 0xff, put the 16-bit stuff (including +# reset vector) at the top, Intel ME descriptor at the bottom, and U-Boot in +# the middle. +ifneq ($(CONFIG_X86_RESET_VECTOR),) +rom: u-boot.rom FORCE + +u-boot.rom: u-boot-x86-16bit.bin u-boot-dtb.bin \ + $(srctree)/board/$(BOARDDIR)/mrc.bin + $(objtree)/tools/ifdtool -c -r $(CONFIG_ROM_SIZE) u-boot.tmp + if [ -n "$(CONFIG_HAVE_INTEL_ME)" ]; then \ + $(objtree)/tools/ifdtool -D \ + $(srctree)/board/$(BOARDDIR)/descriptor.bin u-boot.tmp; \ + $(objtree)/tools/ifdtool \ + -i ME:$(srctree)/board/$(BOARDDIR)/me.bin u-boot.tmp; \ + fi + $(objtree)/tools/ifdtool -w \ + $(CONFIG_SYS_TEXT_BASE):$(objtree)/u-boot-dtb.bin u-boot.tmp + $(objtree)/tools/ifdtool -w \ + $(CONFIG_X86_MRC_START):$(srctree)/board/$(BOARDDIR)/mrc.bin \ + u-boot.tmp + $(objtree)/tools/ifdtool -w \ + $(CONFIG_SYS_X86_START16):$(objtree)/u-boot-x86-16bit.bin \ + u-boot.tmp + mv u-boot.tmp $@ + +OBJCOPYFLAGS_u-boot-x86-16bit.bin := -O binary -j .start16 -j .resetvec +u-boot-x86-16bit.bin: u-boot FORCE + $(call if_changed,objcopy) +endif + ifneq ($(CONFIG_SUNXI),) OBJCOPYFLAGS_u-boot-sunxi-with-spl.bin = -I binary -O binary \ --pad-to=$(CONFIG_SPL_PAD_TO) --gap-fill=0xff diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a5f24d0..aa7cf77 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -34,6 +34,19 @@ config TARGET_CHROMEBOOK_LINK endchoice +config ROM_SIZE + hex + default 0x800000 + +config HAVE_INTEL_ME + bool "Platform requires Intel Management Engine" + help + Newer higher-end devices have an Intel Management Engine (ME) + which is a very large binary blob (typically 1.5MB) which is + required for the platform to work. This enforces a particular + SPI flash format. You will need to supply the me.bin file in + your board directory. + source "arch/x86/cpu/ivybridge/Kconfig" source "board/chromebook-x86/coreboot/Kconfig" diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 394e27b..3137ef0 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -18,8 +18,10 @@ #define CONFIG_SYS_CAR_ADDR 0xff7e0000 #define CONFIG_SYS_CAR_SIZE (128 * 1024) #define CONFIG_SYS_MONITOR_LEN (1 << 20) +#define CONFIG_SYS_X86_START16 0xfffff800 #define CONFIG_BOARD_EARLY_INIT_R +#define CONFIG_X86_RESET_VECTOR #define CONFIG_NR_DRAM_BANKS 8 #define CONFIG_COREBOOT_SERIAL -- cgit v0.10.2 From d1cd045982b1e1e4db2c1cc2b2b932f739b78a11 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:09 -0700 Subject: x86: Emit post codes in startup code for Chromebooks On x86 it is common to use 'post codes' which are 8-bit hex values emitted from the code and visible to the user. Traditionally two 7-segment displays were made available on the motherboard to show the last post code that was emitted. This allows diagnosis of a boot problem since it is possible to see where the code got to before it died. On modern hardware these codes are not normally visible. On Chromebooks they are displayed by the Embedded Controller (EC), so it is useful to emit them. We must enable this feature for the EC to see the codes, so add an option for this. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 8501716..0760a61 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -70,7 +71,7 @@ void show_boot_progress(int val) gd->arch.tsc_prev = now; } #endif - outb(val, 0x80); + outb(val, POST_PORT); } int print_cpuinfo(void) diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index b18f320..1b738f9 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,7 @@ _start: jmp early_board_init .globl early_board_init_ret early_board_init_ret: + post_code(POST_START) /* Initialise Cache-As-RAM */ jmp car_init @@ -96,6 +98,7 @@ car_init_ret: /* Align global data to 16-byte boundary */ andl $0xfffffff0, %esp + post_code(POST_START_STACK) /* Zero the global data since it won't happen later */ xorl %eax, %eax @@ -131,6 +134,7 @@ car_init_ret: call setup_gdt /* Set parameter to board_init_f() to boot flags */ + post_code(POST_START_DONE) xorl %eax, %eax /* Enter, U-boot! */ diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h new file mode 100644 index 0000000..3371185 --- /dev/null +++ b/arch/x86/include/asm/post.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _post_h +#define _post_h + +/* port to use for post codes */ +#define POST_PORT 0x80 + +/* post codes which represent various stages of init */ +#define POST_START 0x1e +#define POST_CAR_START 0x1f + +#define POST_START_STACK 0x29 +#define POST_START_DONE 0x2a + +/* Output a post code using al - value must be 0 to 0xff */ +#ifdef __ASSEMBLY__ +#define post_code(value) \ + movb $value, %al; \ + outb %al, $POST_PORT +#else +static inline void post_code(int code) +{ + outb(code, POST_PORT); +} +#endif + +#endif diff --git a/board/google/chromebook_link/Kconfig b/board/google/chromebook_link/Kconfig index 975d557..9c715ba 100644 --- a/board/google/chromebook_link/Kconfig +++ b/board/google/chromebook_link/Kconfig @@ -12,4 +12,8 @@ config SYS_SOC config SYS_CONFIG_NAME default "chromebook_link" +config EARLY_POST_CROS_EC + bool "Enable early post to Chrome OS EC" + default y + endif diff --git a/board/google/common/early_init.S b/board/google/common/early_init.S index cf70ae4..7017185 100644 --- a/board/google/common/early_init.S +++ b/board/google/common/early_init.S @@ -6,5 +6,24 @@ .globl early_board_init early_board_init: - /* No 32-bit board specific initialisation */ + /* Enable post codes to EC */ +#ifdef CONFIG_EARLY_POST_CROS_EC + mov $0x1b, %ecx + rdmsr + and $0x100, %eax + test %eax, %eax + je 1f + + mov $0x8000f8f0, %eax + mov $0xcf8, %dx + out %eax, (%dx) + mov $0xfed1c001, %eax + mov $0xcfc, %dx + out %eax, (%dx) + mov $0xfed1f410, %esp + mov (%esp), %eax + and $0xfffffffb, %eax + mov %eax, (%esp) +1: +#endif jmp early_board_init_ret -- cgit v0.10.2 From 70a09c6c3dc25b200a9d0475afcf5dfc9836b18e Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:10 -0700 Subject: 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 diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index aa7cf77..f27d731 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..dca68e4 100644 --- a/arch/x86/cpu/ivybridge/car.S +++ b/arch/x86/cpu/ivybridge/car.S @@ -12,9 +12,167 @@ */ #include +#include +#include +#include - /* 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 #include +#include #include 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(); 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 + +#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 + 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 -- cgit v0.10.2 From d188b18f65417a0a6698c43926e3c66b134195b8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:11 -0700 Subject: x86: Refactor PCI to permit alternate init We want access PCI earlier in the init sequence, so refactor the code so that it does not require use of a BSS variable to work. This will allow us to use early malloc() to store information about a PCI hose. Common PCI code moves to arch/x86/cpu/pci.c and a new board_pci_setup_hose() function is provided by boards to set up the (single) hose used by that board. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile index 9d38ef7..97f36d5 100644 --- a/arch/x86/cpu/Makefile +++ b/arch/x86/cpu/Makefile @@ -11,3 +11,4 @@ extra-y = start.o obj-$(CONFIG_X86_RESET_VECTOR) += resetvec.o start16.o obj-y += interrupts.o cpu.o call64.o +obj-$(CONFIG_PCI) += pci.o diff --git a/arch/x86/cpu/coreboot/pci.c b/arch/x86/cpu/coreboot/pci.c index 33f16a3..4778f71 100644 --- a/arch/x86/cpu/coreboot/pci.c +++ b/arch/x86/cpu/coreboot/pci.c @@ -13,8 +13,6 @@ #include #include -static struct pci_controller coreboot_hose; - static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev, struct pci_config_table *table) { @@ -31,19 +29,13 @@ static struct pci_config_table pci_coreboot_config_table[] = { {} }; -void pci_init_board(void) +void board_pci_setup_hose(struct pci_controller *hose) { - coreboot_hose.config_table = pci_coreboot_config_table; - coreboot_hose.first_busno = 0; - coreboot_hose.last_busno = 0; - - pci_set_region(coreboot_hose.regions + 0, 0x0, 0x0, 0xffffffff, - PCI_REGION_MEM); - coreboot_hose.region_count = 1; - - pci_setup_type1(&coreboot_hose); - - pci_register_hose(&coreboot_hose); + hose->config_table = pci_coreboot_config_table; + hose->first_busno = 0; + hose->last_busno = 0; - pci_hose_scan(&coreboot_hose); + pci_set_region(hose->regions + 0, 0x0, 0x0, 0xffffffff, + PCI_REGION_MEM); + hose->region_count = 1; } diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c new file mode 100644 index 0000000..0741dc2 --- /dev/null +++ b/arch/x86/cpu/pci.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2008,2009 + * Graeme Russ, + * + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +static struct pci_controller x86_hose; + +void pci_init_board(void) +{ + struct pci_controller *hose = &x86_hose; + + board_pci_setup_hose(hose); + pci_setup_type1(hose); + pci_register_hose(hose); + + hose->last_busno = pci_hose_scan(hose); +} diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 6b16188..c160707 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -12,5 +12,16 @@ #define DEFINE_PCI_DEVICE_TABLE(_table) \ const struct pci_device_id _table[] +struct pci_controller; + void pci_setup_type1(struct pci_controller *hose); + +/** + * board_pci_setup_hose() - Set up the PCI hose + * + * This is called by the common x86 PCI code to set up the PCI controller + * hose. It may be called when no memory/BSS is available so should just + * store things in 'hose' and not in BSS variables. + */ +void board_pci_setup_hose(struct pci_controller *hose); #endif -- cgit v0.10.2 From 7430f1086429fa93e80c3951baac90e1c578898a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:12 -0700 Subject: x86: Support use of PCI before relocation Add support for using PCI before SDRAM is available, using early malloc() and global_data. Signed-off-by: Simon Glass Reviewed-by: Bin Meng diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index 0741dc2..2d8f16c 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -10,15 +10,36 @@ */ #include +#include +#include #include #include static struct pci_controller x86_hose; +int pci_early_init_hose(struct pci_controller **hosep) +{ + struct pci_controller *hose; + + hose = calloc(1, sizeof(struct pci_controller)); + if (!hose) + return -ENOMEM; + + board_pci_setup_hose(hose); + pci_setup_type1(hose); + gd->arch.hose = hose; + *hosep = hose; + + return 0; +} + void pci_init_board(void) { struct pci_controller *hose = &x86_hose; + /* Stop using the early hose */ + gd->arch.hose = NULL; + board_pci_setup_hose(hose); pci_setup_type1(hose); pci_register_hose(hose); diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 186b97e..d32987b 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -24,6 +24,7 @@ struct arch_global_data { uint32_t tsc_mhz; /* TSC frequency in MHz */ void *new_fdt; /* Relocated FDT */ uint32_t bist; /* Built-in self test value */ + struct pci_controller *hose; /* PCI hose for early use */ }; #endif diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index c160707..6e70a99 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -24,4 +24,13 @@ void pci_setup_type1(struct pci_controller *hose); * store things in 'hose' and not in BSS variables. */ void board_pci_setup_hose(struct pci_controller *hose); + +/** + * pci_early_init_hose() - Set up PCI host before relocation + * + * This allocates memory for, sets up and returns the PCI hose. It can be + * called before relocation. The hose will be stored in gd->arch.hose for + * later use, but will become invalid one DRAM is available. + */ +int pci_early_init_hose(struct pci_controller **hosep); #endif -- cgit v0.10.2 From 6e5b12b6144acd83dcfb4a79ea0beff787f3f545 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:13 -0700 Subject: x86: ivybridge: Enable PCI in early init Enable PCI so we can access devices that need to be set up before relocation. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index dbcd4bd..6d0a78d 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -6,4 +6,5 @@ obj-y += car.o obj-y += cpu.o +obj-y += pci.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 5863811..ff6b7b3 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -19,6 +20,7 @@ DECLARE_GLOBAL_DATA_PTR; int arch_cpu_init(void) { + struct pci_controller *hose; int ret; post_code(POST_CPU_INIT); @@ -28,6 +30,10 @@ int arch_cpu_init(void) if (ret) return ret; + ret = pci_early_init_hose(&hose); + if (ret) + return ret; + return 0; } diff --git a/arch/x86/cpu/ivybridge/pci.c b/arch/x86/cpu/ivybridge/pci.c new file mode 100644 index 0000000..c1ae658 --- /dev/null +++ b/arch/x86/cpu/ivybridge/pci.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2008,2009 + * Graeme Russ, + * + * (C) Copyright 2002 + * Daniel Engström, Omicron Ceti AB, + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +static void config_pci_bridge(struct pci_controller *hose, pci_dev_t dev, + struct pci_config_table *table) +{ + u8 secondary; + + hose->read_byte(hose, dev, PCI_SECONDARY_BUS, &secondary); + if (secondary != 0) + pci_hose_scan_bus(hose, secondary); +} + +static struct pci_config_table pci_ivybridge_config_table[] = { + /* vendor, device, class, bus, dev, func */ + { PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_BRIDGE_PCI, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, &config_pci_bridge }, + {} +}; + +void board_pci_setup_hose(struct pci_controller *hose) +{ + hose->config_table = pci_ivybridge_config_table; + hose->first_busno = 0; + hose->last_busno = 0; + + /* PCI memory space */ + pci_set_region(hose->regions + 0, + CONFIG_PCI_MEM_BUS, + CONFIG_PCI_MEM_PHYS, + CONFIG_PCI_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI IO space */ + pci_set_region(hose->regions + 1, + CONFIG_PCI_IO_BUS, + CONFIG_PCI_IO_PHYS, + CONFIG_PCI_IO_SIZE, + PCI_REGION_IO); + + pci_set_region(hose->regions + 2, + CONFIG_PCI_PREF_BUS, + CONFIG_PCI_PREF_PHYS, + CONFIG_PCI_PREF_SIZE, + PCI_REGION_PREFETCH); + + hose->region_count = 3; +} diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 3137ef0..0b8c067 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -45,8 +45,6 @@ #undef CONFIG_CMD_GPIO #undef CONFIG_VIDEO #undef CONFIG_CFB_CONSOLE -#undef CONFIG_SYS_EARLY_PCI_INIT -#undef CONFIG_PCI #undef CONFIG_ICH_SPI #undef CONFIG_SPI #undef CONFIG_CMD_SPI @@ -55,6 +53,18 @@ #undef CONFIG_CMD_USB #undef CONFIG_CMD_SCSI +#define CONFIG_PCI_MEM_BUS 0xe0000000 +#define CONFIG_PCI_MEM_PHYS CONFIG_PCI_MEM_BUS +#define CONFIG_PCI_MEM_SIZE 0x10000000 + +#define CONFIG_PCI_PREF_BUS 0xd0000000 +#define CONFIG_PCI_PREF_PHYS CONFIG_PCI_PREF_BUS +#define CONFIG_PCI_PREF_SIZE 0x10000000 + +#define CONFIG_PCI_IO_BUS 0x1000 +#define CONFIG_PCI_IO_PHYS CONFIG_PCI_IO_BUS +#define CONFIG_PCI_IO_SIZE 0xefff + #define CONFIG_STD_DEVICES_SETTINGS "stdin=usbkbd,vga,serial\0" \ "stdout=vga,serial\0" \ "stderr=vga,serial\0" -- cgit v0.10.2 From 6fb3b72e8745073465b4a5875b7750cc43cbd1af Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:14 -0700 Subject: x86: pci: Allow configuration before relocation Add simple PCI access routines for x86 which permit use before relocation. The normal PCI stack is still used, but for pre-relocation use there can only ever be a single hose. After relocation, fall back to the normal access, although even then on x86 machines there is normally only a single PCI bus. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/pci.c b/arch/x86/cpu/pci.c index 2d8f16c..e399388 100644 --- a/arch/x86/cpu/pci.c +++ b/arch/x86/cpu/pci.c @@ -46,3 +46,53 @@ void pci_init_board(void) hose->last_busno = pci_hose_scan(hose); } + +static struct pci_controller *get_hose(void) +{ + if (gd->arch.hose) + return gd->arch.hose; + + return pci_bus_to_hose(0); +} + +unsigned int pci_read_config8(pci_dev_t dev, unsigned where) +{ + uint8_t value; + + pci_hose_read_config_byte(get_hose(), dev, where, &value); + + return value; +} + +unsigned int pci_read_config16(pci_dev_t dev, unsigned where) +{ + uint16_t value; + + pci_hose_read_config_word(get_hose(), dev, where, &value); + + return value; +} + +unsigned int pci_read_config32(pci_dev_t dev, unsigned where) +{ + uint32_t value; + + pci_hose_read_config_dword(get_hose(), dev, where, &value); + + return value; +} + +void pci_write_config8(pci_dev_t dev, unsigned where, unsigned value) +{ + pci_hose_write_config_byte(get_hose(), dev, where, value); +} + +void pci_write_config16(pci_dev_t dev, unsigned where, unsigned value) +{ + pci_hose_write_config_word(get_hose(), dev, where, value); +} + +void pci_write_config32(pci_dev_t dev, unsigned where, unsigned value) +{ + pci_hose_write_config_dword(get_hose(), dev, where, value); +} diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h index 6e70a99..98817aa 100644 --- a/arch/x86/include/asm/pci.h +++ b/arch/x86/include/asm/pci.h @@ -33,4 +33,17 @@ void board_pci_setup_hose(struct pci_controller *hose); * later use, but will become invalid one DRAM is available. */ int pci_early_init_hose(struct pci_controller **hosep); + +/* + * Simple PCI access routines - these work from either the early PCI hose + * or the 'real' one, created after U-Boot has memory available + */ +unsigned int pci_read_config8(pci_dev_t dev, unsigned where); +unsigned int pci_read_config16(pci_dev_t dev, unsigned where); +unsigned int pci_read_config32(pci_dev_t dev, unsigned where); + +void pci_write_config8(pci_dev_t dev, unsigned where, unsigned value); +void pci_write_config16(pci_dev_t dev, unsigned where, unsigned value); +void pci_write_config32(pci_dev_t dev, unsigned where, unsigned value); + #endif -- cgit v0.10.2 From 2b6051541b562b72d2cf784376a84552da18318d Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:15 -0700 Subject: x86: ivybridge: Add early LPC init so that serial works The PCH (Platform Controller Hub) includes an LPC (Low Pin Count) device which provides a serial port. This is accessible on Chromebooks, so enable it early in the boot process. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 6d0a78d..4b77c9c 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -6,5 +6,6 @@ obj-y += car.o obj-y += cpu.o +obj-y += lpc.o obj-y += pci.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index ff6b7b3..5d7640b 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -11,16 +11,21 @@ */ #include +#include +#include #include #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; int arch_cpu_init(void) { + const void *blob = gd->fdt_blob; struct pci_controller *hose; + int node; int ret; post_code(POST_CPU_INIT); @@ -34,6 +39,13 @@ int arch_cpu_init(void) if (ret) return ret; + node = fdtdec_next_compatible(blob, 0, COMPAT_INTEL_LPC); + if (node < 0) + return -ENOENT; + ret = lpc_early_init(gd->fdt_blob, node, PCH_LPC_DEV); + if (ret) + return ret; + return 0; } diff --git a/arch/x86/cpu/ivybridge/lpc.c b/arch/x86/cpu/ivybridge/lpc.c new file mode 100644 index 0000000..621ef2c --- /dev/null +++ b/arch/x86/cpu/ivybridge/lpc.c @@ -0,0 +1,48 @@ +/* + * From coreboot southbridge/intel/bd82x6x/lpc.c + * + * Copyright (C) 2008-2009 coresystems GmbH + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include + +int lpc_early_init(const void *blob, int node, pci_dev_t dev) +{ + struct reg_info { + u32 base; + u32 size; + } values[4], *ptr; + int count; + int i; + + count = fdtdec_get_int_array_count(blob, node, "gen-dec", + (u32 *)values, sizeof(values) / sizeof(u32)); + if (count < 0) + return -EINVAL; + + /* Set COM1/COM2 decode range */ + pci_write_config16(dev, LPC_IO_DEC, 0x0010); + + /* Enable PS/2 Keyboard/Mouse, EC areas and COM1 */ + pci_write_config16(dev, LPC_EN, KBC_LPC_EN | MC_LPC_EN | + GAMEL_LPC_EN | COMA_LPC_EN); + + /* Write all registers but use 0 if we run out of data */ + count = count * sizeof(u32) / sizeof(values[0]); + for (i = 0, ptr = values; i < ARRAY_SIZE(values); i++, ptr++) { + u32 reg = 0; + + if (i < count) + reg = ptr->base | PCI_COMMAND_IO | (ptr->size << 16); + pci_write_config32(dev, LPC_GENX_DEC(i), reg); + } + + return 0; +} diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index f2fcb39..63933aa 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -53,6 +53,7 @@ compatible = "intel,lpc"; #address-cells = <1>; #size-cells = <1>; + gen-dec = <0x800 0xfc 0x900 0xfc>; cros-ec@200 { compatible = "google,cros-ec"; reg = <0x204 1 0x200 1 0x880 0x80>; diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h new file mode 100644 index 0000000..26ddeab --- /dev/null +++ b/arch/x86/include/asm/arch-ivybridge/pch.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * From Coreboot src/southbridge/intel/bd82x6x/pch.h + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2012 The Chromium OS Authors. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ASM_ARCH_PCH_H +#define _ASM_ARCH_PCH_H + +#include + +/* PCI Configuration Space (D31:F0): LPC */ +#define PCH_LPC_DEV PCI_BDF(0, 0x1f, 0) + +#define LPC_IO_DEC 0x80 /* IO Decode Ranges Register */ +#define LPC_EN 0x82 /* LPC IF Enables Register */ +#define CNF2_LPC_EN (1 << 13) /* 0x4e/0x4f */ +#define CNF1_LPC_EN (1 << 12) /* 0x2e/0x2f */ +#define MC_LPC_EN (1 << 11) /* 0x62/0x66 */ +#define KBC_LPC_EN (1 << 10) /* 0x60/0x64 */ +#define GAMEH_LPC_EN (1 << 9) /* 0x208/0x20f */ +#define GAMEL_LPC_EN (1 << 8) /* 0x200/0x207 */ +#define FDD_LPC_EN (1 << 3) /* LPC_IO_DEC[12] */ +#define LPT_LPC_EN (1 << 2) /* LPC_IO_DEC[9:8] */ +#define COMB_LPC_EN (1 << 1) /* LPC_IO_DEC[6:4] */ +#define COMA_LPC_EN (1 << 0) /* LPC_IO_DEC[3:2] */ +#define LPC_GEN1_DEC 0x84 /* LPC IF Generic Decode Range 1 */ +#define LPC_GEN2_DEC 0x88 /* LPC IF Generic Decode Range 2 */ +#define LPC_GEN3_DEC 0x8c /* LPC IF Generic Decode Range 3 */ +#define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */ +#define LPC_GENX_DEC(x) (0x84 + 4 * (x)) + +/** + * lpc_early_init() - set up LPC serial ports and other early things + * + * @blob: Device tree blob + * @node: Offset of LPC node + * @dev: PCH PCI device containing the LPC + * @return 0 if OK, -ve on error + */ +int lpc_early_init(const void *blob, int node, pci_dev_t dev); + +#endif diff --git a/doc/device-tree-bindings/misc/intel-lpc.txt b/doc/device-tree-bindings/misc/intel-lpc.txt new file mode 100644 index 0000000..7e1b389 --- /dev/null +++ b/doc/device-tree-bindings/misc/intel-lpc.txt @@ -0,0 +1,23 @@ +Intel LPC Device Binding +======================== + +The device tree node which describes the operation of the Intel Low Pin +Count device is as follows: + +Required properties : +- compatible = "intel,lpc" +- gen-dec : Specifies the values for the gen-dec registers. Up to four cell + pairs can be provided - the first of each pair is the base address and + the second is the size. These are written into the GENx_DEC registers of + the LPC device + + +Example +------- + +lpc { + compatible = "intel,lpc"; + #address-cells = <1>; + #size-cells = <1>; + gen-dec = <0x800 0xfc 0x900 0xfc>; +}; -- cgit v0.10.2 From 378a8634ad12981779c24e6ec29619deff88d19b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:16 -0700 Subject: x86: Tidy up coreboot header usage There is no need to explicitly write 'arch-coreboot' when including headers, as when the arch directory points to coreboot the correct files will be used. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 0760a61..3356121 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -16,8 +16,8 @@ #include #include #include -#include -#include +#include +#include #include DECLARE_GLOBAL_DATA_PTR; diff --git a/arch/x86/cpu/coreboot/ipchecksum.c b/arch/x86/cpu/coreboot/ipchecksum.c index 57733d8..5f6c009 100644 --- a/arch/x86/cpu/coreboot/ipchecksum.c +++ b/arch/x86/cpu/coreboot/ipchecksum.c @@ -30,7 +30,7 @@ */ #include -#include +#include unsigned short ipchksum(const void *vptr, unsigned long nbytes) { diff --git a/arch/x86/cpu/coreboot/tables.c b/arch/x86/cpu/coreboot/tables.c index 0d91adc..92b7528 100644 --- a/arch/x86/cpu/coreboot/tables.c +++ b/arch/x86/cpu/coreboot/tables.c @@ -8,9 +8,9 @@ */ #include -#include -#include -#include +#include +#include +#include /* * This needs to be in the .data section so that it's copied over during -- cgit v0.10.2 From 3f70a6f5773432c83429e33dbc062812113b1c50 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:17 -0700 Subject: x86: Add clr/setbits functions These are available on other architectures. Make them available on x86 also. Signed-off-by: Simon Glass diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 86bac90..fcd9aa9 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -69,6 +69,55 @@ #define memcpy_fromio(a,b,c) memcpy((a),(b),(c)) #define memcpy_toio(a,b,c) memcpy((a),(b),(c)) +#define write_arch(type, endian, a, v) __raw_write##type(cpu_to_##endian(v), a) +#define read_arch(type, endian, a) endian##_to_cpu(__raw_read##type(a)) + +#define write_le64(a, v) write_arch(q, le64, a, v) +#define write_le32(a, v) write_arch(l, le32, a, v) +#define write_le16(a, v) write_arch(w, le16, a, v) + +#define read_le64(a) read_arch(q, le64, a) +#define read_le32(a) read_arch(l, le32, a) +#define read_le16(a) read_arch(w, le16, a) + +#define write_be32(a, v) write_arch(l, be32, a, v) +#define write_be16(a, v) write_arch(w, be16, a, v) + +#define read_be32(a) read_arch(l, be32, a) +#define read_be16(a) read_arch(w, be16, a) + +#define write_8(a, v) __raw_writeb(v, a) +#define read_8(a) __raw_readb(a) + +#define clrbits(type, addr, clear) \ + write_##type((addr), read_##type(addr) & ~(clear)) + +#define setbits(type, addr, set) \ + write_##type((addr), read_##type(addr) | (set)) + +#define clrsetbits(type, addr, clear, set) \ + write_##type((addr), (read_##type(addr) & ~(clear)) | (set)) + +#define clrbits_be32(addr, clear) clrbits(be32, addr, clear) +#define setbits_be32(addr, set) setbits(be32, addr, set) +#define clrsetbits_be32(addr, clear, set) clrsetbits(be32, addr, clear, set) + +#define clrbits_le32(addr, clear) clrbits(le32, addr, clear) +#define setbits_le32(addr, set) setbits(le32, addr, set) +#define clrsetbits_le32(addr, clear, set) clrsetbits(le32, addr, clear, set) + +#define clrbits_be16(addr, clear) clrbits(be16, addr, clear) +#define setbits_be16(addr, set) setbits(be16, addr, set) +#define clrsetbits_be16(addr, clear, set) clrsetbits(be16, addr, clear, set) + +#define clrbits_le16(addr, clear) clrbits(le16, addr, clear) +#define setbits_le16(addr, set) setbits(le16, addr, set) +#define clrsetbits_le16(addr, clear, set) clrsetbits(le16, addr, clear, set) + +#define clrbits_8(addr, clear) clrbits(8, addr, clear) +#define setbits_8(addr, set) setbits(8, addr, set) +#define clrsetbits_8(addr, clear, set) clrsetbits(8, addr, clear, set) + /* * ISA space is 'always mapped' on a typical x86 system, no need to * explicitly ioremap() it. The fact that the ISA IO space is mapped -- cgit v0.10.2 From eddbad224b9e0e6834f946f587923f27e54abb69 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:18 -0700 Subject: x86: Add msr read/write functions that use a structure It is convenient to be able to adjust MSRs with a structure that splits the two 32-bit halves into separate fields, as they are often dealt with separately. Add a few functions to support this. Signed-off-by: Simon Glass diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h index 3b5915d..df43983 100644 --- a/arch/x86/include/asm/msr.h +++ b/arch/x86/include/asm/msr.h @@ -175,6 +175,25 @@ static inline int wrmsr_safe_regs(u32 regs[8]) return native_wrmsr_safe_regs(regs); } +typedef struct msr_t { + uint32_t lo; + uint32_t hi; +} msr_t; + +static inline struct msr_t msr_read(unsigned msr_num) +{ + struct msr_t msr; + + rdmsr(msr_num, msr.lo, msr.hi); + + return msr; +} + +static inline void msr_write(unsigned msr_num, msr_t msr) +{ + wrmsr(msr_num, msr.lo, msr.hi); +} + #define rdtscl(low) \ ((low) = (u32)__native_read_tsc()) -- cgit v0.10.2 From f5fbbe95798dba8f1536892598afbf33b5c07b5f Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:19 -0700 Subject: x86: ivybridge: Perform initial CPU setup Set up the flex ratio (controls speed versus heat output) and a few other very early things. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 5d7640b..ab708dd 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -14,13 +14,123 @@ #include #include #include +#include +#include +#include #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; +static void enable_port80_on_lpc(struct pci_controller *hose, pci_dev_t dev) +{ + /* Enable port 80 POST on LPC */ + pci_hose_write_config_dword(hose, dev, PCH_RCBA_BASE, DEFAULT_RCBA | 1); + clrbits_le32(RCB_REG(GCS), 4); +} + +/* + * Enable Prefetching and Caching. + */ +static void enable_spi_prefetch(struct pci_controller *hose, pci_dev_t dev) +{ + u8 reg8; + + pci_hose_read_config_byte(hose, dev, 0xdc, ®8); + reg8 &= ~(3 << 2); + reg8 |= (2 << 2); /* Prefetching and Caching Enabled */ + 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; + u8 nominal_ratio; + + /* Minimum CPU revision for configurable TDP support */ + if (cpuid_eax(1) < IVB_CONFIG_TDP_MIN_CPUID) + return -EINVAL; + + /* Check for Flex Ratio support */ + flex_ratio = msr_read(MSR_FLEX_RATIO); + if (!(flex_ratio.lo & FLEX_RATIO_EN)) + return -EINVAL; + + /* Check for >0 configurable TDPs */ + msr = msr_read(MSR_PLATFORM_INFO); + if (((msr.hi >> 1) & 3) == 0) + return -EINVAL; + + /* Use nominal TDP ratio for flex ratio */ + msr = msr_read(MSR_CONFIG_TDP_NOMINAL); + nominal_ratio = msr.lo & 0xff; + + /* See if flex ratio is already set to nominal TDP ratio */ + if (((flex_ratio.lo >> 8) & 0xff) == nominal_ratio) + return 0; + + /* Set flex ratio to nominal TDP ratio */ + flex_ratio.lo &= ~0xff00; + flex_ratio.lo |= nominal_ratio << 8; + flex_ratio.lo |= FLEX_RATIO_LOCK; + msr_write(MSR_FLEX_RATIO, flex_ratio); + + /* Set flex ratio in soft reset data register bits 11:6 */ + clrsetbits_le32(RCB_REG(SOFT_RESET_DATA), 0x3f << 6, + (nominal_ratio & 0x3f) << 6); + + /* Set soft reset control to use register value */ + setbits_le32(RCB_REG(SOFT_RESET_CTRL), 1); + + /* Issue warm reset, will be "CPU only" due to soft reset data */ + outb(0x0, PORT_RESET); + outb(0x6, PORT_RESET); + cpu_hlt(); + + /* Not reached */ + return -EINVAL; +} + +static void set_spi_speed(void) +{ + u32 fdod; + + /* Observe SPI Descriptor Component Section 0 */ + writel(0x1000, RCB_REG(SPI_DESC_COMP0)); + + /* Extract the1 Write/Erase SPI Frequency from descriptor */ + fdod = readl(RCB_REG(SPI_FREQ_WR_ERA)); + fdod >>= 24; + fdod &= 7; + + /* Set Software Sequence frequency to match */ + clrsetbits_8(RCB_REG(SPI_FREQ_SWSEQ), 7, fdod); +} + int arch_cpu_init(void) { const void *blob = gd->fdt_blob; @@ -46,6 +156,26 @@ int arch_cpu_init(void) if (ret) return ret; + enable_spi_prefetch(hose, PCH_LPC_DEV); + + /* 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(); + + /* + * We should do as little as possible before the serial console is + * up. Perhaps this should move to later. Our next lot of init + * happens in print_cpuinfo() when we have a console + */ + ret = set_flex_ratio_to_tdp_nominal(); + if (ret) + return ret; + return 0; } diff --git a/arch/x86/include/asm/arch-ivybridge/model_206ax.h b/arch/x86/include/asm/arch-ivybridge/model_206ax.h new file mode 100644 index 0000000..8281d7a --- /dev/null +++ b/arch/x86/include/asm/arch-ivybridge/model_206ax.h @@ -0,0 +1,82 @@ +/* + * From Coreboot file of the same name + * + * Copyright (C) 2011 The ChromiumOS Authors. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ASM_ARCH_MODEL_206AX_H +#define _ASM_ARCH_MODEL_206AX_H + +/* SandyBridge/IvyBridge bus clock is fixed at 100MHz */ +#define SANDYBRIDGE_BCLK 100 + +#define CPUID_VMX (1 << 5) +#define CPUID_SMX (1 << 6) +#define MSR_FEATURE_CONFIG 0x13c +#define MSR_FLEX_RATIO 0x194 +#define FLEX_RATIO_LOCK (1 << 20) +#define FLEX_RATIO_EN (1 << 16) +#define IA32_PLATFORM_DCA_CAP 0x1f8 +#define IA32_MISC_ENABLE 0x1a0 +#define MSR_TEMPERATURE_TARGET 0x1a2 +#define IA32_PERF_CTL 0x199 +#define IA32_THERM_INTERRUPT 0x19b +#define IA32_ENERGY_PERFORMANCE_BIAS 0x1b0 +#define ENERGY_POLICY_PERFORMANCE 0 +#define ENERGY_POLICY_NORMAL 6 +#define ENERGY_POLICY_POWERSAVE 15 +#define IA32_PACKAGE_THERM_INTERRUPT 0x1b2 +#define MSR_LT_LOCK_MEMORY 0x2e7 +#define IA32_MC0_STATUS 0x401 + +#define MSR_PIC_MSG_CONTROL 0x2e +#define PLATFORM_INFO_SET_TDP (1 << 29) + +#define MSR_MISC_PWR_MGMT 0x1aa +#define MISC_PWR_MGMT_EIST_HW_DIS (1 << 0) +#define MSR_TURBO_RATIO_LIMIT 0x1ad +#define MSR_POWER_CTL 0x1fc + +#define MSR_PKGC3_IRTL 0x60a +#define MSR_PKGC6_IRTL 0x60b +#define MSR_PKGC7_IRTL 0x60c +#define IRTL_VALID (1 << 15) +#define IRTL_1_NS (0 << 10) +#define IRTL_32_NS (1 << 10) +#define IRTL_1024_NS (2 << 10) +#define IRTL_32768_NS (3 << 10) +#define IRTL_1048576_NS (4 << 10) +#define IRTL_33554432_NS (5 << 10) +#define IRTL_RESPONSE_MASK (0x3ff) + +/* long duration in low dword, short duration in high dword */ +#define PKG_POWER_LIMIT_MASK 0x7fff +#define PKG_POWER_LIMIT_EN (1 << 15) +#define PKG_POWER_LIMIT_CLAMP (1 << 16) +#define PKG_POWER_LIMIT_TIME_SHIFT 17 +#define PKG_POWER_LIMIT_TIME_MASK 0x7f + +#define MSR_PP0_CURRENT_CONFIG 0x601 +#define PP0_CURRENT_LIMIT (112 << 3) /* 112 A */ +#define MSR_PP1_CURRENT_CONFIG 0x602 +#define PP1_CURRENT_LIMIT_SNB (35 << 3) /* 35 A */ +#define PP1_CURRENT_LIMIT_IVB (50 << 3) /* 50 A */ +#define MSR_PKG_POWER_SKU_UNIT 0x606 +#define MSR_PKG_POWER_SKU 0x614 + +#define IVB_CONFIG_TDP_MIN_CPUID 0x306a2 +#define MSR_CONFIG_TDP_NOMINAL 0x648 +#define MSR_CONFIG_TDP_LEVEL1 0x649 +#define MSR_CONFIG_TDP_LEVEL2 0x64a +#define MSR_CONFIG_TDP_CONTROL 0x64b +#define MSR_TURBO_ACTIVATION_RATIO 0x64c + +/* P-state configuration */ +#define PSS_MAX_ENTRIES 8 +#define PSS_RATIO_STEP 2 +#define PSS_LATENCY_TRANSITION 10 +#define PSS_LATENCY_BUSMASTER 10 + +#endif diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h index 26ddeab..c572f76 100644 --- a/arch/x86/include/asm/arch-ivybridge/pch.h +++ b/arch/x86/include/asm/arch-ivybridge/pch.h @@ -35,6 +35,66 @@ #define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */ #define LPC_GENX_DEC(x) (0x84 + 4 * (x)) +#define DEFAULT_RCBA 0xfed1c000 + +/* Root Complex Register Block */ +#define RCB_REG(reg) (DEFAULT_RCBA + (reg)) + +#define PCH_RCBA_BASE 0xf0 + +#define VCH 0x0000 /* 32bit */ +#define VCAP1 0x0004 /* 32bit */ +#define VCAP2 0x0008 /* 32bit */ +#define PVC 0x000c /* 16bit */ +#define PVS 0x000e /* 16bit */ + +#define V0CAP 0x0010 /* 32bit */ +#define V0CTL 0x0014 /* 32bit */ +#define V0STS 0x001a /* 16bit */ + +#define V1CAP 0x001c /* 32bit */ +#define V1CTL 0x0020 /* 32bit */ +#define V1STS 0x0026 /* 16bit */ + +#define RCTCL 0x0100 /* 32bit */ +#define ESD 0x0104 /* 32bit */ +#define ULD 0x0110 /* 32bit */ +#define ULBA 0x0118 /* 64bit */ + +#define RP1D 0x0120 /* 32bit */ +#define RP1BA 0x0128 /* 64bit */ +#define RP2D 0x0130 /* 32bit */ +#define RP2BA 0x0138 /* 64bit */ +#define RP3D 0x0140 /* 32bit */ +#define RP3BA 0x0148 /* 64bit */ +#define RP4D 0x0150 /* 32bit */ +#define RP4BA 0x0158 /* 64bit */ +#define HDD 0x0160 /* 32bit */ +#define HDBA 0x0168 /* 64bit */ +#define RP5D 0x0170 /* 32bit */ +#define RP5BA 0x0178 /* 64bit */ +#define RP6D 0x0180 /* 32bit */ +#define RP6BA 0x0188 /* 64bit */ + +#define RPC 0x0400 /* 32bit */ +#define RPFN 0x0404 /* 32bit */ + +#define SPI_FREQ_SWSEQ 0x3893 +#define SPI_DESC_COMP0 0x38b0 +#define SPI_FREQ_WR_ERA 0x38b4 +#define SOFT_RESET_CTRL 0x38f4 +#define SOFT_RESET_DATA 0x38f8 + +#define RC 0x3400 /* 32bit */ +#define HPTC 0x3404 /* 32bit */ +#define GCS 0x3410 /* 32bit */ +#define BUC 0x3414 /* 32bit */ +#define PCH_DISABLE_GBE (1 << 5) +#define FD 0x3418 /* 32bit */ +#define DISPBDF 0x3424 /* 16bit */ +#define FD2 0x3428 /* 32bit */ +#define CG 0x341c /* 32bit */ + /** * lpc_early_init() - set up LPC serial ports and other early things * diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index b2854a9..b9317cb 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -32,6 +32,8 @@ enum { #ifndef __ASSEMBLY__ +#define PORT_RESET 0xcf9 + static inline __attribute__((always_inline)) void cpu_hlt(void) { asm("hlt"); -- cgit v0.10.2 From 94060ff278e3ed4d91e4605701231d194a5013a3 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:20 -0700 Subject: x86: ivybridge: Check BIST value on boot The built-in self test value should be checked before we continue booting. Refuse to continue if there is something wrong. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index ab708dd..6a242d7 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -179,10 +179,26 @@ int arch_cpu_init(void) return 0; } +static int report_bist_failure(void) +{ + if (gd->arch.bist != 0) { + printf("BIST failed: %08x\n", gd->arch.bist); + return -EFAULT; + } + + return 0; +} + int print_cpuinfo(void) { char processor_name[CPU_MAX_NAME_LEN]; const char *name; + int ret; + + /* Halt if there was a built in self test failure */ + ret = report_bist_failure(); + if (ret) + return ret; /* Print processor name */ name = cpu_get_name(processor_name); -- cgit v0.10.2 From 77f9b1fb6244878ab4aab342a814880d17253b75 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:21 -0700 Subject: x86: ivybridge: Perform Intel microcode update on boot Microcode updates are stored in the device tree. Work through these and apply any that are needed. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 4b77c9c..74f01e8 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -7,5 +7,6 @@ obj-y += car.o obj-y += cpu.o obj-y += lpc.o +obj-y += microcode_intel.o obj-y += pci.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 6a242d7..0aca2f0 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include DECLARE_GLOBAL_DATA_PTR; @@ -200,6 +201,10 @@ int print_cpuinfo(void) if (ret) return ret; + ret = microcode_update_intel(); + if (ret && ret != -ENOENT && ret != -EEXIST) + return ret; + /* Print processor name */ name = cpu_get_name(processor_name); printf("CPU: %s\n", name); diff --git a/arch/x86/cpu/ivybridge/microcode_intel.c b/arch/x86/cpu/ivybridge/microcode_intel.c new file mode 100644 index 0000000..8c11a63 --- /dev/null +++ b/arch/x86/cpu/ivybridge/microcode_intel.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2014 Google, Inc + * Copyright (C) 2000 Ronald G. Minnich + * + * Microcode update for Intel PIII and later CPUs + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +/** + * struct microcode_update - standard microcode header from Intel + * + * We read this information out of the device tree and use it to determine + * whether the update is applicable or not. We also use the same structure + * to read information from the CPU. + */ +struct microcode_update { + uint header_version; + uint update_revision; + uint date_code; + uint processor_signature; + uint checksum; + uint loader_revision; + uint processor_flags; + const void *data; + int size; +}; + +static int microcode_decode_node(const void *blob, int node, + struct microcode_update *update) +{ + update->data = fdt_getprop(blob, node, "data", &update->size); + if (!update->data) + return -EINVAL; + + update->header_version = fdtdec_get_int(blob, node, + "intel,header-version", 0); + update->update_revision = fdtdec_get_int(blob, node, + "intel,update-revision", 0); + update->date_code = fdtdec_get_int(blob, node, + "intel,date-code", 0); + update->processor_signature = fdtdec_get_int(blob, node, + "intel.processor-signature", 0); + update->checksum = fdtdec_get_int(blob, node, "intel,checksum", 0); + update->loader_revision = fdtdec_get_int(blob, node, + "loader-revision", 0); + update->processor_flags = fdtdec_get_int(blob, node, + "processor-flags", 0); + + return 0; +} + +static uint32_t microcode_read_rev(void) +{ + /* + * Some Intel CPUs can be very finicky about the CPUID sequence used. + * So this is implemented in assembly so that it works reliably. + */ + uint32_t low, high; + + asm volatile ( + "xorl %%eax, %%eax\n" + "xorl %%edx, %%edx\n" + "movl $0x8b, %%ecx\n" + "wrmsr\n" + "movl $0x01, %%eax\n" + "cpuid\n" + "movl $0x8b, %%ecx\n" + "rdmsr\n" + : /* outputs */ + "=a" (low), "=d" (high) + : /* inputs */ + : /* clobbers */ + "ebx", "ecx" + ); + + return high; +} + +static void microcode_read_cpu(struct microcode_update *cpu) +{ + /* CPUID sets MSR 0x8B iff a microcode update has been loaded. */ + unsigned int x86_model, x86_family; + struct cpuid_result result; + uint32_t low, high; + + wrmsr(0x8b, 0, 0); + result = cpuid(1); + rdmsr(0x8b, low, cpu->update_revision); + x86_model = (result.eax >> 4) & 0x0f; + x86_family = (result.eax >> 8) & 0x0f; + cpu->processor_signature = result.eax; + + cpu->processor_flags = 0; + if ((x86_model >= 5) || (x86_family > 6)) { + rdmsr(0x17, low, high); + cpu->processor_flags = 1 << ((high >> 18) & 7); + } + debug("microcode: sig=%#x pf=%#x revision=%#x\n", + cpu->processor_signature, cpu->processor_flags, + cpu->update_revision); +} + +/* Get a microcode update from the device tree and apply it */ +int microcode_update_intel(void) +{ + struct microcode_update cpu, update; + const void *blob = gd->fdt_blob; + int count; + int node; + int ret; + + microcode_read_cpu(&cpu); + node = 0; + count = 0; + do { + node = fdtdec_next_compatible(blob, node, + COMPAT_INTEL_MICROCODE); + if (node < 0) { + debug("%s: Found %d updates\n", __func__, count); + return count ? 0 : -ENOENT; + } + + ret = microcode_decode_node(blob, node, &update); + if (ret) { + debug("%s: Unable to decode update: %d\n", __func__, + ret); + return ret; + } + if (update.processor_signature == cpu.processor_signature && + (update.processor_flags & cpu.processor_flags)) { + debug("%s: Update already exists\n", __func__); + return -EEXIST; + } + + wrmsr(0x79, (ulong)update.data, 0); + debug("microcode: updated to revision 0x%x date=%04x-%02x-%02x\n", + microcode_read_rev(), update.date_code & 0xffff, + (update.date_code >> 24) & 0xff, + (update.date_code >> 16) & 0xff); + count++; + } while (1); +} diff --git a/arch/x86/include/asm/arch-ivybridge/microcode.h b/arch/x86/include/asm/arch-ivybridge/microcode.h new file mode 100644 index 0000000..bc9b87c --- /dev/null +++ b/arch/x86/include/asm/arch-ivybridge/microcode.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __ASM_ARCH_MICROCODE_H +#define __ASM_ARCH_MICROCODE_H + +/** + * microcode_update_intel() - Apply microcode updates + * + * Applies any microcode updates in the device tree. + * + * @return 0 if OK, -EEXIST if the updates were already applied, -ENOENT if + * not updates were found, -EINVAL if an update was invalid + */ +int microcode_update_intel(void); + +#endif diff --git a/include/fdtdec.h b/include/fdtdec.h index 6b40006..3bd60b7 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -118,6 +118,7 @@ enum fdt_compat_id { COMPAT_SAMSUNG_EXYNOS_SYSMMU, /* Exynos sysmmu */ COMPAT_PARADE_PS8625, /* Parade PS8622 EDP->LVDS bridge */ COMPAT_INTEL_LPC, /* Intel Low Pin Count I/F */ + COMPAT_INTEL_MICROCODE, /* Intel microcode update */ COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 4aa227a..9a68f9c 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -73,6 +73,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(SAMSUNG_EXYNOS_SYSMMU, "samsung,sysmmu-v3.3"), COMPAT(PARADE_PS8625, "parade,ps8625"), COMPAT(COMPAT_INTEL_LPC, "intel,lpc"), + COMPAT(INTEL_MICROCODE, "intel,microcode"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) -- cgit v0.10.2 From 9c678e152a9a5f2ca786af15e6816ddeaa520c8b Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:22 -0700 Subject: x86: dts: Add microcode updates for ivybridge CPU Add two microcode updates that are provided for this CPU. The updates have been converted to a device tree form. Note: SPDX submission has been done. If this license is approved I will convert the files to use SPDX. Signed-off-by: Simon Glass diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index 63933aa..f1b7bf0 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -67,4 +67,14 @@ }; }; }; + + microcode { + update@0 { +#include "m12206a7_00000028.dtsi" + }; + update@1 { +#include "m12306a9_00000017.dtsi" + }; + }; + }; diff --git a/arch/x86/dts/m12206a7_00000028.dtsi b/arch/x86/dts/m12206a7_00000028.dtsi new file mode 100644 index 0000000..bcd5248 --- /dev/null +++ b/arch/x86/dts/m12206a7_00000028.dtsi @@ -0,0 +1,622 @@ +/* + * Copyright (c) <1995-2013>, Intel Corporation. + * All rights reserved. + * + * Redistribution. Redistribution and use in binary form, without modification, are + * permitted provided that the following conditions are met: + * .Redistributions must reproduce the above copyright notice and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * Neither the name of Intel Corporation nor the names of its suppliers may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * .No reverse engineering, decompilation, or disassembly of this software is + * permitted. + * ."Binary form" includes any format commonly used for electronic conveyance + * which is a reversible, bit-exact translation of binary representation to ASCII or + * ISO text, for example, "uuencode." + * + * DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT + * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *--- + * This is a device tree fragment. Use #include to add these properties to a + * node. + */ + +compatible = "intel,microcode"; +intel,header-version = <1>; +intel,update-revision = <0x28>; +intel,date-code = <0x04242012>; +intel,processor-signature = <0x000206a7>; +intel,checksum = <0xf3e9935d>; +intel,loader-revision = <1>; +intel,processor-flags = <0x12>; + +/* The 48-byte public header is omitted. */ +data = < + 0x00000000 0x000000a1 0x00020001 0x00000028 + 0x00000000 0x00000000 0x20120423 0x000008f1 + 0x00000001 0x000206a7 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x000008f1 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 + 0x52b813ac 0xdb8994c7 0x70e9f6bb 0x9d6db2ff + 0xf4d70f5d 0x5b1eccf6 0xac59106f 0x0ae2e2c1 + 0x1a7bbeb1 0x355a1d62 0x2e7eb594 0x09f8dea9 + 0x432a49e4 0xbf520253 0xdafa4010 0x893a858a + 0x766e0efb 0xd91e196d 0x838bd2ef 0xe5146494 + 0xd515f413 0x29704828 0xe85598b6 0xdcbe6c51 + 0x88eabbfa 0xa1e8909f 0xd8931721 0x35386554 + 0x089a78a7 0xd9914775 0xd4644748 0x1556a4dc + 0xf44448f6 0xd054d7db 0xf30f2b7d 0x5ae223d0 + 0xcbbb48b0 0x5c8b0383 0x177de157 0x9c1e5f73 + 0x2ec28289 0xd72a7b6c 0x823b6eb2 0x35e02171 + 0xba8deae4 0x06f4d468 0x13dbafaa 0x72b419f1 + 0x033385b5 0x05806920 0x4c6034cf 0x9bd117dc + 0x976e2d04 0x250330f0 0x7250b5e1 0x184980c2 + 0x12a9d7d6 0x1bc808f9 0xae79994f 0xc6f87901 + 0xc0e3132f 0x671491c5 0x236cad39 0x37889d9c + 0x67f7c3f3 0x964a6be5 0xbcced7da 0x57eeaa6e + 0x7bca1522 0x654fee4c 0x2a1ca5d9 0xa1803cf3 + 0x00000011 0x8c316d2c 0x17603b7e 0x32e42981 + 0xc26c1400 0xf0fbccb6 0xeab6b43a 0x11d456a5 + 0x5b912d46 0x15195fe0 0x542f6db3 0x0b7f212e + 0x47718dd9 0x7c41b108 0x06c21111 0x4445d5ea + 0xb4fb8128 0xe07404a6 0x8d503da4 0x78fc7e44 + 0xb9919656 0x9968c797 0x87f26ab0 0x23bb1af7 + 0x1ec5d761 0x26f30d2c 0x7cdb747c 0xe4d42033 + 0x8a5d4801 0x768aff57 0xbcfd5d11 0x7c853c2d + 0x231e6207 0x8b1988a6 0xd68fdb75 0x58dcb417 + 0x44422ef9 0x2a186ebb 0x7d27e85f 0x36ac31f7 + 0x1e487e77 0x2b0b8c37 0xd8ba682f 0x2cba791b + 0xe6d3dece 0x1b2c2a99 0x4e5decab 0xfbd313a3 + 0xdbc78294 0x5a80cce7 0x2d8e0f0b 0xcf564f71 + 0x073d1f37 0x25162870 0x96cdb85b 0x9c553048 + 0x24eba740 0xfc0f352e 0x0c83be68 0x89b5076c + 0xc39c4355 0x6a4cf25c 0x2bbd2682 0xc524fdb9 + 0x7ea19bae 0x191ad6f1 0xd3fbf3bf 0x21bf77fa + 0x8f77fec4 0x0f90f635 0xe55e165c 0x868d58c0 + 0x966bc0ad 0x6c276364 0x9d8f7eff 0x4b7925d4 + 0x8b2f9326 0x4ab7b47e 0x33a9087c 0xf31ab949 + 0x69831dfb 0x4711a215 0x8128c1fa 0x8481c213 + 0x7401b01b 0xfdcfdc50 0xd6b55266 0xae9b23ac + 0xfa2ad275 0xa225bb45 0x4dd720c4 0x760a20e6 + 0x5f1223c9 0x2f334372 0x6e1dcdab 0xe8ee8638 + 0x1c19ba8a 0xef9341c4 0x360aaa9d 0x90452ea9 + 0x65852446 0xe9398fa3 0xbba6a631 0x1a3e90b9 + 0xe2a73a56 0x6e8c0747 0x35c7c53d 0xcc1ac842 + 0x183356af 0xb6e98608 0x987b43c2 0xa8a3cfd2 + 0xc2c5fce0 0xcc3af64a 0xd6d3a291 0xe59ad1f5 + 0x124ca513 0x9522b50a 0x25150477 0xa2eb5797 + 0x7fc63626 0x648c48e3 0x9f5797ff 0x2307b84d + 0x980625a4 0xabc05983 0x24980807 0x773c4f99 + 0x3407b872 0x07c3657a 0xa2cd9e48 0x49c1e6a8 + 0xa881b84c 0xf804d72c 0xb5319d2a 0x3e39780f + 0x97518822 0x0acd54c2 0x0721a9ff 0x10e1d2fd + 0xa7b6db77 0x845b1a56 0xef00160e 0x6b41bfd5 + 0xc994df0d 0xcf44a5ca 0x794b36a4 0xf9fdb127 + 0x922a1366 0x822aa8a9 0x4b137bd5 0x5722a49f + 0x8933719a 0x17edc1a9 0x079d9538 0x21fae7d5 + 0xe534fd73 0x9d3038d5 0x48c3a056 0x5b22d58a + 0x6f142866 0xf1d767cd 0xb51ad5a6 0x34a0ef85 + 0x0111703e 0xca4b3a30 0xa0f3c34d 0x9d48775a + 0x3f2059f9 0xf2fe2c36 0x588861a9 0xed5bd9fe + 0x8231f7cb 0x8c115969 0x3f82ba00 0x21b3730c + 0xba757997 0x3ec0bb2c 0x16f11def 0x5d4356c6 + 0xdc2e0bc2 0x58c1eb6e 0x313ede0c 0xb68fcc52 + 0x84d3e1b5 0xcc6d9201 0x95046196 0x276b527b + 0x80a4a729 0xe782916d 0x5cf09e0b 0x98aaf9fa + 0x1de6dd43 0xab4f1962 0x49ece734 0x81455488 + 0xc2597b61 0x5b22af85 0x646f7b94 0x09213a1f + 0x08edf7e4 0x963d343c 0x059ba888 0xb4e804ed + 0xe7cc826c 0xf87bafc7 0xeecaec10 0x8e60919c + 0xbf14c996 0xd3dcaee3 0xb8fa0b7e 0x81563c6e + 0x7f59a258 0x2f344446 0x374d8aa6 0x9b6de5c9 + 0xbf992857 0xbc5b94fc 0x28adb080 0x17e41044 + 0xb87b469e 0xda504d12 0xf21bef8b 0xce75c1e3 + 0xdbd92c83 0x58bba0af 0x77b42977 0x506cfd75 + 0x1139e875 0x6ce5fe43 0xc6a5d7b3 0x87f9e628 + 0x7b5c500b 0x130066b3 0x789b611f 0xec8c1ba9 + 0xb7e6872d 0xaf828cd6 0xc28d3316 0x2a91f6d0 + 0xc725f063 0x065ac531 0x4f9ef4b8 0x2b9d927e + 0xaf54f3f9 0x7c924f72 0xda1d77ad 0xff00db67 + 0xaf4f03c0 0xb4f4ee64 0x169e64e5 0x04653ac0 + 0xed51cb70 0xfeaff0e5 0x51dbf346 0x072a2407 + 0x23fb74f4 0x9a906eef 0x5d6fc3f0 0xbc3c374c + 0x1cf9f063 0x919015d9 0x5b3e9d07 0xd6209d8b + 0xa3710b3d 0x90ad23b8 0x420ceedc 0x58e8371f + 0x5d419d1f 0xb8acd13f 0x7d100d6d 0x210c10d1 + 0xcd0a697e 0x5023db4b 0x33e6d8e7 0x44bbe6b4 + 0x827e859f 0x6ca4cc81 0x661bb2c3 0x71209ee8 + 0xb8c3ffaf 0xd1075f51 0xba1eae10 0x728b0a6a + 0xe4af7a2f 0xca9bcf2e 0xb249a631 0xdce6be47 + 0x5c910321 0x425c3c27 0x33083e43 0xdea067ae + 0xea594a23 0x41b75c2c 0x3a401a95 0xd33cd88a + 0xc295cad0 0x67f48045 0x1dc9ad4c 0x4bc48864 + 0x53991b6e 0x7aadde5f 0x2b0bf775 0x06ba5380 + 0x9eb874be 0x2c4b967a 0x1bcc342f 0xe875001b + 0x15b5642d 0x5be99c9d 0xcb210ace 0x1b4924ad + 0x3793ed81 0x8b983114 0x3ec33981 0x75ec71e7 + 0x8b5b7df3 0x834756f4 0x100fad01 0x70037fdf + 0x0cef9a36 0x3d9e3a2d 0x38b48efd 0xfc4034b6 + 0xa32e29dd 0x388944bc 0xc1c15614 0x3877e9c7 + 0xa5e733fa 0xa621bd53 0x4b651df6 0xce082970 + 0x85f30d6f 0x729a5c87 0x31dd7ba9 0xdb495828 + 0x7b12c698 0x953495c9 0x6b5f99e7 0x2cc42fa8 + 0x697ac512 0x1be679de 0xc116d305 0x94a36606 + 0x9e5e141e 0x874affed 0x58d40b0b 0x5e3cf5e5 + 0x5d05e9a9 0x06840efc 0xd2f98b21 0xa1e83ab2 + 0x4f726202 0xa6394535 0x62a02403 0x9f2167ec + 0x4f9fc77b 0x98073be4 0x2bc781fa 0xfc8e4c89 + 0xc7179b97 0x692cf793 0x708ff7bb 0x12ecba93 + 0xacd06e21 0x202bef76 0x03852241 0xe84e02a1 + 0xf1f9ac8d 0xcee61aef 0x61a4f235 0xd22991eb + 0x67a81345 0x375a15c6 0xe8fae8a3 0xb4ff2b37 + 0x339ee4ea 0x14ffadc3 0xf49340dd 0xf285e568 + 0x00fc6970 0x369c52d1 0x4f55368f 0x3f4d75f1 + 0x6a73b603 0x963c1f59 0x171e2bdc 0x72bac76b + 0x9e2e5c32 0x307f7c3f 0xd3b48637 0x3a917acf + 0xea52a65f 0xecd209fb 0xf0ad84bf 0xd4bdea70 + 0xa2647b38 0xce040b49 0xc6d5f13d 0x5d942c52 + 0xf8edc042 0x798fdefd 0x4b074246 0x1cb1873a + 0x6793c186 0x23b9c774 0x77bb0202 0xc519b3aa + 0xa30c09a2 0xe1f6669a 0xb7eddb8d 0x7aaa91d6 + 0x076a3789 0x0ac47791 0x1e503404 0x44fe8c54 + 0xf3cbbf49 0xd3234eef 0x0d898b3f 0xe854984b + 0xe3986de9 0x923a5c76 0x2ee9abca 0x1a9fedbe + 0xdf76dcd1 0xea07936b 0xcdaaf247 0xe62d98fa + 0xa99c7f7b 0x34fc84d4 0x03a35111 0xad5675c8 + 0xcc64075b 0x408203f9 0x846e1f08 0xe934019e + 0x423d1223 0x2f04f9e3 0xee1dbf40 0x65edc60f + 0x097aa22f 0x7058a2b7 0x41c8a0a5 0xa68aa391 + 0x0f345c40 0x667517e6 0x860838ba 0x6dae933b + 0x764d5919 0x6673fa0f 0xf0a5e97d 0x4262ebbe + 0x64b413f2 0xd2c4145a 0x0b2c11f3 0xfdfe9f93 + 0x96c77107 0x1399fdda 0xf599f215 0xb504da5d + 0xf8a95268 0x9ed1ef87 0x9ae33cfb 0x3b21f1ef + 0xc6d447c2 0xe0694d4e 0x967febab 0xc13f631d + 0x8393bfba 0x37438788 0x1724194d 0x8e77a045 + 0x20e2483c 0xb961c2fc 0x485cf593 0xb3462621 + 0xcb2959b8 0x10307e19 0xf71fbbfd 0xdda641e1 + 0x0daf5f66 0x56d85178 0x145f6749 0xebc46ed1 + 0x5593c249 0x94561f51 0x534cc654 0xca7c8814 + 0xb59a578c 0x40b2b614 0xeaf3437a 0x198d5b4e + 0xf245fa53 0xfb75e0b0 0xa363c46d 0xc43b5468 + 0xdf036413 0xc59f5a36 0xd8ff4381 0xa3af3e36 + 0x7af63462 0x414526d7 0x7bdc41c5 0xa416f1e7 + 0x6987d9ad 0x472c5499 0x4f10ee37 0x47bb7ff7 + 0xc7f2e621 0x820008f7 0x33a475db 0x91ff5d72 + 0x0517401c 0x73d067c8 0xe417b69d 0xb86d9903 + 0x1ac9a032 0x74bbf582 0x8b65596e 0x883be34c + 0x95dcc26f 0xe232c646 0xfae9c19f 0x35cb5273 + 0x6a94d095 0xfff6ca91 0xb9c40eb5 0xd351dcac + 0xc90d464f 0x9b609642 0x15663b56 0x15f7f88d + 0x22499f60 0x417fd6c5 0x2dc36fe2 0x712bf66a + 0x22f1fba8 0x531b8092 0x40d269b6 0x1d227898 + 0xeb6ff35b 0x2490ac31 0xc958ed65 0x3ce6ffb7 + 0x9338a806 0x3beadfe2 0x1c361ac9 0x53d0e3b0 + 0x91d46102 0x4d57045f 0xb5c8afb3 0xfd2c9e7d + 0x3d578410 0x2adb9406 0x10df7459 0x90abccfb + 0xe3f217ed 0xef5f4e09 0x74925ce4 0x169b5879 + 0xfeff4ad5 0xb300dd1d 0xc96022ba 0x72da501b + 0x1e694296 0x9efa33cb 0x0dc3ee6c 0x0ac4e7ea + 0x73041130 0xf0e6a295 0xc46bdb6a 0x6a927044 + 0xd217ceca 0x0b744007 0xd5a2bafb 0x4220cd92 + 0x70d3352a 0x5ee4f661 0xfa07e5c0 0x155542d9 + 0x4a39fba0 0xcec0552d 0x30c1d8ef 0xbef9d21e + 0x183879aa 0x5b3f30a8 0x54a06db4 0xef876e4e + 0x5e823680 0x53e2a353 0xc9aa4112 0x13a56ee5 + 0x848859fd 0x0ba2b801 0xec15260f 0x7bb22672 + 0x1a097332 0xb141339f 0x752a67d9 0xdae373f3 + 0x3c8cfd49 0x2dfaf2a9 0x95820c6c 0x956b39a2 + 0x1ca0d24e 0x1312b978 0x7280e1bd 0xa7a7c2ff + 0x0b48e987 0xb6083e55 0x4b4b82f4 0x9c6104ad + 0xcb93beca 0xe1c34035 0x34de740d 0xbb151baa + 0x71f5942f 0x1eaac228 0x0c68331b 0x3d2a1dd0 + 0xe7a3d41a 0x7253acae 0xfd4de230 0x79988d80 + 0x4468f19b 0xac4440fd 0x6e8a6ef3 0x5736adf8 + 0xded67716 0x1f1d5a4b 0x96c5f451 0x85bae181 + 0x1293ab28 0xc2ba53c2 0x729ff4cf 0x60218df8 + 0xc2870138 0x6127d844 0x89604e9e 0xd2b9ad4e + 0x4f6ded9f 0xdd263849 0x1633bd92 0x64b03a24 + 0x96dabd4d 0x6e85d235 0x1ab69ad0 0x9aa80454 + 0x6b9041e0 0x106c7e9a 0x8f54812f 0xa274efe4 + 0xe45d6695 0xf3aa7bd3 0x6a5a2a63 0xe36f3525 + 0x6238fa4b 0x7d6cb06f 0x16d3b4a2 0xf3b04822 + 0x638f1a60 0x0e1875fa 0x1c0292b9 0x6b519ea4 + 0x9faba37b 0x209341ec 0x83c9061f 0x3387dfe8 + 0xc7f12ceb 0x2bef45d7 0x8f8acb47 0x35d9741b + 0x7009f514 0xfd003802 0x6f9489c5 0xe2ea2504 + 0x910e996a 0xcc81d016 0x3280730d 0xdedfef59 + 0x5a7357cc 0x8fe8dd39 0x15543fe5 0x976c4207 + 0xe41cf62b 0x0ba6b4b5 0x5c3b7ced 0xa6c5b72b + 0x72ad3b4d 0xff143181 0x2b78a157 0x7fe231a5 + 0x6ff0538a 0xe58ed1ac 0x81a311a5 0xefaa54b8 + 0xf04a797e 0xce6e69c7 0xdc810726 0x7bab7be3 + 0xdd5923e8 0x5a2413ed 0x31cef794 0x73dfd806 + 0x1b9223c1 0x0c370882 0x04fa3b68 0x87c50bc1 + 0x1d78c90f 0xf4e2cee6 0xebea941b 0x73e5838f + 0xca8d39a6 0xe004296b 0x28cf8a0e 0x7c73e7ef + 0x26a296c2 0x789d4c72 0xd1490265 0xd9a9e843 + 0xf03504c3 0xfae6dffb 0x7a48f00d 0x51e369c8 + 0xcb3eeee6 0x0625e936 0xe93d0d7d 0xfb15ba6b + 0xec5c76da 0x8fdf44f1 0xa036653a 0x5730c4a3 + 0xe5bfe6dd 0x0b8c091f 0x3b51558c 0x403748f4 + 0xf4007f86 0x952b5db6 0x5524d8ba 0x8046409a + 0xe3fc61a9 0x66f4ea56 0x5645150b 0xdb2bec15 + 0x50672218 0x7f40e87d 0x2b8359f8 0x438787dc + 0x7f221597 0xf8b1590c 0x4f468251 0xff586d05 + 0xb9195380 0x0ee09e0b 0x2fa7dbd9 0xd197b327 + 0xa0dbad58 0xb485681f 0x5ef0937c 0x1e07ebb6 + 0xcb49fe3f 0xc2427cd9 0x6c2c5298 0x4a2e171a + 0xa7f333a8 0xb3609ad6 0x94e374d6 0x0e1eb64d + 0x22c3367d 0xcdf89975 0x647aceef 0x16727c9c + 0xf476ae53 0x35a1212e 0x0db768b8 0xfff8b53d + 0xbd4fe45e 0xab28a5a3 0x59cec0af 0x28bcd1ef + 0x6f43ad69 0x2658a059 0x27aee0ec 0x4e8bbd15 + 0xa9fdcf04 0xc9aa329f 0x687f010f 0x5c968a07 + 0xb894e607 0x0e1cba22 0x2f00f203 0xe8e133ac + 0x494a4746 0xe8bdff9a 0xf69791a2 0x64179ce2 + 0xbfd10dc6 0xc026f6d8 0x4871923a 0x8946b277 + 0x609f49a4 0x6466df1b 0xd8c3c131 0x46ef0291 + 0x0fdce8b6 0x2b9aedb7 0x225c4520 0x72b332cf + 0x4e220d47 0xf2f69c36 0x2c23fad9 0x57a2a918 + 0xe017409c 0x490819af 0xf2121afd 0x951ff7ff + 0x40363fcf 0x5078b94e 0x9e4be775 0xee97ef16 + 0xdb3a2390 0x17d42af9 0x96f56a51 0x1b4c2934 + 0xc866315c 0x2b746f99 0x9a3b73f6 0xa1e081fc + 0xa9d07ebd 0xa6359fae 0xdf50d099 0x55304e01 + 0xfe5aaa81 0x1e74267d 0x38b1d2d7 0x8633e9af + 0x99b013df 0x3aa05831 0x86279736 0xd2b464e0 + 0xdf036a9f 0xe8162915 0x876c0d4f 0x4beb7d0e + 0xfec9b170 0x46bc9df4 0x46cb88fa 0x0cb5904d + 0x2e2961cf 0x7ea5dc1a 0x60670df2 0xf935ca32 + 0x67e6777b 0x8bacc97a 0x5cd07248 0x32e483e6 + 0xfdf09b0d 0xca57150b 0x3f432d09 0xdea2d7db + 0x9f6a2954 0x6f07dff3 0x4133f394 0x60272f97 + 0x1b98c9ec 0x2ab648d9 0xb5df14a8 0x0d2c38f2 + 0x5dfde2c4 0x7cb43ca3 0x8d0c6c01 0xe80ea41e + 0x5f58b71e 0x4ca9fef2 0xabd201a4 0x50905c08 + 0xca8ba387 0x5592922b 0xfa4e05f5 0xceb64b14 + 0x0845c5bd 0x518d369b 0x727e570c 0x1daaab31 + 0x801e8b9c 0xec6568f3 0xd4c3760f 0x40a78d22 + 0x38af58b5 0xc406a76e 0x8c3a7779 0x18272c42 + 0x45cf7b70 0xa6f3c0f3 0x88021e41 0xda662504 + 0xe97aa709 0xe93bafe0 0x8862ed5f 0x35bc8268 + 0xf5a41551 0x3dd3bb21 0x1af0cf11 0x08fe1ad7 + 0x53ecae41 0x01a4a8ae 0xfed636b7 0xf09323e6 + 0x73b9b253 0x7ebd7ce2 0x7074b4de 0x21c719b2 + 0x50982743 0xd23cfd27 0x136a1f4a 0x23260f6e + 0xfad89dcd 0x57586681 0xadc4fba5 0xad0f71b8 + 0x91a3f188 0x20d62385 0xfecda9cb 0x33d67776 + 0x2abb0e6c 0x0ad16087 0x486332da 0x2928d342 + 0xf6d1b174 0x5e133a4e 0x72fc0ad4 0x940578b8 + 0x320a42b1 0x9cbda7d4 0xf2a36135 0x00ab8de3 + 0x5bad9000 0x5778e633 0x3952763d 0xe0e58583 + 0xdfb0bf19 0xb11914b6 0xa67da7a1 0x8d9a9f81 + 0x638cbcf7 0x83bf931d 0x8703b0dd 0xcab30fa4 + 0xd6db2ee6 0x5cc2e5ac 0x717e636b 0xfdcbc760 + 0x563b3b25 0x0e4df458 0x9efb8fa7 0x95aaa7a1 + 0xf05b6680 0x5e237e59 0xc884018a 0x177b5a30 + 0x3ea2c9bc 0xd0325ee6 0xb1dae51b 0x812ee29d + 0x6d58db21 0xb787fa68 0xfd092294 0x09683dd3 + 0xfe0d6405 0xfdd99aad 0x78744a59 0x936738e6 + 0x6ad6cba7 0x370f7f8f 0xd208c214 0x12239384 + 0xbe71f0e7 0xfc0ef264 0xc04e4a49 0x354f9cf3 + 0xf5d7572c 0x07839ad0 0x834a003d 0x23ba26e2 + 0xf4049ecf 0x5ff402b2 0xff9d6769 0x074ebe6d + 0xdc829da1 0xc3d7697d 0x973efe4f 0xfc2a9165 + 0x126dc518 0x0b824ca4 0xc438fb70 0xb7b0ee00 + 0xbe56afd9 0xa3d8defd 0x971455ae 0xc11ffde7 + 0x346e619a 0xb41111a9 0x6004b62e 0x896c668d + 0x738e458c 0x351f9fdd 0xe771b2ba 0xad6d7464 + 0x719b57c2 0x6f6a4611 0x8a676f2d 0xb8db1c43 + 0x3f102641 0x51bffdbc 0xb7862565 0x5d8dd231 + 0x7a79bd39 0xfa472894 0x0fd1d2ff 0x64cf589a + 0x38234d7a 0x5c9acefd 0x8eb0b9f8 0x761e1c95 + 0xf2fe78fa 0xe06220d7 0xaf82a919 0xf4e196e1 + 0xa17c8935 0x06d08d16 0x6bad807b 0xf410805d + 0x4ff2bce6 0x3297c81f 0x06e35353 0xbe1f5e1c + 0x65d1cb92 0x0dc69b2f 0xac55d597 0x636ff24c + 0xe2e4f2ba 0x63d64922 0x4b2e9f71 0xad2279ec + 0x5f0b5c0e 0xac688638 0x35613358 0xf5531360 + 0x54a304e8 0x27ebfe65 0x977b5a3c 0x3dc5e10c + 0x73b32ee9 0x3a2c9454 0x30a149c6 0x31e5b55c + 0x2c10854f 0x745cd38a 0x2853a27b 0x6629e355 + 0x0bb67e39 0x5469184d 0x694a9bb6 0x0a0ca25f + 0xa878c5de 0xee15fd46 0x23d92ff8 0x02328404 + 0x1c9402b5 0xa46b6ce0 0xefc3e947 0x0e9312ad + 0x5830ae9e 0xe30e32f2 0x9db8ee81 0xe8aeebbc + 0x30675c83 0x447278c2 0xab2bad3b 0x08ba3d0c + 0x1124e681 0x3691242d 0x903c8d2b 0x3281c312 + 0x22af690f 0xd69a150c 0x57622c5b 0x29313c73 + 0x6ab2d7c6 0x39b06dad 0x6e1f9f81 0x03324986 + 0x53a49093 0x7654eba3 0x2527245a 0x9af596fb + 0x818ffb3a 0xa3817173 0x6a2c4b80 0xfcc42ad5 + 0xfb1bbb69 0x3a3720a2 0x90a89bcf 0xed80308d + 0x7753cb1c 0x1c2654a5 0xb01ee4af 0x81091e85 + 0x9067b3f1 0x2e2b9b5e 0x9fb0c7d1 0x78fd9f69 + 0x5771c46d 0xacdf498d 0xfd8b8e77 0x4c15fa61 + 0x607120ce 0x18a298d8 0x73716420 0x65e5e06a + 0x18c53e04 0x35b84427 0xcd82b522 0x9a7d26bb + 0xd56b4b74 0x49b47fe8 0x63178dc6 0x0bac0f46 + 0xc8b0755a 0x9bbaaf1f 0x18131d2b 0xcc019330 + 0x0ceb89bb 0x8808c2d6 0xfb5bd86c 0x6c945b71 + 0xdc911924 0x4ebb8d35 0x44e46d08 0xabfee615 + 0xf456931f 0x7a244955 0x0bffce7d 0x5533ca5f + 0xb1b2c636 0x4f29075e 0x64012561 0x7aa5e7c7 + 0x9c8a0666 0x9698782d 0x3481ad8f 0x21a55b19 + 0x735aa45d 0x4245b9c4 0x0d4c3fdc 0xd1b10966 + 0x7035fcde 0xc2257947 0x4a37271a 0x9da464a9 + 0x228adbf8 0xbf309e03 0x096f560a 0xa2b8ca78 + 0x427702cd 0x35a99cf5 0x99811758 0x6953db58 + 0xec07533e 0xe95838b9 0x61c71654 0xc9cce595 + 0x275af106 0xc8697af3 0xb3f27e58 0x411d8d30 + 0xd0d90ecd 0x1503b9dc 0x76bf070e 0x49f89ef0 + 0x7333b083 0x53f9c44b 0x8330c3a2 0x6a1119c3 + 0xca555f2b 0x3d51fc6f 0xac7b3320 0xf8e42cdf + 0x053753fe 0xc122336f 0x94d289c6 0x088b5a64 + 0xc3aac7f0 0x96a76344 0x2ff05828 0x9b4f2af3 + 0x46de6a46 0x4ed29d98 0xe2ab7634 0x27481ddc + 0x300ca71f 0xce7ac539 0x88240e09 0xb1a14e78 + 0x2addd4c5 0xb3a7f320 0xe91f549b 0x6881c45b + 0x0e381c47 0x1018feb4 0x64679650 0xe62281cc + 0x670ee6d4 0x0d226160 0x947b7f08 0xbc595a74 + 0x2380c0b3 0xc0235785 0x63b41221 0x80b9cc31 + 0x3231b4ae 0x33ed5718 0xf2c5c90f 0xdd3b03ea + 0x67dfca08 0x453e9d29 0xa2bdecbf 0x5e9a3181 + 0xad17aea2 0xff0a8f13 0xdf946849 0xcfbbecb7 + 0xb0a602d7 0xb1a820c6 0xfe7abbc8 0x7f70790d + 0xeb5f8863 0x266d3cc1 0xbd552a44 0xe19b1b3d + 0x856aefbd 0x51c11f1e 0xde661b7f 0x61c075d2 + 0xd0f6a834 0xff1d0d37 0x6793d1c2 0x70c133a5 + 0x20c4d2cf 0x8c80d4d3 0x61ebe382 0x788b74df + 0x11c56903 0x535889ba 0x0a9c7380 0xf9de2837 + 0x09437fe7 0x1627c6b2 0xb943bdb8 0x69bc29b2 + 0xee9795a4 0x83c992e0 0x95437918 0x8ce166a2 + 0x56b56b66 0xb0680941 0x623d38a9 0x2add07ad + 0xe583ba09 0x96f6532a 0x3eff4696 0x2a8a6b0b + 0x905b913b 0xafc01673 0xe871e006 0x2c2339ad + 0x248438e5 0x96d83e53 0xb3a75d6b 0x2258cf63 + 0x69ff39bf 0x95727173 0xc3ac09d5 0xea8d2c06 + 0x0e7c0a4b 0x144fcade 0x28a9a5a3 0x97c11ae8 + 0x89865e3d 0x1640cd32 0xe3e551f8 0x1f7ba770 + 0x6d23fb31 0x11eceae3 0xc8ccb8ee 0x46dd0bb0 + 0xd01a46ff 0x0504adf5 0xec6e170e 0x2e3d7ac5 + 0x70f893ac 0xaf9963db 0x061e283c 0xf0ad248f + 0x2fe97e19 0x881fd340 0xc686c9d5 0x88ea8ba5 + 0x92f05cd7 0xd6716148 0x6fc47fc3 0x2c51d9b9 + 0xd50a7faf 0x4eccacd1 0x7c92f802 0xa63ffc83 + 0x7cb0ab1d 0x4492e81b 0x7d906554 0x43306ba1 + 0x73a5d57a 0xe57a05d6 0x6850b964 0xefed595c + 0x7754978f 0x629e8236 0x62ec4dde 0x247439ee + 0x8b9982fa 0x4eece5c2 0x48599175 0x0fdc752c + 0xecd87b12 0x94936c75 0x17a45ea1 0x80a899ac + 0x22a39ee7 0x745730b6 0x03ea4daf 0x4a7570d7 + 0x307621fa 0x7322e0a7 0x3a8e0316 0x454e46f7 + 0x08773750 0x156dcaad 0x5562bc06 0xa23a1ee3 + 0x20435211 0x1d679ea0 0xb220e205 0x682cc1a6 + 0xd64a71c7 0x3ca7f8e3 0x2e92f253 0xa7cfdd0b + 0xd62b4053 0xf5c5f641 0xbf72dde1 0xdcb716c1 + 0xe2f7b05d 0xa03145ea 0xc09828d2 0x7dae7916 + 0x6fb97c79 0xb3a85204 0x998a9c7b 0x5f42ba8c + 0xd9c628b3 0x6b17bacb 0xa889b716 0x450ff97d + 0xe9166f3c 0x2d20777b 0x82a003ae 0x2c7ae0aa + 0x6011a9fe 0xfeed34be 0x1328f67e 0xf61003a3 + 0xfaecdf20 0xee18c81e 0x731a0302 0x11a39e60 + 0x355d78dc 0x99088f2c 0xcf253759 0x97347603 + 0x736f71f1 0x37e4b395 0x9cc74540 0xf7e39994 + 0xf01c5f64 0xbec519f1 0xa79c1067 0x76000d5e + 0x1ac85b6e 0x51e5b7a3 0x62a97ddf 0x6f20096a + 0x2af51e77 0xea5554f6 0xb4e581da 0xc1ac4ba8 + 0xc8f22bf7 0x9e254d3b 0xd7dd62f6 0x6461ae3e + 0x423e1f10 0xf143e7b9 0x18c73b04 0xa43de614 + 0x2da8d02f 0x9befa706 0xc01dcd49 0xa278f1e0 + 0xd85f3177 0x6b6679fd 0x1ccef04e 0x53af9252 + 0x34d751db 0xc8d32c86 0x3d725097 0xa64ed581 + 0xd090c42f 0x9e92bf3f 0x6f82b089 0xd42728eb + 0x3dd651e0 0x1985bc52 0x4b0f4159 0x0f99bd7f + 0xe2597023 0xca0cae4c 0xce48a894 0x7249dd88 + 0x8e146632 0xb4be1d6c 0x790ae7e5 0x6747b657 + 0x52143947 0xa2e42ed3 0xea359617 0x6ca01a11 + 0x35c5e2dc 0xc97b78fc 0x5db6db2a 0x80fe3414 + 0x27da19d4 0xd7431d04 0xa91e9110 0x7d8ecb23 + 0x2508700a 0xc8c71ed9 0xd28835af 0x018c2887 + 0x3d0a6fab 0x3e8523d6 0xd0688dee 0xe5c3865c + 0x838d72e4 0x6bb73a1d 0x497a59ca 0xf77c56de + 0x38ecb72e 0xa55e3565 0x04b12c92 0x1aec9997 + 0x037c340a 0xef0d04c3 0x78f74bd6 0xdec9b9e8 + 0xd95b61ea 0x5528e8f5 0x4ecd325c 0x88ffdc0b + 0xb337ac61 0x899d90e7 0xb5eeb978 0x8295d9ae + 0x1ed8978b 0xa8849eda 0x8633b4a3 0xb8c858b5 + 0xbe3c4375 0x28b9e84e 0xb2a26def 0x22f8f66b + 0x3a4aed99 0x0c4914ea 0xad103249 0xba5a5eff + 0x8a052461 0x26938899 0x915c6ed7 0xe6268ad9 + 0x246e8c74 0x75f3c196 0xc3e725d6 0x92e02549 + 0x1f78a5cb 0xeada57e5 0x40f14906 0x0215e49c + 0x57c06bae 0xc1896b87 0x0cd40a63 0x60741d80 + 0x11a69899 0x80fed942 0x0497e115 0x56697b55 + 0xba89c3d4 0x27d6b7c5 0xddff87b0 0xd3b1ff2f + 0x3160e528 0x9cca1286 0x13b4fdf1 0x38cdd907 + 0xb50c4597 0x4c151714 0x1cab86c7 0x23126a3e + 0xe26e9749 0x289a0d0e 0xc4004640 0x9d33928d + 0x33b691a2 0x15ed6e6b 0x6e773980 0xadd59678 + 0x188ba49f 0x08da4c6d 0x6d150d0b 0x0c6c7b98 + 0xc8e1df7e 0xb8b1e692 0x5e89fd35 0xcb253d24 + 0xfc6ee27c 0x8013de3d 0x1d38012b 0xe50a8f7b + 0x7d410ff1 0xceee4e9f 0x0e8094b6 0xaa1a5f57 + 0xb395a551 0xbd62b2ae 0x5d7b34c8 0xbd2d6195 + 0x33af4109 0x0769ff18 0x9c6cc123 0x78ee6eb6 + 0x412644e7 0x70e0c6f4 0xf45d8fc6 0x0435f5af + 0xd43622b7 0x27409d5b 0x6dd04e8f 0x9f02ecf5 + 0xca415f7d 0xc9f439c2 0x7198e539 0x20476b75 + 0x3cdd8dd8 0xce17fbb0 0xa5bc115e 0xb0ee52c1 + 0x0b074cfa 0xd26d4f99 0x3b43320b 0x230b680b + 0x9908f2d2 0xcbcb1952 0xf45a2f53 0x7b4564c6 + 0xcf2fd983 0x414fe4b2 0x55ea7f11 0x63e8117d + 0xe8954052 0x7c2ea344 0x97a02aaf 0x6ca874c3 + 0x1ae5b4ee 0x41754eae 0x6954abe0 0x115ddcda + 0x9a27968b 0x32a53e65 0xffe47b2f 0x4fe7e5a7 + 0x6016dedc 0xb3c0893e 0x9626776d 0x5ec773f9 + 0x1104e01c 0x1473cfb3 0x43b2cedf 0x8ca9d119 + 0x7f1bc844 0xd8bb7387 0xba90d2ef 0x2bb0dcf4 + 0x2340f124 0xa5bd514c 0x50afab05 0x718f5ad5 + 0x7c03fad9 0x71d00d2d 0x1c31fdc2 0x4a938809 + 0x40945ded 0x437f2a0d 0x83c10d64 0xd224c6ab + 0x0cd44481 0xb0040966 0x27fd6e7f 0x6ff45d4c + 0xab057ad1 0x8fa4e5d4 0xac50270c 0x6e4926ca + 0xc5721498 0x2529b458 0x40ee2ad5 0xde5e21f2 + 0xea8964ca 0x56766e60 0xdc3b8702 0xa93528d4 + 0x28d7713d 0x42edf022 0x59774dd8 0x200ff942 + 0xe7a4d769 0xd8c4ef5e 0xe177f715 0xe9d53cd6 + 0xc11270bb 0xb25977e5 0xb80867b4 0xfb48468b + 0xdbf166a8 0x49700d85 0x0f85f98a 0xa7ca7a75 + 0x109817ce 0xca243f19 0x8bed7688 0x9a1c8231 + 0x94f0ce97 0xc36309ca 0x90ecac24 0x67e7e0de + 0x86b18d62 0x18c7b7a5 0x622f5d3a 0x47e1e067 + 0xdc96b94d 0xe4a03beb 0x59d17692 0x040abc0d + 0x44a5ae50 0x3d3dab7d 0xc18dfd30 0x2802b9d9 + 0x6818379f 0x56db41d7 0x97cbf039 0xe41d6a32 + 0x64b5fb01 0x6506e0b4 0xd60a3234 0xdf3573d2 + 0xac148579 0xe7f46ac0 0x05e1c763 0x904a5aa9 + 0xc7ca1ee0 0xe0c3b047 0x5e36e1bc 0x447a9141 + 0xe24654df 0x9853a49b 0x6a29cedb 0x022f00dc + 0x6df2a7a7 0x3636da02 0x72bb9c81 0x4f0e0918 + 0xd649f4a5 0xbb0c81f9 0xc0ba93fd 0xc1b390f1 + 0xda84e720 0x1aea0064 0xf3ee67e1 0xb874ef4a + 0x82467ce6 0x59abf506 0xafbf145a 0x9a4cf8a1 + 0x17247c89 0xd8669398 0x1796eaf7 0xbc2d24a9 + 0xcb486570 0x17a9db23 0x3e6504f0 0x08684517 + 0x2723ab28 0x7081b814 0x8a265a04 0x697e6d8b + 0x69b146dc 0x6434c182 0x27ec8101 0x864405c5 + 0xfff86c9e 0x3052d8a6 0x23d283db 0x492970e8 + 0xbc6c64c3 0x46d8f98b 0xe16e7ff3 0x731e4f82 + 0xbd26b1af 0x6b30e6c1 0xff192fce 0x097e0bba + 0x49df63a5 0x2fdc3f01 0x50aae053 0x60177b8f + 0x1949eb85 0xa46084ce 0x9658f694 0xcb951fbc + 0xc53806d9 0x63a17d30 0x3b3f86c2 0x8a37aa6c + 0xedf8fe5c 0x87aee1d3 0x8c680126 0xfd8b27a6 + 0x231fa106 0x69358c25 0x4502c348 0xc107861c + 0x46280e70 0xcf6067ac 0xf6a04ff3 0x3e488677 + 0x6f3fb4c1 0xeec1f758 0x560e1c48 0xb604c06b + 0x69e34b1e 0x8ef41dec 0x854cea22 0x726581d7 + 0x55ea91f3 0x38ae4053 0x5ff7389d 0x6952cbf6 + 0x09aa0fc1 0xcccb1d50 0x5c1a633a 0xde1eba46 + 0x797212d8 0xa943fb3d 0x6063a1a8 0xbe68ef36 + 0x6ba0d5ba 0x0dbe2061 0x47711712 0x62679807 + 0x6f34009e 0xe6fe8f18 0x66a6a64b 0x3f80f472 + 0xe953d5e0 0xbcd8196a 0x086faad0 0x49da7f16 + 0x7f2199a5 0x55af4af2 0x085b4d38 0x22e634bd + 0x6cff0416 0x343466f4 0xd121a7a6 0x6caa3942 + 0xe4f365a2 0xd832eb0c 0x616728e5 0xcca4c71a + 0x4010cdc2 0xd0f1d1cb 0x5e695f89 0x27719206 + 0x0ec92854 0x76144a1b 0x49808021 0x12457a1b + 0xdde7aa5c 0x8f1a077f 0x110a4a5a 0xb3a5ad31 + 0xaacebf8f 0x66ff7f33 0xa2340971 0xfb4c7e82 + 0x8dd536d7 0xafd2021a 0x72aa9c6e 0x22df6952 + 0x83c4b4fb 0xba515555 0x93eee8f0 0x22d0ed5a + 0xbec05586 0x83828f28 0xe0d7f930 0xac0f0199 + 0xef6d76f9 0xf56ebdf8 0xf67323c9 0x8b805745 + 0xce5902c0 0xfa2ce3da 0x10f836dd 0xe1ac6d97 + 0xa0e415ea 0xbb7c32ad 0xc421f3b0 0x8166e898 + 0x74e7a73c 0xf454b82a 0x631369b1 0xe30ed23f + 0xdaa1c75b 0xe7c9c6a7 0x5f33c375 0x99c05187 + 0xf2d6e6ae 0xcd2045b8 0x92ff3009 0x15082015 + 0xd1a1580e 0xdce25f9b 0x21984a75 0xa9be5388 + 0x099a5372 0x3ab9bcfa 0xdb9069aa 0x49a99be6 + 0x42a9ee0b 0xfe32d832 0x24e11ad3 0xd16f596b + 0xb95982cc 0x754ab1c8 0x42ffa128 0x539e823d + 0x28e0f976 0x262ddfc0 0x2a16e7ad 0x49b5acd9 + 0x931f3def 0xdc419b84 0x8412cc3c 0x81056cd9 + 0x91933e1f 0x57710b15 0xa55d2696 0x87d88724 + 0xd4fedfdc 0xcc3825c6 0x397f382f 0x80f9b6ba + 0xcdd6d59f 0x24b984d8 0x8f1c5bcf 0x25bcef1d + 0x00dc603a 0x76fd94c2 0xa267a7dc 0xa6e90a6a + 0x5c5916d6 0x065a52cf 0xa28d3263 0x9b17b72d + 0xb8436b48 0x1b1c2391 0x1fda3395 0xa6cecbcb + 0xbc4ec502 0x1766b590 0x5945fbd6 0x6a124405 + 0xf92d06f2 0xe24694b7 0xf6befd08 0x8266cf5c + 0x03ed670a 0x5f98be62 0xf27b7e2e 0x598cf22c + 0x2e855591 0x879815fb 0x153799c6 0x3820faf6 + 0x3d3a2cc6 0xdbb6dece 0x1a3c46b2 0x5031bdda + 0x47894c03 0xe43661fe 0x7a6ee548 0xa5ca9779 + 0x6aa9e105 0xbc8505a3 0xa03b860a 0x448faeb9 + 0x367de4a9 0xc9779c7d 0x6535ad8c 0x4b7fcacc + 0xb2db5c10 0x0ab41ec6 0xe528ab90 0x5e6f03da + 0x98bc76d3 0xf38df42e 0xea59b039 0x1c2eaa28 + 0xca30dac5 0xdb0eb8c6 0x60063860 0x18823f8d + 0x164e2f28 0x7cbbe080 0x70a12315 0xb08f44d9 + 0x5fbb9453 0x4bc62738 0x9fa15ffc 0xe4033ca1 + 0xc9dfbc13 0x58245d7d 0x588113aa 0x8f5a6ac8 + 0x92588a60 0x26330c74 0xb2aaf0e3 0x24ada1ea + 0xa9e973ae 0x624b73e7 0x4ef961db 0x95ede155 + 0xf2bb86ff 0x96bc79d9 0x95cd646b 0x1c3af453 + 0xf60fa711 0x10905115 0x0e24b740 0x169bb227 + 0x34cee6f0 0x990980db 0x18d8ace5 0xd4c87504 + 0x29515d32 0x2e5d9c04 0x87dffa60 0x12e815d1 + 0x021db8e9 0x2c5a42fd 0x6e3a1a13 0x88889ab5 + 0x3bc915a6 0x608919c5 0xd310a970 0xea8f3218 + 0x949f55bc 0x9ed7aadd 0x6d990157 0x181f1c2f + 0xa940df64 0xf3be8c39 0x7ca2e699 0x7b4f07f9 + 0x89e83fee 0xe66b9493 0x54fc3d17 0xa63d2d46 + 0xd5e835d5 0x910e0144 0xecf67025 0x1fa6a93a + 0xe692dbca 0x466af681 0xc2bc808c 0xbb4ebd60 + 0x74d5c729 0xa283ad25 0x1e66fa23 0x6d372988 + 0x753c9fcb 0x1742efdb 0x5b68cf15 0x372a0e33 + 0xaa3a7ebd 0xa0e944d5 0x95d5cbb4 0x4fb6020b + 0xced927b0 0xb2afea78 0xd0646b72 0x1622fad4 + 0x4672c6b6 0x736ae4f8 0x8d46a4db 0x0e6a432e + 0xe0a30a98 0x4c2bcf4f 0xd87acedd 0x19682d7a + 0xf97c025c 0x55d8feb3 0xbcd4d2ff 0x236c6f9f + 0x8ba0246d 0x42812f73 0x327636f5 0xc92cd30a + 0x08a69d9d 0xc735a946 0x82eca01f 0xda0753a0 + 0x7077b1d1 0x17b05834 0xfa24bc02 0xf49f4473 + 0x8f9ac6b4 0xa880c630 0xf7457b4d 0xd5f829e4 + 0x25c49a99 0x1176a997 0xbb2d2009 0x61d35764 + 0xa322c752 0x6ef3ae02 0x5faae6f8 0x9a52acf1 + 0x19176f43 0x43843b07 0x14efc471 0xee474403 + 0x319c4857 0xa19adcf0 0xc0a466e1 0x02db14ad + 0xb7f211f3 0x72aa6ca6 0x0eb9bffe 0x48a6d284 + 0x9a93a2ee 0xac09fc5f 0x92a62c4f 0xd34f0271 + 0xffb348c7 0xf229b6e2 0xc68ec1ca 0x19577dbc + 0x069a10bf 0xf64ac347 0xf7c3c848 0x81975294 + 0x6376e550 0x93b53440 0x8bb17daa 0xc4c64c07 + 0xcaeff293 0xd51497b0 0x33da3565 0xa73d5def + 0x4bf4dcde 0xfb470fcd 0xca7db864 0x7ef17022 + 0x47567363 0xd8fb8d74 0xa68c3c72 0x8202e4f3 + 0x75bf1798 0x16a70fd2 0xcc3b697f 0xab9a1075 + 0x13f56ef3 0x269d0302 0xcb655a43 0xc9a4de88 + 0xfb8363de 0xff40f36d 0xd2555489 0x647a7995 + 0xfd8eda6e 0xa3958c9a 0x20e029b4 0xbed3e225 + 0xa7df5f17 0x63bc3c1a 0x337ecc9d 0x6c329508 + 0x786aa47e 0x1db5b093 0xc0acd73b 0xf9587237 + 0x243e5d40 0xd3623c3a 0x338c4740 0xb672140e + 0x43640a9b 0xb7ef3f6a 0x44151074 0x749bcc46 + 0xfa1f103b 0x0fefb19e 0x58855538 0x138ad276 + 0x2641fd80 0x297d99d0 0xfaa63ba2 0x00b6f11a + 0x3793fb6b 0x124763a1 0x8b9419ac 0x56abf9eb + 0xdbf83419 0x43570571 0x37299cd8 0x8b201e62 + 0xa4058fa5 0xb320e91b 0xbe7d40b7 0x4eca3b2d + 0x8519c155 0xf4b17021 0x9e4c572a 0xdc1f9e16 + 0x39a589a3 0xa6cfc7a8 0x5b986910 0x64e150e7 + 0x60b6f2c1 0x02bacd3f 0x2f3b5a5c 0xc6f453a8 + 0x15a87a7e 0x76104a14 0xafa2ef63 0x2cd48dbe + 0x3c7abddc 0xd786ea5a 0x4f65867a 0x355cda38 + 0x2ae03d9e 0x4f11f6be 0xfc0a0034 0xde4ea602 + 0x21ff83ea 0x0f12d913 0xedf4da28 0xc96d8fd1 + 0xd7e82c3c 0xfec63bdc 0x37a456d7 0x3007e18c + 0x091a47b6 0x82f1c641 0x82219cce 0x3e7e6993 + 0x7b3a2115 0x0b8e1a02 0x40f88213 0xfa2f9c21 + >; diff --git a/arch/x86/dts/m12306a9_00000017.dtsi b/arch/x86/dts/m12306a9_00000017.dtsi new file mode 100644 index 0000000..299d663 --- /dev/null +++ b/arch/x86/dts/m12306a9_00000017.dtsi @@ -0,0 +1,750 @@ +/* + * Copyright (c) <1995-2013>, Intel Corporation. + * All rights reserved. + * + * Redistribution. Redistribution and use in binary form, without modification, are + * permitted provided that the following conditions are met: + * .Redistributions must reproduce the above copyright notice and the following + * disclaimer in the documentation and/or other materials provided with the + * distribution. + * Neither the name of Intel Corporation nor the names of its suppliers may be used + * to endorse or promote products derived from this software without specific prior + * written permission. + * .No reverse engineering, decompilation, or disassembly of this software is + * permitted. + * ."Binary form" includes any format commonly used for electronic conveyance + * which is a reversible, bit-exact translation of binary representation to ASCII or + * ISO text, for example, "uuencode." + * + * DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT + * HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *--- + * This is a device tree fragment. Use #include to add these properties to a + * node. + */ + +compatible = "intel,microcode"; +intel,header-version = <1>; +intel,update-revision = <0x17>; +intel,date-code = <0x01092013>; +intel,processor-signature = <0x000306a9>; +intel,checksum = <0x3546450b>; +intel,loader-revision = <1>; +intel,processor-flags = <0x12>; + +/* The 48-byte public header is omitted. */ +data = < + 0x00000000 0x000000a1 0x00020001 0x00000017 + 0x00000000 0x00000000 0x20130107 0x00000a61 + 0x00000001 0x000306a9 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 + 0x00000000 0x00000000 0x00000000 0x00000000 + 0x86c5b0d4 0xf6978804 0x7f4f5870 0x6319dc3c + 0xbb3b7d61 0x33cf9075 0xe8424658 0xf611a357 + 0x5a3401db 0x42caecce 0xb4d8e75e 0xe6dbaf24 + 0x7861b35f 0x6bd717bc 0x23b9b731 0x82ec1ac8 + 0x20337b64 0x5396dbf1 0x59973bff 0x724bc7e9 + 0x5237193b 0x0b8647c1 0x6a0d0e16 0xbf9ddb5b + 0xace2cc1c 0xad707638 0x056f102f 0xa37e60f8 + 0x76255642 0xfb86e030 0xb8069a40 0x367795f1 + 0x653fb05e 0xab7f14ad 0xb6e8a8e1 0xd2598d20 + 0x2eba3f68 0x78b372f1 0xba8d13f8 0x1f1de861 + 0x97f951d5 0x8097c728 0x27dbf904 0xb97906a8 + 0xffe7a4ac 0x4b947668 0xc1dbd726 0x2adcf777 + 0x63b1bcf0 0x818e2a1b 0x49aa907b 0x2faf5e8d + 0xae842352 0x82707fae 0x0aa12b41 0xa0bae11c + 0xb4298c47 0xd2b4099c 0x4ff625f2 0xcd2630d4 + 0x79850981 0x05dbf57d 0xb05b81a5 0x56e73ec7 + 0x95cb3897 0xe262bda5 0xb2c6e288 0xcb7f8e77 + 0x72b8bdd3 0x3f400494 0x63ade65b 0xbc4adc71 + 0x00000011 0x06c0f8ff 0x0eb63d77 0xc54cdabf + 0x76bc8860 0xdd142643 0xe7bfc220 0x17aa0a91 + 0x4fd676ba 0x4b6b1a15 0x2a1a1c16 0x4fed6de0 + 0x8c3d6bcf 0xbb319bf6 0xa82532f1 0x7c8ce014 + 0xb830a38b 0xec25bc6b 0x61c8a8a9 0x49a21dba + 0xfcf8bad0 0x7372f29c 0x1f7fbcdd 0xc2ff42f4 + 0x780878f0 0xc967068e 0xe19cc3c9 0x155e6646 + 0x75235c43 0x9aaf3741 0x9dfd116d 0x0f031b6a + 0x4963e039 0x6918daa8 0x7f0ca4ab 0xd77dad79 + 0x2f8847e8 0xf79c82a4 0x6a6aaad4 0x24f07dbc + 0x895d3f6a 0xc96b2eb0 0xff50228f 0x573d364a + 0x5fca9d56 0x3c11c35b 0x3e90fb12 0xc4604067 + 0x5c980234 0x7c42e0c7 0x60cca3de 0x637a4644 + 0xedc43956 0xb0efb4e1 0xe94716fa 0xa6478f51 + 0x33965654 0xdf6b40a3 0x48ac1b18 0xd6723c94 + 0xf040d6d1 0xaf850470 0xe2bcde48 0xb90a4998 + 0x8f620105 0x3d592878 0x2f697bad 0x9f7721d9 + 0xec34444a 0xb0594770 0xd7180f9f 0xa510a168 + 0x460563b0 0x5d4f34f4 0x21dfc16b 0x051de344 + 0xa57bc344 0xff2c7863 0xf0bc063d 0xf5a89004 + 0x79a81dab 0x9e8cb974 0x2309b0a4 0xa47a46de + 0xcf9c0c44 0xf761c817 0x67ab642c 0x0db4422f + 0xca3616fc 0x79e66c8a 0xd56a3332 0x5e0f338b + 0x5814cb3a 0xed1b9a4d 0x47d59f72 0x25b03786 + 0x3edd1d42 0x8cd947cd 0x706e6ebd 0x82c2bada + 0x1bf6a96b 0x77dd859a 0xda35335f 0x22fab458 + 0xd0661fd8 0x02bb4a42 0xe2a2bcdb 0x0616580e + 0xd35be23f 0xc206d16c 0x401218be 0x51107c3d + 0xba84b8be 0xace4d8f2 0x505b9b28 0xc517034b + 0xac5ba582 0x7419fe54 0x43493cb1 0x2fe0a66e + 0x206039b5 0x07569011 0x230ce53d 0x168d427f + 0xbfe0bd10 0x82bf11be 0x5b55475b 0x5490a0e9 + 0x1c3c1e3c 0xacad77de 0x1666512f 0xfc3250d8 + 0x930a6312 0xdd85c066 0x1b95c18f 0xc8bbd3b0 + 0x1bb2a34e 0x642c7653 0x0f536213 0x1f7ab4eb + 0xaa5ef677 0xe6ac9581 0xd7a2fe73 0xd417dc79 + 0x455a6877 0xae825a40 0xe0c98bec 0xac39ba49 + 0x299d9bd9 0x957d0bb0 0x1645111b 0xe9da4beb + 0x1b005ce7 0xddb742ce 0x6c5f3ffc 0x24f74d2c + 0xf4ace044 0xb21bc7ba 0x338002dc 0x240effa1 + 0xd208ae00 0xfe8c2b5c 0x9a457293 0xd9365ac4 + 0x98f24244 0xf6d1aaea 0x7b874350 0x1ba4086b + 0x1d3bf168 0x2bb6f4fa 0xb27f8477 0x8da836f6 + 0xa8762693 0xc377fa64 0x74cfd979 0x90435c25 + 0x29d80e17 0xc3503c9c 0xaacd2178 0x232c748d + 0x6fecd3ba 0x00fb4aa0 0xbac3ee19 0x6e5c63e3 + 0x17823c14 0x0e9d33bc 0x0fa9de06 0x998b14b2 + 0xfdd8c80d 0x01b0591b 0xf70bc4ce 0xb278c496 + 0xa7e30708 0x69cf8420 0x14f8b744 0x8bb8a0ff + 0x168f6db0 0x95da6db2 0xf96d121d 0x67fd06f7 + 0xcd81d278 0x8693d095 0x15e1a24c 0xe5f554f2 + 0x499874e8 0x30fc0785 0x0f4fa1b9 0x65c93dad + 0xd939bf24 0xdad29721 0xf253b752 0xf6ff59da + 0xc5dfaffc 0xf0071f34 0xdb0db8b0 0x24475e2d + 0x2a4d5b8a 0xf7624bea 0x3fdcbc90 0xb5a66e35 + 0xd0f08636 0x24643caa 0xc5d08e83 0xb134c55c + 0x8e3653c7 0x34496b0c 0x6b2aeebc 0x2fbab601 + 0x105613a2 0x7babd55d 0xa01af846 0x248be690 + 0xed27917c 0x26ee6e13 0xa1dac5fe 0x852ed91a + 0xfc83fcca 0xdf479c33 0xfd6efe96 0xdc62521b + 0xa37d2a8c 0x1d2bad9e 0x4287614f 0xc4f7b62c + 0x2aab0562 0xec6d4226 0x52853fb4 0x264e3507 + 0x1c3af366 0x33269776 0x81b8529d 0x115530dc + 0xe035f98f 0x433d1b6c 0x1ea6daea 0xecfd2ad2 + 0xa57a0c22 0x1dbe3e12 0x6fafe41b 0x8e579e35 + 0x6c493fbb 0x034dd4f9 0xd17cd6f2 0x05c5cfa8 + 0xd9bffa39 0x0fc16e9c 0x831b88c8 0x7e7dce3e + 0x3320bc7f 0xd5abafaa 0x217ab526 0xade2597d + 0xf01b00f2 0xc9e34b72 0x00a4cb0b 0xdc198512 + 0xdc7cc8a1 0x89db07b5 0x6c2153ea 0xb8bdb8aa + 0xdf8a1ae8 0xa517f6b1 0xd32569d9 0x37e79008 + 0x3c7527c3 0x7d5b2d3b 0xb31cb907 0x35db7f6c + 0x0ab0cd65 0x75feaded 0x7c8260a9 0x5bc04f56 + 0x2fac9f60 0xd7b3a2c0 0x2b393634 0xc2df7f43 + 0x1ff2fa9f 0xc81af169 0x188b1f4e 0x08bf6f86 + 0x5ab2f188 0x0a71eb64 0x03b57501 0xa684fc23 + 0xa729ffef 0xe3b4a709 0xf9eb97d2 0x01506c95 + 0x0d9285f5 0x8e1ee93c 0x7d15a0d8 0xd9390673 + 0xf116ebd8 0x7e68798b 0x3dc8412e 0x5a9a04b4 + 0xe3805f51 0x00493bb1 0x4ec65ca2 0x2aedd69a + 0x7f2a5b18 0x9994ac32 0x476f3703 0x7d3da882 + 0x5635f55f 0x7a0887e0 0x0af46feb 0xfc2f3591 + 0x02e29400 0x70fd3234 0xc549379e 0xaf34fa5a + 0x5bf7c649 0xeb183cff 0xa236d508 0x4525ab64 + 0xc4301026 0xf281df99 0x0b298e46 0x9b7c1a99 + 0xc4b24e77 0xea536992 0x5a39e37c 0x570fb6df + 0xae5d5c49 0x01142cc2 0xda05d3f1 0x337bf65c + 0x3c986598 0xbecefd30 0xb5e34c2a 0xe7c3847f + 0x18cb24b4 0x71278c26 0x4b8d6caa 0xaf7c300e + 0xfb6ce9b8 0x94c4b785 0x67275f17 0x59498cf5 + 0xca8eeec6 0x3374e7a6 0x649affac 0x9049ba78 + 0xff9d3908 0xaceec446 0x225ece3a 0xac1d4fec + 0xdc050fed 0x04e3ed8a 0xb303d8e9 0xe9d26aff + 0x0a98691d 0xf243492d 0xe3b42f00 0x6c21a97b + 0xa385ae98 0x14ba3f4d 0xc0215cc1 0xe1ba6c0d + 0x412bbbe4 0x39f95d1c 0x593bd878 0x45d3066a + 0x9fcee8a1 0x3f29b2fa 0xc9ae58ee 0xed6def92 + 0x6c8f2182 0xdba64e20 0x276c2c21 0x81ea9dfe + 0x20ae00b2 0x8c2d2724 0x66c09f5c 0x24908e2e + 0xfecf8194 0x6be61e94 0xcdf5d7db 0x98b829a3 + 0x4241ab07 0x1207ef2f 0x96e7b073 0x766293ea + 0x58eb0882 0xf12a6426 0x741b074b 0xbd4302cb + 0x909b6c4f 0x1c4949cc 0xd4d6a3e9 0x442b74b3 + 0xbc8cb3f9 0x0efad89a 0xa2ceff3d 0xecdf86bb + 0x46a4a72e 0xe9d8abe4 0x94c91479 0xe99a80b9 + 0x1072b708 0xb8318ad3 0x0685426f 0x3e89a0d8 + 0x0b7c438e 0xb4b577d0 0x046599e2 0xd0ef85f2 + 0x3566d2d2 0x43ade22b 0x8753a78a 0x8f6d8e02 + 0xbdf33e56 0x8b2b6696 0x22a5e911 0xd0e0f4eb + 0x42729c29 0x425921fb 0x82f7634e 0x2c145fd5 + 0xff59deeb 0x018a5372 0x33c4e11a 0xc001c097 + 0xf250cfcf 0x2f682912 0x21f40dc0 0x883196aa + 0xcd5c58d0 0x7c329754 0x481c450e 0x9411c6c0 + 0x69a9df82 0xacb01a1a 0xc0b569a7 0x0b7fd1a9 + 0x4c339ad3 0xb0d9e211 0x07098664 0x14a5cff9 + 0x53beae37 0x4e173257 0x4e1d2e6c 0xce981dd1 + 0x45d6204f 0x3c193268 0x4f51ac3c 0x5ecffa12 + 0x48068ee9 0xde12270f 0x0a0aa980 0xd6fe8ca2 + 0x97d51da8 0xccf2db36 0xb3ad0598 0xbc56eb56 + 0x0adf5e5e 0x9e320aa1 0x8ebb75ef 0x3973a323 + 0x7e3d87e0 0x2c0d1858 0x83b7fa0c 0x36effdb5 + 0xcd9eba1a 0xab5b5790 0xa48fbf00 0x536e2ae9 + 0x2f2a3f61 0x05706a73 0xd2dfed08 0x7e4626b1 + 0x172c6ced 0xbf2e44ba 0x15aefc2e 0x9cf56c37 + 0x663c6695 0x04cece5f 0x4ce00027 0x465b1cd4 + 0x333dc2c7 0xce41f1f1 0x6dd8503b 0x52b79af7 + 0x564c81de 0x0e5e2daf 0x869753f5 0x16667889 + 0xe1acaf08 0x38ffbb0b 0x83400589 0x5144052f + 0xa3819950 0xd21501c5 0x1bdadeda 0x0a874e2b + 0x05480284 0xe8f76f11 0x582cad8a 0x0553f942 + 0xb6451cb9 0x76bdc86f 0x96ffe0c7 0xc630eba2 + 0xa82ec683 0x5902ef45 0xc362248c 0x18c412a9 + 0x1d09c103 0x2355ed98 0x5ec5c718 0x5037e359 + 0x1508f804 0x09cfea9d 0xa16cbdfa 0x5f962b17 + 0x85a35a27 0xa048dd30 0x6fe7ba90 0x0dc20150 + 0xcb56daa0 0x4188fb20 0xb4182598 0xa1bc5dd7 + 0x8c11e0bf 0x2104df35 0x025e74b8 0x79d177df + 0xad74bb77 0x4b2419aa 0xe374add2 0x411593d5 + 0x796778da 0x9e43a420 0x4a2e0860 0xefb48578 + 0x47cafbdb 0xea15924d 0x70ac1467 0xf52fd888 + 0xd2df4bd6 0xc1fc63bb 0x119ab88e 0x0e147ead + 0xa85bd8b5 0xc2e61ddb 0xd566417d 0x6bb9f9ec + 0x69bbcf1e 0x24d46989 0x3caf067f 0x58151211 + 0xc2a6b6e5 0xb233416f 0x3da28155 0xf9cd9385 + 0x7a530045 0x1eab05ce 0xb86ed141 0xa8f13a5b + 0xf9819f81 0x66d5d5c5 0x148c1a02 0x496d3c56 + 0x370dcd45 0x5f13f0b6 0xdd4eaeed 0x8dbad50d + 0x0747ce54 0x69d2adcc 0xfb69c18f 0xd44ea186 + 0x74ab7537 0x0c642449 0x88b096cf 0x3a8ad683 + 0x408cd7aa 0x6daa6708 0xb267b312 0xa4225c7a + 0x7a56dce7 0x6a8d497d 0x8837bcbb 0x6125397c + 0xeb51d233 0x362bdde9 0x689657f7 0x32d09e1f + 0x753a3d39 0xf77db5b2 0x8057908a 0xef12815d + 0x594fffe6 0xcf3402c5 0x1a0d4923 0xca547b2f + 0xaf9d604d 0x5d2e30f3 0xffe18005 0xe29bb0d9 + 0x36fc10f9 0x3720aac6 0x37bc1ad3 0x47d000ae + 0xa4b0da0a 0xa178228b 0xdd9374e6 0xa1f3df5f + 0x9ae2e451 0x21c4aceb 0x8f9fb226 0x5190b712 + 0x70253633 0x9c9cb5f1 0xc9178689 0x551c1a2d + 0x6db67cc0 0xcf1b1ade 0x48449272 0xd18634f1 + 0x9d9c3de7 0x19025530 0x121d78d4 0xae4a39e1 + 0x62850819 0xf3d4af6a 0xe5ad5b80 0xfa053c7d + 0x7ed68b9a 0xdbde2894 0x4b5c04de 0x65178203 + 0x9181cdd8 0xb17e27b9 0x0e29b338 0x50156ab4 + 0xf7726438 0x178108d6 0x1d8dc6b7 0xc3e7512f + 0x0eb8339c 0xe2684a6f 0x7668ed31 0xd0ed6eda + 0x4342a534 0x03840286 0xad1e6969 0xa9a6c98d + 0x1bf77774 0xd32fc9d8 0x405620d2 0x8ab19efc + 0xce4d7506 0x6f4eaae4 0x3e830dbd 0x76818782 + 0xfde4ee8d 0x1953cd0f 0xd47be276 0xf2480bc0 + 0xd1010013 0x2dd56a58 0x083084f4 0xc91b0ad6 + 0xc2524e12 0xa60710f2 0x3d955047 0xce380846 + 0x0f6dec2b 0x604d1492 0x5ca43ee1 0x6b51a626 + 0x350d5483 0x8d99ae30 0xcba06491 0xcc0185eb + 0x7b64caa6 0x2f1754db 0xca0691f1 0x6219efb6 + 0x43291db0 0x259d3f12 0xeaf6ef9f 0x5f0e065b + 0xad576541 0x8615a414 0x81124bdf 0x62b855a9 + 0xabdc529f 0x01bfdf75 0x10e4c656 0xf8e86f78 + 0x1fbe10d1 0xa6873c2c 0xdf83dcd8 0x20d35872 + 0xf46f2861 0x22f3d642 0xfdcda29a 0x16adbdb4 + 0x01e5844c 0x011e5454 0xf5432b04 0xd5f6a80d + 0xb081fab6 0x64fc2fbd 0x4ca76e0f 0x3a8d8b29 + 0x3f03ec12 0x58e2bf6c 0x24f2b8b1 0x108e414f + 0xe76a02ab 0xcb525af9 0x623ba7a3 0x31412c27 + 0x69c2f5db 0xd5546d8b 0x8200d2c9 0xf1e34a71 + 0x393e24dd 0x2b867933 0x0596e778 0xc5112b49 + 0xf433cdea 0xbc505e7b 0xf64bb064 0x1e892633 + 0xbf17307b 0x9118de2c 0x6b1d61a8 0x1945519c + 0x32638ca4 0x5e436733 0x3dc20ff6 0x9babf127 + 0x485c1555 0x0d0c4e2d 0xc4d5d718 0x8cfffc16 + 0xf64050db 0xaa4ef416 0x8d398a00 0xe4a16eca + 0x5d9d9314 0xefa2bf1c 0x05917dd4 0xca5f1660 + 0x59642534 0x02639b9f 0x12b895df 0xb2deaf0e + 0x20d8f0b9 0x04d8342c 0xa1ba5f57 0xa26cdb06 + 0xca732ca8 0xdce0c561 0xf5e4b205 0xc05f5cfb + 0xba4a41a6 0xaf219d7b 0xce08df01 0xa02bbdb9 + 0xc1adbc20 0xcb9ae4fd 0xd828cfb5 0x690b17db + 0xd29ae8bc 0x8fc71289 0xd6fc9cf6 0x61c7a6fc + 0x8e8012d5 0xd3320498 0x36e80084 0x0036d3ab + 0x53141aae 0x987d0cba 0x57581df5 0xace4704c + 0x3ce49642 0x991556c1 0x6cb0b984 0xac15e528 + 0xe7d208ca 0x2486d1c5 0x93b6623e 0x340b7622 + 0xe7e1cf7b 0x3cdeed88 0xa23c849a 0xcc6e8b3b + 0x292add5a 0x17763ee1 0x9f87203e 0x72cf4551 + 0x2053e66f 0x06c3a411 0xb61c2e0c 0xa4a7f3ae + 0x0ff87dbb 0x03999ed8 0x48aacedc 0x2e126ef3 + 0x799441bb 0xaee15b4d 0xea08bf54 0x47248787 + 0xb60afc11 0x8c3d6a20 0x7c04f801 0xb902760e + 0x319040eb 0x370bbd5d 0x9a1dd5e6 0x63f7da1d + 0xb3784eac 0x3b304dea 0x987ada9f 0x2b6b1cda + 0xf9241003 0x0d3d16f2 0x1185dcbf 0x519b7a5f + 0xeb612361 0x28b57da5 0xdeb8419a 0x0ba13122 + 0x062e28fa 0x5ffb9b36 0xb1258247 0x8337401f + 0xed1f6423 0x730cafe6 0xf728c690 0xe40557eb + 0xc4951a15 0x04a988a9 0xbf5fe18c 0x2766e40a + 0xe4d74d13 0x8638d052 0x8eefeaf2 0x9ad07978 + 0x32042a87 0x4385f38d 0xc9b48f02 0x02ab0ae7 + 0x9eaeb632 0xf386c14d 0x8b1c2ab2 0xad432a24 + 0xfc5bd462 0x2d7ac5fe 0x45dff5c6 0xa235e1a6 + 0x825b770c 0x5568471b 0xa7ac3a3a 0xfcc6e40c + 0x0c1be59c 0x77685a3c 0x5b1bafbd 0x40b8a139 + 0x3dd1bf01 0xb6651001 0xf2915a6a 0x16fe1cf2 + 0xe78467d1 0x4bec9fb1 0x88615320 0xa3920831 + 0xed4afac7 0x206cffba 0x96c42567 0xcc2b5215 + 0x7ca0193f 0x0e1a60e5 0xf3892c10 0x2ceee7b2 + 0x110d3311 0x9a322e7e 0x3cb7e5fc 0x3fb971c1 + 0x59971332 0x08386001 0xe4a2444d 0x17d9c47f + 0x9f53c4a5 0xdb54e5c2 0xfaac9f08 0x975c07c6 + 0x8a6e6bcd 0x4392053a 0x6473bef8 0x4b3b91a3 + 0xfb7e8ebc 0x46c6ffed 0x04939839 0x71b93766 + 0x47e4f74a 0x786545c8 0x77f55b59 0xdf8e992d + 0x60a0d2a5 0x6cc8a5cb 0x113ee95c 0xa378558d + 0x5d3b8bd9 0x3c95b2a8 0x6efa3682 0x9535dd34 + 0x3e29974d 0xa477d069 0x2dbf58d2 0x165edae3 + 0xea25d53d 0x44e3ef71 0xba6341cf 0xc61b964c + 0x4612838b 0x62151b9e 0xc1de2511 0xa364130c + 0xa9710643 0x1a436c70 0x97030b09 0x5cef28e0 + 0xd5197e49 0x02b9ffa8 0x1b52dc7b 0x04f9428b + 0x01ebed2a 0x1eaecbee 0xc53c4d54 0x3e34c125 + 0x05b4f37a 0x6e3d042b 0xf1c1f40d 0x39cfe9e1 + 0xd2938e89 0xa14b9846 0xb1333676 0x31068254 + 0x4b627e4b 0xb5185882 0x101b52bc 0x73e05abf + 0x68a4e24c 0x67e301f4 0x6bf8b538 0xc502e1e1 + 0xc3889b5b 0xdfbc6d96 0x4239d0e1 0xbf3667ab + 0xb0c4cb00 0x3efdcffd 0x7cd9661d 0x4f5eca03 + 0x0ef218dd 0x464f0826 0x048fc539 0x6a1c63fe + 0x76cc341a 0x1ae2945c 0x7a339006 0x858fdc20 + 0x2a4a7270 0xd4cbe12c 0x7b27e5d8 0x998cf520 + 0x4795ccf7 0x52e15388 0x86aa7b96 0xff1845fa + 0xd49d1061 0x035b6a80 0x1df18220 0x28fc4fd1 + 0xa8e8f333 0x3a9240a6 0x41a4caca 0xee736b6f + 0xdfa7ce4b 0xd4bf5c0c 0x4e62f6d3 0xe98ae9b4 + 0x7f544550 0x2b0706df 0x8fb2e752 0x546af9d1 + 0x8517758f 0x53f522fc 0x03bd1819 0x6fd264e2 + 0x16839ef8 0x44a1200d 0xcd5a586b 0x1ead251c + 0xf58dd3be 0x80217ce7 0x0367ff42 0x2d8f2ce8 + 0xe8a0a689 0xba33e366 0x5dc7980d 0x005c0eaf + 0xc0c44118 0x5553076a 0xdaf39389 0x703e09eb + 0xc54c8112 0x4a26135c 0x36a46f2b 0xdc93ee12 + 0x7060db72 0x7778befc 0xe028fc55 0x52e86278 + 0xd0b00188 0x6ed5565a 0xb5e2785c 0x3608bffa + 0x55c3f5a3 0xe1e41afa 0x08a227fe 0x94c793ce + 0x650934f7 0xddc36524 0x6dac40de 0x9eec3ceb + 0x8fe3d1cc 0x3cebab86 0x61e4d63a 0x5382ea11 + 0xa90c9495 0x0277ccb3 0x412cecc1 0x5853c945 + 0x97df9a48 0x364d9b10 0x7e8c9bf1 0x6b4974ef + 0xd3dbaeeb 0x6626dd26 0x2b746d2c 0xfb762155 + 0xf942f687 0x1317d1b5 0x0c989def 0x5f4c0ed6 + 0x31aebbd3 0x51cd8d5b 0x3d729511 0xc07c8f23 + 0xa7f3e6f7 0x7683dba9 0x5f051d5c 0x750437f5 + 0x1b9ffe98 0xa4de609b 0x4c498e9a 0x18dfc535 + 0x376c6c34 0x19a57039 0xa70e93eb 0x7e966bc7 + 0xb6e9d77a 0x3ab98e5f 0x1607125e 0xe8845aa3 + 0xa20a2d80 0xb17ac63b 0xa07a9790 0x71e5a14f + 0xb6b5fc78 0x4c610f86 0xb57b21b6 0x1bcfb3ac + 0xbf812998 0xd429986b 0x02b837e9 0x0823aca8 + 0xd8a85194 0x708bad39 0xff94ef19 0xc3599461 + 0xaee622f6 0xa8b5a808 0xf801b298 0x0aeb35b7 + 0x4db4bf27 0xfa31c205 0xa047dc66 0x7e0ae406 + 0x2ceea6cb 0xef0ef96f 0x4cc4fdba 0x6161256f + 0x94505fd1 0xbced5596 0xbf9e36a5 0x271e68bd + 0x7a3308b6 0xef1af50d 0xb55ede06 0x6783e602 + 0x1152acf0 0xdc644ccd 0x1b692da3 0x59f6886b + 0xd7236158 0xe39d75a6 0xe7026697 0x25496283 + 0xb6b0a61c 0x09d0931c 0xe8d459a1 0x1a124097 + 0x88e50621 0xf2ed18ff 0x37681783 0x4afa1ffc + 0x8a96ec4a 0x4474a860 0x274591b1 0x59df3968 + 0x34f56fb9 0xce821f96 0x7ec825b2 0x6ed4a9bf + 0x687253cf 0xa511c1d3 0xaf2bd6f0 0xd1ce1a5c + 0x241dd505 0x39037238 0x0c761934 0x53181db5 + 0x11ad47ec 0x915a527b 0x748bc970 0xeb8f2669 + 0xb8bfd5af 0xd8d19145 0x0361ff58 0x6dc6e2f2 + 0x1fd06556 0x120db4c5 0xbd704c8b 0x70a1a57c + 0x27543851 0x095403a6 0x28171887 0x640e7c92 + 0xb48fd7d1 0x62ad2774 0x224767cd 0x347b8843 + 0x821ca7f3 0xf94749c6 0x2bc7f40f 0x700cc1d8 + 0x50d50832 0xc2f9465c 0xa6e1cbaa 0xe0f5e934 + 0x7f33617f 0x8876cb07 0x408c24fe 0xc0cfcdf7 + 0x39152b72 0xa0ba80ab 0x301a73eb 0x6e704f6c + 0x3b73c24b 0xd433f861 0x43192007 0xa56d2ca4 + 0x2d28bd5d 0x14f4c9cd 0xb7fe189c 0x031e1818 + 0xf8f4133e 0xdc8e7727 0x4f8f5a06 0xe7b114cd + 0x5cb9ff12 0xdb4c5a53 0xed956df5 0xf3634f5f + 0x6cce1cc2 0x5393f9ac 0x1184c2f7 0x0b6fd240 + 0x64771374 0xaafed1a1 0xbdc55bcf 0x976414ef + 0x6a333e56 0x0c5cefb2 0xff2574e0 0x11b059ef + 0xff8b7f2a 0x9651e97b 0x594fe89b 0x7be60f6a + 0x7b7695ac 0x612036f7 0x5be0d4fa 0x25855737 + 0x12e32ee2 0x8e86130f 0x46d75d41 0x3769d438 + 0xd14752d4 0x1612ad6d 0x8f86f2a0 0x63e01251 + 0x9a44ac4a 0x49fdb148 0xe1757062 0x42798804 + 0xf21f46c1 0xed0a3794 0x5528add4 0xeddc0c90 + 0x7f188ce8 0x59568b7a 0x8e25d50f 0x9277c492 + 0x955c6e6a 0x79f94a59 0x3a65fb08 0xceb23267 + 0x7d8dce01 0xd15c492d 0xa35f005c 0x0e7cba9a + 0x950485d9 0x2d92e448 0x4aced016 0x0d10136d + 0x3d2ec365 0xd982e881 0xe81940d2 0xb1a84849 + 0xdb30d967 0x9f51d3d4 0x4fbe18a9 0xef21cd28 + 0x5d3cba6c 0xaa89b02b 0xbe1e9526 0xa20a918e + 0x0c26bd72 0x8372eff8 0xcf7ab414 0x1d3ab83f + 0xfd2c8f79 0x4929f77e 0x2416e8df 0x65dcaaca + 0x58fbf7b3 0x1c4a3089 0x9bfb6e26 0xc7338ac9 + 0x88e5ad26 0xc62bb3d4 0xad6d36f5 0x6445167d + 0xe9de8daf 0xc391c6bc 0xa78b4558 0x0216bcdd + 0xbd4365b9 0xb0a874b2 0xe95e9453 0x77296b9a + 0x49803c1e 0xc01fd0ed 0x165a9d5d 0xf7da6442 + 0x4c00818d 0xaad5bfca 0xdb252937 0x0e4e0f74 + 0x0c2738e8 0xd075b8ba 0xe3b2df11 0x8aee60a4 + 0x36052cd8 0xb4aa190b 0x413e7155 0x3e7e646d + 0x807e6eea 0x97993e6f 0xa5129ff5 0x98e01bca + 0xa8bd70c9 0x8800721e 0xb3407ffa 0x266b2f99 + 0xd9da73ee 0xa06f634a 0xcaae53b1 0xd98e53c6 + 0x49368291 0xc89485fe 0x938a8a29 0xb57f77cc + 0x58c867de 0xcdac8a84 0xf4d57b6f 0xc6daf080 + 0xe3d9c67f 0x0264b194 0xc3b2ca50 0x6d214667 + 0x88503872 0x549ed8cf 0xe827689f 0xcbe94e2e + 0x4a02516d 0x24ddcfa1 0x3cbc736e 0x34c88707 + 0x9f4c9376 0x4ced4d41 0xfdbabfb5 0xafd291d9 + 0x2fa602a3 0x53e19d9c 0x44422427 0xf85e2c53 + 0x40e91ef7 0x02646045 0x3d1fa703 0x1613b99f + 0xa108de10 0xf9cb3d04 0x7b9f9523 0x007d74b1 + 0x961771dc 0x2e49fe1b 0x5fefe27d 0x54737b43 + 0xa11d7c40 0x7f0cc2d9 0x67c6533e 0xd1ab10fa + 0xb1950645 0x536087d2 0xd6937b40 0xc35960c1 + 0x2df0c356 0xecb5ab53 0x61e08998 0x1671bdd0 + 0xd72935b5 0xdf1a9d7c 0x70b1aa4e 0xa9272818 + 0x1f7b8d55 0xc7292a0f 0xda7af847 0x190076ad + 0x58370ba6 0x3020fb4e 0xff8a4b30 0x13818958 + 0x6ba1ca38 0x6a90d39b 0x5e180929 0x206e8a22 + 0x0568f241 0x5f83ad21 0xef05e5c6 0x21d0521c + 0xe7886eff 0x68eebbce 0x550c1659 0xa0843444 + 0x19468c2b 0x539cb9b8 0xa4b18b62 0xdab0680e + 0x1b254dbc 0x47068aaf 0xa8193743 0x44b60b88 + 0x90c07337 0x2e55666a 0x632f4b23 0x68af10db + 0x8e29f54b 0x5f436bcd 0x8bf81d55 0xb640ccc5 + 0x2e4ab6a9 0x198697a5 0x8a1c8481 0x572fb679 + 0x7597c416 0x608fd45e 0x57c8c7f4 0xe151d349 + 0xed9e17bb 0xa66f2816 0x8175fe68 0xd57d91ad + 0x79df0711 0x7a349868 0x13403cd4 0x7d974c60 + 0x8860ce70 0x2e6d62ea 0x8916e2f2 0x0e336838 + 0xf54d382d 0xc4e172c8 0x94bfcfbf 0x5fa53172 + 0x2933cecd 0x4d5b8439 0x0ca0e6e4 0x8ef87b00 + 0x2fdd121c 0x24beae76 0xa85b47f4 0x4e38af2e + 0x12b8734a 0xf698abf4 0xde2c2d93 0xeb100795 + 0x8ab19df8 0x93a6f4d1 0x43c4b2cb 0xbaff7c4a + 0xf52b1471 0x72804f4f 0x0c0ca257 0x1dc24c77 + 0xbad7203b 0x3a998fa0 0x9cb20388 0x7ef1fb3b + 0xbae66020 0x9a22144f 0x39ac47db 0x3f145996 + 0x05a32b6c 0xd201a2ec 0xd868727f 0x08b2df4f + 0x4583bbfa 0x9a422baa 0xa6a2e8f5 0x236310ec + 0x5aafc3cf 0x344156a6 0x6f964ceb 0xed0495ae + 0xb5638c98 0x2c8e84ba 0x63d8c7a5 0xec956b66 + 0x69c54f32 0x767874ec 0xe8fb6ce1 0x68b1c780 + 0xe4b861e4 0x2787cc38 0x4b2202e7 0x23b476be + 0xecdf296f 0x094aa000 0xe95ef073 0x4182ebb5 + 0x30daa31a 0xef68cb68 0x2fbcf6bc 0x21c52620 + 0x19abf83e 0x4de7528c 0x05fe4c05 0x32c2a1e9 + 0x8c23abdb 0xabba9a90 0xa6a215c1 0x891f915c + 0x667cd65a 0xaa5a9b2c 0x689fd1e9 0x42b52c95 + 0xd9872e76 0x05dd5278 0xc19798f7 0x8d031d86 + 0x25690670 0x165f4b19 0x76b51d6f 0x61cd8232 + 0x7b530271 0xa8e9326c 0xd952e94d 0x56a7021b + 0x128be860 0x4da40144 0xeb4ac3d5 0x82b7ff5a + 0xea2abda7 0x690a9ebc 0x33562378 0x6bc91b2f + 0x46134185 0x8fb77fb2 0x029518a2 0xe1fa1f4c + 0xf78783b9 0x5d8ebe63 0x103e8050 0x924085bf + 0x80593f2e 0x5be4bcb6 0xcb935edd 0x882d0a5f + 0x7deb8205 0xcdc0fe2e 0x9c333db4 0x1d0c888d + 0xf8dc3575 0x2f901125 0x6bf48cdb 0x98ab6fb4 + 0x491d7df2 0xa064922e 0xbbb86c70 0x88aad77d + 0xfcff0669 0xb0c47c1c 0x0fcc6fe1 0x50df8a83 + 0x014460e4 0xb014e6ab 0xbeff4bc5 0x8d939fae + 0xd750ae17 0x42dd29c9 0xdb1cbf70 0x82265be9 + 0xd11afd6a 0x21834e1c 0xd11e3c3a 0xbe568139 + 0x6cf92d50 0x9304ebf1 0xf177046b 0xa5b127a5 + 0xfb57e4a7 0xf94291df 0x0f089d58 0x07395b5f + 0xde4ba5b9 0xf7371fc5 0xae44f190 0xd529271d + 0xbcaea246 0xfa777c0b 0xad3bab9f 0x0d6251ec + 0x6f4fa894 0xc39273e2 0x7710fcc3 0x81f08a5d + 0x395b54ee 0x87295638 0x57398bb0 0xfd46c7c9 + 0x3f1dafc6 0x548479b7 0x37c42fba 0xa2130147 + 0x99dc0bb0 0x3596c5cf 0xbcca6bec 0x418735ed + 0xfcd4273d 0xee141135 0x8457cf47 0x95fe7220 + 0x041aaf8a 0x6e947153 0xc963afa7 0x09390a74 + 0xc40dffd3 0x4208039c 0x319b1f84 0x42b6b3b7 + 0xade789da 0x83338c91 0xf2d74712 0xe80011dd + 0xdd61645e 0x286fc63a 0x26e2fb23 0xfef2b4ea + 0x3290efb8 0x595a0c17 0x6cd9bea9 0x7be1338e + 0xe0ff2c09 0x1b93aea5 0xbbd97e91 0x5e1ae1e7 + 0x7c6c078b 0x0b9b3a03 0x43d38011 0x824cd94b + 0x9725170d 0x87ce6f33 0x60525d85 0xc0a5e853 + 0x242e613b 0xebf72857 0xcb500fc6 0x0de5c3f0 + 0x382b625d 0x08840e50 0xcef30663 0x1bc848b6 + 0xefa78141 0x81b860d6 0x4eb125fe 0x7e125296 + 0x276a5558 0x45caa775 0x7c6ec23c 0x5dcddd08 + 0xc41aa32d 0x6a2851b1 0xb69ae1c1 0x8f603c43 + 0x763497f2 0x73344cbd 0xcffd175c 0xfccf5a91 + 0xb2318bf7 0x66ac628f 0xa98fa975 0xb68e5426 + 0x27555715 0x5157a93f 0x666fd404 0xb37fcc40 + 0x563b0512 0xb70f8446 0xe10d257f 0x73793ef2 + 0x31a84915 0xe0de9489 0x08dfa368 0x9169d4fd + 0xc14f5c9a 0x92e6db4f 0xa30b6cec 0xca04670e + 0x8a664367 0xe8984e70 0x1c96a39c 0x655f9abd + 0x6999a190 0x76267621 0x0f49f963 0x8ddad3a1 + 0x51fdab6a 0xaf0d6863 0x23b71bdb 0x32818c8a + 0x6398044d 0x26c60bec 0xb0b631fa 0x938f69c7 + 0x52f11913 0x1e6fbe7a 0x92dcd409 0x419bfeae + 0xb147bb96 0xbac5bf9d 0x08de155a 0xde8ca968 + 0x20aef902 0x62df25a8 0x64a4042f 0xef19da4e + 0xc75fd112 0xc9863e47 0xaccfdbcb 0xd29b6090 + 0x6dc67b4a 0xa84b3cd6 0x45a0e708 0xd28673bd + 0x00bebebe 0xd5e518d7 0xc63d647c 0xa28f5f6d + 0x3372edc8 0xa1c44ed1 0x88e61d44 0x5e095835 + 0x2d8713ce 0x6791a885 0xae89c04a 0xf1dc5105 + 0x6423f3b7 0xf4e2f384 0x2d2761a7 0x38ea905d + 0xa263d776 0xd1936fa6 0x2fc54081 0x429a25c2 + 0x13f6c5df 0xffffa6c1 0xfaf82002 0xe4bbb103 + 0x2fc0c622 0x669ee281 0xec785fda 0x91156b25 + 0xa9f4444e 0x354fdfc2 0x7c5f5069 0x72ae591b + 0x73bfd64e 0x6b96d744 0xf261daaa 0x2de15dae + 0xedaba9c2 0xf287b3fd 0x8b2097b6 0x589934c0 + 0x7edc2a73 0x469b16eb 0x247b9a22 0x8b7e6c7b + 0x3e71ffe2 0x5275f242 0x032a211f 0x977bff60 + 0x4306ad03 0x6a212383 0xceb36448 0xa2a79209 + 0xe3842f42 0xcee0cbe7 0x37cdb626 0x29a0a515 + 0x2857ead6 0x981d5d9b 0xf0ff9b06 0x95de8cad + 0x4dcb565b 0x065d585d 0xe7eb754b 0x278fa774 + 0xe4d8fb7a 0xe152f018 0xfb7bb25e 0x50323b64 + 0xba618e43 0xf8cb1c61 0x1b6dce25 0xb4fc7867 + 0x2a7fb213 0xea9e646e 0x3f9b735b 0x5640315d + 0x0793ba5b 0x71ff31fb 0x4b41f1d6 0xb1538146 + 0x336f4272 0xf176d509 0xb7fc03c5 0xd6a1c927 + 0x56a68c10 0x8b4740cd 0x14c54f8a 0xf07ad8a9 + 0xa8403db8 0x37c23f2b 0xdca69aba 0x4b39ef9d + 0x2af13bdb 0x6baace1f 0x8c7ca0d2 0xba86bd02 + 0x2a74681c 0x5542ae58 0xc36709e2 0x82b34568 + 0x26ea06be 0xd4bf458c 0xde209de7 0xa311b4e5 + 0xdc00e139 0x7d305958 0xc5d76ed7 0x0943a285 + 0x48ce4e29 0xe371bd9a 0xfe6a6501 0x4167d215 + 0x402e47ba 0x588458be 0xbf4bcf37 0xf7fa27a8 + 0xb725f91a 0xc17f5c07 0xce771dbe 0x66f9d592 + 0xe8521ed4 0x42f75171 0x343b3e74 0x2d5448b5 + 0x2d1fca8c 0xd7a32431 0xc29a88d2 0xffb07fd7 + 0xcca0333f 0x43204f2f 0x866c1867 0xcb215814 + 0xfcb67d4f 0x423680be 0xdf22f6d6 0x03373eda + 0x3bd202e3 0xd8972fe3 0xb7733d70 0x7a472c76 + 0x6cc8a627 0x3b27e643 0xa3475f3f 0x87ffb286 + 0xf823d69f 0x6d57c38e 0xa0fd464e 0x53e2e341 + 0xaaab23ef 0x439429ef 0x55ba2a2b 0x4da5ea4c + 0xc1fe05fc 0x874b7a34 0x9a875956 0x713ccc90 + 0x49afcff2 0x5905dc0b 0x1f5dddb7 0x8ef5c1d9 + 0xf60eca50 0x25172569 0x3525639a 0x25804bbe + 0x5729cd49 0x17f84e66 0xc540d86d 0x51524bc9 + 0x9a6e9901 0xf5bcc70e 0xf7a73ffd 0x54509c8f + 0xec58b8a4 0x9993703b 0x6ef45fc4 0x5ce3a507 + 0x1d73c611 0x8780e8ff 0xc7d2e02b 0x0bc825f2 + 0x02f75fca 0xe80c0758 0x24646fe9 0xd378ff5a + 0x592c5619 0x6c80372e 0x1f7351d1 0x4db5182d + 0x3985fdfb 0x16ca9158 0x58ee1ae4 0xaf2b9fa0 + 0xe97f60ce 0xbb911e68 0x01748fa0 0xaef578d3 + 0xc3736418 0x8ab0deb5 0x0de16af1 0xb8369f7b + 0x68e43c12 0x914ca0f6 0xe950ef28 0x834eff90 + 0x51adb952 0xc42ee4ce 0xf70ab4a5 0xbf9fc916 + 0xed9444b1 0x845a6a1e 0xf92e7b64 0xb9ca8a1b + 0xa9cdfcd0 0xb5956bc8 0xb8520e59 0xdde7aa57 + 0xb41d390f 0x364aef3c 0xf39d4482 0x8b4e651e + 0x0b82f5fb 0x7960e81c 0x12ed7b84 0xe9f123ca + 0x88a64db2 0xa0c714cb 0x57b01471 0x80ff31a6 + 0x7571d8cd 0x857035d9 0x0508587c 0x594a4a42 + 0x011503e5 0x27c75e55 0x03264f62 0x9316ed1d + 0x36e5cd1e 0xfa9b23b4 0x5bc8c606 0x0902bd38 + 0xd6745c69 0x6fa73118 0xa50f7b94 0xc529e962 + 0x28738486 0x7b85a599 0x2c495a35 0x85f2cbef + 0xa09dfe51 0x1c763ab2 0x4effdb5c 0x506586f0 + 0xec182a58 0x45293146 0xaf8d78b8 0xa89bd228 + 0xec24826a 0x752cc421 0xbf36aa46 0x6760e225 + 0xe15d0987 0x6fa9bdf3 0x6837c755 0x9426d654 + 0x14b48f5b 0x5d70567d 0x63a14f92 0x809d5361 + 0x3b6e2729 0x84ce5415 0x7eaca6e0 0x9b467302 + 0x8f39d484 0x8e78398c 0x33108b33 0xdc07005c + 0xbdc2500f 0x35f1f452 0x9d254e3d 0xfa61eb21 + 0x2ab6c7aa 0x83561fdc 0x8735d598 0x416e8591 + 0xfe10e93a 0x18da409d 0xab6d0bfd 0x675baaf1 + 0x287fdd24 0x6b50b63c 0x8c08abca 0x871a59c9 + 0x41bb2ae4 0xfba9abdf 0xb46491c7 0x4e433d5a + 0x01e4fbda 0x0bc40399 0x3bdb61c2 0x3cf051ba + 0x910daa46 0x8d4065d6 0x270667eb 0xf6d42459 + 0x01993a1b 0x00a95dda 0x6ed5a693 0xed4fbf7b + 0x24dbb70f 0x67fd62ee 0xcef5f0a4 0x9e65b798 + 0x9a9913fd 0x3d0e7190 0x4265b4e4 0x80bfc46f + 0x6b354d2c 0x2b90a987 0xc989cb75 0x773e6b64 + 0x55325e9f 0x18816a56 0x07413406 0x5177ae31 + 0x24a19ef7 0xdac405a4 0xdca2d3b4 0xab7c7b70 + 0x42b5de0e 0xfcf918a5 0xa54d934b 0xcaa9eab6 + 0x50e63e2a 0x4b168926 0xb2442913 0x594c0f94 + 0xf387f31f 0x4d716749 0xc8433297 0x34c1a5de + 0xe929008e 0x5644251b 0x736476d0 0x0d00aee7 + 0xf20b2f64 0x5e158173 0x9af3e568 0x5f19fa7e + 0xb23b2861 0x8659ee6e 0x94058a64 0x66ec4fb1 + 0x37cd6a4a 0xbd2944fe 0x0ea44ec6 0xe7d64c24 + 0x75a170e3 0xb4a9479c 0x2215716a 0x64a8a574 + 0x257e86ab 0x86bae993 0x3030352b 0x15cb88bc + 0x576363a0 0x61138c36 0x7cc4fe7f 0x648977a8 + 0x0ef71fec 0x1c60df47 0xc75f70ea 0x88509798 + 0x172b407a 0xf888e400 0xef33cd15 0x5976757d + 0xf8cfef13 0xbf024380 0xbb9c1b02 0xe4c38ec9 + 0xf30fce01 0x8efa5213 0xf4b48aad 0xc94c3a37 + 0xeb1bcece 0x09a18b56 0x4e83c0d3 0x6fcf9f77 + 0xf52f4d76 0xf3368a12 0x33b2797f 0x627b6e41 + 0xefd05154 0xa83ae2a0 0xea211129 0xd25723d5 + 0x7bbb0e3b 0x7131f088 0x5dd5193f 0xef5aa905 + 0x39f77be7 0xa21b48c1 0x1ded01c1 0x5cf98c5f + 0x6e23d207 0xd7e7dadf 0x5932ed1a 0x2a729061 + 0x29a89f4a 0xac0e8447 0x01ff4205 0x8b1456c6 + 0x3fba0156 0x658c03f7 0x5c69f968 0xf6570582 + 0x21bb0145 0x8683bf5b 0xa4b6eba5 0x4ccfe5cb + 0xd202898c 0xbd2411cc 0xc2fc702a 0x5c39b695 + 0x87584ccf 0xeae3c735 0xc472b6f9 0x4249f637 + 0x3fa89c0e 0xce5a8bd7 0xbb28138b 0xc080ecb1 + 0x9cbf1916 0xd70424e9 0x75cc4ed1 0xa575f3e9 + 0x1c571f68 0xe2906205 0xc26520cf 0xf9c1fc8e + 0x61c982de 0x1af6cfcc 0xaf397c9a 0x46830771 + 0x623d98bb 0xda7b52fa 0x5a3c57d3 0xfa35d2f0 + 0x4783df19 0x6ad07325 0x487406f4 0x3fae5152 + 0x189137cb 0xd98a644e 0x17ffe880 0xeb6aa9f7 + 0x67184e3e 0xe475734b 0x0f1113c2 0x39a4df47 + 0xbf8f6ec9 0xe13a4d8b 0x63ec02f5 0xdfe7d75d + 0x1379034c 0x5db7314a 0xa9d9ad3e 0xfaaed8f2 + 0xf0fb6074 0x12f27b84 0xc97a92bb 0xae5e3bb7 + 0x5f7fc2bf 0x00cbc1f7 0x9360a4d9 0x3632ba04 + 0xad044c83 0xeda13ec1 0x34a214c0 0xcf9c972a + 0x96352243 0xf1a35357 0x2d77bc30 0x8485bbad + 0x67fbaa99 0x8035b1a5 0x8ca763c0 0x109d7887 + 0xa1c35cd8 0xdc79e308 0x4495404d 0x64419226 + 0xacdcea08 0x9545c0ef 0x5493e09e 0x7fe16336 + 0x41381aa2 0x5c344f46 0xb40cab9f 0xc43951c4 + 0xd86e52a5 0xb141d934 0xd78efcff 0xf37ec320 + 0xc184a45b 0xf4a57954 0xc8aed0bd 0xe602c15a + 0x71a6b48b 0xce837428 0x02733706 0xc4a4a044 + 0xa75efb97 0xcb63d62e 0xd0580b5a 0xce499087 + 0xc12bf4ca 0x9c995345 0x1d8adfbc 0xe62fd60e + 0xccbf5412 0x6161f8d0 0x64268e34 0x565d066b + 0x1896b63f 0x838f8f2a 0x1e314a00 0xac470276 + 0x1879cfdf 0x4702d7f9 0x83b4d777 0x81fcb068 + 0x1b6da94d 0xd075ed01 0x3c7734e8 0x56389a0b + 0x0743b9cd 0xb6b0bf0d 0x63107ab9 0x193172bc + 0xc7b84c8e 0x982ce2aa 0xb8e387a6 0xc264a4b0 + 0x2ac6c802 0xb89ea335 0x052332a4 0x49932ecc + 0xb940f808 0xa7a09330 0x19f3f49d 0x7aef6b5a + 0x201d8ed0 0xf29aac4b 0x8ae2ac0f 0x998c1ca7 + 0x665c3927 0xab4ef641 0xf136710d 0x9644ee9b + 0x34efae96 0x4c596035 0x8cfe8b3b 0x5d9f742e + 0xab2c63ca 0x017d864d 0xd0604d6e 0xab24eee0 + 0x75916a9a 0xad0d1167 0xbeb47775 0x6ac822d1 + 0x776907aa 0x9e9377f2 0x438c5d81 0xd70e9964 + 0x1c09c914 0xab90e5cf 0x31cee523 0x26ba6ea7 + 0xef00781d 0x622b886d 0x36a54031 0x88b1221c + 0x666333f5 0x60e1c93e 0x5e4d0e0a 0x3ee6ff69 + 0xceb4c76b 0xa5deb4f8 0x0668ced8 0x30225378 + 0x6697cf37 0xc5d9661d 0x089eab85 0x7684a876 + 0x018a81af 0x221a7fb2 0x31d80de0 0x9f18ae90 + 0xa29c9af0 0xc3e2b00f 0xda0edbab 0x7ee9cd2a + 0x3ab0f88e 0x02c58228 0x606fa7aa 0x7776cb0a + 0x4e8ad99c 0x3b527469 0x58123d62 0x4ce428d2 + 0xee91a210 0x466ba2cc 0x043c57b9 0xaf7bdd43 + 0x98e76fee 0x8f3eac1b 0x00dffd6c 0x6fcb1c6a + 0x5cb90573 0x485d4505 0x0df5418a 0x26eafe35 + 0x0faddf3e 0x4e972930 0xe113c823 0xe45944d1 + 0xa646077f 0xc1708ae5 0x6ba07c20 0xc7e4e234 + 0xc6754ed5 0xbd6e85aa 0x8cc1756e 0x02afda29 + 0x72809597 0x75b6f5a1 0x61141874 0x1774047f + 0x7a10afed 0xfac2c4ad 0x42cf5c99 0x24f0350e + 0x042f2864 0xfab55b67 0xc8ead5bc 0x914e9512 + 0x77c8ef6b 0x8369aeb1 0x71bc947f 0x0c6b49d8 + 0x8ddd0513 0x028ad10d 0x99a1b28f 0xe6cfbdc8 + 0x7978b4a6 0x3ebbade8 0x9985f5cf 0x431f42f1 + 0x004372b2 0x18b67f68 0x20111c21 0xbb6f77ff + 0x1783b030 0xa045d7d1 0x0e9c7e09 0x3ccbd95f + 0x0b84a2ed 0xf0ee3325 0x63f2e126 0x5ec4c67b + 0x2ca782cc 0xcaf20d04 0x8b59d515 0x3212aa33 + 0x335ca0c3 0x6f9e0cdd 0x4d4bf189 0x44d2fa0c + 0x5abe9396 0x492794ee 0x10dcfcb1 0x9acda9bd + 0xe8aa2803 0x3f1b9605 0x3e2ecb5a 0x971bfa8a + 0xcbf141d2 0x0afafe10 0x2fc906a6 0xefad20c0 + 0x9e922581 0xe69142cc 0xc9c0ba82 0xc069e640 + 0xb99c08b6 0x4b62ca1f 0xf3c5767a 0x6ab088c7 + 0x8f0f0c0b 0x6726f64a 0x9711a3cd 0x46462571 + 0x3a58350e 0xa2561911 0xe24dfdfe 0x97443fdc + 0xf80540be 0x069978bf 0xb38a359b 0x8e574f62 + 0x69aea75c 0xdc753fcb 0x2a74002c 0xced027b4 + 0xda993254 0x03409b83 0xf827331d 0x75fb3271 + 0x01ad839d 0x68520842 0xca65c45c 0x1a3db5a0 + 0x91d37dd3 0x6168c0fb 0x935f5a08 0x002007c3 + 0x42eb4760 0xdab3a804 0x72a6297e 0x905c32d9 + 0x81abcfa9 0x1b21d04a 0x5a1289ae 0x424e7183 + 0xc207906c 0x31fe9134 0x5eb2e5af 0xc9253fc7 + 0xc32be24f 0xe5474cbd 0xeff6e1b0 0x710e5e69 + 0xe6c4c538 0x96b5f1de 0x2abc9c35 0xddbd1a92 + 0x8aca40d7 0xe359c238 0x954718f4 0x18b157e5 + 0xeeed790e 0x6948a963 0x24e70bfb 0x4d681547 + 0xf68369a7 0x5b54409a 0x1f0b787a 0xc2610047 + 0x0f8bd269 0xd7c8c154 0x9dee62d9 0xd4738ed8 + 0x1a66c6b1 0x5bad5a5b 0xb110311a 0xfaec6802 + 0x6b750f2d 0xcbf8d0e0 0x11edaf4b 0xf64a07bb + 0x422e7c15 0xb1732663 0x1ff404f0 0x2d5052b0 + 0x6e45356c 0x7e2201e8 0x7c5ebcd1 0x1cb4425a + 0xb1539a64 0xa2e4459f 0xcf1ade8a 0xfc476473 + 0xf4147deb 0x2afbdd77 0xff01fabc 0x6597408a + 0x0951220b 0x6750f3ec 0x0a242763 0xf3d71c05 + 0x84cb1c26 0xdb7a81bd 0x7aea1a5d 0x7e719a48 + 0xc5c12fe1 0x0ce2e988 0x29ecc6f0 0x5ede901a + 0xda8399b1 0x31c05d6b 0xe1956aff 0x59ed7c3d + 0x60832637 0x9bcb7cac 0x63c530d1 0x14c677de + 0x9225ed18 0x065327c9 0xd1ff6a0e 0x5516517e + 0x53c6f5c2 0xed5983cf 0xaa1d18b9 0xbe300d7f + 0xadc525a7 0x07ea81b6 0xfc517a09 0x4ead3f86 + 0x45435f41 0x2efa58df 0x02348ebc 0x30ed6783 + 0x190b4fb9 0x85c55d6e 0xc9ed8896 0x416ee113 + 0x9b3536d9 0x30577cc0 0xbc4b88c8 0xcda59612 + 0xdfe2bd89 0xd60cde71 0x98843881 0xcc1f32f2 + 0x18b3f643 0x671a14ca 0xd6482a47 0xac6a7d38 + 0x1897da16 0x91b6fcb3 0xf199bb35 0xd38c00ba + 0xa8c946b6 0x52a1ad37 0xd38ed2d4 0xa1d6f81d + 0x5af6865b 0xebdb858f 0xb844b110 0x53201ea2 + 0x08870945 0x10c869de 0x19849613 0xdb35d3ed + 0xd68ebd6e 0x1056fd48 0xf1a0e305 0xe3982ebd + 0x6f7cc391 0x5956374a 0xf414a5a2 0x325119ab + 0x99ee1f96 0x6f044bd9 0x8374805b 0xb55c366c + 0xa2c77051 0x68f199e5 0xd36a9714 0x878f847b + 0xec0394ae 0x86d0584b 0xf4df66b9 0x451cd039 + 0xf4de06ae 0x35dd0554 0x818a342f 0xeefdbfc9 + 0x5b4e9edd 0x22d9313a 0x3b710d60 0x6deaeb4c + 0xa9e26512 0x98d31867 0x3c2c2d61 0x7eb5ce41 + 0x40890db6 0x7a3aa660 0x3ef4f306 0x7322881f + 0x49dac4d5 0x96efe685 0x27bb7f49 0xbb955283 + 0x79c5f2b7 0xff599c28 0x28ee7f5e 0x9f324b73 + 0x45edb7cf 0x39a8b79c 0xd0919c6e 0xe149b29d + 0x62f5f82e 0xebcfa23e 0xd4d68937 0x54270090 + 0x958af0d4 0xa1e4e799 0xaf68ac19 0x82a84f4e + 0x50f67b84 0xd5e59629 0xf5fdf24c 0xab1d63c5 + 0x30835807 0x431fce5f 0xe5f96f4d 0x3f6b4802 + 0x14010be8 0xdca45ae5 0xc82709af 0xff76ce2c + 0x8b222c22 0x73a2d948 0xa8d59cea 0x8c31849e + 0x469c2e5f 0x3777ee84 0x5fdfa5da 0x02ef9bb2 + 0x792d3194 0xbed63f21 0x0b6dc5f1 0xc9d7fe08 + 0x6df7883d 0x366566cf 0xef772769 0x37826465 + 0x1cdc3086 0xa69ff7b6 0x235012ea 0x292f7e75 + 0x30bdd0fd 0xffdc9df1 0x95c6d570 0xec206204 + 0xc6cd42cb 0xc0d6dfd9 0xb7a16b71 0x17fa527e + 0x295f2c79 0x990f9820 0x8b8f447d 0x193f9ad1 + 0xebddb2af 0x5dd532eb 0xf1bbd8e8 0x3444a3f4 + 0x18ccce93 0x05edeb4f 0xc4a6b935 0xba37aab0 + 0x96076ba4 0x250dc2f7 0xc4093548 0x030e777d + 0x7ea40933 0x8da7b1dd 0x59c0b79f 0x807d437c + 0xf5233ddf 0x54c1983f 0xfc18771b 0xe74b85f0 + 0xdbd725b5 0x70cdd153 0x4ffe300c 0xfda4bdae + 0xf4ac75d2 0x91c4e15a 0x34d92b97 0x16356a79 + >; -- cgit v0.10.2 From 8e0df066ffc40fde4cf43014114f8e472b8b9bd6 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:23 -0700 Subject: x86: ivybridge: Add early init for PCH devices Many PCH devices are hard-coded to a particular PCI address. Set these up early in case they are needed. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index 74f01e8..e5c0751 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -6,6 +6,7 @@ obj-y += car.o obj-y += cpu.o +obj-y += early_init.o obj-y += lpc.o obj-y += microcode_intel.o obj-y += pci.o diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index 0aca2f0..d5be2f5 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -4,6 +4,7 @@ * Graeme Russ, graeme.russ@gmail.com. * * Some portions from coreboot src/mainboard/google/link/romstage.c + * and src/cpu/intel/model_206ax/bootblock.c * Copyright (C) 2007-2010 coresystems GmbH * Copyright (C) 2011 Google Inc. * @@ -23,6 +24,7 @@ #include #include #include +#include DECLARE_GLOBAL_DATA_PTR; @@ -180,6 +182,83 @@ int arch_cpu_init(void) return 0; } +static int enable_smbus(void) +{ + pci_dev_t dev; + uint16_t value; + + /* Set the SMBus device statically. */ + dev = PCI_BDF(0x0, 0x1f, 0x3); + + /* Check to make sure we've got the right device. */ + value = pci_read_config16(dev, 0x0); + if (value != 0x8086) { + printf("SMBus controller not found\n"); + return -ENOSYS; + } + + /* Set SMBus I/O base. */ + pci_write_config32(dev, SMB_BASE, + SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO); + + /* Set SMBus enable. */ + pci_write_config8(dev, HOSTC, HST_EN); + + /* Set SMBus I/O space enable. */ + pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO); + + /* Disable interrupt generation. */ + outb(0, SMBUS_IO_BASE + SMBHSTCTL); + + /* Clear any lingering errors, so transactions can run. */ + outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT); + debug("SMBus controller enabled\n"); + + return 0; +} + +#define PCH_EHCI0_TEMP_BAR0 0xe8000000 +#define PCH_EHCI1_TEMP_BAR0 0xe8000400 +#define PCH_XHCI_TEMP_BAR0 0xe8001000 + +/* + * Setup USB controller MMIO BAR to prevent the reference code from + * resetting the controller. + * + * The BAR will be re-assigned during device enumeration so these are only + * temporary. + * + * This is used to speed up the resume path. + */ +static void enable_usb_bar(void) +{ + pci_dev_t usb0 = PCH_EHCI1_DEV; + pci_dev_t usb1 = PCH_EHCI2_DEV; + pci_dev_t usb3 = PCH_XHCI_DEV; + u32 cmd; + + /* USB Controller 1 */ + pci_write_config32(usb0, PCI_BASE_ADDRESS_0, + PCH_EHCI0_TEMP_BAR0); + cmd = pci_read_config32(usb0, PCI_COMMAND); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(usb0, PCI_COMMAND, cmd); + + /* USB Controller 1 */ + pci_write_config32(usb1, PCI_BASE_ADDRESS_0, + PCH_EHCI1_TEMP_BAR0); + cmd = pci_read_config32(usb1, PCI_COMMAND); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(usb1, PCI_COMMAND, cmd); + + /* USB3 Controller */ + pci_write_config32(usb3, PCI_BASE_ADDRESS_0, + PCH_XHCI_TEMP_BAR0); + cmd = pci_read_config32(usb3, PCI_COMMAND); + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config32(usb3, PCI_COMMAND, cmd); +} + static int report_bist_failure(void) { if (gd->arch.bist != 0) { @@ -192,8 +271,11 @@ static int report_bist_failure(void) int print_cpuinfo(void) { + enum pei_boot_mode_t boot_mode = PEI_BOOT_NONE; char processor_name[CPU_MAX_NAME_LEN]; const char *name; + uint32_t pm1_cnt; + uint16_t pm1_sts; int ret; /* Halt if there was a built in self test failure */ @@ -205,9 +287,68 @@ int print_cpuinfo(void) if (ret && ret != -ENOENT && ret != -EEXIST) return ret; + /* Enable upper 128bytes of CMOS */ + writel(1 << 2, RCB_REG(RC)); + + /* TODO: cmos_post_init() */ + if (readl(MCHBAR_REG(SSKPD)) == 0xCAFE) { + debug("soft reset detected\n"); + boot_mode = PEI_BOOT_SOFT_RESET; + + /* System is not happy after keyboard reset... */ + debug("Issuing CF9 warm reset\n"); + outb(0x6, 0xcf9); + cpu_hlt(); + } + + /* Early chipset init required before RAM init can work */ + sandybridge_early_init(SANDYBRIDGE_MOBILE); + + /* Check PM1_STS[15] to see if we are waking from Sx */ + pm1_sts = inw(DEFAULT_PMBASE + PM1_STS); + + /* Read PM1_CNT[12:10] to determine which Sx state */ + pm1_cnt = inl(DEFAULT_PMBASE + PM1_CNT); + + if ((pm1_sts & WAK_STS) && ((pm1_cnt >> 10) & 7) == 5) { +#if CONFIG_HAVE_ACPI_RESUME + debug("Resume from S3 detected.\n"); + boot_mode = PEI_BOOT_RESUME; + /* Clear SLP_TYPE. This will break stage2 but + * we care for that when we get there. + */ + outl(pm1_cnt & ~(7 << 10), DEFAULT_PMBASE + PM1_CNT); +#else + debug("Resume from S3 detected, but disabled.\n"); +#endif + } else { + /* + * TODO: An indication of life might be possible here (e.g. + * keyboard light) + */ + } + post_code(POST_EARLY_INIT); + + /* Enable SPD ROMs and DDR-III DRAM */ + ret = enable_smbus(); + if (ret) + return ret; + + /* Prepare USB controller early in S3 resume */ + if (boot_mode == PEI_BOOT_RESUME) + enable_usb_bar(); + + gd->arch.pei_boot_mode = boot_mode; + + /* TODO: Move this to the board or driver */ + pci_write_config32(PCH_LPC_DEV, GPIO_BASE, DEFAULT_GPIOBASE | 1); + pci_write_config32(PCH_LPC_DEV, GPIO_CNTL, 0x10); + /* Print processor name */ name = cpu_get_name(processor_name); printf("CPU: %s\n", name); + post_code(POST_CPU_INFO); + return 0; } diff --git a/arch/x86/cpu/ivybridge/early_init.c b/arch/x86/cpu/ivybridge/early_init.c new file mode 100644 index 0000000..eb8f613 --- /dev/null +++ b/arch/x86/cpu/ivybridge/early_init.c @@ -0,0 +1,145 @@ +/* + * From Coreboot + * + * Copyright (C) 2007-2010 coresystems GmbH + * Copyright (C) 2011 Google Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +static void sandybridge_setup_bars(pci_dev_t pch_dev, pci_dev_t lpc_dev) +{ + /* Setting up Southbridge. In the northbridge code. */ + debug("Setting up static southbridge registers\n"); + pci_write_config32(lpc_dev, PCH_RCBA_BASE, DEFAULT_RCBA | 1); + + pci_write_config32(lpc_dev, PMBASE, DEFAULT_PMBASE | 1); + pci_write_config8(lpc_dev, ACPI_CNTL, 0x80); /* Enable ACPI BAR */ + + debug("Disabling watchdog reboot\n"); + setbits_le32(RCB_REG(GCS), 1 >> 5); /* No reset */ + outw(1 << 11, DEFAULT_PMBASE | 0x60 | 0x08); /* halt timer */ + + /* Set up all hardcoded northbridge BARs */ + debug("Setting up static registers\n"); + pci_write_config32(pch_dev, EPBAR, DEFAULT_EPBAR | 1); + pci_write_config32(pch_dev, EPBAR + 4, (0LL + DEFAULT_EPBAR) >> 32); + pci_write_config32(pch_dev, MCHBAR, DEFAULT_MCHBAR | 1); + pci_write_config32(pch_dev, MCHBAR + 4, (0LL + DEFAULT_MCHBAR) >> 32); + /* 64MB - busses 0-63 */ + pci_write_config32(pch_dev, PCIEXBAR, DEFAULT_PCIEXBAR | 5); + pci_write_config32(pch_dev, PCIEXBAR + 4, + (0LL + DEFAULT_PCIEXBAR) >> 32); + pci_write_config32(pch_dev, DMIBAR, DEFAULT_DMIBAR | 1); + pci_write_config32(pch_dev, DMIBAR + 4, (0LL + DEFAULT_DMIBAR) >> 32); + + /* Set C0000-FFFFF to access RAM on both reads and writes */ + pci_write_config8(pch_dev, PAM0, 0x30); + pci_write_config8(pch_dev, PAM1, 0x33); + pci_write_config8(pch_dev, PAM2, 0x33); + pci_write_config8(pch_dev, PAM3, 0x33); + pci_write_config8(pch_dev, PAM4, 0x33); + pci_write_config8(pch_dev, PAM5, 0x33); + pci_write_config8(pch_dev, PAM6, 0x33); +} + +static void sandybridge_setup_graphics(pci_dev_t pch_dev, pci_dev_t video_dev) +{ + u32 reg32; + u16 reg16; + u8 reg8; + + reg16 = pci_read_config16(video_dev, PCI_DEVICE_ID); + switch (reg16) { + case 0x0102: /* GT1 Desktop */ + case 0x0106: /* GT1 Mobile */ + case 0x010a: /* GT1 Server */ + case 0x0112: /* GT2 Desktop */ + case 0x0116: /* GT2 Mobile */ + case 0x0122: /* GT2 Desktop >=1.3GHz */ + case 0x0126: /* GT2 Mobile >=1.3GHz */ + case 0x0156: /* IvyBridge */ + case 0x0166: /* IvyBridge */ + break; + default: + debug("Graphics not supported by this CPU/chipset\n"); + return; + } + + debug("Initialising Graphics\n"); + + /* Setup IGD memory by setting GGC[7:3] = 1 for 32MB */ + reg16 = pci_read_config16(pch_dev, GGC); + reg16 &= ~0x00f8; + reg16 |= 1 << 3; + /* Program GTT memory by setting GGC[9:8] = 2MB */ + reg16 &= ~0x0300; + reg16 |= 2 << 8; + /* Enable VGA decode */ + reg16 &= ~0x0002; + pci_write_config16(pch_dev, GGC, reg16); + + /* Enable 256MB aperture */ + reg8 = pci_read_config8(video_dev, MSAC); + reg8 &= ~0x06; + reg8 |= 0x02; + pci_write_config8(video_dev, MSAC, reg8); + + /* Erratum workarounds */ + reg32 = readl(MCHBAR_REG(0x5f00)); + reg32 |= (1 << 9) | (1 << 10); + writel(reg32, MCHBAR_REG(0x5f00)); + + /* Enable SA Clock Gating */ + reg32 = readl(MCHBAR_REG(0x5f00)); + writel(reg32 | 1, MCHBAR_REG(0x5f00)); + + /* GPU RC6 workaround for sighting 366252 */ + reg32 = readl(MCHBAR_REG(0x5d14)); + reg32 |= (1 << 31); + writel(reg32, MCHBAR_REG(0x5d14)); + + /* VLW */ + reg32 = readl(MCHBAR_REG(0x6120)); + reg32 &= ~(1 << 0); + writel(reg32, MCHBAR_REG(0x6120)); + + reg32 = readl(MCHBAR_REG(0x5418)); + reg32 |= (1 << 4) | (1 << 5); + writel(reg32, MCHBAR_REG(0x5418)); +} + +void sandybridge_early_init(int chipset_type) +{ + pci_dev_t pch_dev = PCH_DEV; + pci_dev_t video_dev = PCH_VIDEO_DEV; + pci_dev_t lpc_dev = PCH_LPC_DEV; + u32 capid0_a; + u8 reg8; + + /* Device ID Override Enable should be done very early */ + capid0_a = pci_read_config32(pch_dev, 0xe4); + if (capid0_a & (1 << 10)) { + reg8 = pci_read_config8(pch_dev, 0xf3); + reg8 &= ~7; /* Clear 2:0 */ + + if (chipset_type == SANDYBRIDGE_MOBILE) + reg8 |= 1; /* Set bit 0 */ + + pci_write_config8(pch_dev, 0xf3, reg8); + } + + /* Setup all BARs required for early PCIe and raminit */ + sandybridge_setup_bars(pch_dev, lpc_dev); + + /* Device Enable */ + pci_write_config32(pch_dev, DEVEN, DEVEN_HOST | DEVEN_IGD); + + sandybridge_setup_graphics(pch_dev, video_dev); +} diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h index c572f76..290a737 100644 --- a/arch/x86/include/asm/arch-ivybridge/pch.h +++ b/arch/x86/include/asm/arch-ivybridge/pch.h @@ -14,9 +14,30 @@ #include +#define DEFAULT_GPIOBASE 0x0480 +#define DEFAULT_PMBASE 0x0500 + +#define SMBUS_IO_BASE 0x0400 + +#define PCH_EHCI1_DEV PCI_BDF(0, 0x1d, 0) +#define PCH_EHCI2_DEV PCI_BDF(0, 0x1a, 0) +#define PCH_XHCI_DEV PCI_BDF(0, 0x14, 0) +#define PCH_ME_DEV PCI_BDF(0, 0x16, 0) +#define PCH_PCIE_DEV_SLOT 28 + +#define PCH_DEV PCI_BDF(0, 0, 0) +#define PCH_VIDEO_DEV PCI_BDF(0, 2, 0) + /* PCI Configuration Space (D31:F0): LPC */ #define PCH_LPC_DEV PCI_BDF(0, 0x1f, 0) +#define PMBASE 0x40 +#define ACPI_CNTL 0x44 +#define BIOS_CNTL 0xDC +#define GPIO_BASE 0x48 /* LPC GPIO Base Address Register */ +#define GPIO_CNTL 0x4C /* LPC GPIO Control Register */ +#define GPIO_ROUT 0xb8 + #define LPC_IO_DEC 0x80 /* IO Decode Ranges Register */ #define LPC_EN 0x82 /* LPC IF Enables Register */ #define CNF2_LPC_EN (1 << 13) /* 0x4e/0x4f */ @@ -35,9 +56,35 @@ #define LPC_GEN4_DEC 0x90 /* LPC IF Generic Decode Range 4 */ #define LPC_GENX_DEC(x) (0x84 + 4 * (x)) -#define DEFAULT_RCBA 0xfed1c000 +/* PCI Configuration Space (D31:F3): SMBus */ +#define PCH_SMBUS_DEV PCI_BDF(0, 0x1f, 3) +#define SMB_BASE 0x20 +#define HOSTC 0x40 +#define SMB_RCV_SLVA 0x09 + +/* HOSTC bits */ +#define I2C_EN (1 << 2) +#define SMB_SMI_EN (1 << 1) +#define HST_EN (1 << 0) + +/* SMBus I/O bits. */ +#define SMBHSTSTAT 0x0 +#define SMBHSTCTL 0x2 +#define SMBHSTCMD 0x3 +#define SMBXMITADD 0x4 +#define SMBHSTDAT0 0x5 +#define SMBHSTDAT1 0x6 +#define SMBBLKDAT 0x7 +#define SMBTRNSADD 0x9 +#define SMBSLVDATA 0xa +#define SMLINK_PIN_CTL 0xe +#define SMBUS_PIN_CTL 0xf + +#define SMBUS_TIMEOUT (10 * 1000 * 100) + /* Root Complex Register Block */ +#define DEFAULT_RCBA 0xfed1c000 #define RCB_REG(reg) (DEFAULT_RCBA + (reg)) #define PCH_RCBA_BASE 0xf0 @@ -95,6 +142,78 @@ #define FD2 0x3428 /* 32bit */ #define CG 0x341c /* 32bit */ +/* ICH7 PMBASE */ +#define PM1_STS 0x00 +#define WAK_STS (1 << 15) +#define PCIEXPWAK_STS (1 << 14) +#define PRBTNOR_STS (1 << 11) +#define RTC_STS (1 << 10) +#define PWRBTN_STS (1 << 8) +#define GBL_STS (1 << 5) +#define BM_STS (1 << 4) +#define TMROF_STS (1 << 0) +#define PM1_EN 0x02 +#define PCIEXPWAK_DIS (1 << 14) +#define RTC_EN (1 << 10) +#define PWRBTN_EN (1 << 8) +#define GBL_EN (1 << 5) +#define TMROF_EN (1 << 0) +#define PM1_CNT 0x04 +#define SLP_EN (1 << 13) +#define SLP_TYP (7 << 10) +#define SLP_TYP_S0 0 +#define SLP_TYP_S1 1 +#define SLP_TYP_S3 5 +#define SLP_TYP_S4 6 +#define SLP_TYP_S5 7 +#define GBL_RLS (1 << 2) +#define BM_RLD (1 << 1) +#define SCI_EN (1 << 0) +#define PM1_TMR 0x08 +#define PROC_CNT 0x10 +#define LV2 0x14 +#define LV3 0x15 +#define LV4 0x16 +#define PM2_CNT 0x50 /* mobile only */ +#define GPE0_STS 0x20 +#define PME_B0_STS (1 << 13) +#define PME_STS (1 << 11) +#define BATLOW_STS (1 << 10) +#define PCI_EXP_STS (1 << 9) +#define RI_STS (1 << 8) +#define SMB_WAK_STS (1 << 7) +#define TCOSCI_STS (1 << 6) +#define SWGPE_STS (1 << 2) +#define HOT_PLUG_STS (1 << 1) +#define GPE0_EN 0x28 +#define PME_B0_EN (1 << 13) +#define PME_EN (1 << 11) +#define TCOSCI_EN (1 << 6) +#define SMI_EN 0x30 +#define INTEL_USB2_EN (1 << 18) /* Intel-Specific USB2 SMI logic */ +#define LEGACY_USB2_EN (1 << 17) /* Legacy USB2 SMI logic */ +#define PERIODIC_EN (1 << 14) /* SMI on PERIODIC_STS in SMI_STS */ +#define TCO_EN (1 << 13) /* Enable TCO Logic (BIOSWE et al) */ +#define MCSMI_EN (1 << 11) /* Trap microcontroller range access */ +#define BIOS_RLS (1 << 7) /* asserts SCI on bit set */ +#define SWSMI_TMR_EN (1 << 6) /* start software smi timer on bit set */ +#define APMC_EN (1 << 5) /* Writes to APM_CNT cause SMI# */ +#define SLP_SMI_EN (1 << 4) /* Write SLP_EN in PM1_CNT asserts SMI# */ +#define LEGACY_USB_EN (1 << 3) /* Legacy USB circuit SMI logic */ +#define BIOS_EN (1 << 2) /* Assert SMI# on setting GBL_RLS bit */ +#define EOS (1 << 1) /* End of SMI (deassert SMI#) */ +#define GBL_SMI_EN (1 << 0) /* SMI# generation at all? */ +#define SMI_STS 0x34 +#define ALT_GP_SMI_EN 0x38 +#define ALT_GP_SMI_STS 0x3a +#define GPE_CNTL 0x42 +#define DEVACT_STS 0x44 +#define SS_CNT 0x50 +#define C3_RES 0x54 +#define TCO1_STS 0x64 +#define DMISCI_STS (1 << 9) +#define TCO2_STS 0x66 + /** * lpc_early_init() - set up LPC serial ports and other early things * diff --git a/arch/x86/include/asm/arch-ivybridge/sandybridge.h b/arch/x86/include/asm/arch-ivybridge/sandybridge.h new file mode 100644 index 0000000..a1072f2 --- /dev/null +++ b/arch/x86/include/asm/arch-ivybridge/sandybridge.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * From Coreboot file of the same name + * + * Copyright (C) 2007-2008 coresystems GmbH + * Copyright (C) 2011 Google Inc. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ACH_ASM_SANDYBRIDGE_H +#define _ACH_ASM_SANDYBRIDGE_H + +/* Chipset types */ +#define SANDYBRIDGE_MOBILE 0 +#define SANDYBRIDGE_DESKTOP 1 +#define SANDYBRIDGE_SERVER 2 + +/* Device ID for SandyBridge and IvyBridge */ +#define BASE_REV_SNB 0x00 +#define BASE_REV_IVB 0x50 +#define BASE_REV_MASK 0x50 + +/* SandyBridge CPU stepping */ +#define SNB_STEP_D0 (BASE_REV_SNB + 5) /* Also J0 */ +#define SNB_STEP_D1 (BASE_REV_SNB + 6) +#define SNB_STEP_D2 (BASE_REV_SNB + 7) /* Also J1/Q0 */ + +/* IvyBridge CPU stepping */ +#define IVB_STEP_A0 (BASE_REV_IVB + 0) +#define IVB_STEP_B0 (BASE_REV_IVB + 2) +#define IVB_STEP_C0 (BASE_REV_IVB + 4) +#define IVB_STEP_K0 (BASE_REV_IVB + 5) +#define IVB_STEP_D0 (BASE_REV_IVB + 6) + +/* Intel Enhanced Debug region must be 4MB */ +#define IED_SIZE 0x400000 + +/* Northbridge BARs */ +#define DEFAULT_MCHBAR 0xfed10000 /* 16 KB */ +#define DEFAULT_DMIBAR 0xfed18000 /* 4 KB */ +#define DEFAULT_EPBAR 0xfed19000 /* 4 KB */ +#define DEFAULT_RCBABASE 0xfed1c000 +/* 4 KB per PCIe device */ +#define DEFAULT_PCIEXBAR CONFIG_MMCONF_BASE_ADDRESS + +/* Device 0:0.0 PCI configuration space (Host Bridge) */ +#define EPBAR 0x40 +#define MCHBAR 0x48 +#define PCIEXBAR 0x60 +#define DMIBAR 0x68 +#define X60BAR 0x60 + +#define GGC 0x50 /* GMCH Graphics Control */ + +#define DEVEN 0x54 /* Device Enable */ +#define DEVEN_PEG60 (1 << 13) +#define DEVEN_IGD (1 << 4) +#define DEVEN_PEG10 (1 << 3) +#define DEVEN_PEG11 (1 << 2) +#define DEVEN_PEG12 (1 << 1) +#define DEVEN_HOST (1 << 0) + +#define PAM0 0x80 +#define PAM1 0x81 +#define PAM2 0x82 +#define PAM3 0x83 +#define PAM4 0x84 +#define PAM5 0x85 +#define PAM6 0x86 + +#define LAC 0x87 /* Legacy Access Control */ +#define SMRAM 0x88 /* System Management RAM Control */ +#define D_OPEN (1 << 6) +#define D_CLS (1 << 5) +#define D_LCK (1 << 4) +#define G_SMRAME (1 << 3) +#define C_BASE_SEG ((0 << 2) | (1 << 1) | (0 << 0)) + +#define TOM 0xa0 +#define TOUUD 0xa8 /* Top of Upper Usable DRAM */ +#define TSEG 0xb8 /* TSEG base */ +#define TOLUD 0xbc /* Top of Low Used Memory */ + +#define SKPAD 0xdc /* Scratchpad Data */ + +/* Device 0:1.0 PCI configuration space (PCI Express) */ +#define BCTRL1 0x3e /* 16bit */ + +/* Device 0:2.0 PCI configuration space (Graphics Device) */ + +#define MSAC 0x62 /* Multi Size Aperture Control */ +#define SWSCI 0xe8 /* SWSCI enable */ +#define ASLS 0xfc /* OpRegion Base */ + +/* + * MCHBAR + */ +#define MCHBAR_REG(reg) (DEFAULT_RCBA + (reg)) + +#define SSKPD 0x5d14 /* 16bit (scratchpad) */ +#define BIOS_RESET_CPL 0x5da8 /* 8bit */ + +void sandybridge_early_init(int chipset_type); + +#endif diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index d32987b..ff9574c 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -10,6 +10,13 @@ #ifndef __ASSEMBLY__ +enum pei_boot_mode_t { + PEI_BOOT_NONE = 0, + PEI_BOOT_SOFT_RESET, + PEI_BOOT_RESUME, + +}; + /* Architecture-specific global data */ struct arch_global_data { struct global_data *gd_addr; /* Location of Global Data */ @@ -25,6 +32,7 @@ struct arch_global_data { void *new_fdt; /* Relocated FDT */ uint32_t bist; /* Built-in self test value */ struct pci_controller *hose; /* PCI hose for early use */ + enum pei_boot_mode_t pei_boot_mode; }; #endif diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h index b203dc9..61dcda1 100644 --- a/arch/x86/include/asm/post.h +++ b/arch/x86/include/asm/post.h @@ -25,6 +25,8 @@ #define POST_START_STACK 0x29 #define POST_START_DONE 0x2a #define POST_CPU_INIT 0x2b +#define POST_EARLY_INIT 0x2c +#define POST_CPU_INFO 0x2d /* Output a post code using al - value must be 0 to 0xff */ #ifdef __ASSEMBLY__ -- cgit v0.10.2 From 1b4f25ff8e6967f14494c5a0d173758a7a3ac279 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:24 -0700 Subject: x86: ivybridge: Add support for early GPIO init When not relying on Coreboot for GPIO init the GPIOs must be set up correctly. This is currently done statically through a rather ugly method. As the GPIOs are figured out they can be moved to the device tree and set up as needed rather than all at the start. In this implementation, board files should call ich_gpio_set_gpio_map() before the GPIO driver is used in order to provide the GPIO information. We use the early PCI interface so that this driver can now be used before relocation. Signed-off-by: Simon Glass diff --git a/arch/x86/include/asm/arch-coreboot/gpio.h b/arch/x86/include/asm/arch-coreboot/gpio.h index 3ec1816..4951a8c 100644 --- a/arch/x86/include/asm/arch-coreboot/gpio.h +++ b/arch/x86/include/asm/arch-coreboot/gpio.h @@ -7,9 +7,4 @@ #ifndef _X86_ARCH_GPIO_H_ #define _X86_ARCH_GPIO_H_ -struct ich6_bank_platdata { - uint32_t base_addr; - const char *bank_name; -}; - #endif /* _X86_ARCH_GPIO_H_ */ diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h index 290a737..ae338e3 100644 --- a/arch/x86/include/asm/arch-ivybridge/pch.h +++ b/arch/x86/include/asm/arch-ivybridge/pch.h @@ -142,6 +142,22 @@ #define FD2 0x3428 /* 32bit */ #define CG 0x341c /* 32bit */ +/* ICH7 GPIOBASE */ +#define GPIO_USE_SEL 0x00 +#define GP_IO_SEL 0x04 +#define GP_LVL 0x0c +#define GPO_BLINK 0x18 +#define GPI_INV 0x2c +#define GPIO_USE_SEL2 0x30 +#define GP_IO_SEL2 0x34 +#define GP_LVL2 0x38 +#define GPIO_USE_SEL3 0x40 +#define GP_IO_SEL3 0x44 +#define GP_LVL3 0x48 +#define GP_RST_SEL1 0x60 +#define GP_RST_SEL2 0x64 +#define GP_RST_SEL3 0x68 + /* ICH7 PMBASE */ #define PM1_STS 0x00 #define WAK_STS (1 << 15) diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index ff9574c..4ea46d7 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -33,6 +33,7 @@ struct arch_global_data { uint32_t bist; /* Built-in self test value */ struct pci_controller *hose; /* PCI hose for early use */ enum pei_boot_mode_t pei_boot_mode; + const struct pch_gpio_map *gpio_map; /* board GPIO map */ }; #endif diff --git a/arch/x86/include/asm/gpio.h b/arch/x86/include/asm/gpio.h index 8bda414..5540d42 100644 --- a/arch/x86/include/asm/gpio.h +++ b/arch/x86/include/asm/gpio.h @@ -1,12 +1,152 @@ /* * Copyright (c) 2012, Google Inc. All rights reserved. - * SPDX-License-Identifier: GPL-2.0+ + * SPDX-License-Identifier: GPL-2.0 */ #ifndef _X86_GPIO_H_ #define _X86_GPIO_H_ +#include #include #include +struct ich6_bank_platdata { + uint32_t base_addr; + const char *bank_name; +}; + +#define GPIO_MODE_NATIVE 0 +#define GPIO_MODE_GPIO 1 +#define GPIO_MODE_NONE 1 + +#define GPIO_DIR_OUTPUT 0 +#define GPIO_DIR_INPUT 1 + +#define GPIO_NO_INVERT 0 +#define GPIO_INVERT 1 + +#define GPIO_LEVEL_LOW 0 +#define GPIO_LEVEL_HIGH 1 + +#define GPIO_NO_BLINK 0 +#define GPIO_BLINK 1 + +#define GPIO_RESET_PWROK 0 +#define GPIO_RESET_RSMRST 1 + +struct pch_gpio_set1 { + u32 gpio0:1; + u32 gpio1:1; + u32 gpio2:1; + u32 gpio3:1; + u32 gpio4:1; + u32 gpio5:1; + u32 gpio6:1; + u32 gpio7:1; + u32 gpio8:1; + u32 gpio9:1; + u32 gpio10:1; + u32 gpio11:1; + u32 gpio12:1; + u32 gpio13:1; + u32 gpio14:1; + u32 gpio15:1; + u32 gpio16:1; + u32 gpio17:1; + u32 gpio18:1; + u32 gpio19:1; + u32 gpio20:1; + u32 gpio21:1; + u32 gpio22:1; + u32 gpio23:1; + u32 gpio24:1; + u32 gpio25:1; + u32 gpio26:1; + u32 gpio27:1; + u32 gpio28:1; + u32 gpio29:1; + u32 gpio30:1; + u32 gpio31:1; +} __packed; + +struct pch_gpio_set2 { + u32 gpio32:1; + u32 gpio33:1; + u32 gpio34:1; + u32 gpio35:1; + u32 gpio36:1; + u32 gpio37:1; + u32 gpio38:1; + u32 gpio39:1; + u32 gpio40:1; + u32 gpio41:1; + u32 gpio42:1; + u32 gpio43:1; + u32 gpio44:1; + u32 gpio45:1; + u32 gpio46:1; + u32 gpio47:1; + u32 gpio48:1; + u32 gpio49:1; + u32 gpio50:1; + u32 gpio51:1; + u32 gpio52:1; + u32 gpio53:1; + u32 gpio54:1; + u32 gpio55:1; + u32 gpio56:1; + u32 gpio57:1; + u32 gpio58:1; + u32 gpio59:1; + u32 gpio60:1; + u32 gpio61:1; + u32 gpio62:1; + u32 gpio63:1; +} __packed; + +struct pch_gpio_set3 { + u32 gpio64:1; + u32 gpio65:1; + u32 gpio66:1; + u32 gpio67:1; + u32 gpio68:1; + u32 gpio69:1; + u32 gpio70:1; + u32 gpio71:1; + u32 gpio72:1; + u32 gpio73:1; + u32 gpio74:1; + u32 gpio75:1; +} __packed; + +/* + * This hilariously complex structure came from Coreboot. The + * setup_pch_gpios() function uses it. It could be move to device tree, or + * adjust to use masks instead of bitfields. + */ +struct pch_gpio_map { + struct { + const struct pch_gpio_set1 *mode; + const struct pch_gpio_set1 *direction; + const struct pch_gpio_set1 *level; + const struct pch_gpio_set1 *reset; + const struct pch_gpio_set1 *invert; + const struct pch_gpio_set1 *blink; + } set1; + struct { + const struct pch_gpio_set2 *mode; + const struct pch_gpio_set2 *direction; + const struct pch_gpio_set2 *level; + const struct pch_gpio_set2 *reset; + } set2; + struct { + const struct pch_gpio_set3 *mode; + const struct pch_gpio_set3 *direction; + const struct pch_gpio_set3 *level; + const struct pch_gpio_set3 *reset; + } set3; +}; + +void ich_gpio_set_gpio_map(const struct pch_gpio_map *map); + #endif /* _X86_GPIO_H_ */ diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c index d3381b0..b095d17 100644 --- a/drivers/gpio/intel_ich6_gpio.c +++ b/drivers/gpio/intel_ich6_gpio.c @@ -33,6 +33,11 @@ #include #include #include +#include +#ifdef CONFIG_X86_RESET_VECTOR +#include +#define SUPPORT_GPIO_SETUP +#endif #define GPIO_PER_BANK 32 @@ -46,6 +51,53 @@ struct ich6_bank_priv { uint32_t lvl; }; +#ifdef SUPPORT_GPIO_SETUP +static void setup_pch_gpios(const struct pch_gpio_map *gpio) +{ + u16 gpiobase = pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc; + + /* GPIO Set 1 */ + if (gpio->set1.level) + outl(*((u32 *)gpio->set1.level), gpiobase + GP_LVL); + if (gpio->set1.mode) + outl(*((u32 *)gpio->set1.mode), gpiobase + GPIO_USE_SEL); + if (gpio->set1.direction) + outl(*((u32 *)gpio->set1.direction), gpiobase + GP_IO_SEL); + if (gpio->set1.reset) + outl(*((u32 *)gpio->set1.reset), gpiobase + GP_RST_SEL1); + if (gpio->set1.invert) + outl(*((u32 *)gpio->set1.invert), gpiobase + GPI_INV); + if (gpio->set1.blink) + outl(*((u32 *)gpio->set1.blink), gpiobase + GPO_BLINK); + + /* GPIO Set 2 */ + if (gpio->set2.level) + outl(*((u32 *)gpio->set2.level), gpiobase + GP_LVL2); + if (gpio->set2.mode) + outl(*((u32 *)gpio->set2.mode), gpiobase + GPIO_USE_SEL2); + if (gpio->set2.direction) + outl(*((u32 *)gpio->set2.direction), gpiobase + GP_IO_SEL2); + if (gpio->set2.reset) + outl(*((u32 *)gpio->set2.reset), gpiobase + GP_RST_SEL2); + + /* GPIO Set 3 */ + if (gpio->set3.level) + outl(*((u32 *)gpio->set3.level), gpiobase + GP_LVL3); + if (gpio->set3.mode) + outl(*((u32 *)gpio->set3.mode), gpiobase + GPIO_USE_SEL3); + if (gpio->set3.direction) + outl(*((u32 *)gpio->set3.direction), gpiobase + GP_IO_SEL3); + if (gpio->set3.reset) + outl(*((u32 *)gpio->set3.reset), gpiobase + GP_RST_SEL3); +} + +/* TODO: Move this to device tree, or platform data */ +void ich_gpio_set_gpio_map(const struct pch_gpio_map *map) +{ + gd->arch.gpio_map = map; +} +#endif /* SUPPORT_GPIO_SETUP */ + static int gpio_ich6_ofdata_to_platdata(struct udevice *dev) { struct ich6_bank_platdata *plat = dev_get_platdata(dev); @@ -60,13 +112,13 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev) pci_dev = PCI_BDF(0, 0x1f, 0); /* Is the device present? */ - pci_read_config_word(pci_dev, PCI_VENDOR_ID, &tmpword); + tmpword = pci_read_config16(pci_dev, PCI_VENDOR_ID); if (tmpword != PCI_VENDOR_ID_INTEL) { debug("%s: wrong VendorID\n", __func__); return -ENODEV; } - pci_read_config_word(pci_dev, PCI_DEVICE_ID, &tmpword); + tmpword = pci_read_config16(pci_dev, PCI_DEVICE_ID); debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword); /* * We'd like to validate the Device ID too, but pretty much any @@ -76,34 +128,34 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev) */ /* I/O should already be enabled (it's a RO bit). */ - pci_read_config_word(pci_dev, PCI_COMMAND, &tmpword); + tmpword = pci_read_config16(pci_dev, PCI_COMMAND); if (!(tmpword & PCI_COMMAND_IO)) { debug("%s: device IO not enabled\n", __func__); return -ENODEV; } /* Header Type must be normal (bits 6-0 only; see spec.) */ - pci_read_config_byte(pci_dev, PCI_HEADER_TYPE, &tmpbyte); + tmpbyte = pci_read_config8(pci_dev, PCI_HEADER_TYPE); if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) { debug("%s: invalid Header type\n", __func__); return -ENODEV; } /* Base Class must be a bridge device */ - pci_read_config_byte(pci_dev, PCI_CLASS_CODE, &tmpbyte); + tmpbyte = pci_read_config8(pci_dev, PCI_CLASS_CODE); if (tmpbyte != PCI_CLASS_CODE_BRIDGE) { debug("%s: invalid class\n", __func__); return -ENODEV; } /* Sub Class must be ISA */ - pci_read_config_byte(pci_dev, PCI_CLASS_SUB_CODE, &tmpbyte); + tmpbyte = pci_read_config8(pci_dev, PCI_CLASS_SUB_CODE); if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) { debug("%s: invalid subclass\n", __func__); return -ENODEV; } /* Programming Interface must be 0x00 (no others exist) */ - pci_read_config_byte(pci_dev, PCI_CLASS_PROG, &tmpbyte); + tmpbyte = pci_read_config8(pci_dev, PCI_CLASS_PROG); if (tmpbyte != 0x00) { debug("%s: invalid interface type\n", __func__); return -ENODEV; @@ -114,7 +166,7 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev) * that it was unused (or undocumented). Check that it looks * okay: not all ones or zeros, and mapped to I/O space (bit 0). */ - pci_read_config_dword(pci_dev, PCI_CFG_GPIOBASE, &tmplong); + tmplong = pci_read_config32(pci_dev, PCI_CFG_GPIOBASE); if (tmplong == 0x00000000 || tmplong == 0xffffffff || !(tmplong & 0x00000001)) { debug("%s: unexpected GPIOBASE value\n", __func__); @@ -140,12 +192,18 @@ static int gpio_ich6_ofdata_to_platdata(struct udevice *dev) return 0; } -int ich6_gpio_probe(struct udevice *dev) +static int ich6_gpio_probe(struct udevice *dev) { struct ich6_bank_platdata *plat = dev_get_platdata(dev); struct gpio_dev_priv *uc_priv = dev->uclass_priv; struct ich6_bank_priv *bank = dev_get_priv(dev); +#ifdef SUPPORT_GPIO_SETUP + if (gd->arch.gpio_map) { + setup_pch_gpios(gd->arch.gpio_map); + gd->arch.gpio_map = NULL; + } +#endif uc_priv->gpio_count = GPIO_PER_BANK; uc_priv->bank_name = plat->bank_name; bank->use_sel = plat->base_addr; @@ -155,7 +213,8 @@ int ich6_gpio_probe(struct udevice *dev) return 0; } -int ich6_gpio_request(struct udevice *dev, unsigned offset, const char *label) +static int ich6_gpio_request(struct udevice *dev, unsigned offset, + const char *label) { struct ich6_bank_priv *bank = dev_get_priv(dev); u32 tmplong; -- cgit v0.10.2 From 437c2b7cd04f017cf79dcde63e7d9035f8cd99e5 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:25 -0700 Subject: x86: chromebook_link: Enable GPIO support Enable GPIO support and provide the required GPIO setup information to the driver. Signed-off-by: Simon Glass diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index f1b7bf0..74b2198 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -14,18 +14,21 @@ gpioa { compatible = "intel,ich6-gpio"; + u-boot,dm-pre-reloc; reg = <0 0x10>; bank-name = "A"; }; gpiob { compatible = "intel,ich6-gpio"; + u-boot,dm-pre-reloc; reg = <0x30 0x10>; bank-name = "B"; }; gpioc { compatible = "intel,ich6-gpio"; + u-boot,dm-pre-reloc; reg = <0x40 0x10>; bank-name = "C"; }; diff --git a/board/google/chromebook_link/link.c b/board/google/chromebook_link/link.c index ffa9d60..88cee05 100644 --- a/board/google/chromebook_link/link.c +++ b/board/google/chromebook_link/link.c @@ -5,6 +5,7 @@ */ #include +#include int arch_early_init_r(void) { @@ -15,3 +16,109 @@ int board_early_init_r(void) { return 0; } + +static const struct pch_gpio_set1 pch_gpio_set1_mode = { + .gpio0 = GPIO_MODE_GPIO, /* NMI_DBG# */ + .gpio3 = GPIO_MODE_GPIO, /* ALS_INT# */ + .gpio5 = GPIO_MODE_GPIO, /* SIM_DET */ + .gpio7 = GPIO_MODE_GPIO, /* EC_SCI# */ + .gpio8 = GPIO_MODE_GPIO, /* EC_SMI# */ + .gpio9 = GPIO_MODE_GPIO, /* RECOVERY# */ + .gpio10 = GPIO_MODE_GPIO, /* SPD vector D3 */ + .gpio11 = GPIO_MODE_GPIO, /* smbalert#, let's keep it initialized */ + .gpio12 = GPIO_MODE_GPIO, /* TP_INT# */ + .gpio14 = GPIO_MODE_GPIO, /* Touch_INT_L */ + .gpio15 = GPIO_MODE_GPIO, /* EC_LID_OUT# (EC_WAKE#) */ + .gpio21 = GPIO_MODE_GPIO, /* EC_IN_RW */ + .gpio24 = GPIO_MODE_GPIO, /* DDR3L_EN */ + .gpio28 = GPIO_MODE_GPIO, /* SLP_ME_CSW_DEV# */ +}; + +static const struct pch_gpio_set1 pch_gpio_set1_direction = { + .gpio0 = GPIO_DIR_INPUT, + .gpio3 = GPIO_DIR_INPUT, + .gpio5 = GPIO_DIR_INPUT, + .gpio7 = GPIO_DIR_INPUT, + .gpio8 = GPIO_DIR_INPUT, + .gpio9 = GPIO_DIR_INPUT, + .gpio10 = GPIO_DIR_INPUT, + .gpio11 = GPIO_DIR_INPUT, + .gpio12 = GPIO_DIR_INPUT, + .gpio14 = GPIO_DIR_INPUT, + .gpio15 = GPIO_DIR_INPUT, + .gpio21 = GPIO_DIR_INPUT, + .gpio24 = GPIO_DIR_OUTPUT, + .gpio28 = GPIO_DIR_INPUT, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_level = { + .gpio1 = GPIO_LEVEL_HIGH, + .gpio6 = GPIO_LEVEL_HIGH, + .gpio24 = GPIO_LEVEL_LOW, +}; + +static const struct pch_gpio_set1 pch_gpio_set1_invert = { + .gpio7 = GPIO_INVERT, + .gpio8 = GPIO_INVERT, + .gpio12 = GPIO_INVERT, + .gpio14 = GPIO_INVERT, + .gpio15 = GPIO_INVERT, +}; + +static const struct pch_gpio_set2 pch_gpio_set2_mode = { + .gpio36 = GPIO_MODE_GPIO, /* W_DISABLE_L */ + .gpio41 = GPIO_MODE_GPIO, /* SPD vector D0 */ + .gpio42 = GPIO_MODE_GPIO, /* SPD vector D1 */ + .gpio43 = GPIO_MODE_GPIO, /* SPD vector D2 */ + .gpio57 = GPIO_MODE_GPIO, /* PCH_SPI_WP_D */ + .gpio60 = GPIO_MODE_GPIO, /* DRAMRST_CNTRL_PCH */ +}; + +static const struct pch_gpio_set2 pch_gpio_set2_direction = { + .gpio36 = GPIO_DIR_OUTPUT, + .gpio41 = GPIO_DIR_INPUT, + .gpio42 = GPIO_DIR_INPUT, + .gpio43 = GPIO_DIR_INPUT, + .gpio57 = GPIO_DIR_INPUT, + .gpio60 = GPIO_DIR_OUTPUT, +}; + +static const struct pch_gpio_set2 pch_gpio_set2_level = { + .gpio36 = GPIO_LEVEL_HIGH, + .gpio60 = GPIO_LEVEL_HIGH, +}; + +static const struct pch_gpio_set3 pch_gpio_set3_mode = { +}; + +static const struct pch_gpio_set3 pch_gpio_set3_direction = { +}; + +static const struct pch_gpio_set3 pch_gpio_set3_level = { +}; + +static const struct pch_gpio_map link_gpio_map = { + .set1 = { + .mode = &pch_gpio_set1_mode, + .direction = &pch_gpio_set1_direction, + .level = &pch_gpio_set1_level, + .invert = &pch_gpio_set1_invert, + }, + .set2 = { + .mode = &pch_gpio_set2_mode, + .direction = &pch_gpio_set2_direction, + .level = &pch_gpio_set2_level, + }, + .set3 = { + .mode = &pch_gpio_set3_mode, + .direction = &pch_gpio_set3_direction, + .level = &pch_gpio_set3_level, + }, +}; + +int board_early_init_f(void) +{ + ich_gpio_set_gpio_map(&link_gpio_map); + + return 0; +} diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 0b8c067..3063bd9 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -19,6 +19,7 @@ #define CONFIG_SYS_CAR_SIZE (128 * 1024) #define CONFIG_SYS_MONITOR_LEN (1 << 20) #define CONFIG_SYS_X86_START16 0xfffff800 +#define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_BOARD_EARLY_INIT_R #define CONFIG_X86_RESET_VECTOR @@ -40,9 +41,6 @@ * follow-on patches in this series. Add undefs here to avoid every patch * having to put things back into x86-common.h */ -#undef CONFIG_INTEL_ICH6_GPIO -#undef CONFIG_DM_GPIO -#undef CONFIG_CMD_GPIO #undef CONFIG_VIDEO #undef CONFIG_CFB_CONSOLE #undef CONFIG_ICH_SPI -- cgit v0.10.2 From a49e3c7f09abf4961f2945275338c3a0c18b9b61 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:26 -0700 Subject: x86: Make show_boot_progress() common This function can probably be used on all x86 boards, so move it into the common file. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/coreboot/coreboot.c b/arch/x86/cpu/coreboot/coreboot.c index 3356121..2df7288 100644 --- a/arch/x86/cpu/coreboot/coreboot.c +++ b/arch/x86/cpu/coreboot/coreboot.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -51,29 +50,6 @@ int board_early_init_r(void) return 0; } -void show_boot_progress(int val) -{ -#if MIN_PORT80_KCLOCKS_DELAY - /* - * Scale the time counter reading to avoid using 64 bit arithmetics. - * Can't use get_timer() here becuase it could be not yet - * initialized or even implemented. - */ - if (!gd->arch.tsc_prev) { - gd->arch.tsc_base_kclocks = rdtsc() / 1000; - gd->arch.tsc_prev = 0; - } else { - uint32_t now; - - do { - now = rdtsc() / 1000 - gd->arch.tsc_base_kclocks; - } while (now < (gd->arch.tsc_prev + MIN_PORT80_KCLOCKS_DELAY)); - gd->arch.tsc_prev = now; - } -#endif - outb(val, POST_PORT); -} - int print_cpuinfo(void) { return default_print_cpuinfo(); diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index 97c77ba..b391b7a 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -567,3 +568,26 @@ int cpu_jump_to_64bit(ulong setup_base, ulong target) return -EFAULT; } + +void show_boot_progress(int val) +{ +#if MIN_PORT80_KCLOCKS_DELAY + /* + * Scale the time counter reading to avoid using 64 bit arithmetics. + * Can't use get_timer() here becuase it could be not yet + * initialized or even implemented. + */ + if (!gd->arch.tsc_prev) { + gd->arch.tsc_base_kclocks = rdtsc() / 1000; + gd->arch.tsc_prev = 0; + } else { + uint32_t now; + + do { + now = rdtsc() / 1000 - gd->arch.tsc_base_kclocks; + } while (now < (gd->arch.tsc_prev + MIN_PORT80_KCLOCKS_DELAY)); + gd->arch.tsc_prev = now; + } +#endif + outb(val, POST_PORT); +} -- cgit v0.10.2 From 3eafce05278f867678a66efd867f398cc055359a Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:27 -0700 Subject: x86: ivybridge: Add LAPIC support The local advanced programmable interrupt controller is not used much in U-Boot but we do need to set it up. Add basic support for this, which will be extended as needed. Signed-off-by: Simon Glass diff --git a/arch/x86/cpu/ivybridge/cpu.c b/arch/x86/cpu/ivybridge/cpu.c index d5be2f5..60976db 100644 --- a/arch/x86/cpu/ivybridge/cpu.c +++ b/arch/x86/cpu/ivybridge/cpu.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -283,6 +284,8 @@ int print_cpuinfo(void) if (ret) return ret; + enable_lapic(); + ret = microcode_update_intel(); if (ret && ret != -ENOENT && ret != -EEXIST) return ret; diff --git a/arch/x86/include/asm/lapic.h b/arch/x86/include/asm/lapic.h new file mode 100644 index 0000000..948e643 --- /dev/null +++ b/arch/x86/include/asm/lapic.h @@ -0,0 +1,59 @@ +/* + * From Coreboot file of same name + * + * Copyright (C) 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ARCH_ASM_LAPIC_H +#define _ARCH_ASM_LAPIC_H + +#include +#include +#include +#include + +static inline __attribute__((always_inline)) + unsigned long lapic_read(unsigned long reg) +{ + return readl(LAPIC_DEFAULT_BASE + reg); +} + +static inline __attribute__((always_inline)) + void lapic_write(unsigned long reg, unsigned long val) +{ + writel(val, LAPIC_DEFAULT_BASE + reg); +} + +static inline __attribute__((always_inline)) void lapic_wait_icr_idle(void) +{ + do { } while (lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY); +} + +static inline void enable_lapic(void) +{ + msr_t msr; + + msr = msr_read(LAPIC_BASE_MSR); + msr.hi &= 0xffffff00; + msr.lo &= 0x000007ff; + msr.lo |= LAPIC_DEFAULT_BASE | (1 << 11); + msr_write(LAPIC_BASE_MSR, msr); +} + +static inline void disable_lapic(void) +{ + msr_t msr; + + msr = msr_read(LAPIC_BASE_MSR); + msr.lo &= ~(1 << 11); + msr_write(LAPIC_BASE_MSR, msr); +} + +static inline __attribute__((always_inline)) unsigned long lapicid(void) +{ + return lapic_read(LAPIC_ID) >> 24; +} + +#endif diff --git a/arch/x86/include/asm/lapic_def.h b/arch/x86/include/asm/lapic_def.h new file mode 100644 index 0000000..722cead --- /dev/null +++ b/arch/x86/include/asm/lapic_def.h @@ -0,0 +1,101 @@ +/* + * Taken from the Coreboot file of the same name + * + * (C) Copyright 2014 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ASM_LAPIC_DEF_H +#define _ASM_LAPIC_DEF_H + +#define LAPIC_BASE_MSR 0x1B +#define LAPIC_BASE_MSR_BOOTSTRAP_PROCESSOR (1 << 8) +#define LAPIC_BASE_MSR_ENABLE (1 << 11) +#define LAPIC_BASE_MSR_ADDR_MASK 0xFFFFF000 + +#define LOCAL_APIC_ADDR 0xfee00000 +#define LAPIC_DEFAULT_BASE LOCAL_APIC_ADDR + +#define LAPIC_ID 0x020 +#define LAPIC_LVR 0x030 +#define LAPIC_TASKPRI 0x80 +#define LAPIC_TPRI_MASK 0xFF +#define LAPIC_ARBID 0x090 +#define LAPIC_RRR 0x0C0 +#define LAPIC_SVR 0x0f0 +#define LAPIC_SPIV 0x0f0 +#define LAPIC_SPIV_ENABLE 0x100 +#define LAPIC_ESR 0x280 +#define LAPIC_ESR_SEND_CS 0x00001 +#define LAPIC_ESR_RECV_CS 0x00002 +#define LAPIC_ESR_SEND_ACC 0x00004 +#define LAPIC_ESR_RECV_ACC 0x00008 +#define LAPIC_ESR_SENDILL 0x00020 +#define LAPIC_ESR_RECVILL 0x00040 +#define LAPIC_ESR_ILLREGA 0x00080 +#define LAPIC_ICR 0x300 +#define LAPIC_DEST_SELF 0x40000 +#define LAPIC_DEST_ALLINC 0x80000 +#define LAPIC_DEST_ALLBUT 0xC0000 +#define LAPIC_ICR_RR_MASK 0x30000 +#define LAPIC_ICR_RR_INVALID 0x00000 +#define LAPIC_ICR_RR_INPROG 0x10000 +#define LAPIC_ICR_RR_VALID 0x20000 +#define LAPIC_INT_LEVELTRIG 0x08000 +#define LAPIC_INT_ASSERT 0x04000 +#define LAPIC_ICR_BUSY 0x01000 +#define LAPIC_DEST_LOGICAL 0x00800 +#define LAPIC_DM_FIXED 0x00000 +#define LAPIC_DM_LOWEST 0x00100 +#define LAPIC_DM_SMI 0x00200 +#define LAPIC_DM_REMRD 0x00300 +#define LAPIC_DM_NMI 0x00400 +#define LAPIC_DM_INIT 0x00500 +#define LAPIC_DM_STARTUP 0x00600 +#define LAPIC_DM_EXTINT 0x00700 +#define LAPIC_VECTOR_MASK 0x000FF +#define LAPIC_ICR2 0x310 +#define GET_LAPIC_DEST_FIELD(x) (((x) >> 24) & 0xFF) +#define SET_LAPIC_DEST_FIELD(x) ((x) << 24) +#define LAPIC_LVTT 0x320 +#define LAPIC_LVTPC 0x340 +#define LAPIC_LVT0 0x350 +#define LAPIC_LVT_TIMER_BASE_MASK (0x3 << 18) +#define GET_LAPIC_TIMER_BASE(x) (((x) >> 18) & 0x3) +#define SET_LAPIC_TIMER_BASE(x) (((x) << 18)) +#define LAPIC_TIMER_BASE_CLKIN 0x0 +#define LAPIC_TIMER_BASE_TMBASE 0x1 +#define LAPIC_TIMER_BASE_DIV 0x2 +#define LAPIC_LVT_TIMER_PERIODIC (1 << 17) +#define LAPIC_LVT_MASKED (1 << 16) +#define LAPIC_LVT_LEVEL_TRIGGER (1 << 15) +#define LAPIC_LVT_REMOTE_IRR (1 << 14) +#define LAPIC_INPUT_POLARITY (1 << 13) +#define LAPIC_SEND_PENDING (1 << 12) +#define LAPIC_LVT_RESERVED_1 (1 << 11) +#define LAPIC_DELIVERY_MODE_MASK (7 << 8) +#define LAPIC_DELIVERY_MODE_FIXED (0 << 8) +#define LAPIC_DELIVERY_MODE_NMI (4 << 8) +#define LAPIC_DELIVERY_MODE_EXTINT (7 << 8) +#define GET_LAPIC_DELIVERY_MODE(x) (((x) >> 8) & 0x7) +#define SET_LAPIC_DELIVERY_MODE(x, y) (((x) & ~0x700)|((y) << 8)) +#define LAPIC_MODE_FIXED 0x0 +#define LAPIC_MODE_NMI 0x4 +#define LAPIC_MODE_EXINT 0x7 +#define LAPIC_LVT1 0x360 +#define LAPIC_LVTERR 0x370 +#define LAPIC_TMICT 0x380 +#define LAPIC_TMCCT 0x390 +#define LAPIC_TDCR 0x3E0 +#define LAPIC_TDR_DIV_TMBASE (1 << 2) +#define LAPIC_TDR_DIV_1 0xB +#define LAPIC_TDR_DIV_2 0x0 +#define LAPIC_TDR_DIV_4 0x1 +#define LAPIC_TDR_DIV_8 0x2 +#define LAPIC_TDR_DIV_16 0x3 +#define LAPIC_TDR_DIV_32 0x8 +#define LAPIC_TDR_DIV_64 0x9 +#define LAPIC_TDR_DIV_128 0xA + +#endif -- cgit v0.10.2 From 65dd74a674d636afcc14594c8308ff516e95a445 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:28 -0700 Subject: x86: ivybridge: Implement SDRAM init Implement SDRAM init using the Memory Reference Code (mrc.bin) provided in the board directory and the SDRAM SPD information in the device tree. This also needs the Intel Management Engine (me.bin) to work. Binary blobs everywhere: so far we have MRC, ME and microcode. SDRAM init works by setting up various parameters and calling the MRC. This in turn does some sort of magic to work out how much memory there is and the timing parameters to use. It also sets up the DRAM controllers. When the MRC returns, we use the information it provides to map out the available memory in U-Boot. U-Boot normally moves itself to the top of RAM. On x86 the RAM is not generally contiguous, and anyway some RAM may be above 4GB which doesn't work in 32-bit mode. So we relocate to the top of the largest block of RAM we can find below 4GB. Memory above 4GB is accessible with special functions (see physmem). It would be possible to build U-Boot in 64-bit mode but this wouldn't necessarily provide any more memory, since the largest block is often below 4GB. Anyway U-Boot doesn't need huge amounts of memory - even a very large ramdisk seldom exceeds 100-200MB. U-Boot has support for booting 64-bit kernels directly so this does not pose a limitation in that area. Also there are probably parts of U-Boot that will not work correctly in 64-bit mode. The MRC is one. There is some work remaining in this area. Since memory init is very slow (over 500ms) it is possible to save the parameters in SPI flash to speed it up next time. Suspend/resume support is not fully implemented, or at least it is not efficient. With this patch, link boots to a prompt. Signed-off-by: Simon Glass diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f27d731..43c22ff 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -50,6 +50,17 @@ config CPU_ADDR_BITS int default 36 +config HPET_ADDRESS + hex + default 0xfed00000 if !HPET_ADDRESS_OVERRIDE + +config SMM_TSEG + bool + default n + +config SMM_TSEG_SIZE + hex + config ROM_SIZE hex default 0x800000 @@ -63,6 +74,15 @@ config HAVE_INTEL_ME SPI flash format. You will need to supply the me.bin file in your board directory. +config X86_RAMTEST + bool "Perform a simple RAM test after SDRAM initialisation" + help + If there is something wrong with SDRAM then the platform will + often crash within U-Boot or the kernel. This option enables a + very simple RAM test that quickly checks whether the SDRAM seems + to work correctly. It is not exhaustive but can save time by + detecting obvious failures. + source "arch/x86/cpu/ivybridge/Kconfig" source "board/chromebook-x86/coreboot/Kconfig" diff --git a/arch/x86/cpu/ivybridge/Kconfig b/arch/x86/cpu/ivybridge/Kconfig index 177247e..afca957 100644 --- a/arch/x86/cpu/ivybridge/Kconfig +++ b/arch/x86/cpu/ivybridge/Kconfig @@ -129,6 +129,7 @@ config CPU_SPECIFIC_OPTIONS select CPU_MICROCODE_IN_CBFS select TSC_SYNC_MFENCE select HAVE_INTEL_ME + select X86_RAMTEST config SMM_TSEG_SIZE hex diff --git a/arch/x86/cpu/ivybridge/Makefile b/arch/x86/cpu/ivybridge/Makefile index e5c0751..721b37e 100644 --- a/arch/x86/cpu/ivybridge/Makefile +++ b/arch/x86/cpu/ivybridge/Makefile @@ -7,7 +7,10 @@ obj-y += car.o obj-y += cpu.o obj-y += early_init.o +obj-y += early_me.o obj-y += lpc.o +obj-y += me_status.o obj-y += microcode_intel.o obj-y += pci.o +obj-y += report_platform.o obj-y += sdram.o diff --git a/arch/x86/cpu/ivybridge/early_me.c b/arch/x86/cpu/ivybridge/early_me.c new file mode 100644 index 0000000..b24dea1 --- /dev/null +++ b/arch/x86/cpu/ivybridge/early_me.c @@ -0,0 +1,191 @@ +/* + * From Coreboot src/southbridge/intel/bd82x6x/early_me.c + * + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +static const char *const me_ack_values[] = { + [ME_HFS_ACK_NO_DID] = "No DID Ack received", + [ME_HFS_ACK_RESET] = "Non-power cycle reset", + [ME_HFS_ACK_PWR_CYCLE] = "Power cycle reset", + [ME_HFS_ACK_S3] = "Go to S3", + [ME_HFS_ACK_S4] = "Go to S4", + [ME_HFS_ACK_S5] = "Go to S5", + [ME_HFS_ACK_GBL_RESET] = "Global Reset", + [ME_HFS_ACK_CONTINUE] = "Continue to boot" +}; + +static inline void pci_read_dword_ptr(void *ptr, int offset) +{ + u32 dword; + + dword = pci_read_config32(PCH_ME_DEV, offset); + memcpy(ptr, &dword, sizeof(dword)); +} + +static inline void pci_write_dword_ptr(void *ptr, int offset) +{ + u32 dword = 0; + memcpy(&dword, ptr, sizeof(dword)); + pci_write_config32(PCH_ME_DEV, offset, dword); +} + +void intel_early_me_status(void) +{ + struct me_hfs hfs; + struct me_gmes gmes; + + pci_read_dword_ptr(&hfs, PCI_ME_HFS); + pci_read_dword_ptr(&gmes, PCI_ME_GMES); + + intel_me_status(&hfs, &gmes); +} + +int intel_early_me_init(void) +{ + int count; + struct me_uma uma; + struct me_hfs hfs; + + debug("Intel ME early init\n"); + + /* Wait for ME UMA SIZE VALID bit to be set */ + for (count = ME_RETRY; count > 0; --count) { + pci_read_dword_ptr(&uma, PCI_ME_UMA); + if (uma.valid) + break; + udelay(ME_DELAY); + } + if (!count) { + printf("ERROR: ME is not ready!\n"); + return -EBUSY; + } + + /* Check for valid firmware */ + pci_read_dword_ptr(&hfs, PCI_ME_HFS); + if (hfs.fpt_bad) { + printf("WARNING: ME has bad firmware\n"); + return -EBADF; + } + + debug("Intel ME firmware is ready\n"); + + return 0; +} + +int intel_early_me_uma_size(void) +{ + struct me_uma uma; + + pci_read_dword_ptr(&uma, PCI_ME_UMA); + if (uma.valid) { + debug("ME: Requested %uMB UMA\n", uma.size); + return uma.size; + } + + debug("ME: Invalid UMA size\n"); + return -EINVAL; +} + +static inline void set_global_reset(int enable) +{ + u32 etr3; + + etr3 = pci_read_config32(PCH_LPC_DEV, ETR3); + + /* Clear CF9 Without Resume Well Reset Enable */ + etr3 &= ~ETR3_CWORWRE; + + /* CF9GR indicates a Global Reset */ + if (enable) + etr3 |= ETR3_CF9GR; + else + etr3 &= ~ETR3_CF9GR; + + pci_write_config32(PCH_LPC_DEV, ETR3, etr3); +} + +int intel_early_me_init_done(u8 status) +{ + u8 reset; + int count; + u32 mebase_l, mebase_h; + struct me_hfs hfs; + struct me_did did = { + .init_done = ME_INIT_DONE, + .status = status + }; + + /* MEBASE from MESEG_BASE[35:20] */ + mebase_l = pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_L); + mebase_h = pci_read_config32(PCH_DEV, PCI_CPU_MEBASE_H); + mebase_h &= 0xf; + did.uma_base = (mebase_l >> 20) | (mebase_h << 12); + + /* Send message to ME */ + debug("ME: Sending Init Done with status: %d, UMA base: 0x%04x\n", + status, did.uma_base); + + pci_write_dword_ptr(&did, PCI_ME_H_GS); + + /* Must wait for ME acknowledgement */ + for (count = ME_RETRY; count > 0; --count) { + pci_read_dword_ptr(&hfs, PCI_ME_HFS); + if (hfs.bios_msg_ack) + break; + udelay(ME_DELAY); + } + if (!count) { + printf("ERROR: ME failed to respond\n"); + return -1; + } + + /* Return the requested BIOS action */ + debug("ME: Requested BIOS Action: %s\n", me_ack_values[hfs.ack_data]); + + /* Check status after acknowledgement */ + intel_early_me_status(); + + reset = 0; + switch (hfs.ack_data) { + case ME_HFS_ACK_CONTINUE: + /* Continue to boot */ + return 0; + case ME_HFS_ACK_RESET: + /* Non-power cycle reset */ + set_global_reset(0); + reset = 0x06; + break; + case ME_HFS_ACK_PWR_CYCLE: + /* Power cycle reset */ + set_global_reset(0); + reset = 0x0e; + break; + case ME_HFS_ACK_GBL_RESET: + /* Global reset */ + set_global_reset(1); + reset = 0x0e; + break; + case ME_HFS_ACK_S3: + case ME_HFS_ACK_S4: + case ME_HFS_ACK_S5: + break; + } + + /* Perform the requested reset */ + if (reset) { + outb(reset, 0xcf9); + cpu_hlt(); + } + return -1; +} diff --git a/arch/x86/cpu/ivybridge/me_status.c b/arch/x86/cpu/ivybridge/me_status.c new file mode 100644 index 0000000..15cf69f --- /dev/null +++ b/arch/x86/cpu/ivybridge/me_status.c @@ -0,0 +1,195 @@ +/* + * From Coreboot src/southbridge/intel/bd82x6x/me_status.c + * + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include + +/* HFS1[3:0] Current Working State Values */ +static const char *const me_cws_values[] = { + [ME_HFS_CWS_RESET] = "Reset", + [ME_HFS_CWS_INIT] = "Initializing", + [ME_HFS_CWS_REC] = "Recovery", + [ME_HFS_CWS_NORMAL] = "Normal", + [ME_HFS_CWS_WAIT] = "Platform Disable Wait", + [ME_HFS_CWS_TRANS] = "OP State Transition", + [ME_HFS_CWS_INVALID] = "Invalid CPU Plugged In" +}; + +/* HFS1[8:6] Current Operation State Values */ +static const char *const me_opstate_values[] = { + [ME_HFS_STATE_PREBOOT] = "Preboot", + [ME_HFS_STATE_M0_UMA] = "M0 with UMA", + [ME_HFS_STATE_M3] = "M3 without UMA", + [ME_HFS_STATE_M0] = "M0 without UMA", + [ME_HFS_STATE_BRINGUP] = "Bring up", + [ME_HFS_STATE_ERROR] = "M0 without UMA but with error" +}; + +/* HFS[19:16] Current Operation Mode Values */ +static const char *const me_opmode_values[] = { + [ME_HFS_MODE_NORMAL] = "Normal", + [ME_HFS_MODE_DEBUG] = "Debug", + [ME_HFS_MODE_DIS] = "Soft Temporary Disable", + [ME_HFS_MODE_OVER_JMPR] = "Security Override via Jumper", + [ME_HFS_MODE_OVER_MEI] = "Security Override via MEI Message" +}; + +/* HFS[15:12] Error Code Values */ +static const char *const me_error_values[] = { + [ME_HFS_ERROR_NONE] = "No Error", + [ME_HFS_ERROR_UNCAT] = "Uncategorized Failure", + [ME_HFS_ERROR_IMAGE] = "Image Failure", + [ME_HFS_ERROR_DEBUG] = "Debug Failure" +}; + +/* GMES[31:28] ME Progress Code */ +static const char *const me_progress_values[] = { + [ME_GMES_PHASE_ROM] = "ROM Phase", + [ME_GMES_PHASE_BUP] = "BUP Phase", + [ME_GMES_PHASE_UKERNEL] = "uKernel Phase", + [ME_GMES_PHASE_POLICY] = "Policy Module", + [ME_GMES_PHASE_MODULE] = "Module Loading", + [ME_GMES_PHASE_UNKNOWN] = "Unknown", + [ME_GMES_PHASE_HOST] = "Host Communication" +}; + +/* GMES[27:24] Power Management Event */ +static const char *const me_pmevent_values[] = { + [0x00] = "Clean Moff->Mx wake", + [0x01] = "Moff->Mx wake after an error", + [0x02] = "Clean global reset", + [0x03] = "Global reset after an error", + [0x04] = "Clean Intel ME reset", + [0x05] = "Intel ME reset due to exception", + [0x06] = "Pseudo-global reset", + [0x07] = "S0/M0->Sx/M3", + [0x08] = "Sx/M3->S0/M0", + [0x09] = "Non-power cycle reset", + [0x0a] = "Power cycle reset through M3", + [0x0b] = "Power cycle reset through Moff", + [0x0c] = "Sx/Mx->Sx/Moff" +}; + +/* Progress Code 0 states */ +static const char *const me_progress_rom_values[] = { + [0x00] = "BEGIN", + [0x06] = "DISABLE" +}; + +/* Progress Code 1 states */ +static const char *const me_progress_bup_values[] = { + [0x00] = "Initialization starts", + [0x01] = "Disable the host wake event", + [0x04] = "Flow determination start process", + [0x08] = "Error reading/matching the VSCC table in the descriptor", + [0x0a] = "Check to see if straps say ME DISABLED", + [0x0b] = "Timeout waiting for PWROK", + [0x0d] = "Possibly handle BUP manufacturing override strap", + [0x11] = "Bringup in M3", + [0x12] = "Bringup in M0", + [0x13] = "Flow detection error", + [0x15] = "M3 clock switching error", + [0x18] = "M3 kernel load", + [0x1c] = "T34 missing - cannot program ICC", + [0x1f] = "Waiting for DID BIOS message", + [0x20] = "Waiting for DID BIOS message failure", + [0x21] = "DID reported an error", + [0x22] = "Enabling UMA", + [0x23] = "Enabling UMA error", + [0x24] = "Sending DID Ack to BIOS", + [0x25] = "Sending DID Ack to BIOS error", + [0x26] = "Switching clocks in M0", + [0x27] = "Switching clocks in M0 error", + [0x28] = "ME in temp disable", + [0x32] = "M0 kernel load", +}; + +/* Progress Code 3 states */ +static const char *const me_progress_policy_values[] = { + [0x00] = "Entery into Policy Module", + [0x03] = "Received S3 entry", + [0x04] = "Received S4 entry", + [0x05] = "Received S5 entry", + [0x06] = "Received UPD entry", + [0x07] = "Received PCR entry", + [0x08] = "Received NPCR entry", + [0x09] = "Received host wake", + [0x0a] = "Received AC<>DC switch", + [0x0b] = "Received DRAM Init Done", + [0x0c] = "VSCC Data not found for flash device", + [0x0d] = "VSCC Table is not valid", + [0x0e] = "Flash Partition Boundary is outside address space", + [0x0f] = "ME cannot access the chipset descriptor region", + [0x10] = "Required VSCC values for flash parts do not match", +}; + +void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes) +{ + /* Check Current States */ + debug("ME: FW Partition Table : %s\n", + hfs->fpt_bad ? "BAD" : "OK"); + debug("ME: Bringup Loader Failure : %s\n", + hfs->ft_bup_ld_flr ? "YES" : "NO"); + debug("ME: Firmware Init Complete : %s\n", + hfs->fw_init_complete ? "YES" : "NO"); + debug("ME: Manufacturing Mode : %s\n", + hfs->mfg_mode ? "YES" : "NO"); + debug("ME: Boot Options Present : %s\n", + hfs->boot_options_present ? "YES" : "NO"); + debug("ME: Update In Progress : %s\n", + hfs->update_in_progress ? "YES" : "NO"); + debug("ME: Current Working State : %s\n", + me_cws_values[hfs->working_state]); + debug("ME: Current Operation State : %s\n", + me_opstate_values[hfs->operation_state]); + debug("ME: Current Operation Mode : %s\n", + me_opmode_values[hfs->operation_mode]); + debug("ME: Error Code : %s\n", + me_error_values[hfs->error_code]); + debug("ME: Progress Phase : %s\n", + me_progress_values[gmes->progress_code]); + debug("ME: Power Management Event : %s\n", + me_pmevent_values[gmes->current_pmevent]); + + debug("ME: Progress Phase State : "); + switch (gmes->progress_code) { + case ME_GMES_PHASE_ROM: /* ROM Phase */ + debug("%s", me_progress_rom_values[gmes->current_state]); + break; + + case ME_GMES_PHASE_BUP: /* Bringup Phase */ + if (gmes->current_state < ARRAY_SIZE(me_progress_bup_values) && + me_progress_bup_values[gmes->current_state]) + debug("%s", + me_progress_bup_values[gmes->current_state]); + else + debug("0x%02x", gmes->current_state); + break; + + case ME_GMES_PHASE_POLICY: /* Policy Module Phase */ + if (gmes->current_state < + ARRAY_SIZE(me_progress_policy_values) && + me_progress_policy_values[gmes->current_state]) + debug("%s", + me_progress_policy_values[gmes->current_state]); + else + debug("0x%02x", gmes->current_state); + break; + + case ME_GMES_PHASE_HOST: /* Host Communication Phase */ + if (!gmes->current_state) + debug("Host communication established"); + else + debug("0x%02x", gmes->current_state); + break; + + default: + debug("Unknown 0x%02x", gmes->current_state); + } + debug("\n"); +} diff --git a/arch/x86/cpu/ivybridge/report_platform.c b/arch/x86/cpu/ivybridge/report_platform.c new file mode 100644 index 0000000..69e31b3 --- /dev/null +++ b/arch/x86/cpu/ivybridge/report_platform.c @@ -0,0 +1,89 @@ +/* + * From Coreboot src/northbridge/intel/sandybridge/report_platform.c + * + * Copyright (C) 2012 Google Inc. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include +#include + +static void report_cpu_info(void) +{ + char cpu_string[CPU_MAX_NAME_LEN], *cpu_name; + const char *mode[] = {"NOT ", ""}; + struct cpuid_result cpuidr; + int vt, txt, aes; + u32 index; + + index = 0x80000000; + cpuidr = cpuid(index); + if (cpuidr.eax < 0x80000004) { + strcpy(cpu_string, "Platform info not available"); + cpu_name = cpu_string; + } else { + cpu_name = cpu_get_name(cpu_string); + } + + cpuidr = cpuid(1); + debug("CPU id(%x): %s\n", cpuidr.eax, cpu_name); + aes = (cpuidr.ecx & (1 << 25)) ? 1 : 0; + txt = (cpuidr.ecx & (1 << 6)) ? 1 : 0; + vt = (cpuidr.ecx & (1 << 5)) ? 1 : 0; + debug("AES %ssupported, TXT %ssupported, VT %ssupported\n", + mode[aes], mode[txt], mode[vt]); +} + +/* The PCI id name match comes from Intel document 472178 */ +static struct { + u16 dev_id; + const char *dev_name; +} pch_table[] = { + {0x1E41, "Desktop Sample"}, + {0x1E42, "Mobile Sample"}, + {0x1E43, "SFF Sample"}, + {0x1E44, "Z77"}, + {0x1E45, "H71"}, + {0x1E46, "Z75"}, + {0x1E47, "Q77"}, + {0x1E48, "Q75"}, + {0x1E49, "B75"}, + {0x1E4A, "H77"}, + {0x1E53, "C216"}, + {0x1E55, "QM77"}, + {0x1E56, "QS77"}, + {0x1E58, "UM77"}, + {0x1E57, "HM77"}, + {0x1E59, "HM76"}, + {0x1E5D, "HM75"}, + {0x1E5E, "HM70"}, + {0x1E5F, "NM70"}, +}; + +static void report_pch_info(void) +{ + const char *pch_type = "Unknown"; + int i; + u16 dev_id; + uint8_t rev_id; + + dev_id = pci_read_config16(PCH_LPC_DEV, 2); + for (i = 0; i < ARRAY_SIZE(pch_table); i++) { + if (pch_table[i].dev_id == dev_id) { + pch_type = pch_table[i].dev_name; + break; + } + } + rev_id = pci_read_config8(PCH_LPC_DEV, 8); + debug("PCH type: %s, device id: %x, rev id %x\n", pch_type, dev_id, + rev_id); +} + +void report_platform_info(void) +{ + report_cpu_info(); + report_pch_info(); +} diff --git a/arch/x86/cpu/ivybridge/sdram.c b/arch/x86/cpu/ivybridge/sdram.c index 5f9ae5e..df2b990 100644 --- a/arch/x86/cpu/ivybridge/sdram.c +++ b/arch/x86/cpu/ivybridge/sdram.c @@ -11,10 +11,561 @@ */ #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* + * This function looks for the highest region of memory lower than 4GB which + * has enough space for U-Boot where U-Boot is aligned on a page boundary. + * It overrides the default implementation found elsewhere which simply + * picks the end of ram, wherever that may be. The location of the stack, + * the relocation address, and how far U-Boot is moved by relocation are + * set in the global data structure. + */ +ulong board_get_usable_ram_top(ulong total_size) +{ + struct memory_info *info = &gd->arch.meminfo; + uintptr_t dest_addr = 0; + struct memory_area *largest = NULL; + int i; + + /* Find largest area of memory below 4GB */ + + for (i = 0; i < info->num_areas; i++) { + struct memory_area *area = &info->area[i]; + + if (area->start >= 1ULL << 32) + continue; + if (!largest || area->size > largest->size) + largest = area; + } + + /* If no suitable area was found, return an error. */ + assert(largest); + if (!largest || largest->size < (2 << 20)) + panic("No available memory found for relocation"); + + dest_addr = largest->start + largest->size; + + return (ulong)dest_addr; +} + +void dram_init_banksize(void) +{ + struct memory_info *info = &gd->arch.meminfo; + int num_banks; + int i; + + for (i = 0, num_banks = 0; i < info->num_areas; i++) { + struct memory_area *area = &info->area[i]; + + if (area->start >= 1ULL << 32) + continue; + gd->bd->bi_dram[num_banks].start = area->start; + gd->bd->bi_dram[num_banks].size = area->size; + num_banks++; + } +} + +static const char *const ecc_decoder[] = { + "inactive", + "active on IO", + "disabled on IO", + "active" +}; + +/* + * Dump in the log memory controller configuration as read from the memory + * controller registers. + */ +static void report_memory_config(void) +{ + u32 addr_decoder_common, addr_decode_ch[2]; + int i; + + addr_decoder_common = readl(MCHBAR_REG(0x5000)); + addr_decode_ch[0] = readl(MCHBAR_REG(0x5004)); + addr_decode_ch[1] = readl(MCHBAR_REG(0x5008)); + + debug("memcfg DDR3 clock %d MHz\n", + (readl(MCHBAR_REG(0x5e04)) * 13333 * 2 + 50) / 100); + debug("memcfg channel assignment: A: %d, B % d, C % d\n", + addr_decoder_common & 3, + (addr_decoder_common >> 2) & 3, + (addr_decoder_common >> 4) & 3); + + for (i = 0; i < ARRAY_SIZE(addr_decode_ch); i++) { + u32 ch_conf = addr_decode_ch[i]; + debug("memcfg channel[%d] config (%8.8x):\n", i, ch_conf); + debug(" ECC %s\n", ecc_decoder[(ch_conf >> 24) & 3]); + debug(" enhanced interleave mode %s\n", + ((ch_conf >> 22) & 1) ? "on" : "off"); + debug(" rank interleave %s\n", + ((ch_conf >> 21) & 1) ? "on" : "off"); + debug(" DIMMA %d MB width x%d %s rank%s\n", + ((ch_conf >> 0) & 0xff) * 256, + ((ch_conf >> 19) & 1) ? 16 : 8, + ((ch_conf >> 17) & 1) ? "dual" : "single", + ((ch_conf >> 16) & 1) ? "" : ", selected"); + debug(" DIMMB %d MB width x%d %s rank%s\n", + ((ch_conf >> 8) & 0xff) * 256, + ((ch_conf >> 20) & 1) ? 16 : 8, + ((ch_conf >> 18) & 1) ? "dual" : "single", + ((ch_conf >> 16) & 1) ? ", selected" : ""); + } +} + +static void post_system_agent_init(struct pei_data *pei_data) +{ + /* If PCIe init is skipped, set the PEG clock gating */ + if (!pei_data->pcie_init) + setbits_le32(MCHBAR_REG(0x7010), 1); +} + +static asmlinkage void console_tx_byte(unsigned char byte) +{ +#ifdef DEBUG + putc(byte); +#endif +} + +/** + * Find the PEI executable in the ROM and execute it. + * + * @param pei_data: configuration data for UEFI PEI reference code + */ +int sdram_initialise(struct pei_data *pei_data) +{ + unsigned version; + const char *data; + uint16_t done; + int ret; + + report_platform_info(); + + /* Wait for ME to be ready */ + ret = intel_early_me_init(); + if (ret) + return ret; + ret = intel_early_me_uma_size(); + if (ret < 0) + return ret; + + debug("Starting UEFI PEI System Agent\n"); + + /* If MRC data is not found we cannot continue S3 resume. */ + if (pei_data->boot_mode == PEI_BOOT_RESUME && !pei_data->mrc_input) { + debug("Giving up in sdram_initialize: No MRC data\n"); + outb(0x6, PORT_RESET); + cpu_hlt(); + } + + /* Pass console handler in pei_data */ + pei_data->tx_byte = console_tx_byte; + + debug("PEI data at %p, size %x:\n", pei_data, sizeof(*pei_data)); + + data = (char *)CONFIG_X86_MRC_START; + if (data) { + int rv; + int (*func)(struct pei_data *); + + debug("Calling MRC at %p\n", data); + post_code(POST_PRE_MRC); + func = (int (*)(struct pei_data *))data; + rv = func(pei_data); + post_code(POST_MRC); + if (rv) { + switch (rv) { + case -1: + printf("PEI version mismatch.\n"); + break; + case -2: + printf("Invalid memory frequency.\n"); + break; + default: + printf("MRC returned %x.\n", rv); + } + printf("Nonzero MRC return value.\n"); + return -EFAULT; + } + } else { + printf("UEFI PEI System Agent not found.\n"); + return -ENOSYS; + } + +#if CONFIG_USBDEBUG + /* mrc.bin reconfigures USB, so reinit it to have debug */ + early_usbdebug_init(); +#endif + + version = readl(MCHBAR_REG(0x5034)); + debug("System Agent Version %d.%d.%d Build %d\n", + version >> 24 , (version >> 16) & 0xff, + (version >> 8) & 0xff, version & 0xff); + + /* + * Send ME init done for SandyBridge here. This is done inside the + * SystemAgent binary on IvyBridge + */ + done = pci_read_config32(PCH_DEV, PCI_DEVICE_ID); + done &= BASE_REV_MASK; + if (BASE_REV_SNB == done) + intel_early_me_init_done(ME_INIT_STATUS_SUCCESS); + else + intel_early_me_status(); + + post_system_agent_init(pei_data); + report_memory_config(); + + return 0; +} + +static int copy_spd(struct pei_data *peid) +{ + const int gpio_vector[] = {41, 42, 43, 10, -1}; + int spd_index; + const void *blob = gd->fdt_blob; + int node, spd_node; + int ret, i; + + for (i = 0; ; i++) { + if (gpio_vector[i] == -1) + break; + ret = gpio_requestf(gpio_vector[i], "spd_id%d", i); + if (ret) { + debug("%s: Could not request gpio %d\n", __func__, + gpio_vector[i]); + return ret; + } + } + spd_index = gpio_get_values_as_int(gpio_vector); + debug("spd index %d\n", spd_index); + node = fdtdec_next_compatible(blob, 0, COMPAT_MEMORY_SPD); + if (node < 0) { + printf("SPD data not found.\n"); + return -ENOENT; + } + + for (spd_node = fdt_first_subnode(blob, node); + spd_node > 0; + spd_node = fdt_next_subnode(blob, spd_node)) { + const char *data; + int len; + + if (fdtdec_get_int(blob, spd_node, "reg", -1) != spd_index) + continue; + data = fdt_getprop(blob, spd_node, "data", &len); + if (len < sizeof(peid->spd_data[0])) { + printf("Missing SPD data\n"); + return -EINVAL; + } + + debug("Using SDRAM SPD data for '%s'\n", + fdt_get_name(blob, spd_node, NULL)); + memcpy(peid->spd_data[0], data, sizeof(peid->spd_data[0])); + break; + } + + if (spd_node < 0) { + printf("No SPD data found for index %d\n", spd_index); + return -ENOENT; + } + + return 0; +} + +/** + * add_memory_area() - Add a new usable memory area to our list + * + * Note: @start and @end must not span the first 4GB boundary + * + * @info: Place to store memory info + * @start: Start of this memory area + * @end: End of this memory area + 1 + */ +static int add_memory_area(struct memory_info *info, + uint64_t start, uint64_t end) +{ + struct memory_area *ptr; + + if (info->num_areas == CONFIG_NR_DRAM_BANKS) + return -ENOSPC; + + ptr = &info->area[info->num_areas]; + ptr->start = start; + ptr->size = end - start; + info->total_memory += ptr->size; + if (ptr->start < (1ULL << 32)) + info->total_32bit_memory += ptr->size; + debug("%d: memory %llx size %llx, total now %llx / %llx\n", + info->num_areas, ptr->start, ptr->size, + info->total_32bit_memory, info->total_memory); + info->num_areas++; + + return 0; +} + +/** + * sdram_find() - Find available memory + * + * This is a bit complicated since on x86 there are system memory holes all + * over the place. We create a list of available memory blocks + */ +static int sdram_find(pci_dev_t dev) +{ + struct memory_info *info = &gd->arch.meminfo; + uint32_t tseg_base, uma_size, tolud; + uint64_t tom, me_base, touud; + uint64_t uma_memory_base = 0; + uint64_t uma_memory_size; + unsigned long long tomk; + uint16_t ggc; + + /* Total Memory 2GB example: + * + * 00000000 0000MB-1992MB 1992MB RAM (writeback) + * 7c800000 1992MB-2000MB 8MB TSEG (SMRR) + * 7d000000 2000MB-2002MB 2MB GFX GTT (uncached) + * 7d200000 2002MB-2034MB 32MB GFX UMA (uncached) + * 7f200000 2034MB TOLUD + * 7f800000 2040MB MEBASE + * 7f800000 2040MB-2048MB 8MB ME UMA (uncached) + * 80000000 2048MB TOM + * 100000000 4096MB-4102MB 6MB RAM (writeback) + * + * Total Memory 4GB example: + * + * 00000000 0000MB-2768MB 2768MB RAM (writeback) + * ad000000 2768MB-2776MB 8MB TSEG (SMRR) + * ad800000 2776MB-2778MB 2MB GFX GTT (uncached) + * ada00000 2778MB-2810MB 32MB GFX UMA (uncached) + * afa00000 2810MB TOLUD + * ff800000 4088MB MEBASE + * ff800000 4088MB-4096MB 8MB ME UMA (uncached) + * 100000000 4096MB TOM + * 100000000 4096MB-5374MB 1278MB RAM (writeback) + * 14fe00000 5368MB TOUUD + */ + + /* Top of Upper Usable DRAM, including remap */ + touud = pci_read_config32(dev, TOUUD+4); + touud <<= 32; + touud |= pci_read_config32(dev, TOUUD); + + /* Top of Lower Usable DRAM */ + tolud = pci_read_config32(dev, TOLUD); + + /* Top of Memory - does not account for any UMA */ + tom = pci_read_config32(dev, 0xa4); + tom <<= 32; + tom |= pci_read_config32(dev, 0xa0); + + debug("TOUUD %llx TOLUD %08x TOM %llx\n", touud, tolud, tom); + + /* ME UMA needs excluding if total memory <4GB */ + me_base = pci_read_config32(dev, 0x74); + me_base <<= 32; + me_base |= pci_read_config32(dev, 0x70); + + debug("MEBASE %llx\n", me_base); + + /* TODO: Get rid of all this shifting by 10 bits */ + tomk = tolud >> 10; + if (me_base == tolud) { + /* ME is from MEBASE-TOM */ + uma_size = (tom - me_base) >> 10; + /* Increment TOLUD to account for ME as RAM */ + tolud += uma_size << 10; + /* UMA starts at old TOLUD */ + uma_memory_base = tomk * 1024ULL; + uma_memory_size = uma_size * 1024ULL; + debug("ME UMA base %llx size %uM\n", me_base, uma_size >> 10); + } + + /* Graphics memory comes next */ + ggc = pci_read_config16(dev, GGC); + if (!(ggc & 2)) { + debug("IGD decoded, subtracting "); + + /* Graphics memory */ + uma_size = ((ggc >> 3) & 0x1f) * 32 * 1024ULL; + debug("%uM UMA", uma_size >> 10); + tomk -= uma_size; + uma_memory_base = tomk * 1024ULL; + uma_memory_size += uma_size * 1024ULL; + + /* GTT Graphics Stolen Memory Size (GGMS) */ + uma_size = ((ggc >> 8) & 0x3) * 1024ULL; + tomk -= uma_size; + uma_memory_base = tomk * 1024ULL; + uma_memory_size += uma_size * 1024ULL; + debug(" and %uM GTT\n", uma_size >> 10); + } + + /* Calculate TSEG size from its base which must be below GTT */ + tseg_base = pci_read_config32(dev, 0xb8); + uma_size = (uma_memory_base - tseg_base) >> 10; + tomk -= uma_size; + uma_memory_base = tomk * 1024ULL; + uma_memory_size += uma_size * 1024ULL; + debug("TSEG base 0x%08x size %uM\n", tseg_base, uma_size >> 10); + + debug("Available memory below 4GB: %lluM\n", tomk >> 10); + + /* Report the memory regions */ + add_memory_area(info, 1 << 20, 2 << 28); + 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); + /* + * If >= 4GB installed then memory from TOLUD to 4GB + * is remapped above TOM, TOUUD will account for both + */ + if (touud > (1ULL << 32ULL)) { + debug("Available memory above 4GB: %lluM\n", + (touud >> 20) - 4096); + } + + return 0; +} + +static void rcba_config(void) +{ + /* + * GFX INTA -> PIRQA (MSI) + * D28IP_P3IP WLAN INTA -> PIRQB + * D29IP_E1P EHCI1 INTA -> PIRQD + * D26IP_E2P EHCI2 INTA -> PIRQF + * D31IP_SIP SATA INTA -> PIRQF (MSI) + * D31IP_SMIP SMBUS INTB -> PIRQH + * D31IP_TTIP THRT INTC -> PIRQA + * D27IP_ZIP HDA INTA -> PIRQA (MSI) + * + * TRACKPAD -> PIRQE (Edge Triggered) + * TOUCHSCREEN -> PIRQG (Edge Triggered) + */ + + /* Device interrupt pin register (board specific) */ + writel((INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) | + (INTB << D31IP_SMIP) | (INTA << D31IP_SIP), RCB_REG(D31IP)); + writel(NOINT << D30IP_PIP, RCB_REG(D30IP)); + writel(INTA << D29IP_E1P, RCB_REG(D29IP)); + writel(INTA << D28IP_P3IP, RCB_REG(D28IP)); + writel(INTA << D27IP_ZIP, RCB_REG(D27IP)); + writel(INTA << D26IP_E2P, RCB_REG(D26IP)); + writel(NOINT << D25IP_LIP, RCB_REG(D25IP)); + writel(NOINT << D22IP_MEI1IP, RCB_REG(D22IP)); + + /* Device interrupt route registers */ + writel(DIR_ROUTE(PIRQB, PIRQH, PIRQA, PIRQC), RCB_REG(D31IR)); + writel(DIR_ROUTE(PIRQD, PIRQE, PIRQF, PIRQG), RCB_REG(D29IR)); + writel(DIR_ROUTE(PIRQB, PIRQC, PIRQD, PIRQE), RCB_REG(D28IR)); + writel(DIR_ROUTE(PIRQA, PIRQH, PIRQA, PIRQB), RCB_REG(D27IR)); + writel(DIR_ROUTE(PIRQF, PIRQE, PIRQG, PIRQH), RCB_REG(D26IR)); + writel(DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD), RCB_REG(D25IR)); + writel(DIR_ROUTE(PIRQA, PIRQB, PIRQC, PIRQD), RCB_REG(D22IR)); + + /* Enable IOAPIC (generic) */ + writew(0x0100, RCB_REG(OIC)); + /* PCH BWG says to read back the IOAPIC enable register */ + (void)readw(RCB_REG(OIC)); + + /* Disable unused devices (board specific) */ + setbits_le32(RCB_REG(FD), PCH_DISABLE_ALWAYS); +} int dram_init(void) { - /* TODO: Set up DRAM */ + struct pei_data pei_data __aligned(8) = { + .pei_version = PEI_VERSION, + .mchbar = DEFAULT_MCHBAR, + .dmibar = DEFAULT_DMIBAR, + .epbar = DEFAULT_EPBAR, + .pciexbar = CONFIG_MMCONF_BASE_ADDRESS, + .smbusbar = SMBUS_IO_BASE, + .wdbbar = 0x4000000, + .wdbsize = 0x1000, + .hpet_address = CONFIG_HPET_ADDRESS, + .rcba = DEFAULT_RCBABASE, + .pmbase = DEFAULT_PMBASE, + .gpiobase = DEFAULT_GPIOBASE, + .thermalbase = 0xfed08000, + .system_type = 0, /* 0 Mobile, 1 Desktop/Server */ + .tseg_size = CONFIG_SMM_TSEG_SIZE, + .ts_addresses = { 0x00, 0x00, 0x00, 0x00 }, + .ec_present = 1, + .ddr3lv_support = 1, + /* + * 0 = leave channel enabled + * 1 = disable dimm 0 on channel + * 2 = disable dimm 1 on channel + * 3 = disable dimm 0+1 on channel + */ + .dimm_channel0_disabled = 2, + .dimm_channel1_disabled = 2, + .max_ddr3_freq = 1600, + .usb_port_config = { + /* + * Empty and onboard Ports 0-7, set to un-used pin + * OC3 + */ + { 0, 3, 0x0000 }, /* P0= Empty */ + { 1, 0, 0x0040 }, /* P1= Left USB 1 (OC0) */ + { 1, 1, 0x0040 }, /* P2= Left USB 2 (OC1) */ + { 1, 3, 0x0040 }, /* P3= SDCARD (no OC) */ + { 0, 3, 0x0000 }, /* P4= Empty */ + { 1, 3, 0x0040 }, /* P5= WWAN (no OC) */ + { 0, 3, 0x0000 }, /* P6= Empty */ + { 0, 3, 0x0000 }, /* P7= Empty */ + /* + * Empty and onboard Ports 8-13, set to un-used pin + * OC4 + */ + { 1, 4, 0x0040 }, /* P8= Camera (no OC) */ + { 1, 4, 0x0040 }, /* P9= Bluetooth (no OC) */ + { 0, 4, 0x0000 }, /* P10= Empty */ + { 0, 4, 0x0000 }, /* P11= Empty */ + { 0, 4, 0x0000 }, /* P12= Empty */ + { 0, 4, 0x0000 }, /* P13= Empty */ + }, + }; + pci_dev_t dev = PCI_BDF(0, 0, 0); + int ret; + + debug("Boot mode %d\n", gd->arch.pei_boot_mode); + debug("mcr_input %p\n", pei_data.mrc_input); + pei_data.boot_mode = gd->arch.pei_boot_mode; + ret = copy_spd(&pei_data); + if (!ret) + ret = sdram_initialise(&pei_data); + if (ret) + return ret; + + rcba_config(); + quick_ram_check(); + + writew(0xCAFE, MCHBAR_REG(SSKPD)); + + post_code(POST_DRAM); + + ret = sdram_find(dev); + if (ret) + return ret; + + gd->ram_size = gd->arch.meminfo.total_32bit_memory; return 0; } diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S index 1b738f9..b0d0ac0 100644 --- a/arch/x86/cpu/start.S +++ b/arch/x86/cpu/start.S @@ -78,20 +78,22 @@ car_init_ret: * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM, * or fully initialised SDRAM - we really don't care which) * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack - * and early malloc area. + * and early malloc area. The MRC requires some space at the top. * * Stack grows down from top of CAR. We have: * * top-> CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE + * MRC area * global_data * x86 global descriptor table * early malloc area * stack * bottom-> CONFIG_SYS_CAR_ADDR */ - - /* Stack grows down from top of CAR */ - movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE), %esp + movl $(CONFIG_SYS_CAR_ADDR + CONFIG_SYS_CAR_SIZE - 4), %esp +#ifdef CONFIG_DCACHE_RAM_MRC_VAR_SIZE + subl $CONFIG_DCACHE_RAM_MRC_VAR_SIZE, %esp +#endif /* Reserve space on stack for global data */ subl $GENERATED_GBL_DATA_SIZE, %esp diff --git a/arch/x86/dts/link.dts b/arch/x86/dts/link.dts index 74b2198..9329916 100644 --- a/arch/x86/dts/link.dts +++ b/arch/x86/dts/link.dts @@ -41,6 +41,117 @@ chosen { }; memory { device_type = "memory"; reg = <0 0>; }; + spd { + compatible = "memory-spd"; + #address-cells = <1>; + #size-cells = <0>; + elpida_4Gb_1600_x16 { + reg = <0>; + data = [92 10 0b 03 04 19 02 02 + 03 52 01 08 0a 00 fe 00 + 69 78 69 3c 69 11 18 81 + 20 08 3c 3c 01 40 83 81 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 0f 11 42 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 02 fe 00 + 11 52 00 00 00 07 7f 37 + 45 42 4a 32 30 55 47 36 + 45 42 55 30 2d 47 4e 2d + 46 20 30 20 02 fe 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00]; + }; + samsung_4Gb_1600_1.35v_x16 { + reg = <1>; + data = [92 11 0b 03 04 19 02 02 + 03 11 01 08 0a 00 fe 00 + 69 78 69 3c 69 11 18 81 + f0 0a 3c 3c 01 40 83 01 + 00 80 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 0f 11 02 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 80 ce 01 + 00 00 00 00 00 00 6a 04 + 4d 34 37 31 42 35 36 37 + 34 42 48 30 2d 59 4b 30 + 20 20 00 00 80 ce 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00]; + }; + micron_4Gb_1600_1.35v_x16 { + reg = <2>; + data = [92 11 0b 03 04 19 02 02 + 03 11 01 08 0a 00 fe 00 + 69 78 69 3c 69 11 18 81 + 20 08 3c 3c 01 40 83 05 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 0f 01 02 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 80 2c 00 + 00 00 00 00 00 00 ad 75 + 34 4b 54 46 32 35 36 36 + 34 48 5a 2d 31 47 36 45 + 31 20 45 31 80 2c 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff + ff ff ff ff ff ff ff ff]; + }; + }; + spi { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/x86/include/asm/arch-ivybridge/me.h b/arch/x86/include/asm/arch-ivybridge/me.h new file mode 100644 index 0000000..3a0809d --- /dev/null +++ b/arch/x86/include/asm/arch-ivybridge/me.h @@ -0,0 +1,356 @@ +/* + * From Coreboot src/southbridge/intel/bd82x6x/me.h + * + * Copyright (C) 2011 The Chromium OS Authors. All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef _ASM_INTEL_ME_H +#define _ASM_INTEL_ME_H + +#include +#include + +#define ME_RETRY 100000 /* 1 second */ +#define ME_DELAY 10 /* 10 us */ + +/* + * Management Engine PCI registers + */ + +#define PCI_CPU_MEBASE_L 0x70 /* Set by MRC */ +#define PCI_CPU_MEBASE_H 0x74 /* Set by MRC */ + +#define PCI_ME_HFS 0x40 +#define ME_HFS_CWS_RESET 0 +#define ME_HFS_CWS_INIT 1 +#define ME_HFS_CWS_REC 2 +#define ME_HFS_CWS_NORMAL 5 +#define ME_HFS_CWS_WAIT 6 +#define ME_HFS_CWS_TRANS 7 +#define ME_HFS_CWS_INVALID 8 +#define ME_HFS_STATE_PREBOOT 0 +#define ME_HFS_STATE_M0_UMA 1 +#define ME_HFS_STATE_M3 4 +#define ME_HFS_STATE_M0 5 +#define ME_HFS_STATE_BRINGUP 6 +#define ME_HFS_STATE_ERROR 7 +#define ME_HFS_ERROR_NONE 0 +#define ME_HFS_ERROR_UNCAT 1 +#define ME_HFS_ERROR_IMAGE 3 +#define ME_HFS_ERROR_DEBUG 4 +#define ME_HFS_MODE_NORMAL 0 +#define ME_HFS_MODE_DEBUG 2 +#define ME_HFS_MODE_DIS 3 +#define ME_HFS_MODE_OVER_JMPR 4 +#define ME_HFS_MODE_OVER_MEI 5 +#define ME_HFS_BIOS_DRAM_ACK 1 +#define ME_HFS_ACK_NO_DID 0 +#define ME_HFS_ACK_RESET 1 +#define ME_HFS_ACK_PWR_CYCLE 2 +#define ME_HFS_ACK_S3 3 +#define ME_HFS_ACK_S4 4 +#define ME_HFS_ACK_S5 5 +#define ME_HFS_ACK_GBL_RESET 6 +#define ME_HFS_ACK_CONTINUE 7 + +struct me_hfs { + u32 working_state:4; + u32 mfg_mode:1; + u32 fpt_bad:1; + u32 operation_state:3; + u32 fw_init_complete:1; + u32 ft_bup_ld_flr:1; + u32 update_in_progress:1; + u32 error_code:4; + u32 operation_mode:4; + u32 reserved:4; + u32 boot_options_present:1; + u32 ack_data:3; + u32 bios_msg_ack:4; +} __packed; + +#define PCI_ME_UMA 0x44 + +struct me_uma { + u32 size:6; + u32 reserved_1:10; + u32 valid:1; + u32 reserved_0:14; + u32 set_to_one:1; +} __packed; + +#define PCI_ME_H_GS 0x4c +#define ME_INIT_DONE 1 +#define ME_INIT_STATUS_SUCCESS 0 +#define ME_INIT_STATUS_NOMEM 1 +#define ME_INIT_STATUS_ERROR 2 + +struct me_did { + u32 uma_base:16; + u32 reserved:8; + u32 status:4; + u32 init_done:4; +} __packed; + +#define PCI_ME_GMES 0x48 +#define ME_GMES_PHASE_ROM 0 +#define ME_GMES_PHASE_BUP 1 +#define ME_GMES_PHASE_UKERNEL 2 +#define ME_GMES_PHASE_POLICY 3 +#define ME_GMES_PHASE_MODULE 4 +#define ME_GMES_PHASE_UNKNOWN 5 +#define ME_GMES_PHASE_HOST 6 + +struct me_gmes { + u32 bist_in_prog:1; + u32 icc_prog_sts:2; + u32 invoke_mebx:1; + u32 cpu_replaced_sts:1; + u32 mbp_rdy:1; + u32 mfs_failure:1; + u32 warm_rst_req_for_df:1; + u32 cpu_replaced_valid:1; + u32 reserved_1:2; + u32 fw_upd_ipu:1; + u32 reserved_2:4; + u32 current_state:8; + u32 current_pmevent:4; + u32 progress_code:4; +} __packed; + +#define PCI_ME_HERES 0xbc +#define PCI_ME_EXT_SHA1 0x00 +#define PCI_ME_EXT_SHA256 0x02 +#define PCI_ME_HER(x) (0xc0+(4*(x))) + +struct me_heres { + u32 extend_reg_algorithm:4; + u32 reserved:26; + u32 extend_feature_present:1; + u32 extend_reg_valid:1; +} __packed; + +/* + * Management Engine MEI registers + */ + +#define MEI_H_CB_WW 0x00 +#define MEI_H_CSR 0x04 +#define MEI_ME_CB_RW 0x08 +#define MEI_ME_CSR_HA 0x0c + +struct mei_csr { + u32 interrupt_enable:1; + u32 interrupt_status:1; + u32 interrupt_generate:1; + u32 ready:1; + u32 reset:1; + u32 reserved:3; + u32 buffer_read_ptr:8; + u32 buffer_write_ptr:8; + u32 buffer_depth:8; +} __packed; + +#define MEI_ADDRESS_CORE 0x01 +#define MEI_ADDRESS_AMT 0x02 +#define MEI_ADDRESS_RESERVED 0x03 +#define MEI_ADDRESS_WDT 0x04 +#define MEI_ADDRESS_MKHI 0x07 +#define MEI_ADDRESS_ICC 0x08 +#define MEI_ADDRESS_THERMAL 0x09 + +#define MEI_HOST_ADDRESS 0 + +struct mei_header { + u32 client_address:8; + u32 host_address:8; + u32 length:9; + u32 reserved:6; + u32 is_complete:1; +} __packed; + +#define MKHI_GROUP_ID_CBM 0x00 +#define MKHI_GROUP_ID_FWCAPS 0x03 +#define MKHI_GROUP_ID_MDES 0x08 +#define MKHI_GROUP_ID_GEN 0xff + +#define MKHI_GLOBAL_RESET 0x0b + +#define MKHI_FWCAPS_GET_RULE 0x02 + +#define MKHI_MDES_ENABLE 0x09 + +#define MKHI_GET_FW_VERSION 0x02 +#define MKHI_END_OF_POST 0x0c +#define MKHI_FEATURE_OVERRIDE 0x14 + +struct mkhi_header { + u32 group_id:8; + u32 command:7; + u32 is_response:1; + u32 reserved:8; + u32 result:8; +} __packed; + +struct me_fw_version { + u16 code_minor; + u16 code_major; + u16 code_build_number; + u16 code_hot_fix; + u16 recovery_minor; + u16 recovery_major; + u16 recovery_build_number; + u16 recovery_hot_fix; +} __packed; + + +#define HECI_EOP_STATUS_SUCCESS 0x0 +#define HECI_EOP_PERFORM_GLOBAL_RESET 0x1 + +#define CBM_RR_GLOBAL_RESET 0x01 + +#define GLOBAL_RESET_BIOS_MRC 0x01 +#define GLOBAL_RESET_BIOS_POST 0x02 +#define GLOBAL_RESET_MEBX 0x03 + +struct me_global_reset { + u8 request_origin; + u8 reset_type; +} __packed; + +enum me_bios_path { + ME_NORMAL_BIOS_PATH, + ME_S3WAKE_BIOS_PATH, + ME_ERROR_BIOS_PATH, + ME_RECOVERY_BIOS_PATH, + ME_DISABLE_BIOS_PATH, + ME_FIRMWARE_UPDATE_BIOS_PATH, +}; + +struct __packed mbp_fw_version_name { + u32 major_version:16; + u32 minor_version:16; + u32 hotfix_version:16; + u32 build_version:16; +}; + +struct __packed mbp_icc_profile { + u8 num_icc_profiles; + u8 icc_profile_soft_strap; + u8 icc_profile_index; + u8 reserved; + u32 register_lock_mask[3]; +}; + +struct __packed mefwcaps_sku { + u32 full_net:1; + u32 std_net:1; + u32 manageability:1; + u32 small_business:1; + u32 l3manageability:1; + u32 intel_at:1; + u32 intel_cls:1; + u32 reserved:3; + u32 intel_mpc:1; + u32 icc_over_clocking:1; + u32 pavp:1; + u32 reserved_1:4; + u32 ipv6:1; + u32 kvm:1; + u32 och:1; + u32 vlan:1; + u32 tls:1; + u32 reserved_4:1; + u32 wlan:1; + u32 reserved_5:8; +}; + +struct __packed tdt_state_flag { + u16 lock_state:1; + u16 authenticate_module:1; + u16 s3authentication:1; + u16 flash_wear_out:1; + u16 flash_variable_security:1; + u16 wwan3gpresent:1; + u16 wwan3goob:1; + u16 reserved:9; +}; + +struct __packed tdt_state_info { + u8 state; + u8 last_theft_trigger; + struct tdt_state_flag flags; +}; + +struct __packed platform_type_rule_data { + u32 platform_target_usage_type:4; + u32 platform_target_market_type:2; + u32 super_sku:1; + u32 reserved:1; + u32 intel_me_fw_image_type:4; + u32 platform_brand:4; + u32 reserved_1:16; +}; + +struct __packed mbp_fw_caps { + struct mefwcaps_sku fw_capabilities; + u8 available; +}; + +struct __packed mbp_rom_bist_data { + u16 device_id; + u16 fuse_test_flags; + u32 umchid[4]; +}; + +struct __packed mbp_platform_key { + u32 key[8]; +}; + +struct __packed mbp_plat_type { + struct platform_type_rule_data rule_data; + u8 available; +}; + +struct __packed me_bios_payload { + struct mbp_fw_version_name fw_version_name; + struct mbp_fw_caps fw_caps_sku; + struct mbp_rom_bist_data rom_bist_data; + struct mbp_platform_key platform_key; + struct mbp_plat_type fw_plat_type; + struct mbp_icc_profile icc_profile; + struct tdt_state_info at_state; + u32 mfsintegrity; +}; + +struct __packed mbp_header { + u32 mbp_size:8; + u32 num_entries:8; + u32 rsvd:16; +}; + +struct __packed mbp_item_header { + u32 app_id:8; + u32 item_id:8; + u32 length:8; + u32 rsvd:8; +}; + +struct __packed me_fwcaps { + u32 id; + u8 length; + struct mefwcaps_sku caps_sku; + u8 reserved[3]; +}; + +/* Defined in me_status.c for both romstage and ramstage */ +void intel_me_status(struct me_hfs *hfs, struct me_gmes *gmes); + +void intel_early_me_status(void); +int intel_early_me_init(void); +int intel_early_me_uma_size(void); +int intel_early_me_init_done(u8 status); + +#endif diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h index ae338e3..c6efdb8 100644 --- a/arch/x86/include/asm/arch-ivybridge/pch.h +++ b/arch/x86/include/asm/arch-ivybridge/pch.h @@ -31,6 +31,13 @@ /* PCI Configuration Space (D31:F0): LPC */ #define PCH_LPC_DEV PCI_BDF(0, 0x1f, 0) +#define GEN_PMCON_1 0xa0 +#define GEN_PMCON_2 0xa2 +#define GEN_PMCON_3 0xa4 +#define ETR3 0xac +#define ETR3_CWORWRE (1 << 18) +#define ETR3_CF9GR (1 << 20) + #define PMBASE 0x40 #define ACPI_CNTL 0x44 #define BIOS_CNTL 0xDC @@ -126,12 +133,97 @@ #define RPC 0x0400 /* 32bit */ #define RPFN 0x0404 /* 32bit */ +#define TRSR 0x1e00 /* 8bit */ +#define TRCR 0x1e10 /* 64bit */ +#define TWDR 0x1e18 /* 64bit */ + +#define IOTR0 0x1e80 /* 64bit */ +#define IOTR1 0x1e88 /* 64bit */ +#define IOTR2 0x1e90 /* 64bit */ +#define IOTR3 0x1e98 /* 64bit */ + +#define TCTL 0x3000 /* 8bit */ + +#define NOINT 0 +#define INTA 1 +#define INTB 2 +#define INTC 3 +#define INTD 4 + +#define DIR_IDR 12 /* Interrupt D Pin Offset */ +#define DIR_ICR 8 /* Interrupt C Pin Offset */ +#define DIR_IBR 4 /* Interrupt B Pin Offset */ +#define DIR_IAR 0 /* Interrupt A Pin Offset */ + +#define PIRQA 0 +#define PIRQB 1 +#define PIRQC 2 +#define PIRQD 3 +#define PIRQE 4 +#define PIRQF 5 +#define PIRQG 6 +#define PIRQH 7 + +/* IO Buffer Programming */ +#define IOBPIRI 0x2330 +#define IOBPD 0x2334 +#define IOBPS 0x2338 +#define IOBPS_RW_BX ((1 << 9)|(1 << 10)) +#define IOBPS_WRITE_AX ((1 << 9)|(1 << 10)) +#define IOBPS_READ_AX ((1 << 8)|(1 << 9)|(1 << 10)) + +#define D31IP 0x3100 /* 32bit */ +#define D31IP_TTIP 24 /* Thermal Throttle Pin */ +#define D31IP_SIP2 20 /* SATA Pin 2 */ +#define D31IP_SMIP 12 /* SMBUS Pin */ +#define D31IP_SIP 8 /* SATA Pin */ +#define D30IP 0x3104 /* 32bit */ +#define D30IP_PIP 0 /* PCI Bridge Pin */ +#define D29IP 0x3108 /* 32bit */ +#define D29IP_E1P 0 /* EHCI #1 Pin */ +#define D28IP 0x310c /* 32bit */ +#define D28IP_P8IP 28 /* PCI Express Port 8 */ +#define D28IP_P7IP 24 /* PCI Express Port 7 */ +#define D28IP_P6IP 20 /* PCI Express Port 6 */ +#define D28IP_P5IP 16 /* PCI Express Port 5 */ +#define D28IP_P4IP 12 /* PCI Express Port 4 */ +#define D28IP_P3IP 8 /* PCI Express Port 3 */ +#define D28IP_P2IP 4 /* PCI Express Port 2 */ +#define D28IP_P1IP 0 /* PCI Express Port 1 */ +#define D27IP 0x3110 /* 32bit */ +#define D27IP_ZIP 0 /* HD Audio Pin */ +#define D26IP 0x3114 /* 32bit */ +#define D26IP_E2P 0 /* EHCI #2 Pin */ +#define D25IP 0x3118 /* 32bit */ +#define D25IP_LIP 0 /* GbE LAN Pin */ +#define D22IP 0x3124 /* 32bit */ +#define D22IP_KTIP 12 /* KT Pin */ +#define D22IP_IDERIP 8 /* IDE-R Pin */ +#define D22IP_MEI2IP 4 /* MEI #2 Pin */ +#define D22IP_MEI1IP 0 /* MEI #1 Pin */ +#define D20IP 0x3128 /* 32bit */ +#define D20IP_XHCIIP 0 +#define D31IR 0x3140 /* 16bit */ +#define D30IR 0x3142 /* 16bit */ +#define D29IR 0x3144 /* 16bit */ +#define D28IR 0x3146 /* 16bit */ +#define D27IR 0x3148 /* 16bit */ +#define D26IR 0x314c /* 16bit */ +#define D25IR 0x3150 /* 16bit */ +#define D22IR 0x315c /* 16bit */ +#define D20IR 0x3160 /* 16bit */ +#define OIC 0x31fe /* 16bit */ + #define SPI_FREQ_SWSEQ 0x3893 #define SPI_DESC_COMP0 0x38b0 #define SPI_FREQ_WR_ERA 0x38b4 #define SOFT_RESET_CTRL 0x38f4 #define SOFT_RESET_DATA 0x38f8 +#define DIR_ROUTE(a, b, c, d) \ + (((d) << DIR_IDR) | ((c) << DIR_ICR) | \ + ((b) << DIR_IBR) | ((a) << DIR_IAR)) + #define RC 0x3400 /* 32bit */ #define HPTC 0x3404 /* 32bit */ #define GCS 0x3410 /* 32bit */ @@ -142,6 +234,27 @@ #define FD2 0x3428 /* 32bit */ #define CG 0x341c /* 32bit */ +/* Function Disable 1 RCBA 0x3418 */ +#define PCH_DISABLE_ALWAYS ((1 << 0)|(1 << 26)) +#define PCH_DISABLE_P2P (1 << 1) +#define PCH_DISABLE_SATA1 (1 << 2) +#define PCH_DISABLE_SMBUS (1 << 3) +#define PCH_DISABLE_HD_AUDIO (1 << 4) +#define PCH_DISABLE_EHCI2 (1 << 13) +#define PCH_DISABLE_LPC (1 << 14) +#define PCH_DISABLE_EHCI1 (1 << 15) +#define PCH_DISABLE_PCIE(x) (1 << (16 + x)) +#define PCH_DISABLE_THERMAL (1 << 24) +#define PCH_DISABLE_SATA2 (1 << 25) +#define PCH_DISABLE_XHCI (1 << 27) + +/* Function Disable 2 RCBA 0x3428 */ +#define PCH_DISABLE_KT (1 << 4) +#define PCH_DISABLE_IDER (1 << 3) +#define PCH_DISABLE_MEI2 (1 << 2) +#define PCH_DISABLE_MEI1 (1 << 1) +#define PCH_ENABLE_DBDF (1 << 0) + /* ICH7 GPIOBASE */ #define GPIO_USE_SEL 0x00 #define GP_IO_SEL 0x04 diff --git a/arch/x86/include/asm/arch-ivybridge/pei_data.h b/arch/x86/include/asm/arch-ivybridge/pei_data.h new file mode 100644 index 0000000..5026c8b --- /dev/null +++ b/arch/x86/include/asm/arch-ivybridge/pei_data.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2011, Google Inc. + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#ifndef ASM_ARCH_PEI_DATA_H +#define ASM_ARCH_PEI_DATA_H + +struct pch_usb3_controller_settings { + /* 0: Disable, 1: Enable, 2: Auto, 3: Smart Auto */ + uint16_t mode; + /* 4 bit mask, 1: switchable, 0: not switchable */ + uint16_t hs_port_switch_mask; + /* 0: No xHCI preOS driver, 1: xHCI preOS driver */ + uint16_t preboot_support; + /* 0: Disable, 1: Enable */ + uint16_t xhci_streams; +}; + +typedef asmlinkage void (*tx_byte_func)(unsigned char byte); + +#define PEI_VERSION 6 + +struct __packed pei_data { + uint32_t pei_version; + uint32_t mchbar; + uint32_t dmibar; + uint32_t epbar; + uint32_t pciexbar; + uint16_t smbusbar; + uint32_t wdbbar; + uint32_t wdbsize; + uint32_t hpet_address; + uint32_t rcba; + uint32_t pmbase; + uint32_t gpiobase; + uint32_t thermalbase; + uint32_t system_type; /* 0 Mobile, 1 Desktop/Server */ + uint32_t tseg_size; + uint8_t spd_addresses[4]; + uint8_t ts_addresses[4]; + int boot_mode; + int ec_present; + int gbe_enable; + /* + * 0 = leave channel enabled + * 1 = disable dimm 0 on channel + * 2 = disable dimm 1 on channel + * 3 = disable dimm 0+1 on channel + */ + int dimm_channel0_disabled; + int dimm_channel1_disabled; + /* Seed values saved in CMOS */ + uint32_t scrambler_seed; + uint32_t scrambler_seed_s3; + /* Data read from flash and passed into MRC */ + unsigned char *mrc_input; + unsigned int mrc_input_len; + /* Data from MRC that should be saved to flash */ + unsigned char *mrc_output; + unsigned int mrc_output_len; + /* + * Max frequency DDR3 could be ran at. Could be one of four values: + * 800, 1067, 1333, 1600 + */ + uint32_t max_ddr3_freq; + /* + * USB Port Configuration: + * [0] = enable + * [1] = overcurrent pin + * [2] = length + * + * Ports 0-7 can be mapped to OC0-OC3 + * Ports 8-13 can be mapped to OC4-OC7 + * + * Port Length + * MOBILE: + * < 0x050 = Setting 1 (back panel, 1-5in, lowest tx amplitude) + * < 0x140 = Setting 2 (back panel, 5-14in, highest tx amplitude) + * DESKTOP: + * < 0x080 = Setting 1 (front/back panel, <8in, lowest tx amplitude) + * < 0x130 = Setting 2 (back panel, 8-13in, higher tx amplitude) + * < 0x150 = Setting 3 (back panel, 13-15in, higest tx amplitude) + */ + uint16_t usb_port_config[16][3]; + /* See the usb3 struct above for details */ + struct pch_usb3_controller_settings usb3; + /* + * SPD data array for onboard RAM. Specify address 0xf0, + * 0xf1, 0xf2, 0xf3 to index one of the 4 slots in + * spd_address for a given "DIMM". + */ + uint8_t spd_data[4][256]; + tx_byte_func tx_byte; + int ddr3lv_support; + /* + * pcie_init needs to be set to 1 to have the system agent initialise + * PCIe. Note: This should only be required if your system has Gen3 + * devices and it will increase your boot time by at least 100ms. + */ + int pcie_init; + /* + * N mode functionality. Leave this setting at 0. + * 0 Auto + * 1 1N + * 2 2N + */ + int nmode; + /* + * DDR refresh rate config. JEDEC Standard No.21-C Annex K allows + * for DIMM SPD data to specify whether double-rate is required for + * extended operating temperature range. + * 0 Enable double rate based upon temperature thresholds + * 1 Normal rate + * 2 Always enable double rate + */ + int ddr_refresh_rate_config; +}; + +#endif diff --git a/arch/x86/include/asm/arch-ivybridge/sandybridge.h b/arch/x86/include/asm/arch-ivybridge/sandybridge.h index a1072f2..114ee19 100644 --- a/arch/x86/include/asm/arch-ivybridge/sandybridge.h +++ b/arch/x86/include/asm/arch-ivybridge/sandybridge.h @@ -102,6 +102,8 @@ #define SSKPD 0x5d14 /* 16bit (scratchpad) */ #define BIOS_RESET_CPL 0x5da8 /* 8bit */ +void report_platform_info(void); + void sandybridge_early_init(int chipset_type); #endif diff --git a/arch/x86/include/asm/config.h b/arch/x86/include/asm/config.h index ff15828..c97d988 100644 --- a/arch/x86/include/asm/config.h +++ b/arch/x86/include/asm/config.h @@ -10,5 +10,6 @@ #define CONFIG_SYS_GENERIC_BOARD #define CONFIG_LMB #define CONFIG_SYS_BOOT_RAMDISK_HIGH +#define asmlinkage __attribute__((regparm(0))) #endif diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h index 4ea46d7..48bbd1a 100644 --- a/arch/x86/include/asm/global_data.h +++ b/arch/x86/include/asm/global_data.h @@ -17,6 +17,18 @@ enum pei_boot_mode_t { }; +struct memory_area { + uint64_t start; + uint64_t size; +}; + +struct memory_info { + int num_areas; + uint64_t total_memory; + uint64_t total_32bit_memory; + struct memory_area area[CONFIG_NR_DRAM_BANKS]; +}; + /* Architecture-specific global data */ struct arch_global_data { struct global_data *gd_addr; /* Location of Global Data */ @@ -34,6 +46,7 @@ struct arch_global_data { struct pci_controller *hose; /* PCI hose for early use */ enum pei_boot_mode_t pei_boot_mode; const struct pch_gpio_map *gpio_map; /* board GPIO map */ + struct memory_info meminfo; /* Memory information */ }; #endif diff --git a/arch/x86/include/asm/post.h b/arch/x86/include/asm/post.h index 61dcda1..ce68839 100644 --- a/arch/x86/include/asm/post.h +++ b/arch/x86/include/asm/post.h @@ -27,6 +27,11 @@ #define POST_CPU_INIT 0x2b #define POST_EARLY_INIT 0x2c #define POST_CPU_INFO 0x2d +#define POST_PRE_MRC 0x2e +#define POST_MRC 0x2f +#define POST_DRAM 0x2f + +#define POST_RAM_FAILURE 0xea /* Output a post code using al - value must be 0 to 0xff */ #ifdef __ASSEMBLY__ diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h index 0399417..98217dd 100644 --- a/arch/x86/include/asm/u-boot-x86.h +++ b/arch/x86/include/asm/u-boot-x86.h @@ -70,4 +70,6 @@ static inline __attribute__((no_instrument_function)) uint64_t rdtsc(void) void timer_set_tsc_base(uint64_t new_base); uint64_t timer_get_tsc(void); +void quick_ram_check(void); + #endif /* _U_BOOT_I386_H_ */ diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile index 25b672a..e146e64 100644 --- a/arch/x86/lib/Makefile +++ b/arch/x86/lib/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_SYS_PCAT_TIMER) += pcat_timer.o obj-$(CONFIG_PCI) += pci_type1.o obj-y += relocate.o obj-y += physmem.o +obj-$(CONFIG_X86_RAMTEST) += ramtest.o obj-y += string.o obj-$(CONFIG_SYS_X86_TSC_TIMER) += tsc_timer.o obj-$(CONFIG_VIDEO_VGA) += video.o diff --git a/arch/x86/lib/ramtest.c b/arch/x86/lib/ramtest.c new file mode 100644 index 0000000..c21be03 --- /dev/null +++ b/arch/x86/lib/ramtest.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2014 Google, Inc + * + * From Coreboot src/lib/ramtest.c + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include +#include +#include + +static void write_phys(unsigned long addr, u32 value) +{ +#if CONFIG_SSE2 + asm volatile( + "movnti %1, (%0)" + : /* outputs */ + : "r" (addr), "r" (value) /* inputs */ + : /* clobbers */ + ); +#else + writel(value, addr); +#endif +} + +static u32 read_phys(unsigned long addr) +{ + return readl(addr); +} + +static void phys_memory_barrier(void) +{ +#if CONFIG_SSE2 + /* Needed for movnti */ + asm volatile( + "sfence" + : + : + : "memory" + ); +#else + asm volatile("" + : + : + : "memory"); +#endif +} + +void quick_ram_check(void) +{ + int fail = 0; + u32 backup; + + backup = read_phys(CONFIG_RAMBASE); + write_phys(CONFIG_RAMBASE, 0x55555555); + phys_memory_barrier(); + if (read_phys(CONFIG_RAMBASE) != 0x55555555) + fail = 1; + write_phys(CONFIG_RAMBASE, 0xaaaaaaaa); + phys_memory_barrier(); + if (read_phys(CONFIG_RAMBASE) != 0xaaaaaaaa) + fail = 1; + write_phys(CONFIG_RAMBASE, 0x00000000); + phys_memory_barrier(); + if (read_phys(CONFIG_RAMBASE) != 0x00000000) + fail = 1; + write_phys(CONFIG_RAMBASE, 0xffffffff); + phys_memory_barrier(); + if (read_phys(CONFIG_RAMBASE) != 0xffffffff) + fail = 1; + + write_phys(CONFIG_RAMBASE, backup); + if (fail) { + post_code(POST_RAM_FAILURE); + panic("RAM INIT FAILURE!\n"); + } + phys_memory_barrier(); +} diff --git a/include/configs/chromebook_link.h b/include/configs/chromebook_link.h index 3063bd9..8caeca6 100644 --- a/include/configs/chromebook_link.h +++ b/include/configs/chromebook_link.h @@ -18,12 +18,16 @@ #define CONFIG_SYS_CAR_ADDR 0xff7e0000 #define CONFIG_SYS_CAR_SIZE (128 * 1024) #define CONFIG_SYS_MONITOR_LEN (1 << 20) +#define CONFIG_DCACHE_RAM_MRC_VAR_SIZE 0x4000 #define CONFIG_SYS_X86_START16 0xfffff800 #define CONFIG_BOARD_EARLY_INIT_F #define CONFIG_BOARD_EARLY_INIT_R +#define CONFIG_DISPLAY_CPUINFO #define CONFIG_X86_RESET_VECTOR #define CONFIG_NR_DRAM_BANKS 8 +#define CONFIG_X86_MRC_START 0xfffa0000 +#define CONFIG_CACHE_MRC_SIZE_KB 512 #define CONFIG_COREBOOT_SERIAL diff --git a/include/configs/x86-common.h b/include/configs/x86-common.h index 825e9f7..f16ae32 100644 --- a/include/configs/x86-common.h +++ b/include/configs/x86-common.h @@ -192,7 +192,7 @@ #define CONFIG_SYS_STACK_SIZE (32 * 1024) #define CONFIG_SYS_MONITOR_BASE CONFIG_SYS_TEXT_BASE #define CONFIG_SYS_MALLOC_LEN 0x200000 -#define CONFIG_SYS_MALLOC_F_LEN (1 << 10) +#define CONFIG_SYS_MALLOC_F_LEN (2 << 10) /* allow to overwrite serial and ethaddr */ #define CONFIG_ENV_OVERWRITE diff --git a/include/fdtdec.h b/include/fdtdec.h index 3bd60b7..abfd678 100644 --- a/include/fdtdec.h +++ b/include/fdtdec.h @@ -119,6 +119,7 @@ enum fdt_compat_id { COMPAT_PARADE_PS8625, /* Parade PS8622 EDP->LVDS bridge */ COMPAT_INTEL_LPC, /* Intel Low Pin Count I/F */ COMPAT_INTEL_MICROCODE, /* Intel microcode update */ + COMPAT_MEMORY_SPD, /* Memory SPD information */ COMPAT_COUNT, }; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 9a68f9c..aafc4f9 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -74,6 +74,7 @@ static const char * const compat_names[COMPAT_COUNT] = { COMPAT(PARADE_PS8625, "parade,ps8625"), COMPAT(COMPAT_INTEL_LPC, "intel,lpc"), COMPAT(INTEL_MICROCODE, "intel,microcode"), + COMPAT(MEMORY_SPD, "memory-spd"), }; const char *fdtdec_get_compatible(enum fdt_compat_id id) -- cgit v0.10.2 From fe5b9b447c6eea3873833b1f3ba15c9854aa2ef8 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Wed, 12 Nov 2014 22:42:29 -0700 Subject: x86: Rename chromebook-x86 to coreboot Rename this vendor since it is intended to be used on any platform where coreboot runs at reset and then loads U-Boot. So far it is only tested on link. When other boards are supported it is likely that we will need to move to multiple board names, all under the 'coreboot' vendor. So while it would be possible to remove the vendor for now, that would be short-sighted. Suggested-by: Bin Meng Signed-off-by: Simon Glass diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 43c22ff..6e29868 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -85,7 +85,7 @@ config X86_RAMTEST source "arch/x86/cpu/ivybridge/Kconfig" -source "board/chromebook-x86/coreboot/Kconfig" +source "board/coreboot/coreboot/Kconfig" source "board/google/chromebook_link/Kconfig" diff --git a/board/chromebook-x86/coreboot/Kconfig b/board/chromebook-x86/coreboot/Kconfig deleted file mode 100644 index 83385c7..0000000 --- a/board/chromebook-x86/coreboot/Kconfig +++ /dev/null @@ -1,15 +0,0 @@ -if TARGET_COREBOOT - -config SYS_BOARD - default "coreboot" - -config SYS_VENDOR - default "chromebook-x86" - -config SYS_SOC - default "coreboot" - -config SYS_CONFIG_NAME - default "coreboot" - -endif diff --git a/board/chromebook-x86/coreboot/MAINTAINERS b/board/chromebook-x86/coreboot/MAINTAINERS deleted file mode 100644 index 3b2fb52..0000000 --- a/board/chromebook-x86/coreboot/MAINTAINERS +++ /dev/null @@ -1,6 +0,0 @@ -COREBOOT BOARD -M: Simon Glass -S: Maintained -F: board/chromebook-x86/coreboot/ -F: include/configs/coreboot.h -F: configs/coreboot-x86_defconfig diff --git a/board/chromebook-x86/coreboot/Makefile b/board/chromebook-x86/coreboot/Makefile deleted file mode 100644 index 27ebe78..0000000 --- a/board/chromebook-x86/coreboot/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Copyright (c) 2011 The Chromium OS Authors. -# (C) Copyright 2008 -# Graeme Russ, graeme.russ@gmail.com. -# -# (C) Copyright 2006 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. -# -# (C) Copyright 2002 -# Daniel Engström, Omicron Ceti AB, daniel@omicron.se. -# -# SPDX-License-Identifier: GPL-2.0+ -# - -obj-y += coreboot_start.o coreboot.o diff --git a/board/chromebook-x86/coreboot/coreboot.c b/board/chromebook-x86/coreboot/coreboot.c deleted file mode 100644 index 0240c34..0000000 --- a/board/chromebook-x86/coreboot/coreboot.c +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) 2013 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include -#include - -int arch_early_init_r(void) -{ - if (cros_ec_board_init()) - return -1; - - return 0; -} diff --git a/board/chromebook-x86/coreboot/coreboot_start.S b/board/chromebook-x86/coreboot/coreboot_start.S deleted file mode 100644 index 932fe6c..0000000 --- a/board/chromebook-x86/coreboot/coreboot_start.S +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2011 The Chromium OS Authors. - * (C) Copyright 2008 - * Graeme Russ, graeme.russ@gmail.com. - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -/* board early intialization */ -.globl early_board_init -early_board_init: - /* No 32-bit board specific initialisation */ - jmp early_board_init_ret diff --git a/board/coreboot/coreboot/Kconfig b/board/coreboot/coreboot/Kconfig new file mode 100644 index 0000000..6ca6ced --- /dev/null +++ b/board/coreboot/coreboot/Kconfig @@ -0,0 +1,15 @@ +if TARGET_COREBOOT + +config SYS_BOARD + default "coreboot" + +config SYS_VENDOR + default "coreboot" + +config SYS_SOC + default "coreboot" + +config SYS_CONFIG_NAME + default "coreboot" + +endif diff --git a/board/coreboot/coreboot/MAINTAINERS b/board/coreboot/coreboot/MAINTAINERS new file mode 100644 index 0000000..6ce66f5 --- /dev/null +++ b/board/coreboot/coreboot/MAINTAINERS @@ -0,0 +1,6 @@ +COREBOOT BOARD +M: Simon Glass +S: Maintained +F: board/coreboot/coreboot/ +F: include/configs/coreboot.h +F: configs/coreboot-x86_defconfig diff --git a/board/coreboot/coreboot/Makefile b/board/coreboot/coreboot/Makefile new file mode 100644 index 0000000..27ebe78 --- /dev/null +++ b/board/coreboot/coreboot/Makefile @@ -0,0 +1,15 @@ +# +# Copyright (c) 2011 The Chromium OS Authors. +# (C) Copyright 2008 +# Graeme Russ, graeme.russ@gmail.com. +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2002 +# Daniel Engström, Omicron Ceti AB, daniel@omicron.se. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += coreboot_start.o coreboot.o diff --git a/board/coreboot/coreboot/coreboot.c b/board/coreboot/coreboot/coreboot.c new file mode 100644 index 0000000..0240c34 --- /dev/null +++ b/board/coreboot/coreboot/coreboot.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2013 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +int arch_early_init_r(void) +{ + if (cros_ec_board_init()) + return -1; + + return 0; +} diff --git a/board/coreboot/coreboot/coreboot_start.S b/board/coreboot/coreboot/coreboot_start.S new file mode 100644 index 0000000..932fe6c --- /dev/null +++ b/board/coreboot/coreboot/coreboot_start.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2011 The Chromium OS Authors. + * (C) Copyright 2008 + * Graeme Russ, graeme.russ@gmail.com. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/* board early intialization */ +.globl early_board_init +early_board_init: + /* No 32-bit board specific initialisation */ + jmp early_board_init_ret -- cgit v0.10.2