diff options
| author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:13 -0400 |
|---|---|---|
| committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:13 -0400 |
| commit | d5957be2f1535b1a6c77eabba0781ec7245c5dea (patch) | |
| tree | 8597a5a25444c8cfb222b5fae63674b837919ffa | |
| parent | a23a9fe1d4d725e1624635f49e9790ec32deffd0 (diff) | |
hwmon: (lm63) Convert to a new-style i2c driver
The new-style lm63 driver implements the optional detect() callback
to cover the use cases of the legacy driver.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
| -rw-r--r-- | drivers/hwmon/lm63.c | 99 |
1 files changed, 44 insertions, 55 deletions
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 116287008083..3195a265f0e9 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * lm63.c - driver for the National Semiconductor LM63 temperature sensor | 2 | * lm63.c - driver for the National Semiconductor LM63 temperature sensor |
| 3 | * with integrated fan control | 3 | * with integrated fan control |
| 4 | * Copyright (C) 2004-2006 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2004-2008 Jean Delvare <khali@linux-fr.org> |
| 5 | * Based on the lm90 driver. | 5 | * Based on the lm90 driver. |
| 6 | * | 6 | * |
| 7 | * The LM63 is a sensor chip made by National Semiconductor. It measures | 7 | * The LM63 is a sensor chip made by National Semiconductor. It measures |
| @@ -128,24 +128,36 @@ I2C_CLIENT_INSMOD_1(lm63); | |||
| 128 | * Functions declaration | 128 | * Functions declaration |
| 129 | */ | 129 | */ |
| 130 | 130 | ||
| 131 | static int lm63_attach_adapter(struct i2c_adapter *adapter); | 131 | static int lm63_probe(struct i2c_client *client, |
| 132 | static int lm63_detach_client(struct i2c_client *client); | 132 | const struct i2c_device_id *id); |
| 133 | static int lm63_remove(struct i2c_client *client); | ||
| 133 | 134 | ||
| 134 | static struct lm63_data *lm63_update_device(struct device *dev); | 135 | static struct lm63_data *lm63_update_device(struct device *dev); |
| 135 | 136 | ||
| 136 | static int lm63_detect(struct i2c_adapter *adapter, int address, int kind); | 137 | static int lm63_detect(struct i2c_client *client, int kind, |
| 138 | struct i2c_board_info *info); | ||
| 137 | static void lm63_init_client(struct i2c_client *client); | 139 | static void lm63_init_client(struct i2c_client *client); |
| 138 | 140 | ||
| 139 | /* | 141 | /* |
| 140 | * Driver data (common to all clients) | 142 | * Driver data (common to all clients) |
| 141 | */ | 143 | */ |
| 142 | 144 | ||
| 145 | static const struct i2c_device_id lm63_id[] = { | ||
| 146 | { "lm63", lm63 }, | ||
| 147 | { } | ||
| 148 | }; | ||
| 149 | MODULE_DEVICE_TABLE(i2c, lm63_id); | ||
| 150 | |||
| 143 | static struct i2c_driver lm63_driver = { | 151 | static struct i2c_driver lm63_driver = { |
| 152 | .class = I2C_CLASS_HWMON, | ||
| 144 | .driver = { | 153 | .driver = { |
| 145 | .name = "lm63", | 154 | .name = "lm63", |
| 146 | }, | 155 | }, |
| 147 | .attach_adapter = lm63_attach_adapter, | 156 | .probe = lm63_probe, |
| 148 | .detach_client = lm63_detach_client, | 157 | .remove = lm63_remove, |
| 158 | .id_table = lm63_id, | ||
| 159 | .detect = lm63_detect, | ||
| 160 | .address_data = &addr_data, | ||
| 149 | }; | 161 | }; |
| 150 | 162 | ||
| 151 | /* | 163 | /* |
| @@ -153,7 +165,6 @@ static struct i2c_driver lm63_driver = { | |||
| 153 | */ | 165 | */ |
| 154 | 166 | ||
| 155 | struct lm63_data { | 167 | struct lm63_data { |
| 156 | struct i2c_client client; | ||
| 157 | struct device *hwmon_dev; | 168 | struct device *hwmon_dev; |
| 158 | struct mutex update_lock; | 169 | struct mutex update_lock; |
| 159 | char valid; /* zero until following fields are valid */ | 170 | char valid; /* zero until following fields are valid */ |
| @@ -411,43 +422,14 @@ static const struct attribute_group lm63_group_fan1 = { | |||
| 411 | * Real code | 422 | * Real code |
| 412 | */ | 423 | */ |
| 413 | 424 | ||
| 414 | static int lm63_attach_adapter(struct i2c_adapter *adapter) | 425 | /* Return 0 if detection is successful, -ENODEV otherwise */ |
| 426 | static int lm63_detect(struct i2c_client *new_client, int kind, | ||
| 427 | struct i2c_board_info *info) | ||
| 415 | { | 428 | { |
| 416 | if (!(adapter->class & I2C_CLASS_HWMON)) | 429 | struct i2c_adapter *adapter = new_client->adapter; |
| 417 | return 0; | ||
| 418 | return i2c_probe(adapter, &addr_data, lm63_detect); | ||
| 419 | } | ||
| 420 | |||
| 421 | /* | ||
| 422 | * The following function does more than just detection. If detection | ||
| 423 | * succeeds, it also registers the new chip. | ||
| 424 | */ | ||
| 425 | static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) | ||
| 426 | { | ||
| 427 | struct i2c_client *new_client; | ||
| 428 | struct lm63_data *data; | ||
| 429 | int err = 0; | ||
| 430 | 430 | ||
| 431 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 431 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
| 432 | goto exit; | 432 | return -ENODEV; |
| 433 | |||
| 434 | if (!(data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL))) { | ||
| 435 | err = -ENOMEM; | ||
| 436 | goto exit; | ||
| 437 | } | ||
| 438 | |||
| 439 | /* The common I2C client data is placed right before the | ||
| 440 | LM63-specific data. */ | ||
| 441 | new_client = &data->client; | ||
| 442 | i2c_set_clientdata(new_client, data); | ||
| 443 | new_client->addr = address; | ||
| 444 | new_client->adapter = adapter; | ||
| 445 | new_client->driver = &lm63_driver; | ||
| 446 | new_client->flags = 0; | ||
| 447 | |||
| 448 | /* Default to an LM63 if forced */ | ||
| 449 | if (kind == 0) | ||
| 450 | kind = lm63; | ||
| 451 | 433 | ||
| 452 | if (kind < 0) { /* must identify */ | 434 | if (kind < 0) { /* must identify */ |
| 453 | u8 man_id, chip_id, reg_config1, reg_config2; | 435 | u8 man_id, chip_id, reg_config1, reg_config2; |
| @@ -477,25 +459,38 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 477 | dev_dbg(&adapter->dev, "Unsupported chip " | 459 | dev_dbg(&adapter->dev, "Unsupported chip " |
| 478 | "(man_id=0x%02X, chip_id=0x%02X).\n", | 460 | "(man_id=0x%02X, chip_id=0x%02X).\n", |
| 479 | man_id, chip_id); | 461 | man_id, chip_id); |
| 480 | goto exit_free; | 462 | return -ENODEV; |
| 481 | } | 463 | } |
| 482 | } | 464 | } |
| 483 | 465 | ||
| 484 | strlcpy(new_client->name, "lm63", I2C_NAME_SIZE); | 466 | strlcpy(info->type, "lm63", I2C_NAME_SIZE); |
| 467 | |||
| 468 | return 0; | ||
| 469 | } | ||
| 470 | |||
| 471 | static int lm63_probe(struct i2c_client *new_client, | ||
| 472 | const struct i2c_device_id *id) | ||
| 473 | { | ||
| 474 | struct lm63_data *data; | ||
| 475 | int err; | ||
| 476 | |||
| 477 | data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL); | ||
| 478 | if (!data) { | ||
| 479 | err = -ENOMEM; | ||
| 480 | goto exit; | ||
| 481 | } | ||
| 482 | |||
| 483 | i2c_set_clientdata(new_client, data); | ||
| 485 | data->valid = 0; | 484 | data->valid = 0; |
| 486 | mutex_init(&data->update_lock); | 485 | mutex_init(&data->update_lock); |
| 487 | 486 | ||
| 488 | /* Tell the I2C layer a new client has arrived */ | ||
| 489 | if ((err = i2c_attach_client(new_client))) | ||
| 490 | goto exit_free; | ||
| 491 | |||
| 492 | /* Initialize the LM63 chip */ | 487 | /* Initialize the LM63 chip */ |
| 493 | lm63_init_client(new_client); | 488 | lm63_init_client(new_client); |
| 494 | 489 | ||
| 495 | /* Register sysfs hooks */ | 490 | /* Register sysfs hooks */ |
| 496 | if ((err = sysfs_create_group(&new_client->dev.kobj, | 491 | if ((err = sysfs_create_group(&new_client->dev.kobj, |
| 497 | &lm63_group))) | 492 | &lm63_group))) |
| 498 | goto exit_detach; | 493 | goto exit_free; |
| 499 | if (data->config & 0x04) { /* tachometer enabled */ | 494 | if (data->config & 0x04) { /* tachometer enabled */ |
| 500 | if ((err = sysfs_create_group(&new_client->dev.kobj, | 495 | if ((err = sysfs_create_group(&new_client->dev.kobj, |
| 501 | &lm63_group_fan1))) | 496 | &lm63_group_fan1))) |
| @@ -513,8 +508,6 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) | |||
| 513 | exit_remove_files: | 508 | exit_remove_files: |
| 514 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group); | 509 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group); |
| 515 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); | 510 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); |
| 516 | exit_detach: | ||
| 517 | i2c_detach_client(new_client); | ||
| 518 | exit_free: | 511 | exit_free: |
| 519 | kfree(data); | 512 | kfree(data); |
| 520 | exit: | 513 | exit: |
| @@ -556,18 +549,14 @@ static void lm63_init_client(struct i2c_client *client) | |||
| 556 | (data->config_fan & 0x20) ? "manual" : "auto"); | 549 | (data->config_fan & 0x20) ? "manual" : "auto"); |
| 557 | } | 550 | } |
| 558 | 551 | ||
| 559 | static int lm63_detach_client(struct i2c_client *client) | 552 | static int lm63_remove(struct i2c_client *client) |
| 560 | { | 553 | { |
| 561 | struct lm63_data *data = i2c_get_clientdata(client); | 554 | struct lm63_data *data = i2c_get_clientdata(client); |
| 562 | int err; | ||
| 563 | 555 | ||
| 564 | hwmon_device_unregister(data->hwmon_dev); | 556 | hwmon_device_unregister(data->hwmon_dev); |
| 565 | sysfs_remove_group(&client->dev.kobj, &lm63_group); | 557 | sysfs_remove_group(&client->dev.kobj, &lm63_group); |
| 566 | sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); | 558 | sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); |
| 567 | 559 | ||
| 568 | if ((err = i2c_detach_client(client))) | ||
| 569 | return err; | ||
| 570 | |||
| 571 | kfree(data); | 560 | kfree(data); |
| 572 | return 0; | 561 | return 0; |
| 573 | } | 562 | } |
