diff options
Diffstat (limited to 'drivers/hwmon/pc87360.c')
-rw-r--r-- | drivers/hwmon/pc87360.c | 232 |
1 files changed, 137 insertions, 95 deletions
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c index c8a21be09d87..cb72526c346a 100644 --- a/drivers/hwmon/pc87360.c +++ b/drivers/hwmon/pc87360.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * pc87360.c - Part of lm_sensors, Linux kernel modules | 2 | * pc87360.c - Part of lm_sensors, Linux kernel modules |
3 | * for hardware monitoring | 3 | * for hardware monitoring |
4 | * Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2004, 2007 Jean Delvare <khali@linux-fr.org> |
5 | * | 5 | * |
6 | * Copied from smsc47m1.c: | 6 | * Copied from smsc47m1.c: |
7 | * Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> | 7 | * Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com> |
@@ -37,8 +37,7 @@ | |||
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <linux/jiffies.h> | 39 | #include <linux/jiffies.h> |
40 | #include <linux/i2c.h> | 40 | #include <linux/platform_device.h> |
41 | #include <linux/i2c-isa.h> | ||
42 | #include <linux/hwmon.h> | 41 | #include <linux/hwmon.h> |
43 | #include <linux/hwmon-sysfs.h> | 42 | #include <linux/hwmon-sysfs.h> |
44 | #include <linux/hwmon-vid.h> | 43 | #include <linux/hwmon-vid.h> |
@@ -47,12 +46,10 @@ | |||
47 | #include <asm/io.h> | 46 | #include <asm/io.h> |
48 | 47 | ||
49 | static u8 devid; | 48 | static u8 devid; |
50 | static unsigned short address; | 49 | static struct platform_device *pdev; |
51 | static unsigned short extra_isa[3]; | 50 | static unsigned short extra_isa[3]; |
52 | static u8 confreg[4]; | 51 | static u8 confreg[4]; |
53 | 52 | ||
54 | enum chips { any_chip, pc87360, pc87363, pc87364, pc87365, pc87366 }; | ||
55 | |||
56 | static int init = 1; | 53 | static int init = 1; |
57 | module_param(init, int, 0); | 54 | module_param(init, int, 0); |
58 | MODULE_PARM_DESC(init, | 55 | MODULE_PARM_DESC(init, |
@@ -178,11 +175,11 @@ static inline u8 PWM_TO_REG(int val, int inv) | |||
178 | ((val) + 500) / 1000) | 175 | ((val) + 500) / 1000) |
179 | 176 | ||
180 | /* | 177 | /* |
181 | * Client data (each client gets its own) | 178 | * Device data |
182 | */ | 179 | */ |
183 | 180 | ||
184 | struct pc87360_data { | 181 | struct pc87360_data { |
185 | struct i2c_client client; | 182 | const char *name; |
186 | struct class_device *class_dev; | 183 | struct class_device *class_dev; |
187 | struct mutex lock; | 184 | struct mutex lock; |
188 | struct mutex update_lock; | 185 | struct mutex update_lock; |
@@ -222,27 +219,28 @@ struct pc87360_data { | |||
222 | * Functions declaration | 219 | * Functions declaration |
223 | */ | 220 | */ |
224 | 221 | ||
225 | static int pc87360_detect(struct i2c_adapter *adapter); | 222 | static int pc87360_probe(struct platform_device *pdev); |
226 | static int pc87360_detach_client(struct i2c_client *client); | 223 | static int pc87360_remove(struct platform_device *pdev); |
227 | 224 | ||
228 | static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, | 225 | static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, |
229 | u8 reg); | 226 | u8 reg); |
230 | static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, | 227 | static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, |
231 | u8 reg, u8 value); | 228 | u8 reg, u8 value); |
232 | static void pc87360_init_client(struct i2c_client *client, int use_thermistors); | 229 | static void pc87360_init_device(struct platform_device *pdev, |
230 | int use_thermistors); | ||
233 | static struct pc87360_data *pc87360_update_device(struct device *dev); | 231 | static struct pc87360_data *pc87360_update_device(struct device *dev); |
234 | 232 | ||
235 | /* | 233 | /* |
236 | * Driver data (common to all clients) | 234 | * Driver data |
237 | */ | 235 | */ |
238 | 236 | ||
239 | static struct i2c_driver pc87360_driver = { | 237 | static struct platform_driver pc87360_driver = { |
240 | .driver = { | 238 | .driver = { |
241 | .owner = THIS_MODULE, | 239 | .owner = THIS_MODULE, |
242 | .name = "pc87360", | 240 | .name = "pc87360", |
243 | }, | 241 | }, |
244 | .attach_adapter = pc87360_detect, | 242 | .probe = pc87360_probe, |
245 | .detach_client = pc87360_detach_client, | 243 | .remove = __devexit_p(pc87360_remove), |
246 | }; | 244 | }; |
247 | 245 | ||
248 | /* | 246 | /* |
@@ -281,8 +279,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr, | |||
281 | size_t count) | 279 | size_t count) |
282 | { | 280 | { |
283 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 281 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
284 | struct i2c_client *client = to_i2c_client(dev); | 282 | struct pc87360_data *data = dev_get_drvdata(dev); |
285 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
286 | long fan_min = simple_strtol(buf, NULL, 10); | 283 | long fan_min = simple_strtol(buf, NULL, 10); |
287 | 284 | ||
288 | mutex_lock(&data->update_lock); | 285 | mutex_lock(&data->update_lock); |
@@ -347,8 +344,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, con | |||
347 | size_t count) | 344 | size_t count) |
348 | { | 345 | { |
349 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 346 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
350 | struct i2c_client *client = to_i2c_client(dev); | 347 | struct pc87360_data *data = dev_get_drvdata(dev); |
351 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
352 | long val = simple_strtol(buf, NULL, 10); | 348 | long val = simple_strtol(buf, NULL, 10); |
353 | 349 | ||
354 | mutex_lock(&data->update_lock); | 350 | mutex_lock(&data->update_lock); |
@@ -410,8 +406,7 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, | |||
410 | size_t count) | 406 | size_t count) |
411 | { | 407 | { |
412 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 408 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
413 | struct i2c_client *client = to_i2c_client(dev); | 409 | struct pc87360_data *data = dev_get_drvdata(dev); |
414 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
415 | long val = simple_strtol(buf, NULL, 10); | 410 | long val = simple_strtol(buf, NULL, 10); |
416 | 411 | ||
417 | mutex_lock(&data->update_lock); | 412 | mutex_lock(&data->update_lock); |
@@ -425,8 +420,7 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, | |||
425 | size_t count) | 420 | size_t count) |
426 | { | 421 | { |
427 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 422 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
428 | struct i2c_client *client = to_i2c_client(dev); | 423 | struct pc87360_data *data = dev_get_drvdata(dev); |
429 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
430 | long val = simple_strtol(buf, NULL, 10); | 424 | long val = simple_strtol(buf, NULL, 10); |
431 | 425 | ||
432 | mutex_lock(&data->update_lock); | 426 | mutex_lock(&data->update_lock); |
@@ -511,8 +505,7 @@ static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char | |||
511 | } | 505 | } |
512 | static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 506 | static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
513 | { | 507 | { |
514 | struct i2c_client *client = to_i2c_client(dev); | 508 | struct pc87360_data *data = dev_get_drvdata(dev); |
515 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
516 | data->vrm = simple_strtoul(buf, NULL, 10); | 509 | data->vrm = simple_strtoul(buf, NULL, 10); |
517 | return count; | 510 | return count; |
518 | } | 511 | } |
@@ -584,8 +577,7 @@ static ssize_t set_therm_min(struct device *dev, struct device_attribute *devatt | |||
584 | size_t count) | 577 | size_t count) |
585 | { | 578 | { |
586 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 579 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
587 | struct i2c_client *client = to_i2c_client(dev); | 580 | struct pc87360_data *data = dev_get_drvdata(dev); |
588 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
589 | long val = simple_strtol(buf, NULL, 10); | 581 | long val = simple_strtol(buf, NULL, 10); |
590 | 582 | ||
591 | mutex_lock(&data->update_lock); | 583 | mutex_lock(&data->update_lock); |
@@ -599,8 +591,7 @@ static ssize_t set_therm_max(struct device *dev, struct device_attribute *devatt | |||
599 | size_t count) | 591 | size_t count) |
600 | { | 592 | { |
601 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 593 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
602 | struct i2c_client *client = to_i2c_client(dev); | 594 | struct pc87360_data *data = dev_get_drvdata(dev); |
603 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
604 | long val = simple_strtol(buf, NULL, 10); | 595 | long val = simple_strtol(buf, NULL, 10); |
605 | 596 | ||
606 | mutex_lock(&data->update_lock); | 597 | mutex_lock(&data->update_lock); |
@@ -614,8 +605,7 @@ static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devat | |||
614 | size_t count) | 605 | size_t count) |
615 | { | 606 | { |
616 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 607 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
617 | struct i2c_client *client = to_i2c_client(dev); | 608 | struct pc87360_data *data = dev_get_drvdata(dev); |
618 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
619 | long val = simple_strtol(buf, NULL, 10); | 609 | long val = simple_strtol(buf, NULL, 10); |
620 | 610 | ||
621 | mutex_lock(&data->update_lock); | 611 | mutex_lock(&data->update_lock); |
@@ -715,8 +705,7 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr | |||
715 | size_t count) | 705 | size_t count) |
716 | { | 706 | { |
717 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 707 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
718 | struct i2c_client *client = to_i2c_client(dev); | 708 | struct pc87360_data *data = dev_get_drvdata(dev); |
719 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
720 | long val = simple_strtol(buf, NULL, 10); | 709 | long val = simple_strtol(buf, NULL, 10); |
721 | 710 | ||
722 | mutex_lock(&data->update_lock); | 711 | mutex_lock(&data->update_lock); |
@@ -730,8 +719,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr | |||
730 | size_t count) | 719 | size_t count) |
731 | { | 720 | { |
732 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 721 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
733 | struct i2c_client *client = to_i2c_client(dev); | 722 | struct pc87360_data *data = dev_get_drvdata(dev); |
734 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
735 | long val = simple_strtol(buf, NULL, 10); | 723 | long val = simple_strtol(buf, NULL, 10); |
736 | 724 | ||
737 | mutex_lock(&data->update_lock); | 725 | mutex_lock(&data->update_lock); |
@@ -745,8 +733,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devatt | |||
745 | size_t count) | 733 | size_t count) |
746 | { | 734 | { |
747 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | 735 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); |
748 | struct i2c_client *client = to_i2c_client(dev); | 736 | struct pc87360_data *data = dev_get_drvdata(dev); |
749 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
750 | long val = simple_strtol(buf, NULL, 10); | 737 | long val = simple_strtol(buf, NULL, 10); |
751 | 738 | ||
752 | mutex_lock(&data->update_lock); | 739 | mutex_lock(&data->update_lock); |
@@ -818,6 +805,14 @@ static const struct attribute_group pc8736x_temp_group = { | |||
818 | .attrs = pc8736x_temp_attr_array, | 805 | .attrs = pc8736x_temp_attr_array, |
819 | }; | 806 | }; |
820 | 807 | ||
808 | static ssize_t show_name(struct device *dev, struct device_attribute | ||
809 | *devattr, char *buf) | ||
810 | { | ||
811 | struct pc87360_data *data = dev_get_drvdata(dev); | ||
812 | return sprintf(buf, "%s\n", data->name); | ||
813 | } | ||
814 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
815 | |||
821 | /* | 816 | /* |
822 | * Device detection, registration and update | 817 | * Device detection, registration and update |
823 | */ | 818 | */ |
@@ -912,28 +907,18 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses | |||
912 | return 0; | 907 | return 0; |
913 | } | 908 | } |
914 | 909 | ||
915 | static int pc87360_detect(struct i2c_adapter *adapter) | 910 | static int __devinit pc87360_probe(struct platform_device *pdev) |
916 | { | 911 | { |
917 | int i; | 912 | int i; |
918 | struct i2c_client *client; | ||
919 | struct pc87360_data *data; | 913 | struct pc87360_data *data; |
920 | int err = 0; | 914 | int err = 0; |
921 | const char *name = "pc87360"; | 915 | const char *name = "pc87360"; |
922 | int use_thermistors = 0; | 916 | int use_thermistors = 0; |
923 | struct device *dev; | 917 | struct device *dev = &pdev->dev; |
924 | 918 | ||
925 | if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL))) | 919 | if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL))) |
926 | return -ENOMEM; | 920 | return -ENOMEM; |
927 | 921 | ||
928 | client = &data->client; | ||
929 | dev = &client->dev; | ||
930 | i2c_set_clientdata(client, data); | ||
931 | client->addr = address; | ||
932 | mutex_init(&data->lock); | ||
933 | client->adapter = adapter; | ||
934 | client->driver = &pc87360_driver; | ||
935 | client->flags = 0; | ||
936 | |||
937 | data->fannr = 2; | 922 | data->fannr = 2; |
938 | data->innr = 0; | 923 | data->innr = 0; |
939 | data->tempnr = 0; | 924 | data->tempnr = 0; |
@@ -960,15 +945,17 @@ static int pc87360_detect(struct i2c_adapter *adapter) | |||
960 | break; | 945 | break; |
961 | } | 946 | } |
962 | 947 | ||
963 | strlcpy(client->name, name, sizeof(client->name)); | 948 | data->name = name; |
964 | data->valid = 0; | 949 | data->valid = 0; |
950 | mutex_init(&data->lock); | ||
965 | mutex_init(&data->update_lock); | 951 | mutex_init(&data->update_lock); |
952 | platform_set_drvdata(pdev, data); | ||
966 | 953 | ||
967 | for (i = 0; i < 3; i++) { | 954 | for (i = 0; i < 3; i++) { |
968 | if (((data->address[i] = extra_isa[i])) | 955 | if (((data->address[i] = extra_isa[i])) |
969 | && !request_region(extra_isa[i], PC87360_EXTENT, | 956 | && !request_region(extra_isa[i], PC87360_EXTENT, |
970 | pc87360_driver.driver.name)) { | 957 | pc87360_driver.driver.name)) { |
971 | dev_err(&client->dev, "Region 0x%x-0x%x already " | 958 | dev_err(dev, "Region 0x%x-0x%x already " |
972 | "in use!\n", extra_isa[i], | 959 | "in use!\n", extra_isa[i], |
973 | extra_isa[i]+PC87360_EXTENT-1); | 960 | extra_isa[i]+PC87360_EXTENT-1); |
974 | for (i--; i >= 0; i--) | 961 | for (i--; i >= 0; i--) |
@@ -982,9 +969,6 @@ static int pc87360_detect(struct i2c_adapter *adapter) | |||
982 | if (data->fannr) | 969 | if (data->fannr) |
983 | data->fan_conf = confreg[0] | (confreg[1] << 8); | 970 | data->fan_conf = confreg[0] | (confreg[1] << 8); |
984 | 971 | ||
985 | if ((err = i2c_attach_client(client))) | ||
986 | goto ERROR2; | ||
987 | |||
988 | /* Use the correct reference voltage | 972 | /* Use the correct reference voltage |
989 | Unless both the VLM and the TMS logical devices agree to | 973 | Unless both the VLM and the TMS logical devices agree to |
990 | use an external Vref, the internal one is used. */ | 974 | use an external Vref, the internal one is used. */ |
@@ -996,7 +980,7 @@ static int pc87360_detect(struct i2c_adapter *adapter) | |||
996 | PC87365_REG_TEMP_CONFIG); | 980 | PC87365_REG_TEMP_CONFIG); |
997 | } | 981 | } |
998 | data->in_vref = (i&0x02) ? 3025 : 2966; | 982 | data->in_vref = (i&0x02) ? 3025 : 2966; |
999 | dev_dbg(&client->dev, "Using %s reference voltage\n", | 983 | dev_dbg(dev, "Using %s reference voltage\n", |
1000 | (i&0x02) ? "external" : "internal"); | 984 | (i&0x02) ? "external" : "internal"); |
1001 | 985 | ||
1002 | data->vid_conf = confreg[3]; | 986 | data->vid_conf = confreg[3]; |
@@ -1015,18 +999,18 @@ static int pc87360_detect(struct i2c_adapter *adapter) | |||
1015 | if (devid == 0xe9 && data->address[1]) /* PC87366 */ | 999 | if (devid == 0xe9 && data->address[1]) /* PC87366 */ |
1016 | use_thermistors = confreg[2] & 0x40; | 1000 | use_thermistors = confreg[2] & 0x40; |
1017 | 1001 | ||
1018 | pc87360_init_client(client, use_thermistors); | 1002 | pc87360_init_device(pdev, use_thermistors); |
1019 | } | 1003 | } |
1020 | 1004 | ||
1021 | /* Register all-or-nothing sysfs groups */ | 1005 | /* Register all-or-nothing sysfs groups */ |
1022 | 1006 | ||
1023 | if (data->innr && | 1007 | if (data->innr && |
1024 | (err = sysfs_create_group(&client->dev.kobj, | 1008 | (err = sysfs_create_group(&dev->kobj, |
1025 | &pc8736x_vin_group))) | 1009 | &pc8736x_vin_group))) |
1026 | goto ERROR3; | 1010 | goto ERROR3; |
1027 | 1011 | ||
1028 | if (data->innr == 14 && | 1012 | if (data->innr == 14 && |
1029 | (err = sysfs_create_group(&client->dev.kobj, | 1013 | (err = sysfs_create_group(&dev->kobj, |
1030 | &pc8736x_therm_group))) | 1014 | &pc8736x_therm_group))) |
1031 | goto ERROR3; | 1015 | goto ERROR3; |
1032 | 1016 | ||
@@ -1067,7 +1051,10 @@ static int pc87360_detect(struct i2c_adapter *adapter) | |||
1067 | goto ERROR3; | 1051 | goto ERROR3; |
1068 | } | 1052 | } |
1069 | 1053 | ||
1070 | data->class_dev = hwmon_device_register(&client->dev); | 1054 | if ((err = device_create_file(dev, &dev_attr_name))) |
1055 | goto ERROR3; | ||
1056 | |||
1057 | data->class_dev = hwmon_device_register(dev); | ||
1071 | if (IS_ERR(data->class_dev)) { | 1058 | if (IS_ERR(data->class_dev)) { |
1072 | err = PTR_ERR(data->class_dev); | 1059 | err = PTR_ERR(data->class_dev); |
1073 | goto ERROR3; | 1060 | goto ERROR3; |
@@ -1075,14 +1062,12 @@ static int pc87360_detect(struct i2c_adapter *adapter) | |||
1075 | return 0; | 1062 | return 0; |
1076 | 1063 | ||
1077 | ERROR3: | 1064 | ERROR3: |
1065 | device_remove_file(dev, &dev_attr_name); | ||
1078 | /* can still remove groups whose members were added individually */ | 1066 | /* can still remove groups whose members were added individually */ |
1079 | sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group); | 1067 | sysfs_remove_group(&dev->kobj, &pc8736x_temp_group); |
1080 | sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group); | 1068 | sysfs_remove_group(&dev->kobj, &pc8736x_fan_group); |
1081 | sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group); | 1069 | sysfs_remove_group(&dev->kobj, &pc8736x_therm_group); |
1082 | sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group); | 1070 | sysfs_remove_group(&dev->kobj, &pc8736x_vin_group); |
1083 | |||
1084 | i2c_detach_client(client); | ||
1085 | ERROR2: | ||
1086 | for (i = 0; i < 3; i++) { | 1071 | for (i = 0; i < 3; i++) { |
1087 | if (data->address[i]) { | 1072 | if (data->address[i]) { |
1088 | release_region(data->address[i], PC87360_EXTENT); | 1073 | release_region(data->address[i], PC87360_EXTENT); |
@@ -1093,20 +1078,18 @@ ERROR1: | |||
1093 | return err; | 1078 | return err; |
1094 | } | 1079 | } |
1095 | 1080 | ||
1096 | static int pc87360_detach_client(struct i2c_client *client) | 1081 | static int __devexit pc87360_remove(struct platform_device *pdev) |
1097 | { | 1082 | { |
1098 | struct pc87360_data *data = i2c_get_clientdata(client); | 1083 | struct pc87360_data *data = platform_get_drvdata(pdev); |
1099 | int i; | 1084 | int i; |
1100 | 1085 | ||
1101 | hwmon_device_unregister(data->class_dev); | 1086 | hwmon_device_unregister(data->class_dev); |
1102 | 1087 | ||
1103 | sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group); | 1088 | device_remove_file(&pdev->dev, &dev_attr_name); |
1104 | sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group); | 1089 | sysfs_remove_group(&pdev->dev.kobj, &pc8736x_temp_group); |
1105 | sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group); | 1090 | sysfs_remove_group(&pdev->dev.kobj, &pc8736x_fan_group); |
1106 | sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group); | 1091 | sysfs_remove_group(&pdev->dev.kobj, &pc8736x_therm_group); |
1107 | 1092 | sysfs_remove_group(&pdev->dev.kobj, &pc8736x_vin_group); | |
1108 | if ((i = i2c_detach_client(client))) | ||
1109 | return i; | ||
1110 | 1093 | ||
1111 | for (i = 0; i < 3; i++) { | 1094 | for (i = 0; i < 3; i++) { |
1112 | if (data->address[i]) { | 1095 | if (data->address[i]) { |
@@ -1144,9 +1127,10 @@ static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, | |||
1144 | mutex_unlock(&(data->lock)); | 1127 | mutex_unlock(&(data->lock)); |
1145 | } | 1128 | } |
1146 | 1129 | ||
1147 | static void pc87360_init_client(struct i2c_client *client, int use_thermistors) | 1130 | static void pc87360_init_device(struct platform_device *pdev, |
1131 | int use_thermistors) | ||
1148 | { | 1132 | { |
1149 | struct pc87360_data *data = i2c_get_clientdata(client); | 1133 | struct pc87360_data *data = platform_get_drvdata(pdev); |
1150 | int i, nr; | 1134 | int i, nr; |
1151 | const u8 init_in[14] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 1, 2, 2, 2 }; | 1135 | const u8 init_in[14] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 1, 2, 2, 2 }; |
1152 | const u8 init_temp[3] = { 2, 2, 1 }; | 1136 | const u8 init_temp[3] = { 2, 2, 1 }; |
@@ -1155,7 +1139,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) | |||
1155 | if (init >= 2 && data->innr) { | 1139 | if (init >= 2 && data->innr) { |
1156 | reg = pc87360_read_value(data, LD_IN, NO_BANK, | 1140 | reg = pc87360_read_value(data, LD_IN, NO_BANK, |
1157 | PC87365_REG_IN_CONVRATE); | 1141 | PC87365_REG_IN_CONVRATE); |
1158 | dev_info(&client->dev, "VLM conversion set to " | 1142 | dev_info(&pdev->dev, "VLM conversion set to " |
1159 | "1s period, 160us delay\n"); | 1143 | "1s period, 160us delay\n"); |
1160 | pc87360_write_value(data, LD_IN, NO_BANK, | 1144 | pc87360_write_value(data, LD_IN, NO_BANK, |
1161 | PC87365_REG_IN_CONVRATE, | 1145 | PC87365_REG_IN_CONVRATE, |
@@ -1169,7 +1153,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) | |||
1169 | reg = pc87360_read_value(data, LD_IN, i, | 1153 | reg = pc87360_read_value(data, LD_IN, i, |
1170 | PC87365_REG_IN_STATUS); | 1154 | PC87365_REG_IN_STATUS); |
1171 | if (!(reg & 0x01)) { | 1155 | if (!(reg & 0x01)) { |
1172 | dev_dbg(&client->dev, "Forcibly " | 1156 | dev_dbg(&pdev->dev, "Forcibly " |
1173 | "enabling in%d\n", i); | 1157 | "enabling in%d\n", i); |
1174 | pc87360_write_value(data, LD_IN, i, | 1158 | pc87360_write_value(data, LD_IN, i, |
1175 | PC87365_REG_IN_STATUS, | 1159 | PC87365_REG_IN_STATUS, |
@@ -1193,7 +1177,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) | |||
1193 | reg = pc87360_read_value(data, LD_TEMP, i, | 1177 | reg = pc87360_read_value(data, LD_TEMP, i, |
1194 | PC87365_REG_TEMP_STATUS); | 1178 | PC87365_REG_TEMP_STATUS); |
1195 | if (!(reg & 0x01)) { | 1179 | if (!(reg & 0x01)) { |
1196 | dev_dbg(&client->dev, "Forcibly " | 1180 | dev_dbg(&pdev->dev, "Forcibly " |
1197 | "enabling temp%d\n", i+1); | 1181 | "enabling temp%d\n", i+1); |
1198 | pc87360_write_value(data, LD_TEMP, i, | 1182 | pc87360_write_value(data, LD_TEMP, i, |
1199 | PC87365_REG_TEMP_STATUS, | 1183 | PC87365_REG_TEMP_STATUS, |
@@ -1210,7 +1194,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) | |||
1210 | reg = pc87360_read_value(data, LD_TEMP, | 1194 | reg = pc87360_read_value(data, LD_TEMP, |
1211 | (i-11)/2, PC87365_REG_TEMP_STATUS); | 1195 | (i-11)/2, PC87365_REG_TEMP_STATUS); |
1212 | if (reg & 0x01) { | 1196 | if (reg & 0x01) { |
1213 | dev_dbg(&client->dev, "Skipping " | 1197 | dev_dbg(&pdev->dev, "Skipping " |
1214 | "temp%d, pin already in use " | 1198 | "temp%d, pin already in use " |
1215 | "by temp%d\n", i-7, (i-11)/2); | 1199 | "by temp%d\n", i-7, (i-11)/2); |
1216 | continue; | 1200 | continue; |
@@ -1220,7 +1204,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) | |||
1220 | reg = pc87360_read_value(data, LD_IN, i, | 1204 | reg = pc87360_read_value(data, LD_IN, i, |
1221 | PC87365_REG_IN_STATUS); | 1205 | PC87365_REG_IN_STATUS); |
1222 | if (!(reg & 0x01)) { | 1206 | if (!(reg & 0x01)) { |
1223 | dev_dbg(&client->dev, "Forcibly " | 1207 | dev_dbg(&pdev->dev, "Forcibly " |
1224 | "enabling temp%d\n", i-7); | 1208 | "enabling temp%d\n", i-7); |
1225 | pc87360_write_value(data, LD_IN, i, | 1209 | pc87360_write_value(data, LD_IN, i, |
1226 | PC87365_REG_TEMP_STATUS, | 1210 | PC87365_REG_TEMP_STATUS, |
@@ -1234,7 +1218,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) | |||
1234 | reg = pc87360_read_value(data, LD_IN, NO_BANK, | 1218 | reg = pc87360_read_value(data, LD_IN, NO_BANK, |
1235 | PC87365_REG_IN_CONFIG); | 1219 | PC87365_REG_IN_CONFIG); |
1236 | if (reg & 0x01) { | 1220 | if (reg & 0x01) { |
1237 | dev_dbg(&client->dev, "Forcibly " | 1221 | dev_dbg(&pdev->dev, "Forcibly " |
1238 | "enabling monitoring (VLM)\n"); | 1222 | "enabling monitoring (VLM)\n"); |
1239 | pc87360_write_value(data, LD_IN, NO_BANK, | 1223 | pc87360_write_value(data, LD_IN, NO_BANK, |
1240 | PC87365_REG_IN_CONFIG, | 1224 | PC87365_REG_IN_CONFIG, |
@@ -1246,7 +1230,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) | |||
1246 | reg = pc87360_read_value(data, LD_TEMP, NO_BANK, | 1230 | reg = pc87360_read_value(data, LD_TEMP, NO_BANK, |
1247 | PC87365_REG_TEMP_CONFIG); | 1231 | PC87365_REG_TEMP_CONFIG); |
1248 | if (reg & 0x01) { | 1232 | if (reg & 0x01) { |
1249 | dev_dbg(&client->dev, "Forcibly enabling " | 1233 | dev_dbg(&pdev->dev, "Forcibly enabling " |
1250 | "monitoring (TMS)\n"); | 1234 | "monitoring (TMS)\n"); |
1251 | pc87360_write_value(data, LD_TEMP, NO_BANK, | 1235 | pc87360_write_value(data, LD_TEMP, NO_BANK, |
1252 | PC87365_REG_TEMP_CONFIG, | 1236 | PC87365_REG_TEMP_CONFIG, |
@@ -1268,9 +1252,9 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors) | |||
1268 | } | 1252 | } |
1269 | } | 1253 | } |
1270 | 1254 | ||
1271 | static void pc87360_autodiv(struct i2c_client *client, int nr) | 1255 | static void pc87360_autodiv(struct device *dev, int nr) |
1272 | { | 1256 | { |
1273 | struct pc87360_data *data = i2c_get_clientdata(client); | 1257 | struct pc87360_data *data = dev_get_drvdata(dev); |
1274 | u8 old_min = data->fan_min[nr]; | 1258 | u8 old_min = data->fan_min[nr]; |
1275 | 1259 | ||
1276 | /* Increase clock divider if needed and possible */ | 1260 | /* Increase clock divider if needed and possible */ |
@@ -1280,7 +1264,7 @@ static void pc87360_autodiv(struct i2c_client *client, int nr) | |||
1280 | data->fan_status[nr] += 0x20; | 1264 | data->fan_status[nr] += 0x20; |
1281 | data->fan_min[nr] >>= 1; | 1265 | data->fan_min[nr] >>= 1; |
1282 | data->fan[nr] >>= 1; | 1266 | data->fan[nr] >>= 1; |
1283 | dev_dbg(&client->dev, "Increasing " | 1267 | dev_dbg(dev, "Increasing " |
1284 | "clock divider to %d for fan %d\n", | 1268 | "clock divider to %d for fan %d\n", |
1285 | FAN_DIV_FROM_REG(data->fan_status[nr]), nr+1); | 1269 | FAN_DIV_FROM_REG(data->fan_status[nr]), nr+1); |
1286 | } | 1270 | } |
@@ -1292,7 +1276,7 @@ static void pc87360_autodiv(struct i2c_client *client, int nr) | |||
1292 | data->fan_status[nr] -= 0x20; | 1276 | data->fan_status[nr] -= 0x20; |
1293 | data->fan_min[nr] <<= 1; | 1277 | data->fan_min[nr] <<= 1; |
1294 | data->fan[nr] <<= 1; | 1278 | data->fan[nr] <<= 1; |
1295 | dev_dbg(&client->dev, "Decreasing " | 1279 | dev_dbg(dev, "Decreasing " |
1296 | "clock divider to %d for fan %d\n", | 1280 | "clock divider to %d for fan %d\n", |
1297 | FAN_DIV_FROM_REG(data->fan_status[nr]), | 1281 | FAN_DIV_FROM_REG(data->fan_status[nr]), |
1298 | nr+1); | 1282 | nr+1); |
@@ -1309,14 +1293,13 @@ static void pc87360_autodiv(struct i2c_client *client, int nr) | |||
1309 | 1293 | ||
1310 | static struct pc87360_data *pc87360_update_device(struct device *dev) | 1294 | static struct pc87360_data *pc87360_update_device(struct device *dev) |
1311 | { | 1295 | { |
1312 | struct i2c_client *client = to_i2c_client(dev); | 1296 | struct pc87360_data *data = dev_get_drvdata(dev); |
1313 | struct pc87360_data *data = i2c_get_clientdata(client); | ||
1314 | u8 i; | 1297 | u8 i; |
1315 | 1298 | ||
1316 | mutex_lock(&data->update_lock); | 1299 | mutex_lock(&data->update_lock); |
1317 | 1300 | ||
1318 | if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { | 1301 | if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { |
1319 | dev_dbg(&client->dev, "Data update\n"); | 1302 | dev_dbg(dev, "Data update\n"); |
1320 | 1303 | ||
1321 | /* Fans */ | 1304 | /* Fans */ |
1322 | for (i = 0; i < data->fannr; i++) { | 1305 | for (i = 0; i < data->fannr; i++) { |
@@ -1330,7 +1313,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) | |||
1330 | LD_FAN, NO_BANK, | 1313 | LD_FAN, NO_BANK, |
1331 | PC87360_REG_FAN_MIN(i)); | 1314 | PC87360_REG_FAN_MIN(i)); |
1332 | /* Change clock divider if needed */ | 1315 | /* Change clock divider if needed */ |
1333 | pc87360_autodiv(client, i); | 1316 | pc87360_autodiv(dev, i); |
1334 | /* Clear bits and write new divider */ | 1317 | /* Clear bits and write new divider */ |
1335 | pc87360_write_value(data, LD_FAN, NO_BANK, | 1318 | pc87360_write_value(data, LD_FAN, NO_BANK, |
1336 | PC87360_REG_FAN_STATUS(i), | 1319 | PC87360_REG_FAN_STATUS(i), |
@@ -1418,9 +1401,53 @@ static struct pc87360_data *pc87360_update_device(struct device *dev) | |||
1418 | return data; | 1401 | return data; |
1419 | } | 1402 | } |
1420 | 1403 | ||
1404 | static int __init pc87360_device_add(unsigned short address) | ||
1405 | { | ||
1406 | struct resource res = { | ||
1407 | .name = "pc87360", | ||
1408 | .flags = IORESOURCE_IO, | ||
1409 | }; | ||
1410 | int err, i; | ||
1411 | |||
1412 | pdev = platform_device_alloc("pc87360", address); | ||
1413 | if (!pdev) { | ||
1414 | err = -ENOMEM; | ||
1415 | printk(KERN_ERR "pc87360: Device allocation failed\n"); | ||
1416 | goto exit; | ||
1417 | } | ||
1418 | |||
1419 | for (i = 0; i < 3; i++) { | ||
1420 | if (!extra_isa[i]) | ||
1421 | continue; | ||
1422 | res.start = extra_isa[i]; | ||
1423 | res.end = extra_isa[i] + PC87360_EXTENT - 1; | ||
1424 | err = platform_device_add_resources(pdev, &res, 1); | ||
1425 | if (err) { | ||
1426 | printk(KERN_ERR "pc87360: Device resource[%d] " | ||
1427 | "addition failed (%d)\n", i, err); | ||
1428 | goto exit_device_put; | ||
1429 | } | ||
1430 | } | ||
1431 | |||
1432 | err = platform_device_add(pdev); | ||
1433 | if (err) { | ||
1434 | printk(KERN_ERR "pc87360: Device addition failed (%d)\n", | ||
1435 | err); | ||
1436 | goto exit_device_put; | ||
1437 | } | ||
1438 | |||
1439 | return 0; | ||
1440 | |||
1441 | exit_device_put: | ||
1442 | platform_device_put(pdev); | ||
1443 | exit: | ||
1444 | return err; | ||
1445 | } | ||
1446 | |||
1421 | static int __init pc87360_init(void) | 1447 | static int __init pc87360_init(void) |
1422 | { | 1448 | { |
1423 | int i; | 1449 | int err, i; |
1450 | unsigned short address = 0; | ||
1424 | 1451 | ||
1425 | if (pc87360_find(0x2e, &devid, extra_isa) | 1452 | if (pc87360_find(0x2e, &devid, extra_isa) |
1426 | && pc87360_find(0x4e, &devid, extra_isa)) { | 1453 | && pc87360_find(0x4e, &devid, extra_isa)) { |
@@ -1443,12 +1470,27 @@ static int __init pc87360_init(void) | |||
1443 | return -ENODEV; | 1470 | return -ENODEV; |
1444 | } | 1471 | } |
1445 | 1472 | ||
1446 | return i2c_isa_add_driver(&pc87360_driver); | 1473 | err = platform_driver_register(&pc87360_driver); |
1474 | if (err) | ||
1475 | goto exit; | ||
1476 | |||
1477 | /* Sets global pdev as a side effect */ | ||
1478 | err = pc87360_device_add(address); | ||
1479 | if (err) | ||
1480 | goto exit_driver; | ||
1481 | |||
1482 | return 0; | ||
1483 | |||
1484 | exit_driver: | ||
1485 | platform_driver_unregister(&pc87360_driver); | ||
1486 | exit: | ||
1487 | return err; | ||
1447 | } | 1488 | } |
1448 | 1489 | ||
1449 | static void __exit pc87360_exit(void) | 1490 | static void __exit pc87360_exit(void) |
1450 | { | 1491 | { |
1451 | i2c_isa_del_driver(&pc87360_driver); | 1492 | platform_device_unregister(pdev); |
1493 | platform_driver_unregister(&pc87360_driver); | ||
1452 | } | 1494 | } |
1453 | 1495 | ||
1454 | 1496 | ||