Subversion Repositories shark

Rev

Rev 1059 | 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. */
1059 tullio 215
//static inline int transition_fid_vid(u32 reqfid, u32 reqvid)
216
static int transition_fid_vid(u32 reqfid, u32 reqvid)
770 mauro 217
{
218
        if (core_voltage_pre_transition(reqvid))
219
                return 1;
220
        if (core_frequency_transition(reqfid))
221
                return 1;
222
        if (core_voltage_post_transition(reqvid))
223
                return 1;
224
        if (query_current_values_with_pending_wait())
225
                return 1;
226
 
227
        if ((reqfid != currfid) || (reqvid != currvid)) {
228
                dprintk(KERN_ERR PFX "failed: req %x %x, curr %x %x\n",
229
                       reqfid, reqvid, currfid, currvid);
230
                return 1;
231
        }
232
 
233
        dprintk(KERN_INFO PFX
234
                "transitioned: new fid %x, vid %x\n", currfid, currvid);
235
        return 0;
236
}
237
 
238
/* Phase 1 - core voltage transition ... setup voltage */
1059 tullio 239
//static inline int core_voltage_pre_transition(u32 reqvid)
240
static int core_voltage_pre_transition(u32 reqvid)
770 mauro 241
{
242
        u32 rvosteps = rvo;
243
        u32 savefid = currfid;
244
 
245
        dprintk(KERN_DEBUG PFX
246
                "ph1: start, currfid %x, currvid %x, reqvid %x, rvo %x\n",
247
                currfid, currvid, reqvid, rvo);
248
 
249
        while (currvid > reqvid) {
250
                dprintk(KERN_DEBUG PFX "ph1: curr %x, req vid %x\n",
251
                        currvid, reqvid);
252
                if (decrease_vid_code_by_step(reqvid, vidmvs))
253
                        return 1;
254
        }
255
 
256
        while (rvosteps > 0) {
257
                if (currvid == 0) {
258
                        rvosteps = 0;
259
                } else {
260
                        dprintk(KERN_DEBUG PFX
261
                                "ph1: changing vid for rvo, req %x\n",
262
                                currvid - 1);
263
                        if (decrease_vid_code_by_step(currvid - 1, 1))
264
                                return 1;
265
                        rvosteps--;
266
                }
267
        }
268
 
269
        if (query_current_values_with_pending_wait())
270
                return 1;
271
 
272
        if (savefid != currfid) {
273
                dprintk(KERN_ERR PFX "ph1: err, currfid changed %x\n", currfid);
274
                return 1;
275
        }
276
 
277
        dprintk(KERN_DEBUG PFX "ph1: complete, currfid %x, currvid %x\n",
278
                currfid, currvid);
279
 
280
        return 0;
281
}
282
 
