linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / macintosh / therm_pm72.c
index 20bf672..4f50ee5 100644 (file)
  *     - Use min/max macros here or there
  *     - Latest darwin updated U3H min fan speed to 20% PWM
  *
- *  July. 06, 2006 : 1.3
- *     - Fix setting of RPM fans on Xserve G5 (they were going too fast)
- *      - Add missing slots fan control loop for Xserve G5
- *     - Lower fixed slots fan speed from 50% to 40% on desktop G5s. We
- *        still can't properly implement the control loop for these, so let's
- *        reduce the noise a little bit, it appears that 40% still gives us
- *        a pretty good air flow
- *     - Add code to "tickle" the FCU regulary so it doesn't think that
- *        we are gone while in fact, the machine just didn't need any fan
- *        speed change lately
- *
  */
 
+#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
+#include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/reboot.h>
 #include <linux/kmod.h>
 #include <linux/i2c.h>
+#include <linux/i2c-dev.h>
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 
 #include "therm_pm72.h"
 
-#define VERSION "1.3"
+#define VERSION "1.2b2"
 
 #undef DEBUG
 
@@ -157,7 +149,6 @@ static struct basckside_pid_params  backside_params;
 static struct backside_pid_state       backside_state;
 static struct drives_pid_state         drives_state;
 static struct dimm_pid_state           dimms_state;
-static struct slots_pid_state          slots_state;
 static int                             state;
 static int                             cpu_count;
 static int                             cpu_pid_type;
@@ -166,8 +157,7 @@ static struct completion            ctrl_complete;
 static int                             critical_state;
 static int                             rackmac;
 static s32                             dimm_output_clamp;
-static int                             fcu_rpm_shift;
-static int                             fcu_tickle_ticks;
+
 static DECLARE_MUTEX(driver_lock);
 
 /*
@@ -508,20 +498,13 @@ static int start_fcu(void)
        rc = fan_write_reg(0x2e, &buf, 1);
        if (rc < 0)
                return -EIO;
-       rc = fan_read_reg(0, &buf, 1);
-       if (rc < 0)
-               return -EIO;
-       fcu_rpm_shift = (buf == 1) ? 2 : 3;
-       printk(KERN_DEBUG "FCU Initialized, RPM fan shift is %d\n",
-              fcu_rpm_shift);
-
        return 0;
 }
 
 static int set_rpm_fan(int fan_index, int rpm)
 {
        unsigned char buf[2];
-       int rc, id, min, max;
+       int rc, id;
 
        if (fcu_fans[fan_index].type != FCU_FAN_RPM)
                return -EINVAL;
@@ -529,15 +512,12 @@ static int set_rpm_fan(int fan_index, int rpm)
        if (id == FCU_FAN_ABSENT_ID)
                return -EINVAL;
 
-       min = 2400 >> fcu_rpm_shift;
-       max = 56000 >> fcu_rpm_shift;
-
-       if (rpm < min)
-               rpm = min;
-       else if (rpm > max)
-               rpm = max;
-       buf[0] = rpm >> (8 - fcu_rpm_shift);
-       buf[1] = rpm << fcu_rpm_shift;
+       if (rpm < 300)
+               rpm = 300;
+       else if (rpm > 8191)
+               rpm = 8191;
+       buf[0] = rpm >> 5;
+       buf[1] = rpm << 3;
        rc = fan_write_reg(0x10 + (id * 2), buf, 2);
        if (rc < 0)
                return -EIO;
@@ -574,7 +554,7 @@ static int get_rpm_fan(int fan_index, int programmed)
        if (rc != 2)
                return -EIO;
 
-       return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
+       return (buf[0] << 5) | buf[1] >> 3;
 }
 
 static int set_pwm_fan(int fan_index, int pwm)
@@ -632,26 +612,6 @@ static int get_pwm_fan(int fan_index)
        return (buf[0] * 1000) / 2559;
 }
 
-static void tickle_fcu(void)
-{
-       int pwm;
-
-       pwm = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
-
-       DBG("FCU Tickle, slots fan is: %d\n", pwm);
-       if (pwm < 0)
-               pwm = 100;
-
-       if (!rackmac) {
-               pwm = SLOTS_FAN_DEFAULT_PWM;
-       } else if (pwm < SLOTS_PID_OUTPUT_MIN)
-               pwm = SLOTS_PID_OUTPUT_MIN;
-
-       /* That is hopefully enough to make the FCU happy */
-       set_pwm_fan(SLOTS_FAN_PWM_INDEX, pwm);
-}
-
-
 /*
  * Utility routine to read the CPU calibration EEPROM data
  * from the device-tree
@@ -758,9 +718,6 @@ BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm)
 BUILD_SHOW_FUNC_FIX(drives_temperature, drives_state.last_temp)
 BUILD_SHOW_FUNC_INT(drives_fan_rpm, drives_state.rpm)
 
-BUILD_SHOW_FUNC_FIX(slots_temperature, slots_state.last_temp)
-BUILD_SHOW_FUNC_INT(slots_fan_pwm, slots_state.pwm)
-
 BUILD_SHOW_FUNC_FIX(dimms_temperature, dimms_state.last_temp)
 
 static DEVICE_ATTR(cpu0_temperature,S_IRUGO,show_cpu0_temperature,NULL);
@@ -781,9 +738,6 @@ static DEVICE_ATTR(backside_fan_pwm,S_IRUGO,show_backside_fan_pwm,NULL);
 static DEVICE_ATTR(drives_temperature,S_IRUGO,show_drives_temperature,NULL);
 static DEVICE_ATTR(drives_fan_rpm,S_IRUGO,show_drives_fan_rpm,NULL);
 
-static DEVICE_ATTR(slots_temperature,S_IRUGO,show_slots_temperature,NULL);
-static DEVICE_ATTR(slots_fan_pwm,S_IRUGO,show_slots_fan_pwm,NULL);
-
 static DEVICE_ATTR(dimms_temperature,S_IRUGO,show_dimms_temperature,NULL);
 
 /*
@@ -1125,9 +1079,6 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state)
        fan_min = dimm_output_clamp;
        fan_min = max(fan_min, (int)state->mpu.rminn_intake_fan);
 
-       DBG(" CPU min mpu = %d, min dimm = %d\n",
-           state->mpu.rminn_intake_fan, dimm_output_clamp);
-
        state->rpm = max(state->rpm, (int)fan_min);
        state->rpm = min(state->rpm, (int)state->mpu.rmaxn_intake_fan);
        state->intake_rpm = state->rpm;
@@ -1426,8 +1377,7 @@ static void do_monitor_drives(struct drives_pid_state *state)
        DBG("  current rpm: %d\n", state->rpm);
 
        /* Get some sensor readings */
