i2c: Convert the pca9539 driver to a new-style i2c driver

The new-style pca9539 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/pca953x.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
This commit is contained in:
Jean Delvare 2008-07-16 19:30:07 +02:00 committed by Jean Delvare
parent 97addff6de
commit 3d63430a26
2 changed files with 42 additions and 77 deletions

View file

@ -7,7 +7,7 @@ drivers/gpio/pca9539.c instead.
Supported chips:
* Philips PCA9539
Prefix: 'pca9539'
Addresses scanned: 0x74 - 0x77
Addresses scanned: none
Datasheet:
http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf
@ -23,6 +23,14 @@ The input sense can also be inverted.
The 16 lines are split between two bytes.
Detection
---------
The PCA9539 is difficult to detect and not commonly found in PC machines,
so you have to pass the I2C bus and address of the installed PCA9539
devices explicitly to the driver at load time via the force=... parameter.
Sysfs entries
-------------

View file

@ -14,8 +14,8 @@
#include <linux/i2c.h>
#include <linux/hwmon-sysfs.h>
/* Addresses to scan */
static unsigned short normal_i2c[] = {0x74, 0x75, 0x76, 0x77, I2C_CLIENT_END};
/* Addresses to scan: none, device is not autodetected */
static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD_1(pca9539);
@ -32,23 +32,6 @@ enum pca9539_cmd
PCA9539_DIRECTION_1 = 7,
};
static int pca9539_attach_adapter(struct i2c_adapter *adapter);
static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind);
static int pca9539_detach_client(struct i2c_client *client);
/* This is the driver that will be inserted */
static struct i2c_driver pca9539_driver = {
.driver = {
.name = "pca9539",
},
.attach_adapter = pca9539_attach_adapter,
.detach_client = pca9539_detach_client,
};
struct pca9539_data {
struct i2c_client client;
};
/* following are the sysfs callback functions */
static ssize_t pca9539_show(struct device *dev, struct device_attribute *attr,
char *buf)
@ -105,77 +88,51 @@ static struct attribute_group pca9539_defattr_group = {
.attrs = pca9539_attributes,
};
static int pca9539_attach_adapter(struct i2c_adapter *adapter)
/* Return 0 if detection is successful, -ENODEV otherwise */
static int pca9539_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info)
{
return i2c_probe(adapter, &addr_data, pca9539_detect);
}
/* This function is called by i2c_probe */
static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
{
struct i2c_client *client;
struct pca9539_data *data;
int err = 0;
struct i2c_adapter *adapter = client->adapter;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
goto exit;
return -ENODEV;
/* OK. For now, we presume we have a valid client. We now create the
client structure, even though we cannot fill it completely yet. */
if (!(data = kzalloc(sizeof(struct pca9539_data), GFP_KERNEL))) {
err = -ENOMEM;
goto exit;
}
client = &data->client;
i2c_set_clientdata(client, data);
client->addr = address;
client->adapter = adapter;
client->driver = &pca9539_driver;
if (kind < 0) {
/* Detection: the pca9539 only has 8 registers (0-7).
A read of 7 should succeed, but a read of 8 should fail. */
if ((i2c_smbus_read_byte_data(client, 7) < 0) ||
(i2c_smbus_read_byte_data(client, 8) >= 0))
goto exit_kfree;
}
strlcpy(client->name, "pca9539", I2C_NAME_SIZE);
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(client)))
goto exit_kfree;
/* Register sysfs hooks */
err = sysfs_create_group(&client->dev.kobj,
&pca9539_defattr_group);
if (err)
goto exit_detach;
strlcpy(info->type, "pca9539", I2C_NAME_SIZE);
return 0;
exit_detach:
i2c_detach_client(client);
exit_kfree:
kfree(data);
exit:
return err;
}
static int pca9539_detach_client(struct i2c_client *client)
static int pca9539_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int err;
/* Register sysfs hooks */
return sysfs_create_group(&client->dev.kobj,
&pca9539_defattr_group);
}
static int pca9539_remove(struct i2c_client *client)
{
sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group);
if ((err = i2c_detach_client(client)))
return err;
kfree(i2c_get_clientdata(client));
return 0;
}
static const struct i2c_device_id pca9539_id[] = {
{ "pca9539", 0 },
{ }
};
static struct i2c_driver pca9539_driver = {
.driver = {
.name = "pca9539",
},
.probe = pca9539_probe,
.remove = pca9539_remove,
.id_table = pca9539_id,
.detect = pca9539_detect,
.address_data = &addr_data,
};
static int __init pca9539_init(void)
{
return i2c_add_driver(&pca9539_driver);