Subversion Repositories shark

Rev

Rev 769 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
770 mauro 1
/*
2
 *   (c) 2003, 2004 Advanced Micro Devices, Inc.
3
 *  Your use of this code is subject to the terms and conditions of the
4
 *  GNU general public license version 2. See "../../../COPYING" or
5
 *  http://www.gnu.org/licenses/gpl.html
6
 *
7
 *  Support : paul.devriendt@amd.com
8
 *
9
 *  Based on the powernow-k7.c module written by Dave Jones.
10
 *  (C) 2003 Dave Jones <davej@codemonkey.ork.uk> on behalf of SuSE Labs
11
 *  Licensed under the terms of the GNU GPL License version 2.
12
 *  Based upon datasheets & sample CPUs kindly provided by AMD.
13
 *
14
 *  Valuable input gratefully received from Dave Jones, Pavel Machek, Dominik
15
 *  Brodowski, and others.
16
 *
17
 *  Processor information obtained from Chapter 9 (Power and Thermal Management)
18
 *  of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
19
 *  Opteron Processors" available for download from www.amd.com
20
 */
21
 
22
//#define DEBUG
23
 
24
#include <linux/kernel.h>
25
#include <linux/smp.h>
26
#include <linux/module.h>
27
#include <linux/init.h>
28
#include <linux/cpufreq.h>
29
#include <linux/slab.h>
30
#include <linux/string.h>
31
 
32
#include <asm/msr.h>
33
#include <asm/io.h>
34
#include <asm/delay.h>
35
 
36
#define PFX "powernow-k8: "
37
#define VERSION "version 1.00.12 - February 29, 2004"
38
#include "powernow-k8.h"
39
 
40
#ifdef DEBUG
41
#define dprintk(msg...) printk(msg)
42
#else
43
#define dprintk(msg...) do { } while(0)
44
#endif
45
 
46
static u32 vstable;      /* voltage stabalization time, units 20 us */
47
static u32 plllock;      /* pll lock time, units 1 us */
48
static u32 numps;        /* number of p-states */
49
static u32 batps;        /* number of p-states supported on battery */
50
static u32 rvo;          /* ramp voltage offset */
51
static u32 irt;          /* isochronous relief time */
52
static u32 vidmvs;       /* usable value calculated from mvs */
53
static u32 currvid;      /* keep track of the current fid / vid */
54
static u32 currfid;
55
static struct cpufreq_frequency_table *ftbl;
56
 
57
 
58
/* Return a frequency in MHz, given an input fid */
59
static inline u32 find_freq_from_fid(u32 fid)
60
{
61
        return 800 + (fid * 100);
62
}
63
 
64
/* Return a frequency in KHz, given an input fid */
65
static inline u32 find_khz_freq_from_fid(u32 fid)
66
{
67
        return 1000 * (800 + (fid * 100));
68
}
69
 
70
/* Return the vco fid for an input fid */
71
static u32 convert_fid_to_vco_fid(u32 fid)
72
{
73
        if (fid < HI_FID_TABLE_BOTTOM) {
74
                return 8 + (2 * fid);
75
        } else {
76
                return fid;
77
        }
78
}
79
 
80
/*
81
 * Return 1 if the pending bit is set. Unless we just instructed the processor
82
 * to transition to a new state, seeing this bit set is really bad news.
83
 */
84
static inline int pending_bit_stuck(void)
85
{
86
        u32 lo;
87
        u32 hi;
88
 
89
        rdmsr(MSR_FIDVID_STATUS, lo, hi);
90
        return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0;
91
}
92
 
93
/*
94
 * Update the global current fid / vid values from the status msr. Returns
95
 * 1 on error.
96
 */