-       temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
-                                                   DS1775_TEMP)) << 8;
+       temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor, DS1775_TEMP)) << 8;
        state->last_temp = temp;
        DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
            FIX32TOPRINT(DRIVES_PID_INPUT_TARGET));
@@ -1628,7 +1578,7 @@ static int init_dimms_state(struct dimm_pid_state *state)
 }
 
 /*
- * Dispose of the state data for the DIMM control loop
+ * Dispose of the state data for the drives control loop
  */
 static void dispose_dimms_state(struct dimm_pid_state *state)
 {
@@ -1641,127 +1591,6 @@ static void dispose_dimms_state(struct dimm_pid_state *state)
        state->monitor = NULL;
 }
 
-/*
- * Slots fan control loop
- */
-static void do_monitor_slots(struct slots_pid_state *state)
-{
-       s32 temp, integral, derivative;
-       s64 integ_p, deriv_p, prop_p, sum;
-       int i, rc;
-
-       if (--state->ticks != 0)
-               return;
-       state->ticks = SLOTS_PID_INTERVAL;
-
-       DBG("slots:\n");
-
-       /* Check fan status */
-       rc = get_pwm_fan(SLOTS_FAN_PWM_INDEX);
-       if (rc < 0) {
-               printk(KERN_WARNING "Error %d reading slots fan !\n", rc);
-               /* XXX What do we do now ? */
-       } else
-               state->pwm = rc;
-       DBG("  current pwm: %d\n", state->pwm);
-
-       /* Get some sensor readings */
-       temp = le16_to_cpu(i2c_smbus_read_word_data(state->monitor,
-                                                   DS1775_TEMP)) << 8;
-       state->last_temp = temp;
-       DBG("  temp: %d.%03d, target: %d.%03d\n", FIX32TOPRINT(temp),
-           FIX32TOPRINT(SLOTS_PID_INPUT_TARGET));
-
-       /* Store temperature and error in history array */
-       state->cur_sample = (state->cur_sample + 1) % SLOTS_PID_HISTORY_SIZE;
-       state->sample_history[state->cur_sample] = temp;
-       state->error_history[state->cur_sample] = temp - SLOTS_PID_INPUT_TARGET;
-
-       /* If first loop, fill the history table */
-       if (state->first) {
-               for (i = 0; i < (SLOTS_PID_HISTORY_SIZE - 1); i++) {
-                       state->cur_sample = (state->cur_sample + 1) %
-                               SLOTS_PID_HISTORY_SIZE;
-                       state->sample_history[state->cur_sample] = temp;
-                       state->error_history[state->cur_sample] =
-                               temp - SLOTS_PID_INPUT_TARGET;
-               }
-               state->first = 0;
-       }
-
-       /* Calculate the integral term */
-       sum = 0;
-       integral = 0;
-       for (i = 0; i < SLOTS_PID_HISTORY_SIZE; i++)
-               integral += state->error_history[i];
-       integral *= SLOTS_PID_INTERVAL;
-       DBG("  integral: %08x\n", integral);
-       integ_p = ((s64)SLOTS_PID_G_r) * (s64)integral;
-       DBG("   integ_p: %d\n", (int)(integ_p >> 36));
-       sum += integ_p;
-
-       /* Calculate the derivative term */
-       derivative = state->error_history[state->cur_sample] -
-               state->error_history[(state->cur_sample + SLOTS_PID_HISTORY_SIZE - 1)
-                                   % SLOTS_PID_HISTORY_SIZE];
-       derivative /= SLOTS_PID_INTERVAL;
-       deriv_p = ((s64)SLOTS_PID_G_d) * (s64)derivative;
-       DBG("   deriv_p: %d\n", (int)(deriv_p >> 36));
-       sum += deriv_p;
-
-       /* Calculate the proportional term */
-       prop_p = ((s64)SLOTS_PID_G_p) * (s64)(state->error_history[state->cur_sample]);
-       DBG("   prop_p: %d\n", (int)(prop_p >> 36));
-       sum += prop_p;
-
-       /* Scale sum */
-       sum >>= 36;
-
-       DBG("   sum: %d\n", (int)sum);
-       state->pwm = (s32)sum;
-
-       state->pwm = max(state->pwm, SLOTS_PID_OUTPUT_MIN);
-       state->pwm = min(state->pwm, SLOTS_PID_OUTPUT_MAX);
-
-       DBG("** DRIVES PWM: %d\n", (int)state->pwm);
-       set_pwm_fan(SLOTS_FAN_PWM_INDEX, state->pwm);
-}
-
-/*
- * Initialize the state structure for the slots bay fan control loop
- */
-static int init_slots_state(struct slots_pid_state *state)
-{
-       state->ticks = 1;
-       state->first = 1;
-       state->pwm = 50;
-
-       state->monitor = attach_i2c_chip(XSERVE_SLOTS_LM75, "slots_temp");
-       if (state->monitor == NULL)
-               return -ENODEV;
-
-       device_create_file(&of_dev->dev, &dev_attr_slots_temperature);
-       device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
-
-       return 0;
-}
-
-/*
- * Dispose of the state data for the slots control loop
- */
-static void dispose_slots_state(struct slots_pid_state *state)
-{
-       if (state->monitor == NULL)
-               return;
-
-       device_remove_file(&of_dev->dev, &dev_attr_slots_temperature);
-       device_remove_file(&of_dev->dev, &dev_attr_slots_fan_pwm);
-
-       detach_i2c_chip(state->monitor);
-       state->monitor = NULL;
-}
-
-
 static int call_critical_overtemp(void)
 {
        char *argv[] = { critical_overtemp_path, NULL };
@@ -1791,17 +1620,14 @@ static int main_control_loop(void *x)
                goto out;
        }
 
