Author: rminnich Date: 2008-08-30 05:35:40 +0200 (Sat, 30 Aug 2008) New Revision: 847
Added: coreboot-v3/arch/x86/stage1_mtrr.c coreboot-v3/northbridge/amd/k8/reset_test.c Modified: coreboot-v3/arch/x86/Kconfig coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c coreboot-v3/include/arch/x86/amd/k8/k8.h coreboot-v3/include/arch/x86/cpu.h coreboot-v3/lib/console.c coreboot-v3/lib/lar.c coreboot-v3/mainboard/amd/serengeti/Makefile coreboot-v3/mainboard/amd/serengeti/initram.c coreboot-v3/mainboard/amd/serengeti/mainboard.h coreboot-v3/northbridge/amd/k8/raminit.c Log: This gets us back to a compiling k8 target.
This code has been tested on dbe62, and builds for qemu as well.
the next step is testing on simnow.
k8.h: add more prototypes and some required inline functions. cpu.h: same serengeti: expand defines in mainboard.h, though we need a better mechanism; continue to fix initram.c, add new support files to Makefile lib/console.c: include globalvars.h lib/lar.c: Provide more informative print as the lar is scanned. k8 north: needed reset_test.c from v2, fixes to raminit.c arch/x86 Kconfig: new CONFIG variable CBMEMK, meaning coreboot mem k, memory used for coreboot. init_cpus.c: functions to start up CPUs stage1_mtrr.c: bring over early mtrr support from v2.
Signed-off-by: Ronald G. Minnich rminnich@gmail.com Acked-by: Ronald G. Minnich rminnich@gmail.com
Modified: coreboot-v3/arch/x86/Kconfig =================================================================== --- coreboot-v3/arch/x86/Kconfig 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/arch/x86/Kconfig 2008-08-30 03:35:40 UTC (rev 847) @@ -171,6 +171,15 @@ help This option sets the size of the area used for CAR.
+config CBMEMK + hex + default 0x1000 if CPU_I586 + default 0x1000 if CPU_AMD_GEODELX + default 0x2000 if CPU_AMD_K8 + help + This option sets the top of the memory area, in KiB, + used for coreboot. + config K8_HT_FREQ_1G_SUPPORT hex default 1 if CPU_AMD_K8
Modified: coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c =================================================================== --- coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c 2008-08-30 03:35:40 UTC (rev 847) @@ -321,6 +321,11 @@ unsigned bsp_apicid = 0; unsigned apicid; struct node_core_id id; + /* this is a bit weird but soft_reset can be defined in many places, + * so finding a common + * include file to use is a little daunting. + */ + void soft_reset(void);
/* * MTRR must be set by this point.
Added: coreboot-v3/arch/x86/stage1_mtrr.c =================================================================== --- coreboot-v3/arch/x86/stage1_mtrr.c (rev 0) +++ coreboot-v3/arch/x86/stage1_mtrr.c 2008-08-30 03:35:40 UTC (rev 847) @@ -0,0 +1,141 @@ +/* we will compile this into initram since some basic prototypes differ with same names on v2. Sigh. */ +#include <mainboard.h> +#include <config.h> +#include <types.h> +#include <io.h> +#include <console.h> +#include <globalvars.h> +#include <lar.h> +#include <string.h> +#include <tables.h> +#include <lib.h> +#include <mc146818rtc.h> +#include <cpu.h> +#include <msr.h> +#include <mtrr.h> + +void disable_var_mtrr(unsigned int reg) +{ + /* The invalid bit is kept in the mask so we simply + * clear the relevent mask register to disable a + * range. + */ + struct msr zero; + zero.lo = zero.hi = 0; + wrmsr(MTRRphysMask_MSR(reg), zero); +} + +void set_var_mtrr( + unsigned long reg, unsigned long base, unsigned long size, unsigned long type) + +{ + /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */ + /* FIXME: It only support 4G less range */ + struct msr basem, maskm; + basem.lo = base | type; + basem.hi = 0; + wrmsr(MTRRphysBase_MSR(reg), basem); + maskm.lo = ~(size - 1) | 0x800; + maskm.hi = (1<<(CPU_ADDR_BITS-32))-1; + wrmsr(MTRRphysMask_MSR(reg), maskm); +} + +void set_var_mtrr_x( + unsigned long reg, u32 base_lo, u32 base_hi, u32 size_lo, u32 size_hi, unsigned long type) + +{ + /* Bit Bit 32-35 of MTRRphysMask should be set to 1 */ + struct msr basem, maskm; + basem.lo = (base_lo & 0xfffff000) | type; + basem.hi = base_hi & ((1<<(CPU_ADDR_BITS-32))-1); + wrmsr(MTRRphysBase_MSR(reg), basem); + maskm.hi = (1<<(CPU_ADDR_BITS-32))-1; + if(size_lo) { + maskm.lo = ~(size_lo - 1) | 0x800; + } else { + maskm.lo = 0x800; + maskm.hi &= ~(size_hi - 1); + } + wrmsr(MTRRphysMask_MSR(reg), maskm); +} + +void cache_cbmem(int type) +{ + /* Enable caching for 0 - 1MB using variable mtrr */ + disable_cache(); + set_var_mtrr(0, 0x00000000, COREBOOT_MEM_TOPK << 10, type); + enable_cache(); +} + +/* the fixed and variable MTTRs are power-up with random values, + * clear them to MTRR_TYPE_UNCACHEABLE for safty. + */ +void do_early_mtrr_init(const unsigned long *mtrr_msrs) +{ + /* Precondition: + * The cache is not enabled in cr0 nor in MTRRdefType_MSR + * entry32.inc ensures the cache is not enabled in cr0 + */ + struct msr msr; + const unsigned long *msr_addr; + + /* Inialize all of the relevant msrs to 0 */ + msr.lo = 0; + msr.hi = 0; + unsigned long msr_nr; + for(msr_addr = mtrr_msrs; (msr_nr = *msr_addr); msr_addr++) { + wrmsr(msr_nr, msr); + } + +#warning fix the XIP bits in stage1_mtrr.c that enable write through caching so we can do execute in place on the flash rom. +#if 0 +#if defined(XIP_ROM_SIZE) + /* enable write through caching so we can do execute in place + * on the flash rom. + */ + set_var_mtrr(1, XIP_ROM_BASE, XIP_ROM_SIZE, MTRR_TYPE_WRBACK); +#endif +#endif + + /* Set the default memory type and enable fixed and variable MTRRs + */ + /* Enable Variable MTRRs */ + msr.hi = 0x00000000; + msr.lo = 0x00000800; + wrmsr(MTRRdefType_MSR, msr); + +} + +void early_mtrr_init(void) +{ + static const unsigned long mtrr_msrs[] = { + /* fixed mtrr */ + 0x250, 0x258, 0x259, + 0x268, 0x269, 0x26A, + 0x26B, 0x26C, 0x26D, + 0x26E, 0x26F, + /* var mtrr */ + 0x200, 0x201, 0x202, 0x203, + 0x204, 0x205, 0x206, 0x207, + 0x208, 0x209, 0x20A, 0x20B, + 0x20C, 0x20D, 0x20E, 0x20F, + /* NULL end of table */ + 0 + }; + disable_cache(); + do_early_mtrr_init(mtrr_msrs); + enable_cache(); +} + +int early_mtrr_init_detected(void) +{ + struct msr msr; + /* See if MTRR's are enabled. + * a #RESET disables them while an #INIT + * preserves their state. This works + * on both Intel and AMD cpus, at least + * according to the documentation. + */ + msr = rdmsr(MTRRdefType_MSR); + return msr.lo & 0x00000800; +}
Modified: coreboot-v3/include/arch/x86/amd/k8/k8.h =================================================================== --- coreboot-v3/include/arch/x86/amd/k8/k8.h 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/include/arch/x86/amd/k8/k8.h 2008-08-30 03:35:40 UTC (rev 847) @@ -690,6 +690,76 @@ void enable_fid_change(void); void init_fidvid_bsp(unsigned bsp_apicid);
+/* k8/northbridge.c */ +void sdram_initialize(int controllers, const struct mem_controller *ctrl, struct sys_info *sysinfo); +/* k8/reset_test.c */ +void distinguish_cpu_resets(unsigned nodeid); + +/* These are functions that MUST be inlined as we can not use a stack -- CAR or real ram */ +/* by yhlu 6.2005 */ +/* be warned, this file will be used other cores and core 0 / node 0 */ +static inline __attribute__((always_inline)) void disable_cache_as_ram(void) +{ + + __asm__ volatile ( + + /* We don't need cache as ram for now on */ + /* disable cache */ + "movl %cr0, %eax\n\t" + "orl $(0x1<<30),%eax\n\t" + "movl %eax, %cr0\n\t" + + /* clear sth */ + "movl $0x269, %ecx\n\t" /* fix4k_c8000*/ + "xorl %edx, %edx\n\t" + "xorl %eax, %eax\n\t" + "wrmsr\n\t" +#if CONFIG_CARSIZE > 0x8000 + "movl $0x268, %ecx\n\t" /* fix4k_c0000*/ + "wrmsr\n\t" +#endif + + /* disable fixed mtrr from now on, it will be enabled by coreboot_ram again*/ + "movl $0xC0010010, %ecx\n\t" +// "movl $SYSCFG_MSR, %ecx\n\t" + "rdmsr\n\t" + "andl $(~(3<<18)), %eax\n\t" +// "andl $(~(SYSCFG_MSR_MtrrFixDramModEn | SYSCFG_MSR_MtrrFixDramEn)), %eax\n\t" + "wrmsr\n\t" + + /* Set the default memory type and disable fixed and enable variable MTRRs */ + "movl $0x2ff, %ecx\n\t" +// "movl $MTRRdefType_MSR, %ecx\n\t" + "xorl %edx, %edx\n\t" + /* Enable Variable and Disable Fixed MTRRs */ + "movl $0x00000800, %eax\n\t" + "wrmsr\n\t" + + /* enable cache */ + "movl %cr0, %eax\n\t" + "andl $0x9fffffff,%eax\n\t" + "movl %eax, %cr0\n\t" + + ); +} + +static void disable_cache_as_ram_bsp(void) +{ + __asm__ volatile ( +// "pushl %eax\n\t" + "pushl %edx\n\t" + "pushl %ecx\n\t" + ); + + disable_cache_as_ram(); + __asm__ volatile ( + "popl %ecx\n\t" + "popl %edx\n\t" +// "popl %eax\n\t" + ); +} + + #endif /* ! ASSEMBLY */
#endif /* AMD_K8_H */
Modified: coreboot-v3/include/arch/x86/cpu.h =================================================================== --- coreboot-v3/include/arch/x86/cpu.h 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/include/arch/x86/cpu.h 2008-08-30 03:35:40 UTC (rev 847) @@ -21,10 +21,11 @@
#ifndef ARCH_X86_CPU_H #define ARCH_X86_CPU_H - +#include <config.h> #include <types.h> #include <device/device.h> #include <shared.h> +#include <mtrr.h>
#define X86_VENDOR_INTEL 0 #define X86_VENDOR_CYRIX 1 @@ -81,6 +82,13 @@ u8 x86_mask; };
+/* prototypes for functions that may or may not be compiled in depending on cpu type */ +void set_var_mtrr_x( + unsigned long reg, u32 base_lo, u32 base_hi, u32 size_lo, u32 size_hi, unsigned long type); +void set_var_mtrr( + unsigned long reg, unsigned long base, unsigned long size, unsigned long type); + + /** * Generic CPUID function. * @@ -201,6 +209,48 @@ __asm__ __volatile__("hlt" : : : "memory"); }
+/** + * Optimized generic x86 assembly for clearing memory + * @param addr address + * @param size Size in bytes to clear + */ +static inline void clear_memory(void *addr, unsigned long size) +{ + asm volatile( + "cld \n\t" + "rep; stosl\n\t" + : /* No outputs */ + : "a" (0), "D" (addr), "c" (size>>2) + ); + +} + +/* in v2, these were specialized to the k8 for no apparent reason. + * Also, clear_init_ram was set to noinline, + * for reasons I do not understand (but may be important; see the comment */ +/* by yhlu 6.2005 */ +/* be warned, this file will be used core 0/node 0 only */ + +//static void __attribute__((noinline)) clear_init_ram(void) +static inline void clear_init_ram(void) +{ + // ??? + // gcc 3.4.5 will inline the copy_and_run and clear_init_ram in post_cache_as_ram + // will reuse %edi as 0 from clear_memory for copy_and_run part, actually it is increased already + // so noline clear_init_ram + // ??? + clear_memory(0, ((CONFIG_CBMEMK<<10) - CONFIG_CARSIZE)); + +} + +/* be warned, this file will be used by core other than core 0/node 0 or core0/node0 when cpu_reset*/ +static void set_init_ram_access(void) +{ + set_var_mtrr(0, 0x00000000, CONFIG_CBMEMK << 10, MTRR_TYPE_WRBACK); +} + + + void * bottom_of_stack(void); EXPORT_SYMBOL(bottom_of_stack); struct global_vars * global_vars(void); @@ -260,4 +310,5 @@ void setup_resource_map(const struct rmap *rm, u32 max); EXPORT_SYMBOL(setup_resource_map);
+ #endif /* ARCH_X86_CPU_H */
Modified: coreboot-v3/lib/console.c =================================================================== --- coreboot-v3/lib/console.c 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/lib/console.c 2008-08-30 03:35:40 UTC (rev 847) @@ -1,6 +1,7 @@ #include <types.h> #include <cpu.h> #include <console.h> +#include <globalvars.h> #include <uart8250.h> #include <stdarg.h> #include <string.h>
Modified: coreboot-v3/lib/lar.c =================================================================== --- coreboot-v3/lib/lar.c 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/lib/lar.c 2008-08-30 03:35:40 UTC (rev 847) @@ -120,7 +120,8 @@ header = (struct lar_header *)walk; fullname = walk + sizeof(struct lar_header);
- printk(BIOS_SPEW, "LAR: seen member %s\n", fullname); + printk(BIOS_SPEW, "LAR: %s@%p, size %d\n", fullname, + header, ntohl(header->len)); // FIXME: check checksum
if (strcmp(fullname, filename) == 0) {
Modified: coreboot-v3/mainboard/amd/serengeti/Makefile =================================================================== --- coreboot-v3/mainboard/amd/serengeti/Makefile 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/mainboard/amd/serengeti/Makefile 2008-08-30 03:35:40 UTC (rev 847) @@ -33,7 +33,9 @@ INITRAM_SRC= $(src)/mainboard/$(MAINBOARDDIR)/initram.c \ $(src)/northbridge/amd/k8/raminit.c \ $(src)/northbridge/amd/k8/dqs.c \ + $(src)/northbridge/amd/k8/reset_test.c \ $(src)/arch/x86/pci_ops_conf1.c \ + $(src)/arch/x86/stage1_mtrr.c \ $(src)/southbridge/amd/amd8111/stage1_smbus.c \ $(src)/arch/x86/amd/model_fxx/init_cpus.c \ $(src)/arch/x86/amd/model_fxx/dualcore.c \
Modified: coreboot-v3/mainboard/amd/serengeti/initram.c =================================================================== --- coreboot-v3/mainboard/amd/serengeti/initram.c 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/mainboard/amd/serengeti/initram.c 2008-08-30 03:35:40 UTC (rev 847) @@ -22,6 +22,7 @@ #define _MAINOBJECT
#include <mainboard.h> +#include <config.h> #include <types.h> #include <lib.h> #include <console.h>
Modified: coreboot-v3/mainboard/amd/serengeti/mainboard.h =================================================================== --- coreboot-v3/mainboard/amd/serengeti/mainboard.h 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/mainboard/amd/serengeti/mainboard.h 2008-08-30 03:35:40 UTC (rev 847) @@ -33,7 +33,6 @@ #define SB_HT_CHAIN_UNITID_OFFSET_ONLY 1 #define ENABLE_APIC_EXT_ID 0 #define LIFT_BSP_APIC_ID 1 - #warning clean up confusion on FIDVID. v2 was inconsistent. /* In v2 there is confusion on the settings of these. * The serengeti config sets it to zero. @@ -44,3 +43,7 @@ /* MSR FIDVID_CTL and FIDVID_STATUS are shared by cores, * so may don't need to do twice */ #define K8_SET_FIDVID_CORE0_ONLY 1 + +/* architecture stuff which ought to be set "somewhere" "SOMEHOW" */ +/* preferably by asking the CPU, not be a DEFINE! */ +#define CPU_ADDR_BITS 40
Modified: coreboot-v3/northbridge/amd/k8/raminit.c =================================================================== --- coreboot-v3/northbridge/amd/k8/raminit.c 2008-08-29 21:18:09 UTC (rev 846) +++ coreboot-v3/northbridge/amd/k8/raminit.c 2008-08-30 03:35:40 UTC (rev 847) @@ -2972,3 +2972,40 @@ } } } + +/** + * initialize sdram. There was a "generic" function in v2 that was not really that useful. + * we break it out by northbridge now to accomodate the different peculiarities of + * different chipsets. + *@param controllers Number of controllers + *@param ctlr array of memory controllers + *@param sysinfo pointer to sysinfo struct. + */ +void sdram_initialize(int controllers, const struct mem_controller *ctrl, struct sys_info *sysinfo) +{ + int i; + /* Set the registers we can set once to reasonable values */ + for(i = 0; i < controllers; i++) { + printk(BIOS_DEBUG, "Ram1.%d, ",i); + + sdram_set_registers(ctrl + i , sysinfo); + } + + /* Now setup those things we can auto detect */ + for(i = 0; i < controllers; i++) { + printk(BIOS_DEBUG, "Ram2.%d, ",i); + sdram_set_spd_registers(ctrl + i , sysinfo); + + } + + /* Now that everything is setup enable the SDRAM. + * Some chipsets do the work for us while on others + * we need to it by hand. + */ + printk(BIOS_DEBUG, "Ram3\n"); + + sdram_enable(controllers, ctrl, sysinfo); + + printk(BIOS_DEBUG, "Ram4\n"); + +}
Added: coreboot-v3/northbridge/amd/k8/reset_test.c =================================================================== --- coreboot-v3/northbridge/amd/k8/reset_test.c (rev 0) +++ coreboot-v3/northbridge/amd/k8/reset_test.c 2008-08-30 03:35:40 UTC (rev 847) @@ -0,0 +1,126 @@ +/* + * K8 northbridge + * This file is part of the coreboot project. + * Copyright (C) 2004-2005 Linux Networx + * (Written by Eric Biederman ebiederman@lnxi.com and Jason Schildt for Linux Networx) + * Copyright (C) 2005-7 YingHai Lu + * Copyright (C) 2005 Ollie Lo + * Copyright (C) 2005-2007 Stefan Reinauer stepan@openbios.org + * Copyright (C) 2008 Ronald G. Minnich rminnich@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA + */ +/* This should be done by Eric + 2004.12 yhlu add dual core support + 2005.01 yhlu add support move apic before pci_domain in MB Config.lb + 2005.02 yhlu add e0 memory hole support + 2005.11 yhlu add put sb ht chain on bus 0 +*/ + +#include <mainboard.h> +#include <console.h> +#include <lib.h> +#include <string.h> +#include <mtrr.h> +#include <macros.h> +#include <spd.h> +#include <cpu.h> +#include <msr.h> +#include <amd/k8/k8.h> +#include <amd/k8/sysconf.h> +#include <device/pci.h> +#include <device/hypertransport_def.h> +#include <device/hypertransport.h> +#include <mc146818rtc.h> +#include <lib.h> +#include <lapic.h> + +int cpu_init_detected(unsigned nodeid) +{ + unsigned long htic; + u32 dev; + + dev = PCI_BDF(0, 0x18 + nodeid, 0); + htic = pci_conf1_read_config32(dev, HT_INIT_CONTROL); + + return !!(htic & HTIC_INIT_Detect); +} + +int bios_reset_detected(void) +{ + unsigned long htic; + htic = pci_conf1_read_config32(PCI_BDF(0, 0x18, 0), HT_INIT_CONTROL); + + return (htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect); +} + +int cold_reset_detected(void) +{ + unsigned long htic; + htic = pci_conf1_read_config32(PCI_BDF(0, 0x18, 0), HT_INIT_CONTROL); + + return !(htic & HTIC_ColdR_Detect); +} + +void distinguish_cpu_resets(unsigned nodeid) +{ + u32 htic; + u32 device; + device = PCI_BDF(0, 0x18 + nodeid, 0); + htic = pci_conf1_read_config32(device, HT_INIT_CONTROL); + htic |= HTIC_ColdR_Detect | HTIC_BIOSR_Detect | HTIC_INIT_Detect; + pci_conf1_write_config32(device, HT_INIT_CONTROL, htic); +} + +void set_bios_reset(void) +{ + unsigned long htic; + htic = pci_conf1_read_config32(PCI_BDF(0, 0x18, 0), HT_INIT_CONTROL); + htic &= ~HTIC_BIOSR_Detect; + pci_conf1_write_config32(PCI_BDF(0, 0x18, 0), HT_INIT_CONTROL, htic); +} + +unsigned node_link_to_bus(unsigned node, unsigned link) +{ + unsigned reg; + + for(reg = 0xE0; reg < 0xF0; reg += 0x04) { + unsigned config_map; + config_map = pci_conf1_read_config32(PCI_BDF(0, 0x18, 1), reg); + if ((config_map & 3) != 3) { + continue; + } + if ((((config_map >> 4) & 7) == node) && + (((config_map >> 8) & 3) == link)) + { + return (config_map >> 16) & 0xff; + } + } + return 0; +} + +unsigned get_sblk(void) +{ + u32 reg; + /* read PCI_BDF(0,0x18,0) 0x64 bit [8:9] to find out SbLink m */ + reg = pci_conf1_read_config32(PCI_BDF(0, 0x18, 0), 0x64); + return ((reg>>8) & 3) ; +} + +unsigned get_sbbusn(unsigned sblk) +{ + return node_link_to_bus(0, sblk); +} + +