97
static int query_current_values_with_pending_wait(void)
98
{
99
        u32 lo;
100
        u32 hi;
101
        u32 i = 0;
102
 
103
        lo = MSR_S_LO_CHANGE_PENDING;
104
        while (lo & MSR_S_LO_CHANGE_PENDING) {
105
                if (i++ > 0x1000000) {
106
                        printk(KERN_ERR PFX "detected change pending stuck\n");
107
                        return 1;
108
                }
109
                rdmsr(MSR_FIDVID_STATUS, lo, hi);
110
        }
111
 
112
        currvid = hi & MSR_S_HI_CURRENT_VID;
113
        currfid = lo & MSR_S_LO_CURRENT_FID;
114
 
115
        return 0;
116
}
117
 
118
/* the isochronous relief time */
119
static inline void count_off_irt(void)
120
{
121
        udelay((1 << irt) * 10);
122
        return;
123
}
124
 
125
/* the voltage stabalization time */
126
static inline void count_off_vst(void)
127
{
128
        udelay(vstable * VST_UNITS_20US);
129
        return;
130
}
131
 
132
/* write the new fid value along with the other control fields to the msr */
133
static int write_new_fid(u32 fid)
134
{
135
        u32 lo;
136
        u32 savevid = currvid;
137
 
138
        if ((fid & INVALID_FID_MASK) || (currvid & INVALID_VID_MASK)) {
139
                dprintk(KERN_ERR PFX "internal error - overflow on fid write\n");
140
                return 1;
141
        }
142
 
143
        lo = fid | (currvid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID;
144
        dprintk(KERN_DEBUG PFX "writing fid %x, lo %x, hi %x\n",
145
                fid, lo, plllock * PLL_LOCK_CONVERSION);
146
        wrmsr(MSR_FIDVID_CTL, lo, plllock * PLL_LOCK_CONVERSION);
147
        if (query_current_values_with_pending_wait())
148
                return 1;
149
        count_off_irt();
150
 
151
        if (savevid != currvid) {
152
                dprintk(KERN_ERR PFX "vid change on fid trans, old %x, new %x\n",
153
                       savevid, currvid);
154
                return 1;
155
        }
156
 
157
        if (fid != currfid) {
158
                dprintk(KERN_ERR PFX "fid trans failed, fid %x, curr %x\n", fid,
159
                       currfid);
160
                return 1;
161
        }
162
 
163
        return 0;
164
}
165
 
166
/* Write a new vid to the hardware */
167
static int write_new_vid(u32 vid)
168
{
169
        u32 lo;
170
        u32 savefid = currfid;
171
 
172
        if ((currfid & INVALID_FID_MASK) || (vid & INVALID_VID_MASK)) {
173
                dprintk(KERN_ERR PFX "internal error - overflow on vid write\n");
174
                return 1;
175
        }
176
 
177
        lo = currfid | (vid << MSR_C_LO_VID_SHIFT) | MSR_C_LO_INIT_FID_VID;
178
        dprintk(KERN_DEBUG PFX "writing vid %x, lo %x, hi %x\n",
179
                vid, lo, STOP_GRANT_5NS);
180
        wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS);
181
        if (query_current_values_with_pending_wait())
182
                return 1;
183
 
184
        if (savefid != currfid) {
185
                dprintk(KERN_ERR PFX "fid changed on vid trans, old %x new %x\n",
186
                       savefid, currfid);
187
                return 1;
188
        }
189
 
190
        if (vid != currvid) {
191
                dprintk(KERN_ERR PFX "vid trans failed, vid %x, curr %x\n", vid,
192
                       currvid);
193
                return 1;
194
        }
195
 
196
        return 0;
197
}
198
 
199
/*
200
 * Reduce the vid by the max of step or reqvid.
201
 * Decreasing vid codes represent increasing voltages :
202
 * vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off.
203
 */
204
static int decrease_vid_code_by_step(u32 reqvid, u32 step)
205
{
206
        if ((currvid - reqvid) > step)
207
                reqvid = currvid - step;
208
        if (write_new_vid(reqvid))
209
                return 1;
210
        count_off_vst();
211
        return 0;
212
}
213
 