283
/* Phase 2 - core frequency transition */
284
static inline int core_frequency_transition(u32 reqfid)
285
{
286
        u32 vcoreqfid;
287
        u32 vcocurrfid;
288
        u32 vcofiddiff;
289
        u32 savevid = currvid;
290
 
291
        if ((reqfid < HI_FID_TABLE_BOTTOM) && (currfid < HI_FID_TABLE_BOTTOM)) {
292
                dprintk(KERN_ERR PFX "ph2: illegal lo-lo transition %x %x\n",
293
                       reqfid, currfid);
294
                return 1;
295
        }
296
 
297
        if (currfid == reqfid) {
298
                dprintk(KERN_ERR PFX "ph2: null fid transition %x\n", currfid);
299
                return 0;
300
        }
301
 
302
        dprintk(KERN_DEBUG PFX
303
                "ph2: starting, currfid %x, currvid %x, reqfid %x\n",
304
                currfid, currvid, reqfid);
305
 
306
        vcoreqfid = convert_fid_to_vco_fid(reqfid);
307
        vcocurrfid = convert_fid_to_vco_fid(currfid);
308
        vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
309
            : vcoreqfid - vcocurrfid;
310
 
311
        while (vcofiddiff > 2) {
312
                if (reqfid > currfid) {
313
                        if (currfid > LO_FID_TABLE_TOP) {
314
                                if (write_new_fid(currfid + 2)) {
315
                                        return 1;
316
                                }
317
                        } else {
318
                                if (write_new_fid
319
                                    (2 + convert_fid_to_vco_fid(currfid))) {
320
                                        return 1;
321
                                }
322
                        }
323
                } else {
324
                        if (write_new_fid(currfid - 2))
325
                                return 1;
326
                }
327
 
328
                vcocurrfid = convert_fid_to_vco_fid(currfid);
329
                vcofiddiff = vcocurrfid > vcoreqfid ? vcocurrfid - vcoreqfid
330
                    : vcoreqfid - vcocurrfid;
331
        }
332
 
333
        if (write_new_fid(reqfid))
334
                return 1;
335
        if (query_current_values_with_pending_wait())
336
                return 1;
337
 
338
        if (currfid != reqfid) {
339
                dprintk(KERN_ERR PFX
340
                       "ph2: mismatch, failed fid trans, curr %x, req %x\n",
341
                       currfid, reqfid);
342
                return 1;
343
        }
344
 
345
        if (savevid != currvid) {
346
                dprintk(KERN_ERR PFX "ph2: vid changed, save %x, curr %x\n",
347
                        savevid, currvid);
348
                return 1;
349
        }
350
 
351
        dprintk(KERN_DEBUG PFX "ph2: complete, currfid %x, currvid %x\n",
352
                currfid, currvid);
353
 
354
        return 0;
355
}
356
 
357
/* Phase 3 - core voltage transition flow ... jump to the final vid. */
358
static inline int core_voltage_post_transition(u32 reqvid)
359
{
360
        u32 savefid = currfid;
361
        u32 savereqvid = reqvid;
362
 
363
        dprintk(KERN_DEBUG PFX "ph3: starting, currfid %x, currvid %x\n",
364
                currfid, currvid);
365
 
366
        if (reqvid != currvid) {
367
                if (write_new_vid(reqvid))
368
                        return 1;
369
 
370
                if (savefid != currfid) {
371
                        dprintk(KERN_ERR PFX
372
                               "ph3: bad fid change, save %x, curr %x\n",
373
                               savefid, currfid);
374
                        return 1;
375
                }
376
 
377
                if (currvid != reqvid) {
378
                        dprintk(KERN_ERR PFX
379
                               "ph3: failed vid transition\n, req %x, curr %x",
380
                               reqvid, currvid);
381
                        return 1;
382
                }
383
        }
384
 
385
        if (query_current_values_with_pending_wait())
386
                return 1;
387
 
388
        if (savereqvid != currvid) {
389
                dprintk(KERN_ERR PFX "ph3: failed, currvid %x\n", currvid);
390
                return 1;
391
        }
392
 
393
        if (savefid != currfid) {
394
                dprintk(KERN_ERR PFX "ph3: failed, currfid changed %x\n",
395
                        currfid);
396
                return 1;
397
        }
398
 
399
        dprintk(KERN_DEBUG PFX "ph3: complete, currfid %x, currvid %x\n",
400
                currfid, currvid);
401
        return 0;
402
}
403
 
404
static inline int check_supported_cpu(void)
405
{
406
        struct cpuinfo_x86 *c = &new_cpu_data;
407
        u32 eax, ebx, ecx, edx;
408
 
409
        if (num_online_cpus() != 1) {
410
                dprintk(KERN_INFO PFX "multiprocessor systems not supported\n");
411
                return 0;
412
        }
413
 
414
        if (c->x86_vendor != X86_VENDOR_AMD)
415
                return 0;
416
 
417
        eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE);
418
        if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) ||
419
            ((eax & CPUID_XFAM) != CPUID_XFAM_K8) ||
420
            ((eax & CPUID_XMOD) > CPUID_XMOD_REV_E)) {
421
                dprintk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax);
422
                return 0;
423
        } else {
424
                dprintk(KERN_INFO PFX "AMD Athlon 64 or AMD Opteron processor found\n");
425
        }
426
 
427
        eax = cpuid_eax(CPUID_GET_MAX_CAPABILITIES);
