1 /* 2 * Device driver for the i2c thermostat found on the iBook G4, Albook G4 3 * 4 * Copyright (C) 2003, 2004 Colin Leroy, Rasmus Rohde, Benjamin Herrenschmidt 5 * 6 * Documentation from 115254175ADT7467_pra.pdf and 3686221171167ADT7460_b.pdf 7 * http://www.onsemi.com/PowerSolutions/product.do?id=ADT7467 8 * http://www.onsemi.com/PowerSolutions/product.do?id=ADT7460 9 * 10 */ 11 12 #include <linux/types.h> 13 #include <linux/module.h> 14 #include <linux/errno.h> 15 #include <linux/kernel.h> 16 #include <linux/delay.h> 17 #include <linux/sched.h> 18 #include <linux/i2c.h> 19 #include <linux/slab.h> 20 #include <linux/init.h> 21 #include <linux/spinlock.h> 22 #include <linux/wait.h> 23 #include <linux/suspend.h> 24 #include <linux/kthread.h> 25 #include <linux/moduleparam.h> 26 #include <linux/freezer.h> 27 #include <linux/of_platform.h> 28 29 #include <asm/prom.h> 30 #include <asm/machdep.h> 31 #include <asm/io.h> 32 #include <asm/system.h> 33 #include <asm/sections.h> 34 35 #undef DEBUG 36 37 #define CONFIG_REG 0x40 38 #define MANUAL_MASK 0xe0 39 #define AUTO_MASK 0x20 40 #define INVERT_MASK 0x10 41 42 static u8 TEMP_REG[3] = {0x26, 0x25, 0x27}; /* local, sensor1, sensor2 */ 43 static u8 LIMIT_REG[3] = {0x6b, 0x6a, 0x6c}; /* local, sensor1, sensor2 */ 44 static u8 MANUAL_MODE[2] = {0x5c, 0x5d}; 45 static u8 REM_CONTROL[2] = {0x00, 0x40}; 46 static u8 FAN_SPEED[2] = {0x28, 0x2a}; 47 static u8 FAN_SPD_SET[2] = {0x30, 0x31}; 48 49 static u8 default_limits_local[3] = {70, 50, 70}; /* local, sensor1, sensor2 */ 50 static u8 default_limits_chip[3] = {80, 65, 80}; /* local, sensor1, sensor2 */ 51 static const char *sensor_location[3]; 52 53 static int limit_adjust; 54 static int fan_speed = -1; 55 static int verbose; 56 57 MODULE_AUTHOR("Colin Leroy <colin@colino.net>"); 58 MODULE_DESCRIPTION("Driver for ADT746x thermostat in iBook G4 and " 59 "Powerbook G4 Alu"); 60 MODULE_LICENSE("GPL"); 61 62 module_param(limit_adjust, int, 0644); 63 MODULE_PARM_DESC(limit_adjust,"Adjust maximum temperatures (50 sensor1, 70 sensor2) " 64 "by N degrees."); 65 66 module_param(fan_speed, int, 0644); 67 MODULE_PARM_DESC(fan_speed,"Specify starting fan speed (0-255) " 68 "(default 64)"); 69 70 module_param(verbose, bool, 0); 71 MODULE_PARM_DESC(verbose,"Verbose log operations " 72 "(default 0)"); 73 74 struct thermostat { 75 struct i2c_client *clt; 76 u8 temps[3]; 77 u8 cached_temp[3]; 78 u8 initial_limits[3]; 79 u8 limits[3]; 80 int last_speed[2]; 81 int last_var[2]; 82 int pwm_inv[2]; 83 }; 84 85 static enum {ADT7460, ADT7467} therm_type; 86 static int therm_bus, therm_address; 87 static struct platform_device * of_dev; 88 static struct thermostat* thermostat; 89 static struct task_struct *thread_therm = NULL; 90 91 static void write_both_fan_speed(struct thermostat *th, int speed); 92 static void write_fan_speed(struct thermostat *th, int speed, int fan); 93 static void thermostat_create_files(void); 94 static void thermostat_remove_files(void); 95 96 static int 97 write_reg(struct thermostat* th, int reg, u8 data) 98 { 99 u8 tmp[2]; 100 int rc; 101 102 tmp[0] = reg; 103 tmp[1] = data; 104 rc = i2c_master_send(th->clt, (const char *)tmp, 2); 105 if (rc < 0) 106 return rc; 107 if (rc != 2) 108 return -ENODEV; 109 return 0; 110 } 111 112 static int 113 read_reg(struct thermostat* th, int reg) 114 { 115 u8 reg_addr, data; 116 int rc; 117 118 reg_addr = (u8)reg; 119 rc = i2c_master_send(th->clt, ®_addr, 1); 120 if (rc < 0) 121 return rc; 122 if (rc != 1) 123 return -ENODEV; 124 rc = i2c_master_recv(th->clt, (char *)&data, 1); 125 if (rc < 0) 126 return rc; 127 return data; 128 } 129 130 static struct i2c_driver thermostat_driver; 131 132 static int 133 attach_thermostat(struct i2c_adapter *adapter) 134 { 135 unsigned long bus_no; 136 struct i2c_board_info info; 137 struct i2c_client *client; 138 139 if (strncmp(adapter->name, "uni-n", 5)) 140 return -ENODEV; 141 bus_no = simple_strtoul(adapter->name + 6, NULL, 10); 142 if (bus_no != therm_bus) 143 return -ENODEV; 144 145 memset(&info, 0, sizeof(struct i2c_board_info)); 146 strlcpy(info.type, "therm_adt746x", I2C_NAME_SIZE); 147 info.addr = therm_address; 148 client = i2c_new_device(adapter, &info); 149 if (!client) 150 return -ENODEV; 151 152 /* 153 * Let i2c-core delete that device on driver removal. 154 * This is safe because i2c-core holds the core_lock mutex for us. 155 */ 156 list_add_tail(&client->detected, &thermostat_driver.clients); 157 return 0; 158 } 159 160 static int 161 remove_thermostat(struct i2c_client *client) 162 { 163 struct thermostat *th = i2c_get_clientdata(client); 164 int i; 165 166 thermostat_remove_files(); 167 168 if (thread_therm != NULL) { 169 kthread_stop(thread_therm); 170 } 171 172 printk(KERN_INFO "adt746x: Putting max temperatures back from " 173 "%d, %d, %d to %d, %d, %d\n", 174 th->limits[0], th->limits[1], th->limits[2], 175 th->initial_limits[0], th->initial_limits[1], 176 th->initial_limits[2]); 177 178 for (i = 0; i < 3; i++) 179 write_reg(th, LIMIT_REG[i], th->initial_limits[i]); 180 181 write_both_fan_speed(th, -1); 182 183 thermostat = NULL; 184 185 kfree(th); 186 187 return 0; 188 } 189 190 static int read_fan_speed(struct thermostat *th, u8 addr) 191 { 192 u8 tmp[2]; 193 u16 res; 194 195 /* should start with low byte */ 196 tmp[1] = read_reg(th, addr); 197 tmp[0] = read_reg(th, addr + 1); 198 199 res = tmp[1] + (tmp[0] << 8); 200 /* "a value of 0xffff means that the fan has stopped" */ 201 return (res == 0xffff ? 0 : (90000*60)/res); 202 } 203 204 static void write_both_fan_speed(struct thermostat *th, int speed) 205 { 206 write_fan_speed(th, speed, 0); 207 if (therm_type == ADT7460) 208 write_fan_speed(th, speed, 1); 209 } 210 211 static void write_fan_speed(struct thermostat *th, int speed, int fan) 212 { 213 u8 manual; 214 215 if (speed > 0xff) 216 speed = 0xff; 217 else if (speed < -1) 218 speed = 0; 219 220 if (therm_type == ADT7467 && fan == 1) 221 return; 222 223 if (th->last_speed[fan] != speed) { 224 if (verbose) { 225 if (speed == -1) 226 printk(KERN_DEBUG "adt746x: Setting speed to automatic " 227 "for %s fan.\n", sensor_location[fan+1]); 228 else 229 printk(KERN_DEBUG "adt746x: Setting speed to %d " 230 "for %s fan.\n", speed, sensor_location[fan+1]); 231 } 232 } else 233 return; 234 235 if (speed >= 0) { 236 manual = read_reg(th, MANUAL_MODE[fan]); 237 manual &= ~INVERT_MASK; 238 write_reg(th, MANUAL_MODE[fan], 239 manual | MANUAL_MASK | th->pwm_inv[fan]); 240 write_reg(th, FAN_SPD_SET[fan], speed); 241 } else { 242 /* back to automatic */ 243 if(therm_type == ADT7460) { 244 manual = read_reg(th, 245 MANUAL_MODE[fan]) & (~MANUAL_MASK); 246 manual &= ~INVERT_MASK; 247 manual |= th->pwm_inv[fan]; 248 write_reg(th, 249 MANUAL_MODE[fan], manual|REM_CONTROL[fan]); 250 } else { 251 manual = read_reg(th, MANUAL_MODE[fan]); 252 manual &= ~INVERT_MASK; 253 manual |= th->pwm_inv[fan]; 254 write_reg(th, MANUAL_MODE[fan], manual&(~AUTO_MASK)); 255 } 256 } 257 258 th->last_speed[fan] = speed; 259 } 260 261 static void read_sensors(struct thermostat *th) 262 { 263 int i = 0; 264 265 for (i = 0; i < 3; i++) 266 th->temps[i] = read_reg(th, TEMP_REG[i]); 267 } 268 269 #ifdef DEBUG 270 static void display_stats(struct thermostat *th) 271 { 272 if (th->temps[0] != th->cached_temp[0] 273 || th->temps[1] != th->cached_temp[1] 274 || th->temps[2] != th->cached_temp[2]) { 275 printk(KERN_INFO "adt746x: Temperature infos:" 276 " thermostats: %d,%d,%d;" 277 " limits: %d,%d,%d;" 278 " fan speed: %d RPM\n", 279 th->temps[0], th->temps[1], th->temps[2], 280 th->limits[0], th->limits[1], th->limits[2], 281 read_fan_speed(th, FAN_SPEED[0])); 282 } 283 th->cached_temp[0] = th->temps[0]; 284 th->cached_temp[1] = th->temps[1]; 285 th->cached_temp[2] = th->temps[2]; 286 } 287 #endif 288 289 static void update_fans_speed (struct thermostat *th) 290 { 291 int lastvar = 0; /* last variation, for iBook */ 292 int i = 0; 293 294 /* we don't care about local sensor, so we start at sensor 1 */ 295 for (i = 1; i < 3; i++) { 296 int started = 0; 297 int fan_number = (therm_type == ADT7460 && i == 2); 298 int var = th->temps[i] - th->limits[i]; 299 300 if (var > -1) { 301 int step = (255 - fan_speed) / 7; 302 int new_speed = 0; 303 304 /* hysteresis : change fan speed only if variation is 305 * more than two degrees */ 306 if (abs(var - th->last_var[fan_number]) < 2) 307 continue; 308 309 started = 1; 310 new_speed = fan_speed + ((var-1)*step); 311 312 if (new_speed < fan_speed) 313 new_speed = fan_speed; 314 if (new_speed > 255) 315 new_speed = 255; 316 317 if (verbose) 318 printk(KERN_DEBUG "adt746x: Setting fans speed to %d " 319 "(limit exceeded by %d on %s)\n", 320 new_speed, var, 321 sensor_location[fan_number+1]); 322 write_both_fan_speed(th, new_speed); 323 th->last_var[fan_number] = var; 324 } else if (var < -2) { 325 /* don't stop fan if sensor2 is cold and sensor1 is not 326 * so cold (lastvar >= -1) */ 327 if (i == 2 && lastvar < -1) { 328 if (th->last_speed[fan_number] != 0) 329 if (verbose) 330 printk(KERN_DEBUG "adt746x: Stopping " 331 "fans.\n"); 332 write_both_fan_speed(th, 0); 333 } 334 } 335 336 lastvar = var; 337 338 if (started) 339 return; /* we don't want to re-stop the fan 340 * if sensor1 is heating and sensor2 is not */ 341 } 342 } 343 344 static int monitor_task(void *arg) 345 { 346 struct thermostat* th = arg; 347 348 set_freezable(); 349 while(!kthread_should_stop()) { 350 try_to_freeze(); 351 msleep_interruptible(2000); 352 353 #ifndef DEBUG 354 if (fan_speed != -1) 355 read_sensors(th); 356 #else 357 read_sensors(th); 358 #endif 359 360 if (fan_speed != -1) 361 update_fans_speed(th); 362 363 #ifdef DEBUG 364 display_stats(th); 365 #endif 366 367 } 368 369 return 0; 370 } 371 372 static void set_limit(struct thermostat *th, int i) 373 { 374 /* Set sensor1 limit higher to avoid powerdowns */ 375 th->limits[i] = default_limits_chip[i] + limit_adjust; 376 write_reg(th, LIMIT_REG[i], th->limits[i]); 377 378 /* set our limits to normal */ 379 th->limits[i] = default_limits_local[i] + limit_adjust; 380 } 381 382 static int probe_thermostat(struct i2c_client *client, 383 const struct i2c_device_id *id) 384 { 385 struct thermostat* th; 386 int rc; 387 int i; 388 389 if (thermostat) 390 return 0; 391 392 th = kzalloc(sizeof(struct thermostat), GFP_KERNEL); 393 if (!th) 394 return -ENOMEM; 395 396 i2c_set_clientdata(client, th); 397 th->clt = client; 398 399 rc = read_reg(th, CONFIG_REG); 400 if (rc < 0) { 401 dev_err(&client->dev, "Thermostat failed to read config!\n"); 402 kfree(th); 403 return -ENODEV; 404 } 405 406 /* force manual control to start the fan quieter */ 407 if (fan_speed == -1) 408 fan_speed = 64; 409 410 if(therm_type == ADT7460) { 411 printk(KERN_INFO "adt746x: ADT7460 initializing\n"); 412 /* The 7460 needs to be started explicitly */ 413 write_reg(th, CONFIG_REG, 1); 414 } else 415 printk(KERN_INFO "adt746x: ADT7467 initializing\n"); 416 417 for (i = 0; i < 3; i++) { 418 th->initial_limits[i] = read_reg(th, LIMIT_REG[i]); 419 set_limit(th, i); 420 } 421 422 printk(KERN_INFO "adt746x: Lowering max temperatures from %d, %d, %d" 423 " to %d, %d, %d\n", 424 th->initial_limits[0], th->initial_limits[1], 425 th->initial_limits[2], th->limits[0], th->limits[1], 426 th->limits[2]); 427 428 thermostat = th; 429 430 /* record invert bit status because fw can corrupt it after suspend */ 431 th->pwm_inv[0] = read_reg(th, MANUAL_MODE[0]) & INVERT_MASK; 432 th->pwm_inv[1] = read_reg(th, MANUAL_MODE[1]) & INVERT_MASK; 433 434 /* be sure to really write fan speed the first time */ 435 th->last_speed[0] = -2; 436 th->last_speed[1] = -2; 437 th->last_var[0] = -80; 438 th->last_var[1] = -80; 439 440 if (fan_speed != -1) { 441 /* manual mode, stop fans */ 442 write_both_fan_speed(th, 0); 443 } else { 444 /* automatic mode */ 445 write_both_fan_speed(th, -1); 446 } 447 448 thread_therm = kthread_run(monitor_task, th, "kfand"); 449 450 if (thread_therm == ERR_PTR(-ENOMEM)) { 451 printk(KERN_INFO "adt746x: Kthread creation failed\n"); 452 thread_therm = NULL; 453 return -ENOMEM; 454 } 455 456 thermostat_create_files(); 457 458 return 0; 459 } 460 461 static const struct i2c_device_id therm_adt746x_id[] = { 462 { "therm_adt746x", 0 }, 463 { } 464 }; 465 466 static struct i2c_driver thermostat_driver = { 467 .driver = { 468 .name = "therm_adt746x", 469 }, 470 .attach_adapter = attach_thermostat, 471 .probe = probe_thermostat, 472 .remove = remove_thermostat, 473 .id_table = therm_adt746x_id, 474 }; 475 476 /* 477 * Now, unfortunately, sysfs doesn't give us a nice void * we could 478 * pass around to the attribute functions, so we don't really have 479 * choice but implement a bunch of them... 480 * 481 * FIXME, it does now... 482 */ 483 #define BUILD_SHOW_FUNC_INT(name, data) \ 484 static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \ 485 { \ 486 return sprintf(buf, "%d\n", data); \ 487 } 488 489 #define BUILD_SHOW_FUNC_STR(name, data) \ 490 static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \ 491 { \ 492 return sprintf(buf, "%s\n", data); \ 493 } 494 495 #define BUILD_SHOW_FUNC_FAN(name, data) \ 496 static ssize_t show_##name(struct device *dev, struct device_attribute *attr, char *buf) \ 497 { \ 498 return sprintf(buf, "%d (%d rpm)\n", \ 499 thermostat->last_speed[data], \ 500 read_fan_speed(thermostat, FAN_SPEED[data]) \ 501 ); \ 502 } 503 504 #define BUILD_STORE_FUNC_DEG(name, data) \ 505 static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \ 506 { \ 507 int val; \ 508 int i; \ 509 val = simple_strtol(buf, NULL, 10); \ 510 printk(KERN_INFO "Adjusting limits by %d degrees\n", val); \ 511 limit_adjust = val; \ 512 for (i=0; i < 3; i++) \ 513 set_limit(thermostat, i); \ 514 return n; \ 515 } 516 517 #define BUILD_STORE_FUNC_INT(name, data) \ 518 static ssize_t store_##name(struct device *dev, struct device_attribute *attr, const char *buf, size_t n) \ 519 { \ 520 int val; \ 521 val = simple_strtol(buf, NULL, 10); \ 522 if (val < 0 || val > 255) \ 523 return -EINVAL; \ 524 printk(KERN_INFO "Setting specified fan speed to %d\n", val); \ 525 data = val; \ 526 return n; \ 527 } 528 529 BUILD_SHOW_FUNC_INT(sensor1_temperature, (read_reg(thermostat, TEMP_REG[1]))) 530 BUILD_SHOW_FUNC_INT(sensor2_temperature, (read_reg(thermostat, TEMP_REG[2]))) 531 BUILD_SHOW_FUNC_INT(sensor1_limit, thermostat->limits[1]) 532 BUILD_SHOW_FUNC_INT(sensor2_limit, thermostat->limits[2]) 533 BUILD_SHOW_FUNC_STR(sensor1_location, sensor_location[1]) 534 BUILD_SHOW_FUNC_STR(sensor2_location, sensor_location[2]) 535 536 BUILD_SHOW_FUNC_INT(specified_fan_speed, fan_speed) 537 BUILD_SHOW_FUNC_FAN(sensor1_fan_speed, 0) 538 BUILD_SHOW_FUNC_FAN(sensor2_fan_speed, 1) 539 540 BUILD_STORE_FUNC_INT(specified_fan_speed,fan_speed) 541 BUILD_SHOW_FUNC_INT(limit_adjust, limit_adjust) 542 BUILD_STORE_FUNC_DEG(limit_adjust, thermostat) 543 544 static DEVICE_ATTR(sensor1_temperature, S_IRUGO, 545 show_sensor1_temperature,NULL); 546 static DEVICE_ATTR(sensor2_temperature, S_IRUGO, 547 show_sensor2_temperature,NULL); 548 static DEVICE_ATTR(sensor1_limit, S_IRUGO, 549 show_sensor1_limit, NULL); 550 static DEVICE_ATTR(sensor2_limit, S_IRUGO, 551 show_sensor2_limit, NULL); 552 static DEVICE_ATTR(sensor1_location, S_IRUGO, 553 show_sensor1_location, NULL); 554 static DEVICE_ATTR(sensor2_location, S_IRUGO, 555 show_sensor2_location, NULL); 556 557 static DEVICE_ATTR(specified_fan_speed, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 558 show_specified_fan_speed,store_specified_fan_speed); 559 560 static DEVICE_ATTR(sensor1_fan_speed, S_IRUGO, 561 show_sensor1_fan_speed, NULL); 562 static DEVICE_ATTR(sensor2_fan_speed, S_IRUGO, 563 show_sensor2_fan_speed, NULL); 564 565 static DEVICE_ATTR(limit_adjust, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 566 show_limit_adjust, store_limit_adjust); 567 568 569 static int __init 570 thermostat_init(void) 571 { 572 struct device_node* np; 573 const u32 *prop; 574 int i = 0, offset = 0; 575 576 np = of_find_node_by_name(NULL, "fan"); 577 if (!np) 578 return -ENODEV; 579 if (of_device_is_compatible(np, "adt7460")) 580 therm_type = ADT7460; 581 else if (of_device_is_compatible(np, "adt7467")) 582 therm_type = ADT7467; 583 else { 584 of_node_put(np); 585 return -ENODEV; 586 } 587 588 prop = of_get_property(np, "hwsensor-params-version", NULL); 589 printk(KERN_INFO "adt746x: version %d (%ssupported)\n", *prop, 590 (*prop == 1)?"":"un"); 591 if (*prop != 1) { 592 of_node_put(np); 593 return -ENODEV; 594 } 595 596 prop = of_get_property(np, "reg", NULL); 597 if (!prop) { 598 of_node_put(np); 599 return -ENODEV; 600 } 601 602 /* look for bus either by path or using "reg" */ 603 if (strstr(np->full_name, "/i2c-bus@") != NULL) { 604 const char *tmp_bus = (strstr(np->full_name, "/i2c-bus@") + 9); 605 therm_bus = tmp_bus[0]-'0'; 606 } else { 607 therm_bus = ((*prop) >> 8) & 0x0f; 608 } 609 610 therm_address = ((*prop) & 0xff) >> 1; 611 612 printk(KERN_INFO "adt746x: Thermostat bus: %d, address: 0x%02x, " 613 "limit_adjust: %d, fan_speed: %d\n", 614 therm_bus, therm_address, limit_adjust, fan_speed); 615 616 if (of_get_property(np, "hwsensor-location", NULL)) { 617 for (i = 0; i < 3; i++) { 618 sensor_location[i] = of_get_property(np, 619 "hwsensor-location", NULL) + offset; 620 621 if (sensor_location[i] == NULL) 622 sensor_location[i] = ""; 623 624 printk(KERN_INFO "sensor %d: %s\n", i, sensor_location[i]); 625 offset += strlen(sensor_location[i]) + 1; 626 } 627 } else { 628 sensor_location[0] = "?"; 629 sensor_location[1] = "?"; 630 sensor_location[2] = "?"; 631 } 632 633 of_dev = of_platform_device_create(np, "temperatures", NULL); 634 of_node_put(np); 635 636 if (of_dev == NULL) { 637 printk(KERN_ERR "Can't register temperatures device !\n"); 638 return -ENODEV; 639 } 640 641 #ifndef CONFIG_I2C_POWERMAC 642 request_module("i2c-powermac"); 643 #endif 644 645 return i2c_add_driver(&thermostat_driver); 646 } 647 648 static void thermostat_create_files(void) 649 { 650 int err; 651 652 err = device_create_file(&of_dev->dev, &dev_attr_sensor1_temperature); 653 err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_temperature); 654 err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_limit); 655 err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_limit); 656 err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_location); 657 err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_location); 658 err |= device_create_file(&of_dev->dev, &dev_attr_limit_adjust); 659 err |= device_create_file(&of_dev->dev, &dev_attr_specified_fan_speed); 660 err |= device_create_file(&of_dev->dev, &dev_attr_sensor1_fan_speed); 661 if(therm_type == ADT7460) 662 err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed); 663 if (err) 664 printk(KERN_WARNING 665 "Failed to create tempertaure attribute file(s).\n"); 666 } 667 668 static void thermostat_remove_files(void) 669 { 670 if (of_dev) { 671 device_remove_file(&of_dev->dev, &dev_attr_sensor1_temperature); 672 device_remove_file(&of_dev->dev, &dev_attr_sensor2_temperature); 673 device_remove_file(&of_dev->dev, &dev_attr_sensor1_limit); 674 device_remove_file(&of_dev->dev, &dev_attr_sensor2_limit); 675 device_remove_file(&of_dev->dev, &dev_attr_sensor1_location); 676 device_remove_file(&of_dev->dev, &dev_attr_sensor2_location); 677 device_remove_file(&of_dev->dev, &dev_attr_limit_adjust); 678 device_remove_file(&of_dev->dev, &dev_attr_specified_fan_speed); 679 device_remove_file(&of_dev->dev, &dev_attr_sensor1_fan_speed); 680 681 if(therm_type == ADT7460) 682 device_remove_file(&of_dev->dev, 683 &dev_attr_sensor2_fan_speed); 684 685 } 686 } 687 688 static void __exit 689 thermostat_exit(void) 690 { 691 i2c_del_driver(&thermostat_driver); 692 of_device_unregister(of_dev); 693 } 694 695 module_init(thermostat_init); 696 module_exit(thermostat_exit); 697