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 <khali@linux-fr.org>
This commit is contained in:
Jean Delvare 2008-07-16 19:30:06 +02:00 committed by Jean Delvare
parent 833bedb813
commit 97addff6de
2 changed files with 45 additions and 64 deletions

View File

@ -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
--------------

View File

@ -32,11 +32,8 @@
#include <linux/slab.h> /* kzalloc() */
#include <linux/sysfs.h> /* 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);
}
/* This function is called by i2c_probe */
static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct pcf8575_data *data;
int err = 0;
struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
goto exit;
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;
}
static int pcf8575_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pcf8575_data *data;
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);