]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
[CPUFREQ] Fix up merge conflicts with recent ACPI changes.
authorDave Jones <davej@redhat.com>
Sun, 11 Feb 2007 01:36:29 +0000 (20:36 -0500)
committerDave Jones <davej@redhat.com>
Sun, 11 Feb 2007 01:36:29 +0000 (20:36 -0500)
Signed-off-by: Dave Jones <davej@redhat.com>
1  2 
arch/i386/kernel/cpu/cpufreq/longhaul.c

index 8f40cb47720e390a1a83836ad72e4e6d042508cb,a3db9332d652eccbc9c3745b55aaf309c4eebbe7..fa5cac255c16e32f0e2e19562b92ef8874fa740b
  #define       CPU_EZRA        3
  #define       CPU_EZRA_T      4
  #define       CPU_NEHEMIAH    5
 +#define       CPU_NEHEMIAH_C  6
  
  /* 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;
@@@ -65,8 -63,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];
  
@@@ -76,10 -73,10 +76,10 @@@ 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;
 -static int ignore_latency;
  
  #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_DRIVER, "longhaul", msg)
  
@@@ -167,79 -164,41 +167,79 @@@ static void do_longhaul1(unsigned int c
  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;
-                       t = inl(acpi_fadt.xpm_tmr_blk.address);
 +              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_gbl_FADT.xpm_timer_block.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();
                /* Invoke C3 */
                inb(cx_address);
                /* Dummy op - must do something useless after P_LVL3 read */
-               t = inl(acpi_fadt.xpm_tmr_blk.address);
+               t = inl(acpi_gbl_FADT.xpm_timer_block.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);
-                       t = inl(acpi_fadt.xpm_tmr_blk.address);
 +
 +      /* 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_gbl_FADT.xpm_timer_block.address);
 +              }
 +              longhaul.bits.EnableSoftVID = 0;
 +              wrmsrl(MSR_VIA_LONGHAUL, longhaul.val);
 +              longhaul_pos = dest_pos;
 +      }
  }
  
  /**
@@@ -291,8 -250,7 +291,7 @@@ static void longhaul_setstate(unsigned 
                outb(3, 0x22);
        } else if ((pr != NULL) && pr->flags.bm_control) {
                /* Disable bus master arbitration */