428
        if (eax < CPUID_FREQ_VOLT_CAPABILITIES) {
429
                dprintk(KERN_INFO PFX "No freq change capabilities\n");
430
                return 0;
431
        }
432
 
433
        cpuid(CPUID_FREQ_VOLT_CAPABILITIES, &eax, &ebx, &ecx, &edx);
434
        if ((edx & P_STATE_TRANSITION_CAPABLE) != P_STATE_TRANSITION_CAPABLE) {
435
                dprintk(KERN_INFO PFX "Power state transitions not supported\n");
436
                return 0;
437
        }
438
 
439
        dprintk(KERN_INFO PFX "Found AMD Athlon 64 / Opteron processor\n");
440
        return 1;
441
}
442
 
443
static int check_pst_table(struct pst_s *pst, u8 maxvid)
444
{
445
        unsigned int j;
446
        u8 lastfid = 0xff;
447
 
448
        for (j = 0; j < numps; j++) {
449
                if (pst[j].vid > LEAST_VID) {
450
                        dprintk(KERN_ERR PFX "vid %d bad: %x\n", j, pst[j].vid);
451
                        return -EINVAL;
452
                }
453
                if (pst[j].vid < rvo) { /* vid + rvo >= 0 */
454
                        dprintk(KERN_ERR PFX "0 vid exceeded with pst %d\n", j);
455
                        return -ENODEV;
456
                }
457
                if (pst[j].vid < maxvid + rvo) { /* vid + rvo >= maxvid */
458
                        dprintk(KERN_ERR PFX "maxvid exceeded with pst %d\n", j);
459
                        return -ENODEV;
460
                }
461
                if ((pst[j].fid > MAX_FID)
462
                    || (pst[j].fid & 1)
463
                    || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) {
464
                        dprintk(KERN_ERR PFX "fid %d bad: %x\n", j, pst[j].fid);
465
                        return -EINVAL;
466
                }
467
                if (pst[j].fid < lastfid)
468
                        lastfid = pst[j].fid;
469
        }
470
        if (lastfid & 1) {
471
                dprintk(KERN_ERR PFX "lastfid invalid\n");
472
                return -EINVAL;
473
        }
474
        if (lastfid > LO_FID_TABLE_TOP)
475
                dprintk(KERN_INFO PFX "first fid not from lo freq table\n");
476
 
477
        return 0;
478
}
479
 