214
/* Change the fid and vid, by the 3 phases. */
215
static inline int transition_fid_vid(u32 reqfid, u32 reqvid)
216
{
217
        if (core_voltage_pre_transition(reqvid))
218
                return 1;
219
        if (core_frequency_transition(reqfid))
220
                return 1;
221
        if (core_voltage_post_transition(reqvid))
222
                return 1;
223
        if (query_current_values_with_pending_wait())
224
                return 1;
225
 
226
        if ((reqfid != currfid) || (reqvid != currvid)) {
227
                dprintk(KERN_ERR PFX "failed: req %x %x, curr %x %x\n",
228
                       reqfid, reqvid, currfid, currvid);
229
                return 1;
230
        }
231
 
232
        dprintk(KERN_INFO PFX
233
                "transitioned: new fid %x, vid %x\n", currfid, currvid);
234
        return 0;
235
}
236
 
237
/* Phase 1 - core voltage transition ... setup voltage */
238
static inline int core_voltage_pre_transition(u32 reqvid)
239
{
240
        u32 rvosteps = rvo;
241
        u32 savefid = currfid;
242
 
243
        dprintk(KERN_DEBUG PFX
244
                "ph1: start, currfid %x, currvid %x, reqvid %x, rvo %x\n",
245
                currfid, currvid, reqvid, rvo);
246
 
247
        while (currvid > reqvid) {
248
                dprintk(KERN_DEBUG PFX "ph1: curr %x, req vid %x\n",
249
                        currvid, reqvid);
250
                if (decrease_vid_code_by_step(reqvid, vidmvs))
251
                        return 1;
252
        }
253
 
254
        while (rvosteps > 0) {
255
                if (currvid == 0) {
256
                        rvosteps = 0;
257
                } else {
258
                        dprintk(KERN_DEBUG PFX
259
                                "ph1: changing vid for rvo, req %x\n",
260
                                currvid - 1);
261
                        if (decrease_vid_code_by_step(currvid - 1, 1))
262
                                return 1;
263
                        rvosteps--;
264
                }
265
        }
266
 
267
        if (query_current_values_with_pending_wait())
268
                return 1;
269
 
270
        if (savefid != currfid) {
271
                dprintk(KERN_ERR PFX "ph1: err, currfid changed %x\n", currfid);
272
                return 1;
273
        }
274
 
275
        dprintk(KERN_DEBUG PFX "ph1: complete, currfid %x, currvid %x\n",
276
                currfid, currvid);
277
 
278
        return 0;
279
}
280
 
281
/* Phase 2 - core frequency transition */
282
static inline int core_frequency_transition(u32 reqfid)
283
{
284
        u32 vcoreqfid;
285
        u32 vcocurrfid;
286
        u32 vcofiddiff;
287
        u32 savevid = currvid;
288
 
289
        if ((reqfid < HI_FID_TABLE_BOTTOM) && (currfid < HI_FID_TABLE_BOTTOM)) {
290
                dprintk(KERN_ERR PFX "ph2: illegal lo-lo transition %x %x\n",
291
                       reqfid, currfid);
292
                return 1;
293
        }
294
 
295
        if (currfid == reqfid) {
296
                dprintk(KERN_ERR PFX "ph2: null fid transition %x\n", currfid);
297
                return 0;
298
        }
299
 
300
        dprintk(KERN_DEBUG PFX
301
                "ph2: starting, currfid %x, currvid %x, reqfid %x\n",
302
                currfid, currvid, reqfid);
303
 
304
        vcoreqfid = convert_fid_to_vco_fid(reqfid);
305
        vcocurrfid = convert_fid_to_vco_fid(currfid);
306
        vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
307
            : vcoreqfid - vcocurrfid;
308
 
309
        while (vcofiddiff > 2) {
310
                if (reqfid > currfid) {
311
                        if (currfid > LO_FID_TABLE_TOP) {
312
                                if (write_new_fid(currfid + 2)) {
313
                                        return 1;
314
                                }
315
                        } else {
316
                                if (write_new_fid
317
                                    (2 + convert_fid_to_vco_fid(currfid))) {
318
                                        return 1;
319
                                }
320
                        }
321
                } else {
322
                        if (write_new_fid(currfid - 2))
323
                                return 1;
324
                }
325
 
326
                vcocurrfid = convert_fid_to_vco_fid(currfid);
327
                vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
328
                    : vcoreqfid - vcocurrfid;
329
        }
330
 
331
        if (write_new_fid(reqfid))
332
                return 1;
333
        if (query_current_values_with_pending_wait())
334
                return 1;
335
 
336
        if (currfid != reqfid) {
337
                dprintk(KERN_ERR PFX
338
                       "ph2: mismatch, failed fid trans, curr %x, req %x\n",
339
                       currfid, reqfid);
340
                return 1;
341
        }
342
 
343
        if (savevid != currvid) {
344
                dprintk(KERN_ERR PFX "ph2: vid changed, save %x, curr %x\n",
345
                        savevid, currvid);
346
                return 1;
347
        }
348
 
349
        dprintk(KERN_DEBUG PFX "ph2: complete, currfid %x, currvid %x\n",
350
                currfid, currvid);
351
 
352
        return 0;
353
}
354
 
