fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / macintosh / therm_pm72.c
index 82336a5..0d3c1f9 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 <asm/system.h>
 #include <asm/sections.h>
 #include <asm/of_device.h>
+#include <asm/macio.h>
+#include <asm/of_platform.h>
 
 #include "therm_pm72.h"
 
-#define VERSION "1.2b2"
+#define VERSION "1.3"
 
 #undef DEBUG
 
@@ -148,6 +158,7 @@ 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;
@@ -156,7 +167,8 @@ 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);
 
 /*
@@ -282,9 +294,9 @@ static int therm_pm72_detach(struct i2c_adapter *adapter);
 
 static struct i2c_driver therm_pm72_driver =
 {
-       .owner          = THIS_MODULE,
-       .name           = "therm_pm72",
-       .flags          = I2C_DF_NOTIFY,
+       .driver = {
+               .name   = "therm_pm72",
+       },
        .attach_adapter = therm_pm72_attach,
        .detach_adapter = therm_pm72_detach,
 };
@@ -497,13 +509,20 @@ 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;
+       int rc, id, min, max;
 
        if (fcu_fans[fan_index].type != FCU_FAN_RPM)
                return -EINVAL;
@@ -511,12 +530,15 @@ static int set_rpm_fan(int fan_index, int rpm)
        if (id == FCU_FAN_ABSENT_ID)
                return -EINVAL;
 
-       if (rpm < 300)
-               rpm = 300;
-       else if (rpm > 8191)
-               rpm = 8191;
-       buf[0] = rpm >> 5;
-       buf[1] = rpm << 3;
+       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;
        rc = fan_write_reg(0x10 + (id * 2), buf, 2);
        if (rc < 0)
                return -EIO;
@@ -553,7 +575,7 @@ static int get_rpm_fan(int fan_index, int programmed)
        if (rc != 2)
                return -EIO;
 
-       return (buf[0] << 5) | buf[1] >> 3;
+       return (buf[0] << (8 - fcu_rpm_shift)) | buf[1] >> fcu_rpm_shift;
 }
 
 static int set_pwm_fan(int fan_index, int pwm)
@@ -611,6 +633,26 @@ 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
@@ -619,7 +661,7 @@ static int read_eeprom(int cpu, struct mpu_data *out)
 {
        struct device_node *np;
        char nodename[64];
-       u8 *data;
+       const u8 *data;
        int len;
 
        /* prom.c routine for finding a node by path is a bit brain dead
@@ -629,12 +671,12 @@ static int read_eeprom(int cpu, struct mpu_data *out)
        sprintf(nodename, "/u3@0,f8000000/i2c@f8001000/cpuid@a%d", cpu ? 2 : 0);
        np = of_find_node_by_path(nodename);
        if (np == NULL) {
-               printk(KERN_ERR "therm_pm72: Failed to retreive cpuid node from device-tree\n");
+               printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid node from device-tree\n");
                return -ENODEV;
        }
-       data = (u8 *)get_property(np, "cpuid", &len);
+       data = get_property(np, "cpuid", &len);
        if (data == NULL) {
-               printk(KERN_ERR "therm_pm72: Failed to retreive cpuid property from device-tree\n");
+               printk(KERN_ERR "therm_pm72: Failed to retrieve cpuid property from device-tree\n");
                of_node_put(np);
                return -ENODEV;
        }
@@ -685,7 +727,7 @@ static void fetch_cpu_pumps_minmax(void)
  * the input twice... I accept patches :)
  */
 #define BUILD_SHOW_FUNC_FIX(name, data)                                \
-static ssize_t show_##name(struct device *dev, char *buf)      \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)       \
 {                                                              \
        ssize_t r;                                              \
        down(&driver_lock);                                     \
@@ -694,7 +736,7 @@ static ssize_t show_##name(struct device *dev, char *buf)   \
        return r;                                               \
 }
 #define BUILD_SHOW_FUNC_INT(name, data)                                \
-static ssize_t show_##name(struct device *dev, char *buf)      \
+static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf)       \
 {                                                              \
        return sprintf(buf, "%d", data);                        \
 }