-       /* Set the PCI fan once for now on non-RackMac */
-       if (!rackmac)
-               set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
+       /* Set the PCI fan once for now */
+       set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
 
        /* Initialize ADCs */
        initialize_adc(&cpu_state[0]);
        if (cpu_state[1].monitor != NULL)
                initialize_adc(&cpu_state[1]);
 
-       fcu_tickle_ticks = FCU_TICKLE_TICKS;
-
        up(&driver_lock);
 
        while (state == state_attached) {
@@ -1811,12 +1637,6 @@ static int main_control_loop(void *x)
 
                down(&driver_lock);
 
-               /* Tickle the FCU just in case */
-               if (--fcu_tickle_ticks < 0) {
-                       fcu_tickle_ticks = FCU_TICKLE_TICKS;
-                       tickle_fcu();
-               }
-
                /* First, we always calculate the new DIMMs state on an Xserve */
                if (rackmac)
                        do_monitor_dimms(&dimms_state);
@@ -1837,9 +1657,7 @@ static int main_control_loop(void *x)
                }
                /* Then, the rest */
                do_monitor_backside(&backside_state);
-               if (rackmac)
-                       do_monitor_slots(&slots_state);
-               else
+               if (!rackmac)
                        do_monitor_drives(&drives_state);
                up(&driver_lock);
 
@@ -1881,7 +1699,6 @@ static void dispose_control_loops(void)
        dispose_cpu_state(&cpu_state[1]);
        dispose_backside_state(&backside_state);
        dispose_drives_state(&drives_state);
-       dispose_slots_state(&slots_state);
        dispose_dimms_state(&dimms_state);
 }
 
@@ -1931,8 +1748,6 @@ static int create_control_loops(void)
                goto fail;
        if (rackmac && init_dimms_state(&dimms_state))
                goto fail;
-       if (rackmac && init_slots_state(&slots_state))
-               goto fail;
        if (!rackmac && init_drives_state(&drives_state))
                goto fail;