[CPUFREQ] Longhaul - Simplier minmult
[powerpc.git] / arch / i386 / kernel / cpu / cpufreq / longhaul.c
index 849a6df..8f65ebe 100644 (file)
@@ -56,6 +56,7 @@
 /* Flags */
 #define USE_ACPI_C3            (1 << 1)
 #define USE_NORTHBRIDGE                (1 << 2)
+#define USE_VT8235             (1 << 3)
 
 static int cpu_model;
 static unsigned int numscales=16;
@@ -318,31 +319,19 @@ static void longhaul_setstate(unsigned int clock_ratio_index)
 
 #define ROUNDING       0xf
 
-static int _guess(int guess, int mult)
-{
-       int target;
-
-       target = ((mult/10)*guess);
-       if (mult%10 != 0)
-               target += (guess/2);
-       target += ROUNDING/2;
-       target &= ~ROUNDING;
-       return target;
-}
-
-
 static int guess_fsb(int mult)
 {
-       int speed = (cpu_khz/1000);
+       int speed = cpu_khz / 1000;
        int i;
-       int speeds[] = { 66, 100, 133, 200 };
-
-       speed += ROUNDING/2;
-       speed &= ~ROUNDING;
+       int speeds[] = { 666, 1000, 1333, 2000 };
+       int f_max, f_min;
 
-       for (i=0; i<4; i++) {
-               if (_guess(speeds[i], mult) == speed)
-                       return speeds[i];
+       for (i = 0; i < 4; i++) {
+               f_max = ((speeds[i] * mult) + 50) / 100;
+               f_max += (ROUNDING / 2);
+               f_min = f_max - ROUNDING;
+               if ((speed <= f_max) && (speed >= f_min))
+                       return speeds[i] / 10;
        }
        return 0;
 }
@@ -369,22 +358,15 @@ static int __init longhaul_get_ranges(void)
         * C3 is booting at max anyway. */
        maxmult = mult;
        /* Get min multiplier */
-       switch (longhaul_version) {
-       case TYPE_LONGHAUL_V1:
-       case TYPE_LONGHAUL_V2:
-               minmult = 30;
+       switch (cpu_model) {
+       case CPU_NEHEMIAH:
+               minmult = 50;
                break;
-
-       case TYPE_POWERSAVER:
-               /* Ezra-T */
-               if (cpu_model == CPU_EZRA_T)
-                       minmult = 30;
-               /* Nehemiah */
-               else if (cpu_model == CPU_NEHEMIAH)
-                       minmult = 50;
-               /* Nehemiah C */
-               else if (cpu_model == CPU_NEHEMIAH_C)
-                       minmult = 40;
+       case CPU_NEHEMIAH_C:
+               minmult = 40;
+               break;
+       default:
+               minmult = 30;
                break;
        }
 
@@ -556,20 +538,50 @@ static int enable_arbiter_disable(void)
        if (dev != NULL) {
                /* Enable access to port 0x22 */
                pci_read_config_byte(dev, reg, &pci_cmd);
-               if ( !(pci_cmd & 1<<7) ) {
+               if (!(pci_cmd & 1<<7)) {
                        pci_cmd |= 1<<7;
                        pci_write_config_byte(dev, reg, pci_cmd);
+                       pci_read_config_byte(dev, reg, &pci_cmd);
+                       if (!(pci_cmd & 1<<7)) {
+                               printk(KERN_ERR PFX
+                                       "Can't enable access to port 0x22.\n");
+                               return 0;
+                       }
                }
                return 1;
        }
        return 0;
 }
 
+static int longhaul_setup_vt8235(void)
+{
+       struct pci_dev *dev;
+       u8 pci_cmd;
+
+       /* Find VT8235 southbridge */
+       dev = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235, NULL);
+       if (dev != NULL) {
+               /* Set transition time to max */
+               pci_read_config_byte(dev, 0xec, &pci_cmd);
+               pci_cmd &= ~(1 << 2);
+               pci_write_config_byte(dev, 0xec, pci_cmd);
+               pci_read_config_byte(dev, 0xe4, &pci_cmd);
+               pci_cmd &= ~(1 << 7);
+               pci_write_config_byte(dev, 0xe4, pci_cmd);
+               pci_read_config_byte(dev, 0xe5, &pci_cmd);
+               pci_cmd |= 1 << 7;
+               pci_write_config_byte(dev, 0xe5, pci_cmd);
+               return 1;
+       }
+       return 0;
+}
+
 static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 {
        struct cpuinfo_x86 *c = cpu_data;
        char *cpuname=NULL;
        int ret;
+       int vt8235_present;
 
        /* Check what we have on this motherboard */
        switch (c->x86_model) {
@@ -616,25 +628,23 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
 
        case 9:
                longhaul_version = TYPE_POWERSAVER;
-               numscales=32;
+               numscales = 32;
+               memcpy(clock_ratio,
+                      nehemiah_clock_ratio,
+                      sizeof(nehemiah_clock_ratio));
+               memcpy(eblcr_table, nehemiah_eblcr, sizeof(nehemiah_eblcr));
                switch (c->x86_mask) {
                case 0 ... 1:
                        cpu_model = CPU_NEHEMIAH;
                        cpuname = "C3 'Nehemiah A' [C5N]";
-                       memcpy (clock_ratio, nehemiah_a_clock_ratio, sizeof(nehemiah_a_clock_ratio));
-                       memcpy (eblcr_table, nehemiah_a_eblcr, sizeof(nehemiah_a_eblcr));
                        break;
                case 2 ... 4:
                        cpu_model = CPU_NEHEMIAH;
                        cpuname = "C3 'Nehemiah B' [C5N]";
-                       memcpy (clock_ratio, nehemiah_b_clock_ratio, sizeof(nehemiah_b_clock_ratio));
-                       memcpy (eblcr_table, nehemiah_b_eblcr, sizeof(nehemiah_b_eblcr));
                        break;
                case 5 ... 15:
                        cpu_model = CPU_NEHEMIAH_C;
                        cpuname = "C3 'Nehemiah C' [C5N]";
-                       memcpy (clock_ratio, nehemiah_c_clock_ratio, sizeof(nehemiah_c_clock_ratio));
-                       memcpy (eblcr_table, nehemiah_c_eblcr, sizeof(nehemiah_c_eblcr));
                        break;
                }
                break;
@@ -655,12 +665,16 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                break;
        };
 
+       /* Doesn't hurt */
+       vt8235_present = longhaul_setup_vt8235();
+
        /* Find ACPI data for processor */
-       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX,
-                           &longhaul_walk_callback, NULL, (void *)&pr);
+       acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT,
+                               ACPI_UINT32_MAX, &longhaul_walk_callback,
+                               NULL, (void *)&pr);
 
        /* Check ACPI support for C3 state */
