From 97addff6def3f8e228a634fa017589f45c69de5c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 16 Jul 2008 19:30:06 +0200 Subject: i2c: Convert the pcf8575 driver to a new-style i2c driver The new-style pcf8575 driver implements the optional detect() callback to cover the use cases of the legacy driver. Warning: users will now have to use the force module parameter to get the driver to attach to their device. That's not a bad thing as these devices can't be detected anyway. Note that this doesn't change the fact that this driver is deprecated in favor of gpio/pcf857x. Signed-off-by: Jean Delvare --- Documentation/i2c/chips/pcf8575 | 9 ++-- drivers/i2c/chips/pcf8575.c | 96 +++++++++++++++++------------------------ 2 files changed, 43 insertions(+), 62 deletions(-) diff --git a/Documentation/i2c/chips/pcf8575 b/Documentation/i2c/chips/pcf8575 index 25f5698..40b268e 100644 --- a/Documentation/i2c/chips/pcf8575 +++ b/Documentation/i2c/chips/pcf8575 @@ -40,12 +40,9 @@ Detection --------- There is no method known to detect whether a chip on a given I2C address is -a PCF8575 or whether it is any other I2C device. So there are two alternatives -to let the driver find the installed PCF8575 devices: -- Load this driver after any other I2C driver for I2C devices with addresses - in the range 0x20 .. 0x27. -- Pass the I2C bus and address of the installed PCF8575 devices explicitly to - the driver at load time via the probe=... or force=... parameters. +a PCF8575 or whether it is any other I2C device, so you have to pass the I2C +bus and address of the installed PCF8575 devices explicitly to the driver at +load time via the force=... parameter. /sys interface -------------- diff --git a/drivers/i2c/chips/pcf8575.c b/drivers/i2c/chips/pcf8575.c index 3ea08ac..07fd7cb 100644 --- a/drivers/i2c/chips/pcf8575.c +++ b/drivers/i2c/chips/pcf8575.c @@ -32,11 +32,8 @@ #include /* kzalloc() */ #include /* sysfs_create_group() */ -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - I2C_CLIENT_END -}; +/* Addresses to scan: none, device can't be detected */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; /* Insmod parameters */ I2C_CLIENT_INSMOD; @@ -44,24 +41,9 @@ I2C_CLIENT_INSMOD; /* Each client has this additional data */ struct pcf8575_data { - struct i2c_client client; int write; /* last written value, or error code */ }; -static int pcf8575_attach_adapter(struct i2c_adapter *adapter); -static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind); -static int pcf8575_detach_client(struct i2c_client *client); - -/* This is the driver that will be inserted */ -static struct i2c_driver pcf8575_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "pcf8575", - }, - .attach_adapter = pcf8575_attach_adapter, - .detach_client = pcf8575_detach_client, -}; - /* following are the sysfs callback functions */ static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf) @@ -126,75 +108,77 @@ static const struct attribute_group pcf8575_attr_group = { * Real code */ -static int pcf8575_attach_adapter(struct i2c_adapter *adapter) +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int pcf8575_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) { - return i2c_probe(adapter, &addr_data, pcf8575_detect); + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + return -ENODEV; + + /* This is the place to detect whether the chip at the specified + address really is a PCF8575 chip. However, there is no method known + to detect whether an I2C chip is a PCF8575 or any other I2C chip. */ + + strlcpy(info->type, "pcf8575", I2C_NAME_SIZE); + + return 0; } -/* This function is called by i2c_probe */ -static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind) +static int pcf8575_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client; struct pcf8575_data *data; - int err = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) - goto exit; + int err; - /* OK. For now, we presume we have a valid client. We now create the - client structure, even though we cannot fill it completely yet. */ data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL); if (!data) { err = -ENOMEM; goto exit; } - client = &data->client; i2c_set_clientdata(client, data); - client->addr = address; - client->adapter = adapter; - client->driver = &pcf8575_driver; - strlcpy(client->name, "pcf8575", I2C_NAME_SIZE); data->write = -EAGAIN; - /* This is the place to detect whether the chip at the specified - address really is a PCF8575 chip. However, there is no method known - to detect whether an I2C chip is a PCF8575 or any other I2C chip. */ - - /* Tell the I2C layer a new client has arrived */ - err = i2c_attach_client(client); - if (err) - goto exit_free; - /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group); if (err) - goto exit_detach; + goto exit_free; return 0; -exit_detach: - i2c_detach_client(client); exit_free: kfree(data); exit: return err; } -static int pcf8575_detach_client(struct i2c_client *client) +static int pcf8575_remove(struct i2c_client *client) { - int err; - sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group); - - err = i2c_detach_client(client); - if (err) - return err; - kfree(i2c_get_clientdata(client)); return 0; } +static const struct i2c_device_id pcf8575_id[] = { + { "pcf8575", 0 }, + { } +}; + +static struct i2c_driver pcf8575_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "pcf8575", + }, + .probe = pcf8575_probe, + .remove = pcf8575_remove, + .id_table = pcf8575_id, + + .detect = pcf8575_detect, + .address_data = &addr_data, +}; + static int __init pcf8575_init(void) { return i2c_add_driver(&pcf8575_driver); -- cgit v1.1