aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2008-07-16 13:30:06 -0400
committerJean Delvare <khali@mahadeva.delvare>2008-07-16 13:30:06 -0400
commit97addff6def3f8e228a634fa017589f45c69de5c (patch)
treeabdbe65bb56dd88dbdaeb1878168ef4640ff829c
parent833bedb813689807385ae73175389c73a3f855c1 (diff)
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>
-rw-r--r--Documentation/i2c/chips/pcf85759
-rw-r--r--drivers/i2c/chips/pcf8575.c96
2 files changed, 43 insertions, 62 deletions
diff --git a/Documentation/i2c/chips/pcf8575 b/Documentation/i2c/chips/pcf8575
index 25f5698a61cf..40b268eb276f 100644
--- a/Documentation/i2c/chips/pcf8575
+++ b/Documentation/i2c/chips/pcf8575
@@ -40,12 +40,9 @@ Detection
40--------- 40---------
41 41
42There is no method known to detect whether a chip on a given I2C address is 42There is no method known to detect whether a chip on a given I2C address is
43a PCF8575 or whether it is any other I2C device. So there are two alternatives 43a PCF8575 or whether it is any other I2C device, so you have to pass the I2C
44to let the driver find the installed PCF8575 devices: 44bus and address of the installed PCF8575 devices explicitly to the driver at
45- Load this driver after any other I2C driver for I2C devices with addresses 45load time via the force=... parameter.
46 in the range 0x20 .. 0x27.
47- Pass the I2C bus and address of the installed PCF8575 devices explicitly to
48 the driver at load time via the probe=... or force=... parameters.
49 46
50/sys interface 47/sys interface
51-------------- 48--------------
diff --git a/drivers/i2c/chips/pcf8575.c b/drivers/i2c/chips/pcf8575.c
index 3ea08ac0bfa3..07fd7cb3c57d 100644
--- a/drivers/i2c/chips/pcf8575.c
+++ b/drivers/i2c/chips/pcf8575.c
@@ -32,11 +32,8 @@
32#include <linux/slab.h> /* kzalloc() */ 32#include <linux/slab.h> /* kzalloc() */
33#include <linux/sysfs.h> /* sysfs_create_group() */ 33#include <linux/sysfs.h> /* sysfs_create_group() */
34 34
35/* Addresses to scan */ 35/* Addresses to scan: none, device can't be detected */
36static const unsigned short normal_i2c[] = { 36static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
37 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
38 I2C_CLIENT_END
39};
40 37
41/* Insmod parameters */ 38/* Insmod parameters */
42I2C_CLIENT_INSMOD; 39I2C_CLIENT_INSMOD;
@@ -44,24 +41,9 @@ I2C_CLIENT_INSMOD;
44 41
45/* Each client has this additional data */ 42/* Each client has this additional data */
46struct pcf8575_data { 43struct pcf8575_data {
47 struct i2c_client client;
48 int write; /* last written value, or error code */ 44 int write; /* last written value, or error code */
49}; 45};
50 46
51static int pcf8575_attach_adapter(struct i2c_adapter *adapter);
52static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind);
53static int pcf8575_detach_client(struct i2c_client *client);
54
55/* This is the driver that will be inserted */
56static struct i2c_driver pcf8575_driver = {
57 .driver = {
58 .owner = THIS_MODULE,
59 .name = "pcf8575",
60 },
61 .attach_adapter = pcf8575_attach_adapter,
62 .detach_client = pcf8575_detach_client,
63};
64
65/* following are the sysfs callback functions */ 47/* following are the sysfs callback functions */
66static ssize_t show_read(struct device *dev, struct device_attribute *attr, 48static ssize_t show_read(struct device *dev, struct device_attribute *attr,
67 char *buf) 49 char *buf)
@@ -126,75 +108,77 @@ static const struct attribute_group pcf8575_attr_group = {
126 * Real code 108 * Real code
127 */ 109 */
128 110
129static int pcf8575_attach_adapter(struct i2c_adapter *adapter) 111/* Return 0 if detection is successful, -ENODEV otherwise */
112static int pcf8575_detect(struct i2c_client *client, int kind,
113 struct i2c_board_info *info)
130{ 114{
131 return i2c_probe(adapter, &addr_data, pcf8575_detect); 115 struct i2c_adapter *adapter = client->adapter;
116
117 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
118 return -ENODEV;
119
120 /* This is the place to detect whether the chip at the specified
121 address really is a PCF8575 chip. However, there is no method known
122 to detect whether an I2C chip is a PCF8575 or any other I2C chip. */
123
124 strlcpy(info->type, "pcf8575", I2C_NAME_SIZE);
125
126 return 0;
132} 127}
133 128
134/* This function is called by i2c_probe */ 129static int pcf8575_probe(struct i2c_client *client,
135static int pcf8575_detect(struct i2c_adapter *adapter, int address, int kind) 130 const struct i2c_device_id *id)
136{ 131{
137 struct i2c_client *client;
138 struct pcf8575_data *data; 132 struct pcf8575_data *data;
139 int err = 0; 133 int err;
140
141 if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
142 goto exit;
143 134
144 /* OK. For now, we presume we have a valid client. We now create the
145 client structure, even though we cannot fill it completely yet. */
146 data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL); 135 data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL);
147 if (!data) { 136 if (!data) {
148 err = -ENOMEM; 137 err = -ENOMEM;
149 goto exit; 138 goto exit;
150 } 139 }
151 140
152 client = &data->client;
153 i2c_set_clientdata(client, data); 141 i2c_set_clientdata(client, data);
154 client->addr = address;
155 client->adapter = adapter;
156 client->driver = &pcf8575_driver;
157 strlcpy(client->name, "pcf8575", I2C_NAME_SIZE);
158 data->write = -EAGAIN; 142 data->write = -EAGAIN;
159 143
160 /* This is the place to detect whether the chip at the specified
161 address really is a PCF8575 chip. However, there is no method known
162 to detect whether an I2C chip is a PCF8575 or any other I2C chip. */
163
164 /* Tell the I2C layer a new client has arrived */
165 err = i2c_attach_client(client);
166 if (err)
167 goto exit_free;
168
169 /* Register sysfs hooks */ 144 /* Register sysfs hooks */
170 err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group); 145 err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group);
171 if (err) 146 if (err)
172 goto exit_detach; 147 goto exit_free;
173 148
174 return 0; 149 return 0;
175 150
176exit_detach:
177 i2c_detach_client(client);
178exit_free: 151exit_free:
179 kfree(data); 152 kfree(data);
180exit: 153exit:
181 return err; 154 return err;
182} 155}
183 156
184static int pcf8575_detach_client(struct i2c_client *client) 157static int pcf8575_remove(struct i2c_client *client)
185{ 158{
186 int err;
187
188 sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group); 159 sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group);
189
190 err = i2c_detach_client(client);
191 if (err)
192 return err;
193
194 kfree(i2c_get_clientdata(client)); 160 kfree(i2c_get_clientdata(client));
195 return 0; 161 return 0;
196} 162}
197 163
164static const struct i2c_device_id pcf8575_id[] = {
165 { "pcf8575", 0 },
166 { }
167};
168
169static struct i2c_driver pcf8575_driver = {
170 .driver = {
171 .owner = THIS_MODULE,
172 .name = "pcf8575",
173 },
174 .probe = pcf8575_probe,
175 .remove = pcf8575_remove,
176 .id_table = pcf8575_id,
177
178 .detect = pcf8575_detect,
179 .address_data = &addr_data,
180};
181
198static int __init pcf8575_init(void) 182static int __init pcf8575_init(void)
199{ 183{
200 return i2c_add_driver(&pcf8575_driver); 184 return i2c_add_driver(&pcf8575_driver);