diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:06 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:06 -0400 |
commit | 8b77e6ac4911a79993e583ece719736a9e035b1d (patch) | |
tree | 91019e9effc2ceb173c08c00ed5698057beb4ccf /drivers/i2c/chips/pcf8591.c | |
parent | 68be3363740e4ac3b4309faebcdf8fe5bf62ed2f (diff) |
i2c: Convert the pcf8591 driver to a new-style i2c driver
The new-style pcf8591 driver implements the optional detect() callback
to cover the use cases of the legacy driver.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/i2c/chips/pcf8591.c')
-rw-r--r-- | drivers/i2c/chips/pcf8591.c | 94 |
1 files changed, 40 insertions, 54 deletions
diff --git a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c index db735379f22f..16ce3e193776 100644 --- a/drivers/i2c/chips/pcf8591.c +++ b/drivers/i2c/chips/pcf8591.c | |||
@@ -72,28 +72,15 @@ MODULE_PARM_DESC(input_mode, | |||
72 | #define REG_TO_SIGNED(reg) (((reg) & 0x80)?((reg) - 256):(reg)) | 72 | #define REG_TO_SIGNED(reg) (((reg) & 0x80)?((reg) - 256):(reg)) |
73 | 73 | ||
74 | struct pcf8591_data { | 74 | struct pcf8591_data { |
75 | struct i2c_client client; | ||
76 | struct mutex update_lock; | 75 | struct mutex update_lock; |
77 | 76 | ||
78 | u8 control; | 77 | u8 control; |
79 | u8 aout; | 78 | u8 aout; |
80 | }; | 79 | }; |
81 | 80 | ||
82 | static int pcf8591_attach_adapter(struct i2c_adapter *adapter); | ||
83 | static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind); | ||
84 | static int pcf8591_detach_client(struct i2c_client *client); | ||
85 | static void pcf8591_init_client(struct i2c_client *client); | 81 | static void pcf8591_init_client(struct i2c_client *client); |
86 | static int pcf8591_read_channel(struct device *dev, int channel); | 82 | static int pcf8591_read_channel(struct device *dev, int channel); |
87 | 83 | ||
88 | /* This is the driver that will be inserted */ | ||
89 | static struct i2c_driver pcf8591_driver = { | ||
90 | .driver = { | ||
91 | .name = "pcf8591", | ||
92 | }, | ||
93 | .attach_adapter = pcf8591_attach_adapter, | ||
94 | .detach_client = pcf8591_detach_client, | ||
95 | }; | ||
96 | |||
97 | /* following are the sysfs callback functions */ | 84 | /* following are the sysfs callback functions */ |
98 | #define show_in_channel(channel) \ | 85 | #define show_in_channel(channel) \ |
99 | static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf) \ | 86 | static ssize_t show_in##channel##_input(struct device *dev, struct device_attribute *attr, char *buf) \ |
@@ -180,58 +167,46 @@ static const struct attribute_group pcf8591_attr_group_opt = { | |||
180 | /* | 167 | /* |
181 | * Real code | 168 | * Real code |
182 | */ | 169 | */ |
183 | static int pcf8591_attach_adapter(struct i2c_adapter *adapter) | ||
184 | { | ||
185 | return i2c_probe(adapter, &addr_data, pcf8591_detect); | ||
186 | } | ||
187 | 170 | ||
188 | /* This function is called by i2c_probe */ | 171 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
189 | static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) | 172 | static int pcf8591_detect(struct i2c_client *client, int kind, |
173 | struct i2c_board_info *info) | ||
190 | { | 174 | { |
191 | struct i2c_client *client; | 175 | struct i2c_adapter *adapter = client->adapter; |
192 | struct pcf8591_data *data; | ||
193 | int err = 0; | ||
194 | 176 | ||
195 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE | 177 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE |
196 | | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) | 178 | | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) |
197 | goto exit; | 179 | return -ENODEV; |
180 | |||
181 | /* Now, we would do the remaining detection. But the PCF8591 is plainly | ||
182 | impossible to detect! Stupid chip. */ | ||
183 | |||
184 | strlcpy(info->type, "pcf8591", I2C_NAME_SIZE); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int pcf8591_probe(struct i2c_client *client, | ||
190 | const struct i2c_device_id *id) | ||
191 | { | ||
192 | struct pcf8591_data *data; | ||
193 | int err; | ||
198 | 194 | ||
199 | /* OK. For now, we presume we have a valid client. We now create the | ||
200 | client structure, even though we cannot fill it completely yet. */ | ||
201 | if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) { | 195 | if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) { |
202 | err = -ENOMEM; | 196 | err = -ENOMEM; |
203 | goto exit; | 197 | goto exit; |
204 | } | 198 | } |
205 | 199 | ||
206 | client = &data->client; | ||
207 | i2c_set_clientdata(client, data); | 200 | i2c_set_clientdata(client, data); |
208 | client->addr = address; | ||
209 | client->adapter = adapter; | ||
210 | client->driver = &pcf8591_driver; | ||
211 | |||
212 | /* Now, we would do the remaining detection. But the PCF8591 is plainly | ||
213 | impossible to detect! Stupid chip. */ | ||
214 | |||
215 | /* Determine the chip type - only one kind supported! */ | ||
216 | if (kind <= 0) | ||
217 | kind = pcf8591; | ||
218 | |||
219 | /* Fill in the remaining client fields and put it into the global | ||
220 | list */ | ||
221 | strlcpy(client->name, "pcf8591", I2C_NAME_SIZE); | ||
222 | mutex_init(&data->update_lock); | 201 | mutex_init(&data->update_lock); |
223 | 202 | ||
224 | /* Tell the I2C layer a new client has arrived */ | ||
225 | if ((err = i2c_attach_client(client))) | ||
226 | goto exit_kfree; | ||
227 | |||
228 | /* Initialize the PCF8591 chip */ | 203 | /* Initialize the PCF8591 chip */ |
229 | pcf8591_init_client(client); | 204 | pcf8591_init_client(client); |
230 | 205 | ||
231 | /* Register sysfs hooks */ | 206 | /* Register sysfs hooks */ |
232 | err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group); | 207 | err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group); |
233 | if (err) | 208 | if (err) |
234 | goto exit_detach; | 209 | goto exit_kfree; |
235 | 210 | ||
236 | /* Register input2 if not in "two differential inputs" mode */ | 211 | /* Register input2 if not in "two differential inputs" mode */ |
237 | if (input_mode != 3) { | 212 | if (input_mode != 3) { |
@@ -252,24 +227,16 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind) | |||
252 | exit_sysfs_remove: | 227 | exit_sysfs_remove: |
253 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); | 228 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); |
254 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); | 229 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); |
255 | exit_detach: | ||
256 | i2c_detach_client(client); | ||
257 | exit_kfree: | 230 | exit_kfree: |
258 | kfree(data); | 231 | kfree(data); |
259 | exit: | 232 | exit: |
260 | return err; | 233 | return err; |
261 | } | 234 | } |
262 | 235 | ||
263 | static int pcf8591_detach_client(struct i2c_client *client) | 236 | static int pcf8591_remove(struct i2c_client *client) |
264 | { | 237 | { |
265 | int err; | ||
266 | |||
267 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); | 238 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); |
268 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); | 239 | sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); |
269 | |||
270 | if ((err = i2c_detach_client(client))) | ||
271 | return err; | ||
272 | |||
273 | kfree(i2c_get_clientdata(client)); | 240 | kfree(i2c_get_clientdata(client)); |
274 | return 0; | 241 | return 0; |
275 | } | 242 | } |
@@ -316,6 +283,25 @@ static int pcf8591_read_channel(struct device *dev, int channel) | |||
316 | return (10 * value); | 283 | return (10 * value); |
317 | } | 284 | } |
318 | 285 | ||
286 | static const struct i2c_device_id pcf8591_id[] = { | ||
287 | { "pcf8591", 0 }, | ||
288 | { } | ||
289 | }; | ||
290 | MODULE_DEVICE_TABLE(i2c, pcf8591_id); | ||
291 | |||
292 | static struct i2c_driver pcf8591_driver = { | ||
293 | .driver = { | ||
294 | .name = "pcf8591", | ||
295 | }, | ||
296 | .probe = pcf8591_probe, | ||
297 | .remove = pcf8591_remove, | ||
298 | .id_table = pcf8591_id, | ||
299 | |||
300 | .class = I2C_CLASS_HWMON, /* Nearest choice */ | ||
301 | .detect = pcf8591_detect, | ||
302 | .address_data = &addr_data, | ||
303 | }; | ||
304 | |||
319 | static int __init pcf8591_init(void) | 305 | static int __init pcf8591_init(void) |
320 | { | 306 | { |
321 | if (input_mode < 0 || input_mode > 3) { | 307 | if (input_mode < 0 || input_mode > 3) { |