355
/* Phase 3 - core voltage transition flow ... jump to the final vid. */
356
static inline int core_voltage_post_transition(u32 reqvid)
357
{
358
        u32 savefid = currfid;
359
        u32 savereqvid = reqvid;
360
 
361
        dprintk(KERN_DEBUG PFX "ph3: starting, currfid %x, currvid %x\n",
362
                currfid, currvid);
363
 
364
        if (reqvid != currvid) {
365
                if (write_new_vid(reqvid))
366
                        return 1;
367
 
368
                if (savefid != currfid) {
369
                        dprintk(KERN_ERR PFX
370
                               "ph3: bad fid change, save %x, curr %x\n",
371
                               savefid, currfid);
372
                        return 1;
373
                }
374
 
375
                if (currvid != reqvid) {
376
                        dprintk(KERN_ERR PFX
377
                               "ph3: failed vid transition\n, req %x, curr %x",
378
                               reqvid, currvid);
379
                        return 1;
380
                }
381
        }
382
 
383
        if (query_current_values_with_pending_wait())
384
                return 1;
385
 
386
        if (savereqvid != currvid) {
387
                dprintk(KERN_ERR PFX "ph3: failed, currvid %x\n", currvid);
388
                return 1;
389
        }
390
 
391
        if (savefid != currfid) {
392
                dprintk(KERN_ERR PFX "ph3: failed, currfid changed %x\n",
393
                        currfid);
394
                return 1;
395
        }
396
 
397
        dprintk(KERN_DEBUG PFX "ph3: complete, currfid %x, currvid %x\n",
398
                currfid, currvid);
399
        return 0;
400
}
401
 
402
static inline int check_supported_cpu(void)
403
{
404
        struct cpuinfo_x86 *c = &new_cpu_data;
405
        u32 eax, ebx, ecx, edx;
406
 
407
        if (num_online_cpus() != 1) {
408
                dprintk(KERN_INFO PFX "multiprocessor systems not supported\n");
409
                return 0;
410
        }
411
 
412
        if (c->x86_vendor != X86_VENDOR_AMD)
413
                return 0;
414
 
415
        eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
416
        if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
417
            ((eax & CPUID_XFAM) != CPUID_XFAM_K8) ||
418
            ((eax & CPUID_XMOD) > CPUID_XMOD_REV_E)) {
419
                dprintk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
420
                return 0;
421
        } else {
422
                dprintk(KERN_INFO PFX "AMD Athlon 64 or AMD Opteron processor found\n");
423
        }
424
 
425
        eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
426
        if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
427
                dprintk(KERN_INFO PFX "No freq change capabilities\n");
428
                return 0;
429
        }
430
 
431
        cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
432
        if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
433
                dprintk(KERN_INFO PFX "Power state transitions not supported\n");
