X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=drivers%2Fmacintosh%2Ftherm_pm72.c;h=817607e2af6a9c89193cc390ab16d2455dc7a0f7;hb=73f38fe1b563a9d23ffacbda7b51decf41b0c49c;hp=97807be6422bd09d668105ac326eb8779fcf943f;hpb=a33ca23231a37e28d15da9546b1f3e83dc48284b;p=safe%2Fjmp%2Flinux-2.6 diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index 97807be..817607e 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -95,36 +95,46 @@ * - 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 #include #include #include #include #include #include -#include #include #include #include -#include #include #include #include #include -#include +#include +#include +#include +#include #include #include #include #include #include -#include #include #include "therm_pm72.h" -#define VERSION "1.2b2" +#define VERSION "1.3" #undef DEBUG @@ -149,16 +159,18 @@ 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; -static pid_t ctrl_task; +static struct task_struct *ctrl_task; static struct completion ctrl_complete; static int critical_state; static int rackmac; static s32 dimm_output_clamp; - -static DECLARE_MUTEX(driver_lock); +static int fcu_rpm_shift; +static int fcu_tickle_ticks; +static DEFINE_MUTEX(driver_lock); /* * We have 3 types of CPU PID control. One is "split" old style control @@ -284,7 +296,6 @@ static int therm_pm72_detach(struct i2c_adapter *adapter); static struct i2c_driver therm_pm72_driver = { .driver = { - .owner = THIS_MODULE, .name = "therm_pm72", }, .attach_adapter = therm_pm72_attach, @@ -309,10 +320,9 @@ static struct i2c_client *attach_i2c_chip(int id, const char *name) if (adap == NULL) return NULL; - clt = kmalloc(sizeof(struct i2c_client), GFP_KERNEL); + clt = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); if (clt == NULL) return NULL; - memset(clt, 0, sizeof(struct i2c_client)); clt->addr = (id >> 1) & 0x7f; clt->adapter = adap; @@ -499,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; @@ -513,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; @@ -555,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) @@ -613,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 @@ -621,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 @@ -631,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 = of_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; } @@ -690,9 +730,9 @@ static void fetch_cpu_pumps_minmax(void) static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \ { \ ssize_t r; \ - down(&driver_lock); \ + mutex_lock(&driver_lock); \ r = sprintf(buf, "%d.%03d", FIX32TOPRINT(data)); \ - up(&driver_lock); \ + mutex_unlock(&driver_lock); \ return r; \ } #define BUILD_SHOW_FUNC_INT(name, data) \ @@ -719,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); @@ -739,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); /* @@ -1080,6 +1126,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; @@ -1109,6 +1158,8 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state) */ static int init_cpu_state(struct cpu_pid_state *state, int index) { + int err; + state->index = index; state->first = 1; state->rpm = (cpu_pid_type == CPU_PID_TYPE_RACKMAC) ? 4000 : 1000; @@ -1134,18 +1185,21 @@ static int init_cpu_state(struct cpu_pid_state *state, int index) DBG("CPU %d Using %d power history entries\n", index, state->count_power); if (index == 0) { - device_create_file(&of_dev->dev, &dev_attr_cpu0_temperature); - device_create_file(&of_dev->dev, &dev_attr_cpu0_voltage); - device_create_file(&of_dev->dev, &dev_attr_cpu0_current); - device_create_file(&of_dev->dev, &dev_attr_cpu0_exhaust_fan_rpm); - device_create_file(&of_dev->dev, &dev_attr_cpu0_intake_fan_rpm); + err = device_create_file(&of_dev->dev, &dev_attr_cpu0_temperature); + err |= device_create_file(&of_dev->dev, &dev_attr_cpu0_voltage); + err |= device_create_file(&of_dev->dev, &dev_attr_cpu0_current); + err |= device_create_file(&of_dev->dev, &dev_attr_cpu0_exhaust_fan_rpm); + err |= device_create_file(&of_dev->dev, &dev_attr_cpu0_intake_fan_rpm); } else { - device_create_file(&of_dev->dev, &dev_attr_cpu1_temperature); - device_create_file(&of_dev->dev, &dev_attr_cpu1_voltage); - device_create_file(&of_dev->dev, &dev_attr_cpu1_current); - device_create_file(&of_dev->dev, &dev_attr_cpu1_exhaust_fan_rpm); - device_create_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm); + err = device_create_file(&of_dev->dev, &dev_attr_cpu1_temperature); + err |= device_create_file(&of_dev->dev, &dev_attr_cpu1_voltage); + err |= device_create_file(&of_dev->dev, &dev_attr_cpu1_current); + err |= device_create_file(&of_dev->dev, &dev_attr_cpu1_exhaust_fan_rpm); + err |= device_create_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm); } + if (err) + printk(KERN_WARNING "Failed to create some of the atribute" + "files for CPU %d\n", index); return 0; fail: @@ -1281,6 +1335,7 @@ static int init_backside_state(struct backside_pid_state *state) { struct device_node *u3; int u3h = 1; /* conservative by default */ + int err; /* * There are different PID params for machines with U3 and machines @@ -1288,7 +1343,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 = of_get_property(u3, "device-rev", NULL); if (vers) if (((*vers) & 0x3f) < 0x34) u3h = 0; @@ -1332,8 +1387,11 @@ static int init_backside_state(struct backside_pid_state *state) if (state->monitor == NULL) return -ENODEV; - device_create_file(&of_dev->dev, &dev_attr_backside_temperature); - device_create_file(&of_dev->dev, &dev_attr_backside_fan_pwm); + err = device_create_file(&of_dev->dev, &dev_attr_backside_temperature); + err |= device_create_file(&of_dev->dev, &dev_attr_backside_fan_pwm); + if (err) + printk(KERN_WARNING "Failed to create attribute file(s)" + " for backside fan\n"); return 0; } @@ -1378,7 +1436,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)); @@ -1443,6 +1502,8 @@ static void do_monitor_drives(struct drives_pid_state *state) */ static int init_drives_state(struct drives_pid_state *state) { + int err; + state->ticks = 1; state->first = 1; state->rpm = 1000; @@ -1451,8 +1512,11 @@ static int init_drives_state(struct drives_pid_state *state) if (state->monitor == NULL) return -ENODEV; - device_create_file(&of_dev->dev, &dev_attr_drives_temperature); - device_create_file(&of_dev->dev, &dev_attr_drives_fan_rpm); + err = device_create_file(&of_dev->dev, &dev_attr_drives_temperature); + err |= device_create_file(&of_dev->dev, &dev_attr_drives_fan_rpm); + if (err) + printk(KERN_WARNING "Failed to create attribute file(s)" + " for drives bay fan\n"); return 0; } @@ -1573,13 +1637,15 @@ static int init_dimms_state(struct dimm_pid_state *state) if (state->monitor == NULL) return -ENODEV; - device_create_file(&of_dev->dev, &dev_attr_dimms_temperature); + if (device_create_file(&of_dev->dev, &dev_attr_dimms_temperature)) + printk(KERN_WARNING "Failed to create attribute file" + " for DIMM temperature\n"); return 0; } /* - * 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) { @@ -1592,6 +1658,132 @@ 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) +{ + int err; + + 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; + + err = device_create_file(&of_dev->dev, &dev_attr_slots_temperature); + err |= device_create_file(&of_dev->dev, &dev_attr_slots_fan_pwm); + if (err) + printk(KERN_WARNING "Failed to create attribute file(s)" + " for slots bay fan\n"); + + 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 }; @@ -1600,7 +1792,8 @@ static int call_critical_overtemp(void) "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL }; - return call_usermodehelper(critical_overtemp_path, argv, envp, 0); + return call_usermodehelper(critical_overtemp_path, + argv, envp, UMH_WAIT_EXEC); } @@ -1609,34 +1802,41 @@ static int call_critical_overtemp(void) */ static int main_control_loop(void *x) { - daemonize("kfand"); - DBG("main_control_loop started\n"); - down(&driver_lock); + mutex_lock(&driver_lock); if (start_fcu() < 0) { printk(KERN_ERR "kfand: failed to start FCU\n"); - up(&driver_lock); + mutex_unlock(&driver_lock); 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]); - up(&driver_lock); + fcu_tickle_ticks = FCU_TICKLE_TICKS; + + mutex_unlock(&driver_lock); while (state == state_attached) { unsigned long elapsed, start; start = jiffies; - down(&driver_lock); + mutex_lock(&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) @@ -1658,9 +1858,11 @@ 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); + mutex_unlock(&driver_lock); if (critical_state == 1) { printk(KERN_WARNING "Temperature control detected a critical condition\n"); @@ -1700,6 +1902,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); } @@ -1749,6 +1952,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; @@ -1772,7 +1977,7 @@ static void start_control_loops(void) { init_completion(&ctrl_complete); - ctrl_task = kernel_thread(main_control_loop, NULL, SIGCHLD | CLONE_KERNEL); + ctrl_task = kthread_run(main_control_loop, NULL, "kfand"); } /* @@ -1780,7 +1985,7 @@ static void start_control_loops(void) */ static void stop_control_loops(void) { - if (ctrl_task != 0) + if (ctrl_task) wait_for_completion(&ctrl_complete); } @@ -1815,13 +2020,13 @@ static void detach_fcu(void) */ static int therm_pm72_attach(struct i2c_adapter *adapter) { - down(&driver_lock); + mutex_lock(&driver_lock); /* Check state */ if (state == state_detached) state = state_attaching; if (state != state_attaching) { - up(&driver_lock); + mutex_unlock(&driver_lock); return 0; } @@ -1850,7 +2055,7 @@ static int therm_pm72_attach(struct i2c_adapter *adapter) state = state_attached; start_control_loops(); } - up(&driver_lock); + mutex_unlock(&driver_lock); return 0; } @@ -1861,16 +2066,16 @@ static int therm_pm72_attach(struct i2c_adapter *adapter) */ static int therm_pm72_detach(struct i2c_adapter *adapter) { - down(&driver_lock); + mutex_lock(&driver_lock); if (state != state_detached) state = state_detaching; /* Stop control loops if any */ DBG("stopping control loops\n"); - up(&driver_lock); + mutex_unlock(&driver_lock); stop_control_loops(); - down(&driver_lock); + mutex_lock(&driver_lock); if (u3_0 != NULL && !strcmp(adapter->name, "u3 0")) { DBG("lost U3-0, disposing control loops\n"); @@ -1886,7 +2091,7 @@ static int therm_pm72_detach(struct i2c_adapter *adapter) if (u3_0 == NULL && u3_1 == NULL) state = state_detached; - up(&driver_lock); + mutex_unlock(&driver_lock); return 0; } @@ -1927,8 +2132,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); @@ -1944,8 +2149,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 = of_get_property(np, "location", NULL); + reg = of_get_property(np, "reg", NULL); if (loc == NULL || reg == NULL) continue; DBG(" matching location: %s, reg: 0x%08x\n", loc, *reg); @@ -1989,18 +2194,13 @@ static void fcu_lookup_fans(struct device_node *fcu_node) 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) @@ -2057,14 +2257,14 @@ static int __init therm_pm72_init(void) 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);