023292b96adbbb299c00c30a63fba6aead34822d
[coreboot.git] / src / cpu / amd / model_fxx / powernow_acpi.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2008 Advanced Micro Devices, Inc.
5  * Copyright (C) 2009 Rudolf Marek <r.marek@assembler.cz>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; version 2 of the License.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include <console/console.h>
22 #include <stdint.h>
23 #include <cpu/x86/msr.h>
24 #include <arch/acpigen.h>
25 #include <cpu/amd/model_fxx_powernow.h>
26 #include <device/pci.h>
27 #include <device/pci_ids.h>
28 #include <cpu/x86/msr.h>
29 #include <cpu/amd/mtrr.h>
30 #include <cpu/amd/amdk8_sysconf.h>
31 #include <arch/cpu.h>
32
33 static int write_pstates_for_core(u8 pstate_num, u16 *pstate_feq, u8 *pstate_vid,
34                                 u8 *pstate_fid, u32 *pstate_power, int coreID,
35                                 u32 pcontrol_blk, u8 plen, u8 onlyBSP, u32 control)
36 {
37         int lenp, lenpr, i;
38
39         if ((onlyBSP) && (coreID != 0)) {
40             plen = 0;
41             pcontrol_blk = 0;
42         }
43
44         lenpr = acpigen_write_processor(coreID, pcontrol_blk, plen);
45         lenpr += acpigen_write_empty_PCT();
46         lenpr += acpigen_write_name("_PSS");
47
48         /* add later to total sum */
49         lenp = acpigen_write_package(pstate_num);
50
51         for (i = 0;i < pstate_num;i++) {
52                 u32 status, c2;
53                 c2 = control | (pstate_vid[i] << 6) |
54                             pstate_fid[i];
55                 status =
56                             (pstate_vid[i] << 6) |
57                             pstate_fid[i];
58
59                 lenp += acpigen_write_PSS_package(pstate_feq[i],
60                                                 pstate_power[i],
61                                                 0x64,
62                                                 0x7,
63                                                 c2,
64                                                 status);
65         }
66         /* update the package  size */
67         acpigen_patch_len(lenp - 1);
68
69         lenpr += lenp;
70         lenpr += acpigen_write_PPC(pstate_num);
71         /* patch the whole Processor token length */
72         acpigen_patch_len(lenpr - 2);
73         return lenpr;
74 }
75
76 #if CONFIG_K8_REV_F_SUPPORT
77 /*
78 * Details about this algorithm , refert to BDKG 10.5.1
79 * Two parts are included, the another is the DSDT reconstruction process
80 */
81
82 static int pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
83 {
84         int len;
85         u8 processor_brand[49];
86         u32 *v, control;
87         struct cpuid_result cpuid1;
88
89         struct power_limit_encoding {
90                 u8 socket_type;
91                 u8 cmp_cap;
92                 u8 pwr_lmt;
93                 u32 power_limit;
94         };
95         u8 Max_fid, Max_vid, Start_fid, Start_vid, Min_fid, Min_vid;
96         u16 Max_feq;
97         u8 Pstate_fid[10];
98         u16 Pstate_feq[10];
99         u8 Pstate_vid[10];
100         u32 Pstate_power[10];
101         u32 Pstate_volt[10];
102         u8 PstateStep, PstateStep_coef;
103         u8 IntPstateSup;
104         u8 Pstate_num;
105         u16 Cur_feq;
106         u8 Cur_fid;
107         u8 cmp_cap, pwr_lmt;
108         u32 power_limit = 0;
109         u8 index;
110         msr_t msr;
111         u32 fid_multiplier;
112         static struct power_limit_encoding TDP[20] = {
113                 {0x11, 0x0, 0x8, 62},
114                 {0x11, 0x1, 0x8, 89},
115                 {0x11, 0x1, 0xa, 103},
116                 {0x11, 0x1, 0xc, 125},
117                 {0x11, 0x0, 0x2, 15},
118                 {0x11, 0x0, 0x4, 35},
119                 {0x11, 0x1, 0x2, 35},
120                 {0x11, 0x0, 0x5, 45},
121                 {0x11, 0x1, 0x7, 76},
122                 {0x11, 0x1, 0x6, 65},
123                 {0x11, 0x1, 0x8, 89},
124                 {0x11, 0x0, 0x1, 8},
125                 {0x11, 0x1, 0x1, 22},
126                 {0x12, 0x0, 0x6, 25},
127                 {0x12, 0x0, 0x1, 8},
128                 {0x12, 0x0, 0x2, 9},
129                 {0x12, 0x0, 0x4, 15},
130                 {0x12, 0x0, 0xc, 35},
131                 {0x12, 0x1, 0xc, 35},
132                 {0x12, 0x1, 0x4, 20}
133         };
134
135         /* Get the Processor Brand String using cpuid(0x8000000x) command x=2,3,4 */
136         cpuid1 = cpuid(0x80000002);
137         v = (u32 *) processor_brand;
138         v[0] = cpuid1.eax;
139         v[1] = cpuid1.ebx;
140         v[2] = cpuid1.ecx;
141         v[3] = cpuid1.edx;
142         cpuid1 = cpuid(0x80000003);
143         v[4] = cpuid1.eax;
144         v[5] = cpuid1.ebx;
145         v[6] = cpuid1.ecx;
146         v[7] = cpuid1.edx;
147         cpuid1 = cpuid(0x80000004);
148         v[8] = cpuid1.eax;
149         v[9] = cpuid1.ebx;
150         v[10] = cpuid1.ecx;
151         v[11] = cpuid1.edx;
152         processor_brand[48] = 0;
153         printk(BIOS_INFO, "processor_brand=%s\n", processor_brand);
154
155         /*
156          * Based on the CPU socket type,cmp_cap and pwr_lmt , get the power limit.
157          * socket_type : 0x10 SocketF; 0x11 AM2/ASB1 ; 0x12 S1G1
158          * cmp_cap : 0x0 SingleCore ; 0x1 DualCore
159          */
160         printk(BIOS_INFO, "Pstates Algorithm ...\n");
161         cmp_cap =
162             (pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xE8) &
163              0x3000) >> 12;
164         cpuid1 = cpuid(0x80000001);
165         pwr_lmt = ((cpuid1.ebx & 0x1C0) >> 5) | ((cpuid1.ebx & 0x4000) >> 14);
166         for (index = 0; index <= sizeof(TDP) / sizeof(TDP[0]); index++)
167                 if (TDP[index].socket_type == CONFIG_CPU_SOCKET_TYPE &&
168                     TDP[index].cmp_cap == cmp_cap &&
169                     TDP[index].pwr_lmt == pwr_lmt) {
170                         power_limit = TDP[index].power_limit;
171                 }
172
173         Pstate_num = 0;
174
175         /* See if the CPUID(0x80000007) returned EDX[2:1]==11b */
176         cpuid1 = cpuid(0x80000007);
177         if ((cpuid1.edx & 0x6) != 0x6) {
178                 printk(BIOS_INFO, "No valid set of P-states\n");
179                 goto write_pstates;
180         }
181
182         msr = rdmsr(0xc0010042);
183         Max_fid = (msr.lo & 0x3F0000) >> 16;
184         Start_fid = (msr.lo & 0x3F00) >> 8;
185         Max_vid = (msr.hi & 0x3F0000) >> 16;
186         Start_vid = (msr.hi & 0x3F00) >> 8;
187         PstateStep = (msr.hi & 0x1000000) >> 24;
188         IntPstateSup = (msr.hi & 0x20000000) >> 29;
189
190         /*
191          * The P1...P[Min+1] VID need PstateStep to calculate
192          * P[N] = P[N-1]VID + 2^PstateStep
193          * PstateStep_coef = 2^PstateStep
194          */
195         if (PstateStep == 0)
196                 PstateStep_coef = 1;
197         else
198                 PstateStep_coef = 2;
199
200         if (IntPstateSup == 0) {
201                 printk(BIOS_INFO, "No intermediate P-states are supported\n");
202                 goto write_pstates;
203         }
204
205         /* Get the multipier of the fid frequency */
206         /*
207          * Fid multiplier is always 100 revF and revG.
208          */
209         fid_multiplier = 100;
210
211         /*
212          * Formula1:    CPUFreq = FID * fid_multiplier + 800
213          * Formula2:       CPUVolt = 1550 - VID * 25 (mv)
214          * Formula3:       Power = (PwrLmt * P[N]Frequency*(P[N]Voltage^2))/(P[0]Frequency * P[0]Voltage^2))
215          */
216
217         /* Construct P0(P[Max]) state */
218         Max_feq = Max_fid * fid_multiplier + 800;
219         if (Max_fid == 0x2A && Max_vid != 0x0) {
220                 Min_fid = 0x2;
221                 Pstate_fid[0] = Start_fid + 0xA;        /* Start Frequency + 1GHz */
222                 Pstate_feq[0] = Pstate_fid[0] * fid_multiplier + 800;
223                 Min_vid = Start_vid;
224                 Pstate_vid[0] = Max_vid + 0x2;  /* Maximum Voltage - 50mV */
225                 Pstate_volt[0] = 1550 - Pstate_vid[0] * 25;
226                 Pstate_power[0] = power_limit * 1000;   /* mw */
227                 Pstate_num++;
228         } else {
229                 Min_fid = Start_fid;
230                 Pstate_fid[0] = Max_fid;
231                 Pstate_feq[0] = Max_feq;
232                 Min_vid = Start_vid;
233                 Pstate_vid[0] = Max_vid + 0x2;
234                 Pstate_volt[0] = 1550 - Pstate_vid[0] * 25;
235                 Pstate_power[0] = power_limit * 1000;   /* mw */
236                 Pstate_num++;
237         }
238
239         Cur_feq = Max_feq;
240         Cur_fid = Max_fid;
241         /* Construct P1 state */
242         if (((Max_fid & 0x1) != 0) && ((Max_fid - 0x1) >= (Min_fid + 0x8))) {   /* odd value */
243                 Pstate_fid[1] = Max_fid - 0x1;
244                 Pstate_feq[1] = Pstate_fid[1] * fid_multiplier + 800;
245                 Cur_fid = Pstate_fid[1];
246                 Cur_feq = Pstate_feq[1];
247                 if (((Pstate_vid[0] & 0x1) != 0) && ((Pstate_vid[0] - 0x1) < Min_vid)) {        /* odd value */
248                         Pstate_vid[1] = Pstate_vid[0] + 0x1;
249                         Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
250                         Pstate_power[1] =
251                             (unsigned long long)Pstate_power[0] *
252                             Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1] /
253                             (Pstate_feq[0] * Pstate_volt[0] * Pstate_volt[0]);
254                 }
255                 if (((Pstate_vid[0] & 0x1) == 0) && ((Pstate_vid[0] - 0x1) < Min_vid)) {        /* even value */
256                         Pstate_vid[1] = Pstate_vid[0] + PstateStep_coef;
257                         Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
258                         Pstate_power[1] =
259                             (unsigned long long)Pstate_power[0] *
260                             Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1] /
261                             (Pstate_feq[0] * Pstate_volt[0] * Pstate_volt[0]);
262                 }
263                 Pstate_num++;
264         }
265
266         if (((Max_fid & 0x1) == 0) && ((Max_fid - 0x2) >= (Min_fid + 0x8))) {   /* even value */
267                 Pstate_fid[1] = Max_fid - 0x2;
268                 Pstate_feq[1] = Pstate_fid[1] * fid_multiplier + 800;
269                 Cur_fid = Pstate_fid[1];
270                 Cur_feq = Pstate_feq[1];
271                 if (((Pstate_vid[0] & 0x1) != 0) && ((Pstate_vid[0] - 0x1) < Min_vid)) {        /* odd value */
272                         Pstate_vid[1] = Pstate_vid[0] + 0x1;
273                         Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
274                         Pstate_power[1] =
275                             (unsigned long long)Pstate_power[0] *
276                             Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1] /
277                             (Pstate_feq[0] * Pstate_volt[0] * Pstate_volt[0]);
278                 }
279                 if (((Pstate_vid[0] & 0x1) == 0) && ((Pstate_vid[0] - 0x1) < Min_vid)) {        /* even value */
280                         Pstate_vid[1] = Pstate_vid[0] + PstateStep_coef;
281                         Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
282                         Pstate_power[1] =
283                             (unsigned long long)Pstate_power[0] *
284                             Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1] /
285                             (Pstate_feq[0] * Pstate_volt[0] * Pstate_volt[0]);
286                 }
287
288                 Pstate_num++;
289         }
290
291         /* Construct P2...P[Min-1] state */
292         Cur_fid = Cur_fid - 0x2;
293         Cur_feq = Cur_fid * fid_multiplier + 800;
294         while (Cur_feq >= ((Min_fid * fid_multiplier) + 800) * 2) {
295                 Pstate_fid[Pstate_num] = Cur_fid;
296                 Pstate_feq[Pstate_num] =
297                     Pstate_fid[Pstate_num] * fid_multiplier + 800;
298                 Cur_fid = Cur_fid - 0x2;
299                 Cur_feq = Cur_fid * fid_multiplier + 800;
300                 if (Pstate_vid[Pstate_num - 1] >= Min_vid) {
301                         Pstate_vid[Pstate_num] = Pstate_vid[Pstate_num - 1];
302                         Pstate_volt[Pstate_num] = Pstate_volt[Pstate_num - 1];
303                         Pstate_power[Pstate_num] = Pstate_power[Pstate_num - 1];
304                 } else {
305                         Pstate_vid[Pstate_num] =
306                             Pstate_vid[Pstate_num - 1] + PstateStep_coef;
307                         Pstate_volt[Pstate_num] =
308                             1550 - Pstate_vid[Pstate_num] * 25;
309                         Pstate_power[Pstate_num] =
310                             (unsigned long long)Pstate_power[0] *
311                             Pstate_feq[Pstate_num] * Pstate_volt[Pstate_num] *
312                             Pstate_volt[Pstate_num] / (Pstate_feq[0] *
313                                                        Pstate_volt[0] *
314                                                        Pstate_volt[0]);
315                 }
316                 Pstate_num++;
317         }
318
319         /* Constuct P[Min] State */
320         if (Max_fid == 0x2A && Max_vid != 0x0) {
321                 Pstate_fid[Pstate_num] = 0x2;
322                 Pstate_feq[Pstate_num] =
323                     Pstate_fid[Pstate_num] * fid_multiplier + 800;
324                 Pstate_vid[Pstate_num] = Min_vid;
325                 Pstate_volt[Pstate_num] = 1550 - Pstate_vid[Pstate_num] * 25;
326                 Pstate_power[Pstate_num] =
327                     (unsigned long long)Pstate_power[0] *
328                     Pstate_feq[Pstate_num] * Pstate_volt[Pstate_num] *
329                     Pstate_volt[Pstate_num] / (Pstate_feq[0] * Pstate_volt[0] *
330                                                Pstate_volt[0]);
331                 Pstate_num++;
332         } else {
333                 Pstate_fid[Pstate_num] = Start_fid;
334                 Pstate_feq[Pstate_num] =
335                     Pstate_fid[Pstate_num] * fid_multiplier + 800;
336                 Pstate_vid[Pstate_num] = Min_vid;
337                 Pstate_volt[Pstate_num] = 1550 - Pstate_vid[Pstate_num] * 25;
338                 Pstate_power[Pstate_num] =
339                     (unsigned long long)Pstate_power[0] *
340                     Pstate_feq[Pstate_num] * Pstate_volt[Pstate_num] *
341                     Pstate_volt[Pstate_num] / (Pstate_feq[0] * Pstate_volt[0] *
342                                                Pstate_volt[0]);
343                 Pstate_num++;
344         }
345
346         /* Print Pstate freq,vid,volt,power */
347
348         for (index = 0; index < Pstate_num; index++) {
349                 printk(BIOS_INFO, "Pstate_freq[%d] = %dMHz\t", index,
350                             Pstate_feq[index]);
351                 printk(BIOS_INFO, "Pstate_vid[%d] = %d\t", index, Pstate_vid[index]);
352                 printk(BIOS_INFO, "Pstate_volt[%d] = %dmv\t", index,
353                             Pstate_volt[index]);
354                 printk(BIOS_INFO, "Pstate_power[%d] = %dmw\n", index,
355                             Pstate_power[index]);
356         }
357
358
359 write_pstates:
360
361         len = 0;
362
363         control = (0x3 << 30) | /* IRT */
364                   (0x2 << 28) | /* RVO */
365                   (0x1 << 27) | /* ExtType */
366                   (0x2 << 20) | /* PLL_LOCK_TIME */
367                   (0x0 << 18) | /* MVS */
368                   (0x5 << 11); /* VST */
369
370         for (index = 0; index < (cmp_cap + 1); index++) {
371                 len += write_pstates_for_core(Pstate_num, Pstate_feq, Pstate_vid,
372                                 Pstate_fid, Pstate_power, index,
373                                 pcontrol_blk, plen, onlyBSP, control);
374         }
375
376         return len;
377 }
378
379 #else
380
381
382 static uint8_t vid_to_reg(uint32_t vid)
383 {
384         return (1550 - vid) / 25;
385 }
386
387 static uint32_t vid_from_reg(uint8_t val)
388 {
389         return (val == 0x1f ? 0 : 1550 - val * 25);
390 }
391
392 static uint8_t freq_to_fid(uint32_t freq)
393 {
394         return (freq - 800) / 100;
395 }
396 /* Return a frequency in MHz, given an input fid */
397 static uint32_t fid_to_freq(uint32_t fid)
398 {
399         return 800 + (fid * 100);
400 }
401
402 #define MAXP 7
403
404 struct pstate {
405         uint16_t freqMhz; /* in MHz */
406         uint16_t voltage; /* in mV */
407         uint16_t tdp; /* in W * 10 */
408 };
409
410 struct cpuentry {
411         uint16_t modelnr; /* numeric model value, unused in code */
412         uint8_t brandID; /* CPUID 8000_0001h EBX [11:6] (BrandID) */
413         uint32_t cpuid; /* CPUID 8000_0001h EAX [31:0] (CPUID) */
414         uint8_t maxFID; /* FID/VID Status MaxFID Field */
415         uint8_t startFID; /* FID/VID Status StartFID Field */
416         uint16_t pwr:12; /* Thermal Design Power of Max P-State  *10 (fixed point) */
417         /* Other MAX P state are read from CPU, other P states in following table */
418         struct pstate pstates[MAXP];
419 };
420
421 struct cpuentry entr[] = {
422         /* rev E single core, check OSA152FAA5BK */
423         {152, 0xc, 0x20f51, 0x12, 0x12, 926,
424          {{2400, 1350, 900}, {2200, 1300, 766},
425           {2000, 1250, 651}, {1800, 1200, 522},
426           {1000, 1100, 320}}},
427         {252, 0x10, 0x20f51, 0x12, 0x12, 926,
428          {{2400, 1350, 900}, {2200, 1300, 766},
429           {2000, 1250, 651}, {1800, 1200, 522},
430           {1000, 1100, 320}}},
431         {852, 0x14, 0x20f51, 0x12, 0x12, 926,
432          {{2400, 1350, 900}, {2200, 1300, 766},
433           {2000, 1250, 651}, {1800, 1200, 522},
434           {1000, 1100, 320}}},
435         {254, 0x10, 0x20f51, 0x14, 0x14, 926,
436          {{2600, 1350, 902}, {2400, 1300, 770},
437           {2200, 1250, 657}, {2000, 1200, 559},
438           {1800, 1150, 476}, {1000, 1100, 361}}},
439         {854, 0x14, 0x20f51, 0x14, 0x14, 926,
440          {{2600, 1350, 902}, {2400, 1300, 770},
441           {2200, 1250, 657}, {2000, 1200, 559},
442           {1800, 1150, 476}, {1000, 1100, 361}}},
443         {242, 0x10, 0x20f51, 0x8, 0x8, 853,
444          {}},
445         {842, 0x10, 0x20f51, 0x8, 0x8, 853,
446          {}},
447         {244, 0x10, 0x20f51, 0xa, 0xa, 853,
448          {{1000, 1100, 378}}},
449         {844, 0x14, 0x20f51, 0xa, 0xa, 853,
450          {{1000, 1100, 378}}},
451         {246, 0x10, 0x20f51, 0xc, 0xc, 853,
452          {{1800, 1350, 853},
453          {1000, 1100, 378}}},
454         {846, 0x14, 0x20f51, 0xc, 0xc, 853,
455          {{1800, 1350, 853},
456          {1000, 1100, 378}}},
457         {242, 0x10, 0x20f51, 0x8, 0x8, 853,
458          {}},
459         {842, 0x14, 0x20f51, 0x8, 0x8, 853,
460          {}},
461         {244, 0x10, 0x20f51, 0xa, 0xa, 853,
462          {{1000, 1100, 378}}},
463         {844, 0x14, 0x20f51, 0xa, 0xa, 853,
464          {{1000, 1100, 378}}},
465         {246, 0x10, 0x20f51, 0xc, 0xc, 853,
466          {{1800, 1350, 827}, {1000, 1100, 366}}},
467         {846, 0x14, 0x20f51, 0xc, 0xc, 853,
468          {{1800, 1350, 827}, {1000, 1100, 366}}},
469         {248, 0x10, 0x20f51, 0xe, 0xe, 853,
470          {{2000, 1350, 827}, {1800, 1300, 700},
471           {1000, 1100, 366}}},
472         {848, 0x14, 0x20f51, 0xe, 0xe, 853,
473          {{2000, 1350, 827}, {1800, 1300, 700},
474           {1000, 1100, 366}}},
475         {250, 0x10, 0x20f51, 0x10, 0x10, 853,
476          {{2200, 1350, 853}, {2000, 1300, 827},
477           {1800, 1250, 702}, {1000, 1100, 301}}},
478         {850, 0x14, 0x20f51, 0x10, 0x10, 853,
479          {{2200, 1350, 853}, {2000, 1300, 827},
480           {1800, 1250, 702}, {1000, 1100, 301}}},
481 /* begin OSK246FAA5BL */
482         {246, 0x12, 0x20f51, 0xc, 0xc, 547,
483          {{1800, 1350, 461}, {1000, 1100, 223}}},
484         {846, 0x16, 0x20f51, 0xc, 0xc, 547,
485          {{1800, 1350, 461}, {1000, 1100, 223}}},
486         {148, 0xe, 0x20f51, 0xe, 0xe, 547,
487          {{2000, 1350, 521}, {1800, 1300, 459},
488           {1000, 1100, 211}}},
489         {248, 0x12, 0x20f51, 0xe, 0xe, 547,
490          {{2000, 1350, 521}, {1800, 1300, 459},
491           {1000, 1100, 211}}},
492         {848, 0x16, 0x20f51, 0xe, 0xe, 547,
493          {{2000, 1350, 521}, {1800, 1300, 459},
494           {1000, 1100, 211}}},
495         {250, 0x12, 0x20f51, 0x10, 0x10, 547,
496          {{2200, 1350, 521}, {2000, 1300, 440},
497           {1800, 1250, 379}, {1000, 1100, 199}}},
498         {850, 0x16, 0x20f51, 0x10, 0x10, 547,
499          {{2200, 1350, 521}, {2000, 1300, 440},
500           {1800, 1250, 379}, {1000, 1100, 199}}},
501         {144, 0xc, 0x20f71, 0xa, 0xa, 670,
502          {{1000, 1100, 296}}},
503         {148, 0xc, 0x20f71, 0xe, 0xe, 853,
504          {{2000, 1350, 830}, {1800, 1300, 704},
505          {1000, 1100, 296}}},
506         {152, 0xc, 0x20f71, 0x12, 0x12, 104,
507          {{2400, 1350, 1016}, {2200, 1300, 863},
508          {2000, 1250, 732}, {1800, 1200, 621},
509           {1000, 1100, 419}}},
510         {146, 0xc, 0x20f71, 0xc, 0xc, 670,
511          {{1800, 1350, 647}, {1000, 1100, 286}}},
512         {150, 0xc, 0x20f71, 0x10, 0x10, 853,
513         {{2200, 1350, 830}, {2000, 1300, 706},
514         {1800, 1250, 596}, {1000, 1100, 350}}},
515         {154, 0xc, 0x20f71, 0x14, 0x14, 1040,
516         {{2600, 1350, 1017}, {2400, 1300, 868},
517         {2200, 1250, 740}, {2000, 1200, 630},
518         {1800, 1150, 537}, {1000, 1100, 416}}},
519         /* rev E dualcore */
520         {165, 0x2c, 0x20f12, 0xa, 0xa, 950,
521          {{1000, 1100, 406}}},
522         {265, 0x30, 0x20f12, 0xa, 0xa, 950,
523          {{1000, 1100, 406}}},
524         {865, 0x34, 0x20f12, 0xa, 0xa, 950,
525          {{1000, 1100, 406}}},
526         {270, 0x30, 0x20f12, 0xc, 0xc, 950,
527          {{1800, 1300, 903}, {1000, 1100, 383}}},
528         {870, 0x34, 0x20f12, 0xc, 0xc, 950,
529          {{1800, 1300, 903}, {1000, 1100, 383}}},
530         {275, 0x30, 0x20f12, 0xe, 0xe, 950,
531          {{2000, 1300, 903}, {1800, 1250, 759},
532          {1000, 1100, 361}}},
533         {875, 0x34, 0x20f12, 0xe, 0xe, 950,
534          {{2000, 1300, 903}, {1800, 1250, 759},
535          {1000, 1100, 361}}},
536         {280, 0x30, 0x20f12, 0x10, 0x10, 926,
537          {{2400, 1350, 900}, {2200, 1300, 766},
538          {1800, 1200, 552}, {1000, 1100, 320}}},
539         {880, 0x34, 0x20f12, 0x10, 0x10, 926,
540          {{2400, 1350, 900}, {2200, 1300, 766},
541          {1800, 1200, 552}, {1000, 1100, 320}}},
542         {170, 0x2c, 0x20f32, 0xc, 0xc, 1100,
543          {{1800, 1300, 1056}, {1000, 1100, 514}}},
544         {175, 0x2c, 0x20f32, 0xe, 0xe, 1100,
545          {{2000, 1300, 1056}, {1800, 1250, 891},
546           {1000, 1100, 490}}},
547         {260, 0x32, 0x20f32, 0x8, 0x8, 550,
548          {}},
549         {860, 0x36, 0x20f32, 0x8, 0x8, 550,
550          {}},
551         {165, 0x2e, 0x20f32, 0xa, 0xa, 550,
552          {{1000, 1100, 365}}},
553         {265, 0x32, 0x20f32, 0xa, 0xa, 550,
554          {{1000, 1100, 365}}},
555         {865, 0x36, 0x20f32, 0xa, 0xa, 550,
556          {{1000, 1100, 365}}},
557         {270, 0x32, 0x20f12, 0xc, 0xc, 550,
558          {{1800, 1150, 520}, {1000, 1100, 335}}},
559         {870, 0x36, 0x20f12, 0xc, 0xc, 550,
560          {{1800, 1150, 520}, {1000, 1100, 335}}},
561         {180, 0x2c, 0x20f32, 0x10, 0x10, 1100,
562          {{2200, 1300, 1056}, {2000, 1250, 891},
563           {1800, 1200, 748}, {1000, 1100, 466}}},
564         {3000, 0x4, 0x10ff0, 0xa, 0xa, 670,
565          {{1000, 1100, 210}}},
566 };
567
568 static int pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
569 {
570
571         u8 cmp_cap;
572         struct cpuentry *data = NULL;
573         uint32_t control;
574         int i = 0, index, len = 0, Pstate_num = 0;
575         msr_t msr;
576         u8 Pstate_fid[10];
577         u16 Pstate_feq[10];
578         u8 Pstate_vid[10];
579         u32 Pstate_power[10];
580         u8 Max_fid, Start_fid, Start_vid, Max_vid;
581         struct cpuid_result cpuid1 = cpuid(0x80000001);
582
583         msr = rdmsr(0xc0010042);
584         Max_fid = (msr.lo & 0x3F0000) >> 16;
585         Max_vid = (msr.hi & 0x3F0000) >> 16;
586         Start_fid = (msr.lo & 0x3F00) >> 8;
587         Start_vid = (msr.hi & 0x3F00) >> 8;
588
589         cmp_cap =
590             (pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xE8) &
591              0x3000) >> 12;
592
593         for (i = 0; i < ARRAY_SIZE(entr); i++) {
594                 if ((entr[i].cpuid == cpuid1.eax)
595                     && (entr[i].startFID == Start_fid)
596                     && (entr[i].maxFID == Max_fid)
597                     && (entr[i].brandID == ((u8 )((cpuid1.ebx >> 6) & 0xff)))) {
598                         data = &entr[i];
599                         break;
600                 }
601         }
602
603         if (data == NULL) {
604                 printk(BIOS_WARNING, "Unknown CPU, please update the powernow_acpi.c\n");
605                 return 0;
606         }
607
608         /* IRT 80us, PLL_LOCK_TIME 2us, MVS 25mv, VST 100us */
609         control = (3 << 30) | (2 << 20) | (0 << 18) | (5 << 11) | (1 << 29);
610         len = 0;
611         Pstate_num = 0;
612
613         Pstate_fid[Pstate_num] = Max_fid;
614         Pstate_feq[Pstate_num] = fid_to_freq(Max_fid);
615         Pstate_vid[Pstate_num] = Max_vid;
616         Pstate_power[Pstate_num] = data->pwr * 100;
617         Pstate_num++;
618
619         do {
620                 Pstate_fid[Pstate_num] = freq_to_fid(data->pstates[Pstate_num - 1].freqMhz) & 0x3f;
621                 Pstate_feq[Pstate_num] = data->pstates[Pstate_num - 1].freqMhz;
622                 Pstate_vid[Pstate_num] = vid_to_reg(data->pstates[Pstate_num - 1].voltage);
623                 Pstate_power[Pstate_num] = data->pstates[Pstate_num - 1].tdp * 100;
624                 Pstate_num++;
625         } while ((Pstate_num < MAXP) && (data->pstates[Pstate_num - 1].freqMhz != 0));
626
627         for (i=0;i<Pstate_num;i++)
628                 printk(BIOS_DEBUG, "P#%d freq %d [MHz] voltage %d [mV] TDP %d [mW]\n", i,
629                        Pstate_feq[i],
630                        vid_from_reg(Pstate_vid[i]),
631                        Pstate_power[i]);
632
633         for (index = 0; index < (cmp_cap + 1); index++) {
634                 len += write_pstates_for_core(Pstate_num, Pstate_feq, Pstate_vid,
635                                 Pstate_fid, Pstate_power, index,
636                                 pcontrol_blk, plen, onlyBSP, control);
637         }
638
639         return len;
640 }
641
642 #endif
643
644
645 int amd_model_fxx_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
646 {
647         int lens;
648         char pscope[] = "\\_PR";
649
650         lens = acpigen_write_scope(pscope);
651         lens += pstates_algorithm(pcontrol_blk, plen, onlyBSP);
652         //minus opcode
653         acpigen_patch_len(lens - 1);
654         return lens;
655 }
656