Author: rminnich Date: 2008-08-28 00:43:18 +0200 (Thu, 28 Aug 2008) New Revision: 828
Added: coreboot-v3/include/globalvars.h Modified: coreboot-v3/arch/x86/amd/stage0.S coreboot-v3/arch/x86/stage1.c coreboot-v3/include/arch/x86/amd/k8/k8.h coreboot-v3/include/arch/x86/amd_geodelx.h coreboot-v3/include/console.h coreboot-v3/mainboard/amd/Kconfig coreboot-v3/mainboard/amd/serengeti/dts coreboot-v3/mainboard/amd/serengeti/initram.c coreboot-v3/mainboard/amd/serengeti/stage1.c coreboot-v3/northbridge/amd/k8/coherent_ht.c coreboot-v3/northbridge/amd/k8/dqs.c coreboot-v3/northbridge/amd/k8/incoherent_ht.c Log: Fixes to make k8 and others work.
We need the sys_info struct in the global variables struct for cache as ram on k8. The sys_info struct is generally very useful so it makes sense to start accomodating it.
This patch adds an (empty for now) sys_info struct for geode. It add sys_info to the global variables struct.
It removes global variables from console.h to a new file, globalvars.h. Very little code needs to include this file.
This patch is tested on the dbe62 and simnow with no problems.
k8 compilation is now broken but I'm working on it. I'm going through the eyeballs-bleed code on k8 startup to document it and with any luck we'll have more functionality by the end of today. But it's hard ...
Signed-off-by: Ronald G. Minnich rminnich@gmail.com
Acked-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Modified: coreboot-v3/arch/x86/amd/stage0.S =================================================================== --- coreboot-v3/arch/x86/amd/stage0.S 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/arch/x86/amd/stage0.S 2008-08-27 22:43:18 UTC (rev 828) @@ -178,8 +178,6 @@ /* Restore the BIST value to %eax. */ movl %ebp, %eax
- /*for normal part %ebx already contain cpu_init_detected from fallback call */ - cache_as_ram_setup:
movb $0xA0, %al
Modified: coreboot-v3/arch/x86/stage1.c =================================================================== --- coreboot-v3/arch/x86/stage1.c 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/arch/x86/stage1.c 2008-08-27 22:43:18 UTC (rev 828) @@ -21,6 +21,7 @@ #include <types.h> #include <io.h> #include <console.h> +#include <globalvars.h> #include <lar.h> #include <string.h> #include <tables.h> @@ -138,12 +139,16 @@ } #endif /* CONFIG_PAYLOAD_ELF_LOADER */
-/* +/** * This function is called from assembler code with its argument on the * stack. Force the compiler to generate always correct code for this case. * We have cache as ram running and can start executing code in C. + * @param bist Built In Self Test value + * @param init_detected This (optionally set) value is used on some platforms (e.g. k8) to indicate + * that we are restarting after some sort of reconfiguration. Note that we could use it on geode but + * do not at present. */ -void __attribute__((stdcall)) stage1_main(u32 bist) +void __attribute__((stdcall)) stage1_main(u32 bist, u32 init_detected) { struct global_vars globvars; int ret; @@ -178,6 +183,8 @@ * NEVER run this on an AP! */ global_vars_init(&globvars); + globvars.bist = bist; + globvars.init_detected = init_detected;
hardware_stage1();
Modified: coreboot-v3/include/arch/x86/amd/k8/k8.h =================================================================== --- coreboot-v3/include/arch/x86/amd/k8/k8.h 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/include/arch/x86/amd/k8/k8.h 2008-08-27 22:43:18 UTC (rev 828) @@ -20,6 +20,8 @@
/* Until we resolve a better way to do this, work around it with a value "too large to fail" */
+#ifndef AMD_K8_H +#define AMD_K8_H /* Socket types */ #define SOCKET_AM2 0x11 #define SOCKET_L1 0x10 @@ -62,6 +64,7 @@
/* Definitions of various K8 registers for REV F*/ /* Function 0 */ +#define NODEID 0x60 #define HT_TRANSACTION_CONTROL 0x68 #define HTTC_DIS_RD_B_P (1 << 0) #define HTTC_DIS_RD_DW_P (1 << 1) @@ -611,7 +614,8 @@ unsigned coreid; };
-// it can be used to get unitid and coreid it running only +/* use this to get the nodeid and core it of the current cpu (but not other CPUs) */ +/* the nb_cfg_54 indicates the setting of bit 54 (InitApicIdCpuIdLo) */ struct node_core_id get_node_core_id(unsigned int nb_cfg_54);
struct device; @@ -627,3 +631,5 @@ struct hw_mem_hole_info get_hw_mem_hole_info(void);
#endif /* ! ASSEMBLY */ + +#endif /* AMD_K8_H */
Modified: coreboot-v3/include/arch/x86/amd_geodelx.h =================================================================== --- coreboot-v3/include/arch/x86/amd_geodelx.h 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/include/arch/x86/amd_geodelx.h 2008-08-27 22:43:18 UTC (rev 828) @@ -1258,6 +1258,18 @@
#ifndef __ASSEMBLER__
+/* This is new. + * We're not using it yet on Geode. + * K8 requires it and, for future ports, we are going to require it. + * it's a useful placeholder for platform info that usually ends up + * scattered everywhere. On K8, it is initially stored at the base of stack + * in cache-as-ram and then copied out once ram is started. + */ +struct sys_info { + int empty; +}; + + /* * Write to a Virtual Register * @param class_index The register index
Modified: coreboot-v3/include/console.h =================================================================== --- coreboot-v3/include/console.h 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/include/console.h 2008-08-27 22:43:18 UTC (rev 828) @@ -60,19 +60,6 @@ }; #endif
-/* - * struct global_vars is managed entirely from C code. Keep in mind that there - * is NO buffer at the end of the struct, so having zero-sized arrays at the - * end or similar stuff for which the compiler can't determine the final size - * will corrupt memory. If you don't try to be clever, everything will be fine. - */ -struct global_vars { -#ifdef CONFIG_CONSOLE_BUFFER - struct printk_buffer *printk_buffer; -#endif - unsigned int loglevel; -}; - int printk(int msg_level, const char *fmt, ...) __attribute__((format (printf, 2, 3))); EXPORT_SYMBOL(printk); void banner(int msg_level, const char *msg);
Added: coreboot-v3/include/globalvars.h =================================================================== --- coreboot-v3/include/globalvars.h (rev 0) +++ coreboot-v3/include/globalvars.h 2008-08-27 22:43:18 UTC (rev 828) @@ -0,0 +1,51 @@ +/* + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#ifndef GLOBALVARS_H +#define GLOBALVARS_H + +/* you need to include all files that might be referenced in the global variables struct */ +#include <console.h> +#include <types.h> +/* the sys_info struct is architecture-dependent, with parameters controlled from mainboard.h in some cases */ +#ifdef CONFIG_CPU_AMD_K8 +#include <mainboard.h> +#include <amd/k8/k8.h> +#include <amd/k8/sysconf.h> +#endif + +#ifdef CONFIG_CPU_AMD_GEODELX +#include <amd_geodelx.h> +#endif + +/* + * struct global_vars is managed entirely from C code. Keep in mind that there + * is NO buffer at the end of the struct, so having zero-sized arrays at the + * end or similar stuff for which the compiler can't determine the final size + * will corrupt memory. If you don't try to be clever, everything will be fine. + */ +struct global_vars { +#ifdef CONFIG_CONSOLE_BUFFER + struct printk_buffer *printk_buffer; +#endif + unsigned int loglevel; + /* these two values are of interest in many stages */ + u32 bist; + u32 init_detected; + struct sys_info sys_info; +}; + +#endif /* GLOBALVARS_H */
Modified: coreboot-v3/mainboard/amd/Kconfig =================================================================== --- coreboot-v3/mainboard/amd/Kconfig 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/mainboard/amd/Kconfig 2008-08-27 22:43:18 UTC (rev 828) @@ -53,6 +53,7 @@ select CPU_AMD_K8 select NORTHBRIDGE_AMD_K8 select SOUTHBRIDGE_AMD_AMD8111 + select SUPERIO_WINBOND_W83627HF select IOAPIC help AMD Serengeti
Modified: coreboot-v3/mainboard/amd/serengeti/dts =================================================================== --- coreboot-v3/mainboard/amd/serengeti/dts 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/mainboard/amd/serengeti/dts 2008-08-27 22:43:18 UTC (rev 828) @@ -40,5 +40,9 @@ /config/("southbridge/amd/amd8111/nic.dts"); }; }; + ioport@2e { + /config/("superio/winbond/w83627hf/dts"); + com1enable = "1"; + }; }; };
Modified: coreboot-v3/mainboard/amd/serengeti/initram.c =================================================================== --- coreboot-v3/mainboard/amd/serengeti/initram.c 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/mainboard/amd/serengeti/initram.c 2008-08-27 22:43:18 UTC (rev 828) @@ -25,6 +25,7 @@ #include <types.h> #include <lib.h> #include <console.h> +#include <globalvars.h> #include <device/device.h> #include <device/pci.h> #include <string.h> @@ -35,6 +36,20 @@ #include <mc146818rtc.h> #include <spd.h>
+#define RC0 ((1<<0)<<8) +#define RC1 ((1<<1)<<8) +#define RC2 ((1<<2)<<8) +#define RC3 ((1<<3)<<8) + +#define DIMM0 0x50 +#define DIMM1 0x51 +#define DIMM2 0x52 +#define DIMM3 0x53 +#define DIMM4 0x54 +#define DIMM5 0x55 +#define DIMM6 0x56 +#define DIMM7 0x57 + # warning fix hard_reset void hard_reset(void) { @@ -49,18 +64,204 @@
void activate_spd_rom(const struct mem_controller *ctrl) { - /* nothing to do */ +#define SMBUS_HUB 0x18 + int smbus_write_byte(u16 device, u16 address, u8 val); + int ret,i; + u16 device=(ctrl->channel0[0])>>8; + /* the very first write always get COL_STS=1 and ABRT_STS=1, so try another time*/ + i=2; + do { + ret = smbus_write_byte(SMBUS_HUB, 0x01, device); + } while ((ret!=0) && (i-->0)); + + smbus_write_byte(SMBUS_HUB, 0x03, 0); }
+u8 spd_read_byte(u16 device, u8 address) +{ + int smbus_read_byte(u16 device, u16 address); + return smbus_read_byte(device, address); +}
+ /** - * main for initram for the Gigabyte m57sli. + * main for initram for the AMD Serengeti + * @param bist Built In Self Test, which is used to indicate status of self test + * @param init_detected Used to indicate that we have been started via init + * @returns 0 on success + * The purpose of this code is to not only get ram going, but get any other cpus/cores going. + * The two activities are very tightly connected and not really seperable. + * The BSP (boot strap processor? ) Core 0 is responsible for all training or all sockets. Note that + * this need not be socket 0; one great strength of coreboot, as opposed to other BIOSes, is that it could + * always boot with with a CPU in any socket, and even with empty sockets (as opposed to, e.g., the BIOS + * that came installed on the Sun Ultra 40, which would freeze if one CPU were not installed). + * The bringup proceeds in several sections. The cool part is that this code is run by all CPUs, and + * control flow is managed by seeing which CPU we are -- BSP or AP? + * */ +/* + * bist is defined by the CPU hardware and is present in EAX on first instruction of coreboot. + * Its value is implementation defined. + * + * init_detected is used to determine if we did a soft reset as required by a reprogramming of the + * hypertransport links. If we did this kind of reset, bit 11 will be set in the MTRRdefType_MSR MSR. + * That may seem crazy, but there are not lots of places to hide a bit when the CPU does a reset. + * This value is picked up in assembly, or it should be. + */ int main(void) { + void enable_smbus(void); + u32 bist, u32 init_detected; + static const u16 spd_addr[] = { + //first node + RC0|DIMM0, RC0|DIMM2, 0, 0, + RC0|DIMM1, RC0|DIMM3, 0, 0, +#if CONFIG_MAX_PHYSICAL_CPUS > 1 + //second node + RC1|DIMM0, RC1|DIMM2, RC1|DIMM4, RC1|DIMM6, + RC1|DIMM1, RC1|DIMM3, RC1|DIMM5, RC1|DIMM7, +#endif +#if CONFIG_MAX_PHYSICAL_CPUS > 2 + // third node + RC2|DIMM0, RC2|DIMM2, 0, 0, + RC2|DIMM1, RC2|DIMM3, 0, 0, + // four node + RC3|DIMM0, RC3|DIMM2, RC3|DIMM4, RC3|DIMM6, + RC3|DIMM1, RC3|DIMM3, RC3|DIMM5, RC3|DIMM7, +#endif + + }; + + struct sys_info *sysinfo; + int needs_reset; int i; + unsigned bsp_apicid = 0; printk(BIOS_DEBUG, "Hi there from stage1\n"); post_code(POST_START_OF_MAIN); + sysinfo = &(global_vars()->sys_info);
+ bist = sysinfo->bist; + init_detected = sysinfo->init_detected; + /* We start out by looking at bist. Where was bist set? */ + /* well, here we are. For starters, we need to know if this is cpu0 core0. + * cpu0 core 0 will do all the DRAM setup. + */ + if (bist) { + printk(BIOS_EMERG, "Bist 0x%x\n", bist); + die("bist failure"); + } else + bsp_apicid = init_cpus(init_detected, sysinfo); + +// dump_mem(DCACHE_RAM_BASE+DCACHE_RAM_SIZE-0x200, DCACHE_RAM_BASE+DCACHE_RAM_SIZE); + +#if 0 + dump_pci_device(PCI_DEV(0, 0x18, 0)); + dump_pci_device(PCI_DEV(0, 0x19, 0)); +#endif + + printk(BIOS_DEBUG, "bsp_apicid=%02x\n", bsp_apicid); + +#if MEM_TRAIN_SEQ == 1 + set_sysinfo_in_ram(0); // in BSP so could hold all ap until sysinfo is in ram +#endif + setup_coherent_ht_domain(); // routing table and start other core0 + + wait_all_core0_started(); +#if CONFIG_LOGICAL_CPUS==1 + // It is said that we should start core1 after all core0 launched + /* becase optimize_link_coherent_ht is moved out from setup_coherent_ht_domain, + * So here need to make sure last core0 is started, esp for two way system, + * (there may be apic id conflicts in that case) + */ + start_other_cores(); + wait_all_other_cores_started(bsp_apicid); +#endif + + /* it will set up chains and store link pair for optimization later */ + ht_setup_chains_x(sysinfo); // it will init sblnk and sbbusn, nodes, sbdn + +#if 0 + //it your CPU min fid is 1G, you can change HT to 1G and FID to max one time. + needs_reset = optimize_link_coherent_ht(); + needs_reset |= optimize_link_incoherent_ht(sysinfo); +#endif + +#if K8_SET_FIDVID == 1 + + { + msr_t msr; + msr=rdmsr(0xc0010042); + print_debug("begin msr fid, vid "); print_debug_hex32( msr.hi ); print_debug_hex32(msr.lo); print_debug("\r\n"); + + } + + enable_fid_change(); + + enable_fid_change_on_sb(sysinfo->sbbusn, sysinfo->sbdn); + + init_fidvid_bsp(bsp_apicid); + + // show final fid and vid + { + msr_t msr; + msr=rdmsr(0xc0010042); + print_debug("end msr fid, vid "); print_debug_hex32( msr.hi ); print_debug_hex32(msr.lo); print_debug("\r\n"); + + } +#endif + +#if 1 + needs_reset = optimize_link_coherent_ht(); + needs_reset |= optimize_link_incoherent_ht(sysinfo); + + // fidvid change will issue one LDTSTOP and the HT change will be effective too + if (needs_reset) { + print_info("ht reset -\r\n"); + soft_reset_x(sysinfo->sbbusn, sysinfo->sbdn); + } +#endif + allow_all_aps_stop(bsp_apicid); + + //It's the time to set ctrl in sysinfo now; + fill_mem_ctrl(sysinfo->nodes, sysinfo->ctrl, spd_addr); + + enable_smbus(); + +#if 0 + for(i=0;i<4;i++) { + activate_spd_rom(&cpu[i]); + dump_smbus_registers(); + } +#endif + +#if 0 + for(i=1;i<256;i<<=1) { + change_i2c_mux(i); + dump_smbus_registers(); + } +#endif + + memreset_setup(); + + //do we need apci timer, tsc...., only debug need it for better output + /* all ap stopped? */ +// init_timer(); // Need to use TMICT to synconize FID/VID + + sdram_initialize(sysinfo->nodes, sysinfo->ctrl, sysinfo); + +#if 0 + print_pci_devices(); +#endif + +#if 0 +// dump_pci_devices(); + dump_pci_device_index_wait(PCI_DEV(0, 0x18, 2), 0x98); + dump_pci_device_index_wait(PCI_DEV(0, 0x19, 2), 0x98); +#endif + + post_cache_as_ram(); // bsp swtich stack to ram and copy sysinfo ram now + +1 + printk(BIOS_DEBUG, "stage1 returns\n"); return 0; }
Modified: coreboot-v3/mainboard/amd/serengeti/stage1.c =================================================================== --- coreboot-v3/mainboard/amd/serengeti/stage1.c 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/mainboard/amd/serengeti/stage1.c 2008-08-27 22:43:18 UTC (rev 828) @@ -25,15 +25,15 @@ #include <console.h> #include <device/device.h> #include <cpu.h> -#include <amd/k8/k8.h> -#include <amd/k8/sysconf.h> #include <device/pci.h> #include <string.h> #include <msr.h> #include <io.h> #include <arch/x86/msr.h> +#include <superio/winbond/w83627hf/w83627hf.h> +#include <amd/k8/k8.h> +#include <amd/k8/sysconf.h>
- static const struct rmap register_values[] = { /* Careful set limit registers before base registers which contain the enables */ /* DRAM Limit i Registers @@ -289,8 +289,12 @@
void amd8111_enable_rom(void);
+#define SERIAL_DEV W83627HF_SP1 +#define SERIAL_IOBASE 0x3f8 + void hardware_stage1(void) { + void w83627hf_enable_serial(u8 dev, u8 serial, u16 iobase); void enumerate_ht_chain(void); int max; printk(BIOS_ERR, "Stage1: enable rom ...\n"); @@ -299,6 +303,7 @@ enumerate_ht_chain(); amd8111_enable_rom(); printk(BIOS_ERR, "Done.\n"); + w83627hf_enable_serial(0x2e, SERIAL_DEV, SERIAL_IOBASE); post_code(POST_START_OF_MAIN);
}
Modified: coreboot-v3/northbridge/amd/k8/coherent_ht.c =================================================================== --- coreboot-v3/northbridge/amd/k8/coherent_ht.c 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/northbridge/amd/k8/coherent_ht.c 2008-08-27 22:43:18 UTC (rev 828) @@ -1689,9 +1689,15 @@ return needs_reset; }
-inline unsigned get_nodes(void) +/** + * get_nodes + * see page 46 of the BKDG Publication # 26094 Revision: 3.30 Issue Date: February 2006 + * @returns an int containing the node id. + * The format of the register is 32 bits, and the node count is in bits 4-6 + */ +unsigned int get_nodes(void) { - return ((pci_conf1_read_config32(PCI_BDF(0, 0x18, 0), 0x60)>>4) & 7) + 1; + return ((pci_conf1_read_config32(PCI_BDF(0, 0x18, 0), NODEID)>>4) & 7) + 1; }
int optimize_link_coherent_ht(void)
Modified: coreboot-v3/northbridge/amd/k8/dqs.c =================================================================== --- coreboot-v3/northbridge/amd/k8/dqs.c 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/northbridge/amd/k8/dqs.c 2008-08-27 22:43:18 UTC (rev 828) @@ -27,12 +27,12 @@ #include <spd.h> #include <cpu.h> #include <msr.h> -#include <amd/k8/k8.h> -#include <amd/k8/sysconf.h> #include <device/pci.h> #include <pci_ops.h> #include <mc146818rtc.h> #include <lib.h> +#include <amd/k8/k8.h> +#include <amd/k8/sysconf.h>
#include <spd_ddr2.h> /*
Modified: coreboot-v3/northbridge/amd/k8/incoherent_ht.c =================================================================== --- coreboot-v3/northbridge/amd/k8/incoherent_ht.c 2008-08-27 22:29:38 UTC (rev 827) +++ coreboot-v3/northbridge/amd/k8/incoherent_ht.c 2008-08-27 22:43:18 UTC (rev 828) @@ -756,7 +756,7 @@
}
-unsigned get_nodes(void); +unsigned int get_nodes(void);
void ht_setup_chains_x(struct sys_info *sysinfo) {