Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=348f31ed2bd18391fe5903aa0ad7bfcda6d8ca0b
Commit:     348f31ed2bd18391fe5903aa0ad7bfcda6d8ca0b
Parent:     e57501c15f48d6b7a8fe2b023be8f4779484482d
Author:     Rafa� Bilski <[EMAIL PROTECTED]>
AuthorDate: Thu Feb 8 18:56:04 2007 +0100
Committer:  Dave Jones <[EMAIL PROTECTED]>
CommitDate: Sat Feb 10 20:05:50 2007 -0500

    [CPUFREQ] Longhaul - Separate frequency and voltage transition
    
    This change should make Longhaul more compatible with
    both ver. 2 and Powersaver processors. Voltage transitions
    will be done before or after frequency transition. That depends
    on direction of change. I don't know how to force conservative
    governor when voltage scaling is enabled, so there is only
    a warning for user. Minimal voltage is calculated in different
    way now because in this way more power is saved at lower
    multipliers.
    
    Signed-off-by: Rafal Bilski <[EMAIL PROTECTED]>
    Signed-off-by: Dave Jones <[EMAIL PROTECTED]>
---
 arch/i386/kernel/cpu/cpufreq/longhaul.c |  109 ++++++++++++++++++++++++++-----
 1 files changed, 93 insertions(+), 16 deletions(-)

diff --git a/arch/i386/kernel/cpu/cpufreq/longhaul.c 
b/arch/i386/kernel/cpu/cpufreq/longhaul.c
index fc9afbb..8f40cb4 100644
--- a/arch/i386/kernel/cpu/cpufreq/longhaul.c
+++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c
@@ -65,7 +65,8 @@ static unsigned int fsb;
 static struct mV_pos *vrm_mV_table;
 static unsigned char *mV_vrm_table;
 struct f_msr {
-       unsigned char vrm;
+       u8 vrm;
+       u8 pos;
 };
 static struct f_msr f_msr_table[32];
 
@@ -75,6 +76,7 @@ static int can_scale_voltage;
 static struct acpi_processor *pr = NULL;
 static struct acpi_processor_cx *cx = NULL;
 static u8 longhaul_flags;
+static u8 longhaul_pos;
 
 /* Module parameters */
 static int scale_voltage;