-       if ((pr != NULL) && (longhaul_version == TYPE_POWERSAVER)) {
+       if (pr != NULL && longhaul_version == TYPE_POWERSAVER) {
                cx = &pr->power.states[ACPI_STATE_C3];
                if (cx->address > 0 && cx->latency <= 1000) {
                        longhaul_flags |= USE_ACPI_C3;
@@ -672,8 +686,11 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
                longhaul_flags |= USE_NORTHBRIDGE;
                goto print_support_type;
        }
-
-       /* No ACPI C3 or we can't use it */
+       /* Use VT8235 southbridge if present */
+       if (longhaul_version == TYPE_POWERSAVER && vt8235_present) {
+               longhaul_flags |= USE_VT8235;
+               goto print_support_type;
+       }
        /* Check ACPI support for bus master arbiter disable */
        if ((pr == NULL) || !(pr->flags.bm_control)) {
                printk(KERN_ERR PFX
@@ -682,18 +699,18 @@ static int __init longhaul_cpu_init(struct cpufreq_policy *policy)
        }
 
 print_support_type:
-       if (!(longhaul_flags & USE_NORTHBRIDGE)) {
-               printk (KERN_INFO PFX "Using ACPI support.\n");
-       } else {
+       if (longhaul_flags & USE_NORTHBRIDGE)
                printk (KERN_INFO PFX "Using northbridge support.\n");
-       }
+       else if (longhaul_flags & USE_VT8235)
+               printk (KERN_INFO PFX "Using VT8235 support.\n");
+       else
+               printk (KERN_INFO PFX "Using ACPI support.\n");
 
        ret = longhaul_get_ranges();
        if (ret != 0)
                return ret;
 
-       if ((longhaul_version==TYPE_LONGHAUL_V2 || longhaul_version==TYPE_POWERSAVER) &&
-                (scale_voltage != 0))
+       if ((longhaul_version != TYPE_LONGHAUL_V1) && (scale_voltage != 0))
                longhaul_setup_voltagescaling();
 
        policy->governor = CPUFREQ_DEFAULT_GOVERNOR;