434
                return 0;
435
        }
436
 
437
        dprintk(KERN_INFO PFX "Found AMD Athlon 64 / Opteron processor\n");
438
        return 1;
439
}
440
 
441
static int check_pst_table(struct pst_s *pst, u8 maxvid)
442
{
443
        unsigned int j;
444
        u8 lastfid = 0xff;
445
 
446
        for (j = 0; j < numps; j++) {
447
                if (pst[j].vid > LEAST_VID) {
448
                        dprintk(KERN_ERR PFX "vid %d bad: %x\n", j, pst[j].vid);
449
                        return -EINVAL;
450
                }
451
                if (pst[j].vid < rvo) { /* vid + rvo >= 0 */
452
                        dprintk(KERN_ERR PFX "0 vid exceeded with pst %d\n", j);
453
                        return -ENODEV;
454
                }
455
                if (pst[j].vid < maxvid + rvo) { /* vid + rvo >= maxvid */
456
                        dprintk(KERN_ERR PFX "maxvid exceeded with pst %d\n", j);
457
                        return -ENODEV;
458
                }
459
                if ((pst[j].fid > MAX_FID)
460
                    || (pst[j].fid & 1)
461
                    || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) {
462
                        dprintk(KERN_ERR PFX "fid %d bad: %x\n", j, pst[j].fid);
463
                        return -EINVAL;
464
                }
465
                if (pst[j].fid < lastfid)
466
                        lastfid = pst[j].fid;
467
        }
468
        if (lastfid & 1) {
469
                dprintk(KERN_ERR PFX "lastfid invalid\n");
470
                return -EINVAL;
471
        }
472
        if (lastfid > LO_FID_TABLE_TOP)
473
                dprintk(KERN_INFO PFX "first fid not from lo freq table\n");
474
 
475
        return 0;
476
}
477
 