480
/* Find and validate the PSB/PST table in BIOS. */
481
static inline int find_psb_table(void)
482
{
483
        struct psb_s *psb;
484
        struct pst_s *pst;
485
        unsigned int i, j;
486
        u32 mvs;
487
        u8 maxvid;
488
 
489
        for (i = 0xc0000; i < 0xffff0; i += 0x10) {
490
                /* Scan BIOS looking for the signature. */
491
                /* It can not be at ffff0 - it is too big. */
492
 
493
                psb = phys_to_virt(i);
494
                if (memcmp(psb, PSB_ID_STRING, PSB_ID_STRING_LEN) != 0)
495
                        continue;
496
 
497
                dprintk(KERN_DEBUG PFX "found PSB header at %p\n", psb);
498
                dprintk(KERN_DEBUG PFX "table version: %x\n",
499
                                psb->tableversion);
500
                if (psb->tableversion != PSB_VERSION_1_4) {
501
                        dprintk(KERN_INFO PFX "PSB table is not v1.4\n");
502
                        return -ENODEV;
503
                }
504
 
505
                dprintk(KERN_DEBUG PFX "flags: %x\n", psb->flags1);
506
                if (psb->flags1) {
507
                        dprintk(KERN_ERR PFX "unknown flags\n");
508
                        return -ENODEV;
509
                }
510
 
511
                vstable = psb->voltagestabilizationtime;
512
                dprintk(KERN_INFO PFX "voltage stabilization time: %d(*20us)\n",
513
                       vstable);
514
 
515
                dprintk(KERN_DEBUG PFX "flags2: %x\n", psb->flags2);
516
                rvo = psb->flags2 & 3;
517
                irt = ((psb->flags2) >> 2) & 3;
518
                mvs = ((psb->flags2) >> 4) & 3;
519
                vidmvs = 1 << mvs;
520
                batps = ((psb->flags2) >> 6) & 3;
521
                if (batps)
522
                        dprintk(KERN_INFO PFX "only %d pstates on battery\n",
523
                                batps );
524
 
525
                dprintk(KERN_INFO PFX "ramp voltage offset: %d\n", rvo);
526
                dprintk(KERN_INFO PFX "isochronous relief time: %d\n", irt);
527
                dprintk(KERN_INFO PFX "maximum voltage step: %d - %x\n",
528
                        mvs, vidmvs);
529
 
530
                if (psb->numpst != 1) {
531
                        dprintk(KERN_ERR PFX "numpst must be 1\n");
532
                        return -ENODEV;
533
                }
534
 
535
                plllock = psb->plllocktime;
536
                dprintk(KERN_INFO PFX "plllocktime: %x (units 1us)\n",
537
                       psb->plllocktime);
538
                dprintk(KERN_INFO PFX "maxfid: %x\n", psb->maxfid);
539
                dprintk(KERN_INFO PFX "maxvid: %x\n", psb->maxvid);
540
                maxvid = psb->maxvid;
541
 
542
                numps = psb->numpstates;
543
                dprintk(KERN_INFO PFX "numpstates: %x\n", numps);
544
                if (numps < 2) {
545
                        dprintk(KERN_ERR PFX "no p states to transition\n");
546
                        return -ENODEV;
547
                }
548
 
549
                pst = (struct pst_s *)(psb + 1);
550
                if (check_pst_table(pst, maxvid))
551
                        return -EINVAL;
552
 
553
                ftbl = kmalloc((sizeof(struct cpufreq_frequency_table)
554
                                              * (numps + 1)), GFP_KERNEL);
555
                if (!ftbl) {
556
                        dprintk(KERN_ERR PFX "ftbl memory alloc failure\n");
557
                        return -ENOMEM;
558
                }
559
 
560
                for (j = 0; j < numps; j++) {
561
                        dprintk(KERN_INFO PFX "   %d : fid %x, vid %x\n", j,
562
                                       pst[j].fid, pst[j].vid);
563
 
564
                        ftbl[j].index = pst[j].fid; /* lower 8 bits */
565
                        ftbl[j].index |= (pst[j].vid << 8); /* upper 8 bits */
566
                        ftbl[j].frequency = find_khz_freq_from_fid(pst[j].fid);
567
                }
568
                ftbl[numps].frequency = CPUFREQ_TABLE_END;
569
                ftbl[numps].index = 0;
570
 
571
                if (query_current_values_with_pending_wait()) {
572
                        kfree(ftbl);
573
                        return 1;
574
                }
575
                dprintk(KERN_INFO PFX "cfid %x, cvid %x\n", currfid, currvid);
576
 
577
                for (j = 0; j < numps; j++)
578
                        if ((pst[j].fid == currfid) && (pst[j].vid == currvid))
579
                                        return (0);
580
                dprintk(KERN_ERR PFX "currfid/vid do not match PST, ignoring\n");
581
                return 0;
582
        }
583
 
584
        dprintk(KERN_ERR PFX "BIOS error - no PSB\n");
585
 
586
#if 0
587
        /* hack for machines without a PSB - hardcode 2.0/1.8/0.8 GHz  */
588
        /* use this hack at your own risk                             */
589
        vstable = 5;
590
        rvo = 2;
591
        irt = 2;
592
        mvs = 1;
593
        vidmvs = 1 << mvs;
594
        batps = numps = 3;
595
        plllock = 2;
596
 
597
        ftbl = kmalloc((sizeof(struct cpufreq_frequency_table)
598
                                              * (numps + 1)), GFP_KERNEL);
599
        if (!ftbl)
600
                return -ENOMEM;
601
 
602
        ftbl[0].index = 0x00;        /* 800 MHz */
603
        ftbl[0].index |= 0x12 << 8;  /* 1.100v */
604
 
605
        ftbl[0].frequency = find_khz_freq_from_fid( ftbl[0].index & 0x0f );
606
 
607
        ftbl[1].index = 0x0a;        /* 1.8 GHz */
608
        ftbl[1].index |= 0x03 << 8;  /* 1.475v */
609
 
610
        ftbl[1].frequency = find_khz_freq_from_fid( ftbl[1].index & 0x0f );
611
 
612
        ftbl[2].index = 0x0c;        /* 2.0 GHz */
613
        ftbl[2].index |= 0x02 << 8;  /* 1.500v */
614
 
615
        ftbl[2].frequency =  find_khz_freq_from_fid( ftbl[2].index & 0x0f );
616
 
617
        ftbl[numps].frequency = CPUFREQ_TABLE_END;
618
        ftbl[numps].index = 0;
619
 
620
        if (query_current_values_with_pending_wait()) {
621
                kfree(ftbl);
622
                return 1;
623
        }
624
        dprintk(KERN_INFO PFX "currfid %x, currvid %x\n",
625
               currfid, currvid);
626
 
627
        return 0;
628
#endif
629
 
630
        return -ENODEV;
631
}
632
 
