This patch unifies the use of config options in v2 to all start with CONFIG_
[coreboot.git] / src / cpu / amd / dualcore / dualcore.c
1 /* 2004.12 yhlu add dual core support */
2
3
4 #ifndef SET_NB_CFG_54
5         #define SET_NB_CFG_54 1
6 #endif
7
8 #include "cpu/amd/dualcore/dualcore_id.c"
9
10 static inline unsigned get_core_num_in_bsp(unsigned nodeid)
11 {
12         uint32_t dword;
13         dword = pci_read_config32(PCI_DEV(0, 0x18+nodeid, 3), 0xe8);
14         dword >>= 12;
15         dword &= 3;
16         return dword;
17 }
18
19 #if SET_NB_CFG_54 == 1
20 static inline uint8_t set_apicid_cpuid_lo(void)
21 {
22 #if CONFIG_K8_REV_F_SUPPORT == 0
23         if(is_cpu_pre_e0()) return 0; // pre_e0 can not be set
24 #endif
25
26         // set the NB_CFG[54]=1; why the OS will be happy with that ???
27         msr_t msr;
28         msr = rdmsr(NB_CFG_MSR);
29         msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
30         wrmsr(NB_CFG_MSR, msr);
31
32         return 1;
33 }
34 #else
35
36 static inline void set_apicid_cpuid_lo(void) { }
37
38 #endif
39
40 static inline void real_start_other_core(unsigned nodeid)
41 {
42         uint32_t dword;
43         // set PCI_DEV(0, 0x18+nodeid, 3), 0x44 bit 27 to redirect all MC4 accesses and error logging to core0
44         dword = pci_read_config32(PCI_DEV(0, 0x18+nodeid, 3), 0x44);
45         dword |= 1<<27; // NbMcaToMstCpuEn bit
46         pci_write_config32(PCI_DEV(0, 0x18+nodeid, 3), 0x44, dword);
47         // set PCI_DEV(0, 0x18+nodeid, 0), 0x68 bit 5 to start core1
48         dword = pci_read_config32(PCI_DEV(0, 0x18+nodeid, 0), 0x68);
49         dword |= 1<<5;
50         pci_write_config32(PCI_DEV(0, 0x18+nodeid, 0), 0x68, dword);
51 }
52
53 //it is running on core0 of node0
54 static inline void start_other_cores(void)
55 {
56         unsigned nodes;
57         unsigned nodeid;
58
59         if (CONFIG_HAVE_OPTION_TABLE &&
60             read_option(CMOS_VSTART_dual_core, CMOS_VLEN_dual_core, 0) != 0)  {
61                 return; // disable dual_core
62         }
63
64         nodes = get_nodes();
65
66         for(nodeid=0; nodeid<nodes; nodeid++) {
67                 if( get_core_num_in_bsp(nodeid) > 0) {
68                         real_start_other_core(nodeid);
69                 }
70         }
71
72 }
73 #if CONFIG_USE_DCACHE_RAM == 0
74 static void do_k8_init_and_stop_secondaries(void)
75 {
76         struct node_core_id id;
77         device_t dev;
78         unsigned apicid;
79         unsigned max_siblings;
80         msr_t msr;
81         
82         /* Skip this if there was a built in self test failure */
83
84         if (is_cpu_pre_e0()) {
85                 id.nodeid = lapicid() & 0x7;
86                 id.coreid = 0;
87         } else {
88                 /* Which cpu are we on? */
89                 id = get_node_core_id_x();
90
91                 /* Set NB_CFG_MSR
92                  * Linux expect the core to be in the least signficant bits.
93                  */
94                 msr = rdmsr(NB_CFG_MSR);
95                 msr.hi |= (1<<(54-32)); // InitApicIdCpuIdLo
96                 wrmsr(NB_CFG_MSR, msr);
97         }
98
99         /* For now assume all cpus have the same number of siblings */
100         max_siblings = (cpuid_ecx(0x80000008) & 0xff) + 1;
101
102         /* Enable extended apic ids */
103         device_t dev_f0 = PCI_DEV(0, 0x18+id.nodeid, 0);
104         unsigned val = pci_read_config32(dev_f0, 0x68);
105         val |= (1 << 18) | (1 << 17);
106         pci_write_config32(dev_f0, 0x68, val);
107
108         /* Set the lapicid */
109         #if (CONFIG_ENABLE_APIC_EXT_ID == 1)
110                 unsigned initial_apicid = get_initial_apicid();
111                 #if CONFIG_LIFT_BSP_APIC_ID == 0
112                 if( initial_apicid != 0 ) // other than bsp
113                 #endif
114                 {
115                                 /* use initial apic id to lift it */
116                                 uint32_t dword = lapic_read(LAPIC_ID);
117                                 dword &= ~(0xff<<24);
118                                 dword |= (((initial_apicid + CONFIG_APIC_ID_OFFSET) & 0xff)<<24);
119
120                                 lapic_write(LAPIC_ID, dword);
121                 }
122
123                 #if CONFIG_LIFT_BSP_APIC_ID == 1
124                 bsp_apicid += CONFIG_APIC_ID_OFFSET;
125                 #endif
126
127         #endif
128
129
130         /* Remember the cpuid */
131         if (id.coreid == 0) {
132                 dev = PCI_DEV(0, 0x18 + id.nodeid, 2);
133                 pci_write_config32(dev, 0x9c, cpuid_eax(1));    
134         }
135         
136         /* Maybe call distinguish_cpu_resets only on the last core? */
137         distinguish_cpu_resets(id.nodeid);
138         if (!boot_cpu()) {
139                 stop_this_cpu();
140         }
141 }
142
143 static void k8_init_and_stop_secondaries(void)
144 {
145         /* This doesn't work with Cache As Ram because it messes with 
146            the MTRR state, which breaks the init detection.
147            do_k8_init_and_stop_secondaries should be usable by CAR code.
148         */
149
150         int init_detected;
151
152         init_detected = early_mtrr_init_detected();
153         amd_early_mtrr_init();
154
155         enable_lapic();
156         init_timer();
157         if (init_detected) {
158                 asm volatile ("jmp __cpu_reset");
159         }
160
161         do_k8_init_and_stop_secondaries();
162 }
163
164 #endif