478
/* Find and validate the PSB/PST table in BIOS. */
479
static inline int find_psb_table(void)
480
{
481
        struct psb_s *psb;
482
        struct pst_s *pst;
483
        unsigned int i, j;
484
        u32 mvs;
485
        u8 maxvid;
486
 
487
        for (i = 0xc0000; i < 0xffff0; i += 0x10) {
488
                /* Scan BIOS looking for the signature. */
489
                /* It can not be at ffff0 - it is too big. */
490
 
491
                psb = phys_to_virt(i);
492
                if (memcmp(psb, PSB_ID_STRING, PSB_ID_STRING_LEN) != 0)
493
                        continue;
494
 
495
                dprintk(KERN_DEBUG PFX "found PSB header at %p\n", psb);
496
                dprintk(KERN_DEBUG PFX "table version: %x\n",
497
                                psb->tableversion);
498
                if (psb->tableversion != PSB_VERSION_1_4) {
499
                        dprintk(KERN_INFO PFX "PSB table is not v1.4\n");
500
                        return -ENODEV;
501
                }
502
 
503
                dprintk(KERN_DEBUG PFX "flags: %x\n", psb->flags1);
504
                if (psb->flags1) {
505
                        dprintk(KERN_ERR PFX "unknown flags\n");
506
                        return -ENODEV;
507
                }
508
 
509
                vstable = psb->voltagestabilizationtime;
510
                dprintk(KERN_INFO PFX "voltage stabilization time: %d(*20us)\n",
511
                       vstable);
512
 
513
                dprintk(KERN_DEBUG PFX "flags2: %x\n", psb->flags2);
514
                rvo = psb->flags2 & 3;
515
                irt = ((psb->flags2) >> 2) & 3;
516
                mvs = ((psb->flags2) >> 4) & 3;
517
                vidmvs = 1 << mvs;
518
                batps = ((psb->flags2) >> 6) & 3;
519
                if (batps)
520
                        dprintk(KERN_INFO PFX "only %d pstates on battery\n",
521
                                batps );
522
 
523
                dprintk(KERN_INFO PFX "ramp voltage offset: %d\n", rvo);
524
                dprintk(KERN_INFO PFX "isochronous relief time: %d\n", irt);
525
                dprintk(KERN_INFO PFX "maximum voltage step: %d - %x\n",
526
                        mvs, vidmvs);
527
 
528
                if (psb->numpst != 1) {
529
                        dprintk(KERN_ERR PFX "numpst must be 1\n");
530
                        return -ENODEV;
531
                }
532
 
533
                plllock = psb->plllocktime;
534
                dprintk(KERN_INFO PFX "plllocktime: %x (units 1us)\n",
535
                       psb->plllocktime);
536
                dprintk(KERN_INFO PFX "maxfid: %x\n", psb->maxfid);
537
                dprintk(KERN_INFO PFX "maxvid: %x\n", psb->maxvid);
538
                maxvid = psb->maxvid;
539
 
540
                numps = psb->numpstates;
541
                dprintk(KERN_INFO PFX "numpstates: %x\n", numps);
542
                if (numps < 2) {
543
                        dprintk(KERN_ERR PFX "no p states to transition\n");
544
                        return -ENODEV;
545
                }
546
 
547
                pst = (struct pst_s *)(psb + 1);
548
                if (check_pst_table(pst, maxvid))
549
                        return -EINVAL;
550
 
551
                ftbl = kmalloc((sizeof(struct cpufreq_frequency_table)
552
                                              * (numps + 1)), GFP_KERNEL);
553
                if (!ftbl) {
554
                        dprintk(KERN_ERR PFX "ftbl memory alloc failure\n");
555
                        return -ENOMEM;
556
                }
557
 
558
                for (j = 0; j < numps; j++) {
559
                        dprintk(KERN_INFO PFX "   %d : fid %x, vid %x\n", j,
560
                                       pst[j].fid, pst[j].vid);
561
 
562
                        ftbl[j].index = pst[j].fid; /* lower 8 bits */
563
                        ftbl[j].index |= (pst[j].vid << 8); /* upper 8 bits */
564
                        ftbl[j].frequency = find_khz_freq_from_fid(pst[j].fid);
565
                }
566
                ftbl[numps].frequency = CPUFREQ_TABLE_END;
567
                ftbl[numps].index = 0;
568
 
569
                if (query_current_values_with_pending_wait()) {
570
                        kfree(ftbl);
571
                        return 1;
572
                }
573
                dprintk(KERN_INFO PFX "cfid %x, cvid %x\n", currfid, currvid);
574
 
575
                for (j = 0; j < numps; j++)
576
                        if ((pst[j].fid == currfid) && (pst[j].vid == currvid))
577
                                        return (0);
578
                dprintk(KERN_ERR PFX "currfid/vid do not match PST, ignoring\n");
579
                return 0;
580
        }
581
 
582
        dprintk(KERN_ERR PFX "BIOS error - no PSB\n");
583
 
584
#if 0
585
        /* hack for machines without a PSB - hardcode 2.0/1.8/0.8 GHz  */
586
        /* use this hack at your own risk                             */
587
        vstable = 5;
588
        rvo = 2;
589
        irt = 2;
590
        mvs = 1;
591
        vidmvs = 1 << mvs;
592
        batps = numps = 3;
593
        plllock = 2;
594
 
595
        ftbl = kmalloc((sizeof(struct cpufreq_frequency_table)
596
                                              * (numps + 1)), GFP_KERNEL);
597
        if (!ftbl)
598
                return -ENOMEM;
599
 
600
        ftbl[0].index = 0x00;        /* 800 MHz */
601
        ftbl[0].index |= 0x12 << 8;  /* 1.100v */
602
 
603
        ftbl[0].frequency = find_khz_freq_from_fid( ftbl[0].index & 0x0f );
604
 
605
        ftbl[1].index = 0x0a;        /* 1.8 GHz */
606
        ftbl[1].index |= 0x03 << 8;  /* 1.475v */
607
 
608
        ftbl[1].frequency = find_khz_freq_from_fid( ftbl[1].index & 0x0f );
609
 
610
        ftbl[2].index = 0x0c;        /* 2.0 GHz */
611
        ftbl[2].index |= 0x02 << 8;  /* 1.500v */
612
 
613
        ftbl[2].frequency =  find_khz_freq_from_fid( ftbl[2].index & 0x0f );
614
 
615
        ftbl[numps].frequency = CPUFREQ_TABLE_END;
616
        ftbl[numps].index = 0;
617
 
618
        if (query_current_values_with_pending_wait()) {
619
                kfree(ftbl);
620
                return 1;
621
        }
622
        dprintk(KERN_INFO PFX "currfid %x, currvid %x\n",
623
               currfid, currvid);
624
 
625
        return 0;
626
#endif
627
 
628
        return -ENODEV;
629
}
630
 
