Bellongs to r3946
[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 v2 as published by
9  * the Free Software Foundation.
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)  {
36         int lenp, lenpr, i;
37
38         if ((onlyBSP) && (coreID != 0)) {
39             plen = 0;
40             pcontrol_blk = 0;
41         }
42
43         lenpr = acpigen_write_processor(coreID, pcontrol_blk, plen);
44         lenpr += acpigen_write_empty_PCT();
45         lenpr += acpigen_write_name("_PSS");
46
47         /* add later to total sum */
48         lenp = acpigen_write_package(pstate_num);
49
50         for (i = 0;i < pstate_num;i++) {
51                 u32 control, status;
52
53                 control =
54                             (0x3 << 30) | /* IRT */
55                             (0x2 << 28) | /* RVO */
56                             (0x1 << 27) | /* ExtType */
57                             (0x2 << 20) | /* PLL_LOCK_TIME */
58                             (0x0 << 18) | /* MVS */
59                             (0x5 << 11) | /* VST */
60                             (pstate_vid[i] << 6) |
61                             pstate_fid[i];
62                 status =
63                             (pstate_vid[i] << 6) |
64                             pstate_fid[i];
65
66                 lenp += acpigen_write_PSS_package(pstate_feq[i],
67                                                 pstate_power[i],
68                                                 0x64,
69                                                 0x7,
70                                                 control,
71                                                 status);
72         }
73         /* update the package  size */
74         acpigen_patch_len(lenp - 1);
75
76         lenpr += lenp;
77         lenpr += acpigen_write_PPC(pstate_num);
78         /* patch the whole Processor token length */
79         acpigen_patch_len(lenpr - 2);
80         return lenpr;
81 }
82 /*
83 * Details about this algorithm , refert to BDKG 10.5.1
84 * Two parts are included, the another is the DSDT reconstruction process
85 */
86
87 static int pstates_algorithm(u32 pcontrol_blk, u8 plen, u8 onlyBSP)
88 {
89         int len;
90         u8 processor_brand[49];
91         u32 *v;
92         struct cpuid_result cpuid1;
93
94         struct power_limit_encoding {
95                 u8 socket_type;
96                 u8 cmp_cap;
97                 u8 pwr_lmt;
98                 u32 power_limit;
99         };
100         u8 Max_fid, Max_vid, Start_fid, Start_vid, Min_fid, Min_vid;
101         u16 Max_feq;
102         u8 Pstate_fid[10];
103         u16 Pstate_feq[10];
104         u8 Pstate_vid[10];
105         u32 Pstate_power[10];
106         u32 Pstate_volt[10];
107         u8 PstateStep, PstateStep_coef;
108         u8 IntPstateSup;
109         u8 Pstate_num;
110         u16 Cur_feq;
111         u8 Cur_fid;
112         u8 cmp_cap, pwr_lmt;
113         u32 power_limit = 0;
114         u8 index;
115         msr_t msr;
116         u32 fid_multiplier;
117         static struct power_limit_encoding TDP[20] = {
118                 {0x11, 0x0, 0x8, 62},
119                 {0x11, 0x1, 0x8, 89},
120                 {0x11, 0x1, 0xa, 103},
121                 {0x11, 0x1, 0xc, 125},
122                 {0x11, 0x0, 0x2, 15},
123                 {0x11, 0x0, 0x4, 35},
124                 {0x11, 0x1, 0x2, 35},
125                 {0x11, 0x0, 0x5, 45},
126                 {0x11, 0x1, 0x7, 76},
127                 {0x11, 0x1, 0x6, 65},
128                 {0x11, 0x1, 0x8, 89},
129                 {0x11, 0x0, 0x1, 8},
130                 {0x11, 0x1, 0x1, 22},
131                 {0x12, 0x0, 0x6, 25},
132                 {0x12, 0x0, 0x1, 8},
133                 {0x12, 0x0, 0x2, 9},
134                 {0x12, 0x0, 0x4, 15},
135                 {0x12, 0x0, 0xc, 35},
136                 {0x12, 0x1, 0xc, 35},
137                 {0x12, 0x1, 0x4, 20}
138         };
139
140         /* Get the Processor Brand String using cpuid(0x8000000x) command x=2,3,4 */
141         cpuid1 = cpuid(0x80000002);
142         v = (u32 *) processor_brand;
143         v[0] = cpuid1.eax;
144         v[1] = cpuid1.ebx;
145         v[2] = cpuid1.ecx;
146         v[3] = cpuid1.edx;
147         cpuid1 = cpuid(0x80000003);
148         v[4] = cpuid1.eax;
149         v[5] = cpuid1.ebx;
150         v[6] = cpuid1.ecx;
151         v[7] = cpuid1.edx;
152         cpuid1 = cpuid(0x80000004);
153         v[8] = cpuid1.eax;
154         v[9] = cpuid1.ebx;
155         v[10] = cpuid1.ecx;
156         v[11] = cpuid1.edx;
157         processor_brand[48] = 0;
158         printk_info("processor_brand=%s\n", processor_brand);
159
160         /*
161          * Based on the CPU socket type,cmp_cap and pwr_lmt , get the power limit.
162          * socket_type : 0x10 SocketF; 0x11 AM2/ASB1 ; 0x12 S1G1
163          * cmp_cap : 0x0 SingleCore ; 0x1 DualCore
164          */
165         printk_info("Pstates Algorithm ...\n");
166         cmp_cap =
167             (pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x18, 3)), 0xE8) &
168              0x3000) >> 12;
169         cpuid1 = cpuid(0x80000001);
170         pwr_lmt = ((cpuid1.ebx & 0x1C0) >> 5) | ((cpuid1.ebx & 0x4000) >> 14);
171         for (index = 0; index <= sizeof(TDP) / sizeof(TDP[0]); index++)
172                 if (TDP[index].socket_type == CPU_SOCKET_TYPE &&
173                     TDP[index].cmp_cap == cmp_cap &&
174                     TDP[index].pwr_lmt == pwr_lmt) {
175                         power_limit = TDP[index].power_limit;
176                 }
177
178         Pstate_num = 0;
179
180         /* See if the CPUID(0x80000007) returned EDX[2:1]==11b */
181         cpuid1 = cpuid(0x80000007);
182         if ((cpuid1.edx & 0x6) != 0x6) {
183                 printk_info("No valid set of P-states\n");
184                 goto write_pstates;
185         }
186
187         msr = rdmsr(0xc0010042);
188         Max_fid = (msr.lo & 0x3F0000) >> 16;
189         Start_fid = (msr.lo & 0x3F00) >> 8;
190         Max_vid = (msr.hi & 0x3F0000) >> 16;
191         Start_vid = (msr.hi & 0x3F00) >> 8;
192         PstateStep = (msr.hi & 0x1000000) >> 24;
193         IntPstateSup = (msr.hi & 0x20000000) >> 29;
194
195         /*
196          * The P1...P[Min+1] VID need PstateStep to calculate
197          * P[N] = P[N-1]VID + 2^PstateStep
198          * PstateStep_coef = 2^PstateStep
199          */
200         if (PstateStep == 0)
201                 PstateStep_coef = 1;
202         else
203                 PstateStep_coef = 2;
204
205         if (IntPstateSup == 0) {
206                 printk_info("No intermediate P-states are supported\n");
207                 goto write_pstates;
208         }
209
210         /* Get the multipier of the fid frequency */
211         /*
212          * Fid multiplier is always 100 revF and revG.
213          */
214         fid_multiplier = 100;
215
216         /*
217          * Formula1:    CPUFreq = FID * fid_multiplier + 800
218          * Formula2:       CPUVolt = 1550 - VID * 25 (mv)
219          * Formula3:       Power = (PwrLmt * P[N]Frequency*(P[N]Voltage^2))/(P[0]Frequency * P[0]Voltage^2))
220          */
221
222         /* Construct P0(P[Max]) state */
223         Max_feq = Max_fid * fid_multiplier + 800;
224         if (Max_fid == 0x2A && Max_vid != 0x0) {
225                 Min_fid = 0x2;
226                 Pstate_fid[0] = Start_fid + 0xA;        /* Start Frequency + 1GHz */
227                 Pstate_feq[0] = Pstate_fid[0] * fid_multiplier + 800;
228                 Min_vid = Start_vid;
229                 Pstate_vid[0] = Max_vid + 0x2;  /* Maximum Voltage - 50mV */
230                 Pstate_volt[0] = 1550 - Pstate_vid[0] * 25;
231                 Pstate_power[0] = power_limit * 1000;   /* mw */
232                 Pstate_num++;
233         } else {
234                 Min_fid = Start_fid;
235                 Pstate_fid[0] = Max_fid;
236                 Pstate_feq[0] = Max_feq;
237                 Min_vid = Start_vid;
238                 Pstate_vid[0] = Max_vid + 0x2;
239                 Pstate_volt[0] = 1550 - Pstate_vid[0] * 25;
240                 Pstate_power[0] = power_limit * 1000;   /* mw */
241                 Pstate_num++;
242         }
243
244         Cur_feq = Max_feq;
245         Cur_fid = Max_fid;
246         /* Construct P1 state */
247         if (((Max_fid & 0x1) != 0) && ((Max_fid - 0x1) >= (Min_fid + 0x8))) {   /* odd value */
248                 Pstate_fid[1] = Max_fid - 0x1;
249                 Pstate_feq[1] = Pstate_fid[1] * fid_multiplier + 800;
250                 Cur_fid = Pstate_fid[1];
251                 Cur_feq = Pstate_feq[1];
252                 if (((Pstate_vid[0] & 0x1) != 0) && ((Pstate_vid[0] - 0x1) < Min_vid)) {        /* odd value */
253                         Pstate_vid[1] = Pstate_vid[0] + 0x1;
254                         Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
255                         Pstate_power[1] =
256                             (unsigned long long)Pstate_power[0] *
257                             Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1] /
258                             (Pstate_feq[0] * Pstate_volt[0] * Pstate_volt[0]);
259                 }
260                 if (((Pstate_vid[0] & 0x1) == 0) && ((Pstate_vid[0] - 0x1) < Min_vid)) {        /* even value */
261                         Pstate_vid[1] = Pstate_vid[0] + PstateStep_coef;
262                         Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
263                         Pstate_power[1] =
264                             (unsigned long long)Pstate_power[0] *
265                             Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1] /
266                             (Pstate_feq[0] * Pstate_volt[0] * Pstate_volt[0]);
267                 }
268                 Pstate_num++;
269         }
270
271         if (((Max_fid & 0x1) == 0) && ((Max_fid - 0x2) >= (Min_fid + 0x8))) {   /* even value */
272                 Pstate_fid[1] = Max_fid - 0x2;
273                 Pstate_feq[1] = Pstate_fid[1] * fid_multiplier + 800;
274                 Cur_fid = Pstate_fid[1];
275                 Cur_feq = Pstate_feq[1];
276                 if (((Pstate_vid[0] & 0x1) != 0) && ((Pstate_vid[0] - 0x1) < Min_vid)) {        /* odd value */
277                         Pstate_vid[1] = Pstate_vid[0] + 0x1;
278                         Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
279                         Pstate_power[1] =
280                             (unsigned long long)Pstate_power[0] *
281                             Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1] /
282                             (Pstate_feq[0] * Pstate_volt[0] * Pstate_volt[0]);
283                 }
284                 if (((Pstate_vid[0] & 0x1) == 0) && ((Pstate_vid[0] - 0x1) < Min_vid)) {        /* even value */
285                         Pstate_vid[1] = Pstate_vid[0] + PstateStep_coef;
286                         Pstate_volt[1] = 1550 - Pstate_vid[1] * 25;
287                         Pstate_power[1] =
288                             (unsigned long long)Pstate_power[0] *
289                             Pstate_feq[1] * Pstate_volt[1] * Pstate_volt[1] /
290                             (Pstate_feq[0] * Pstate_volt[0] * Pstate_volt[0]);
291                 }
292
293                 Pstate_num++;
294         }
295
296         /* Construct P2...P[Min-1] state */
297         Cur_fid = Cur_fid - 0x2;
298         Cur_feq = Cur_fid * fid_multiplier + 800;
299         while (Cur_feq >= ((Min_fid * fid_multiplier) + 800) * 2) {
300                 Pstate_fid[Pstate_num] = Cur_fid;
301                 Pstate_feq[Pstate_num] =
302                     Pstate_fid[Pstate_num] * fid_multiplier + 800;
303                 Cur_fid = Cur_fid - 0x2;
304                 Cur_feq = Cur_fid * fid_multiplier + 800;
305                 if (Pstate_vid[Pstate_num - 1] >= Min_vid) {
306                         Pstate_vid[Pstate_num] = Pstate_vid[Pstate_num - 1];
307                         Pstate_volt[Pstate_num] = Pstate_volt[Pstate_num - 1];
308                         Pstate_power[Pstate_num] = Pstate_power[Pstate_num - 1];
309                 } else {
310                         Pstate_vid[Pstate_num] =
311                             Pstate_vid[Pstate_num - 1] + PstateStep_coef;
312                         Pstate_volt[Pstate_num] =
313                             1550 - Pstate_vid[Pstate_num] * 25;
314                         Pstate_power[Pstate_num] =
315                             (unsigned long long)Pstate_power[0] *
316                             Pstate_feq[Pstate_num] * Pstate_volt[Pstate_num] *
317                             Pstate_volt[Pstate_num] / (Pstate_feq[0] *
318                                                        Pstate_volt[0] *
319                                                        Pstate_volt[0]);
320                 }
321                 Pstate_num++;
322         }
323
324         /* Constuct P[Min] State */
325         if (Max_fid == 0x2A && Max_vid != 0x0) {
326                 Pstate_fid[Pstate_num] = 0x2;
327                 Pstate_feq[Pstate_num] =
328                     Pstate_fid[Pstate_num] * fid_multiplier + 800;
329                 Pstate_vid[Pstate_num] = Min_vid;
330                 Pstate_volt[Pstate_num] = 1550 - Pstate_vid[Pstate_num] * 25;
331                 Pstate_power[Pstate_num] =
332                     (unsigned long long)Pstate_power[0] *
333                     Pstate_feq[Pstate_num] * Pstate_volt[Pstate_num] *
334                     Pstate_volt[Pstate_num] / (Pstate_feq[0] * Pstate_volt[0] *
335                                                Pstate_volt[0]);
336                 Pstate_num++;
337         } else {
338                 Pstate_fid[Pstate_num] = Start_fid;
339                 Pstate_feq[Pstate_num] =
340                     Pstate_fid[Pstate_num] * fid_multiplier + 800;
341                 Pstate_vid[Pstate_num] = Min_vid;
342                 Pstate_volt[Pstate_num] = 1550 - Pstate_vid[Pstate_num] * 25;
343                 Pstate_power[Pstate_num] =
344                     (unsigned long long)Pstate_power[0] *
345                     Pstate_feq[Pstate_num] * Pstate_volt[Pstate_num] *
346                     Pstate_volt[Pstate_num] / (Pstate_feq[0] * Pstate_volt[0] *
347                                                Pstate_volt[0]);
348                 Pstate_num++;
349         }
350
351         /* Print Pstate freq,vid,volt,power */
352
353         for (index = 0; index < Pstate_num; index++) {
354                 printk_info("Pstate_freq[%d] = %dMHz\t", index,
355                             Pstate_feq[index]);
356                 printk_info("Pstate_vid[%d] = %d\t", index, Pstate_vid[index]);
357                 printk_info("Pstate_volt[%d] = %dmv\t", index,
358                             Pstate_volt[index]);
359                 printk_info("Pstate_power[%d] = %dmw\n", index,
360                             Pstate_power[index]);
361         }
362
363
364 write_pstates:
365
366         len = 0;
367
368         for (index = 0; index < (cmp_cap + 1); index++) {
369                 len += write_pstates_for_core(Pstate_num, Pstate_feq, Pstate_vid,
370                                 Pstate_fid, Pstate_power, index,
371                                 pcontrol_blk, plen, onlyBSP);
372         }
373
374         return len;
375 }
376
377 int amd_model_fxx_generate_powernow(u32 pcontrol_blk, u8 plen, u8 onlyBSP) {
378         int lens;
379         char pscope[] = "\\_PR_";
380
381         lens = acpigen_write_scope(pscope);
382         lens += pstates_algorithm(pcontrol_blk, plen, onlyBSP);
383         //minus opcode
384         acpigen_patch_len(lens - 1);
385         return lens;
386 }