@@ -717,6 +759,9 @@ 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);
@@ -737,6 +782,9 @@ 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);
 
 /*
@@ -922,17 +970,23 @@ static void do_monitor_cpu_combined(void)
        if (temp_combi >= ((state0->mpu.tmax + 8) << 16)) {
                printk(KERN_WARNING "Warning ! Temperature way above maximum (%d) !\n",
                       temp_combi >> 16);
-               state0->overtemp = CPU_MAX_OVERTEMP;
-       } else if (temp_combi > (state0->mpu.tmax << 16))
+               state0->overtemp += CPU_MAX_OVERTEMP / 4;
+       } else if (temp_combi > (state0->mpu.tmax << 16)) {
                state0->overtemp++;
-       else
+               printk(KERN_WARNING "Temperature %d above max %d. overtemp %d\n",
+                      temp_combi >> 16, state0->mpu.tmax, state0->overtemp);
+       } else {
+               if (state0->overtemp)
+                       printk(KERN_WARNING "Temperature back down to %d\n",
+                              temp_combi >> 16);
                state0->overtemp = 0;
+       }
        if (state0->overtemp >= CPU_MAX_OVERTEMP)
                critical_state = 1;
        if (state0->overtemp > 0) {
                state0->rpm = state0->mpu.rmaxn_exhaust_fan;
                state0->intake_rpm = intake = state0->mpu.rmaxn_intake_fan;
-               pump = state0->pump_min;
+               pump = state0->pump_max;
                goto do_set_fans;
        }
 
@@ -997,11 +1051,17 @@ static void do_monitor_cpu_split(struct cpu_pid_state *state)
                printk(KERN_WARNING "Warning ! CPU %d temperature way above maximum"
                       " (%d) !\n",
                       state->index, temp >> 16);
-               state->overtemp = CPU_MAX_OVERTEMP;
-       } else if (temp > (state->mpu.tmax << 16))
+               state->overtemp += CPU_MAX_OVERTEMP / 4;
+       } else if (temp > (state->mpu.tmax << 16)) {
                state->overtemp++;
-       else
+               printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n",
+                      state->index, temp >> 16, state->mpu.tmax, state->overtemp);
+       } else {
+               if (state->overtemp)
+                       printk(KERN_WARNING "CPU %d temperature back down to %d\n",
+                              state->index, temp >> 16);
                state->overtemp = 0;
+       }
        if (state->overtemp >= CPU_MAX_OVERTEMP)
                critical_state = 1;
        if (state->overtemp > 0) {
@@ -1059,11 +1119,17 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state)
                printk(KERN_WARNING "Warning ! CPU %d temperature way above maximum"
                       " (%d) !\n",
                       state->index, temp >> 16);
-               state->overtemp = CPU_MAX_OVERTEMP;
-       } else if (temp > (state->mpu.tmax << 16))
+               state->overtemp = CPU_MAX_OVERTEMP / 4;
+       } else if (temp > (state->mpu.tmax << 16)) {
                state->overtemp++;
-       else
+               printk(KERN_WARNING "CPU %d temperature %d above max %d. overtemp %d\n",
+                      state->index, temp >> 16, state->mpu.tmax, state->overtemp);
+       } else {
+               if (state->overtemp)
+                       printk(KERN_WARNING "CPU %d temperature back down to %d\n",
+                              state->index, temp >> 16);
                state->overtemp = 0;
+       }
        if (state->overtemp >= CPU_MAX_OVERTEMP)
                critical_state = 1;
        if (state->overtemp > 0) {
@@ -1078,6 +1144,9 @@ 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;
@@ -1286,7 +1355,7 @@ static int init_backside_state(struct backside_pid_state *state)
         */
        u3 = of_find_node_by_path("/u3@0,f8000000");
        if (u3 != NULL) {
-               u32 *vers = (u32 *)get_property(u3, "device-rev", NULL);
+               const u32 *vers = get_property(u3, "device-rev", NULL);
                if (vers)
                        if (((*vers) & 0x3f) < 0x34)
                                u3h = 0;
@@ -1376,7 +1445,8 @@ 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));
@@ -1577,7 +1647,7 @@ static int init_dimms_state(struct dimm_pid_state *state)
 }
 
 /*
- * Dispose of the state data for the drives control loop
+ * Dispose of the state data for the DIMM control loop
  */
 static void dispose_dimms_state(struct dimm_pid_state *state)
 {
@@ -1590,6 +1660,127 @@ 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 };
@@ -1619,14 +1810,17 @@ static int main_control_loop(void *x)
                goto out;
        }
 