631
/* Take a frequency, and issue the fid/vid transition command */
632
static inline int transition_frequency(unsigned int index)
633
{
634
        u32 fid;
635
        u32 vid;
636
        int res;
637
        struct cpufreq_freqs freqs;
638
 
639
        dprintk(KERN_DEBUG PFX "transition to index %u\n", index );
640
 
641
        /* fid are the lower 8 bits of the index we stored into
642
         * the cpufreq frequency table in find_psb_table, vid are
643
         * the upper 8 bits.
644
         */
645
 
646
        fid = ftbl[index].index & 0xFF;
647
        vid = (ftbl[index].index & 0xFF00) >> 8;
648
 
649
        dprintk(KERN_DEBUG PFX "matched fid %x, giving vid %x\n", fid, vid);
650
 
651
        if (query_current_values_with_pending_wait())
652
                return 1;
653
 
654
        if ((currvid == vid) && (currfid == fid)) {
655
                dprintk(KERN_DEBUG PFX "target matches curr (fid %x, vid %x)\n",
656
                        fid, vid);
657
                return 0;
658
        }
659
 
660
        if ((fid < HI_FID_TABLE_BOTTOM) && (currfid < HI_FID_TABLE_BOTTOM)) {
661
                dprintk(KERN_ERR PFX
662
                       "ignoring illegal change in lo freq table-%x to %x\n",
663
                       currfid, fid);
664
                return 1;
665
        }
666
 
667
        dprintk(KERN_DEBUG PFX "changing to fid %x, vid %x\n", fid, vid);
668
 
669
        freqs.cpu = 0;          /* only true because SMP not supported */
670
        freqs.old = find_freq_from_fid(currfid);
671
        freqs.new = find_freq_from_fid(fid);
672
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
673
 
674
        res = transition_fid_vid(fid, vid);
675
 
676
        freqs.new = find_freq_from_fid(currfid);
677
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
678
 
679
        return res;
680
}
681
 
682
/* Driver entry point to switch to the target frequency */
683
static int
684
drv_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
685
{
686
        u32 checkfid = currfid;
687
        u32 checkvid = currvid;
688
        unsigned int newstate;
689
 
690
        if (pending_bit_stuck()) {
691
                dprintk(KERN_ERR PFX "failing targ, change pending bit set\n");
692
                return -EIO;
693
        }
694
 
695
        dprintk(KERN_DEBUG PFX "targ: %d kHz, min %d, max %d, relation %d\n",
696
                targfreq, pol->min, pol->max, relation);
697
 
698
        if (query_current_values_with_pending_wait())
699
                return -EIO;
700
        dprintk(KERN_DEBUG PFX "targ: curr fid %x, vid %x\n",
701
                currfid, currvid);
702
 
703
        if ((checkvid != currvid) || (checkfid != currfid)) {
704
                dprintk(KERN_ERR PFX "out of sync, fid %x %x, vid %x %x\n",
705
                       checkfid, currfid, checkvid, currvid);
706
        }
707
 
708
        if (cpufreq_frequency_table_target(pol, ftbl, targfreq, relation,
709
                                                &newstate))
710
                return -EINVAL;
711
 
712
        if (transition_frequency(newstate))
713
        {
714
                dprintk(KERN_ERR PFX "transition frequency failed\n");
715
                return 1;
716
        }
717
 
718
        pol->cur = find_khz_freq_from_fid(currfid);
719
        return 0;
720
}
721
 