633
/* Take a frequency, and issue the fid/vid transition command */
634
static inline int transition_frequency(unsigned int index)
635
{
636
        u32 fid;
637
        u32 vid;
638
        int res;
639
        struct cpufreq_freqs freqs;
640
 
641
        dprintk(KERN_DEBUG PFX "transition to index %u\n", index );
642
 
643
        /* fid are the lower 8 bits of the index we stored into
644
         * the cpufreq frequency table in find_psb_table, vid are
645
         * the upper 8 bits.
646
         */
647
 
648
        fid = ftbl[index].index & 0xFF;
649
        vid = (ftbl[index].index & 0xFF00) >> 8;
650
 
651
        dprintk(KERN_DEBUG PFX "matched fid %x, giving vid %x\n", fid, vid);
652
 
653
        if (query_current_values_with_pending_wait())
654
                return 1;
655
 
656
        if ((currvid == vid) && (currfid == fid)) {
657
                dprintk(KERN_DEBUG PFX "target matches curr (fid %x, vid %x)\n",
658
                        fid, vid);
659
                return 0;
660
        }
661
 
662
        if ((fid < HI_FID_TABLE_BOTTOM) && (currfid < HI_FID_TABLE_BOTTOM)) {
663
                dprintk(KERN_ERR PFX
664
                       "ignoring illegal change in lo freq table-%x to %x\n",
665
                       currfid, fid);
666
                return 1;
667
        }
668
 
669
        dprintk(KERN_DEBUG PFX "changing to fid %x, vid %x\n", fid, vid);
670
 
671
        freqs.cpu = 0;          /* only true because SMP not supported */
672
        freqs.old = find_freq_from_fid(currfid);
673
        freqs.new = find_freq_from_fid(fid);
674
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
675
 
676
        res = transition_fid_vid(fid, vid);
677
 
678
        freqs.new = find_freq_from_fid(currfid);
679
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
680
 
681
        return res;
682
}
683
 
684
/* Driver entry point to switch to the target frequency */
685
static int
686
drv_target(struct cpufreq_policy *pol, unsigned targfreq, unsigned relation)
687
{
688
        u32 checkfid = currfid;
689
        u32 checkvid = currvid;
690
        unsigned int newstate;
691
 
692
        if (pending_bit_stuck()) {
693
                dprintk(KERN_ERR PFX "failing targ, change pending bit set\n");
694
                return -EIO;
695
        }
696
 
697
        dprintk(KERN_DEBUG PFX "targ: %d kHz, min %d, max %d, relation %d\n",
698
                targfreq, pol->min, pol->max, relation);
699
 
700
        if (query_current_values_with_pending_wait())
701
                return -EIO;
702
        dprintk(KERN_DEBUG PFX "targ: curr fid %x, vid %x\n",
703
                currfid, currvid);
704
 
705
        if ((checkvid != currvid) || (checkfid != currfid)) {
706
                dprintk(KERN_ERR PFX "out of sync, fid %x %x, vid %x %x\n",
707
                       checkfid, currfid, checkvid, currvid);
708
        }
709
 
710
        if (cpufreq_frequency_table_target(pol, ftbl, targfreq, relation,
711
                                                &newstate))
712
                return -EINVAL;
713
 
714
        if (transition_frequency(newstate))
715
        {
716
                dprintk(KERN_ERR PFX "transition frequency failed\n");
717
                return 1;
718
        }
719
 
720
        pol->cur = find_khz_freq_from_fid(currfid);
721
        return 0;
722
}
723
 