-               acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1,
-                                 ACPI_MTX_DO_NOT_LOCK);
+               acpi_set_register(ACPI_BITREG_ARB_DISABLE, 1);
        }
        switch (longhaul_version) {
  
        case TYPE_POWERSAVER:
                if (longhaul_flags & USE_ACPI_C3) {
                        /* Don't allow wakeup */
-                       acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0,
-                                         ACPI_MTX_DO_NOT_LOCK);
+                       acpi_set_register(ACPI_BITREG_BUS_MASTER_RLD, 0);
                        do_powersaver(cx->address, clock_ratio_index);
                } else {
                        do_powersaver(0, clock_ratio_index);
                outb(0, 0x22);
        } else if ((pr != NULL) && pr->flags.bm_control) {
                /* Enable bus master arbitration */
-               acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0,
-                                 ACPI_MTX_DO_NOT_LOCK);
+               acpi_set_register(ACPI_BITREG_ARB_DISABLE, 0);
        }
        outb(pic2_mask,0xA1);   /* restore mask */
        outb(pic1_mask,0x21);
  
  #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;
 -
 -      for (i=0; i<4; i++) {
 -              if (_guess(speeds[i], mult) == speed)
 -                      return speeds[i];
 +      int speeds[] = { 666, 1000, 1333, 2000 };
 +      int f_max, f_min;
 +
 +      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;
  }
  
  static int __init longhaul_get_ranges(void)
  {
 -      unsigned long invalue;
 -      unsigned int ezra_t_multipliers[32]= {
 -                      90,  30,  40, 100,  55,  35,  45,  95,
 -                      50,  70,  80,  60, 120,  75,  85,  65,
 -                      -1, 110, 120,  -1, 135, 115, 125, 105,
 -                      130, 150, 160, 140,  -1, 155,  -1, 145 };
        unsigned int j, k = 0;
 -      union msr_longhaul longhaul;
 -      int mult = 0;
 +      int mult;
  
 -      switch (longhaul_version) {
 -      case TYPE_LONGHAUL_V1:
 -      case TYPE_LONGHAUL_V2:
 -              /* Ugh, Longhaul v1 didn't have the min/max MSRs.
 -                 Assume min=3.0x & max = whatever we booted at. */
 +      /* Get current frequency */
 +      mult = longhaul_get_cpu_mult();
 +      if (mult == -1) {
 +              printk(KERN_INFO PFX "Invalid (reserved) multiplier!\n");
 +              return -EINVAL;
 +      }
 +      fsb = guess_fsb(mult);
 +      if (fsb == 0) {
 +              printk(KERN_INFO PFX "Invalid (reserved) FSB!\n");
 +              return -EINVAL;
 +      }
 +      /* Get max multiplier - as we always did.
 +       * Longhaul MSR is usefull only when voltage scaling is enabled.
 +       * C3 is booting at max anyway. */
 +      maxmult = mult;
 +      /* Get min multiplier */
 +      switch (cpu_model) {
 +      case CPU_NEHEMIAH:
 +              minmult = 50;
 +              break;
 +      case CPU_NEHEMIAH_C:
 +              minmult = 40;
 +              break;
 +      default:
                minmult = 30;
 -              maxmult = mult = longhaul_get_cpu_mult();
                break;
 -
 -      case TYPE_POWERSAVER:
 -              /* Ezra-T */
 -              if (cpu_model==CPU_EZRA_T) {
 -                      minmult = 30;
 -                      rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
 -                      invalue = longhaul.bits.MaxMHzBR;
 -                      if (longhaul.bits.MaxMHzBR4)
 -                              invalue += 16;
 -                      maxmult = mult = ezra_t_multipliers[invalue];
 -                      break;
 -              }
 -
 -              /* Nehemiah */
 -              if (cpu_model==CPU_NEHEMIAH) {
 -                      rdmsrl (MSR_VIA_LONGHAUL, longhaul.val);
 -
 -                      /*
 -                       * TODO: This code works, but raises a lot of questions.
 -                       * - Some Nehemiah's seem to have broken Min/MaxMHzBR's.
 -                       *   We get around this by using a hardcoded multiplier of 4.0x
 -                       *   for the minimimum speed, and the speed we booted up at for the max.
 -                       *   This is done in longhaul_get_cpu_mult() by reading the EBLCR register.
 -                       * - According to some VIA documentation EBLCR is only
 -                       *   in pre-Nehemiah C3s. How this still works is a mystery.
 -                       *   We're possibly using something undocumented and unsupported,
 -                       *   But it works, so we don't grumble.
 -                       */
 -                      minmult=40;
 -                      maxmult = mult = longhaul_get_cpu_mult();
 -                      break;
 -              }
        }
 -      fsb = guess_fsb(mult);
  
        dprintk ("MinMult:%d.%dx MaxMult:%d.%dx\n",
                 minmult/10, minmult%10, maxmult/10, maxmult%10);
  
 -      if (fsb == 0) {
 -              printk (KERN_INFO PFX "Invalid (reserved) FSB!\n");
 -              return -EINVAL;
 -      }
 -
        highest_speed = calc_speed(maxmult);
        lowest_speed = calc_speed(minmult);
        dprintk ("FSB:%dMHz  Lowest speed: %s   Highest speed:%s\n", fsb,
-                print_speed(lowest_speed/1000), 
+                print_speed(lowest_speed/1000),
                 print_speed(highest_speed/1000));
  
        if (lowest_speed == highest_speed) {
@@@ -460,7 -455,6 +457,7 @@@ static void __init longhaul_setup_volta
        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)) {
  
        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. "
                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");
  }
  
  
@@@ -615,50 -573,20 +613,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) {
                break;
  
        case 9:
 -              cpu_model = CPU_NEHEMIAH;
                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:
 -                      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));
 +                      cpu_model = CPU_NEHEMIAH;
 +                      cpuname = "C3 'Nehemiah A' [C5XLOE]";
                        break;
                case 2 ... 4:
 -                      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));
 +                      cpu_model = CPU_NEHEMIAH;
 +                      cpuname = "C3 'Nehemiah B' [C5XLOH]";
                        break;
                case 5 ... 15:
 -                      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));
 +                      cpu_model = CPU_NEHEMIAH_C;
 +                      cpuname = "C3 'Nehemiah C' [C5P]";
                        break;
                }
                break;
                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 || ignore_latency != 0) ) {
 +              if (cx->address > 0 && cx->latency <= 1000) {
                        longhaul_flags |= USE_ACPI_C3;
                        goto print_support_type;
                }
                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
        }
  
  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;
@@@ -875,6 -797,8 +873,6 @@@ static void __exit longhaul_exit(void
  
  module_param (scale_voltage, int, 0644);
  MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
 -module_param(ignore_latency, int, 0644);
 -MODULE_PARM_DESC(ignore_latency, "Skip ACPI C3 latency test");
  
  MODULE_AUTHOR ("Dave Jones <davej@codemonkey.org.uk>");
  MODULE_DESCRIPTION ("Longhaul driver for VIA Cyrix processors.");