722
/* Driver entry point to verify the policy and range of frequencies */
723
static int drv_verify(struct cpufreq_policy *pol)
724
{
725
        if (pending_bit_stuck()) {
726
                dprintk(KERN_ERR PFX "failing verify, change pending bit set\n");
727
                return -EIO;
728
        }
729
 
730
        return cpufreq_frequency_table_verify(pol, ftbl);
731
}
732
 
733
/* per CPU init entry point to the driver */
734
static int __init
735
drv_cpu_init(struct cpufreq_policy *pol)
736
{
737
        if (pol->cpu != 0) {
738
                dprintk(KERN_ERR PFX "init - cpu 0\n");
739
                return -ENODEV;
740
        }
741
 
742
        pol->governor = 0; //!!! CPUFREQ_DEFAULT_GOVERNOR;
743
 
744
        /* Take a crude guess here. */
745
        pol->cpuinfo.transition_latency = ((rvo + 8) * vstable * VST_UNITS_20US)
746
            + (3 * (1 << irt) * 10);
747
 
748
        if (query_current_values_with_pending_wait())
749
                return -EIO;
750
 
751
        pol->cur = find_khz_freq_from_fid(currfid);
752
        dprintk(KERN_DEBUG PFX "policy current frequency %d kHz\n", pol->cur);
753
 
754
        /* min/max the cpu is capable of */
755
        if (cpufreq_frequency_table_cpuinfo(pol, ftbl)) {
756
                dprintk(KERN_ERR PFX "invalid ftbl\n");
757
                kfree(ftbl);
758
                return -EINVAL;
759
        }
760
 
761
        /* Added by Nino */
762
        cpufreq_frequency_table_get_attr(ftbl, pol->cpu);
763
 
764
        dprintk(KERN_INFO PFX "init, curr fid %x vid %x\n", currfid, currvid);
765
        return 0;
766
}
767
 
768
 
769
static int __exit drv_cpu_exit (struct cpufreq_policy *pol)
770
{
771
        if (pol->cpu != 0)
772
                return -EINVAL;
773
 
774
        /* Added by Nino */
775
        cpufreq_frequency_table_put_attr(pol->cpu);
776
 
777
        kfree(ftbl);
778
 
779
        return 0;
780
}
781
 
782
static struct cpufreq_driver cpufreq_amd64_driver = {
783
        .verify = drv_verify,
784
        .target = drv_target,
785
        .init = drv_cpu_init,
786
        .exit = drv_cpu_exit,
787
        .name = "powernow-k8",
788
        .owner = THIS_MODULE
789
};
790
 
791
 
792
/* driver entry point for init */
793
/*static*/ int __init powernowk8_init(void)
794
{
795
        int rc;
796
 
797
        dprintk(KERN_INFO PFX VERSION "\n");
798
 
799
        if (check_supported_cpu() == 0)
800
                return -ENODEV;
801
 
802
        rc = find_psb_table();
803
        if (rc)
804
                return rc;
805
 
806
        if (pending_bit_stuck()) {
807
                dprintk(KERN_ERR PFX "failing init, change pending bit set\n");
808
                return -EIO;
809
        }
810
 
811
        return cpufreq_register_driver(&cpufreq_amd64_driver);
812
}
813
 
814
/* driver entry point for term */
815
/*static*/ void __exit powernowk8_exit(void)
816
{
817
        dprintk(KERN_INFO PFX "exit\n");
818
        cpufreq_unregister_driver(&cpufreq_amd64_driver);
819
}
820
 
821
MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>");
822
MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
823
MODULE_LICENSE("GPL");
824
 
825
module_init(powernowk8_init);
826
module_exit(powernowk8_exit);