diff --git a/arch/x86/amd/model_fxx/dualcore.c b/arch/x86/amd/model_fxx/dualcore.c index 06b8d3eafb..c6bc826b3c 100644 --- a/arch/x86/amd/model_fxx/dualcore.c +++ b/arch/x86/amd/model_fxx/dualcore.c @@ -21,10 +21,11 @@ /** * Given a nodeid, return the count of the number of cores in that node. + * Note there are two very similar functions that do almost the same thing. * @param nodeid The nodeid * @returns The number of cores in that node. */ -unsigned int get_core_count(unsigned int nodeid) +unsigned int get_node_core_count(unsigned int nodeid) { u32 dword; dword = pci_conf1_read_config32(PCI_BDF(0, 0x18+nodeid, 3), NORTHBRIDGE_CAP); @@ -59,22 +60,22 @@ void set_apicid_cpuid_lo(void) void start_cores(unsigned nodeid) { u32 dword; - /* set PCI_DEV(0, 0x18+nodeid, 3), 0x44 bit 27 to redirect all MC4 + /* set PCI_BDF(0, 0x18+nodeid, 3), 0x44 bit 27 to redirect all MC4 * accesses and error logging to core0 */ dword = pci_conf1_read_config32(PCI_BDF(0, 0x18+nodeid, 3), MCA_NB_CONFIG); dword |= MNC_NBMCATOMSTCPUEN; // NbMcaToMstCpuEn bit - pci_conf1_write_config32(PCI_DEV(0, 0x18+nodeid, 3), MCA_NB_CONFIG, dword); - // set PCI_DEV(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1 + pci_conf1_write_config32(PCI_BDF(0, 0x18+nodeid, 3), MCA_NB_CONFIG, dword); + // set PCI_BDF(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1 dword = pci_conf1_read_config32(PCI_BDF(0, 0x18+nodeid, 0), HT_TRANSACTION_CONTROL); dword |= HTTC_CPU1_EN; - pci_conf1_write_config32(PCI_DEV(0, 0x18+nodeid, 0), HT_TRANSACTION_CONTROL, dword); + pci_conf1_write_config32(PCI_BDF(0, 0x18+nodeid, 0), HT_TRANSACTION_CONTROL, dword); } /** * start cores on all nodes including BSP. This is assumed to be running on core 0 of node 0 */ -static inline void start_all_cores(void) +void start_all_cores(void) { unsigned nodes; unsigned nodeid; @@ -88,7 +89,7 @@ static inline void start_all_cores(void) nodes = get_nodes(); for(nodeid=0; nodeid 0) { + if( get_node_core_count(nodeid) > 0) { start_cores(nodeid); } } diff --git a/arch/x86/amd/model_fxx/fidvid.c b/arch/x86/amd/model_fxx/fidvid.c index 353c4cd1ef..45a05a8ddc 100644 --- a/arch/x86/amd/model_fxx/fidvid.c +++ b/arch/x86/amd/model_fxx/fidvid.c @@ -12,6 +12,7 @@ #include #include #include +#include #define K8_SET_FIDVID_DEBUG 1 @@ -25,7 +26,7 @@ #define FX_SUPPORT 1 -static void enable_fid_change(void) +void enable_fid_change(void) { u32 dword; unsigned nodes; @@ -35,26 +36,26 @@ static void enable_fid_change(void) #warning document these settings! for (i = 0; i < nodes; i++) { - dword = pci_conf1_read_config32(PCI_DEV(0, 0x18+i, 3), 0xd8); + dword = pci_conf1_read_config32(PCI_BDF(0, 0x18+i, 3), 0xd8); dword &= 0x8ff00000; dword |= (2 << 28) | (0x02710); - pci_conf1_write_config32(PCI_DEV(0, 0x18+i, 3), 0xd8, dword); + pci_conf1_write_config32(PCI_BDF(0, 0x18+i, 3), 0xd8, dword); dword = 0x04e2a707; - pci_conf1_write_config32(PCI_DEV(0, 0x18+i, 3), 0xd4, dword); + pci_conf1_write_config32(PCI_BDF(0, 0x18+i, 3), 0xd4, dword); /* disable the DRAM interface at first, it will be enabled * by raminit again */ - dword = pci_conf1_read_config32(PCI_DEV(0, 0x18+i, 2), 0x94); + dword = pci_conf1_read_config32(PCI_BDF(0, 0x18+i, 2), 0x94); dword |= (1 << 14); - pci_conf1_write_config32(PCI_DEV(0, 0x18+i, 2), 0x94, dword); + pci_conf1_write_config32(PCI_BDF(0, 0x18+i, 2), 0x94, dword); dword = 0x23070700; /* enable FID/VID change */ // dword = 0x00070000; /* enable FID/VID change */ - pci_conf1_write_config32(PCI_DEV(0, 0x18+i, 3), 0x80, dword); + pci_conf1_write_config32(PCI_BDF(0, 0x18+i, 3), 0x80, dword); dword = 0x00132113; - pci_conf1_write_config32(PCI_DEV(0, 0x18+i, 3), 0x84, dword); + pci_conf1_write_config32(PCI_BDF(0, 0x18+i, 3), 0x84, dword); } } @@ -250,7 +251,7 @@ void init_fidvid_ap(unsigned bsp_apicid, unsigned apicid) u32 send; u32 readback = 0; unsigned int timeout = 1; - struct msr; + struct msr msr; u32 vid_cur; u32 fid_cur; u32 fid_max; @@ -425,7 +426,7 @@ static void store_ap_apicid(unsigned ap_apicid, void *gp) } #endif -static void init_fidvid_bsp(unsigned bsp_apicid) +void init_fidvid_bsp(unsigned bsp_apicid) { u32 vid_max; u32 fid_max; diff --git a/arch/x86/amd/model_fxx/init_cpus.c b/arch/x86/amd/model_fxx/init_cpus.c index 7d133ca6ad..794442ecf9 100644 --- a/arch/x86/amd/model_fxx/init_cpus.c +++ b/arch/x86/amd/model_fxx/init_cpus.c @@ -35,7 +35,6 @@ #include #include -typedef void (*process_ap_t) (unsigned apicid, void *gp); /* See page 330 of Publication # 26094 Revision: 3.30 Issue Date: February 2006 * for APIC id discussion */ @@ -51,7 +50,7 @@ typedef void (*process_ap_t) (unsigned apicid, void *gp); * @param process pointer to the function to run * @param gp general purpose argument to be passed as a parameter to the function */ -static void for_each_ap(unsigned bsp_apicid, unsigned core_range, +void for_each_ap(unsigned bsp_apicid, unsigned core_range, process_ap_t process_ap, void *gp) { /* Assume the OS will not change our APIC ID. Why does this matter? Because some of the setup @@ -74,8 +73,10 @@ static void for_each_ap(unsigned bsp_apicid, unsigned core_range, get_option(&disable_siblings, "dual_core"); /* There is an interesting problem in different steppings. See page 373. The interpretation of the - * APIC ID bits is different. To determine which order is used, check bit 54 of the - /* here we assume that all nodes are the same stepping. If not, "otherwise we can use use nb_cfg_54 from bsp for all nodes" */ + * APIC ID bits is different. To determine which order is used, check bit 54 of the programmers' guide + * here we assume that all nodes are the same stepping. + * If not, "otherwise we can use use nb_cfg_54 from bsp for all nodes" + */ nb_cfg_54 = read_nb_cfg_54(); @@ -88,7 +89,7 @@ static void for_each_ap(unsigned bsp_apicid, unsigned core_range, NBCAP_CmpCap_MASK); if (nb_cfg_54) { if (j == 0) // if it is single core, we need to increase siblings for apic calculation - J = 1; + j = 1; } siblings = j; @@ -192,7 +193,7 @@ void init_fidvid_ap(unsigned bsp_apicid, unsigned apicid); void print_apicid_nodeid_coreid(unsigned apicid, struct node_core_id id, const char *str) { - printk(BIOS_DEBUG, ""%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\r\n", + printk(BIOS_DEBUG, "%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\n", str, apicid, id.nodeid, id.coreid); } @@ -445,8 +446,7 @@ unsigned int init_cpus(unsigned cpu_init_detectedx, timeout = wait_cpu_state(bsp_apicid, 0x44); } if (timeout) { - print_initcpu8 - ("while waiting for BSP signal to STOP, timeout in ap ", + printk(BIOS_DEBUG, "while waiting for BSP signal to STOP, timeout in ap 0x%08x\n", apicid); } /* indicate that we are in state 44 as well. We are catching up to the BSP. */ diff --git a/include/arch/x86/amd/k8/k8.h b/include/arch/x86/amd/k8/k8.h index 10d704c28c..3b0f4718fb 100644 --- a/include/arch/x86/amd/k8/k8.h +++ b/include/arch/x86/amd/k8/k8.h @@ -62,6 +62,28 @@ #define TOP_MEM_MASK 0x007fffff #define TOP_MEM_MASK_KB (TOP_MEM_MASK >> 10) +/* MSRs for the model_fxx */ +/* the comments are confusing. Does "only E0" mean "only E0 or later" or really "Only E0" + */ +#define HWCR_MSR 0xC0010015 +#define NB_CFG_MSR 0xC001001f +#define LS_CFG_MSR 0xC0011020 +#define IC_CFG_MSR 0xC0011021 +#define DC_CFG_MSR 0xC0011022 +#define BU_CFG_MSR 0xC0011023 +#define FIDVID_CTL 0xC0010041 +#define FIDVID_STATUS 0xC0010042 + + +#define CPU_ID_FEATURES_MSR 0xc0011004 + +/* D0 only */ +#define CPU_ID_HYPER_EXT_FEATURES 0xc001100d +/* E0 only */ +#define LOGICAL_CPUS_NUM_MSR 0xc001100d + +#define CPU_ID_EXT_FEATURES_MSR 0xc0011005 + /* Definitions of various K8 registers for REV F*/ /* Function 0 */ #define NODEID 0x60 @@ -102,6 +124,10 @@ #define HTTC_HI_PRI_BYP_CNT_SHIFT 26 #define HTTC_HI_PRI_BYP_CNT_MASK 3 +#define HT_INIT_CONTROL 0x6c +#define HTIC_ColdR_Detect (1<<4) +#define HTIC_BIOSR_Detect (1<<5) +#define HTIC_INIT_Detect (1<<6) /* Function 1 */ #define PCI_IO_BASE0 0xc0 @@ -459,6 +485,7 @@ that are corresponding to 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, #define MCA_NB_CONFIG 0x44 #define MNC_ECC_EN (1 << 22) #define MNC_CHIPKILL_EN (1 << 23) +#define MNC_NBMCATOMSTCPUEN (1 << 27) #define SCRUB_CONTROL 0x58 #define SCRUB_NONE 0 @@ -520,6 +547,9 @@ that are corresponding to 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, #define NonCoherent (1 << 2) #define ConnectionPending (1 << 4) +/* Special LAPIC define which we only find in the K8 sources. */ +#define LAPIC_MSG_REG 0x380 + #ifndef ASSEMBLY /* Steppings of the K8 cpu */ @@ -614,9 +644,10 @@ struct node_core_id { unsigned coreid; }; -/* 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); +/* use this to get the nodeid and core id of the current cpu + * (but not other CPUs) + */ +struct node_core_id get_node_core_id(void); struct device; unsigned get_apicid_base(unsigned ioapic_num); @@ -628,8 +659,37 @@ struct hw_mem_hole_info { int node_id; }; +typedef void (*process_ap_t) (unsigned apicid, void *gp); + struct hw_mem_hole_info get_hw_mem_hole_info(void); +/* General purpose support functions that can run in any stage. */ + +unsigned int get_nodes(void); +unsigned int init_cpus(unsigned cpu_init_detectedx, + struct sys_info *sysinfo); +void setup_coherent_ht_domain(void); +void wait_all_core0_started(void); +void start_all_cores(void); +void wait_all_other_cores_started(unsigned bsp_apicid); +void for_each_ap(unsigned bsp_apicid, unsigned core_range, + process_ap_t process_ap, void *gp); +void ht_setup_chains_x(struct sys_info *sysinfo); +int optimize_link_coherent_ht(void); +int optimize_link_incoherent_ht(struct sys_info *sysinfo); +void allow_all_aps_stop(unsigned bsp_apicid); +unsigned int get_core_count(void); +void fill_mem_ctrl(int controllers, struct mem_controller *ctrl_a, + const u16 *spd_addr); +int lapic_remote_read(int apicid, int reg, unsigned int *pvalue); +void print_apicid_nodeid_coreid(unsigned apicid, struct node_core_id id, + const char *str); +unsigned int wait_cpu_state(unsigned apicid, unsigned state); +void set_apicid_cpuid_lo(void); +/* fidvid.c */ +void enable_fid_change(void); +void init_fidvid_bsp(unsigned bsp_apicid); + #endif /* ! ASSEMBLY */ #endif /* AMD_K8_H */ diff --git a/include/arch/x86/lapic.h b/include/arch/x86/lapic.h index 41b348068f..e72cded7f5 100644 --- a/include/arch/x86/lapic.h +++ b/include/arch/x86/lapic.h @@ -120,7 +120,8 @@ extern inline void lapic_write_atomic(unsigned long reg, unsigned long v) xchg((volatile unsigned long *)(LAPIC_DEFAULT_BASE+reg), v); } - +/* I think we don't want to do this any more. But there is one defined for k8 explicitly; what to do?*/ +#if 0 #ifdef CONFIG_X86_GOOD_APIC # define FORCE_READ_AROUND_WRITE 0 # define lapic_read_around(x) lapic_read(x) @@ -155,7 +156,7 @@ static inline int lapic_remote_read(int apicid, int reg, unsigned long *pvalue) return result; } - +#endif void setup_lapic(void); diff --git a/mainboard/amd/serengeti/initram.c b/mainboard/amd/serengeti/initram.c index 2744de9eb4..76f7a372ca 100644 --- a/mainboard/amd/serengeti/initram.c +++ b/mainboard/amd/serengeti/initram.c @@ -111,6 +111,7 @@ int main(void) * That way we can see the definition without grepping the source tree. */ void enable_smbus(void); + void enable_fid_change_on_sb(u16 sbbusn, u16 sbdn); u32 init_detected; static const u16 spd_addr[] = { //first node @@ -195,8 +196,8 @@ int main(void) // show final fid and vid { - struct msr; - msr=rdmsr(msr_t); + struct msr msr; + msr=rdmsr(FIDVID_STATUS); printk(BIOS_DEBUG, "begin msr fid, vid %08x:%08x\n", msr.hi ,msr.lo); } diff --git a/northbridge/amd/k8/coherent_ht.c b/northbridge/amd/k8/coherent_ht.c index 13196c001c..c3b9d38c23 100644 --- a/northbridge/amd/k8/coherent_ht.c +++ b/northbridge/amd/k8/coherent_ht.c @@ -1692,7 +1692,7 @@ int optimize_link_read_pointers(unsigned nodes) /** * get_nodes * see page 46 of the BKDG Publication # 26094 Revision: 3.30 Issue Date: February 2006 - * @returns an int containing the node id. + * @returns an int containing the number of nodes. * The format of the register is 32 bits, and the node count is in bits 4-6 */ unsigned int get_nodes(void)