diff options
author | Jean Delvare <khali@linux-fr.org> | 2008-07-16 13:30:12 -0400 |
---|---|---|
committer | Jean Delvare <khali@mahadeva.delvare> | 2008-07-16 13:30:12 -0400 |
commit | 40ac1994bf988dac05434f856c2a4fa24e22b2ea (patch) | |
tree | 88acc783bdb40d53df0cce86a67197391574e809 | |
parent | c2df1591df3ea83b4a5890a1131dd821ca07e761 (diff) |
hwmon: (fschmd) Convert to a new-style i2c driver
The new-style fschmd driver implements the optional detect() callback
to cover the use cases of the legacy driver.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Hans de Goede <j.w.r.degoede@hhs.nl>
-rw-r--r-- | drivers/hwmon/fschmd.c | 112 |
1 files changed, 57 insertions, 55 deletions
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c index bd89d270a5ed..967170368933 100644 --- a/drivers/hwmon/fschmd.c +++ b/drivers/hwmon/fschmd.c | |||
@@ -171,20 +171,37 @@ static const int FSCHMD_NO_TEMP_SENSORS[5] = { 3, 3, 4, 3, 5 }; | |||
171 | * Functions declarations | 171 | * Functions declarations |
172 | */ | 172 | */ |
173 | 173 | ||
174 | static int fschmd_attach_adapter(struct i2c_adapter *adapter); | 174 | static int fschmd_probe(struct i2c_client *client, |
175 | static int fschmd_detach_client(struct i2c_client *client); | 175 | const struct i2c_device_id *id); |
176 | static int fschmd_detect(struct i2c_client *client, int kind, | ||
177 | struct i2c_board_info *info); | ||
178 | static int fschmd_remove(struct i2c_client *client); | ||
176 | static struct fschmd_data *fschmd_update_device(struct device *dev); | 179 | static struct fschmd_data *fschmd_update_device(struct device *dev); |
177 | 180 | ||
178 | /* | 181 | /* |
179 | * Driver data (common to all clients) | 182 | * Driver data (common to all clients) |
180 | */ | 183 | */ |
181 | 184 | ||
185 | static const struct i2c_device_id fschmd_id[] = { | ||
186 | { "fscpos", fscpos }, | ||
187 | { "fscher", fscher }, | ||
188 | { "fscscy", fscscy }, | ||
189 | { "fschrc", fschrc }, | ||
190 | { "fschmd", fschmd }, | ||
191 | { } | ||
192 | }; | ||
193 | MODULE_DEVICE_TABLE(i2c, fschmd_id); | ||
194 | |||
182 | static struct i2c_driver fschmd_driver = { | 195 | static struct i2c_driver fschmd_driver = { |
196 | .class = I2C_CLASS_HWMON, | ||
183 | .driver = { | 197 | .driver = { |
184 | .name = FSCHMD_NAME, | 198 | .name = FSCHMD_NAME, |
185 | }, | 199 | }, |
186 | .attach_adapter = fschmd_attach_adapter, | 200 | .probe = fschmd_probe, |
187 | .detach_client = fschmd_detach_client, | 201 | .remove = fschmd_remove, |
202 | .id_table = fschmd_id, | ||
203 | .detect = fschmd_detect, | ||
204 | .address_data = &addr_data, | ||
188 | }; | 205 | }; |
189 | 206 | ||
190 | /* | 207 | /* |
@@ -192,7 +209,6 @@ static struct i2c_driver fschmd_driver = { | |||
192 | */ | 209 | */ |
193 | 210 | ||
194 | struct fschmd_data { | 211 | struct fschmd_data { |
195 | struct i2c_client client; | ||
196 | struct device *hwmon_dev; | 212 | struct device *hwmon_dev; |
197 | struct mutex update_lock; | 213 | struct mutex update_lock; |
198 | int kind; | 214 | int kind; |
@@ -269,7 +285,7 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute | |||
269 | v = SENSORS_LIMIT(v, -128, 127) + 128; | 285 | v = SENSORS_LIMIT(v, -128, 127) + 128; |
270 | 286 | ||
271 | mutex_lock(&data->update_lock); | 287 | mutex_lock(&data->update_lock); |
272 | i2c_smbus_write_byte_data(&data->client, | 288 | i2c_smbus_write_byte_data(to_i2c_client(dev), |
273 | FSCHMD_REG_TEMP_LIMIT[data->kind][index], v); | 289 | FSCHMD_REG_TEMP_LIMIT[data->kind][index], v); |
274 | data->temp_max[index] = v; | 290 | data->temp_max[index] = v; |
275 | mutex_unlock(&data->update_lock); | 291 | mutex_unlock(&data->update_lock); |
@@ -346,14 +362,14 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute | |||
346 | 362 | ||
347 | mutex_lock(&data->update_lock); | 363 | mutex_lock(&data->update_lock); |
348 | 364 | ||
349 | reg = i2c_smbus_read_byte_data(&data->client, | 365 | reg = i2c_smbus_read_byte_data(to_i2c_client(dev), |
350 | FSCHMD_REG_FAN_RIPPLE[data->kind][index]); | 366 | FSCHMD_REG_FAN_RIPPLE[data->kind][index]); |
351 | 367 | ||
352 | /* bits 2..7 reserved => mask with 0x03 */ | 368 | /* bits 2..7 reserved => mask with 0x03 */ |
353 | reg &= ~0x03; | 369 | reg &= ~0x03; |
354 | reg |= v; | 370 | reg |= v; |
355 | 371 | ||
356 | i2c_smbus_write_byte_data(&data->client, | 372 | i2c_smbus_write_byte_data(to_i2c_client(dev), |
357 | FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg); | 373 | FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg); |
358 | 374 | ||
359 | data->fan_ripple[index] = reg; | 375 | data->fan_ripple[index] = reg; |
@@ -416,7 +432,7 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev, | |||
416 | 432 | ||
417 | mutex_lock(&data->update_lock); | 433 | mutex_lock(&data->update_lock); |
418 | 434 | ||
419 | i2c_smbus_write_byte_data(&data->client, | 435 | i2c_smbus_write_byte_data(to_i2c_client(dev), |
420 | FSCHMD_REG_FAN_MIN[data->kind][index], v); | 436 | FSCHMD_REG_FAN_MIN[data->kind][index], v); |
421 | data->fan_min[index] = v; | 437 | data->fan_min[index] = v; |
422 | 438 | ||
@@ -448,14 +464,14 @@ static ssize_t store_alert_led(struct device *dev, | |||
448 | 464 | ||
449 | mutex_lock(&data->update_lock); | 465 | mutex_lock(&data->update_lock); |
450 | 466 | ||
451 | reg = i2c_smbus_read_byte_data(&data->client, FSCHMD_REG_CONTROL); | 467 | reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL); |
452 | 468 | ||
453 | if (v) | 469 | if (v) |
454 | reg |= FSCHMD_CONTROL_ALERT_LED_MASK; | 470 | reg |= FSCHMD_CONTROL_ALERT_LED_MASK; |
455 | else | 471 | else |
456 | reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK; | 472 | reg &= ~FSCHMD_CONTROL_ALERT_LED_MASK; |
457 | 473 | ||
458 | i2c_smbus_write_byte_data(&data->client, FSCHMD_REG_CONTROL, reg); | 474 | i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg); |
459 | 475 | ||
460 | data->global_control = reg; | 476 | data->global_control = reg; |
461 | 477 | ||
@@ -600,32 +616,15 @@ static void fschmd_dmi_decode(const struct dmi_header *header) | |||
600 | } | 616 | } |
601 | } | 617 | } |
602 | 618 | ||
603 | static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) | 619 | static int fschmd_detect(struct i2c_client *client, int kind, |
620 | struct i2c_board_info *info) | ||
604 | { | 621 | { |
605 | struct i2c_client *client; | 622 | struct i2c_adapter *adapter = client->adapter; |
606 | struct fschmd_data *data; | ||
607 | u8 revision; | ||
608 | const char * const names[5] = { "Poseidon", "Hermes", "Scylla", | ||
609 | "Heracles", "Heimdall" }; | ||
610 | const char * const client_names[5] = { "fscpos", "fscher", "fscscy", | 623 | const char * const client_names[5] = { "fscpos", "fscher", "fscscy", |
611 | "fschrc", "fschmd" }; | 624 | "fschrc", "fschmd" }; |
612 | int i, err = 0; | ||
613 | 625 | ||
614 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) | 626 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
615 | return 0; | 627 | return -ENODEV; |
616 | |||
617 | /* OK. For now, we presume we have a valid client. We now create the | ||
618 | * client structure, even though we cannot fill it completely yet. | ||
619 | * But it allows us to access i2c_smbus_read_byte_data. */ | ||
620 | if (!(data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL))) | ||
621 | return -ENOMEM; | ||
622 | |||
623 | client = &data->client; | ||
624 | i2c_set_clientdata(client, data); | ||
625 | client->addr = address; | ||
626 | client->adapter = adapter; | ||
627 | client->driver = &fschmd_driver; | ||
628 | mutex_init(&data->update_lock); | ||
629 | 628 | ||
630 | /* Detect & Identify the chip */ | 629 | /* Detect & Identify the chip */ |
631 | if (kind <= 0) { | 630 | if (kind <= 0) { |
@@ -650,9 +649,31 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) | |||
650 | else if (!strcmp(id, "HMD")) | 649 | else if (!strcmp(id, "HMD")) |
651 | kind = fschmd; | 650 | kind = fschmd; |
652 | else | 651 | else |
653 | goto exit_free; | 652 | return -ENODEV; |
654 | } | 653 | } |
655 | 654 | ||
655 | strlcpy(info->type, client_names[kind - 1], I2C_NAME_SIZE); | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | static int fschmd_probe(struct i2c_client *client, | ||
661 | const struct i2c_device_id *id) | ||
662 | { | ||
663 | struct fschmd_data *data; | ||
664 | u8 revision; | ||
665 | const char * const names[5] = { "Poseidon", "Hermes", "Scylla", | ||
666 | "Heracles", "Heimdall" }; | ||
667 | int i, err; | ||
668 | enum chips kind = id->driver_data; | ||
669 | |||
670 | data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL); | ||
671 | if (!data) | ||
672 | return -ENOMEM; | ||
673 | |||
674 | i2c_set_clientdata(client, data); | ||
675 | mutex_init(&data->update_lock); | ||
676 | |||
656 | if (kind == fscpos) { | 677 | if (kind == fscpos) { |
657 | /* The Poseidon has hardwired temp limits, fill these | 678 | /* The Poseidon has hardwired temp limits, fill these |
658 | in for the alarm resetting code */ | 679 | in for the alarm resetting code */ |
@@ -674,11 +695,6 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) | |||
674 | 695 | ||
675 | /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ | 696 | /* i2c kind goes from 1-5, we want from 0-4 to address arrays */ |
676 | data->kind = kind - 1; | 697 | data->kind = kind - 1; |
677 | strlcpy(client->name, client_names[data->kind], I2C_NAME_SIZE); | ||
678 | |||
679 | /* Tell the I2C layer a new client has arrived */ | ||
680 | if ((err = i2c_attach_client(client))) | ||
681 | goto exit_free; | ||
682 | 698 | ||
683 | for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) { | 699 | for (i = 0; i < ARRAY_SIZE(fschmd_attr); i++) { |
684 | err = device_create_file(&client->dev, | 700 | err = device_create_file(&client->dev, |
@@ -726,25 +742,14 @@ static int fschmd_detect(struct i2c_adapter *adapter, int address, int kind) | |||
726 | return 0; | 742 | return 0; |
727 | 743 | ||
728 | exit_detach: | 744 | exit_detach: |
729 | fschmd_detach_client(client); /* will also free data for us */ | 745 | fschmd_remove(client); /* will also free data for us */ |
730 | return err; | ||
731 | |||
732 | exit_free: | ||
733 | kfree(data); | ||
734 | return err; | 746 | return err; |
735 | } | 747 | } |
736 | 748 | ||
737 | static int fschmd_attach_adapter(struct i2c_adapter *adapter) | 749 | static int fschmd_remove(struct i2c_client *client) |
738 | { | ||
739 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
740 | return 0; | ||
741 | return i2c_probe(adapter, &addr_data, fschmd_detect); | ||
742 | } | ||
743 | |||
744 | static int fschmd_detach_client(struct i2c_client *client) | ||
745 | { | 750 | { |
746 | struct fschmd_data *data = i2c_get_clientdata(client); | 751 | struct fschmd_data *data = i2c_get_clientdata(client); |
747 | int i, err; | 752 | int i; |
748 | 753 | ||
749 | /* Check if registered in case we're called from fschmd_detect | 754 | /* Check if registered in case we're called from fschmd_detect |
750 | to cleanup after an error */ | 755 | to cleanup after an error */ |
@@ -760,9 +765,6 @@ static int fschmd_detach_client(struct i2c_client *client) | |||
760 | device_remove_file(&client->dev, | 765 | device_remove_file(&client->dev, |
761 | &fschmd_fan_attr[i].dev_attr); | 766 | &fschmd_fan_attr[i].dev_attr); |
762 | 767 | ||
763 | if ((err = i2c_detach_client(client))) | ||
764 | return err; | ||
765 | |||
766 | kfree(data); | 768 | kfree(data); |
767 | return 0; | 769 | return 0; |
768 | } | 770 | } |