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 | 7dbafe021ba360bf25674a7e290d3e4a5c953981 (patch) | |
tree | e45fc613b0604a99e0935974669b213b35650e3e /drivers/hwmon/adm1025.c | |
parent | 65817ed8d1376afff21019b5c0e0109e5a7d9cc0 (diff) |
hwmon: (adm1025) Convert to a new-style i2c driver
The new-style adm1025 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/adm1025.c')
-rw-r--r-- | drivers/hwmon/adm1025.c | 101 |
1 files changed, 49 insertions, 52 deletions
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 1d76de7d75c7..4db04d603ec9 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * adm1025.c | 2 | * adm1025.c |
3 | * | 3 | * |
4 | * Copyright (C) 2000 Chen-Yuan Wu <gwu@esoft.com> | 4 | * Copyright (C) 2000 Chen-Yuan Wu <gwu@esoft.com> |
5 | * Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org> | 5 | * Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org> |
6 | * | 6 | * |
7 | * The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6 | 7 | * The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6 |
8 | * voltages (including its own power source) and up to two temperatures | 8 | * voltages (including its own power source) and up to two temperatures |
@@ -109,22 +109,35 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; | |||
109 | * Functions declaration | 109 | * Functions declaration |
110 | */ | 110 | */ |
111 | 111 | ||
112 | static int adm1025_attach_adapter(struct i2c_adapter *adapter); | 112 | static int adm1025_probe(struct i2c_client *client, |
113 | static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind); | 113 | const struct i2c_device_id *id); |
114 | static int adm1025_detect(struct i2c_client *client, int kind, | ||
115 | struct i2c_board_info *info); | ||
114 | static void adm1025_init_client(struct i2c_client *client); | 116 | static void adm1025_init_client(struct i2c_client *client); |
115 | static int adm1025_detach_client(struct i2c_client *client); | 117 | static int adm1025_remove(struct i2c_client *client); |
116 | static struct adm1025_data *adm1025_update_device(struct device *dev); | 118 | static struct adm1025_data *adm1025_update_device(struct device *dev); |
117 | 119 | ||
118 | /* | 120 | /* |
119 | * Driver data (common to all clients) | 121 | * Driver data (common to all clients) |
120 | */ | 122 | */ |
121 | 123 | ||
124 | static const struct i2c_device_id adm1025_id[] = { | ||
125 | { "adm1025", adm1025 }, | ||
126 | { "ne1619", ne1619 }, | ||
127 | { } | ||
128 | }; | ||
129 | MODULE_DEVICE_TABLE(i2c, adm1025_id); | ||
130 | |||
122 | static struct i2c_driver adm1025_driver = { | 131 | static struct i2c_driver adm1025_driver = { |
132 | .class = I2C_CLASS_HWMON, | ||
123 | .driver = { | 133 | .driver = { |
124 | .name = "adm1025", | 134 | .name = "adm1025", |
125 | }, | 135 | }, |
126 | .attach_adapter = adm1025_attach_adapter, | 136 | .probe = adm1025_probe, |
127 | .detach_client = adm1025_detach_client, | 137 | .remove = adm1025_remove, |
138 | .id_table = adm1025_id, | ||
139 | .detect = adm1025_detect, | ||
140 | .address_data = &addr_data, | ||
128 | }; | 141 | }; |
129 | 142 | ||
130 | /* | 143 | /* |
@@ -132,7 +145,6 @@ static struct i2c_driver adm1025_driver = { | |||
132 | */ | 145 | */ |
133 | 146 | ||
134 | struct adm1025_data { | 147 | struct adm1025_data { |
135 | struct i2c_client client; | ||
136 | struct device *hwmon_dev; | 148 | struct device *hwmon_dev; |
137 | struct mutex update_lock; | 149 | struct mutex update_lock; |
138 | char valid; /* zero until following fields are valid */ | 150 | char valid; /* zero until following fields are valid */ |
@@ -344,13 +356,6 @@ static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); | |||
344 | * Real code | 356 | * Real code |
345 | */ | 357 | */ |
346 | 358 | ||
347 | static int adm1025_attach_adapter(struct i2c_adapter *adapter) | ||
348 | { | ||
349 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
350 | return 0; | ||
351 | return i2c_probe(adapter, &addr_data, adm1025_detect); | ||
352 | } | ||
353 | |||
354 | static struct attribute *adm1025_attributes[] = { | 359 | static struct attribute *adm1025_attributes[] = { |
355 | &sensor_dev_attr_in0_input.dev_attr.attr, | 360 | &sensor_dev_attr_in0_input.dev_attr.attr, |
356 | &sensor_dev_attr_in1_input.dev_attr.attr, | 361 | &sensor_dev_attr_in1_input.dev_attr.attr, |
@@ -403,31 +408,16 @@ static const struct attribute_group adm1025_group_in4 = { | |||
403 | .attrs = adm1025_attributes_in4, | 408 | .attrs = adm1025_attributes_in4, |
404 | }; | 409 | }; |
405 | 410 | ||
406 | /* | 411 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
407 | * The following function does more than just detection. If detection | 412 | static int adm1025_detect(struct i2c_client *client, int kind, |
408 | * succeeds, it also registers the new chip. | 413 | struct i2c_board_info *info) |
409 | */ | ||
410 | static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) | ||
411 | { | 414 | { |
412 | struct i2c_client *client; | 415 | struct i2c_adapter *adapter = client->adapter; |
413 | struct adm1025_data *data; | ||
414 | int err = 0; | ||
415 | const char *name = ""; | 416 | const char *name = ""; |
416 | u8 config; | 417 | u8 config; |
417 | 418 | ||
418 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 419 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
419 | goto exit; | 420 | return -ENODEV; |
420 | |||
421 | if (!(data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL))) { | ||
422 | err = -ENOMEM; | ||
423 | goto exit; | ||
424 | } | ||
425 | |||
426 | client = &data->client; | ||
427 | i2c_set_clientdata(client, data); | ||
428 | client->addr = address; | ||
429 | client->adapter = adapter; | ||
430 | client->driver = &adm1025_driver; | ||
431 | 421 | ||
432 | /* | 422 | /* |
433 | * Now we do the remaining detection. A negative kind means that | 423 | * Now we do the remaining detection. A negative kind means that |
@@ -448,8 +438,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) | |||
448 | ADM1025_REG_STATUS2) & 0xBC) != 0x00) { | 438 | ADM1025_REG_STATUS2) & 0xBC) != 0x00) { |
449 | dev_dbg(&adapter->dev, | 439 | dev_dbg(&adapter->dev, |
450 | "ADM1025 detection failed at 0x%02x.\n", | 440 | "ADM1025 detection failed at 0x%02x.\n", |
451 | address); | 441 | client->addr); |
452 | goto exit_free; | 442 | return -ENODEV; |
453 | } | 443 | } |
454 | } | 444 | } |
455 | 445 | ||
@@ -465,7 +455,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) | |||
465 | } | 455 | } |
466 | } else | 456 | } else |
467 | if (man_id == 0xA1) { /* Philips */ | 457 | if (man_id == 0xA1) { /* Philips */ |
468 | if (address != 0x2E | 458 | if (client->addr != 0x2E |
469 | && (chip_id & 0xF0) == 0x20) { /* NE1619 */ | 459 | && (chip_id & 0xF0) == 0x20) { /* NE1619 */ |
470 | kind = ne1619; | 460 | kind = ne1619; |
471 | } | 461 | } |
@@ -475,7 +465,7 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) | |||
475 | dev_info(&adapter->dev, | 465 | dev_info(&adapter->dev, |
476 | "Unsupported chip (man_id=0x%02X, " | 466 | "Unsupported chip (man_id=0x%02X, " |
477 | "chip_id=0x%02X).\n", man_id, chip_id); | 467 | "chip_id=0x%02X).\n", man_id, chip_id); |
478 | goto exit_free; | 468 | return -ENODEV; |
479 | } | 469 | } |
480 | } | 470 | } |
481 | 471 | ||
@@ -484,23 +474,36 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) | |||
484 | } else if (kind == ne1619) { | 474 | } else if (kind == ne1619) { |
485 | name = "ne1619"; | 475 | name = "ne1619"; |
486 | } | 476 | } |
477 | strlcpy(info->type, name, I2C_NAME_SIZE); | ||
487 | 478 | ||
488 | /* We can fill in the remaining client fields */ | 479 | return 0; |
489 | strlcpy(client->name, name, I2C_NAME_SIZE); | 480 | } |
490 | mutex_init(&data->update_lock); | ||
491 | 481 | ||
492 | /* Tell the I2C layer a new client has arrived */ | 482 | static int adm1025_probe(struct i2c_client *client, |
493 | if ((err = i2c_attach_client(client))) | 483 | const struct i2c_device_id *id) |
494 | goto exit_free; | 484 | { |
485 | struct adm1025_data *data; | ||
486 | int err; | ||
487 | u8 config; | ||
488 | |||
489 | data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL); | ||
490 | if (!data) { | ||
491 | err = -ENOMEM; | ||
492 | goto exit; | ||
493 | } | ||
494 | |||
495 | i2c_set_clientdata(client, data); | ||
496 | mutex_init(&data->update_lock); | ||
495 | 497 | ||
496 | /* Initialize the ADM1025 chip */ | 498 | /* Initialize the ADM1025 chip */ |
497 | adm1025_init_client(client); | 499 | adm1025_init_client(client); |
498 | 500 | ||
499 | /* Register sysfs hooks */ | 501 | /* Register sysfs hooks */ |
500 | if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group))) | 502 | if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group))) |
501 | goto exit_detach; | 503 | goto exit_free; |
502 | 504 | ||
503 | /* Pin 11 is either in4 (+12V) or VID4 */ | 505 | /* Pin 11 is either in4 (+12V) or VID4 */ |
506 | config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); | ||
504 | if (!(config & 0x20)) { | 507 | if (!(config & 0x20)) { |
505 | if ((err = sysfs_create_group(&client->dev.kobj, | 508 | if ((err = sysfs_create_group(&client->dev.kobj, |
506 | &adm1025_group_in4))) | 509 | &adm1025_group_in4))) |
@@ -518,8 +521,6 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind) | |||
518 | exit_remove: | 521 | exit_remove: |
519 | sysfs_remove_group(&client->dev.kobj, &adm1025_group); | 522 | sysfs_remove_group(&client->dev.kobj, &adm1025_group); |
520 | sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); | 523 | sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); |
521 | exit_detach: | ||
522 | i2c_detach_client(client); | ||
523 | exit_free: | 524 | exit_free: |
524 | kfree(data); | 525 | kfree(data); |
525 | exit: | 526 | exit: |
@@ -568,18 +569,14 @@ static void adm1025_init_client(struct i2c_client *client) | |||
568 | (reg&0x7E)|0x01); | 569 | (reg&0x7E)|0x01); |
569 | } | 570 | } |
570 | 571 | ||
571 | static int adm1025_detach_client(struct i2c_client *client) | 572 | static int adm1025_remove(struct i2c_client *client) |
572 | { | 573 | { |
573 | struct adm1025_data *data = i2c_get_clientdata(client); | 574 | struct adm1025_data *data = i2c_get_clientdata(client); |
574 | int err; | ||
575 | 575 | ||
576 | hwmon_device_unregister(data->hwmon_dev); | 576 | hwmon_device_unregister(data->hwmon_dev); |
577 | sysfs_remove_group(&client->dev.kobj, &adm1025_group); | 577 | sysfs_remove_group(&client->dev.kobj, &adm1025_group); |
578 | sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); | 578 | sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); |
579 | 579 | ||
580 | if ((err = i2c_detach_client(client))) | ||
581 | return err; | ||
582 | |||
583 | kfree(data); | 580 | kfree(data); |
584 | return 0; | 581 | return 0; |
585 | } | 582 | } |