@@ -165,26 +167,47 @@ static void do_longhaul1(unsigned int clock_ratio_index)
 static void do_powersaver(int cx_address, unsigned int clock_ratio_index)
 {
        union msr_longhaul longhaul;
+       u8 dest_pos;
        u32 t;
 
+       dest_pos = f_msr_table[clock_ratio_index].pos;
+
        rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+       /* Setup new frequency */
        longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
        longhaul.bits.SoftBusRatio = clock_ratio_index & 0xf;
        longhaul.bits.SoftBusRatio4 = (clock_ratio_index & 0x10) >> 4;
-       longhaul.bits.EnableSoftBusRatio = 1;
-
-       if (can_scale_voltage) {
+       /* Setup new voltage */
+       if (can_scale_voltage)
                longhaul.bits.SoftVID = f_msr_table[clock_ratio_index].vrm;
+       /* Sync to timer tick */
+       safe_halt();
+       /* Raise voltage if necessary */
+       if (can_scale_voltage && longhaul_pos < dest_pos) {
                longhaul.bits.EnableSoftVID = 1;
+               wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+               /* Change voltage */
+               if (!cx_address) {
+                       ACPI_FLUSH_CPU_CACHE();
+                       halt();
+               } else {
+                       ACPI_FLUSH_CPU_CACHE();
+                       /* Invoke C3 */
+                       inb(cx_address);
+                       /* Dummy op - must do something useless after P_LVL3
+                        * read */
+                       t = inl(acpi_fadt.xpm_tmr_blk.address);
+               }
+               longhaul.bits.EnableSoftVID = 0;
+               wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+               longhaul_pos = dest_pos;
        }
 
-       /* Sync to timer tick */
-       safe_halt();
        /* Change frequency on next halt or sleep */
+       longhaul.bits.EnableSoftBusRatio = 1;
        wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
        if (!cx_address) {
                ACPI_FLUSH_CPU_CACHE();
-               /* Invoke C1 */
                halt();
        } else {
                ACPI_FLUSH_CPU_CACHE();
@@ -194,12 +217,29 @@ static void do_powersaver(int cx_address, unsigned int 
clock_ratio_index)
                t = inl(acpi_fadt.xpm_tmr_blk.address);
        }
        /* Disable bus ratio bit */
-       local_irq_disable();
-       longhaul.bits.RevisionKey = longhaul.bits.RevisionID;
        longhaul.bits.EnableSoftBusRatio = 0;
-       longhaul.bits.EnableSoftBSEL = 0;
-       longhaul.bits.EnableSoftVID = 0;
        wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+
+       /* Reduce voltage if necessary */
+       if (can_scale_voltage && longhaul_pos > dest_pos) {
+               longhaul.bits.EnableSoftVID = 1;
+               wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+               /* Change voltage */
+               if (!cx_address) {
+                       ACPI_FLUSH_CPU_CACHE();
+                       halt();
+               } else {
+                       ACPI_FLUSH_CPU_CACHE();
+                       /* Invoke C3 */
+                       inb(cx_address);
+                       /* Dummy op - must do something useless after P_LVL3
+                        * read */
+                       t = inl(acpi_fadt.xpm_tmr_blk.address);
+               }
+               longhaul.bits.EnableSoftVID = 0;
+               wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
+               longhaul_pos = dest_pos;
+       }
 }
 
 /**
@@ -420,6 +460,7 @@ static void __init longhaul_setup_voltagescaling(void)
        union msr_longhaul longhaul;
        struct mV_pos minvid, maxvid;
        unsigned int j, speed, pos, kHz_step, numvscales;
+       int min_vid_speed;
 
        rdmsrl(MSR_VIA_LONGHAUL, longhaul.val);
        if (!(longhaul.bits.RevisionID & 1)) {
@@ -439,8 +480,6 @@ static void __init longhaul_setup_voltagescaling(void)
 
        minvid = vrm_mV_table[longhaul.bits.MinimumVID];
        maxvid = vrm_mV_table[longhaul.bits.MaximumVID];
-       numvscales = maxvid.pos - minvid.pos + 1;
-       kHz_step = (highest_speed - lowest_speed) / numvscales;
 
        if (minvid.mV == 0 || maxvid.mV == 0 || minvid.mV > maxvid.mV) {
                printk (KERN_INFO PFX "Bogus values Min:%d.%03d Max:%d.%03d. "
@@ -456,20 +495,58 @@ static void __init longhaul_setup_voltagescaling(void)
                return;
        }
 
-       printk(KERN_INFO PFX "Max VID=%d.%03d  Min VID=%d.%03d, %d possible 
voltage scales\n",
+       /* How many voltage steps */
+       numvscales = maxvid.pos - minvid.pos + 1;
+       printk(KERN_INFO PFX
+               "Max VID=%d.%03d  "
+               "Min VID=%d.%03d, "
+               "%d possible voltage scales\n",
                maxvid.mV/1000, maxvid.mV%1000,
                minvid.mV/1000, minvid.mV%1000,
                numvscales);
-       
+
+       /* Calculate max frequency at min voltage */
+       j = longhaul.bits.MinMHzBR;
+       if (longhaul.bits.MinMHzBR4)
+               j += 16;
+       min_vid_speed = eblcr_table[j];
+       if (min_vid_speed == -1)
+               return;
+       switch (longhaul.bits.MinMHzFSB) {
+       case 0:
+               min_vid_speed *= 13333;
+               break;
+       case 1:
+               min_vid_speed *= 10000;
+               break;
+       case 3:
+               min_vid_speed *= 6666;
+               break;
+       default:
+               return;
+               break;
+       }
+       if (min_vid_speed >= highest_speed)
+               return;
+       /* Calculate kHz for one voltage step */
+       kHz_step = (highest_speed - min_vid_speed) / numvscales;
+
        j = 0;
        while (longhaul_table[j].frequency != CPUFREQ_TABLE_END) {
                speed = longhaul_table[j].frequency;
-               pos = (speed - lowest_speed) / kHz_step + minvid.pos;
+               if (speed > min_vid_speed)
+                       pos = (speed - min_vid_speed) / kHz_step + minvid.pos;
+               else
+                       pos = minvid.pos;
                f_msr_table[longhaul_table[j].index].vrm = mV_vrm_table[pos];
+               f_msr_table[longhaul_table[j].index].pos = pos;
                j++;
        }
 
+       longhaul_pos = maxvid.pos;
        can_scale_voltage = 1;
+       printk(KERN_INFO PFX "Voltage scaling enabled. "
+               "Use of \"conservative\" governor is highly recommended.\n");
 }
 
 
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to