blob: e1d4d2e0e26a4cdeaef88da4b78d7e4cfe6eb9dc [file] [log] [blame]
arch import user (historical)ef03afa2005-07-06 17:15:30 +00001/* 2004.12 yhlu add dual core support */
2
3#include <console/console.h>
4#include <cpu/cpu.h>
5#include <cpu/x86/lapic.h>
Stefan Reinauer9a16e3e2010-03-29 14:45:36 +00006#include <cpu/amd/multicore.h>
arch import user (historical)ef03afa2005-07-06 17:15:30 +00007#include <device/device.h>
8#include <device/pci.h>
9#include <pc80/mc146818rtc.h>
10#include <smp/spinlock.h>
11#include <cpu/x86/mtrr.h>
Stefan Reinauer991f1842015-11-22 23:40:29 +010012#include <cpu/amd/msr.h>
Stefan Reinauerf5183cf2005-12-01 11:01:01 +000013#include <cpu/amd/model_fxx_rev.h>
Yinghai Lud4b278c2006-10-04 20:46:15 +000014#include <cpu/amd/amdk8_sysconf.h>
arch import user (historical)ef03afa2005-07-06 17:15:30 +000015
Luc Verhaegena9c5ea02009-06-03 14:19:33 +000016static int disable_siblings = !CONFIG_LOGICAL_CPUS;
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +000017
Stefan Reinauerf5183cf2005-12-01 11:01:01 +000018#include "dualcore_id.c"
Jason Schildt8b26cab2005-10-25 21:24:23 +000019
arch import user (historical)ef03afa2005-07-06 17:15:30 +000020static int get_max_siblings(int nodes)
21{
22 device_t dev;
23 int nodeid;
24 int siblings=0;
25
26 //get max siblings from all the nodes
27 for(nodeid=0; nodeid<nodes; nodeid++){
28 int j;
29 dev = dev_find_slot(0, PCI_DEVFN(0x18+nodeid, 3));
Stefan Reinauer14e22772010-04-27 06:56:47 +000030 j = (pci_read_config32(dev, 0xe8) >> 12) & 3;
arch import user (historical)ef03afa2005-07-06 17:15:30 +000031 if(siblings < j) {
32 siblings = j;
33 }
34 }
Stefan Reinauer14e22772010-04-27 06:56:47 +000035
arch import user (historical)ef03afa2005-07-06 17:15:30 +000036 return siblings;
37}
38
39static void enable_apic_ext_id(int nodes)
40{
41 device_t dev;
42 int nodeid;
43
44 //enable APIC_EXIT_ID all the nodes
45 for(nodeid=0; nodeid<nodes; nodeid++){
46 uint32_t val;
47 dev = dev_find_slot(0, PCI_DEVFN(0x18+nodeid, 0));
48 val = pci_read_config32(dev, 0x68);
49 val |= (1<<17)|(1<<18);
Stefan Reinauer14e22772010-04-27 06:56:47 +000050 pci_write_config32(dev, 0x68, val);
arch import user (historical)ef03afa2005-07-06 17:15:30 +000051 }
52}
53
54
55unsigned get_apicid_base(unsigned ioapic_num)
56{
57 device_t dev;
58 int nodes;
59 unsigned apicid_base;
60 int siblings;
61 unsigned nb_cfg_54;
62 int bsp_apic_id = lapicid(); // bsp apicid
63
Myles Watson4839e2c2010-04-08 15:06:44 +000064 get_option(&disable_siblings, "multi_core");
arch import user (historical)ef03afa2005-07-06 17:15:30 +000065
66 //get the nodes number
67 dev = dev_find_slot(0, PCI_DEVFN(0x18,0));
68 nodes = ((pci_read_config32(dev, 0x60)>>4) & 7) + 1;
69
70 siblings = get_max_siblings(nodes);
71
72 if(bsp_apic_id > 0) { // io apic could start from 0
Stefan Reinauer14e22772010-04-27 06:56:47 +000073 return 0;
arch import user (historical)ef03afa2005-07-06 17:15:30 +000074 } else if(pci_read_config32(dev, 0x68) & ( (1<<17) | (1<<18)) ) { // enabled ext id but bsp = 0
Stefan Reinauer14e22772010-04-27 06:56:47 +000075 return 1;
arch import user (historical)ef03afa2005-07-06 17:15:30 +000076 }
77
78 nb_cfg_54 = read_nb_cfg_54();
79
Stefan Reinauerf5183cf2005-12-01 11:01:01 +000080#if 0
Stefan Reinauer38f147e2010-02-08 12:20:50 +000081 //it is for all e0 single core and nc_cfg_54 low is set, but in the romstage.c stage we do not set that bit for it.
Stefan Reinauerf5183cf2005-12-01 11:01:01 +000082 if(nb_cfg_54 && (!disable_siblings) && (siblings == 0)) {
83 //we need to check if e0 single core is there
84 int i;
85 for(i=0; i<nodes; i++) {
86 if(is_e0_later_in_bsp(i)) {
87 siblings = 1;
88 break;
89 }
90 }
91 }
92#endif
93
Martin Roth4c3ab732013-07-08 16:23:54 -060094 //Construct apicid_base
arch import user (historical)ef03afa2005-07-06 17:15:30 +000095
96 if((!disable_siblings) && (siblings>0) ) {
Martin Roth4c3ab732013-07-08 16:23:54 -060097 /* for 8 way dual core, we will used up apicid 16:16, actually 16 is not allowed by current kernel
arch import user (historical)ef03afa2005-07-06 17:15:30 +000098 and the kernel will try to get one that is small than 16 to make io apic work.
99 I don't know when the kernel can support 256 apic id. (APIC_EXT_ID is enabled) */
100
101 //4:10 for two way 8:12 for four way 16:16 for eight way
102 //Use CONFIG_MAX_PHYSICAL_CPUS instead of nodes for better consistency?
Stefan Reinauer14e22772010-04-27 06:56:47 +0000103 apicid_base = nb_cfg_54 ? (siblings+1) * nodes : 8 * siblings + nodes;
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000104
105 }
106 else {
107 apicid_base = nodes;
108 }
109
110 if((apicid_base+ioapic_num-1)>0xf) {
111 // We need to enable APIC EXT ID
Stefan Reinauer64ed2b72010-03-31 14:47:43 +0000112 printk(BIOS_INFO, "if the IO APIC device doesn't support 256 apic id, \n you need to set CONFIG_ENABLE_APIC_EXT_ID in romstage.c so you can spare 16 id for ioapic\n");
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000113 enable_apic_ext_id(nodes);
114 }
Stefan Reinauer14e22772010-04-27 06:56:47 +0000115
arch import user (historical)ef03afa2005-07-06 17:15:30 +0000116 return apicid_base;
117}