2
* (C) 2004-2006 Sebastian Witt <se.witt@gmx.net>
4
* Licensed under the terms of the GNU GPL License version 2.
5
* Based upon reverse engineered information
7
* BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
10
#include <linux/kernel.h>
11
#include <linux/module.h>
12
#include <linux/moduleparam.h>
13
#include <linux/init.h>
14
#include <linux/cpufreq.h>
15
#include <linux/pci.h>
16
#include <linux/delay.h>
18
#define NFORCE2_XTAL 25
19
#define NFORCE2_BOOTFSB 0x48
20
#define NFORCE2_PLLENABLE 0xa8
21
#define NFORCE2_PLLREG 0xa4
22
#define NFORCE2_PLLADR 0xa0
23
#define NFORCE2_PLL(mul, div) (0x100000 | (mul << 8) | div)
25
#define NFORCE2_MIN_FSB 50
26
#define NFORCE2_SAFE_DISTANCE 50
28
/* Delay in ms between FSB changes */
29
/* #define NFORCE2_DELAY 10 */
33
* FSB is changed using the chipset
35
static struct pci_dev *nforce2_dev;
43
* minimum and maximum FSB (= FSB at boot time)
48
MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
49
MODULE_DESCRIPTION("nForce2 FSB changing cpufreq driver");
50
MODULE_LICENSE("GPL");
52
module_param(fid, int, 0444);
53
module_param(min_fsb, int, 0444);
55
MODULE_PARM_DESC(fid, "CPU multiplier to use (11.5 = 115)");
56
MODULE_PARM_DESC(min_fsb,
57
"Minimum FSB to use, if not defined: current FSB - 50");
59
#define PFX "cpufreq-nforce2: "
62
* nforce2_calc_fsb - calculate FSB
65
* Calculates FSB from PLL value
67
static int nforce2_calc_fsb(int pll)
69
unsigned char mul, div;
71
mul = (pll >> 8) & 0xff;
75
return NFORCE2_XTAL * mul / div;
81
* nforce2_calc_pll - calculate PLL value
84
* Calculate PLL value for given FSB
86
static int nforce2_calc_pll(unsigned int fsb)
88
unsigned char xmul, xdiv;
89
unsigned char mul = 0, div = 0;
92
/* Try to calculate multiplier and divider up to 4 times */
93
while (((mul == 0) || (div == 0)) && (tried <= 3)) {
94
for (xdiv = 2; xdiv <= 0x80; xdiv++)
95
for (xmul = 1; xmul <= 0xfe; xmul++)
96
if (nforce2_calc_fsb(NFORCE2_PLL(xmul, xdiv)) ==
104
if ((mul == 0) || (div == 0))
107
return NFORCE2_PLL(mul, div);
111
* nforce2_write_pll - write PLL value to chipset
114
* Writes new FSB PLL value to chipset
116
static void nforce2_write_pll(int pll)
120
/* Set the pll addr. to 0x00 */
121
pci_write_config_dword(nforce2_dev, NFORCE2_PLLADR, 0);
123
/* Now write the value in all 64 registers */
124
for (temp = 0; temp <= 0x3f; temp++)
125
pci_write_config_dword(nforce2_dev, NFORCE2_PLLREG, pll);
131
* nforce2_fsb_read - Read FSB
133
* Read FSB from chipset
134
* If bootfsb != 0, return FSB at boot-time
136
static unsigned int nforce2_fsb_read(int bootfsb)
138
struct pci_dev *nforce2_sub5;
141
/* Get chipset boot FSB from subdevice 5 (FSB at boot-time) */
142
nforce2_sub5 = pci_get_subsys(PCI_VENDOR_ID_NVIDIA, 0x01EF,
143
PCI_ANY_ID, PCI_ANY_ID, NULL);
147
pci_read_config_dword(nforce2_sub5, NFORCE2_BOOTFSB, &fsb);
150
/* Check if PLL register is already set */
151
pci_read_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8 *)&temp);
153
if (bootfsb || !temp)
156
/* Use PLL register FSB value */
157
pci_read_config_dword(nforce2_dev, NFORCE2_PLLREG, &temp);
158
fsb = nforce2_calc_fsb(temp);
164
* nforce2_set_fsb - set new FSB
169
static int nforce2_set_fsb(unsigned int fsb)
176
if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) {
177
printk(KERN_ERR PFX "FSB %d is out of range!\n", fsb);
181
tfsb = nforce2_fsb_read(0);
183
printk(KERN_ERR PFX "Error while reading the FSB\n");
187
/* First write? Then set actual value */
188
pci_read_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8 *)&temp);
190
pll = nforce2_calc_pll(tfsb);
195
nforce2_write_pll(pll);
198
/* Enable write access */
200
pci_write_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8)temp);
207
while ((tfsb != fsb) && (tfsb <= max_fsb) && (tfsb >= min_fsb)) {
213
/* Calculate the PLL reg. value */
214
pll = nforce2_calc_pll(tfsb);
218
nforce2_write_pll(pll);
220
mdelay(NFORCE2_DELAY);
225
pci_write_config_byte(nforce2_dev, NFORCE2_PLLADR, (u8)temp);
231
* nforce2_get - get the CPU frequency
234
* Returns the CPU frequency
236
static unsigned int nforce2_get(unsigned int cpu)
240
return nforce2_fsb_read(0) * fid * 100;
244
* nforce2_target - set a new CPUFreq policy
245
* @policy: new policy
246
* @target_freq: the target frequency
247
* @relation: how that frequency relates to achieved frequency
248
* (CPUFREQ_RELATION_L or CPUFREQ_RELATION_H)
250
* Sets a new CPUFreq policy.
252
static int nforce2_target(struct cpufreq_policy *policy,
253
unsigned int target_freq, unsigned int relation)
255
/* unsigned long flags; */
256
struct cpufreq_freqs freqs;
257
unsigned int target_fsb;
259
if ((target_freq > policy->max) || (target_freq < policy->min))
262
target_fsb = target_freq / (fid * 100);
264
freqs.old = nforce2_get(policy->cpu);
265
freqs.new = target_fsb * fid * 100;
266
freqs.cpu = 0; /* Only one CPU on nForce2 platforms */
268
if (freqs.old == freqs.new)
271
pr_debug("Old CPU frequency %d kHz, new %d kHz\n",
272
freqs.old, freqs.new);
274
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
277
/* local_irq_save(flags); */
279
if (nforce2_set_fsb(target_fsb) < 0)
280
printk(KERN_ERR PFX "Changing FSB to %d failed\n",
283
pr_debug("Changed FSB successfully to %d\n",
287
/* local_irq_restore(flags); */
289
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
295
* nforce2_verify - verifies a new CPUFreq policy
296
* @policy: new policy
298
static int nforce2_verify(struct cpufreq_policy *policy)
300
unsigned int fsb_pol_max;
302
fsb_pol_max = policy->max / (fid * 100);
304
if (policy->min < (fsb_pol_max * fid * 100))
305
policy->max = (fsb_pol_max + 1) * fid * 100;
307
cpufreq_verify_within_limits(policy,
308
policy->cpuinfo.min_freq,
309
policy->cpuinfo.max_freq);
313
static int nforce2_cpu_init(struct cpufreq_policy *policy)
318
/* capability check */
319
if (policy->cpu != 0)
322
/* Get current FSB */
323
fsb = nforce2_fsb_read(0);
328
/* FIX: Get FID from CPU */
331
printk(KERN_WARNING PFX
332
"cpu_khz not set, can't calculate multiplier!\n");
336
fid = cpu_khz / (fsb * 100);
347
printk(KERN_INFO PFX "FSB currently at %i MHz, FID %d.%d\n", fsb,
350
/* Set maximum FSB to FSB at boot time */
351
max_fsb = nforce2_fsb_read(1);
357
min_fsb = max_fsb - NFORCE2_SAFE_DISTANCE;
359
if (min_fsb < NFORCE2_MIN_FSB)
360
min_fsb = NFORCE2_MIN_FSB;
362
/* cpuinfo and default policy values */
363
policy->cpuinfo.min_freq = min_fsb * fid * 100;
364
policy->cpuinfo.max_freq = max_fsb * fid * 100;
365
policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
366
policy->cur = nforce2_get(policy->cpu);
367
policy->min = policy->cpuinfo.min_freq;
368
policy->max = policy->cpuinfo.max_freq;
373
static int nforce2_cpu_exit(struct cpufreq_policy *policy)
378
static struct cpufreq_driver nforce2_driver = {
380
.verify = nforce2_verify,
381
.target = nforce2_target,
383
.init = nforce2_cpu_init,
384
.exit = nforce2_cpu_exit,
385
.owner = THIS_MODULE,
389
* nforce2_detect_chipset - detect the Southbridge which contains FSB PLL logic
391
* Detects nForce2 A2 and C1 stepping
394
static int nforce2_detect_chipset(void)
396
nforce2_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
397
PCI_DEVICE_ID_NVIDIA_NFORCE2,
398
PCI_ANY_ID, PCI_ANY_ID, NULL);
400
if (nforce2_dev == NULL)
403
printk(KERN_INFO PFX "Detected nForce2 chipset revision %X\n",
404
nforce2_dev->revision);
406
"FSB changing is maybe unstable and can lead to "
407
"crashes and data loss.\n");
413
* nforce2_init - initializes the nForce2 CPUFreq driver
415
* Initializes the nForce2 FSB support. Returns -ENODEV on unsupported
416
* devices, -EINVAL on problems during initiatization, and zero on
419
static int __init nforce2_init(void)
421
/* TODO: do we need to detect the processor? */
424
if (nforce2_detect_chipset()) {
425
printk(KERN_INFO PFX "No nForce2 chipset.\n");
429
return cpufreq_register_driver(&nforce2_driver);
433
* nforce2_exit - unregisters cpufreq module
435
* Unregisters nForce2 FSB change support.
437
static void __exit nforce2_exit(void)
439
cpufreq_unregister_driver(&nforce2_driver);
442
module_init(nforce2_init);
443
module_exit(nforce2_exit);