]> git.neil.brown.name Git - history.git/commitdiff
[CPUFREQ] Geode register fixes.
authorDave Jones <davej@redhat.com>
Tue, 10 Feb 2004 16:54:06 +0000 (16:54 +0000)
committerDave Jones <davej@delerium.codemonkey.org.uk>
Tue, 10 Feb 2004 16:54:06 +0000 (16:54 +0000)
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.

arch/i386/kernel/cpu/cpufreq/gx-suspmod.c

index bb5471e2bc81f09022109782703c2a1f63eacfe5..91ea29efd08437a1132829aa395761d17e721eca 100644 (file)
  *     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);