Merge branch 'topic/asoc' into for-linus
[safe/jmp/linux-2.6] / drivers / macintosh / therm_windtunnel.c
index d11821a..0839770 100644 (file)
@@ -15,7 +15,7 @@
  *
  *     WARNING: This driver has only been testen on Apple's
  *     1.25 MHz Dual G4 (March 03). It is tuned for a CPU
- *     temperatur around 57 C.
+ *     temperature around 57 C.
  *
  *   Copyright (C) 2003, 2004 Samuel Rydh (samuel@ibrium.se)
  *
 #include <linux/delay.h>
 #include <linux/sched.h>
 #include <linux/i2c.h>
-#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/kthread.h>
+#include <linux/of_platform.h>
 
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/sections.h>
-#include <asm/of_platform.h>
 #include <asm/macio.h>
 
 #define LOG_TEMP               0                       /* continously log temperature */
 
-static int                     do_probe( struct i2c_adapter *adapter, int addr, int kind);
-
-/* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
-static const unsigned short    normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
-                                                0x4c, 0x4d, 0x4e, 0x4f,
-                                                0x2c, 0x2d, 0x2e, 0x2f,
-                                                I2C_CLIENT_END };
-
-I2C_CLIENT_INSMOD;
-
 static struct {
        volatile int            running;
        struct task_struct      *poll_task;
        
-       struct semaphore        lock;
+       struct mutex            lock;
        struct of_device        *of_dev;
        
        struct i2c_client       *thermostat;
@@ -249,8 +238,8 @@ setup_hardware( void )
         * to be on the safe side (OSX doesn't)...
         */
        if( x.overheat_temp == (80 << 8) ) {
-               x.overheat_temp = 65 << 8;
-               x.overheat_hyst = 60 << 8;
+               x.overheat_temp = 75 << 8;
+               x.overheat_hyst = 70 << 8;
                write_reg( x.thermostat, 2, x.overheat_hyst, 2 );
                write_reg( x.thermostat, 3, x.overheat_temp, 2 );
 
@@ -286,23 +275,23 @@ restore_regs( void )
 
 static int control_loop(void *dummy)
 {
-       down(&x.lock);
+       mutex_lock(&x.lock);
        setup_hardware();
-       up(&x.lock);
+       mutex_unlock(&x.lock);
 
        for (;;) {
                msleep_interruptible(8000);
                if (kthread_should_stop())
                        break;
 
-               down(&x.lock);
+               mutex_lock(&x.lock);
                poll_temp();
-               up(&x.lock);
+               mutex_unlock(&x.lock);
        }
 
-       down(&x.lock);
+       mutex_lock(&x.lock);
        restore_regs();
-       up(&x.lock);
+       mutex_unlock(&x.lock);
 
        return 0;
 }
@@ -315,53 +304,54 @@ static int control_loop(void *dummy)
 static int
 do_attach( struct i2c_adapter *adapter )
 {
-       int ret = 0;
+       /* scan 0x48-0x4f (DS1775) and 0x2c-2x2f (ADM1030) */
+       static const unsigned short scan_ds1775[] = {
+               0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
+               I2C_CLIENT_END
+       };
+       static const unsigned short scan_adm1030[] = {
+               0x2c, 0x2d, 0x2e, 0x2f,
+               I2C_CLIENT_END
+       };
 
        if( strncmp(adapter->name, "uni-n", 5) )
                return 0;
 
        if( !x.running ) {
-               ret = i2c_probe( adapter, &addr_data, &do_probe );
+               struct i2c_board_info info;
+
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               strlcpy(info.type, "therm_ds1775", I2C_NAME_SIZE);
+               i2c_new_probed_device(adapter, &info, scan_ds1775);
+
+               strlcpy(info.type, "therm_adm1030", I2C_NAME_SIZE);
+               i2c_new_probed_device(adapter, &info, scan_adm1030);
+
                if( x.thermostat && x.fan ) {
                        x.running = 1;
                        x.poll_task = kthread_run(control_loop, NULL, "g4fand");
                }
        }
-       return ret;
+       return 0;
 }
 
 static int
-do_detach( struct i2c_client *client )
+do_remove(struct i2c_client *client)
 {
-       int err;
-
-       if( (err=i2c_detach_client(client)) )
-               printk(KERN_ERR "failed to detach thermostat client\n");
-       else {
-               if( x.running ) {
-                       x.running = 0;
-                       kthread_stop(x.poll_task);
-                       x.poll_task = NULL;
-               }
-               if( client == x.thermostat )
-                       x.thermostat = NULL;
-               else if( client == x.fan )
-                       x.fan = NULL;
-               else {
-                       printk(KERN_ERR "g4fan: bad client\n");
-               }
-               kfree( client );
+       if (x.running) {
+               x.running = 0;
+               kthread_stop(x.poll_task);
+               x.poll_task = NULL;
        }
-       return err;
-}
+       if (client == x.thermostat)
+               x.thermostat = NULL;
+       else if (client == x.fan)
+               x.fan = NULL;
+       else
+               printk(KERN_ERR "g4fan: bad client\n");
 
-static struct i2c_driver g4fan_driver = {  
-       .driver = {
-               .name   = "therm_windtunnel",
-       },
-       .attach_adapter = do_attach,
-       .detach_client  = do_detach,
-};
+       return 0;
+}
 
 static int
 attach_fan( struct i2c_client *cl )
@@ -374,13 +364,8 @@ attach_fan( struct i2c_client *cl )
                goto out;
        printk("ADM1030 fan controller [@%02x]\n", cl->addr );
 
-       strlcpy( cl->name, "ADM1030 fan controller", sizeof(cl->name) );
-
-       if( !i2c_attach_client(cl) )
-               x.fan = cl;
+       x.fan = cl;
  out:
-       if( cl != x.fan )
-               kfree( cl );
        return 0;
 }
 
