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 */ |