76 #include <linux/kernel.h>
77 #include <linux/module.h>
81 #include <linux/pci.h>
82 #include <linux/errno.h>
83 #include <linux/slab.h>
89 #define PCI_PMER1 0x80
90 #define PCI_PMER2 0x81
91 #define PCI_PMER3 0x82
92 #define PCI_IRQTC 0x8c
93 #define PCI_VIDTC 0x8d
94 #define PCI_MODOFF 0x94
95 #define PCI_MODON 0x95
96 #define PCI_SUSCFG 0x96
102 #define IRQ_SPDUP (1<<3)
103 #define VID_SPDUP (1<<4)
106 #define SUSMOD (1<<0)
108 #define SMISPDUP (1<<1)
110 #define SUSCFG (1<<2)
112 #define PWRSVE_ISA (1<<3)
113 #define PWRSVE (1<<4)
125 static int stock_freq;
128 static int pci_busclk;
137 static int max_duration = 255;
143 #define POLICY_MIN_DIV 20
160 static int gx_freq_mult[16] = {
161 4, 10, 4, 6, 9, 5, 7, 8,
162 0, 0, 0, 0, 0, 0, 0, 0
177 static void gx_write_byte(
int reg,
int value)
179 pci_write_config_byte(gx_params->
cs55x0, reg, value);
196 pr_debug(
"error: no supported chipset found!\n");
206 static unsigned int gx_get_cpuspeed(
unsigned int cpu)
221 static unsigned int gx_validate_speed(
unsigned int khz,
u8 *on_duration,
226 int old_tmp_freq = stock_freq;
232 for (i = max_duration; i > 0; i--) {
233 tmp_off = ((khz *
i) / stock_freq) & 0xff;
234 tmp_on = i - tmp_off;
235 tmp_freq = (stock_freq * tmp_off) / i;
238 if (
abs(tmp_freq - khz) <=
abs(old_tmp_freq - khz)) {
239 *on_duration = tmp_on;
240 *off_duration = tmp_off;
241 old_tmp_freq = tmp_freq;
254 static void gx_set_cpuspeed(
unsigned int khz)
257 unsigned int new_khz;
262 freqs.old = gx_get_cpuspeed(0);
264 new_khz = gx_validate_speed(khz, &gx_params->
on_duration,
274 if (new_khz != stock_freq) {
276 switch (gx_params->
cs55x0->device) {
286 if (gx_params->
cs55x0->revision < 0x10) {
300 pr_debug(
"fatal: try to set unknown chipset.\n");
307 pr_debug(
"suspend modulation disabled: cpu runs 100%% speed.\n");
322 pr_debug(
"suspend modulation w/ duration of ON:%d us, OFF:%d us\n",
324 pr_debug(
"suspend modulation w/ clock speed: %d kHz.\n", freqs.new);
340 unsigned int tmp_freq = 0;
343 if (!stock_freq || !policy)
347 cpufreq_verify_within_limits(policy, (stock_freq / max_duration),
356 tmp_freq = gx_validate_speed(policy->
min, &tmp1, &tmp2);
357 if (tmp_freq < policy->
min)
358 tmp_freq += stock_freq / max_duration;
359 policy->
min = tmp_freq;
360 if (policy->
min > policy->
max)
361 policy->
max = tmp_freq;
362 tmp_freq = gx_validate_speed(policy->
max, &tmp1, &tmp2);
363 if (tmp_freq > policy->
max)
364 tmp_freq -= stock_freq / max_duration;
365 policy->
max = tmp_freq;
366 if (policy->
max < policy->
min)
367 policy->
max = policy->
min;
368 cpufreq_verify_within_limits(policy, (stock_freq / max_duration),
379 unsigned int target_freq,
380 unsigned int relation)
383 unsigned int tmp_freq;
385 if (!stock_freq || !policy)
390 tmp_freq = gx_validate_speed(target_freq, &tmp1, &tmp2);
391 while (tmp_freq < policy->min) {
392 tmp_freq += stock_freq / max_duration;
393 tmp_freq = gx_validate_speed(tmp_freq, &tmp1, &tmp2);
395 while (tmp_freq > policy->
max) {
396 tmp_freq -= stock_freq / max_duration;
397 tmp_freq = gx_validate_speed(tmp_freq, &tmp1, &tmp2);
400 gx_set_cpuspeed(tmp_freq);
407 unsigned int maxfreq, curfreq;
409 if (!policy || policy->
cpu != 0)
414 maxfreq = pci_busclk * gx_freq_mult[getCx86(
CX86_DIR1) & 0x0f];
418 maxfreq = 30000 * gx_freq_mult[getCx86(
CX86_DIR1) & 0x0f];
420 stock_freq = maxfreq;
421 curfreq = gx_get_cpuspeed(0);
423 pr_debug(
"cpu max frequency is %d.\n", maxfreq);
424 pr_debug(
"cpu current frequency is %dkHz.\n", curfreq);
430 policy->
min = maxfreq / max_duration;
433 policy->
max = maxfreq;
434 policy->
cur = curfreq;
435 policy->
cpuinfo.min_freq = maxfreq / max_duration;
436 policy->
cpuinfo.max_freq = maxfreq;
447 .get = gx_get_cpuspeed,
448 .verify = cpufreq_gx_verify,
449 .target = cpufreq_gx_target,
450 .init = cpufreq_gx_cpu_init,
451 .name =
"gx-suspmod",
455 static int __init cpufreq_gx_init(
void)
462 gx_pci = gx_detect_chipset();
467 if (max_duration > 0xff)
470 pr_debug(
"geode suspend modulation available.\n");
496 static void __exit cpufreq_gx_exit(
void)