@@ -412,39 +397,47 @@ attach_thermostat( struct i2c_client *cl )
        x.temp = temp;
        x.overheat_temp = os_temp;
        x.overheat_hyst = hyst_temp;
-       
-       strlcpy( cl->name, "DS1775 thermostat", sizeof(cl->name) );
-
-       if( !i2c_attach_client(cl) )
-               x.thermostat = cl;
+       x.thermostat = cl;
 out:
-       if( cl != x.thermostat )
-               kfree( cl );
        return 0;
 }
 
+enum chip { ds1775, adm1030 };
+
+static const struct i2c_device_id therm_windtunnel_id[] = {
+       { "therm_ds1775", ds1775 },
+       { "therm_adm1030", adm1030 },
+       { }
+};
+
 static int
-do_probe( struct i2c_adapter *adapter, int addr, int kind )
+do_probe(struct i2c_client *cl, const struct i2c_device_id *id)
 {
-       struct i2c_client *cl;
+       struct i2c_adapter *adapter = cl->adapter;
 
        if( !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA
                                     | I2C_FUNC_SMBUS_WRITE_BYTE) )
                return 0;
 
-       if( !(cl=kzalloc(sizeof(*cl), GFP_KERNEL)) )
-               return -ENOMEM;
-
-       cl->addr = addr;
-       cl->adapter = adapter;
-       cl->driver = &g4fan_driver;
-       cl->flags = 0;
-
-       if( addr < 0x48 )
+       switch (id->driver_data) {
+       case adm1030:
                return attach_fan( cl );
-       return attach_thermostat( cl );
+       case ds1775:
+               return attach_thermostat(cl);
+       }
+       return 0;
 }
 
+static struct i2c_driver g4fan_driver = {
+       .driver = {
+               .name   = "therm_windtunnel",
+       },
+       .attach_adapter = do_attach,
+       .probe          = do_probe,
+       .remove         = do_remove,
+       .id_table       = therm_windtunnel_id,
+};
+
 
 /************************************************************************/
 /*     initialization / cleanup                                        */
@@ -463,7 +456,7 @@ therm_of_remove( struct of_device *dev )
        return 0;
 }
 
-static struct of_device_id therm_of_match[] = {{
+static const struct of_device_id therm_of_match[] = {{
        .name           = "fan",
        .compatible     = "adm1030"
     }, {}
@@ -489,14 +482,14 @@ g4fan_init( void )
        const struct apple_thermal_info *info;
        struct device_node *np;
 
-       init_MUTEX( &x.lock );
+       mutex_init(&x.lock);
 
        if( !(np=of_find_node_by_name(NULL, "power-mgt")) )
                return -ENODEV;
        info = of_get_property(np, "thermal-info", NULL);
        of_node_put(np);
 
-       if( !info || !machine_is_compatible("PowerMac3,6") )
+       if( !info || !of_machine_is_compatible("PowerMac3,6") )
                return -ENODEV;
 
        if( info->id != 3 ) {