diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:08 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:08 -0400 |
commit | 65817ed8d1376afff21019b5c0e0109e5a7d9cc0 (patch) | |
tree | c06d100f8f6874fe46465c43b0167c98f36f8296 /drivers/hwmon | |
parent | 369932f6f840aedfbc717dd156bba7668a11d916 (diff) |
hwmon: (adm1021) Convert to a new-style i2c driver
The new-style adm1021 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/hwmon')
-rw-r--r-- | drivers/hwmon/adm1021.c | 105 |
1 files changed, 53 insertions, 52 deletions
diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index ecbf69484bf5..b11e06f644b1 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c | |||
@@ -78,7 +78,6 @@ clearing it. Weird, ey? --Phil */ | |||
78 | 78 | ||
79 | /* Each client has this additional data */ | 79 | /* Each client has this additional data */ |
80 | struct adm1021_data { | 80 | struct adm1021_data { |
81 | struct i2c_client client; | ||
82 | struct device *hwmon_dev; | 81 | struct device *hwmon_dev; |
83 | enum chips type; | 82 | enum chips type; |
84 | 83 | ||
@@ -98,23 +97,42 @@ struct adm1021_data { | |||
98 | u8 remote_temp_offset_prec; | 97 | u8 remote_temp_offset_prec; |
99 | }; | 98 | }; |
100 | 99 | ||
101 | static int adm1021_attach_adapter(struct i2c_adapter *adapter); | 100 | static int adm1021_probe(struct i2c_client *client, |
102 | static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind); | 101 | const struct i2c_device_id *id); |
102 | static int adm1021_detect(struct i2c_client *client, int kind, | ||
103 | struct i2c_board_info *info); | ||
103 | static void adm1021_init_client(struct i2c_client *client); | 104 | static void adm1021_init_client(struct i2c_client *client); |
104 | static int adm1021_detach_client(struct i2c_client *client); | 105 | static int adm1021_remove(struct i2c_client *client); |
105 | static struct adm1021_data *adm1021_update_device(struct device *dev); | 106 | static struct adm1021_data *adm1021_update_device(struct device *dev); |
106 | 107 | ||
107 | /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */ | 108 | /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */ |
108 | static int read_only; | 109 | static int read_only; |
109 | 110 | ||
110 | 111 | ||
112 | static const struct i2c_device_id adm1021_id[] = { | ||
113 | { "adm1021", adm1021 }, | ||
114 | { "adm1023", adm1023 }, | ||
115 | { "max1617", max1617 }, | ||
116 | { "max1617a", max1617a }, | ||
117 | { "thmc10", thmc10 }, | ||
118 | { "lm84", lm84 }, | ||
119 | { "gl523sm", gl523sm }, | ||
120 | { "mc1066", mc1066 }, | ||
121 | { } | ||
122 | }; | ||
123 | MODULE_DEVICE_TABLE(i2c, adm1021_id); | ||
124 | |||
111 | /* This is the driver that will be inserted */ | 125 | /* This is the driver that will be inserted */ |
112 | static struct i2c_driver adm1021_driver = { | 126 | static struct i2c_driver adm1021_driver = { |
127 | .class = I2C_CLASS_HWMON, | ||
113 | .driver = { | 128 | .driver = { |
114 | .name = "adm1021", | 129 | .name = "adm1021", |
115 | }, | 130 | }, |
116 | .attach_adapter = adm1021_attach_adapter, | 131 | .probe = adm1021_probe, |
117 | .detach_client = adm1021_detach_client, | 132 | .remove = adm1021_remove, |
133 | .id_table = adm1021_id, | ||
134 | .detect = adm1021_detect, | ||
135 | .address_data = &addr_data, | ||
118 | }; | 136 | }; |
119 | 137 | ||
120 | static ssize_t show_temp(struct device *dev, | 138 | static ssize_t show_temp(struct device *dev, |
@@ -216,13 +234,6 @@ static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); | |||
216 | 234 | ||
217 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 235 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
218 | 236 | ||
219 | static int adm1021_attach_adapter(struct i2c_adapter *adapter) | ||
220 | { | ||
221 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
222 | return 0; | ||
223 | return i2c_probe(adapter, &addr_data, adm1021_detect); | ||
224 | } | ||
225 | |||
226 | static struct attribute *adm1021_attributes[] = { | 237 | static struct attribute *adm1021_attributes[] = { |
227 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 238 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
228 | &sensor_dev_attr_temp1_min.dev_attr.attr, | 239 | &sensor_dev_attr_temp1_min.dev_attr.attr, |
@@ -243,36 +254,21 @@ static const struct attribute_group adm1021_group = { | |||
243 | .attrs = adm1021_attributes, | 254 | .attrs = adm1021_attributes, |
244 | }; | 255 | }; |
245 | 256 | ||
246 | static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) | 257 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
258 | static int adm1021_detect(struct i2c_client *client, int kind, | ||
259 | struct i2c_board_info *info) | ||
247 | { | 260 | { |
261 | struct i2c_adapter *adapter = client->adapter; | ||
248 | int i; | 262 | int i; |
249 | struct i2c_client *client; | ||
250 | struct adm1021_data *data; | ||
251 | int err = 0; | ||
252 | const char *type_name = ""; | 263 | const char *type_name = ""; |
253 | int conv_rate, status, config; | 264 | int conv_rate, status, config; |
254 | 265 | ||
255 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 266 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
256 | pr_debug("adm1021: detect failed, " | 267 | pr_debug("adm1021: detect failed, " |
257 | "smbus byte data not supported!\n"); | 268 | "smbus byte data not supported!\n"); |
258 | goto error0; | 269 | return -ENODEV; |
259 | } | ||
260 | |||
261 | /* OK. For now, we presume we have a valid client. We now create the | ||
262 | client structure, even though we cannot fill it completely yet. | ||
263 | But it allows us to access adm1021 register values. */ | ||
264 | |||
265 | if (!(data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL))) { | ||
266 | pr_debug("adm1021: detect failed, kzalloc failed!\n"); | ||
267 | err = -ENOMEM; | ||
268 | goto error0; | ||
269 | } | 270 | } |
270 | 271 | ||
271 | client = &data->client; | ||
272 | i2c_set_clientdata(client, data); | ||
273 | client->addr = address; | ||
274 | client->adapter = adapter; | ||
275 | client->driver = &adm1021_driver; | ||
276 | status = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS); | 272 | status = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS); |
277 | conv_rate = i2c_smbus_read_byte_data(client, | 273 | conv_rate = i2c_smbus_read_byte_data(client, |
278 | ADM1021_REG_CONV_RATE_R); | 274 | ADM1021_REG_CONV_RATE_R); |
@@ -284,8 +280,7 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) | |||
284 | || (conv_rate & 0xF8) != 0x00) { | 280 | || (conv_rate & 0xF8) != 0x00) { |
285 | pr_debug("adm1021: detect failed, " | 281 | pr_debug("adm1021: detect failed, " |
286 | "chip not detected!\n"); | 282 | "chip not detected!\n"); |
287 | err = -ENODEV; | 283 | return -ENODEV; |
288 | goto error1; | ||
289 | } | 284 | } |
290 | } | 285 | } |
291 | 286 | ||
@@ -336,24 +331,36 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) | |||
336 | type_name = "mc1066"; | 331 | type_name = "mc1066"; |
337 | } | 332 | } |
338 | pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n", | 333 | pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n", |
339 | type_name, i2c_adapter_id(adapter), address); | 334 | type_name, i2c_adapter_id(adapter), client->addr); |
335 | strlcpy(info->type, type_name, I2C_NAME_SIZE); | ||
340 | 336 | ||
341 | /* Fill in the remaining client fields */ | 337 | return 0; |
342 | strlcpy(client->name, type_name, I2C_NAME_SIZE); | 338 | } |
343 | data->type = kind; | ||
344 | mutex_init(&data->update_lock); | ||
345 | 339 | ||
346 | /* Tell the I2C layer a new client has arrived */ | 340 | static int adm1021_probe(struct i2c_client *client, |
347 | if ((err = i2c_attach_client(client))) | 341 | const struct i2c_device_id *id) |
348 | goto error1; | 342 | { |
343 | struct adm1021_data *data; | ||
344 | int err; | ||
345 | |||
346 | data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL); | ||
347 | if (!data) { | ||
348 | pr_debug("adm1021: detect failed, kzalloc failed!\n"); | ||
349 | err = -ENOMEM; | ||
350 | goto error0; | ||
351 | } | ||
352 | |||
353 | i2c_set_clientdata(client, data); | ||
354 | data->type = id->driver_data; | ||
355 | mutex_init(&data->update_lock); | ||
349 | 356 | ||
350 | /* Initialize the ADM1021 chip */ | 357 | /* Initialize the ADM1021 chip */ |
351 | if (kind != lm84 && !read_only) | 358 | if (data->type != lm84 && !read_only) |
352 | adm1021_init_client(client); | 359 | adm1021_init_client(client); |
353 | 360 | ||
354 | /* Register sysfs hooks */ | 361 | /* Register sysfs hooks */ |
355 | if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group))) | 362 | if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group))) |
356 | goto error2; | 363 | goto error1; |
357 | 364 | ||
358 | data->hwmon_dev = hwmon_device_register(&client->dev); | 365 | data->hwmon_dev = hwmon_device_register(&client->dev); |
359 | if (IS_ERR(data->hwmon_dev)) { | 366 | if (IS_ERR(data->hwmon_dev)) { |
@@ -365,8 +372,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind) | |||
365 | 372 | ||
366 | error3: | 373 | error3: |
367 | sysfs_remove_group(&client->dev.kobj, &adm1021_group); | 374 | sysfs_remove_group(&client->dev.kobj, &adm1021_group); |
368 | error2: | ||
369 | i2c_detach_client(client); | ||
370 | error1: | 375 | error1: |
371 | kfree(data); | 376 | kfree(data); |
372 | error0: | 377 | error0: |
@@ -382,17 +387,13 @@ static void adm1021_init_client(struct i2c_client *client) | |||
382 | i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); | 387 | i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); |
383 | } | 388 | } |
384 | 389 | ||
385 | static int adm1021_detach_client(struct i2c_client *client) | 390 | static int adm1021_remove(struct i2c_client *client) |
386 | { | 391 | { |
387 | struct adm1021_data *data = i2c_get_clientdata(client); | 392 | struct adm1021_data *data = i2c_get_clientdata(client); |
388 | int err; | ||
389 | 393 | ||
390 | hwmon_device_unregister(data->hwmon_dev); | 394 | hwmon_device_unregister(data->hwmon_dev); |
391 | sysfs_remove_group(&client->dev.kobj, &adm1021_group); | 395 | sysfs_remove_group(&client->dev.kobj, &adm1021_group); |
392 | 396 | ||
393 | if ((err = i2c_detach_client(client))) | ||
394 | return err; | ||
395 | |||
396 | kfree(data); | 397 | kfree(data); |
397 | return 0; | 398 | return 0; |
398 | } | 399 | } |