aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/macintosh/therm_windtunnel.c126
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
51static int do_probe( struct i2c_adapter *adapter, int addr, int kind);
52
53/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
54static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
55 0x4c, 0x4d, 0x4e, 0x4f,
56 0x2c, 0x2d, 0x2e, 0x2f,
57 I2C_CLIENT_END };
58
59I2C_CLIENT_INSMOD;
60
61static struct { 51static 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)
315static int 305static int
316do_attach( struct i2c_adapter *adapter ) 306do_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
333static int 339static int
334do_detach( struct i2c_client *client ) 340do_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
358static 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
366static int 357static int
367attach_fan( struct i2c_client *cl ) 358attach_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;
420out: 402out:
421 if( cl != x.thermostat )
422 kfree( cl );
423 return 0; 403 return 0;
424} 404}
425 405
406enum chip { ds1775, adm1030 };
407
408static const struct i2c_device_id therm_windtunnel_id[] = {
409 { "therm_ds1775", ds1775 },
410 { "therm_adm1030", adm1030 },
411 { }
412};
413
426static int 414static int
427do_probe( struct i2c_adapter *adapter, int addr, int kind ) 415do_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
432static 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 */