diff options
Diffstat (limited to 'drivers/hwmon/adm1025.c')
| -rw-r--r-- | drivers/hwmon/adm1025.c | 234 |
1 files changed, 98 insertions, 136 deletions
diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 9ffc4c8ca8b5..d6c767ace916 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c | |||
| @@ -103,46 +103,12 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; | |||
| 103 | (val) + 500) / 1000)) | 103 | (val) + 500) / 1000)) |
| 104 | 104 | ||
| 105 | /* | 105 | /* |
| 106 | * Functions declaration | ||
| 107 | */ | ||
| 108 | |||
| 109 | static int adm1025_probe(struct i2c_client *client, | ||
| 110 | const struct i2c_device_id *id); | ||
| 111 | static int adm1025_detect(struct i2c_client *client, | ||
| 112 | struct i2c_board_info *info); | ||
| 113 | static void adm1025_init_client(struct i2c_client *client); | ||
| 114 | static int adm1025_remove(struct i2c_client *client); | ||
| 115 | static struct adm1025_data *adm1025_update_device(struct device *dev); | ||
| 116 | |||
| 117 | /* | ||
| 118 | * Driver data (common to all clients) | ||
| 119 | */ | ||
| 120 | |||
| 121 | static const struct i2c_device_id adm1025_id[] = { | ||
| 122 | { "adm1025", adm1025 }, | ||
| 123 | { "ne1619", ne1619 }, | ||
| 124 | { } | ||
| 125 | }; | ||
| 126 | MODULE_DEVICE_TABLE(i2c, adm1025_id); | ||
| 127 | |||
| 128 | static struct i2c_driver adm1025_driver = { | ||
| 129 | .class = I2C_CLASS_HWMON, | ||
| 130 | .driver = { | ||
| 131 | .name = "adm1025", | ||
| 132 | }, | ||
| 133 | .probe = adm1025_probe, | ||
| 134 | .remove = adm1025_remove, | ||
| 135 | .id_table = adm1025_id, | ||
| 136 | .detect = adm1025_detect, | ||
| 137 | .address_list = normal_i2c, | ||
| 138 | }; | ||
| 139 | |||
| 140 | /* | ||
| 141 | * Client data (each client gets its own) | 106 | * Client data (each client gets its own) |
| 142 | */ | 107 | */ |
| 143 | 108 | ||
| 144 | struct adm1025_data { | 109 | struct adm1025_data { |
| 145 | struct device *hwmon_dev; | 110 | struct i2c_client *client; |
| 111 | const struct attribute_group *groups[3]; | ||
| 146 | struct mutex update_lock; | 112 | struct mutex update_lock; |
| 147 | char valid; /* zero until following fields are valid */ | 113 | char valid; /* zero until following fields are valid */ |
| 148 | unsigned long last_updated; /* in jiffies */ | 114 | unsigned long last_updated; /* in jiffies */ |
| @@ -158,6 +124,51 @@ struct adm1025_data { | |||
| 158 | u8 vrm; | 124 | u8 vrm; |
| 159 | }; | 125 | }; |
| 160 | 126 | ||
| 127 | static struct adm1025_data *adm1025_update_device(struct device *dev) | ||
| 128 | { | ||
| 129 | struct adm1025_data *data = dev_get_drvdata(dev); | ||
| 130 | struct i2c_client *client = data->client; | ||
| 131 | |||
| 132 | mutex_lock(&data->update_lock); | ||
| 133 | |||
| 134 | if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { | ||
| 135 | int i; | ||
| 136 | |||
| 137 | dev_dbg(&client->dev, "Updating data.\n"); | ||
| 138 | for (i = 0; i < 6; i++) { | ||
| 139 | data->in[i] = i2c_smbus_read_byte_data(client, | ||
| 140 | ADM1025_REG_IN(i)); | ||
| 141 | data->in_min[i] = i2c_smbus_read_byte_data(client, | ||
| 142 | ADM1025_REG_IN_MIN(i)); | ||
| 143 | data->in_max[i] = i2c_smbus_read_byte_data(client, | ||
| 144 | ADM1025_REG_IN_MAX(i)); | ||
| 145 | } | ||
| 146 | for (i = 0; i < 2; i++) { | ||
| 147 | data->temp[i] = i2c_smbus_read_byte_data(client, | ||
| 148 | ADM1025_REG_TEMP(i)); | ||
| 149 | data->temp_min[i] = i2c_smbus_read_byte_data(client, | ||
| 150 | ADM1025_REG_TEMP_LOW(i)); | ||
| 151 | data->temp_max[i] = i2c_smbus_read_byte_data(client, | ||
| 152 | ADM1025_REG_TEMP_HIGH(i)); | ||
| 153 | } | ||
| 154 | data->alarms = i2c_smbus_read_byte_data(client, | ||
| 155 | ADM1025_REG_STATUS1) | ||
| 156 | | (i2c_smbus_read_byte_data(client, | ||
| 157 | ADM1025_REG_STATUS2) << 8); | ||
| 158 | data->vid = (i2c_smbus_read_byte_data(client, | ||
| 159 | ADM1025_REG_VID) & 0x0f) | ||
| 160 | | ((i2c_smbus_read_byte_data(client, | ||
| 161 | ADM1025_REG_VID4) & 0x01) << 4); | ||
| 162 | |||
| 163 | data->last_updated = jiffies; | ||
| 164 | data->valid = 1; | ||
| 165 | } | ||
| 166 | |||
| 167 | mutex_unlock(&data->update_lock); | ||
| 168 | |||
| 169 | return data; | ||
| 170 | } | ||
| 171 | |||
| 161 | /* | 172 | /* |
| 162 | * Sysfs stuff | 173 | * Sysfs stuff |
| 163 | */ | 174 | */ |
| @@ -217,8 +228,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, | |||
| 217 | const char *buf, size_t count) | 228 | const char *buf, size_t count) |
| 218 | { | 229 | { |
| 219 | int index = to_sensor_dev_attr(attr)->index; | 230 | int index = to_sensor_dev_attr(attr)->index; |
| 220 | struct i2c_client *client = to_i2c_client(dev); | 231 | struct adm1025_data *data = dev_get_drvdata(dev); |
| 221 | struct adm1025_data *data = i2c_get_clientdata(client); | 232 | struct i2c_client *client = data->client; |
| 222 | long val; | 233 | long val; |
| 223 | int err; | 234 | int err; |
| 224 | 235 | ||
| @@ -238,8 +249,8 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, | |||
| 238 | const char *buf, size_t count) | 249 | const char *buf, size_t count) |
| 239 | { | 250 | { |
| 240 | int index = to_sensor_dev_attr(attr)->index; | 251 | int index = to_sensor_dev_attr(attr)->index; |
| 241 | struct i2c_client *client = to_i2c_client(dev); | 252 | struct adm1025_data *data = dev_get_drvdata(dev); |
| 242 | struct adm1025_data *data = i2c_get_clientdata(client); | 253 | struct i2c_client *client = data->client; |
| 243 | long val; | 254 | long val; |
| 244 | int err; | 255 | int err; |
| 245 | 256 | ||
| @@ -273,8 +284,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, | |||
| 273 | const char *buf, size_t count) | 284 | const char *buf, size_t count) |
| 274 | { | 285 | { |
| 275 | int index = to_sensor_dev_attr(attr)->index; | 286 | int index = to_sensor_dev_attr(attr)->index; |
| 276 | struct i2c_client *client = to_i2c_client(dev); | 287 | struct adm1025_data *data = dev_get_drvdata(dev); |
| 277 | struct adm1025_data *data = i2c_get_clientdata(client); | 288 | struct i2c_client *client = data->client; |
| 278 | long val; | 289 | long val; |
| 279 | int err; | 290 | int err; |
| 280 | 291 | ||
| @@ -294,8 +305,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, | |||
| 294 | const char *buf, size_t count) | 305 | const char *buf, size_t count) |
| 295 | { | 306 | { |
| 296 | int index = to_sensor_dev_attr(attr)->index; | 307 | int index = to_sensor_dev_attr(attr)->index; |
| 297 | struct i2c_client *client = to_i2c_client(dev); | 308 | struct adm1025_data *data = dev_get_drvdata(dev); |
| 298 | struct adm1025_data *data = i2c_get_clientdata(client); | 309 | struct i2c_client *client = data->client; |
| 299 | long val; | 310 | long val; |
| 300 | int err; | 311 | int err; |
| 301 | 312 | ||
| @@ -371,6 +382,9 @@ static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, | |||
| 371 | if (err) | 382 | if (err) |
| 372 | return err; | 383 | return err; |
| 373 | 384 | ||
| 385 | if (val > 255) | ||
| 386 | return -EINVAL; | ||
| 387 | |||
| 374 | data->vrm = val; | 388 | data->vrm = val; |
| 375 | return count; | 389 | return count; |
| 376 | } | 390 | } |
| @@ -470,51 +484,6 @@ static int adm1025_detect(struct i2c_client *client, | |||
| 470 | return 0; | 484 | return 0; |
| 471 | } | 485 | } |
| 472 | 486 | ||
| 473 | static int adm1025_probe(struct i2c_client *client, | ||
| 474 | const struct i2c_device_id *id) | ||
| 475 | { | ||
| 476 | struct adm1025_data *data; | ||
| 477 | int err; | ||
| 478 | u8 config; | ||
| 479 | |||
| 480 | data = devm_kzalloc(&client->dev, sizeof(struct adm1025_data), | ||
| 481 | GFP_KERNEL); | ||
| 482 | if (!data) | ||
| 483 | return -ENOMEM; | ||
| 484 | |||
| 485 | i2c_set_clientdata(client, data); | ||
| 486 | mutex_init(&data->update_lock); | ||
| 487 | |||
| 488 | /* Initialize the ADM1025 chip */ | ||
| 489 | adm1025_init_client(client); | ||
| 490 | |||
| 491 | /* Register sysfs hooks */ | ||
| 492 | err = sysfs_create_group(&client->dev.kobj, &adm1025_group); | ||
| 493 | if (err) | ||
| 494 | return err; | ||
| 495 | |||
| 496 | /* Pin 11 is either in4 (+12V) or VID4 */ | ||
| 497 | config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); | ||
| 498 | if (!(config & 0x20)) { | ||
| 499 | err = sysfs_create_group(&client->dev.kobj, &adm1025_group_in4); | ||
| 500 | if (err) | ||
| 501 | goto exit_remove; | ||
| 502 | } | ||
| 503 | |||
| 504 | data->hwmon_dev = hwmon_device_register(&client->dev); | ||
| 505 | if (IS_ERR(data->hwmon_dev)) { | ||
| 506 | err = PTR_ERR(data->hwmon_dev); | ||
| 507 | goto exit_remove; | ||
| 508 | } | ||
| 509 | |||
| 510 | return 0; | ||
| 511 | |||
| 512 | exit_remove: | ||
| 513 | sysfs_remove_group(&client->dev.kobj, &adm1025_group); | ||
| 514 | sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); | ||
| 515 | return err; | ||
| 516 | } | ||
| 517 | |||
| 518 | static void adm1025_init_client(struct i2c_client *client) | 487 | static void adm1025_init_client(struct i2c_client *client) |
| 519 | { | 488 | { |
| 520 | u8 reg; | 489 | u8 reg; |
| @@ -557,61 +526,54 @@ static void adm1025_init_client(struct i2c_client *client) | |||
| 557 | (reg&0x7E)|0x01); | 526 | (reg&0x7E)|0x01); |
| 558 | } | 527 | } |
| 559 | 528 | ||
| 560 | static int adm1025_remove(struct i2c_client *client) | 529 | static int adm1025_probe(struct i2c_client *client, |
| 530 | const struct i2c_device_id *id) | ||
| 561 | { | 531 | { |
| 562 | struct adm1025_data *data = i2c_get_clientdata(client); | 532 | struct device *dev = &client->dev; |
| 563 | 533 | struct device *hwmon_dev; | |
| 564 | hwmon_device_unregister(data->hwmon_dev); | 534 | struct adm1025_data *data; |
| 565 | sysfs_remove_group(&client->dev.kobj, &adm1025_group); | 535 | u8 config; |
| 566 | sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); | ||
| 567 | |||
| 568 | return 0; | ||
| 569 | } | ||
| 570 | 536 | ||
| 571 | static struct adm1025_data *adm1025_update_device(struct device *dev) | 537 | data = devm_kzalloc(dev, sizeof(struct adm1025_data), GFP_KERNEL); |
| 572 | { | 538 | if (!data) |
| 573 | struct i2c_client *client = to_i2c_client(dev); | 539 | return -ENOMEM; |
| 574 | struct adm1025_data *data = i2c_get_clientdata(client); | ||
| 575 | 540 | ||
| 576 | mutex_lock(&data->update_lock); | 541 | i2c_set_clientdata(client, data); |
| 542 | data->client = client; | ||
| 543 | mutex_init(&data->update_lock); | ||
| 577 | 544 | ||
| 578 | if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { | 545 | /* Initialize the ADM1025 chip */ |
| 579 | int i; | 546 | adm1025_init_client(client); |
| 580 | 547 | ||
| 581 | dev_dbg(&client->dev, "Updating data.\n"); | 548 | /* sysfs hooks */ |
| 582 | for (i = 0; i < 6; i++) { | 549 | data->groups[0] = &adm1025_group; |
| 583 | data->in[i] = i2c_smbus_read_byte_data(client, | 550 | /* Pin 11 is either in4 (+12V) or VID4 */ |
| 584 | ADM1025_REG_IN(i)); | 551 | config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); |
| 585 | data->in_min[i] = i2c_smbus_read_byte_data(client, | 552 | if (!(config & 0x20)) |
| 586 | ADM1025_REG_IN_MIN(i)); | 553 | data->groups[1] = &adm1025_group_in4; |
| 587 | data->in_max[i] = i2c_smbus_read_byte_data(client, | ||
| 588 | ADM1025_REG_IN_MAX(i)); | ||
| 589 | } | ||
| 590 | for (i = 0; i < 2; i++) { | ||
| 591 | data->temp[i] = i2c_smbus_read_byte_data(client, | ||
| 592 | ADM1025_REG_TEMP(i)); | ||
| 593 | data->temp_min[i] = i2c_smbus_read_byte_data(client, | ||
| 594 | ADM1025_REG_TEMP_LOW(i)); | ||
| 595 | data->temp_max[i] = i2c_smbus_read_byte_data(client, | ||
| 596 | ADM1025_REG_TEMP_HIGH(i)); | ||
| 597 | } | ||
| 598 | data->alarms = i2c_smbus_read_byte_data(client, | ||
| 599 | ADM1025_REG_STATUS1) | ||
| 600 | | (i2c_smbus_read_byte_data(client, | ||
| 601 | ADM1025_REG_STATUS2) << 8); | ||
| 602 | data->vid = (i2c_smbus_read_byte_data(client, | ||
| 603 | ADM1025_REG_VID) & 0x0f) | ||
| 604 | | ((i2c_smbus_read_byte_data(client, | ||
| 605 | ADM1025_REG_VID4) & 0x01) << 4); | ||
| 606 | 554 | ||
| 607 | data->last_updated = jiffies; | 555 | hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, |
| 608 | data->valid = 1; | 556 | data, data->groups); |
| 609 | } | 557 | return PTR_ERR_OR_ZERO(hwmon_dev); |
| 558 | } | ||
| 610 | 559 | ||
| 611 | mutex_unlock(&data->update_lock); | 560 | static const struct i2c_device_id adm1025_id[] = { |
| 561 | { "adm1025", adm1025 }, | ||
| 562 | { "ne1619", ne1619 }, | ||
| 563 | { } | ||
| 564 | }; | ||
| 565 | MODULE_DEVICE_TABLE(i2c, adm1025_id); | ||
| 612 | 566 | ||
| 613 | return data; | 567 | static struct i2c_driver adm1025_driver = { |
| 614 | } | 568 | .class = I2C_CLASS_HWMON, |
| 569 | .driver = { | ||
| 570 | .name = "adm1025", | ||
| 571 | }, | ||
| 572 | .probe = adm1025_probe, | ||
| 573 | .id_table = adm1025_id, | ||
| 574 | .detect = adm1025_detect, | ||
| 575 | .address_list = normal_i2c, | ||
| 576 | }; | ||
| 615 | 577 | ||
| 616 | module_i2c_driver(adm1025_driver); | 578 | module_i2c_driver(adm1025_driver); |
| 617 | 579 | ||
