diff options
| -rw-r--r-- | drivers/macintosh/therm_windtunnel.c | 126 |
1 files changed, 60 insertions, 66 deletions
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c index 3da0a02efd76..40023313a760 100644 --- a/drivers/macintosh/therm_windtunnel.c +++ b/drivers/macintosh/therm_windtunnel.c | |||
| @@ -48,16 +48,6 @@ | |||
| 48 | 48 | ||
| 49 | #define LOG_TEMP 0 /* continously log temperature */ | 49 | #define LOG_TEMP 0 /* continously log temperature */ |
| 50 | 50 | ||
| 51 | static int do_probe( struct i2c_adapter *adapter, int addr, int kind); | ||
| 52 | |||
| 53 | /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */ | ||
| 54 | static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, | ||
| 55 | 0x4c, 0x4d, 0x4e, 0x4f, | ||
| 56 | 0x2c, 0x2d, 0x2e, 0x2f, | ||
| 57 | I2C_CLIENT_END }; | ||
| 58 | |||
| 59 | I2C_CLIENT_INSMOD; | ||
| 60 | |||
| 61 | static struct { | 51 | static struct { |
| 62 | volatile int running; | 52 | volatile int running; |
| 63 | struct task_struct *poll_task; | 53 | struct task_struct *poll_task; |
| @@ -315,53 +305,54 @@ static int control_loop(void *dummy) | |||
| 315 | static int | 305 | static int |
| 316 | do_attach( struct i2c_adapter *adapter ) | 306 | do_attach( struct i2c_adapter *adapter ) |
| 317 | { | 307 | { |
| 318 | int ret = 0; | 308 | /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */ |
| 309 | static const unsigned short scan_ds1775[] = { | ||
| 310 | 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, | ||
| 311 | I2C_CLIENT_END | ||
| 312 | }; | ||
| 313 | static const unsigned short scan_adm1030[] = { | ||
| 314 | 0x2c, 0x2d, 0x2e, 0x2f, | ||
| 315 | I2C_CLIENT_END | ||
| 316 | }; | ||
| 319 | 317 | ||
| 320 | if( strncmp(adapter->name, "uni-n", 5) ) | 318 | if( strncmp(adapter->name, "uni-n", 5) ) |
| 321 | return 0; | 319 | return 0; |
| 322 | 320 | ||
| 323 | if( !x.running ) { | 321 | if( !x.running ) { |
| 324 | ret = i2c_probe( adapter, &addr_data, &do_probe ); | 322 | struct i2c_board_info info; |
| 323 | |||
| 324 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
| 325 | strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE); | ||
| 326 | i2c_new_probed_device(adapter, &info, scan_ds1775); | ||
| 327 | |||
| 328 | strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE); | ||
| 329 | i2c_new_probed_device(adapter, &info, scan_adm1030); | ||
| 330 | |||
| 325 | if( x.thermostat && x.fan ) { | 331 | if( x.thermostat && x.fan ) { |
| 326 | x.running = 1; | 332 | x.running = 1; |
| 327 | x.poll_task = kthread_run(control_loop, NULL, "g4fand"); | 333 | x.poll_task = kthread_run(control_loop, NULL, "g4fand"); |
| 328 | } | 334 | } |
| 329 | } | 335 | } |
| 330 | return ret; | 336 | return 0; |
| 331 | } | 337 | } |
| 332 | 338 | ||
| 333 | static int | 339 | static int |
| 334 | do_detach( struct i2c_client *client ) | 340 | do_remove(struct i2c_client *client) |
| 335 | { | 341 | { |
| 336 | int err; | 342 | if (x.running) { |
| 337 | 343 | x.running = 0; | |
| 338 | if( (err=i2c_detach_client(client)) ) | 344 | kthread_stop(x.poll_task); |
| 339 | printk(KERN_ERR "failed to detach thermostat client\n"); | 345 | x.poll_task = NULL; |
| 340 | else { | ||
| 341 | if( x.running ) { | ||
| 342 | x.running = 0; | ||
| 343 | kthread_stop(x.poll_task); | ||
| 344 | x.poll_task = NULL; | ||
| 345 | } | ||
| 346 | if( client == x.thermostat ) | ||
| 347 | x.thermostat = NULL; | ||
| 348 | else if( client == x.fan ) | ||
| 349 | x.fan = NULL; | ||
| 350 | else { | ||
| 351 | printk(KERN_ERR "g4fan: bad client\n"); | ||
| 352 | } | ||
| 353 | kfree( client ); | ||
| 354 | } | 346 | } |
| 355 | return err; | 347 | if (client == x.thermostat) |
| 356 | } | 348 | x.thermostat = NULL; |
| 349 | else if (client == x.fan) | ||
| 350 | x.fan = NULL; | ||
| 351 | else | ||
| 352 | printk(KERN_ERR "g4fan: bad client\n"); | ||
| 357 | 353 | ||
| 358 | static struct i2c_driver g4fan_driver = { | 354 | return 0; |
| 359 | .driver = { | 355 | } |
| 360 | .name = "therm_windtunnel", | ||
| 361 | }, | ||
| 362 | .attach_adapter = do_attach, | ||
| 363 | .detach_client = do_detach, | ||
| 364 | }; | ||
| 365 | 356 | ||
| 366 | static int | 357 | static int |
| 367 | attach_fan( struct i2c_client *cl ) | 358 | attach_fan( struct i2c_client *cl ) |
| @@ -374,13 +365,8 @@ attach_fan( struct i2c_client *cl ) | |||
| 374 | goto out; | 365 | goto out; |
| 375 | printk("ADM1030 fan controller [@%02x]\n", cl->addr ); | 366 | printk("ADM1030 fan controller [@%02x]\n", cl->addr ); |
| 376 | 367 | ||
| 377 | strlcpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) ); | 368 | x.fan = cl; |
| 378 | |||
| 379 | if( !i2c_attach_client(cl) ) | ||
| 380 | x.fan = cl; | ||
| 381 | out: | 369 | out: |
| 382 | if( cl != x.fan ) | ||
| 383 | kfree( cl ); | ||
| 384 | return 0; | 370 | return 0; |
| 385 | } | 371 | } |
| 386 | 372 | ||
| @@ -412,39 +398,47 @@ attach_thermostat( struct i2c_client *cl ) | |||
| 412 | x.temp = temp; | 398 | x.temp = temp; |
| 413 | x.overheat_temp = os_temp; | 399 | x.overheat_temp = os_temp; |
| 414 | x.overheat_hyst = hyst_temp; | 400 | x.overheat_hyst = hyst_temp; |
| 415 | 401 | x.thermostat = cl; | |
| 416 | strlcpy( cl->name, "DS1775 thermostat", sizeof(cl->name) ); | ||
| 417 | |||
| 418 | if( !i2c_attach_client(cl) ) | ||
| 419 | x.thermostat = cl; | ||
| 420 | out: | 402 | out: |
| 421 | if( cl != x.thermostat ) | ||
| 422 | kfree( cl ); | ||
| 423 | return 0; | 403 | return 0; |
| 424 | } | 404 | } |
| 425 | 405 | ||
| 406 | enum chip { ds1775, adm1030 }; | ||
| 407 | |||
| 408 | static const struct i2c_device_id therm_windtunnel_id[] = { | ||
| 409 | { "therm_ds1775", ds1775 }, | ||
| 410 | { "therm_adm1030", adm1030 }, | ||
| 411 | { } | ||
| 412 | }; | ||
| 413 | |||
| 426 | static int | 414 | static int |
| 427 | do_probe( struct i2c_adapter *adapter, int addr, int kind ) | 415 | do_probe(struct i2c_client *cl, const struct i2c_device_id *id) |
| 428 | { | 416 | { |
| 429 | struct i2c_client *cl; | 417 | struct i2c_adapter *adapter = cl->adapter; |
| 430 | 418 | ||
| 431 | if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA | 419 | if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA |
| 432 | | I2C_FUNC_SMBUS_WRITE_BYTE) ) | 420 | | I2C_FUNC_SMBUS_WRITE_BYTE) ) |
| 433 | return 0; | 421 | return 0; |
| 434 | 422 | ||
| 435 | if( !(cl=kzalloc(sizeof(*cl), GFP_KERNEL)) ) | 423 | switch (id->driver_data) { |
| 436 | return -ENOMEM; | 424 | case adm1030: |
| 437 | |||
| 438 | cl->addr = addr; | ||
| 439 | cl->adapter = adapter; | ||
| 440 | cl->driver = &g4fan_driver; | ||
| 441 | cl->flags = 0; | ||
| 442 | |||
| 443 | if( addr < 0x48 ) | ||
| 444 | return attach_fan( cl ); | 425 | return attach_fan( cl ); |
| 445 | return attach_thermostat( cl ); | 426 | case ds1775: |
| 427 | return attach_thermostat(cl); | ||
| 428 | } | ||
| 429 | return 0; | ||
| 446 | } | 430 | } |
| 447 | 431 | ||
| 432 | static struct i2c_driver g4fan_driver = { | ||
| 433 | .driver = { | ||
| 434 | .name = "therm_windtunnel", | ||
| 435 | }, | ||
| 436 | .attach_adapter = do_attach, | ||
| 437 | .probe = do_probe, | ||
| 438 | .remove = do_remove, | ||
| 439 | .id_table = therm_windtunnel_id, | ||
| 440 | }; | ||
| 441 | |||
| 448 | 442 | ||
| 449 | /************************************************************************/ | 443 | /************************************************************************/ |
| 450 | /* initialization / cleanup */ | 444 | /* initialization / cleanup */ |
