2 * This file is part of the coreboot project.
4 * Copyright (C) 2007 Advanced Micro Devices, Inc.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 //it takes the ENABLE_APIC_EXT_ID and APIC_ID_OFFSET and LIFT_BSP_APIC_ID
22 #ifndef FAM10_SET_FIDVID
23 #define FAM10_SET_FIDVID 1
26 #ifndef FAM10_SET_FIDVID_CORE0_ONLY
27 /* MSR FIDVID_CTL and FIDVID_STATUS are shared by cores,
28 Need to do every AP to set common FID/VID*/
29 #define FAM10_SET_FIDVID_CORE0_ONLY 0
33 static inline void print_initcpu8 (const char *strval, u8 val)
35 printk_debug("%s%02x\n", strval, val);
38 static inline void print_initcpu8_nocr (const char *strval, u8 val)
40 printk_debug("%s%02x", strval, val);
44 static inline void print_initcpu16 (const char *strval, u16 val)
46 printk_debug("%s%04x\n", strval, val);
50 static inline void print_initcpu(const char *strval, u32 val)
52 printk_debug("%s%08x\n", strval, val);
56 static void prep_fid_change(void);
57 static void init_fidvid_stage2(u32 apicid, u32 nodeid);
59 #if PCI_IO_CFG_EXT == 1
60 static inline void set_EnableCf8ExtCfg(void)
62 // set the NB_CFG[46]=1;
64 msr = rdmsr(NB_CFG_MSR);
65 // EnableCf8ExtCfg: We need that to access PCI_IO_CFG_EXT 4K range
66 msr.hi |= (1<<(46-32));
67 wrmsr(NB_CFG_MSR, msr);
70 static inline void set_EnableCf8ExtCfg(void) { }
75 #define PCI_MMIO_BASE 0xfe000000
76 /* because we will use gs to store hi, so need to make sure lo can start
77 from 0, So PCI_MMIO_BASE & 0x00ffffff should be equal to 0*/
79 static inline void set_pci_mmio_conf_reg(void)
83 msr = rdmsr(0xc0010058);
84 msr.lo &= ~(0xfff00000 | (0xf << 2));
85 // 256 bus per segment, MMIO reg will be 4G , enable MMIO Config space
86 msr.lo |= ((8+PCI_BUS_SEGN_BITS) << 2) | (1 << 0);
87 msr.hi &= ~(0x0000ffff);
88 msr.hi |= (PCI_MMIO_BASE >> (32-8));
89 wrmsr(0xc0010058, msr); // MMIO Config Base Address Reg
91 //mtrr for that range?
92 // set_var_mtrr_x(7, PCI_MMIO_BASE<<8, PCI_MMIO_BASE>>(32-8), 0x00000000, 0x01, MTRR_TYPE_UNCACHEABLE);
96 msr.hi = (PCI_MMIO_BASE >> (32-8));
98 wrmsr(0xc0000101, msr); //GS_Base Reg
106 typedef void (*process_ap_t)(u32 apicid, void *gp);
108 //core_range = 0 : all cores
109 //core range = 1 : core 0 only
110 //core range = 2 : cores other than core0
112 static void for_each_ap(u32 bsp_apicid, u32 core_range,
113 process_ap_t process_ap, void *gp)
115 // here assume the OS don't change our apicid
120 u32 disable_siblings;
124 u32 ApicIdCoreIdSize;
126 /* get_nodes define in ht_wrapper.c */
129 disable_siblings = !CONFIG_LOGICAL_CPUS;
131 #if CONFIG_LOGICAL_CPUS == 1
132 if(read_option(CMOS_VSTART_quad_core, CMOS_VLEN_quad_core, 0) != 0) { // 0 mean quad core
133 disable_siblings = 1;
137 /* Assume that all node are same stepping, otherwise we can use use
138 nb_cfg_54 from bsp for all nodes */
139 nb_cfg_54 = read_nb_cfg_54();
141 ApicIdCoreIdSize = (cpuid_ecx(0x80000008) >> 12 & 0xf);
142 if(ApicIdCoreIdSize) {
143 siblings = ((1 << ApicIdCoreIdSize) - 1);
145 siblings = 3; //quad core
148 for (i = 0; i < nodes; i++) {
149 cores_found = get_core_num_in_bsp(i);
153 if (core_range == 2) {
159 if (disable_siblings || (core_range==1)) {
166 for (j = jstart; j <= jend; j++) {
167 ap_apicid = i * (nb_cfg_54 ? (siblings + 1):1) + j * (nb_cfg_54 ? 1:64);
169 #if (ENABLE_APIC_EXT_ID == 1) && (APIC_ID_OFFSET > 0)
170 #if LIFT_BSP_APIC_ID == 0
171 if( (i != 0) || (j != 0)) /* except bsp */
173 ap_apicid += APIC_ID_OFFSET;
176 if(ap_apicid == bsp_apicid) continue;
178 process_ap(ap_apicid, gp);
184 /* FIXME: Duplicate of what is in lapic.h? */
185 static inline int lapic_remote_read(int apicid, int reg, u32 *pvalue)
190 lapic_wait_icr_idle();
191 lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
192 lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
196 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
197 } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
201 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
202 } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
206 if (status == LAPIC_ICR_RR_VALID) {
207 *pvalue = lapic_read(LAPIC_RRR);
214 /* Use the LAPIC timer count register to hold each cores init status */
215 #define LAPIC_MSG_REG 0x380
218 #if FAM10_SET_FIDVID == 1
219 static void init_fidvid_ap(u32 bsp_apicid, u32 apicid, u32 nodeid, u32 coreid);
222 static inline __attribute__((always_inline)) void print_apicid_nodeid_coreid(u32 apicid, struct node_core_id id, const char *str)
224 printk_debug("%s --- { APICID = %02x NODEID = %02x COREID = %02x} ---\n", str, apicid, id.nodeid, id.coreid);
228 static unsigned wait_cpu_state(u32 apicid, u32 state)
234 if (lapic_remote_read(apicid, LAPIC_MSG_REG, &readback) != 0) continue;
235 if ((readback & 0x3f) == state) {
237 break; //target cpu is in stage started
250 static void wait_ap_started(u32 ap_apicid, void *gp )
253 timeout = wait_cpu_state(ap_apicid, 0x13); // started
255 print_initcpu8_nocr("* AP ", ap_apicid);
256 print_initcpu(" didn't start timeout:", timeout);
259 print_initcpu8_nocr("AP started: ", ap_apicid);
264 static void wait_all_aps_started(u32 bsp_apicid)
266 for_each_ap(bsp_apicid, 0 , wait_ap_started, (void *)0);
270 static void wait_all_other_cores_started(u32 bsp_apicid)
272 // all aps other than core0
273 print_debug("started ap apicid: ");
274 for_each_ap(bsp_apicid, 2 , wait_ap_started, (void *)0);
279 static void allow_all_aps_stop(u32 bsp_apicid)
281 /* Called by the BSP to indicate AP can stop */
283 /* FIXME Do APs use this?
284 Looks like wait_till_sysinfo_in_ram is used instead. */
286 // allow aps to stop use 6 bits for state
287 lapic_write(LAPIC_MSG_REG, (bsp_apicid << 24) | 0x14);
291 static void STOP_CAR_AND_CPU()
293 disable_cache_as_ram(); // inline
298 #ifndef MEM_TRAIN_SEQ
299 #define MEM_TRAIN_SEQ 0
302 #if RAMINIT_SYSINFO == 1
303 static u32 init_cpus(u32 cpu_init_detectedx ,struct sys_info *sysinfo)
305 static u32 init_cpus(u32 cpu_init_detectedx)
310 struct node_core_id id;
313 * already set early mtrr in cache_as_ram.inc
316 /* enable access pci conf via mmio*/
317 set_pci_mmio_conf_reg();
319 /* that is from initial apicid, we need nodeid and coreid
321 id = get_node_core_id_x();
323 /* NB_CFG MSR is shared between cores, so we need make sure
324 core0 is done at first --- use wait_all_core0_started */
326 set_apicid_cpuid_lo(); /* only set it on core0 */
327 set_EnableCf8ExtCfg(); /* only set it on core0 */
328 #if (ENABLE_APIC_EXT_ID == 1)
329 enable_apic_ext_id(id.nodeid);
336 #if (ENABLE_APIC_EXT_ID == 1) && (APIC_ID_OFFSET > 0)
337 u32 initial_apicid = get_initial_apicid();
339 #if LIFT_BSP_APIC_ID == 0
340 if( initial_apicid != 0 ) // other than bsp
343 /* use initial apic id to lift it */
344 u32 dword = lapic_read(LAPIC_ID);
345 dword &= ~(0xff << 24);
346 dword |= (((initial_apicid + APIC_ID_OFFSET) & 0xff) << 24);
348 lapic_write(LAPIC_ID, dword);
351 #if LIFT_BSP_APIC_ID == 1
352 bsp_apicid += APIC_ID_OFFSET;
357 /* get the apicid, it may be lifted already */
360 // show our apicid, nodeid, and coreid
362 if (id.nodeid!=0) //all core0 except bsp
363 print_apicid_nodeid_coreid(apicid, id, " core0: ");
365 else { //all other cores
366 print_apicid_nodeid_coreid(apicid, id, " corex: ");
370 if (cpu_init_detectedx) {
371 print_apicid_nodeid_coreid(apicid, id, "\n\n\nINIT detected from ");
372 print_debug("\nIssuing SOFT_RESET...\n");
377 if(!(warm_reset_detect(id.nodeid))) //FIXME: INIT is checked above but check for more resets?
378 distinguish_cpu_resets(id.nodeid); // Also indicates we are started
381 // Mark the core as started.
382 lapic_write(LAPIC_MSG_REG, (apicid << 24) | 0x13);
385 if(apicid != bsp_apicid) {
386 #if FAM10_SET_FIDVID == 1
387 #if (CONFIG_LOGICAL_CPUS == 1) && (FAM10_SET_FIDVID_CORE0_ONLY == 1)
388 // Run on all AP for proper FID/VID setup.
389 if(id.coreid == 0 ) // only need set fid for core0
392 // check warm(bios) reset to call stage2 otherwise do stage1
393 if (warm_reset_detect(id.nodeid)) {
394 printk_debug("init_fidvid_stage2 apicid: %02x\n", apicid);
395 init_fidvid_stage2(apicid, id.nodeid);
397 printk_debug("init_fidvid_ap(stage1) apicid: %02x\n", apicid);
398 init_fidvid_ap(bsp_apicid, apicid, id.nodeid, id.coreid);
403 /* AP is ready, Wait for the BSP to get memory configured */
404 /* FIXME: many cores spinning on node0 pci register seems to be bad.
405 * Why do we need to wait? These APs are just going to go sit in a hlt.
407 //wait_till_sysinfo_in_ram();
409 set_init_ram_access();
412 printk_debug("\nAP %02x should be halted but you are reading this....\n", apicid);
419 static u32 is_core0_started(u32 nodeid)
423 device = NODE_PCI(nodeid, 0);
424 htic = pci_read_config32(device, HT_INIT_CONTROL);
425 htic &= HTIC_ColdR_Detect;
430 static void wait_all_core0_started(void)
432 /* When core0 is started, it will distingush_cpu_resets
433 . So wait for that to finish */
435 u32 nodes = get_nodes();
437 printk_debug("Wait all core0s started \n");
438 for(i=1;i<nodes;i++) { // skip bsp, because it is running on bsp
439 while(!is_core0_started(i)) {}
440 print_initcpu8(" Core0 started on node: ", i);
442 printk_debug("Wait all core0s started done\n");
444 #if CONFIG_MAX_PHYSICAL_CPUS > 1
446 * void start_node(u32 node)
448 * start the core0 in node, so it can generate HT packet to feature code.
450 * This function starts the AP nodes core0s. wait_all_core0_started() in
451 * cache_as_ram_auto.c waits for all the AP to be finished before continuing
454 static void start_node(u8 node)
458 /* Enable routing table */
459 printk_debug("Start node %02x", node);
462 /* For CAR_FAM10 support, we need to set Dram base/limit for the new node */
463 pci_write_config32(NODE_MP(node), 0x44, 0);
464 pci_write_config32(NODE_MP(node), 0x40, 3);
467 /* Allow APs to make requests (ROM fetch) */
468 val=pci_read_config32(NODE_HT(node), 0x6c);
470 pci_write_config32(NODE_HT(node), 0x6c, val);
472 printk_debug(" done.\n");
477 * static void setup_remote_node(u32 node)
479 * Copy the BSP Adress Map to each AP.
481 static void setup_remote_node(u8 node)
483 /* There registers can be used with F1x114_x Address Map at the
484 same time, So must set them even 32 node */
485 static const u16 pci_reg[] = {
486 /* DRAM Base/Limits Registers */
487 0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c,
488 0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
489 0x144, 0x14c, 0x154, 0x15c, 0x164, 0x16c, 0x174, 0x17c,
490 0x140, 0x148, 0x150, 0x158, 0x160, 0x168, 0x170, 0x178,
491 /* MMIO Base/Limits Registers */
492 0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
493 0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
494 /* IO Base/Limits Registers */
495 0xc4, 0xcc, 0xd4, 0xdc,
496 0xc0, 0xc8, 0xd0, 0xd8,
497 /* Configuration Map Registers */
498 0xe0, 0xe4, 0xe8, 0xec,
502 printk_debug("setup_remote_node: %02x", node);
504 /* copy the default resource map from node 0 */
505 for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
509 value = pci_read_config32(NODE_MP(0), reg);
510 pci_write_config32(NODE_MP(node), reg, value);
513 printk_debug(" done\n");
517 * finalize_node_setup()
519 * Do any additional post HT init
521 * This could really be moved to cache_as_ram_auto.c since it really isn't HT init.
523 void finalize_node_setup(struct sys_info *sysinfo)
526 u8 nodes = get_nodes();
529 #if RAMINIT_SYSINFO == 1
530 /* read Node0 F0_0x64 bit [8:10] to find out SbLink # */
531 reg = pci_read_config32(NODE_HT(0), 0x64);
532 sysinfo->sblk = (reg>>8) & 7;
534 sysinfo->nodes = nodes;
535 sysinfo->sbdn = get_sbdn(sysinfo->sbbusn);
538 setup_link_trans_cntrl();
540 #if FAM10_SET_FIDVID == 1
541 // Prep each node for FID/VID setup.
545 #if CONFIG_MAX_PHYSICAL_CPUS > 1
546 /* Skip the BSP, start at node 1 */
547 for(i=1; i<nodes; i++) {
548 setup_remote_node(i);