Commit 690c11be authored by Dave Jones's avatar Dave Jones Committed by Dave Jones

[CPUFREQ] Geode register fixes.

From: Hiroshi Miura <miura at da-cha.org>
                                                                                                        
I mistook a Geode chipset's register meanings. (-.-;
ON is not 'CPU is ON' but 'cpu modulation is ON' that is stops cpu.
                                                                                                               
this causes a bad freq setting.
                                                                                                               
This patch fixes this and minor bug that is,
                                                                                                               
        if (new_khz == stock_freq) {  /* if new khz == 100% of CPU speed, it is special case */
                local_irq_save(flags);
                cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
                                                                                                               
cpufreq_notify_transition() called after local_irq_save();
this makes not update cpu_khz.
parent 5344ce83
......@@ -28,30 +28,34 @@
* with 'Suspend Modulation OFF Count Register'
* and 'Suspend Modulation ON Count Register'.
* These registers are 8bit counters that represent the number of
* 32us intervals which the SUSP# pin is asserted/de-asserted to the
* processor.
* 32us intervals which the SUSP# pin is asserted(ON)/de-asserted(OFF)
* to the processor.
*
* These counters define a ratio which is the effective frequency
* of operation of the system.
*
* On Count
* OFF Count
* F_eff = Fgx * ----------------------
* On Count + Off Count
* OFF Count + ON Count
*
* 0 <= On Count, Off Count <= 255
*
* From these limits, we can get register values
*
* on_duration + off_duration <= MAX_DURATION
* off_duration = on_duration * (stock_freq - freq) / freq
* off_duration + on_duration <= MAX_DURATION
* on_duration = off_duration * (stock_freq - freq) / freq
*
* on_duration = (freq * DURATION) / stock_freq
* off_duration = DURATION - on_duration
* off_duration = (freq * DURATION) / stock_freq
* on_duration = DURATION - off_duration
*
*
*---------------------------------------------------------------------------
*
* ChangeLog:
* Dec. 12, 2003 Hiroshi Miura <miura@da-cha.org>
* - fix on/off register mistake
* - fix cpu_khz calc when it stops cpu modulation.
*
* Dec. 11, 2002 Hiroshi Miura <miura@da-cha.org>
* - rewrite for Cyrix MediaGX Cx5510/5520 and
* NatSemi Geode Cs5530(A).
......@@ -233,13 +237,13 @@ static unsigned int gx_validate_speed(unsigned int khz, u8 *on_duration, u8 *off
int old_tmp_freq = stock_freq;
int tmp_freq;
*on_duration=1;
*off_duration=0;
*off_duration=1;
*on_duration=0;
for (i=max_duration; i>0; i--) {
tmp_on = ((khz * i) / stock_freq) & 0xff;
tmp_off = i - tmp_on;
tmp_freq = (stock_freq * tmp_on) / i;
tmp_off = ((khz * i) / stock_freq) & 0xff;
tmp_on = i - tmp_off;
tmp_freq = (stock_freq * tmp_off) / i;
/* if this relation is closer to khz, use this. If it's equal,
* prefer it, too - lower latency */
if (abs(tmp_freq - khz) <= abs(old_tmp_freq - khz)) {
......@@ -273,42 +277,37 @@ static void gx_set_cpuspeed(unsigned int khz)
freqs.new = new_khz;
if (new_khz == stock_freq) { /* if new khz == 100% of CPU speed, it is special case */
local_irq_save(flags);
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
pci_write_config_byte(gx_params->cs55x0, PCI_SUSCFG, (gx_params->pci_suscfg & ~(SUSMOD)));
pci_read_config_byte(gx_params->cs55x0, PCI_SUSCFG, &(gx_params->pci_suscfg));
local_irq_restore(flags);
dprintk("suspend modulation disabled: cpu runs 100 percent speed.\n");
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
return;
}
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
local_irq_save(flags);
switch (gx_params->cs55x0->device) {
case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
pmer1 = gx_params->pci_pmer1 | IRQ_SPDUP | VID_SPDUP;
/* FIXME: need to test other values -- Zwane,Miura */
pci_write_config_byte(gx_params->cs55x0, PCI_IRQTC, 4); /* typical 2 to 4ms */
pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */
pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1);
if (gx_params->pci_rev < 0x10) { /* CS5530(rev 1.2, 1.3) */
if (new_khz != stock_freq) { /* if new khz == 100% of CPU speed, it is special case */
switch (gx_params->cs55x0->device) {
case PCI_DEVICE_ID_CYRIX_5530_LEGACY:
pmer1 = gx_params->pci_pmer1 | IRQ_SPDUP | VID_SPDUP;
/* FIXME: need to test other values -- Zwane,Miura */
pci_write_config_byte(gx_params->cs55x0, PCI_IRQTC, 4); /* typical 2 to 4ms */
pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */
pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1);
if (gx_params->pci_rev < 0x10) { /* CS5530(rev 1.2, 1.3) */
suscfg = gx_params->pci_suscfg | SUSMOD;
} else { /* CS5530A,B.. */
suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE;
}
break;
case PCI_DEVICE_ID_CYRIX_5520:
case PCI_DEVICE_ID_CYRIX_5510:
suscfg = gx_params->pci_suscfg | SUSMOD;
} else { /* CS5530A,B.. */
suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE;
default:
local_irq_restore(flags);
dprintk("fatal: try to set unknown chipset.\n");
return;
}
break;
case PCI_DEVICE_ID_CYRIX_5520:
case PCI_DEVICE_ID_CYRIX_5510:
suscfg = gx_params->pci_suscfg | SUSMOD;
break;
default:
local_irq_restore(flags);
dprintk("fatal: try to set unknown chipset.\n");
return;
} else {
suscfg = gx_params->pci_suscfg & ~(SUSMOD);
gx_params->off_duration = 0;
gx_params->on_duration = 0;
dprintk("suspend modulation disabled: cpu runs 100 percent speed.\n");
}
pci_write_config_byte(gx_params->cs55x0, PCI_MODOFF, gx_params->off_duration);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment