Remove some warnings.
[coreboot.git] / src / cpu / amd / model_fxx / init_cpus.c
1 //it takes the CONFIG_ENABLE_APIC_EXT_ID and CONFIG_APIC_ID_OFFSET and CONFIG_LIFT_BSP_APIC_ID
2 #ifndef K8_SET_FIDVID
3         #if CONFIG_K8_REV_F_SUPPORT == 0
4                 #define K8_SET_FIDVID 0
5         #else
6                 // for rev F, need to set FID to max
7                 #define K8_SET_FIDVID 1
8         #endif
9         
10 #endif
11
12 #ifndef K8_SET_FIDVID_CORE0_ONLY
13         /* MSR FIDVID_CTL and FIDVID_STATUS are shared by cores, so may don't need to do twice*/
14         #define K8_SET_FIDVID_CORE0_ONLY 1
15 #endif
16
17 static inline void print_initcpu8 (const char *strval, unsigned val)
18 {
19 #if CONFIG_USE_PRINTK_IN_CAR
20         printk_debug("%s%02x\r\n", strval, val);
21 #else
22         print_debug(strval); print_debug_hex8(val); print_debug("\r\n");
23 #endif
24 }
25
26 static inline void print_initcpu8_nocr (const char *strval, unsigned val)
27 {
28 #if CONFIG_USE_PRINTK_IN_CAR
29         printk_debug("%s%02x", strval, val);
30 #else
31         print_debug(strval); print_debug_hex8(val);
32 #endif
33 }
34
35
36 static inline void print_initcpu16 (const char *strval, unsigned val)
37 {
38 #if CONFIG_USE_PRINTK_IN_CAR
39         printk_debug("%s%04x\r\n", strval, val);
40 #else
41         print_debug(strval); print_debug_hex16(val); print_debug("\r\n");
42 #endif
43 }
44
45 static inline void print_initcpu(const char *strval, unsigned val)
46 {
47 #if CONFIG_USE_PRINTK_IN_CAR
48         printk_debug("%s%08x\r\n", strval, val);
49 #else
50         print_debug(strval); print_debug_hex32(val); print_debug("\r\n");
51 #endif
52 }
53
54 typedef void (*process_ap_t)(unsigned apicid, void *gp);
55
56 //core_range = 0 : all cores
57 //core range = 1 : core 0 only
58 //core range = 2 : cores other than core0
59 static void for_each_ap(unsigned bsp_apicid, unsigned core_range, process_ap_t process_ap, void *gp)
60 {
61         // here assume the OS don't change our apicid
62         unsigned ap_apicid;
63
64         unsigned nodes;
65         unsigned siblings = 0;
66         unsigned disable_siblings;
67         unsigned e0_later_single_core;
68         unsigned nb_cfg_54;
69         int i,j;
70
71         /* get_nodes define in in_coherent_ht.c */
72         nodes = get_nodes();
73
74         disable_siblings = !CONFIG_LOGICAL_CPUS;
75 #if CONFIG_LOGICAL_CPUS == 1 && CONFIG_HAVE_OPTION_TABLE == 1
76         if(read_option(CMOS_VSTART_dual_core, CMOS_VLEN_dual_core, 0) != 0) { // 0 mean dual core
77                 disable_siblings = 1;
78         }
79 #endif
80
81         /* here I assume that all node are same stepping, otherwise we can use use nb_cfg_54 from bsp for all nodes */
82         nb_cfg_54 = read_nb_cfg_54();
83
84
85         for(i=0; i<nodes;i++) {
86                 e0_later_single_core = 0;
87                 j = ((pci_read_config32(PCI_DEV(0, 0x18+i, 3), 0xe8) >> 12) & 3);
88                 if(nb_cfg_54) {
89                        if(j == 0 ){ // if it is single core, we need to increase siblings for apic calculation 
90                        #if CONFIG_K8_REV_F_SUPPORT == 0
91                                e0_later_single_core = is_e0_later_in_bsp(i);  // single core
92                        #else
93                                e0_later_single_core = is_cpu_f0_in_bsp(i);  // We can read cpuid(1) from Func3
94                        #endif
95                        } 
96                        if(e0_later_single_core) {
97                                 j=1;
98                        }
99                 }
100                 siblings = j;
101
102                 unsigned jstart, jend;
103
104                 if(core_range == 2) {
105                         jstart = 1;
106                 }
107                 else {
108                         jstart = 0;
109                 }
110
111                 if(e0_later_single_core || disable_siblings || (core_range==1)) {
112                         jend = 0;
113                 } else {
114                         jend = siblings;
115                 }       
116                 
117         
118                 for(j=jstart; j<=jend; j++) {
119
120                         ap_apicid = i * (nb_cfg_54?(siblings+1):1) + j * (nb_cfg_54?1:8);
121
122                 #if (CONFIG_ENABLE_APIC_EXT_ID == 1)
123                         #if CONFIG_LIFT_BSP_APIC_ID == 0
124                         if( (i!=0) || (j!=0)) /* except bsp */
125                         #endif
126                                 ap_apicid += CONFIG_APIC_ID_OFFSET;
127                 #endif
128
129                         if(ap_apicid == bsp_apicid) continue;
130
131                         process_ap(ap_apicid, gp); 
132
133                 }
134         }
135 }
136
137
138 static inline int lapic_remote_read(int apicid, int reg, unsigned *pvalue)
139 {
140         int timeout;
141         unsigned status;
142         int result;
143         lapic_wait_icr_idle();
144         lapic_write(LAPIC_ICR2, SET_LAPIC_DEST_FIELD(apicid));
145         lapic_write(LAPIC_ICR, LAPIC_DM_REMRD | (reg >> 4));
146         timeout = 0;
147
148         do {
149                 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_BUSY;
150         } while (status == LAPIC_ICR_BUSY && timeout++ < 1000);
151
152         timeout = 0;
153         do {
154                 status = lapic_read(LAPIC_ICR) & LAPIC_ICR_RR_MASK;
155         } while (status == LAPIC_ICR_RR_INPROG && timeout++ < 1000);
156
157         result = -1;
158         if (status == LAPIC_ICR_RR_VALID) {
159                 *pvalue = lapic_read(LAPIC_RRR);
160                 result = 0;
161         }
162         return result;
163 }
164
165 #define LAPIC_MSG_REG 0x380
166
167
168 #if K8_SET_FIDVID == 1
169 static void init_fidvid_ap(unsigned bsp_apicid, unsigned apicid);
170 #endif
171
172 static inline __attribute__((always_inline)) void print_apicid_nodeid_coreid(unsigned apicid, struct node_core_id id, const char *str)
173 {
174         #if CONFIG_USE_PRINTK_IN_CAR
175                 printk_debug("%s --- {  APICID = %02x NODEID = %02x COREID = %02x} ---\r\n", str, apicid, id.nodeid, id.coreid);
176         #else
177                 print_debug(str);
178                 print_debug(" ---- {APICID = "); print_debug_hex8(apicid);
179                 print_debug(" NODEID = "), print_debug_hex8(id.nodeid); print_debug(" COREID = "), print_debug_hex8(id.coreid);
180                 print_debug("} --- \r\n");
181         #endif
182 }
183
184
185 static unsigned wait_cpu_state(unsigned apicid, unsigned state)
186 {
187         unsigned readback = 0;
188         unsigned timeout = 1;
189         int loop = 2000000;
190         while(--loop>0) {
191                 if(lapic_remote_read(apicid, LAPIC_MSG_REG, &readback)!=0) continue;
192                 if((readback & 0xff) == state) {
193                         timeout = 0;
194                         break; //target cpu is in stage started
195                 }
196         }
197         if(timeout) {
198                 if(readback) {
199                         timeout = readback;
200                 }
201         }
202
203         return timeout;
204 }
205 static void wait_ap_started(unsigned ap_apicid, void *gp )
206 {
207         unsigned timeout;
208         timeout = wait_cpu_state(ap_apicid, 0x33); // started
209         if(timeout) {
210                 print_initcpu8_nocr("*", ap_apicid);
211                 print_initcpu("*", timeout);
212         }
213         else {
214                 print_initcpu8_nocr(" ", ap_apicid);
215         }
216 }
217
218 static void wait_all_aps_started(unsigned bsp_apicid)
219 {
220         for_each_ap(bsp_apicid, 0 , wait_ap_started, (void *)0);
221 }
222
223 static void wait_all_other_cores_started(unsigned bsp_apicid) // all aps other than core0
224 {
225         print_debug("started ap apicid: ");
226         for_each_ap(bsp_apicid, 2 , wait_ap_started, (void *)0);
227         print_debug("\r\n");
228 }
229
230 static void allow_all_aps_stop(unsigned bsp_apicid)
231 {
232         lapic_write(LAPIC_MSG_REG, (bsp_apicid<<24) | 0x44); // allow aps to stop
233 }
234
235 static void STOP_CAR_AND_CPU(void)
236 {
237         disable_cache_as_ram(); // inline
238         stop_this_cpu(); // inline, it will stop all cores except node0/core0 the bsp ....
239 }
240
241 #ifndef CONFIG_MEM_TRAIN_SEQ
242 #define CONFIG_MEM_TRAIN_SEQ 0
243 #endif
244
245
246 #if CONFIG_MEM_TRAIN_SEQ == 1
247 static inline void train_ram_on_node(unsigned nodeid, unsigned coreid, struct sys_info *sysinfo, unsigned retcall); 
248 #endif
249
250 #if RAMINIT_SYSINFO == 1
251 static unsigned init_cpus(unsigned cpu_init_detectedx ,struct sys_info *sysinfo)
252 #else
253 static unsigned init_cpus(unsigned cpu_init_detectedx)
254 #endif
255 {
256                 unsigned bsp_apicid = 0;
257                 unsigned apicid;
258                 struct node_core_id id;
259
260                 /* 
261                  * already set early mtrr in cache_as_ram.inc
262                  */
263
264                 /* that is from initial apicid, we need nodeid and coreid later */
265                 id = get_node_core_id_x(); 
266
267
268                 /* NB_CFG MSR is shared between cores, so we need make sure core0 is done at first --- use wait_all_core0_started  */
269                 if(id.coreid == 0) {
270                         set_apicid_cpuid_lo(); /* only set it on core0 */
271                         #if CONFIG_ENABLE_APIC_EXT_ID == 1
272                         enable_apic_ext_id(id.nodeid);
273                         #endif
274                 }
275
276                 enable_lapic();
277 //              init_timer(); // We need TMICT to pass msg for FID/VID change
278
279         #if (CONFIG_ENABLE_APIC_EXT_ID == 1)
280                 unsigned initial_apicid = get_initial_apicid(); 
281                 #if CONFIG_LIFT_BSP_APIC_ID == 0
282                 if( initial_apicid != 0 ) // other than bsp
283                 #endif
284                 {
285                                 /* use initial apic id to lift it */
286                                 uint32_t dword = lapic_read(LAPIC_ID);
287                                 dword &= ~(0xff<<24);
288                                 dword |= (((initial_apicid + CONFIG_APIC_ID_OFFSET) & 0xff)<<24);
289
290                                 lapic_write(LAPIC_ID, dword);
291                 }
292
293                 #if CONFIG_LIFT_BSP_APIC_ID == 1
294                 bsp_apicid += CONFIG_APIC_ID_OFFSET;
295                 #endif
296
297         #endif
298
299                 /* get the apicid, it may be lifted already */
300                 apicid = lapicid();
301
302 #if 0 
303                 // show our apicid, nodeid, and coreid
304                 if( id.coreid==0 ) {
305                         if (id.nodeid!=0) //all core0 except bsp
306                                 print_apicid_nodeid_coreid(apicid, id, " core0: ");
307                 }
308         #if 0 
309                 else { //all core1
310                         print_apicid_nodeid_coreid(apicid, id, " core1: ");
311                 }
312         #endif
313
314 #endif
315
316                 if (cpu_init_detectedx) {
317                         print_apicid_nodeid_coreid(apicid, id, "\r\n\r\n\r\nINIT detected from ");
318                         print_debug("\r\nIssuing SOFT_RESET...\r\n");
319                         soft_reset();
320                 }
321
322                 if(id.coreid==0) {
323                         distinguish_cpu_resets(id.nodeid);
324         //              start_other_core(id.nodeid); // start second core in first cpu, only allowed for nb_cfg_54 is not set
325                 }
326
327                 //here don't need to wait 
328                 lapic_write(LAPIC_MSG_REG, (apicid<<24) | 0x33); // mark the cpu is started
329
330                 if(apicid != bsp_apicid) {
331                         unsigned timeout=1;
332                         unsigned loop = 100;
333         #if K8_SET_FIDVID == 1
334                 #if (CONFIG_LOGICAL_CPUS == 1) && (K8_SET_FIDVID_CORE0_ONLY == 1)
335                         if(id.coreid == 0 ) // only need set fid for core0
336                 #endif 
337                                 init_fidvid_ap(bsp_apicid, apicid);
338         #endif
339
340                        // We need to stop the CACHE as RAM for this CPU, really?
341                         while(timeout && (loop-->0)) {  
342                                 timeout = wait_cpu_state(bsp_apicid, 0x44);
343                         }
344                         if(timeout) {
345                                 print_initcpu8("while waiting for BSP signal to STOP, timeout in ap ", apicid);
346                         }
347                         lapic_write(LAPIC_MSG_REG, (apicid<<24) | 0x44); // bsp can not check it before stop_this_cpu
348                         set_init_ram_access();
349         #if CONFIG_MEM_TRAIN_SEQ == 1
350                         train_ram_on_node(id.nodeid, id.coreid, sysinfo,
351                                           (unsigned) STOP_CAR_AND_CPU);
352         #endif
353
354                         STOP_CAR_AND_CPU();
355                 } 
356
357                 return bsp_apicid;
358 }
359
360
361 static unsigned is_core0_started(unsigned nodeid)
362 {
363         uint32_t htic;
364         device_t device;
365         device = PCI_DEV(0, 0x18 + nodeid, 0);
366         htic = pci_read_config32(device, HT_INIT_CONTROL);
367         htic &= HTIC_INIT_Detect;
368         return htic;
369 }
370
371 static void wait_all_core0_started(void)
372 {
373         //When core0 is started, it will distingush_cpu_resets. So wait for that
374         unsigned i;
375         unsigned nodes = get_nodes();
376
377         print_debug("core0 started: ");
378         for(i=1;i<nodes;i++) { // skip bsp, because it is running on bsp
379                 while(!is_core0_started(i)) {}
380                 print_initcpu8_nocr(" ", i);
381         }
382         print_debug("\r\n");
383
384 }
385