Author: rminnich Date: 2008-09-19 20:35:22 +0200 (Fri, 19 Sep 2008) New Revision: 868
Modified: coreboot-v3/arch/x86/amd/k8/stage1.c 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/mainboard/amd/serengeti/Makefile coreboot-v3/mainboard/amd/serengeti/initram.c coreboot-v3/mainboard/amd/serengeti/mainboard.h coreboot-v3/southbridge/amd/amd8111/stage1_reset.c coreboot-v3/southbridge/amd/amd8111/stage1_smbus.c Log: substantial cleanups for k8.
AMP TinyGX still builds, this won't affect other platforms.
clean up 8111 stage1 code; add function to smbus, memreset_setup_amd8111, for the 8111 specific parts of memreset.
include k8 .h to reduce warnings. Turn some things into functions (romcc legacy cleanup) and put them in .c files.
simnow actually successfully gets through a reset cycle now.
Next is to fix the fidvid code.
Signed-off-by: Ronald G. Minnich rminnich@gmail.com Acked-by: Ronald G. Minnich rminnich@gmail.com
Modified: coreboot-v3/arch/x86/amd/k8/stage1.c =================================================================== --- coreboot-v3/arch/x86/amd/k8/stage1.c 2008-09-18 16:45:46 UTC (rev 867) +++ coreboot-v3/arch/x86/amd/k8/stage1.c 2008-09-19 18:35:22 UTC (rev 868) @@ -28,6 +28,16 @@ #include <amd/k8/k8.h>
/** + * Set the MTRR for initial ram access. + * be warned, this will be used by core other than core 0/node 0 or core0/node0 when cpu_reset. + * This warning has some significance I don't yet understand. + */ +void set_init_ram_access(void) +{ + set_var_mtrr(0, 0x00000000, CONFIG_CBMEMK << 10, MTRR_TYPE_WRBACK); +} + +/** * Disable Cache As RAM (CAR) after memory is setup. * * Unknown how to do this just yet. @@ -60,5 +70,7 @@ [carsizequads] "i" (CONFIG_CARSIZE/4) : "memory", "%edi", "%esi", "%ecx"); banner(BIOS_DEBUG, "Disable_car: done wbinvd"); + /* we're now running in ram. Although this will be called again, it does no harm to call it here. */ + set_init_ram_access(); banner(BIOS_DEBUG, "disable_car: done"); }
Modified: coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c =================================================================== --- coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c 2008-09-18 16:45:46 UTC (rev 867) +++ coreboot-v3/arch/x86/amd/model_fxx/init_cpus.c 2008-09-19 18:35:22 UTC (rev 868) @@ -246,11 +246,33 @@ } }
+/** + * disable cache as ram on a BSP. + * For reasons not totally known we are saving ecx and edx. + * That will work on k8 as we copy the stack and return in the same stack frame. + */ +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" + ); +} + + /** * wait for all apics to start. Make sure we don't wait on ourself. * @param bsp_apicid The BSP APIC ID */ -static void wait_all_aps_started(unsigned bsp_apicid) +void wait_all_aps_started(unsigned bsp_apicid) { for_each_ap(bsp_apicid, 0, wait_ap_started, (void *) 0); }
Modified: coreboot-v3/include/arch/x86/amd/k8/k8.h =================================================================== --- coreboot-v3/include/arch/x86/amd/k8/k8.h 2008-09-18 16:45:46 UTC (rev 867) +++ coreboot-v3/include/arch/x86/amd/k8/k8.h 2008-09-19 18:35:22 UTC (rev 868) @@ -743,23 +743,8 @@ ); }
-static void disable_cache_as_ram_bsp(void) -{ - __asm__ volatile ( -// "pushl %eax\n\t" - "pushl %edx\n\t" - "pushl %ecx\n\t" - ); +void disable_cache_as_ram_bsp(void);
- 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-09-18 16:45:46 UTC (rev 867) +++ coreboot-v3/include/arch/x86/cpu.h 2008-09-19 18:35:22 UTC (rev 868) @@ -243,14 +243,8 @@
}
-/* 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 set_init_ram_access(void);
- - void * bottom_of_stack(void); EXPORT_SYMBOL(bottom_of_stack); struct global_vars * global_vars(void);
Modified: coreboot-v3/mainboard/amd/serengeti/Makefile =================================================================== --- coreboot-v3/mainboard/amd/serengeti/Makefile 2008-09-18 16:45:46 UTC (rev 867) +++ coreboot-v3/mainboard/amd/serengeti/Makefile 2008-09-19 18:35:22 UTC (rev 868) @@ -23,6 +23,7 @@ STAGE0_MAINBOARD_SRC := $(src)/lib/clog2.c \ $(src)/mainboard/$(MAINBOARDDIR)/stage1.c \ $(src)/mainboard/$(MAINBOARDDIR)/option_table.c \ + $(src)/arch/x86/stage1_mtrr.c \ $(src)/southbridge/amd/amd8111/stage1_smbus.c \ $(src)/southbridge/amd/amd8111/stage1_ctrl.c \ $(src)/southbridge/amd/amd8111/stage1_enable_rom.c \
Modified: coreboot-v3/mainboard/amd/serengeti/initram.c =================================================================== --- coreboot-v3/mainboard/amd/serengeti/initram.c 2008-09-18 16:45:46 UTC (rev 867) +++ coreboot-v3/mainboard/amd/serengeti/initram.c 2008-09-19 18:35:22 UTC (rev 868) @@ -51,14 +51,21 @@ #define DIMM6 0x56 #define DIMM7 0x57
-# warning fix hard_reset -void hard_reset(void) +/* this code is very mainboard dependent, sadly. */ +/** + * call the amd 8111 memreset_setup_amd8111 function to jam the GPIOs to reset memory. + */ +static void memreset_setup(void) { + void memreset_setup_amd8111(u8 data, u16 offset); + //GPIO on amd8111 to enable MEMRST ???? + memreset_setup_amd8111((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), 0xc0 + 16); //REVC_MEMRST_EN=1 + memreset_setup_amd8111((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), 0xc0 + 17); } -void memreset_setup(void) -{ -}
+/** + * this is a no op on this platform. + */ void memreset(int controllers, const struct mem_controller *ctrl) { } @@ -66,25 +73,30 @@ void activate_spd_rom(const struct mem_controller *ctrl) { #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)); + 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); + smbus_write_byte(SMBUS_HUB, 0x03, 0); }
+/** + * read a byte from spd. + * @param device device to read from + * @param address address in the spd ROM + * @return the value of the byte at that address. + */ u8 spd_read_byte(u16 device, u8 address) { int smbus_read_byte(u16 device, u16 address); - return smbus_read_byte(device, address); + return smbus_read_byte(device, address); }
- /** * main for initram for the AMD Serengeti * @param init_detected Used to indicate that we have been started via init @@ -113,30 +125,33 @@ */ void enable_smbus(void); void enable_fid_change_on_sb(u16 sbbusn, u16 sbdn); + void soft_reset_x(unsigned sbbusn, unsigned sbdn); u32 init_detected; static const u16 spd_addr[] = { - //first node - RC0|DIMM0, RC0|DIMM2, 0, 0, - RC0|DIMM1, RC0|DIMM3, 0, 0, + //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, + //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, + // 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; + int needs_reset; + unsigned bsp_apicid = 0; + struct msr msr; + printk(BIOS_DEBUG, "Hi there from stage1\n"); post_code(POST_START_OF_MAIN); sysinfo = &(global_vars()->sys_info); @@ -146,116 +161,91 @@ */ bsp_apicid = init_cpus(init_detected, sysinfo);
-// dump_mem(DCACHE_RAM_BASE+DCACHE_RAM_SIZE-0x200, DCACHE_RAM_BASE+DCACHE_RAM_SIZE); +// 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, 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 + 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 + 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 + // 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_all_cores(); + start_all_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 + 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); + needs_reset = optimize_link_coherent_ht(); + needs_reset |= optimize_link_incoherent_ht(sysinfo); #endif
-#if K8_SET_FIDVID == 1 + msr = rdmsr(FIDVID_STATUS); + printk(BIOS_DEBUG, "begin msr fid, vid %08x:%08x\n", + msr.hi, msr.lo);
- { - struct msr msr; - msr=rdmsr(FIDVID_STATUS); - printk(BIOS_DEBUG, "begin msr fid, vid %08x:%08x\n", msr.hi ,msr.lo); - - } - enable_fid_change();
enable_fid_change_on_sb(sysinfo->sbbusn, sysinfo->sbdn);
- init_fidvid_bsp(bsp_apicid); + init_fidvid_bsp(bsp_apicid);
- // show final fid and vid - { - struct msr msr; - msr=rdmsr(FIDVID_STATUS); - printk(BIOS_DEBUG, "begin msr fid, vid %08x:%08x\n", msr.hi ,msr.lo); + msr = rdmsr(FIDVID_STATUS); + printk(BIOS_DEBUG, "begin msr fid, vid %08x:%08x\n", + msr.hi, msr.lo);
- } -#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) { - printk(BIOS_INFO, "ht reset -\r\n"); -#warning define soft_reset_x -//FIXME soft_reset_x(sysinfo->sbbusn, sysinfo->sbdn); - } + // fidvid change will issue one LDTSTOP and the HT change will be effective too + if (needs_reset) { + printk(BIOS_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; + //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? */ + /* 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(); + 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, 0x18, 2), 0x98); dump_pci_device_index_wait(PCI_DEV(0, 0x19, 2), 0x98); #endif
#warning re-implement post_cache_as_ram - // post_cache_as_ram(); // bsp swtich stack to ram and copy sysinfo ram now + // post_cache_as_ram(); // bsp switch stack to ram and copy sysinfo ram now
printk(BIOS_DEBUG, "stage1 returns\n"); return 0;
Modified: coreboot-v3/mainboard/amd/serengeti/mainboard.h =================================================================== --- coreboot-v3/mainboard/amd/serengeti/mainboard.h 2008-09-18 16:45:46 UTC (rev 867) +++ coreboot-v3/mainboard/amd/serengeti/mainboard.h 2008-09-19 18:35:22 UTC (rev 868) @@ -33,12 +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. - * In the model_fxx support it is hardwired to 1. - * We'll assume that setting it to 1 is ok. - */ #define K8_SET_FIDVID 1 /* MSR FIDVID_CTL and FIDVID_STATUS are shared by cores, * so may don't need to do twice */
Modified: coreboot-v3/southbridge/amd/amd8111/stage1_reset.c =================================================================== --- coreboot-v3/southbridge/amd/amd8111/stage1_reset.c 2008-09-18 16:45:46 UTC (rev 867) +++ coreboot-v3/southbridge/amd/amd8111/stage1_reset.c 2008-09-19 18:35:22 UTC (rev 868) @@ -30,7 +30,10 @@
void hard_reset(void) { - u32 dev; + void set_bios_reset(void); + unsigned get_sblk(void); + u8 node_link_to_bus(unsigned int node, unsigned int link); + u32 busdevfn; unsigned int bus; unsigned int node = 0; unsigned int link = get_sblk(); @@ -39,9 +42,9 @@ * There can only be one 8111 on a hypertransport chain/bus. */ bus = node_link_to_bus(node, link); - pci_locate_device_on_bus(0, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_ISA, &dev); + pci_conf1_find_on_bus(0, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_ISA, &busdevfn);
/* Reset */ set_bios_reset(); - pci_write_config8(dev, 0x47, 1); + pci_conf1_write_config8(busdevfn, 0x47, 1); }
Modified: coreboot-v3/southbridge/amd/amd8111/stage1_smbus.c =================================================================== --- coreboot-v3/southbridge/amd/amd8111/stage1_smbus.c 2008-09-18 16:45:46 UTC (rev 867) +++ coreboot-v3/southbridge/amd/amd8111/stage1_smbus.c 2008-09-19 18:35:22 UTC (rev 868) @@ -305,3 +305,17 @@ return smbus_read_byte(device, address); }
+/** + * memreset_setup_amd8111 + * This function is part of a complex dance played between the mainboard and + * the southbridge. We don't want to export SMBUS_IO_BASE, but neither can the + * amd8111 know about what GPIOs connect to what reset lines. So + * we split the difference. The mainboard must call this function with bytes + * to be output to accomplish reset, as well as the offset from IOBASE; + * amd8111 will output those bytes to SMBIOS_IOBASE. + * The caller of this function must have called spd_init for it to work correctly. + */ +void memreset_setup_amd8111(u8 data, u16 offset) +{ + outb(data, SMBUS_IO_BASE + offset); +}