-       /* Set the PCI fan once for now */
-       set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
+       /* Set the PCI fan once for now on non-RackMac */
+       if (!rackmac)
+               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) {
@@ -1636,6 +1830,12 @@ 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);
@@ -1656,7 +1856,9 @@ static int main_control_loop(void *x)
                }
                /* Then, the rest */
                do_monitor_backside(&backside_state);
-               if (!rackmac)
+               if (rackmac)
+                       do_monitor_slots(&slots_state);
+               else
                        do_monitor_drives(&drives_state);
                up(&driver_lock);
 
@@ -1677,10 +1879,9 @@ static int main_control_loop(void *x)
                }
 
                // FIXME: Deal with signals
-               set_current_state(TASK_INTERRUPTIBLE);
                elapsed = jiffies - start;
                if (elapsed < HZ)
-                       schedule_timeout(HZ - elapsed);
+                       schedule_timeout_interruptible(HZ - elapsed);
        }
 
  out:
@@ -1699,6 +1900,7 @@ 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);
 }
 
@@ -1748,6 +1950,8 @@ 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;
 
@@ -1926,8 +2130,8 @@ static void fcu_lookup_fans(struct device_node *fcu_node)
 
        while ((np = of_get_next_child(fcu_node, np)) != NULL) {
                int type = -1;
-               char *loc;
-               u32 *reg;
+               const char *loc;
+               const u32 *reg;
 
                DBG(" control: %s, type: %s\n", np->name, np->type);
 
@@ -1943,8 +2147,8 @@ static void fcu_lookup_fans(struct device_node *fcu_node)
                        continue;
 
                /* Lookup for a matching location */
-               loc = (char *)get_property(np, "location", NULL);
-               reg = (u32 *)get_property(np, "reg", NULL);
+               loc = get_property(np, "location", NULL);
+               reg = get_property(np, "reg", NULL);
                if (loc == NULL || reg == NULL)
                        continue;
                DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg);
@@ -1986,20 +2190,15 @@ static void fcu_lookup_fans(struct device_node *fcu_node)
        }
 }
 
-static int fcu_of_probe(struct of_device* dev, const struct of_match *match)
+static int fcu_of_probe(struct of_device* dev, const struct of_device_id *match)
 {
-       int rc;
-
        state = state_detached;
 
        /* Lookup the fans in the device tree */
        fcu_lookup_fans(dev->node);
 
        /* Add the driver */
-       rc = i2c_add_driver(&therm_pm72_driver);
-       if (rc < 0)
-               return rc;
-       return 0;
+       return i2c_add_driver(&therm_pm72_driver);
 }
 
 static int fcu_of_remove(struct of_device* dev)
@@ -2009,12 +2208,10 @@ static int fcu_of_remove(struct of_device* dev)
        return 0;
 }
 
-static struct of_match fcu_of_match[] = 
+static struct of_device_id fcu_match[] = 
 {
        {
-       .name           = OF_ANY_MATCH,
        .type           = "fcu",
-       .compatible     = OF_ANY_MATCH
        },
        {},
 };
@@ -2022,7 +2219,7 @@ static struct of_match fcu_of_match[] =
 static struct of_platform_driver fcu_of_platform_driver = 
 {
        .name           = "temperature",
-       .match_table    = fcu_of_match,
+       .match_table    = fcu_match,
        .probe          = fcu_of_probe,
        .remove         = fcu_of_remove
 };
@@ -2052,20 +2249,20 @@ static int __init therm_pm72_init(void)
                            return -ENODEV;
                }
        }
-       of_dev = of_platform_device_create(np, "temperature");
+       of_dev = of_platform_device_create(np, "temperature", NULL);
        if (of_dev == NULL) {
                printk(KERN_ERR "Can't register FCU platform device !\n");
                return -ENODEV;
        }
 
-       of_register_driver(&fcu_of_platform_driver);
+       of_register_platform_driver(&fcu_of_platform_driver);
        
        return 0;
 }
 
 static void __exit therm_pm72_exit(void)
 {
-       of_unregister_driver(&fcu_of_platform_driver);
+       of_unregister_platform_driver(&fcu_of_platform_driver);
 
        if (of_dev)
                of_device_unregister(of_dev);