Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpufreq-nforce2.c
Go to the documentation of this file.
1 /*
2  * (C) 2004-2006 Sebastian Witt <[email protected]>
3  *
4  * Licensed under the terms of the GNU GPL License version 2.
5  * Based upon reverse engineered information
6  *
7  * BIG FAT DISCLAIMER: Work in progress code. Possibly *dangerous*
8  */
9 
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>
17 
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)
24 
25 #define NFORCE2_MIN_FSB 50
26 #define NFORCE2_SAFE_DISTANCE 50
27 
28 /* Delay in ms between FSB changes */
29 /* #define NFORCE2_DELAY 10 */
30 
31 /*
32  * nforce2_chipset:
33  * FSB is changed using the chipset
34  */
35 static struct pci_dev *nforce2_dev;
36 
37 /* fid:
38  * multiplier * 10
39  */
40 static int fid;
41 
42 /* min_fsb, max_fsb:
43  * minimum and maximum FSB (= FSB at boot time)
44  */
45 static int min_fsb;
46 static int max_fsb;
47 
48 MODULE_AUTHOR("Sebastian Witt <[email protected]>");
49 MODULE_DESCRIPTION("nForce2 FSB changing cpufreq driver");
50 MODULE_LICENSE("GPL");
51 
52 module_param(fid, int, 0444);
53 module_param(min_fsb, int, 0444);
54 
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");
58 
59 #define PFX "cpufreq-nforce2: "
60 
67 static int nforce2_calc_fsb(int pll)
68 {
69  unsigned char mul, div;
70 
71  mul = (pll >> 8) & 0xff;
72  div = pll & 0xff;
73 
74  if (div > 0)
75  return NFORCE2_XTAL * mul / div;
76 
77  return 0;
78 }
79 
86 static int nforce2_calc_pll(unsigned int fsb)
87 {
88  unsigned char xmul, xdiv;
89  unsigned char mul = 0, div = 0;
90  int tried = 0;
91 
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)) ==
97  fsb + tried) {
98  mul = xmul;
99  div = xdiv;
100  }
101  tried++;
102  }
103 
104  if ((mul == 0) || (div == 0))
105  return -1;
106 
107  return NFORCE2_PLL(mul, div);
108 }
109 
116 static void nforce2_write_pll(int pll)
117 {
118  int temp;
119 
120  /* Set the pll addr. to 0x00 */
121  pci_write_config_dword(nforce2_dev, NFORCE2_PLLADR, 0);
122 
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);
126 
127  return;
128 }
129 
136 static unsigned int nforce2_fsb_read(int bootfsb)
137 {
138  struct pci_dev *nforce2_sub5;
139  u32 fsb, temp = 0;
140 
141  /* Get chipset boot FSB from subdevice 5 (FSB at boot-time) */
142  nforce2_sub5 = pci_get_subsys(PCI_VENDOR_ID_NVIDIA, 0x01EF,
144  if (!nforce2_sub5)
145  return 0;
146 
147  pci_read_config_dword(nforce2_sub5, NFORCE2_BOOTFSB, &fsb);
148  fsb /= 1000000;
149 
150  /* Check if PLL register is already set */
151  pci_read_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8 *)&temp);
152 
153  if (bootfsb || !temp)
154  return fsb;
155 
156  /* Use PLL register FSB value */
157  pci_read_config_dword(nforce2_dev, NFORCE2_PLLREG, &temp);
158  fsb = nforce2_calc_fsb(temp);
159 
160  return fsb;
161 }
162 
169 static int nforce2_set_fsb(unsigned int fsb)
170 {
171  u32 temp = 0;
172  unsigned int tfsb;
173  int diff;
174  int pll = 0;
175 
176  if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) {
177  printk(KERN_ERR PFX "FSB %d is out of range!\n", fsb);
178  return -EINVAL;
179  }
180 
181  tfsb = nforce2_fsb_read(0);
182  if (!tfsb) {
183  printk(KERN_ERR PFX "Error while reading the FSB\n");
184  return -EINVAL;
185  }
186 
187  /* First write? Then set actual value */
188  pci_read_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8 *)&temp);
189  if (!temp) {
190  pll = nforce2_calc_pll(tfsb);
191 
192  if (pll < 0)
193  return -EINVAL;
194 
195  nforce2_write_pll(pll);
196  }
197 
198  /* Enable write access */
199  temp = 0x01;
200  pci_write_config_byte(nforce2_dev, NFORCE2_PLLENABLE, (u8)temp);
201 
202  diff = tfsb - fsb;
203 
204  if (!diff)
205  return 0;
206 
207  while ((tfsb != fsb) && (tfsb <= max_fsb) && (tfsb >= min_fsb)) {
208  if (diff < 0)
209  tfsb++;
210  else
211  tfsb--;
212 
213  /* Calculate the PLL reg. value */
214  pll = nforce2_calc_pll(tfsb);
215  if (pll == -1)
216  return -EINVAL;
217 
218  nforce2_write_pll(pll);
219 #ifdef NFORCE2_DELAY
220  mdelay(NFORCE2_DELAY);
221 #endif
222  }
223 
224  temp = 0x40;
225  pci_write_config_byte(nforce2_dev, NFORCE2_PLLADR, (u8)temp);
226 
227  return 0;
228 }
229 
236 static unsigned int nforce2_get(unsigned int cpu)
237 {
238  if (cpu)
239  return 0;
240  return nforce2_fsb_read(0) * fid * 100;
241 }
242 
252 static int nforce2_target(struct cpufreq_policy *policy,
253  unsigned int target_freq, unsigned int relation)
254 {
255 /* unsigned long flags; */
256  struct cpufreq_freqs freqs;
257  unsigned int target_fsb;
258 
259  if ((target_freq > policy->max) || (target_freq < policy->min))
260  return -EINVAL;
261 
262  target_fsb = target_freq / (fid * 100);
263 
264  freqs.old = nforce2_get(policy->cpu);
265  freqs.new = target_fsb * fid * 100;
266  freqs.cpu = 0; /* Only one CPU on nForce2 platforms */
267 
268  if (freqs.old == freqs.new)
269  return 0;
270 
271  pr_debug("Old CPU frequency %d kHz, new %d kHz\n",
272  freqs.old, freqs.new);
273 
275 
276  /* Disable IRQs */
277  /* local_irq_save(flags); */
278 
279  if (nforce2_set_fsb(target_fsb) < 0)
280  printk(KERN_ERR PFX "Changing FSB to %d failed\n",
281  target_fsb);
282  else
283  pr_debug("Changed FSB successfully to %d\n",
284  target_fsb);
285 
286  /* Enable IRQs */
287  /* local_irq_restore(flags); */
288 
290 
291  return 0;
292 }
293 
298 static int nforce2_verify(struct cpufreq_policy *policy)
299 {
300  unsigned int fsb_pol_max;
301 
302  fsb_pol_max = policy->max / (fid * 100);
303 
304  if (policy->min < (fsb_pol_max * fid * 100))
305  policy->max = (fsb_pol_max + 1) * fid * 100;
306 
307  cpufreq_verify_within_limits(policy,
308  policy->cpuinfo.min_freq,
309  policy->cpuinfo.max_freq);
310  return 0;
311 }
312 
313 static int nforce2_cpu_init(struct cpufreq_policy *policy)
314 {
315  unsigned int fsb;
316  unsigned int rfid;
317 
318  /* capability check */
319  if (policy->cpu != 0)
320  return -ENODEV;
321 
322  /* Get current FSB */
323  fsb = nforce2_fsb_read(0);
324 
325  if (!fsb)
326  return -EIO;
327 
328  /* FIX: Get FID from CPU */
329  if (!fid) {
330  if (!cpu_khz) {
332  "cpu_khz not set, can't calculate multiplier!\n");
333  return -ENODEV;
334  }
335 
336  fid = cpu_khz / (fsb * 100);
337  rfid = fid % 5;
338 
339  if (rfid) {
340  if (rfid > 2)
341  fid += 5 - rfid;
342  else
343  fid -= rfid;
344  }
345  }
346 
347  printk(KERN_INFO PFX "FSB currently at %i MHz, FID %d.%d\n", fsb,
348  fid / 10, fid % 10);
349 
350  /* Set maximum FSB to FSB at boot time */
351  max_fsb = nforce2_fsb_read(1);
352 
353  if (!max_fsb)
354  return -EIO;
355 
356  if (!min_fsb)
357  min_fsb = max_fsb - NFORCE2_SAFE_DISTANCE;
358 
359  if (min_fsb < NFORCE2_MIN_FSB)
360  min_fsb = NFORCE2_MIN_FSB;
361 
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;
369 
370  return 0;
371 }
372 
373 static int nforce2_cpu_exit(struct cpufreq_policy *policy)
374 {
375  return 0;
376 }
377 
378 static struct cpufreq_driver nforce2_driver = {
379  .name = "nforce2",
380  .verify = nforce2_verify,
381  .target = nforce2_target,
382  .get = nforce2_get,
383  .init = nforce2_cpu_init,
384  .exit = nforce2_cpu_exit,
385  .owner = THIS_MODULE,
386 };
387 
388 #ifdef MODULE
389 static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = {
391  {}
392 };
393 MODULE_DEVICE_TABLE(pci, nforce2_ids);
394 #endif
395 
402 static int nforce2_detect_chipset(void)
403 {
404  nforce2_dev = pci_get_subsys(PCI_VENDOR_ID_NVIDIA,
407 
408  if (nforce2_dev == NULL)
409  return -ENODEV;
410 
411  printk(KERN_INFO PFX "Detected nForce2 chipset revision %X\n",
412  nforce2_dev->revision);
414  "FSB changing is maybe unstable and can lead to "
415  "crashes and data loss.\n");
416 
417  return 0;
418 }
419 
427 static int __init nforce2_init(void)
428 {
429  /* TODO: do we need to detect the processor? */
430 
431  /* detect chipset */
432  if (nforce2_detect_chipset()) {
433  printk(KERN_INFO PFX "No nForce2 chipset.\n");
434  return -ENODEV;
435  }
436 
437  return cpufreq_register_driver(&nforce2_driver);
438 }
439 
445 static void __exit nforce2_exit(void)
446 {
447  cpufreq_unregister_driver(&nforce2_driver);
448 }
449 
450 module_init(nforce2_init);
451 module_exit(nforce2_exit);
452