From patchwork Thu Apr 16 16:56:15 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jean Delvare X-Patchwork-Id: 26077 X-Patchwork-Delegate: paulus@samba.org Return-Path: X-Original-To: patchwork-incoming@bilbo.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from ozlabs.org (ozlabs.org [203.10.76.45]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "mx.ozlabs.org", Issuer "CA Cert Signing Authority" (verified OK)) by bilbo.ozlabs.org (Postfix) with ESMTPS id 62B9CB6F44 for ; Fri, 17 Apr 2009 02:57:30 +1000 (EST) Received: by ozlabs.org (Postfix) id 20913DE4C6; Fri, 17 Apr 2009 02:56:54 +1000 (EST) Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id 1E963DE4C5 for ; Fri, 17 Apr 2009 02:56:54 +1000 (EST) X-Original-To: linuxppc-dev@ozlabs.org Delivered-To: linuxppc-dev@ozlabs.org Received: from services.gcu-squad.org (zone0.gcu-squad.org [212.85.147.21]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id C6641DE0AC for ; Fri, 17 Apr 2009 02:56:31 +1000 (EST) Received: from jdelvare.pck.nerim.net ([62.212.121.182] helo=hyperion.delvare) by services.gcu-squad.org (GCU Mailer Daemon) with esmtpsa id 1LuVy8-000375-EG (TLSv1:AES256-SHA:256) (envelope-from ) ; Thu, 16 Apr 2009 20:05:48 +0200 Date: Thu, 16 Apr 2009 18:56:15 +0200 From: Jean Delvare To: linuxppc-dev@ozlabs.org Subject: [PATCH] windfarm: Convert to a new-style i2c drivers Message-ID: <20090416185615.2f7914ca@hyperion.delvare> X-Mailer: Claws Mail 3.5.0 (GTK+ 2.14.4; x86_64-suse-linux-gnu) Mime-Version: 1.0 Cc: Paul Mackerras X-BeenThere: linuxppc-dev@ozlabs.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org The legacy i2c binding model is going away soon, so convert the macintosh windfarm drivers to the new model or they will break. Signed-off-by: Jean Delvare Cc: Benjamin Herrenschmidt Cc: Paul Mackerras Tested-by: Paul Mackerras --- Can someone please test this patch for me? I could only build-test it. Remember that you need this patch applied: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=935298696f469c0e07c73be687bd055878074ce0 Thanks. drivers/macintosh/windfarm_lm75_sensor.c | 131 +++++++++++++++------------ drivers/macintosh/windfarm_max6690_sensor.c | 103 ++++++++++++--------- drivers/macintosh/windfarm_smu_sat.c | 109 ++++++++++++---------- 3 files changed, 198 insertions(+), 145 deletions(-) --- linux-2.6.30-rc2.orig/drivers/macintosh/windfarm_lm75_sensor.c 2009-04-16 11:15:00.000000000 +0200 +++ linux-2.6.30-rc2/drivers/macintosh/windfarm_lm75_sensor.c 2009-04-16 11:23:17.000000000 +0200 @@ -37,34 +37,22 @@ struct wf_lm75_sensor { int ds1775 : 1; int inited : 1; - struct i2c_client i2c; + struct i2c_client *i2c; struct wf_sensor sens; }; #define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens) -#define i2c_to_lm75(c) container_of(c, struct wf_lm75_sensor, i2c) - -static int wf_lm75_attach(struct i2c_adapter *adapter); -static int wf_lm75_detach(struct i2c_client *client); - -static struct i2c_driver wf_lm75_driver = { - .driver = { - .name = "wf_lm75", - }, - .attach_adapter = wf_lm75_attach, - .detach_client = wf_lm75_detach, -}; static int wf_lm75_get(struct wf_sensor *sr, s32 *value) { struct wf_lm75_sensor *lm = wf_to_lm75(sr); s32 data; - if (lm->i2c.adapter == NULL) + if (lm->i2c == NULL) return -ENODEV; /* Init chip if necessary */ if (!lm->inited) { - u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(&lm->i2c, 1); + u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(lm->i2c, 1); DBG("wf_lm75: Initializing %s, cfg was: %02x\n", sr->name, cfg); @@ -73,7 +61,7 @@ static int wf_lm75_get(struct wf_sensor * the firmware for now */ cfg_new = cfg & ~0x01; - i2c_smbus_write_byte_data(&lm->i2c, 1, cfg_new); + i2c_smbus_write_byte_data(lm->i2c, 1, cfg_new); lm->inited = 1; /* If we just powered it up, let's wait 200 ms */ @@ -81,7 +69,7 @@ static int wf_lm75_get(struct wf_sensor } /* Read temperature register */ - data = (s32)le16_to_cpu(i2c_smbus_read_word_data(&lm->i2c, 0)); + data = (s32)le16_to_cpu(i2c_smbus_read_word_data(lm->i2c, 0)); data <<= 8; *value = data; @@ -92,12 +80,6 @@ static void wf_lm75_release(struct wf_se { struct wf_lm75_sensor *lm = wf_to_lm75(sr); - /* check if client is registered and detach from i2c */ - if (lm->i2c.adapter) { - i2c_detach_client(&lm->i2c); - lm->i2c.adapter = NULL; - } - kfree(lm); } @@ -107,59 +89,77 @@ static struct wf_sensor_ops wf_lm75_ops .owner = THIS_MODULE, }; -static struct wf_lm75_sensor *wf_lm75_create(struct i2c_adapter *adapter, - u8 addr, int ds1775, - const char *loc) +static int wf_lm75_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct wf_lm75_sensor *lm; int rc; - DBG("wf_lm75: creating %s device at address 0x%02x\n", - ds1775 ? "ds1775" : "lm75", addr); - lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL); if (lm == NULL) - return NULL; + return -ENODEV; + + lm->inited = 0; + lm->ds1775 = id->driver_data; + lm->i2c = client; + lm->sens.name = client->dev.platform_data; + lm->sens.ops = &wf_lm75_ops; + i2c_set_clientdata(client, lm); + + rc = wf_register_sensor(&lm->sens); + if (rc) { + i2c_set_clientdata(client, NULL); + kfree(lm); + } + + return rc; +} + +static struct i2c_client *wf_lm75_create(struct i2c_adapter *adapter, + u8 addr, int ds1775, + const char *loc) +{ + struct i2c_board_info info; + struct i2c_client *client; + char *name; + + DBG("wf_lm75: creating %s device at address 0x%02x\n", + ds1775 ? "ds1775" : "lm75", addr); /* Usual rant about sensor names not beeing very consistent in * the device-tree, oh well ... * Add more entries below as you deal with more setups */ if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY")) - lm->sens.name = "hd-temp"; + name = "hd-temp"; else if (!strcmp(loc, "Incoming Air Temp")) - lm->sens.name = "incoming-air-temp"; + name = "incoming-air-temp"; else if (!strcmp(loc, "ODD Temp")) - lm->sens.name = "optical-drive-temp"; + name = "optical-drive-temp"; else if (!strcmp(loc, "HD Temp")) - lm->sens.name = "hard-drive-temp"; + name = "hard-drive-temp"; else goto fail; - lm->inited = 0; - lm->sens.ops = &wf_lm75_ops; - lm->ds1775 = ds1775; - lm->i2c.addr = (addr >> 1) & 0x7f; - lm->i2c.adapter = adapter; - lm->i2c.driver = &wf_lm75_driver; - strncpy(lm->i2c.name, lm->sens.name, I2C_NAME_SIZE-1); - - rc = i2c_attach_client(&lm->i2c); - if (rc) { - printk(KERN_ERR "windfarm: failed to attach %s %s to i2c," - " err %d\n", ds1775 ? "ds1775" : "lm75", - lm->i2c.name, rc); - goto fail; - } - - if (wf_register_sensor(&lm->sens)) { - i2c_detach_client(&lm->i2c); + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = (addr >> 1) & 0x7f; + info.platform_data = name; + strlcpy(info.type, ds1775 ? "wf_ds1775" : "wf_lm75", I2C_NAME_SIZE); + + client = i2c_new_device(adapter, &info); + if (client == NULL) { + printk(KERN_ERR "windfarm: failed to attach %s %s to i2c\n", + ds1775 ? "ds1775" : "lm75", name); goto fail; } - return lm; + /* + * Let i2c-core delete that device on driver removal. + * This is safe because i2c-core holds the core_lock mutex for us. + */ + list_add_tail(&client->detected, &client->driver->clients); + return client; fail: - kfree(lm); return NULL; } @@ -202,21 +202,38 @@ static int wf_lm75_attach(struct i2c_ada return 0; } -static int wf_lm75_detach(struct i2c_client *client) +static int wf_lm75_remove(struct i2c_client *client) { - struct wf_lm75_sensor *lm = i2c_to_lm75(client); + struct wf_lm75_sensor *lm = i2c_get_clientdata(client); DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name); /* Mark client detached */ - lm->i2c.adapter = NULL; + lm->i2c = NULL; /* release sensor */ wf_unregister_sensor(&lm->sens); + i2c_set_clientdata(client, NULL); return 0; } +static const struct i2c_device_id wf_lm75_id[] = { + { "wf_lm75", 0 }, + { "wf_ds1775", 1 }, + { } +}; + +static struct i2c_driver wf_lm75_driver = { + .driver = { + .name = "wf_lm75", + }, + .attach_adapter = wf_lm75_attach, + .probe = wf_lm75_probe, + .remove = wf_lm75_remove, + .id_table = wf_lm75_id, +}; + static int __init wf_lm75_sensor_init(void) { /* Don't register on old machines that use therm_pm72 for now */ --- linux-2.6.30-rc2.orig/drivers/macintosh/windfarm_max6690_sensor.c 2009-04-16 17:45:07.000000000 +0200 +++ linux-2.6.30-rc2/drivers/macintosh/windfarm_max6690_sensor.c 2009-04-16 17:45:13.000000000 +0200 @@ -26,34 +26,22 @@ #define MAX6690_EXTERNAL_TEMP 1 struct wf_6690_sensor { - struct i2c_client i2c; + struct i2c_client *i2c; struct wf_sensor sens; }; #define wf_to_6690(x) container_of((x), struct wf_6690_sensor, sens) -#define i2c_to_6690(x) container_of((x), struct wf_6690_sensor, i2c) - -static int wf_max6690_attach(struct i2c_adapter *adapter); -static int wf_max6690_detach(struct i2c_client *client); - -static struct i2c_driver wf_max6690_driver = { - .driver = { - .name = "wf_max6690", - }, - .attach_adapter = wf_max6690_attach, - .detach_client = wf_max6690_detach, -}; static int wf_max6690_get(struct wf_sensor *sr, s32 *value) { struct wf_6690_sensor *max = wf_to_6690(sr); s32 data; - if (max->i2c.adapter == NULL) + if (max->i2c == NULL) return -ENODEV; /* chip gets initialized by firmware */ - data = i2c_smbus_read_byte_data(&max->i2c, MAX6690_EXTERNAL_TEMP); + data = i2c_smbus_read_byte_data(max->i2c, MAX6690_EXTERNAL_TEMP); if (data < 0) return data; *value = data << 16; @@ -64,10 +52,6 @@ static void wf_max6690_release(struct wf { struct wf_6690_sensor *max = wf_to_6690(sr); - if (max->i2c.adapter) { - i2c_detach_client(&max->i2c); - max->i2c.adapter = NULL; - } kfree(max); } @@ -77,19 +61,40 @@ static struct wf_sensor_ops wf_max6690_o .owner = THIS_MODULE, }; -static void wf_max6690_create(struct i2c_adapter *adapter, u8 addr, - const char *loc) +static int wf_max6690_probe(struct i2c_client *client, + const struct i2c_device_id *id) { struct wf_6690_sensor *max; - char *name; + int rc; max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL); if (max == NULL) { - printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor %s: " - "no memory\n", loc); - return; + printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: " + "no memory\n"); + return -ENOMEM; + } + + max->i2c = client; + max->sens.name = client->dev.platform_data; + max->sens.ops = &wf_max6690_ops; + i2c_set_clientdata(client, max); + + rc = wf_register_sensor(&max->sens); + if (rc) { + i2c_set_clientdata(client, NULL); + kfree(max); } + return rc; +} + +static struct i2c_client *wf_max6690_create(struct i2c_adapter *adapter, + u8 addr, const char *loc) +{ + struct i2c_board_info info; + struct i2c_client *client; + char *name; + if (!strcmp(loc, "BACKSIDE")) name = "backside-temp"; else if (!strcmp(loc, "NB Ambient")) @@ -99,27 +104,26 @@ static void wf_max6690_create(struct i2c else goto fail; - max->sens.ops = &wf_max6690_ops; - max->sens.name = name; - max->i2c.addr = addr >> 1; - max->i2c.adapter = adapter; - max->i2c.driver = &wf_max6690_driver; - strncpy(max->i2c.name, name, I2C_NAME_SIZE-1); + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = addr >> 1; + info.platform_data = name; + strlcpy(info.type, "wf_max6690", I2C_NAME_SIZE); - if (i2c_attach_client(&max->i2c)) { + client = i2c_new_device(adapter, &info); + if (client == NULL) { printk(KERN_ERR "windfarm: failed to attach MAX6690 sensor\n"); goto fail; } - if (wf_register_sensor(&max->sens)) { - i2c_detach_client(&max->i2c); - goto fail; - } - - return; + /* + * Let i2c-core delete that device on driver removal. + * This is safe because i2c-core holds the core_lock mutex for us. + */ + list_add_tail(&client->detected, &client->driver->clients); + return client; fail: - kfree(max); + return NULL; } static int wf_max6690_attach(struct i2c_adapter *adapter) @@ -154,16 +158,31 @@ static int wf_max6690_attach(struct i2c_ return 0; } -static int wf_max6690_detach(struct i2c_client *client) +static int wf_max6690_remove(struct i2c_client *client) { - struct wf_6690_sensor *max = i2c_to_6690(client); + struct wf_6690_sensor *max = i2c_get_clientdata(client); - max->i2c.adapter = NULL; + max->i2c = NULL; wf_unregister_sensor(&max->sens); return 0; } +static const struct i2c_device_id wf_max6690_id[] = { + { "wf_max6690", 0 }, + { } +}; + +static struct i2c_driver wf_max6690_driver = { + .driver = { + .name = "wf_max6690", + }, + .attach_adapter = wf_max6690_attach, + .probe = wf_max6690_probe, + .remove = wf_max6690_remove, + .id_table = wf_max6690_id, +}; + static int __init wf_max6690_sensor_init(void) { /* Don't register on old machines that use therm_pm72 for now */ --- linux-2.6.30-rc2.orig/drivers/macintosh/windfarm_smu_sat.c 2009-04-16 17:45:06.000000000 +0200 +++ linux-2.6.30-rc2/drivers/macintosh/windfarm_smu_sat.c 2009-04-16 18:13:07.000000000 +0200 @@ -39,7 +39,7 @@ struct wf_sat { struct mutex mutex; unsigned long last_read; /* jiffies when cache last updated */ u8 cache[16]; - struct i2c_client i2c; + struct i2c_client *i2c; struct device_node *node; }; @@ -54,18 +54,6 @@ struct wf_sat_sensor { }; #define wf_to_sat(c) container_of(c, struct wf_sat_sensor, sens) -#define i2c_to_sat(c) container_of(c, struct wf_sat, i2c) - -static int wf_sat_attach(struct i2c_adapter *adapter); -static int wf_sat_detach(struct i2c_client *client); - -static struct i2c_driver wf_sat_driver = { - .driver = { - .name = "wf_smu_sat", - }, - .attach_adapter = wf_sat_attach, - .detach_client = wf_sat_detach, -}; struct smu_sdbp_header *smu_sat_get_sdb_partition(unsigned int sat_id, int id, unsigned int *size) @@ -81,13 +69,13 @@ struct smu_sdbp_header *smu_sat_get_sdb_ if (sat_id > 1 || (sat = sats[sat_id]) == NULL) return NULL; - err = i2c_smbus_write_word_data(&sat->i2c, 8, id << 8); + err = i2c_smbus_write_word_data(sat->i2c, 8, id << 8); if (err) { printk(KERN_ERR "smu_sat_get_sdb_part wr error %d\n", err); return NULL; } - err = i2c_smbus_read_word_data(&sat->i2c, 9); + err = i2c_smbus_read_word_data(sat->i2c, 9); if (err < 0) { printk(KERN_ERR "smu_sat_get_sdb_part rd len error\n"); return NULL; @@ -105,7 +93,7 @@ struct smu_sdbp_header *smu_sat_get_sdb_ return NULL; for (i = 0; i < len; i += 4) { - err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0xa, 4, data); + err = i2c_smbus_read_i2c_block_data(sat->i2c, 0xa, 4, data); if (err < 0) { printk(KERN_ERR "smu_sat_get_sdb_part rd err %d\n", err); @@ -138,7 +126,7 @@ static int wf_sat_read_cache(struct wf_s { int err; - err = i2c_smbus_read_i2c_block_data(&sat->i2c, 0x3f, 16, sat->cache); + err = i2c_smbus_read_i2c_block_data(sat->i2c, 0x3f, 16, sat->cache); if (err < 0) return err; sat->last_read = jiffies; @@ -161,7 +149,7 @@ static int wf_sat_get(struct wf_sensor * int i, err; s32 val; - if (sat->i2c.adapter == NULL) + if (sat->i2c == NULL) return -ENODEV; mutex_lock(&sat->mutex); @@ -193,10 +181,6 @@ static void wf_sat_release(struct wf_sen struct wf_sat *sat = sens->sat; if (atomic_dec_and_test(&sat->refcnt)) { - if (sat->i2c.adapter) { - i2c_detach_client(&sat->i2c); - sat->i2c.adapter = NULL; - } if (sat->nr >= 0) sats[sat->nr] = NULL; kfree(sat); @@ -212,38 +196,58 @@ static struct wf_sensor_ops wf_sat_ops = static void wf_sat_create(struct i2c_adapter *adapter, struct device_node *dev) { + struct i2c_board_info info; + struct i2c_client *client; + const u32 *reg; + u8 addr; + + reg = of_get_property(dev, "reg", NULL); + if (reg == NULL) + return; + addr = *reg; + DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); + + memset(&info, 0, sizeof(struct i2c_board_info)); + info.addr = (addr >> 1) & 0x7f; + info.platform_data = dev; + strlcpy(info.type, "wf_sat", I2C_NAME_SIZE); + + client = i2c_new_device(adapter, &info); + if (client == NULL) { + printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); + return; + } + + /* + * Let i2c-core delete that device on driver removal. + * This is safe because i2c-core holds the core_lock mutex for us. + */ + list_add_tail(&client->detected, &client->driver->clients); +} + +static int wf_sat_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device_node *dev = client->dev.platform_data; struct wf_sat *sat; struct wf_sat_sensor *sens; const u32 *reg; const char *loc, *type; - u8 addr, chip, core; + u8 chip, core; struct device_node *child; int shift, cpu, index; char *name; int vsens[2], isens[2]; - reg = of_get_property(dev, "reg", NULL); - if (reg == NULL) - return; - addr = *reg; - DBG(KERN_DEBUG "wf_sat: creating sat at address %x\n", addr); - sat = kzalloc(sizeof(struct wf_sat), GFP_KERNEL); if (sat == NULL) - return; + return -ENOMEM; sat->nr = -1; sat->node = of_node_get(dev); atomic_set(&sat->refcnt, 0); mutex_init(&sat->mutex); - sat->i2c.addr = (addr >> 1) & 0x7f; - sat->i2c.adapter = adapter; - sat->i2c.driver = &wf_sat_driver; - strncpy(sat->i2c.name, "smu-sat", I2C_NAME_SIZE-1); - - if (i2c_attach_client(&sat->i2c)) { - printk(KERN_ERR "windfarm: failed to attach smu-sat to i2c\n"); - goto fail; - } + sat->i2c = client; + i2c_set_clientdata(client, sat); vsens[0] = vsens[1] = -1; isens[0] = isens[1] = -1; @@ -344,10 +348,7 @@ static void wf_sat_create(struct i2c_ada if (sat->nr >= 0) sats[sat->nr] = sat; - return; - - fail: - kfree(sat); + return 0; } static int wf_sat_attach(struct i2c_adapter *adapter) @@ -366,16 +367,32 @@ static int wf_sat_attach(struct i2c_adap return 0; } -static int wf_sat_detach(struct i2c_client *client) +static int wf_sat_remove(struct i2c_client *client) { - struct wf_sat *sat = i2c_to_sat(client); + struct wf_sat *sat = i2c_get_clientdata(client); /* XXX TODO */ - sat->i2c.adapter = NULL; + sat->i2c = NULL; + i2c_set_clientdata(client, NULL); return 0; } +static const struct i2c_device_id wf_sat_id[] = { + { "wf_sat", 0 }, + { } +}; + +static struct i2c_driver wf_sat_driver = { + .driver = { + .name = "wf_smu_sat", + }, + .attach_adapter = wf_sat_attach, + .probe = wf_sat_probe, + .remove = wf_sat_remove, + .id_table = wf_sat_id, +}; + static int __init sat_sensors_init(void) { return i2c_add_driver(&wf_sat_driver);