14f19048fSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2bb0a56ecSDave Jones /*
3bb0a56ecSDave Jones * AMD K7 Powernow driver.
4bb0a56ecSDave Jones * (C) 2003 Dave Jones on behalf of SuSE Labs.
5bb0a56ecSDave Jones *
6bb0a56ecSDave Jones * Based upon datasheets & sample CPUs kindly provided by AMD.
7bb0a56ecSDave Jones *
8bb0a56ecSDave Jones * Errata 5:
9bb0a56ecSDave Jones * CPU may fail to execute a FID/VID change in presence of interrupt.
10bb0a56ecSDave Jones * - We cli/sti on stepping A0 CPUs around the FID/VID transition.
11bb0a56ecSDave Jones * Errata 15:
12bb0a56ecSDave Jones * CPU with half frequency multipliers may hang upon wakeup from disconnect.
13bb0a56ecSDave Jones * - We disable half multipliers if ACPI is used on A0 stepping CPUs.
14bb0a56ecSDave Jones */
15bb0a56ecSDave Jones
161c5864e2SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
171c5864e2SJoe Perches
18bb0a56ecSDave Jones #include <linux/kernel.h>
19bb0a56ecSDave Jones #include <linux/module.h>
20bb0a56ecSDave Jones #include <linux/moduleparam.h>
21bb0a56ecSDave Jones #include <linux/init.h>
22bb0a56ecSDave Jones #include <linux/cpufreq.h>
23bb0a56ecSDave Jones #include <linux/slab.h>
24bb0a56ecSDave Jones #include <linux/string.h>
25bb0a56ecSDave Jones #include <linux/dmi.h>
26bb0a56ecSDave Jones #include <linux/timex.h>
27bb0a56ecSDave Jones #include <linux/io.h>
28bb0a56ecSDave Jones
29bb0a56ecSDave Jones #include <asm/timer.h> /* Needed for recalibrate_cpu_khz() */
30bb0a56ecSDave Jones #include <asm/msr.h>
31fa8031aeSAndi Kleen #include <asm/cpu_device_id.h>
32bb0a56ecSDave Jones
33bb0a56ecSDave Jones #ifdef CONFIG_X86_POWERNOW_K7_ACPI
34bb0a56ecSDave Jones #include <linux/acpi.h>
35bb0a56ecSDave Jones #include <acpi/processor.h>
36bb0a56ecSDave Jones #endif
37bb0a56ecSDave Jones
38bb0a56ecSDave Jones #include "powernow-k7.h"
39bb0a56ecSDave Jones
40bb0a56ecSDave Jones struct psb_s {
41bb0a56ecSDave Jones u8 signature[10];
42bb0a56ecSDave Jones u8 tableversion;
43bb0a56ecSDave Jones u8 flags;
44bb0a56ecSDave Jones u16 settlingtime;
45bb0a56ecSDave Jones u8 reserved1;
46bb0a56ecSDave Jones u8 numpst;
47bb0a56ecSDave Jones };
48bb0a56ecSDave Jones
49bb0a56ecSDave Jones struct pst_s {
50bb0a56ecSDave Jones u32 cpuid;
51bb0a56ecSDave Jones u8 fsbspeed;
52bb0a56ecSDave Jones u8 maxfid;
53bb0a56ecSDave Jones u8 startvid;
54bb0a56ecSDave Jones u8 numpstates;
55bb0a56ecSDave Jones };
56bb0a56ecSDave Jones
57bb0a56ecSDave Jones #ifdef CONFIG_X86_POWERNOW_K7_ACPI
58bb0a56ecSDave Jones union powernow_acpi_control_t {
59bb0a56ecSDave Jones struct {
60bb0a56ecSDave Jones unsigned long fid:5,
61bb0a56ecSDave Jones vid:5,
62bb0a56ecSDave Jones sgtc:20,
63bb0a56ecSDave Jones res1:2;
64bb0a56ecSDave Jones } bits;
65bb0a56ecSDave Jones unsigned long val;
66bb0a56ecSDave Jones };
67bb0a56ecSDave Jones #endif
68bb0a56ecSDave Jones
69bb0a56ecSDave Jones /* divide by 1000 to get VCore voltage in V. */
70bb0a56ecSDave Jones static const int mobile_vid_table[32] = {
71bb0a56ecSDave Jones 2000, 1950, 1900, 1850, 1800, 1750, 1700, 1650,
72bb0a56ecSDave Jones 1600, 1550, 1500, 1450, 1400, 1350, 1300, 0,
73bb0a56ecSDave Jones 1275, 1250, 1225, 1200, 1175, 1150, 1125, 1100,
74bb0a56ecSDave Jones 1075, 1050, 1025, 1000, 975, 950, 925, 0,
75bb0a56ecSDave Jones };
76bb0a56ecSDave Jones
77bb0a56ecSDave Jones /* divide by 10 to get FID. */
78bb0a56ecSDave Jones static const int fid_codes[32] = {
79bb0a56ecSDave Jones 110, 115, 120, 125, 50, 55, 60, 65,
80bb0a56ecSDave Jones 70, 75, 80, 85, 90, 95, 100, 105,
81bb0a56ecSDave Jones 30, 190, 40, 200, 130, 135, 140, 210,
82bb0a56ecSDave Jones 150, 225, 160, 165, 170, 180, -1, -1,
83bb0a56ecSDave Jones };
84bb0a56ecSDave Jones
85bb0a56ecSDave Jones /* This parameter is used in order to force ACPI instead of legacy method for
86bb0a56ecSDave Jones * configuration purpose.
87bb0a56ecSDave Jones */
88bb0a56ecSDave Jones
89bb0a56ecSDave Jones static int acpi_force;
90bb0a56ecSDave Jones
91bb0a56ecSDave Jones static struct cpufreq_frequency_table *powernow_table;
92bb0a56ecSDave Jones
93bb0a56ecSDave Jones static unsigned int can_scale_bus;
94bb0a56ecSDave Jones static unsigned int can_scale_vid;
95bb0a56ecSDave Jones static unsigned int minimum_speed = -1;
96bb0a56ecSDave Jones static unsigned int maximum_speed;
97bb0a56ecSDave Jones static unsigned int number_scales;
98bb0a56ecSDave Jones static unsigned int fsb;
99bb0a56ecSDave Jones static unsigned int latency;
100bb0a56ecSDave Jones static char have_a0;
101bb0a56ecSDave Jones
check_fsb(unsigned int fsbspeed)102bb0a56ecSDave Jones static int check_fsb(unsigned int fsbspeed)
103bb0a56ecSDave Jones {
104bb0a56ecSDave Jones int delta;
105bb0a56ecSDave Jones unsigned int f = fsb / 1000;
106bb0a56ecSDave Jones
107bb0a56ecSDave Jones delta = (fsbspeed > f) ? fsbspeed - f : f - fsbspeed;
108bb0a56ecSDave Jones return delta < 5;
109bb0a56ecSDave Jones }
110bb0a56ecSDave Jones
111fa8031aeSAndi Kleen static const struct x86_cpu_id powernow_k7_cpuids[] = {
112*b11d77faSThomas Gleixner X86_MATCH_VENDOR_FAM(AMD, 6, NULL),
113fa8031aeSAndi Kleen {}
114fa8031aeSAndi Kleen };
115fa8031aeSAndi Kleen MODULE_DEVICE_TABLE(x86cpu, powernow_k7_cpuids);
116fa8031aeSAndi Kleen
check_powernow(void)117bb0a56ecSDave Jones static int check_powernow(void)
118bb0a56ecSDave Jones {
119bb0a56ecSDave Jones struct cpuinfo_x86 *c = &cpu_data(0);
120bb0a56ecSDave Jones unsigned int maxei, eax, ebx, ecx, edx;
121bb0a56ecSDave Jones
122fa8031aeSAndi Kleen if (!x86_match_cpu(powernow_k7_cpuids))
123bb0a56ecSDave Jones return 0;
124bb0a56ecSDave Jones
125bb0a56ecSDave Jones /* Get maximum capabilities */
126bb0a56ecSDave Jones maxei = cpuid_eax(0x80000000);
127bb0a56ecSDave Jones if (maxei < 0x80000007) { /* Any powernow info ? */
128bb0a56ecSDave Jones #ifdef MODULE
1291c5864e2SJoe Perches pr_info("No powernow capabilities detected\n");
130bb0a56ecSDave Jones #endif
131bb0a56ecSDave Jones return 0;
132bb0a56ecSDave Jones }
133bb0a56ecSDave Jones
134b399151cSJia Zhang if ((c->x86_model == 6) && (c->x86_stepping == 0)) {
1351c5864e2SJoe Perches pr_info("K7 660[A0] core detected, enabling errata workarounds\n");
136bb0a56ecSDave Jones have_a0 = 1;
137bb0a56ecSDave Jones }
138bb0a56ecSDave Jones
139bb0a56ecSDave Jones cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
140bb0a56ecSDave Jones
141bb0a56ecSDave Jones /* Check we can actually do something before we say anything.*/
142bb0a56ecSDave Jones if (!(edx & (1 << 1 | 1 << 2)))
143bb0a56ecSDave Jones return 0;
144bb0a56ecSDave Jones
1451c5864e2SJoe Perches pr_info("PowerNOW! Technology present. Can scale: ");
146bb0a56ecSDave Jones
147bb0a56ecSDave Jones if (edx & 1 << 1) {
148b49c22a6SJoe Perches pr_cont("frequency");
149bb0a56ecSDave Jones can_scale_bus = 1;
150bb0a56ecSDave Jones }
151bb0a56ecSDave Jones
152bb0a56ecSDave Jones if ((edx & (1 << 1 | 1 << 2)) == 0x6)
153b49c22a6SJoe Perches pr_cont(" and ");
154bb0a56ecSDave Jones
155bb0a56ecSDave Jones if (edx & 1 << 2) {
156b49c22a6SJoe Perches pr_cont("voltage");
157bb0a56ecSDave Jones can_scale_vid = 1;
158bb0a56ecSDave Jones }
159bb0a56ecSDave Jones
160b49c22a6SJoe Perches pr_cont("\n");
161bb0a56ecSDave Jones return 1;
162bb0a56ecSDave Jones }
163bb0a56ecSDave Jones
164bb0a56ecSDave Jones #ifdef CONFIG_X86_POWERNOW_K7_ACPI
invalidate_entry(unsigned int entry)165bb0a56ecSDave Jones static void invalidate_entry(unsigned int entry)
166bb0a56ecSDave Jones {
167bb0a56ecSDave Jones powernow_table[entry].frequency = CPUFREQ_ENTRY_INVALID;
168bb0a56ecSDave Jones }
169bb0a56ecSDave Jones #endif
170bb0a56ecSDave Jones
get_ranges(unsigned char * pst)171bb0a56ecSDave Jones static int get_ranges(unsigned char *pst)
172bb0a56ecSDave Jones {
173bb0a56ecSDave Jones unsigned int j;
174bb0a56ecSDave Jones unsigned int speed;
175bb0a56ecSDave Jones u8 fid, vid;
176bb0a56ecSDave Jones
177d5b73cd8SViresh Kumar powernow_table = kzalloc((sizeof(*powernow_table) *
178bb0a56ecSDave Jones (number_scales + 1)), GFP_KERNEL);
179bb0a56ecSDave Jones if (!powernow_table)
180bb0a56ecSDave Jones return -ENOMEM;
181bb0a56ecSDave Jones
182bb0a56ecSDave Jones for (j = 0 ; j < number_scales; j++) {
183bb0a56ecSDave Jones fid = *pst++;
184bb0a56ecSDave Jones
185bb0a56ecSDave Jones powernow_table[j].frequency = (fsb * fid_codes[fid]) / 10;
18650701588SViresh Kumar powernow_table[j].driver_data = fid; /* lower 8 bits */
187bb0a56ecSDave Jones
188bb0a56ecSDave Jones speed = powernow_table[j].frequency;
189bb0a56ecSDave Jones
190bb0a56ecSDave Jones if ((fid_codes[fid] % 10) == 5) {
191bb0a56ecSDave Jones #ifdef CONFIG_X86_POWERNOW_K7_ACPI
192bb0a56ecSDave Jones if (have_a0 == 1)
193bb0a56ecSDave Jones invalidate_entry(j);
194bb0a56ecSDave Jones #endif
195bb0a56ecSDave Jones }
196bb0a56ecSDave Jones
197bb0a56ecSDave Jones if (speed < minimum_speed)
198bb0a56ecSDave Jones minimum_speed = speed;
199bb0a56ecSDave Jones if (speed > maximum_speed)
200bb0a56ecSDave Jones maximum_speed = speed;
201bb0a56ecSDave Jones
202bb0a56ecSDave Jones vid = *pst++;
20350701588SViresh Kumar powernow_table[j].driver_data |= (vid << 8); /* upper 8 bits */
204bb0a56ecSDave Jones
205bb0a56ecSDave Jones pr_debug(" FID: 0x%x (%d.%dx [%dMHz]) "
206bb0a56ecSDave Jones "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
207bb0a56ecSDave Jones fid_codes[fid] % 10, speed/1000, vid,
208bb0a56ecSDave Jones mobile_vid_table[vid]/1000,
209bb0a56ecSDave Jones mobile_vid_table[vid]%1000);
210bb0a56ecSDave Jones }
211bb0a56ecSDave Jones powernow_table[number_scales].frequency = CPUFREQ_TABLE_END;
21250701588SViresh Kumar powernow_table[number_scales].driver_data = 0;
213bb0a56ecSDave Jones
214bb0a56ecSDave Jones return 0;
215bb0a56ecSDave Jones }
216bb0a56ecSDave Jones
217bb0a56ecSDave Jones
change_FID(int fid)218bb0a56ecSDave Jones static void change_FID(int fid)
219bb0a56ecSDave Jones {
220bb0a56ecSDave Jones union msr_fidvidctl fidvidctl;
221bb0a56ecSDave Jones
222bb0a56ecSDave Jones rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
223bb0a56ecSDave Jones if (fidvidctl.bits.FID != fid) {
224bb0a56ecSDave Jones fidvidctl.bits.SGTC = latency;
225bb0a56ecSDave Jones fidvidctl.bits.FID = fid;
226bb0a56ecSDave Jones fidvidctl.bits.VIDC = 0;
227bb0a56ecSDave Jones fidvidctl.bits.FIDC = 1;
228bb0a56ecSDave Jones wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
229bb0a56ecSDave Jones }
230bb0a56ecSDave Jones }
231bb0a56ecSDave Jones
232bb0a56ecSDave Jones
change_VID(int vid)233bb0a56ecSDave Jones static void change_VID(int vid)
234bb0a56ecSDave Jones {
235bb0a56ecSDave Jones union msr_fidvidctl fidvidctl;
236bb0a56ecSDave Jones
237bb0a56ecSDave Jones rdmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
238bb0a56ecSDave Jones if (fidvidctl.bits.VID != vid) {
239bb0a56ecSDave Jones fidvidctl.bits.SGTC = latency;
240bb0a56ecSDave Jones fidvidctl.bits.VID = vid;
241bb0a56ecSDave Jones fidvidctl.bits.FIDC = 0;
242bb0a56ecSDave Jones fidvidctl.bits.VIDC = 1;
243bb0a56ecSDave Jones wrmsrl(MSR_K7_FID_VID_CTL, fidvidctl.val);
244bb0a56ecSDave Jones }
245bb0a56ecSDave Jones }
246bb0a56ecSDave Jones
247bb0a56ecSDave Jones
powernow_target(struct cpufreq_policy * policy,unsigned int index)2489c0ebcf7SViresh Kumar static int powernow_target(struct cpufreq_policy *policy, unsigned int index)
249bb0a56ecSDave Jones {
250bb0a56ecSDave Jones u8 fid, vid;
251bb0a56ecSDave Jones struct cpufreq_freqs freqs;
252bb0a56ecSDave Jones union msr_fidvidstatus fidvidstatus;
253bb0a56ecSDave Jones int cfid;
254bb0a56ecSDave Jones
255bb0a56ecSDave Jones /* fid are the lower 8 bits of the index we stored into
256bb0a56ecSDave Jones * the cpufreq frequency table in powernow_decode_bios,
257bb0a56ecSDave Jones * vid are the upper 8 bits.
258bb0a56ecSDave Jones */
259bb0a56ecSDave Jones
26050701588SViresh Kumar fid = powernow_table[index].driver_data & 0xFF;
26150701588SViresh Kumar vid = (powernow_table[index].driver_data & 0xFF00) >> 8;
262bb0a56ecSDave Jones
263bb0a56ecSDave Jones rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
264bb0a56ecSDave Jones cfid = fidvidstatus.bits.CFID;
265bb0a56ecSDave Jones freqs.old = fsb * fid_codes[cfid] / 10;
266bb0a56ecSDave Jones
267bb0a56ecSDave Jones freqs.new = powernow_table[index].frequency;
268bb0a56ecSDave Jones
269bb0a56ecSDave Jones /* Now do the magic poking into the MSRs. */
270bb0a56ecSDave Jones
271bb0a56ecSDave Jones if (have_a0 == 1) /* A0 errata 5 */
272bb0a56ecSDave Jones local_irq_disable();
273bb0a56ecSDave Jones
274bb0a56ecSDave Jones if (freqs.old > freqs.new) {
275bb0a56ecSDave Jones /* Going down, so change FID first */
276bb0a56ecSDave Jones change_FID(fid);
277bb0a56ecSDave Jones change_VID(vid);
278bb0a56ecSDave Jones } else {
279bb0a56ecSDave Jones /* Going up, so change VID first */
280bb0a56ecSDave Jones change_VID(vid);
281bb0a56ecSDave Jones change_FID(fid);
282bb0a56ecSDave Jones }
283bb0a56ecSDave Jones
284bb0a56ecSDave Jones
285bb0a56ecSDave Jones if (have_a0 == 1)
286bb0a56ecSDave Jones local_irq_enable();
287bb0a56ecSDave Jones
2889c0ebcf7SViresh Kumar return 0;
289bb0a56ecSDave Jones }
290bb0a56ecSDave Jones
291bb0a56ecSDave Jones
292bb0a56ecSDave Jones #ifdef CONFIG_X86_POWERNOW_K7_ACPI
293bb0a56ecSDave Jones
294bb0a56ecSDave Jones static struct acpi_processor_performance *acpi_processor_perf;
295bb0a56ecSDave Jones
powernow_acpi_init(void)296bb0a56ecSDave Jones static int powernow_acpi_init(void)
297bb0a56ecSDave Jones {
298bb0a56ecSDave Jones int i;
299bb0a56ecSDave Jones int retval = 0;
300bb0a56ecSDave Jones union powernow_acpi_control_t pc;
301bb0a56ecSDave Jones
302bb0a56ecSDave Jones if (acpi_processor_perf != NULL && powernow_table != NULL) {
303bb0a56ecSDave Jones retval = -EINVAL;
304bb0a56ecSDave Jones goto err0;
305bb0a56ecSDave Jones }
306bb0a56ecSDave Jones
307d5b73cd8SViresh Kumar acpi_processor_perf = kzalloc(sizeof(*acpi_processor_perf), GFP_KERNEL);
308bb0a56ecSDave Jones if (!acpi_processor_perf) {
309bb0a56ecSDave Jones retval = -ENOMEM;
310bb0a56ecSDave Jones goto err0;
311bb0a56ecSDave Jones }
312bb0a56ecSDave Jones
313bb0a56ecSDave Jones if (!zalloc_cpumask_var(&acpi_processor_perf->shared_cpu_map,
314bb0a56ecSDave Jones GFP_KERNEL)) {
315bb0a56ecSDave Jones retval = -ENOMEM;
316bb0a56ecSDave Jones goto err05;
317bb0a56ecSDave Jones }
318bb0a56ecSDave Jones
319bb0a56ecSDave Jones if (acpi_processor_register_performance(acpi_processor_perf, 0)) {
320bb0a56ecSDave Jones retval = -EIO;
321bb0a56ecSDave Jones goto err1;
322bb0a56ecSDave Jones }
323bb0a56ecSDave Jones
324bb0a56ecSDave Jones if (acpi_processor_perf->control_register.space_id !=
325bb0a56ecSDave Jones ACPI_ADR_SPACE_FIXED_HARDWARE) {
326bb0a56ecSDave Jones retval = -ENODEV;
327bb0a56ecSDave Jones goto err2;
328bb0a56ecSDave Jones }
329bb0a56ecSDave Jones
330bb0a56ecSDave Jones if (acpi_processor_perf->status_register.space_id !=
331bb0a56ecSDave Jones ACPI_ADR_SPACE_FIXED_HARDWARE) {
332bb0a56ecSDave Jones retval = -ENODEV;
333bb0a56ecSDave Jones goto err2;
334bb0a56ecSDave Jones }
335bb0a56ecSDave Jones
336bb0a56ecSDave Jones number_scales = acpi_processor_perf->state_count;
337bb0a56ecSDave Jones
338bb0a56ecSDave Jones if (number_scales < 2) {
339bb0a56ecSDave Jones retval = -ENODEV;
340bb0a56ecSDave Jones goto err2;
341bb0a56ecSDave Jones }
342bb0a56ecSDave Jones
343d5b73cd8SViresh Kumar powernow_table = kzalloc((sizeof(*powernow_table) *
344bb0a56ecSDave Jones (number_scales + 1)), GFP_KERNEL);
345bb0a56ecSDave Jones if (!powernow_table) {
346bb0a56ecSDave Jones retval = -ENOMEM;
347bb0a56ecSDave Jones goto err2;
348bb0a56ecSDave Jones }
349bb0a56ecSDave Jones
350bb0a56ecSDave Jones pc.val = (unsigned long) acpi_processor_perf->states[0].control;
351bb0a56ecSDave Jones for (i = 0; i < number_scales; i++) {
352bb0a56ecSDave Jones u8 fid, vid;
353bb0a56ecSDave Jones struct acpi_processor_px *state =
354bb0a56ecSDave Jones &acpi_processor_perf->states[i];
355bb0a56ecSDave Jones unsigned int speed, speed_mhz;
356bb0a56ecSDave Jones
357bb0a56ecSDave Jones pc.val = (unsigned long) state->control;
358bb0a56ecSDave Jones pr_debug("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n",
359bb0a56ecSDave Jones i,
360bb0a56ecSDave Jones (u32) state->core_frequency,
361bb0a56ecSDave Jones (u32) state->power,
362bb0a56ecSDave Jones (u32) state->transition_latency,
363bb0a56ecSDave Jones (u32) state->control,
364bb0a56ecSDave Jones pc.bits.sgtc);
365bb0a56ecSDave Jones
366bb0a56ecSDave Jones vid = pc.bits.vid;
367bb0a56ecSDave Jones fid = pc.bits.fid;
368bb0a56ecSDave Jones
369bb0a56ecSDave Jones powernow_table[i].frequency = fsb * fid_codes[fid] / 10;
37050701588SViresh Kumar powernow_table[i].driver_data = fid; /* lower 8 bits */
37150701588SViresh Kumar powernow_table[i].driver_data |= (vid << 8); /* upper 8 bits */
372bb0a56ecSDave Jones
373bb0a56ecSDave Jones speed = powernow_table[i].frequency;
374bb0a56ecSDave Jones speed_mhz = speed / 1000;
375bb0a56ecSDave Jones
376bb0a56ecSDave Jones /* processor_perflib will multiply the MHz value by 1000 to
377bb0a56ecSDave Jones * get a KHz value (e.g. 1266000). However, powernow-k7 works
378bb0a56ecSDave Jones * with true KHz values (e.g. 1266768). To ensure that all
379bb0a56ecSDave Jones * powernow frequencies are available, we must ensure that
380bb0a56ecSDave Jones * ACPI doesn't restrict them, so we round up the MHz value
381bb0a56ecSDave Jones * to ensure that perflib's computed KHz value is greater than
382bb0a56ecSDave Jones * or equal to powernow's KHz value.
383bb0a56ecSDave Jones */
384bb0a56ecSDave Jones if (speed % 1000 > 0)
385bb0a56ecSDave Jones speed_mhz++;
386bb0a56ecSDave Jones
387bb0a56ecSDave Jones if ((fid_codes[fid] % 10) == 5) {
388bb0a56ecSDave Jones if (have_a0 == 1)
389bb0a56ecSDave Jones invalidate_entry(i);
390bb0a56ecSDave Jones }
391bb0a56ecSDave Jones
392bb0a56ecSDave Jones pr_debug(" FID: 0x%x (%d.%dx [%dMHz]) "
393bb0a56ecSDave Jones "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10,
394bb0a56ecSDave Jones fid_codes[fid] % 10, speed_mhz, vid,
395bb0a56ecSDave Jones mobile_vid_table[vid]/1000,
396bb0a56ecSDave Jones mobile_vid_table[vid]%1000);
397bb0a56ecSDave Jones
398bb0a56ecSDave Jones if (state->core_frequency != speed_mhz) {
399bb0a56ecSDave Jones state->core_frequency = speed_mhz;
400bb0a56ecSDave Jones pr_debug(" Corrected ACPI frequency to %d\n",
401bb0a56ecSDave Jones speed_mhz);
402bb0a56ecSDave Jones }
403bb0a56ecSDave Jones
404bb0a56ecSDave Jones if (latency < pc.bits.sgtc)
405bb0a56ecSDave Jones latency = pc.bits.sgtc;
406bb0a56ecSDave Jones
407bb0a56ecSDave Jones if (speed < minimum_speed)
408bb0a56ecSDave Jones minimum_speed = speed;
409bb0a56ecSDave Jones if (speed > maximum_speed)
410bb0a56ecSDave Jones maximum_speed = speed;
411bb0a56ecSDave Jones }
412bb0a56ecSDave Jones
413bb0a56ecSDave Jones powernow_table[i].frequency = CPUFREQ_TABLE_END;
41450701588SViresh Kumar powernow_table[i].driver_data = 0;
415bb0a56ecSDave Jones
416bb0a56ecSDave Jones /* notify BIOS that we exist */
417bb0a56ecSDave Jones acpi_processor_notify_smm(THIS_MODULE);
418bb0a56ecSDave Jones
419bb0a56ecSDave Jones return 0;
420bb0a56ecSDave Jones
421bb0a56ecSDave Jones err2:
422b2f8dc4cSRafael J. Wysocki acpi_processor_unregister_performance(0);
423bb0a56ecSDave Jones err1:
424bb0a56ecSDave Jones free_cpumask_var(acpi_processor_perf->shared_cpu_map);
425bb0a56ecSDave Jones err05:
426bb0a56ecSDave Jones kfree(acpi_processor_perf);
427bb0a56ecSDave Jones err0:
4281c5864e2SJoe Perches pr_warn("ACPI perflib can not be used on this platform\n");
429bb0a56ecSDave Jones acpi_processor_perf = NULL;
430bb0a56ecSDave Jones return retval;
431bb0a56ecSDave Jones }
432bb0a56ecSDave Jones #else
powernow_acpi_init(void)433bb0a56ecSDave Jones static int powernow_acpi_init(void)
434bb0a56ecSDave Jones {
4351c5864e2SJoe Perches pr_info("no support for ACPI processor found - please recompile your kernel with ACPI processor\n");
436bb0a56ecSDave Jones return -EINVAL;
437bb0a56ecSDave Jones }
438bb0a56ecSDave Jones #endif
439bb0a56ecSDave Jones
print_pst_entry(struct pst_s * pst,unsigned int j)440bb0a56ecSDave Jones static void print_pst_entry(struct pst_s *pst, unsigned int j)
441bb0a56ecSDave Jones {
442bb0a56ecSDave Jones pr_debug("PST:%d (@%p)\n", j, pst);
443bb0a56ecSDave Jones pr_debug(" cpuid: 0x%x fsb: %d maxFID: 0x%x startvid: 0x%x\n",
444bb0a56ecSDave Jones pst->cpuid, pst->fsbspeed, pst->maxfid, pst->startvid);
445bb0a56ecSDave Jones }
446bb0a56ecSDave Jones
powernow_decode_bios(int maxfid,int startvid)447bb0a56ecSDave Jones static int powernow_decode_bios(int maxfid, int startvid)
448bb0a56ecSDave Jones {
449bb0a56ecSDave Jones struct psb_s *psb;
450bb0a56ecSDave Jones struct pst_s *pst;
451bb0a56ecSDave Jones unsigned int i, j;
452bb0a56ecSDave Jones unsigned char *p;
453bb0a56ecSDave Jones unsigned int etuple;
454bb0a56ecSDave Jones unsigned int ret;
455bb0a56ecSDave Jones
456bb0a56ecSDave Jones etuple = cpuid_eax(0x80000001);
457bb0a56ecSDave Jones
458bb0a56ecSDave Jones for (i = 0xC0000; i < 0xffff0 ; i += 16) {
459bb0a56ecSDave Jones
460bb0a56ecSDave Jones p = phys_to_virt(i);
461bb0a56ecSDave Jones
462bb0a56ecSDave Jones if (memcmp(p, "AMDK7PNOW!", 10) == 0) {
463bb0a56ecSDave Jones pr_debug("Found PSB header at %p\n", p);
464bb0a56ecSDave Jones psb = (struct psb_s *) p;
465bb0a56ecSDave Jones pr_debug("Table version: 0x%x\n", psb->tableversion);
466bb0a56ecSDave Jones if (psb->tableversion != 0x12) {
4671c5864e2SJoe Perches pr_info("Sorry, only v1.2 tables supported right now\n");
468bb0a56ecSDave Jones return -ENODEV;
469bb0a56ecSDave Jones }
470bb0a56ecSDave Jones
471bb0a56ecSDave Jones pr_debug("Flags: 0x%x\n", psb->flags);
472bb0a56ecSDave Jones if ((psb->flags & 1) == 0)
473bb0a56ecSDave Jones pr_debug("Mobile voltage regulator\n");
474bb0a56ecSDave Jones else
475bb0a56ecSDave Jones pr_debug("Desktop voltage regulator\n");
476bb0a56ecSDave Jones
477bb0a56ecSDave Jones latency = psb->settlingtime;
478bb0a56ecSDave Jones if (latency < 100) {
4791c5864e2SJoe Perches pr_info("BIOS set settling time to %d microseconds. Should be at least 100. Correcting.\n",
480b49c22a6SJoe Perches latency);
481bb0a56ecSDave Jones latency = 100;
482bb0a56ecSDave Jones }
483bb0a56ecSDave Jones pr_debug("Settling Time: %d microseconds.\n",
484bb0a56ecSDave Jones psb->settlingtime);
485bb0a56ecSDave Jones pr_debug("Has %d PST tables. (Only dumping ones "
486bb0a56ecSDave Jones "relevant to this CPU).\n",
487bb0a56ecSDave Jones psb->numpst);
488bb0a56ecSDave Jones
489d5b73cd8SViresh Kumar p += sizeof(*psb);
490bb0a56ecSDave Jones
491bb0a56ecSDave Jones pst = (struct pst_s *) p;
492bb0a56ecSDave Jones
493bb0a56ecSDave Jones for (j = 0; j < psb->numpst; j++) {
494bb0a56ecSDave Jones pst = (struct pst_s *) p;
495bb0a56ecSDave Jones number_scales = pst->numpstates;
496bb0a56ecSDave Jones
497bb0a56ecSDave Jones if ((etuple == pst->cpuid) &&
498bb0a56ecSDave Jones check_fsb(pst->fsbspeed) &&
499bb0a56ecSDave Jones (maxfid == pst->maxfid) &&
500bb0a56ecSDave Jones (startvid == pst->startvid)) {
501bb0a56ecSDave Jones print_pst_entry(pst, j);
502d5b73cd8SViresh Kumar p = (char *)pst + sizeof(*pst);
503bb0a56ecSDave Jones ret = get_ranges(p);
504bb0a56ecSDave Jones return ret;
505bb0a56ecSDave Jones } else {
506bb0a56ecSDave Jones unsigned int k;
507d5b73cd8SViresh Kumar p = (char *)pst + sizeof(*pst);
508bb0a56ecSDave Jones for (k = 0; k < number_scales; k++)
509bb0a56ecSDave Jones p += 2;
510bb0a56ecSDave Jones }
511bb0a56ecSDave Jones }
5121c5864e2SJoe Perches pr_info("No PST tables match this cpuid (0x%x)\n",
513b49c22a6SJoe Perches etuple);
5141c5864e2SJoe Perches pr_info("This is indicative of a broken BIOS\n");
515bb0a56ecSDave Jones
516bb0a56ecSDave Jones return -EINVAL;
517bb0a56ecSDave Jones }
518bb0a56ecSDave Jones p++;
519bb0a56ecSDave Jones }
520bb0a56ecSDave Jones
521bb0a56ecSDave Jones return -ENODEV;
522bb0a56ecSDave Jones }
523bb0a56ecSDave Jones
524bb0a56ecSDave Jones
525bb0a56ecSDave Jones /*
526bb0a56ecSDave Jones * We use the fact that the bus frequency is somehow
527bb0a56ecSDave Jones * a multiple of 100000/3 khz, then we compute sgtc according
528bb0a56ecSDave Jones * to this multiple.
529bb0a56ecSDave Jones * That way, we match more how AMD thinks all of that work.
530bb0a56ecSDave Jones * We will then get the same kind of behaviour already tested under
531bb0a56ecSDave Jones * the "well-known" other OS.
532bb0a56ecSDave Jones */
fixup_sgtc(void)5332760984fSPaul Gortmaker static int fixup_sgtc(void)
534bb0a56ecSDave Jones {
535bb0a56ecSDave Jones unsigned int sgtc;
536bb0a56ecSDave Jones unsigned int m;
537bb0a56ecSDave Jones
538bb0a56ecSDave Jones m = fsb / 3333;
539bb0a56ecSDave Jones if ((m % 10) >= 5)
540bb0a56ecSDave Jones m += 5;
541bb0a56ecSDave Jones
542bb0a56ecSDave Jones m /= 10;
543bb0a56ecSDave Jones
544bb0a56ecSDave Jones sgtc = 100 * m * latency;
545bb0a56ecSDave Jones sgtc = sgtc / 3;
546bb0a56ecSDave Jones if (sgtc > 0xfffff) {
5471c5864e2SJoe Perches pr_warn("SGTC too large %d\n", sgtc);
548bb0a56ecSDave Jones sgtc = 0xfffff;
549bb0a56ecSDave Jones }
550bb0a56ecSDave Jones return sgtc;
551bb0a56ecSDave Jones }
552bb0a56ecSDave Jones
powernow_get(unsigned int cpu)553bb0a56ecSDave Jones static unsigned int powernow_get(unsigned int cpu)
554bb0a56ecSDave Jones {
555bb0a56ecSDave Jones union msr_fidvidstatus fidvidstatus;
556bb0a56ecSDave Jones unsigned int cfid;
557bb0a56ecSDave Jones
558bb0a56ecSDave Jones if (cpu)
559bb0a56ecSDave Jones return 0;
560bb0a56ecSDave Jones rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
561bb0a56ecSDave Jones cfid = fidvidstatus.bits.CFID;
562bb0a56ecSDave Jones
563bb0a56ecSDave Jones return fsb * fid_codes[cfid] / 10;
564bb0a56ecSDave Jones }
565bb0a56ecSDave Jones
566bb0a56ecSDave Jones
acer_cpufreq_pst(const struct dmi_system_id * d)5672760984fSPaul Gortmaker static int acer_cpufreq_pst(const struct dmi_system_id *d)
568bb0a56ecSDave Jones {
5691c5864e2SJoe Perches pr_warn("%s laptop with broken PST tables in BIOS detected\n",
570bb0a56ecSDave Jones d->ident);
5711c5864e2SJoe Perches pr_warn("You need to downgrade to 3A21 (09/09/2002), or try a newer BIOS than 3A71 (01/20/2003)\n");
5721c5864e2SJoe Perches pr_warn("cpufreq scaling has been disabled as a result of this\n");
573bb0a56ecSDave Jones return 0;
574bb0a56ecSDave Jones }
575bb0a56ecSDave Jones
576bb0a56ecSDave Jones /*
577bb0a56ecSDave Jones * Some Athlon laptops have really fucked PST tables.
578bb0a56ecSDave Jones * A BIOS update is all that can save them.
579bb0a56ecSDave Jones * Mention this, and disable cpufreq.
580bb0a56ecSDave Jones */
5816faadbbbSChristoph Hellwig static const struct dmi_system_id powernow_dmi_table[] = {
582bb0a56ecSDave Jones {
583bb0a56ecSDave Jones .callback = acer_cpufreq_pst,
584bb0a56ecSDave Jones .ident = "Acer Aspire",
585bb0a56ecSDave Jones .matches = {
586bb0a56ecSDave Jones DMI_MATCH(DMI_SYS_VENDOR, "Insyde Software"),
587bb0a56ecSDave Jones DMI_MATCH(DMI_BIOS_VERSION, "3A71"),
588bb0a56ecSDave Jones },
589bb0a56ecSDave Jones },
590bb0a56ecSDave Jones { }
591bb0a56ecSDave Jones };
592bb0a56ecSDave Jones
powernow_cpu_init(struct cpufreq_policy * policy)5932760984fSPaul Gortmaker static int powernow_cpu_init(struct cpufreq_policy *policy)
594bb0a56ecSDave Jones {
595bb0a56ecSDave Jones union msr_fidvidstatus fidvidstatus;
596bb0a56ecSDave Jones int result;
597bb0a56ecSDave Jones
598bb0a56ecSDave Jones if (policy->cpu != 0)
599bb0a56ecSDave Jones return -ENODEV;
600bb0a56ecSDave Jones
601bb0a56ecSDave Jones rdmsrl(MSR_K7_FID_VID_STATUS, fidvidstatus.val);
602bb0a56ecSDave Jones
603bb0a56ecSDave Jones recalibrate_cpu_khz();
604bb0a56ecSDave Jones
605bb0a56ecSDave Jones fsb = (10 * cpu_khz) / fid_codes[fidvidstatus.bits.CFID];
606bb0a56ecSDave Jones if (!fsb) {
6071c5864e2SJoe Perches pr_warn("can not determine bus frequency\n");
608bb0a56ecSDave Jones return -EINVAL;
609bb0a56ecSDave Jones }
610bb0a56ecSDave Jones pr_debug("FSB: %3dMHz\n", fsb/1000);
611bb0a56ecSDave Jones
612bb0a56ecSDave Jones if (dmi_check_system(powernow_dmi_table) || acpi_force) {
6131c5864e2SJoe Perches pr_info("PSB/PST known to be broken - trying ACPI instead\n");
614bb0a56ecSDave Jones result = powernow_acpi_init();
615bb0a56ecSDave Jones } else {
616bb0a56ecSDave Jones result = powernow_decode_bios(fidvidstatus.bits.MFID,
617bb0a56ecSDave Jones fidvidstatus.bits.SVID);
618bb0a56ecSDave Jones if (result) {
6191c5864e2SJoe Perches pr_info("Trying ACPI perflib\n");
620bb0a56ecSDave Jones maximum_speed = 0;
621bb0a56ecSDave Jones minimum_speed = -1;
622bb0a56ecSDave Jones latency = 0;
623bb0a56ecSDave Jones result = powernow_acpi_init();
624bb0a56ecSDave Jones if (result) {
6251c5864e2SJoe Perches pr_info("ACPI and legacy methods failed\n");
626bb0a56ecSDave Jones }
627bb0a56ecSDave Jones } else {
628bb0a56ecSDave Jones /* SGTC use the bus clock as timer */
629bb0a56ecSDave Jones latency = fixup_sgtc();
6301c5864e2SJoe Perches pr_info("SGTC: %d\n", latency);
631bb0a56ecSDave Jones }
632bb0a56ecSDave Jones }
633bb0a56ecSDave Jones
634bb0a56ecSDave Jones if (result)
635bb0a56ecSDave Jones return result;
636bb0a56ecSDave Jones
6371c5864e2SJoe Perches pr_info("Minimum speed %d MHz - Maximum speed %d MHz\n",
638bb0a56ecSDave Jones minimum_speed/1000, maximum_speed/1000);
639bb0a56ecSDave Jones
640bb0a56ecSDave Jones policy->cpuinfo.transition_latency =
641bb0a56ecSDave Jones cpufreq_scale(2000000UL, fsb, latency);
642e2376d1fSViresh Kumar policy->freq_table = powernow_table;
643bb0a56ecSDave Jones
644e2376d1fSViresh Kumar return 0;
645bb0a56ecSDave Jones }
646bb0a56ecSDave Jones
powernow_cpu_exit(struct cpufreq_policy * policy)647bb0a56ecSDave Jones static int powernow_cpu_exit(struct cpufreq_policy *policy)
648bb0a56ecSDave Jones {
649bb0a56ecSDave Jones #ifdef CONFIG_X86_POWERNOW_K7_ACPI
650bb0a56ecSDave Jones if (acpi_processor_perf) {
651b2f8dc4cSRafael J. Wysocki acpi_processor_unregister_performance(0);
652bb0a56ecSDave Jones free_cpumask_var(acpi_processor_perf->shared_cpu_map);
653bb0a56ecSDave Jones kfree(acpi_processor_perf);
654bb0a56ecSDave Jones }
655bb0a56ecSDave Jones #endif
656bb0a56ecSDave Jones
657bb0a56ecSDave Jones kfree(powernow_table);
658bb0a56ecSDave Jones return 0;
659bb0a56ecSDave Jones }
660bb0a56ecSDave Jones
661bb0a56ecSDave Jones static struct cpufreq_driver powernow_driver = {
662d63bd27fSViresh Kumar .verify = cpufreq_generic_frequency_table_verify,
6639c0ebcf7SViresh Kumar .target_index = powernow_target,
664bb0a56ecSDave Jones .get = powernow_get,
665bb0a56ecSDave Jones #ifdef CONFIG_X86_POWERNOW_K7_ACPI
666bb0a56ecSDave Jones .bios_limit = acpi_processor_get_bios_limit,
667bb0a56ecSDave Jones #endif
668bb0a56ecSDave Jones .init = powernow_cpu_init,
669bb0a56ecSDave Jones .exit = powernow_cpu_exit,
670bb0a56ecSDave Jones .name = "powernow-k7",
671d63bd27fSViresh Kumar .attr = cpufreq_generic_attr,
672bb0a56ecSDave Jones };
673bb0a56ecSDave Jones
powernow_init(void)674bb0a56ecSDave Jones static int __init powernow_init(void)
675bb0a56ecSDave Jones {
676bb0a56ecSDave Jones if (check_powernow() == 0)
677bb0a56ecSDave Jones return -ENODEV;
678bb0a56ecSDave Jones return cpufreq_register_driver(&powernow_driver);
679bb0a56ecSDave Jones }
680bb0a56ecSDave Jones
681bb0a56ecSDave Jones
powernow_exit(void)682bb0a56ecSDave Jones static void __exit powernow_exit(void)
683bb0a56ecSDave Jones {
684bb0a56ecSDave Jones cpufreq_unregister_driver(&powernow_driver);
685bb0a56ecSDave Jones }
686bb0a56ecSDave Jones
687bb0a56ecSDave Jones module_param(acpi_force, int, 0444);
688bb0a56ecSDave Jones MODULE_PARM_DESC(acpi_force, "Force ACPI to be used.");
689bb0a56ecSDave Jones
690d5e80b4bSDave Jones MODULE_AUTHOR("Dave Jones");
691bb0a56ecSDave Jones MODULE_DESCRIPTION("Powernow driver for AMD K7 processors.");
692bb0a56ecSDave Jones MODULE_LICENSE("GPL");
693bb0a56ecSDave Jones
694bb0a56ecSDave Jones late_initcall(powernow_init);
695bb0a56ecSDave Jones module_exit(powernow_exit);
696bb0a56ecSDave Jones
697