22ade3a4fdcef21d0a5cc8922c423fd97de0a11f
[coreboot.git] / src / cpu / amd / model_fxx / fidvid.c
1 #if K8_SET_FIDVID == 1
2
3 #define K8_SET_FIDVID_DEBUG 0
4
5 #define K8_SET_FIDVID_ONE_BY_ONE 1
6
7 #define K8_SET_FIDVID_STORE_AP_APICID_AT_FIRST 1
8
9 #ifndef SB_VFSMAF
10 #define SB_VFSMAF 1
11 #endif
12
13 #define FX_SUPPORT 1
14
15 static inline void print_debug_fv(const char *str, unsigned val)
16 {
17 #if K8_SET_FIDVID_DEBUG == 1
18         #if CONFIG_USE_PRINTK_IN_CAR
19                 printk_debug("%s%x\r\n", str, val);
20         #else
21                 print_debug(str); print_debug_hex32(val); print_debug("\r\n");
22         #endif
23 #endif
24 }
25
26 static inline void print_debug_fv_8(const char *str, unsigned val)
27 {
28 #if K8_SET_FIDVID_DEBUG == 1
29         #if CONFIG_USE_PRINTK_IN_CAR
30                 printk_debug("%s%02x\r\n", str, val);
31         #else
32                 print_debug(str); print_debug_hex8(val); print_debug("\r\n");
33         #endif
34 #endif
35 }
36
37 static inline void print_debug_fv_64(const char *str, unsigned val, unsigned val2)
38 {
39 #if K8_SET_FIDVID_DEBUG == 1
40         #if CONFIG_USE_PRINTK_IN_CAR
41                 printk_debug("%s%x%x\r\n", str, val, val2);
42         #else
43                 print_debug(str); print_debug_hex32(val); print_debug_hex32(val2); print_debug("\r\n");
44         #endif
45 #endif
46 }
47
48
49 static void enable_fid_change(void)
50 {
51         uint32_t dword;
52         unsigned nodes;
53         int i;
54
55         nodes = ((pci_read_config32(PCI_DEV(0, 0x18, 0), 0x60) >> 4) & 7) + 1;
56
57         for (i = 0; i < nodes; i++) {
58                 dword = pci_read_config32(PCI_DEV(0, 0x18+i, 3), 0xd8);
59                 dword &= 0x8ff00000;
60                 dword |= (2 << 28) | (0x02710);
61                 pci_write_config32(PCI_DEV(0, 0x18+i, 3), 0xd8, dword);
62
63                 dword = 0x04e2a707;
64                 pci_write_config32(PCI_DEV(0, 0x18+i, 3), 0xd4, dword);
65
66                 /* disable the DRAM interface at first, it will be enabled
67                  * by raminit again */
68                 dword = pci_read_config32(PCI_DEV(0, 0x18+i, 2), 0x94);
69                 dword |= (1 << 14);
70                 pci_write_config32(PCI_DEV(0, 0x18+i, 2), 0x94, dword);
71
72                 dword = 0x23070700; /* enable FID/VID change */
73 //              dword = 0x00070000; /* enable FID/VID change */
74                 pci_write_config32(PCI_DEV(0, 0x18+i, 3), 0x80, dword);
75
76                 dword = 0x00132113;
77                 pci_write_config32(PCI_DEV(0, 0x18+i, 3), 0x84, dword);
78
79         }
80 }
81
82 #if K8_SET_FIDVID_ONE_BY_ONE == 0
83 static unsigned set_fidvid_without_init(unsigned fidvid)
84 {
85         msr_t msr;
86         uint32_t vid;
87         uint32_t fid;
88
89         fid = (fidvid >> 8) & 0x3f;
90         vid = (fidvid >> 16) & 0x3f;
91
92         /* set new FID/VID */
93         msr.hi = 1;
94         msr.lo = (vid<<8) | fid;
95         wrmsr(0xc0010041, msr);
96         return fidvid;
97 }
98 #endif
99
100 static unsigned set_fidvid(unsigned apicid, unsigned fidvid, int showmessage)
101 {
102         /* for (cur, new) there is one <1600MHz x8 to find out next_fid */
103         static const uint8_t next_fid_a[] = {
104         /*  x4  x5  x6  x7  x8  x9 x10 x11 x12 x13 x14 x15 */
105 /* x4 */    0,  9,  9,  8,  9,  9,  9,  9,  9,  9,  9,  9,
106 /* x5 */    9,  0, 11, 11,  9,  9, 10, 11, 11, 11, 11, 11,
107 /* x6 */   11, 11,  0, 13, 11, 11, 11, 11, 12, 13, 13, 13,
108 /* x7 */   13, 13, 13,  0, 13, 13, 13, 13, 13, 13, 14, 15,
109 /* x8 */    4,  9,  9,  9,  0,  9,  9,  9,  9,  9,  9,  9,
110 /* x9 */    4,  5, 10, 10,  8,  0,  0,  0,  0,  0,  0,  0,
111 /*x10 */    9,  5, 11, 11,  9,  0,  0,  0,  0,  0,  0,  0,
112 /*x11 */   10,  5,  6, 12, 10,  0,  0,  0,  0,  0,  0,  0,
113 /*x12 */   11, 11,  6, 13, 11,  0,  0,  0,  0,  0,  0,  0,
114 /*x13 */   12, 12,  6,  7, 12,  0,  0,  0,  0,  0,  0,  0,
115 /*x14 */   13, 13, 13,  7, 13,  0,  0,  0,  0,  0,  0,  0,
116 /*x15 */   14, 14, 14,  7, 14,  0,  0,  0,  0,  0,  0,  0,
117 /* 0:x4, 2:x5....BASE=4, MIN=4, MAX=25, INC=2 result = (xX-BASE)*INC */
118         };
119
120         msr_t msr;
121         uint32_t vid;
122         uint32_t fid;
123         uint32_t vid_max;
124         uint32_t fid_max;
125         uint32_t vid_cur;
126         uint32_t fid_cur;
127         unsigned apicidx;
128
129         int steps;
130         int loop;
131
132         apicidx = lapicid();
133
134         if (apicid != apicidx) {
135 #if CONFIG_USE_PRINTK_IN_CAR
136                 printk_err("wrong apicid, we want change %x, but it is %x\r\n", apicid, apicidx);
137 #else
138                 print_err("wrong apicid, we want change "); print_err_hex8(apicid); print_err(" but it is "); print_err_hex8(apicidx); print_err("\r\n");
139 #endif
140                 return fidvid;
141         }
142
143         fid = (fidvid >> 8) & 0x3f;
144         vid = (fidvid >> 16) & 0x3f;
145
146         msr = rdmsr(0xc0010042);
147
148         vid_cur = msr.hi & 0x3f;
149         fid_cur = msr.lo & 0x3f;
150
151         if ((vid_cur==vid) && (fid_cur==fid))
152                 return fidvid;
153
154         vid_max = (msr.hi>>(48-32)) & 0x3f;
155         fid_max = ((msr.lo>>16) & 0x3f); /* max fid */
156 #if FX_SUPPORT
157         if (fid_max>=((25-4)*2)) { /* FX max fid is 5G */
158                 fid_max = ((msr.lo >> 8) & 0x3f) + 5 * 2; /* max FID is min fid + 1G */
159                 if (fid_max >= ((25-4) * 2)) {
160                         fid_max = (10-4) * 2; /* hard set to 2G */
161                 }
162         }
163 #endif
164
165         /* set vid to max */
166         msr.hi = 1;
167         msr.lo = (vid_max << 8) | (fid_cur);
168 #if SB_VFSMAF == 1
169         msr.lo |= (1<<16); /* init changes */
170 #endif
171         wrmsr(0xc0010041, msr);
172 #if SB_VFSMAF == 0
173         ldtstop_sb();
174 #endif
175
176
177         for (loop=0;loop<100000;loop++){
178                 msr = rdmsr(0xc0010042);
179                 if (!(msr.lo & (1<<31)))
180                         break;
181         }
182         vid_cur = msr.hi & 0x3f;
183
184         steps = 8; //??
185         while ((fid_cur != fid) && (steps-- > 0)) {
186                 uint32_t fid_temp;
187                 if ((fid_cur > (8-4)*2) && (fid> (8-4)*2)) {
188                         if (fid_cur<fid) {
189                                 fid_temp = fid_cur + 2;
190                                 } else {
191                                         fid_temp = fid_cur - 2;
192                                 }
193                 } else {
194                         /* there is one < 8, So we need to lookup the table to
195                          * find the fid_cur */
196                         int temp;
197                         temp = next_fid_a[(fid_cur/2)*12+(fid/2)];
198                         if (temp <= 0) break;
199                         fid_temp = (temp-4) * 2;
200                 }
201                 if (fid_temp > fid_max)
202                         break;
203
204                 fid_cur = fid_temp;
205
206                 /* set target fid */
207                 msr.hi = (100000/5);
208                 msr.lo = (vid_cur << 8) | fid_cur;
209 #if SB_VFSMAF == 1
210                 msr.lo |= (1 << 16); /* init changes */
211 #endif
212                 wrmsr(0xc0010041, msr);
213 #if SB_VFSMAF == 0
214                 ldtstop_sb();
215 #endif
216
217
218 #if K8_SET_FIDVID_DEBUG == 1
219                 if (showmessage) {
220                         print_debug_fv_8("\tapicid in set_fidvid = ", apicid);
221                         print_debug_fv_64("ctrl msr fid, vid ", msr.hi, msr.lo);
222                 }
223 #endif
224
225                 for (loop = 0; loop < 100000; loop++){
226                         msr = rdmsr(0xc0010042);
227                         if (!(msr.lo & (1 << 31)))
228                                 break;
229                 }
230                 fid_cur = msr.lo & 0x3f;
231
232 #if K8_SET_FIDVID_DEBUG == 1
233                 if (showmessage)        {
234                          print_debug_fv_64("status msr fid, vid ", msr.hi, msr.lo);
235                 }
236 #endif
237         }
238
239         /* set vid to final */
240         msr.hi = 1;
241         msr.lo = (vid << 8) | (fid_cur);
242 #if SB_VFSMAF == 1
243         msr.lo |= (1 << 16); // init changes
244 #endif
245         wrmsr(0xc0010041, msr);
246 #if SB_VFSMAF == 0
247         ldtstop_sb();
248 #endif
249
250         for (loop = 0; loop < 100000; loop++){
251                 msr = rdmsr(0xc0010042);
252                 if (!(msr.lo & (1 << 31)))
253                         break;
254         }
255         vid_cur = msr.hi & 0x3f;
256
257         fidvid = (vid_cur << 16) | (fid_cur << 8);
258
259         if (showmessage) {
260                 if (vid!=vid_cur) {
261                         print_err("set vid failed for apicid ="); print_err_hex8(apicidx);  print_err("\r\n");
262                 }
263                 if (fid!=fid_cur) {
264                         print_err("set fid failed for apicid ="); print_err_hex8(apicidx); print_err("\r\n");
265                 }
266         }
267
268         return fidvid;
269
270 }
271
272 static void init_fidvid_ap(unsigned bsp_apicid, unsigned apicid)
273 {
274         uint32_t send;
275         uint32_t readback = 0;
276         unsigned timeout = 1;
277         msr_t msr;
278         uint32_t vid_cur;
279         uint32_t fid_cur;
280         uint32_t fid_max;
281         int loop;
282
283         msr =   rdmsr(0xc0010042);
284         fid_max = ((msr.lo >> 16) & 0x3f); /* max fid */
285 #if FX_SUPPORT
286         if (fid_max >= ((25-4) * 2)) { /* FX max fid is 5G */
287                 fid_max = ((msr.lo>>8) & 0x3f) + 5*2; /* maxFID = minFID + 1G */
288                 if (fid_max >= ((25-4) * 2)) {
289                         fid_max = (10-4) * 2; // hard set to 2G
290                 }
291         }
292 #endif
293         send = fid_max<<8;
294
295         send |= ((msr.hi >> (48-32)) & 0x3f) << 16; /* max vid */
296         send |= (apicid << 24); /* ap apicid */
297
298 #if K8_SET_FIDVID_ONE_BY_ONE == 1
299         vid_cur = msr.hi & 0x3f;
300         fid_cur = msr.lo & 0x3f;
301
302         /* set to current */ 
303         msr.hi = 1;
304         msr.lo = (vid_cur << 8) | (fid_cur);
305         wrmsr(0xc0010041, msr);
306 #endif
307
308         timeout = wait_cpu_state(bsp_apicid, 1);
309         if (timeout) {
310                 print_initcpu8("fidvid_ap_stage1: time out while reading from BSP on ", apicid);
311         }
312         /* send signal to BSP about this AP max fid and vid */
313         /* AP at state 1 that sent our fid and vid */
314         lapic_write(LAPIC_MSG_REG, send | 1);
315
316 //      wait_cpu_state(bsp_apicid, 2); /* don't need we can use apicid directly */
317         loop = 1000000;
318         while (--loop > 0) {
319                 /* remote read BSP signal that include vid/fid that need to set */
320                 if (lapic_remote_read(bsp_apicid, LAPIC_MSG_REG, &readback)!=0)
321                         continue;
322                 if (((readback >> 24) & 0xff) == apicid)
323                         break; /* it is this cpu turn */
324         }
325
326         if (loop > 0) {
327         #if K8_SET_FIDVID_ONE_BY_ONE == 1
328                         readback = set_fidvid(apicid, readback & 0xffff00, 1); // this AP
329         #else
330                 readback = set_fidvid_without_init(readback & 0xffff00); // this AP
331         #endif
332                 /* send signal to BSP that this AP fid/vid is set */
333                 /* allow to change state2 is together with apicid */
334                 /* AP at state that We set the requested fid/vid */
335                 send = (apicid<<24) | (readback & 0x00ffff00); 
336         } else {
337                 print_initcpu8("fidvid_ap_stage2: time out while reading from BSP on ", apicid);
338         }
339
340                 lapic_write(LAPIC_MSG_REG, send | 2);
341
342         timeout = wait_cpu_state(bsp_apicid, 3);
343         if (timeout) {
344                 print_initcpu8("fidvid_ap_stage3: time out while reading from BSP on ", apicid);
345         }
346 }
347
348 static unsigned calc_common_fidvid(unsigned fidvid, unsigned fidvidx)
349 {
350         /* FIXME: need to check the change path to verify if it is reachable 
351          * when common fid is small than 1.6G */
352         if ((fidvid & 0xff00) <= (fidvidx & 0xff00)) {
353                 return fidvid;
354         }
355         else {
356                 return fidvidx;
357         }
358 }
359
360 struct fidvid_st {
361         unsigned common_fidvid;
362 };
363
364 static void init_fidvid_bsp_stage1(unsigned ap_apicid, void *gp )
365 {
366         unsigned readback = 0;
367         unsigned timeout = 1;
368
369         struct fidvid_st *fvp = gp;
370         int loop;
371
372         print_debug_fv("state 1: ap_apicid=", ap_apicid);
373
374         loop = 1000000;
375         while (--loop > 0) {
376                 if (lapic_remote_read(ap_apicid, LAPIC_MSG_REG, &readback)!=0)
377                         continue;
378                 if ((readback & 0xff) == 1) {
379                         timeout = 0;
380                         break; /* target ap is in stage 1 */
381                 }
382         }
383         if (timeout) {
384                 print_initcpu8("fidvid_bsp_stage1: time out while reading from ap ", ap_apicid);
385                 return;
386         }
387
388         print_debug_fv("\treadback=", readback);
389
390         fvp->common_fidvid = calc_common_fidvid(fvp->common_fidvid, readback & 0xffff00);
391
392         print_debug_fv("\tcommon_fidvid=", fvp->common_fidvid);
393 }
394
395 static void init_fidvid_bsp_stage2(unsigned ap_apicid, void *gp)
396 {
397         unsigned readback = 0;
398         unsigned timeout = 1;
399
400         struct fidvid_st *fvp = gp;
401         int loop;
402
403         print_debug_fv("state 2: ap_apicid=", ap_apicid);
404
405         /* all set to state2 */
406         lapic_write(LAPIC_MSG_REG, fvp->common_fidvid | (ap_apicid<<24) | 2);
407
408         loop = 1000000;
409         while (--loop > 0) {
410                 if (lapic_remote_read(ap_apicid, LAPIC_MSG_REG, &readback)!=0)
411                         continue;
412                 if ((readback & 0xff) == 2) {
413                         timeout = 0;
414                         break; /* target ap is stage 2, it's FID has beed set */
415                 }
416         }
417
418         if (timeout) {
419                 print_initcpu8("fidvid_bsp_stage2: time out while reading from ap ", ap_apicid);
420                 return;
421         }
422
423         print_debug_fv("\treadback=", readback);
424 }
425
426 #if K8_SET_FIDVID_STORE_AP_APICID_AT_FIRST == 1
427 struct ap_apicid_st {
428         unsigned num;
429         unsigned apicid[16]; /* 8 way dual core need 16 */
430         /* FIXME: 32 node quad core, may need 128 */
431 };
432
433 static void store_ap_apicid(unsigned ap_apicid, void *gp)
434 {
435         struct ap_apicid_st *p = gp;
436
437         p->apicid[p->num++] = ap_apicid;
438
439 }
440 #endif
441
442 static void init_fidvid_bsp(unsigned bsp_apicid)
443 {
444         uint32_t vid_max;
445         uint32_t fid_max;
446
447         struct fidvid_st fv;
448
449 #if K8_SET_FIDVID_STORE_AP_APICID_AT_FIRST == 1
450         struct ap_apicid_st ap_apicidx;
451         unsigned i;
452 #endif
453
454         msr_t msr;
455         msr =   rdmsr(0xc0010042);
456         fid_max = ((msr.lo >> 16) & 0x3f); /* max fid */
457 #if FX_SUPPORT == 1
458         if (fid_max >= ((25-4) * 2)) { /* FX max fid is 5G */
459                 fid_max = ((msr.lo >> 8) & 0x3f) + 5*2; /* maxFID = minFID + 1G */
460                 if (fid_max >= ((25-4) * 2)) {
461                         fid_max = (10-4) * 2; /* hard set to 2G */
462                 }
463         }
464 #endif
465         vid_max = ((msr.hi>>(48-32)) & 0x3f); //max vid
466         fv.common_fidvid = (fid_max << 8)|(vid_max << 16);
467
468
469         /* for all APs (We know the APIC ID of all APs even the APIC ID is lifted)
470          * remote read from AP about max fid/vid */
471
472         /* let all ap trains to state 1 */
473         lapic_write(LAPIC_MSG_REG,  (bsp_apicid << 24) | 1);
474
475         /* calculate the common max fid/vid that could be used for 
476          * all APs and BSP */
477 #if K8_SET_FIDVID_STORE_AP_APICID_AT_FIRST == 1
478         ap_apicidx.num = 0;
479
480         for_each_ap(bsp_apicid, K8_SET_FIDVID_CORE0_ONLY, store_ap_apicid, &ap_apicidx);
481
482         for (i = 0; i < ap_apicidx.num; i++) {
483                 init_fidvid_bsp_stage1(ap_apicidx.apicid[i], &fv);
484         }
485 #else
486         for_each_ap(bsp_apicid, K8_SET_FIDVID_CORE0_ONLY, init_fidvid_bsp_stage1, &fv);
487 #endif
488
489
490 #if 0
491         unsigned fid, vid;
492         /* Can we use max only? So we can only set fid in one around,
493          * otherwise we need to set that to max after raminit */
494         /* set fid vid to DQS training required */
495         fid = (fv.common_fidvid >> 8)  & 0x3f;
496         vid = (fv.common_fidvid >> 16) & 0x3f;
497
498         if (fid > (10-4) * 2) {
499                 fid = (10-4) * 2; // x10
500         }
501
502         if (vid >= 0x1f) {
503                 vid += 4; /* unit is 12.5mV */
504         } else {
505                 vid += 2; /* unit is 25mV */
506         }
507
508         fv.common_fidvid = (fid<<8) | (vid<<16);
509
510         print_debug_fv("common_fidvid=", fv.common_fidvid);
511
512 #endif
513
514 #if K8_SET_FIDVID_ONE_BY_ONE == 1
515         /* set BSP fid and vid */
516         print_debug_fv("bsp apicid=", bsp_apicid);
517         fv.common_fidvid = set_fidvid(bsp_apicid, fv.common_fidvid, 1);
518         print_debug_fv("common_fidvid=", fv.common_fidvid);
519 #endif
520
521         /* For all APs ( We know the APIC ID of all AP even the APIC ID is lifted)
522          *  send signal to the AP it could change it's fid/vid */
523         /* remote read singnal from AP that AP is done */
524
525         fv.common_fidvid &= 0xffff00;
526
527         /* set state 2 allow is in init_fidvid_bsp_stage2 */
528 #if K8_SET_FIDVID_STORE_AP_APICID_AT_FIRST == 1
529         for (i = 0; i < ap_apicidx.num; i++) {
530                 init_fidvid_bsp_stage2(ap_apicidx.apicid[i], &fv);
531         }
532 #else
533         for_each_ap(bsp_apicid, K8_SET_FIDVID_CORE0_ONLY, init_fidvid_bsp_stage2, &fv);
534 #endif
535
536 #if K8_SET_FIDVID_ONE_BY_ONE == 0
537         /* set BSP fid and vid */
538         print_debug_fv("bsp apicid=", bsp_apicid);
539         fv.common_fidvid = set_fidvid(bsp_apicid, fv.common_fidvid, 1);
540         print_debug_fv("common_fidvid=", fv.common_fidvid);
541
542 #endif
543
544         /* clear the state */
545         lapic_write(LAPIC_MSG_REG, fv.common_fidvid | (bsp_apicid << 24) | 3);
546
547         /* here wait a while, so last ap could read pack, and stop it, don't
548          * call init_timer too early or just don't use init_timer */
549
550 }
551
552 #endif