724
/* Driver entry point to verify the policy and range of frequencies */
725
static int drv_verify(struct cpufreq_policy *pol)
726
{
727
        if (pending_bit_stuck()) {
728
                dprintk(KERN_ERR PFX "failing verify, change pending bit set\n");
729
                return -EIO;
730
        }
731
 
732
        return cpufreq_frequency_table_verify(pol, ftbl);
733
}
734
 
735
/* per CPU init entry point to the driver */
736
static int __init
737
drv_cpu_init(struct cpufreq_policy *pol)
738
{
739
        if (pol->cpu != 0) {
740
                dprintk(KERN_ERR PFX "init - cpu 0\n");
741
                return -ENODEV;
742
        }
743
 
744
        pol->governor = 0; //!!! CPUFREQ_DEFAULT_GOVERNOR;
745
 
746
        /* Take a crude guess here. */
747
        pol->cpuinfo.transition_latency = ((rvo + 8) * vstable * VST_UNITS_20US)
748
            + (3 * (1 << irt) * 10);
749
 
750
        if (query_current_values_with_pending_wait())
751
                return -EIO;
752
 
753
        pol->cur = find_khz_freq_from_fid(currfid);
754
        dprintk(KERN_DEBUG PFX "policy current frequency %d kHz\n", pol->cur);
755
 
756
        /* min/max the cpu is capable of */
757
        if (cpufreq_frequency_table_cpuinfo(pol, ftbl)) {
758
                dprintk(KERN_ERR PFX "invalid ftbl\n");
759
                kfree(ftbl);
760
                return -EINVAL;
761
        }
762
 
763
        /* Added by Nino */
764
        cpufreq_frequency_table_get_attr(ftbl, pol->cpu);
765
 
766
        dprintk(KERN_INFO PFX "init, curr fid %x vid %x\n", currfid, currvid);
767
        return 0;
768
}
769
 
770
 
771
static int __exit drv_cpu_exit (struct cpufreq_policy *pol)
772
{
773
        if (pol->cpu != 0)
774
                return -EINVAL;
775
 
776
        /* Added by Nino */
777
        cpufreq_frequency_table_put_attr(pol->cpu);
778
 
779
        kfree(ftbl);
780
 
781
        return 0;
782
}
783
 
784
static struct cpufreq_driver cpufreq_amd64_driver = {
785
        .verify = drv_verify,
786
        .target = drv_target,
787
        .init = drv_cpu_init,
788
        .exit = drv_cpu_exit,
789
        .name = "powernow-k8",
790
        .owner = THIS_MODULE
791
};
792
 
793
 
794
/* driver entry point for init */
795
/*static*/ int __init powernowk8_init(void)
796
{
797
        int rc;
798
 
799
        dprintk(KERN_INFO PFX VERSION "\n");
800
 
801
        if (check_supported_cpu() == 0)
802
                return -ENODEV;
803
 
804
        rc = find_psb_table();
805
        if (rc)
806
                return rc;
807
 
808
        if (pending_bit_stuck()) {
809
                dprintk(KERN_ERR PFX "failing init, change pending bit set\n");
810
                return -EIO;
811
        }
812
 
813
        return cpufreq_register_driver(&cpufreq_amd64_driver);
814
}
815
 
816
/* driver entry point for term */
817
/*static*/ void __exit powernowk8_exit(void)
818
{
819
        dprintk(KERN_INFO PFX "exit\n");
820
        cpufreq_unregister_driver(&cpufreq_amd64_driver);
821
}
822
 
823
MODULE_AUTHOR("Paul Devriendt <paul.devriendt@amd.com>");
824
MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver.");
825
MODULE_LICENSE("GPL");
826
 
827
module_init(powernowk8_init);
828
module_exit(powernowk8_exit);