Find matching settings for each CPUs FID, VID, and P-state registers and initialize...
[coreboot.git] / src / cpu / amd / model_10xxx / pstate.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2007 Advanced Micro Devices, Inc.
5  *
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.
9  *
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.
14  *
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
18  */
19
20 #include <console/console.h>
21 #include <cpu/x86/msr.h>
22 #include <cpu/amd/mtrr.h>
23 #include <device/device.h>
24 #include <device/pci.h>
25 #include <string.h>
26 #include <cpu/x86/msr.h>
27 #include <cpu/x86/pae.h>
28 #include <pc80/mc146818rtc.h>
29 #include <cpu/x86/lapic.h>
30
31 #include "../../../northbridge/amd/amdfam10/amdfam10.h"
32
33 #include <cpu/amd/model_10xxx_rev.h>
34 #include <cpu/cpu.h>
35 #include <cpu/x86/cache.h>
36 #include <cpu/x86/mtrr.h>
37 #include <cpu/x86/mem.h>
38
39 #include <cpu/amd/quadcore.h>
40
41 #include <cpu/amd/model_10xxx_msr.h>
42 #include <cpu/amd/amdfam10_sysconf.h>
43
44 extern device_t get_node_pci(u32 nodeid, u32 fn);
45
46 #include "fidvid_common.c"
47
48 #define PSTATES_DEBUG 0
49
50
51
52 static void inline dump_msr_pstates(u32 nodes)
53 {
54 #if PSTATES_DEBUG==1
55         int i, j;
56         for(j=0; j<5; j++) {
57                 printk_debug("P%d:", j);
58                 for(i=0;i<nodes;i++)  {
59                         printk_debug(" [%08x %08x] ", sysconf.msr_pstate[i*5+j].hi, sysconf.msr_pstate[i*5+j].lo);
60                 }
61                 printk_debug("\n");
62         }
63 #endif
64 }
65
66
67 static void inline dump_p(const char *p_c, u32 nodes, u32 *p)
68 {
69 #if PSTATES_DEBUG==1
70         int i, j;
71                 printk_debug(p_c);
72                 printk_debug("p:");
73                 for(i=0;i<nodes;i++)  {
74                         printk_debug(" %d ", p[i]);
75                 }
76                 printk_debug("\n");
77
78 #endif
79 }
80
81
82 //according the pstate and make it work conformed to mixed conf system
83 static u32 get_pwrvalue(u32 val)
84 {
85         u32 times;
86         switch((val>>8)&3) {
87         case 0: times = 1000; break;
88         case 1: times = 100;  break;
89         case 2: times = 10;   break;
90         default:
91                 //error
92                 times = 1;
93         }
94
95         return (val & 0xff) * times;
96
97 }
98
99
100 static u32 get_powerstep(u32 val)
101 {
102         u32 time;
103         if(val<4) {time = (4 - val)*100;}
104         else if(val<8) { time = (9+4-val)*10;}
105         else { time = (10+8-val) * 5; }
106
107         return time;
108
109 }
110
111
112 static u32 get_plllocktime(u32 val)
113 {
114         u32 time;
115         switch(val) {
116         case 0:
117         case 1:
118         case 2:
119         case 3:
120                 time = val+1; break;
121         case 4: time = 8; break;
122         case 5: time = 16; break;
123         default:
124                 //erro2
125                 time = 1;
126         }
127         return time;
128 }
129
130
131 static void disable_pstate(u32 nodes, u32 *p)
132 {
133         int i;
134
135         for(i=0;i<nodes; i++) {
136                 sysconf.msr_pstate[i*5+p[i]].hi &= ~(1<<(63-32));
137         }
138 }
139
140
141 static void match_pstate(u32 nodes, u32 *p)
142 {
143         int i;
144         u32 corecof_min, pwrvalue_max, pwrval_max;
145         u32 enable;
146         enable = (sysconf.msr_pstate[0*5+p[0]].hi >> 31);
147         if(!enable)  {
148                 disable_pstate(nodes, p);
149                 return;
150         }
151         corecof_min = ((sysconf.msr_pstate[0*5+p[0]].lo & 0x3f) + 0x10)>>((sysconf.msr_pstate[0*5+p[0]].lo>>6) & 7);
152         pwrval_max = sysconf.msr_pstate[0*5+p[0]].hi & 0x3ff;
153         pwrvalue_max = get_pwrvalue(pwrval_max);
154
155         for(i=1; i<nodes; i++) {
156                 enable = (sysconf.msr_pstate[0*5+p[i]].hi >> 31);
157                 if(!enable) {
158                         disable_pstate(nodes, p);
159                         return;
160                 }
161
162                 u32 coredid = ((sysconf.msr_pstate[i*5+p[i]].lo>>6) & 7);
163                 u32 corecof = ((sysconf.msr_pstate[i*5+p[i]].lo & 0x3f) + 0x10)>>coredid;
164                 if(corecof<corecof_min) corecof_min = corecof;
165                 u32 pwrval, pwrvalue;
166                 pwrval = sysconf.msr_pstate[i*5+p[i]].hi & 0x3ff;
167                 pwrvalue = get_pwrvalue(pwrval);
168                 if(pwrvalue>pwrvalue_max) {
169                         pwrvalue_max = pwrvalue;
170                         pwrval_max = pwrval;
171                 }
172         }
173
174         for(i=0; i<nodes; i++) {
175                 u32 coredid = ((sysconf.msr_pstate[i*5+p[i]].lo>>6) & 7);
176                 u32 corefid = (corecof_min<<coredid);
177                 while(corefid<0x10) {
178                         coredid++;
179                         corefid = (corecof_min<<coredid);
180                 }
181                 sysconf.msr_pstate[i*5+p[i]].lo &= ~(0x1ff);
182                 sysconf.msr_pstate[i*5+p[i]].lo |= (corefid - 0x10) | (coredid << 6);
183                 sysconf.msr_pstate[i*5+p[i]].hi &= ~(0x3ff);
184                 sysconf.msr_pstate[i*5+p[i]].hi |= pwrval_max;
185         }
186 }
187
188
189 static void match_pstates(u32 nodes, u32 *p, u32 *px)
190 {
191         int i;
192         int j;
193         u32 p_int[NODE_NUMS];
194
195         int jj=1;
196         u32 end = 0;
197         for(i=0;i<nodes; i++) {
198                 p_int[i] = px[i];
199         }
200         while(1){
201                 for(i=0;i<nodes; i++) {
202                         if(px[i]<=(p[i]+jj)) {
203                                 end = 1;
204                                 break;
205                         }
206                 }
207                 if(!end) {
208                         for(i=0; i<nodes; i++) {
209                                 p_int[i] = px[i] - jj;
210                         }
211                         match_pstate(nodes, p_int);
212                         dump_p("P int\n", nodes, p_int);
213                         jj++;
214                 }
215                 else {
216                         for(i=0;i<nodes; i++) {
217                                 for(j=p[i]+1; j<p_int[i]; j++) {
218                                         sysconf.msr_pstate[i*5+j].hi &= ~(1<<(63-32));
219                                 }
220                         }
221                         break;
222                 }
223         }
224 }
225
226
227 void prep_pstates_all(void)
228 {
229         device_t f3_dev[NODE_NUMS], f4_dev[NODE_NUMS];
230         u32 p[NODE_NUMS];
231         u32 p_htc[NODE_NUMS];
232         u32 p_lowest[NODE_NUMS];
233         u32 htc_cap = 1;
234         u32 lowest_htc_equal = 0;
235
236         u32 nodes = sysconf.nodes;
237         int i;
238         int j;
239         u32 val;
240         u32 nbdid;
241         u32 nbvid0;
242         u32 nbvid1;
243
244         for(i=0;i<nodes; i++) { // get the value from F4x1F0:E0 or we can get that msr in CAR stage...
245                 f3_dev[i] = get_node_pci(i, 3);
246                 f4_dev[i] = get_node_pci(i, 4);
247         }
248
249         for(i=0;i<nodes; i++) { // get the value from F4x1F0:E0 or we can get that msr in CAR stage...
250                 val = pci_read_config32(f4_dev[i], 0x1f4);
251                 nbvid0 = val & 0x3f;
252                 nbvid1 = (val>>7) & 0x3f;
253                 for(j=0; j<5; j++) {
254                         val = pci_read_config32(f4_dev[i], 0x1e0 + (j<<2));
255                         nbdid = ((val>>16) & 1);
256                         sysconf.msr_pstate[i*5+j].lo = (val & 0xffff)  | (nbdid<<22) | ((nbdid?nbvid1:nbvid0)<<25);
257                         sysconf.msr_pstate[i*5+j].hi = (((val>>17) & 0x3ff) << (32-32)) | (((val>>27) & 1)<<(63-32));
258                 }
259         }
260
261         dump_msr_pstates(nodes);
262
263         sysconf.needs_update_pstate_msrs = 0; // normal case for all sockets are installed same conf CPU
264
265         for(i=1; (i<nodes) && (!sysconf.needs_update_pstate_msrs); i++) {
266                 for(j=0; j<5; j++) {
267                         if((sysconf.msr_pstate[i*5+j].lo != sysconf.msr_pstate[0*5+j].lo) || (sysconf.msr_pstate[i*5+j].hi != sysconf.msr_pstate[0*5+j].hi)) {
268                                 sysconf.needs_update_pstate_msrs = 1;
269                                 break;
270                         }
271                 }
272         }
273
274         if(sysconf.needs_update_pstate_msrs) {
275
276                 // update msr_pstate for mixed conf
277
278                 //P0
279                 /* Match P0 cpu cof for all cpu cores to the lowest P0 cpu cof value in the coherent fabric, and match P0 power for all cpu cores to the highest P0 power value */
280                 for(i=0;i<nodes; i++) p[i] = 0;
281                 match_pstate(nodes, p);
282                 dump_p("P0\n", nodes, p);
283                  dump_msr_pstates(nodes);
284
285
286                 //p_htc
287                 for(i=0;i<nodes; i++) {
288                         val = pci_read_config32(f3_dev[i], 0xe8); //htc cap
289                         if(!(val & (1<<10))) {
290                                 htc_cap = 0;
291                                 break;
292                         }
293
294                         //HtcPstateLimit
295                         val = pci_read_config32(f3_dev[i], 0x64);
296                         p_htc[i] = (((val>>28) & 7));
297                         if(p_htc[i] == 0) {
298                                 val |= 1<<28;
299                                 pci_write_config32(f3_dev[i], 0x64, val);
300                                 val = pci_read_config32(f3_dev[i], 0x68); //stc
301                                 val &= ~(7<<28);
302                                 val |= (1<<28);
303                                 pci_write_config32(f3_dev[i], 0x68, val);
304
305                                 p_htc[i] = 1;
306                         }
307                 }
308                 if(htc_cap) {
309                         match_pstate(nodes, p_htc);
310
311                         dump_p("P_htc\n", nodes, p_htc);
312                         dump_msr_pstates(nodes);
313                 }
314
315                 //p_lowest
316                 for(i=0;i<nodes; i++) {
317                         p_lowest[i] = 0;
318                         for(j=1; j<5; j++) {
319                                 if(sysconf.msr_pstate[i*5+j].hi & (1<<(63-32))) {
320                                         p_lowest[i] = j;
321                                 }
322                         }
323                         // PstateMaxVal
324                         val = pci_read_config32(f3_dev[i], 0xdc);
325                         if(p_lowest[i]>((val>>8) & 7)) {
326                                 val &= ~(7<<8);
327                                 val |= (p_lowest[i])<<8;
328                                 pci_write_config32(f3_dev[i], 0xdc, val);
329                         }
330                         else {
331                                 p_lowest[i] = (val>>8) & 7;
332                         }
333                 }
334                 if(htc_cap) {
335                         for(i=0;i<nodes; i++) {
336                                 if(p_lowest[i]==p_htc[i]){
337                                         lowest_htc_equal = 1;
338                                         break;
339                                 }
340                         }
341                 }
342                 if(lowest_htc_equal) {
343                         for(i=0;i<nodes; i++) {
344                                 // PstateMaxVal
345                                 val = pci_read_config32(f3_dev[i], 0xdc);
346                                 val &= ~(7<<8);
347                                 val |= p_htc[i];
348                                 pci_write_config32(f3_dev[i], 0xdc, val);
349                                 for(j=p_htc[i]+1; j<5; j++) {
350                                         sysconf.msr_pstate[i*5+j].hi &= ~(1<<(63-32));
351                                 }
352                         }
353                 } else {
354                         match_pstate(nodes, p_lowest);
355                         for(i=0; i<nodes; i++) {
356                                 for(j=p_lowest[i]+1; j<5; j++) {
357                                       sysconf.msr_pstate[i*5+j].hi &= ~(1<<(63-32));
358                                 }
359                         }
360
361                 }
362
363                 dump_p("Px\n", nodes, p_lowest);
364                 dump_msr_pstates(nodes);
365
366
367                 if(htc_cap) {
368                         //p_up_int
369                         match_pstates(nodes, p, p_htc);
370
371                         dump_msr_pstates(nodes);
372
373                         //p_lower_int
374                         match_pstates(nodes, p_htc, p_lowest);
375                 } else {
376                         match_pstates(nodes, p, p_lowest);
377                 }
378
379                 dump_msr_pstates(nodes);
380
381         }
382
383         // fill data into p_state
384         for(i=0; i<nodes; i++) {
385                 sysconf.p_state_num = 0;
386                 u32 corefid_equal = 1;
387                 u32 corefid;
388                 corefid = (sysconf.msr_pstate[i*5+0].lo & 0x3f);
389                 for(j=1; j<5; j++) {
390                         msr_t *msr_pstate;
391                         msr_pstate = &(sysconf.msr_pstate[i*5+j]);
392                         if(!(msr_pstate->hi & (1<<(63-32)) )) continue;
393                         if((msr_pstate->lo & 0x3f) != corefid) {
394                                 corefid_equal = 0;
395                                 break;
396                         }
397                 }
398                 for(j=0; j<5; j++) {
399                         struct p_state_t *p_state;
400                         msr_t *msr_pstate;
401                         msr_pstate = &sysconf.msr_pstate[i*5+j];
402                         if(!(msr_pstate->hi & (1<<(63-32)) )) continue;
403                         p_state = &sysconf.p_state[i*5+sysconf.p_state_num];
404                         u32 coredid = ((msr_pstate->lo>>6) & 7);
405                         u32 corecof = ((msr_pstate->lo & 0x3f) + 0x10)>>coredid;
406                         p_state->corefreq = corecof;
407
408                         u32 pwrval, pwrvalue;
409                         pwrval = msr_pstate->hi & 0x3ff;
410                         pwrvalue = get_pwrvalue(pwrval);
411                         p_state->power = pwrvalue;
412
413                         u32 lat;
414                         val = pci_read_config32(f3_dev[i], 0xd4);
415                         lat = 15 * (get_powerstep((val>>24)& 0xf)+get_powerstep((val>>20)& 0xf)) /1000;
416                         if(!corefid_equal) {
417                                 val = pci_read_config32(f3_dev[i], 0xa0);
418                                 lat += get_plllocktime((val >> 11 ) & 7);
419                         }
420                         p_state->transition_lat = lat;
421                         p_state->busmaster_lat = lat;
422
423                         p_state->control = j;
424                         p_state->status = j;
425
426                         sysconf.p_state_num++;
427                 }
428                 // don't need look at other nodes
429                 if(!sysconf.p_state_num) break;
430         }
431 }
432
433
434 //it will update pstates info from ram into MSR
435 void init_pstates(device_t dev, u32 nodeid, u32 coreid)
436 {
437         int j;
438         msr_t msr;
439
440         if(sysconf.needs_update_pstate_msrs) {
441                 for(j=0; j < 5; j++) {
442                         wrmsr(0xC0010064 + j, sysconf.msr_pstate[nodeid * 5 + j]);
443                 }
444         }
445
446         /* Set TSC Freq Select: TSC increments at the rate of the core P-state 0 */
447         msr = rdmsr(0xC0010015);
448         msr.lo |= 1 << 24;
449         wrmsr(0xC0010015, msr);
450
451         // Enter the state P0
452         //FIXME I don't think that this works correctly. May depend on early fid/vid setup.
453         if(sysconf.p_state_num)
454                 set_core_nb_max_pstate_after_other_warm_reset(nodeid, coreid);
455
456 }