diff options
author | Jean Delvare <khali@linux-fr.org> | 2007-05-08 11:22:02 -0400 |
---|---|---|
committer | Jean Delvare <khali@hyperion.delvare> | 2007-05-08 11:22:02 -0400 |
commit | 7666c13c627fdc65e8057013893c183c3bafe59e (patch) | |
tree | ee3b90f711a751b52763613b98c10ab5c1292834 /drivers/hwmon/w83781d.c | |
parent | 47a5dba1dca723d890d0b9409c82e72311a1f641 (diff) |
hwmon/w83781d: No longer use i2c-isa
Reimplement the ISA device support as a platform driver, so that we no
longer rely on i2c-isa.
Signed-off-by: Jean Delvare <khali@linux-fr.org>
Diffstat (limited to 'drivers/hwmon/w83781d.c')
-rw-r--r-- | drivers/hwmon/w83781d.c | 571 |
1 files changed, 377 insertions, 194 deletions
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index a47da3ec5472..96338ddd74a7 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c | |||
@@ -2,8 +2,9 @@ | |||
2 | w83781d.c - Part of lm_sensors, Linux kernel modules for hardware | 2 | w83781d.c - Part of lm_sensors, Linux kernel modules for hardware |
3 | monitoring | 3 | monitoring |
4 | Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, | 4 | Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>, |
5 | Philip Edelbrock <phil@netroedge.com>, | 5 | Philip Edelbrock <phil@netroedge.com>, |
6 | and Mark Studebaker <mdsxyz123@yahoo.com> | 6 | and Mark Studebaker <mdsxyz123@yahoo.com> |
7 | Copyright (c) 2007 Jean Delvare <khali@linux-fr.org> | ||
7 | 8 | ||
8 | This program is free software; you can redistribute it and/or modify | 9 | This program is free software; you can redistribute it and/or modify |
9 | it under the terms of the GNU General Public License as published by | 10 | it under the terms of the GNU General Public License as published by |
@@ -38,7 +39,8 @@ | |||
38 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
39 | #include <linux/jiffies.h> | 40 | #include <linux/jiffies.h> |
40 | #include <linux/i2c.h> | 41 | #include <linux/i2c.h> |
41 | #include <linux/i2c-isa.h> | 42 | #include <linux/platform_device.h> |
43 | #include <linux/ioport.h> | ||
42 | #include <linux/hwmon.h> | 44 | #include <linux/hwmon.h> |
43 | #include <linux/hwmon-vid.h> | 45 | #include <linux/hwmon-vid.h> |
44 | #include <linux/sysfs.h> | 46 | #include <linux/sysfs.h> |
@@ -47,6 +49,9 @@ | |||
47 | #include <asm/io.h> | 49 | #include <asm/io.h> |
48 | #include "lm75.h" | 50 | #include "lm75.h" |
49 | 51 | ||
52 | /* ISA device, if found */ | ||
53 | static struct platform_device *pdev; | ||
54 | |||
50 | /* Addresses to scan */ | 55 | /* Addresses to scan */ |
51 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, | 56 | static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, |
52 | 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, | 57 | 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, |
@@ -221,8 +226,8 @@ DIV_TO_REG(long val, enum chips type) | |||
221 | a bit - except if there could be more than one SMBus. Groan. No solution | 226 | a bit - except if there could be more than one SMBus. Groan. No solution |
222 | for this yet. */ | 227 | for this yet. */ |
223 | 228 | ||
224 | /* For each registered chip, we need to keep some data in memory. | 229 | /* For ISA chips, we abuse the i2c_client addr and name fields. We also use |
225 | The structure is dynamically allocated. */ | 230 | the driver field to differentiate between I2C and ISA chips. */ |
226 | struct w83781d_data { | 231 | struct w83781d_data { |
227 | struct i2c_client client; | 232 | struct i2c_client client; |
228 | struct class_device *class_dev; | 233 | struct class_device *class_dev; |
@@ -263,14 +268,16 @@ struct w83781d_data { | |||
263 | }; | 268 | }; |
264 | 269 | ||
265 | static int w83781d_attach_adapter(struct i2c_adapter *adapter); | 270 | static int w83781d_attach_adapter(struct i2c_adapter *adapter); |
266 | static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter); | ||
267 | static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); | 271 | static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind); |
268 | static int w83781d_detach_client(struct i2c_client *client); | 272 | static int w83781d_detach_client(struct i2c_client *client); |
269 | 273 | ||
274 | static int __devinit w83781d_isa_probe(struct platform_device *pdev); | ||
275 | static int __devexit w83781d_isa_remove(struct platform_device *pdev); | ||
276 | |||
270 | static int w83781d_read_value(struct i2c_client *client, u16 reg); | 277 | static int w83781d_read_value(struct i2c_client *client, u16 reg); |
271 | static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value); | 278 | static int w83781d_write_value(struct i2c_client *client, u16 reg, u16 value); |
272 | static struct w83781d_data *w83781d_update_device(struct device *dev); | 279 | static struct w83781d_data *w83781d_update_device(struct device *dev); |
273 | static void w83781d_init_client(struct i2c_client *client); | 280 | static void w83781d_init_device(struct device *dev); |
274 | 281 | ||
275 | static struct i2c_driver w83781d_driver = { | 282 | static struct i2c_driver w83781d_driver = { |
276 | .driver = { | 283 | .driver = { |
@@ -281,13 +288,13 @@ static struct i2c_driver w83781d_driver = { | |||
281 | .detach_client = w83781d_detach_client, | 288 | .detach_client = w83781d_detach_client, |
282 | }; | 289 | }; |
283 | 290 | ||
284 | static struct i2c_driver w83781d_isa_driver = { | 291 | static struct platform_driver w83781d_isa_driver = { |
285 | .driver = { | 292 | .driver = { |
286 | .owner = THIS_MODULE, | 293 | .owner = THIS_MODULE, |
287 | .name = "w83781d-isa", | 294 | .name = "w83781d", |
288 | }, | 295 | }, |
289 | .attach_adapter = w83781d_isa_attach_adapter, | 296 | .probe = w83781d_isa_probe, |
290 | .detach_client = w83781d_detach_client, | 297 | .remove = w83781d_isa_remove, |
291 | }; | 298 | }; |
292 | 299 | ||
293 | 300 | ||
@@ -305,8 +312,8 @@ show_in_reg(in_max); | |||
305 | #define store_in_reg(REG, reg) \ | 312 | #define store_in_reg(REG, reg) \ |
306 | static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 313 | static ssize_t store_in_##reg (struct device *dev, const char *buf, size_t count, int nr) \ |
307 | { \ | 314 | { \ |
308 | struct i2c_client *client = to_i2c_client(dev); \ | 315 | struct w83781d_data *data = dev_get_drvdata(dev); \ |
309 | struct w83781d_data *data = i2c_get_clientdata(client); \ | 316 | struct i2c_client *client = &data->client; \ |
310 | u32 val; \ | 317 | u32 val; \ |
311 | \ | 318 | \ |
312 | val = simple_strtoul(buf, NULL, 10) / 10; \ | 319 | val = simple_strtoul(buf, NULL, 10) / 10; \ |
@@ -368,8 +375,8 @@ show_fan_reg(fan_min); | |||
368 | static ssize_t | 375 | static ssize_t |
369 | store_fan_min(struct device *dev, const char *buf, size_t count, int nr) | 376 | store_fan_min(struct device *dev, const char *buf, size_t count, int nr) |
370 | { | 377 | { |
371 | struct i2c_client *client = to_i2c_client(dev); | 378 | struct w83781d_data *data = dev_get_drvdata(dev); |
372 | struct w83781d_data *data = i2c_get_clientdata(client); | 379 | struct i2c_client *client = &data->client; |
373 | u32 val; | 380 | u32 val; |
374 | 381 | ||
375 | val = simple_strtoul(buf, NULL, 10); | 382 | val = simple_strtoul(buf, NULL, 10); |
@@ -427,8 +434,8 @@ show_temp_reg(temp_max_hyst); | |||
427 | #define store_temp_reg(REG, reg) \ | 434 | #define store_temp_reg(REG, reg) \ |
428 | static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ | 435 | static ssize_t store_temp_##reg (struct device *dev, const char *buf, size_t count, int nr) \ |
429 | { \ | 436 | { \ |
430 | struct i2c_client *client = to_i2c_client(dev); \ | 437 | struct w83781d_data *data = dev_get_drvdata(dev); \ |
431 | struct w83781d_data *data = i2c_get_clientdata(client); \ | 438 | struct i2c_client *client = &data->client; \ |
432 | s32 val; \ | 439 | s32 val; \ |
433 | \ | 440 | \ |
434 | val = simple_strtol(buf, NULL, 10); \ | 441 | val = simple_strtol(buf, NULL, 10); \ |
@@ -498,8 +505,7 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) | |||
498 | static ssize_t | 505 | static ssize_t |
499 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) | 506 | store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) |
500 | { | 507 | { |
501 | struct i2c_client *client = to_i2c_client(dev); | 508 | struct w83781d_data *data = dev_get_drvdata(dev); |
502 | struct w83781d_data *data = i2c_get_clientdata(client); | ||
503 | u32 val; | 509 | u32 val; |
504 | 510 | ||
505 | val = simple_strtoul(buf, NULL, 10); | 511 | val = simple_strtoul(buf, NULL, 10); |
@@ -539,8 +545,8 @@ static ssize_t | |||
539 | store_beep_reg(struct device *dev, const char *buf, size_t count, | 545 | store_beep_reg(struct device *dev, const char *buf, size_t count, |
540 | int update_mask) | 546 | int update_mask) |
541 | { | 547 | { |
542 | struct i2c_client *client = to_i2c_client(dev); | 548 | struct w83781d_data *data = dev_get_drvdata(dev); |
543 | struct w83781d_data *data = i2c_get_clientdata(client); | 549 | struct i2c_client *client = &data->client; |
544 | u32 val, val2; | 550 | u32 val, val2; |
545 | 551 | ||
546 | val = simple_strtoul(buf, NULL, 10); | 552 | val = simple_strtoul(buf, NULL, 10); |
@@ -599,8 +605,8 @@ show_fan_div_reg(struct device *dev, char *buf, int nr) | |||
599 | static ssize_t | 605 | static ssize_t |
600 | store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) | 606 | store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr) |
601 | { | 607 | { |
602 | struct i2c_client *client = to_i2c_client(dev); | 608 | struct w83781d_data *data = dev_get_drvdata(dev); |
603 | struct w83781d_data *data = i2c_get_clientdata(client); | 609 | struct i2c_client *client = &data->client; |
604 | unsigned long min; | 610 | unsigned long min; |
605 | u8 reg; | 611 | u8 reg; |
606 | unsigned long val = simple_strtoul(buf, NULL, 10); | 612 | unsigned long val = simple_strtoul(buf, NULL, 10); |
@@ -666,8 +672,8 @@ show_pwmenable_reg(struct device *dev, char *buf, int nr) | |||
666 | static ssize_t | 672 | static ssize_t |
667 | store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) | 673 | store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) |
668 | { | 674 | { |
669 | struct i2c_client *client = to_i2c_client(dev); | 675 | struct w83781d_data *data = dev_get_drvdata(dev); |
670 | struct w83781d_data *data = i2c_get_clientdata(client); | 676 | struct i2c_client *client = &data->client; |
671 | u32 val; | 677 | u32 val; |
672 | 678 | ||
673 | val = simple_strtoul(buf, NULL, 10); | 679 | val = simple_strtoul(buf, NULL, 10); |
@@ -682,8 +688,8 @@ store_pwm_reg(struct device *dev, const char *buf, size_t count, int nr) | |||
682 | static ssize_t | 688 | static ssize_t |
683 | store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) | 689 | store_pwmenable_reg(struct device *dev, const char *buf, size_t count, int nr) |
684 | { | 690 | { |
685 | struct i2c_client *client = to_i2c_client(dev); | 691 | struct w83781d_data *data = dev_get_drvdata(dev); |
686 | struct w83781d_data *data = i2c_get_clientdata(client); | 692 | struct i2c_client *client = &data->client; |
687 | u32 val, reg; | 693 | u32 val, reg; |
688 | 694 | ||
689 | val = simple_strtoul(buf, NULL, 10); | 695 | val = simple_strtoul(buf, NULL, 10); |
@@ -755,8 +761,8 @@ show_sensor_reg(struct device *dev, char *buf, int nr) | |||
755 | static ssize_t | 761 | static ssize_t |
756 | store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) | 762 | store_sensor_reg(struct device *dev, const char *buf, size_t count, int nr) |
757 | { | 763 | { |
758 | struct i2c_client *client = to_i2c_client(dev); | 764 | struct w83781d_data *data = dev_get_drvdata(dev); |
759 | struct w83781d_data *data = i2c_get_clientdata(client); | 765 | struct i2c_client *client = &data->client; |
760 | u32 val, tmp; | 766 | u32 val, tmp; |
761 | 767 | ||
762 | val = simple_strtoul(buf, NULL, 10); | 768 | val = simple_strtoul(buf, NULL, 10); |
@@ -813,6 +819,16 @@ sysfs_sensor(1); | |||
813 | sysfs_sensor(2); | 819 | sysfs_sensor(2); |
814 | sysfs_sensor(3); | 820 | sysfs_sensor(3); |
815 | 821 | ||
822 | /* I2C devices get this name attribute automatically, but for ISA devices | ||
823 | we must create it by ourselves. */ | ||
824 | static ssize_t | ||
825 | show_name(struct device *dev, struct device_attribute *devattr, char *buf) | ||
826 | { | ||
827 | struct w83781d_data *data = dev_get_drvdata(dev); | ||
828 | return sprintf(buf, "%s\n", data->client.name); | ||
829 | } | ||
830 | static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); | ||
831 | |||
816 | /* This function is called when: | 832 | /* This function is called when: |
817 | * w83781d_driver is inserted (when this module is loaded), for each | 833 | * w83781d_driver is inserted (when this module is loaded), for each |
818 | available adapter | 834 | available adapter |
@@ -825,12 +841,6 @@ w83781d_attach_adapter(struct i2c_adapter *adapter) | |||
825 | return i2c_probe(adapter, &addr_data, w83781d_detect); | 841 | return i2c_probe(adapter, &addr_data, w83781d_detect); |
826 | } | 842 | } |
827 | 843 | ||
828 | static int | ||
829 | w83781d_isa_attach_adapter(struct i2c_adapter *adapter) | ||
830 | { | ||
831 | return w83781d_detect(adapter, isa_address, -1); | ||
832 | } | ||
833 | |||
834 | /* Assumes that adapter is of I2C, not ISA variety. | 844 | /* Assumes that adapter is of I2C, not ISA variety. |
835 | * OTHERWISE DON'T CALL THIS | 845 | * OTHERWISE DON'T CALL THIS |
836 | */ | 846 | */ |
@@ -994,77 +1004,85 @@ static const struct attribute_group w83781d_group_opt = { | |||
994 | .attrs = w83781d_attributes_opt, | 1004 | .attrs = w83781d_attributes_opt, |
995 | }; | 1005 | }; |
996 | 1006 | ||
1007 | /* No clean up is done on error, it's up to the caller */ | ||
997 | static int | 1008 | static int |
998 | w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | 1009 | w83781d_create_files(struct device *dev, int kind, int is_isa) |
999 | { | 1010 | { |
1000 | int i = 0, val1 = 0, val2; | ||
1001 | struct i2c_client *client; | ||
1002 | struct device *dev; | ||
1003 | struct w83781d_data *data; | ||
1004 | int err; | 1011 | int err; |
1005 | const char *client_name = ""; | ||
1006 | int is_isa = i2c_is_isa_adapter(adapter); | ||
1007 | enum vendor { winbond, asus } vendid; | ||
1008 | 1012 | ||
1009 | if (!is_isa | 1013 | if ((err = sysfs_create_group(&dev->kobj, &w83781d_group))) |
1010 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 1014 | return err; |
1011 | err = -EINVAL; | 1015 | |
1012 | goto ERROR0; | 1016 | if (kind != w83783s) { |
1017 | if ((err = device_create_file(dev, &dev_attr_in1_input)) | ||
1018 | || (err = device_create_file(dev, &dev_attr_in1_min)) | ||
1019 | || (err = device_create_file(dev, &dev_attr_in1_max))) | ||
1020 | return err; | ||
1021 | } | ||
1022 | if (kind != as99127f && kind != w83781d && kind != w83783s) { | ||
1023 | if ((err = device_create_file(dev, &dev_attr_in7_input)) | ||
1024 | || (err = device_create_file(dev, &dev_attr_in7_min)) | ||
1025 | || (err = device_create_file(dev, &dev_attr_in7_max)) | ||
1026 | || (err = device_create_file(dev, &dev_attr_in8_input)) | ||
1027 | || (err = device_create_file(dev, &dev_attr_in8_min)) | ||
1028 | || (err = device_create_file(dev, &dev_attr_in8_max))) | ||
1029 | return err; | ||
1030 | } | ||
1031 | if (kind != w83783s) { | ||
1032 | if ((err = device_create_file(dev, &dev_attr_temp3_input)) | ||
1033 | || (err = device_create_file(dev, &dev_attr_temp3_max)) | ||
1034 | || (err = device_create_file(dev, | ||
1035 | &dev_attr_temp3_max_hyst))) | ||
1036 | return err; | ||
1013 | } | 1037 | } |
1014 | 1038 | ||
1015 | /* Prevent users from forcing a kind for a bus it isn't supposed | 1039 | if (kind != w83781d && kind != as99127f) { |
1016 | to possibly be on */ | 1040 | if ((err = device_create_file(dev, &dev_attr_pwm1)) |
1017 | if (is_isa && (kind == as99127f || kind == w83783s)) { | 1041 | || (err = device_create_file(dev, &dev_attr_pwm2)) |
1018 | dev_err(&adapter->dev, | 1042 | || (err = device_create_file(dev, &dev_attr_pwm2_enable))) |
1019 | "Cannot force I2C-only chip for ISA address 0x%02x.\n", | 1043 | return err; |
1020 | address); | ||
1021 | err = -EINVAL; | ||
1022 | goto ERROR0; | ||
1023 | } | 1044 | } |
1024 | 1045 | if (kind == w83782d && !is_isa) { | |
1025 | if (is_isa) | 1046 | if ((err = device_create_file(dev, &dev_attr_pwm3)) |
1026 | if (!request_region(address, W83781D_EXTENT, | 1047 | || (err = device_create_file(dev, &dev_attr_pwm4))) |
1027 | w83781d_isa_driver.driver.name)) { | 1048 | return err; |
1028 | dev_dbg(&adapter->dev, "Request of region " | 1049 | } |
1029 | "0x%x-0x%x for w83781d failed\n", address, | 1050 | |
1030 | address + W83781D_EXTENT - 1); | 1051 | if (kind != as99127f && kind != w83781d) { |
1031 | err = -EBUSY; | 1052 | if ((err = device_create_file(dev, &dev_attr_temp1_type)) |
1032 | goto ERROR0; | 1053 | || (err = device_create_file(dev, |
1054 | &dev_attr_temp2_type))) | ||
1055 | return err; | ||
1056 | if (kind != w83783s) { | ||
1057 | if ((err = device_create_file(dev, | ||
1058 | &dev_attr_temp3_type))) | ||
1059 | return err; | ||
1033 | } | 1060 | } |
1061 | } | ||
1034 | 1062 | ||
1035 | /* Probe whether there is anything available on this address. Already | 1063 | if (is_isa) { |
1036 | done for SMBus clients */ | 1064 | err = device_create_file(&pdev->dev, &dev_attr_name); |
1037 | if (kind < 0) { | 1065 | if (err) |
1038 | if (is_isa) { | 1066 | return err; |
1067 | } | ||
1039 | 1068 | ||
1040 | #define REALLY_SLOW_IO | 1069 | return 0; |
1041 | /* We need the timeouts for at least some LM78-like | 1070 | } |
1042 | chips. But only if we read 'undefined' registers. */ | ||
1043 | i = inb_p(address + 1); | ||
1044 | if (inb_p(address + 2) != i | ||
1045 | || inb_p(address + 3) != i | ||
1046 | || inb_p(address + 7) != i) { | ||
1047 | dev_dbg(&adapter->dev, "Detection of w83781d " | ||
1048 | "chip failed at step 1\n"); | ||
1049 | err = -ENODEV; | ||
1050 | goto ERROR1; | ||
1051 | } | ||
1052 | #undef REALLY_SLOW_IO | ||
1053 | 1071 | ||
1054 | /* Let's just hope nothing breaks here */ | 1072 | static int |
1055 | i = inb_p(address + 5) & 0x7f; | 1073 | w83781d_detect(struct i2c_adapter *adapter, int address, int kind) |
1056 | outb_p(~i & 0x7f, address + 5); | 1074 | { |
1057 | val2 = inb_p(address + 5) & 0x7f; | 1075 | int val1 = 0, val2; |
1058 | if (val2 != (~i & 0x7f)) { | 1076 | struct i2c_client *client; |
1059 | outb_p(i, address + 5); | 1077 | struct device *dev; |
1060 | dev_dbg(&adapter->dev, "Detection of w83781d " | 1078 | struct w83781d_data *data; |
1061 | "chip failed at step 2 (0x%x != " | 1079 | int err; |
1062 | "0x%x at 0x%x)\n", val2, ~i & 0x7f, | 1080 | const char *client_name = ""; |
1063 | address + 5); | 1081 | enum vendor { winbond, asus } vendid; |
1064 | err = -ENODEV; | 1082 | |
1065 | goto ERROR1; | 1083 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
1066 | } | 1084 | err = -EINVAL; |
1067 | } | 1085 | goto ERROR1; |
1068 | } | 1086 | } |
1069 | 1087 | ||
1070 | /* OK. For now, we presume we have a valid client. We now create the | 1088 | /* OK. For now, we presume we have a valid client. We now create the |
@@ -1081,8 +1099,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1081 | client->addr = address; | 1099 | client->addr = address; |
1082 | mutex_init(&data->lock); | 1100 | mutex_init(&data->lock); |
1083 | client->adapter = adapter; | 1101 | client->adapter = adapter; |
1084 | client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver; | 1102 | client->driver = &w83781d_driver; |
1085 | client->flags = 0; | ||
1086 | dev = &client->dev; | 1103 | dev = &client->dev; |
1087 | 1104 | ||
1088 | /* Now, we do the remaining detection. */ | 1105 | /* Now, we do the remaining detection. */ |
@@ -1111,8 +1128,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1111 | } | 1128 | } |
1112 | /* If Winbond SMBus, check address at 0x48. | 1129 | /* If Winbond SMBus, check address at 0x48. |
1113 | Asus doesn't support, except for as99127f rev.2 */ | 1130 | Asus doesn't support, except for as99127f rev.2 */ |
1114 | if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) || | 1131 | if ((!(val1 & 0x80) && (val2 == 0xa3)) || |
1115 | ((val1 & 0x80) && (val2 == 0x5c)))) { | 1132 | ((val1 & 0x80) && (val2 == 0x5c))) { |
1116 | if (w83781d_read_value | 1133 | if (w83781d_read_value |
1117 | (client, W83781D_REG_I2C_ADDR) != address) { | 1134 | (client, W83781D_REG_I2C_ADDR) != address) { |
1118 | dev_dbg(&adapter->dev, "Detection of w83781d " | 1135 | dev_dbg(&adapter->dev, "Detection of w83781d " |
@@ -1149,12 +1166,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1149 | kind = w83781d; | 1166 | kind = w83781d; |
1150 | else if (val1 == 0x30 && vendid == winbond) | 1167 | else if (val1 == 0x30 && vendid == winbond) |
1151 | kind = w83782d; | 1168 | kind = w83782d; |
1152 | else if (val1 == 0x40 && vendid == winbond && !is_isa | 1169 | else if (val1 == 0x40 && vendid == winbond && address == 0x2d) |
1153 | && address == 0x2d) | ||
1154 | kind = w83783s; | 1170 | kind = w83783s; |
1155 | else if (val1 == 0x21 && vendid == winbond) | 1171 | else if (val1 == 0x21 && vendid == winbond) |
1156 | kind = w83627hf; | 1172 | kind = w83627hf; |
1157 | else if (val1 == 0x31 && !is_isa && address >= 0x28) | 1173 | else if (val1 == 0x31 && address >= 0x28) |
1158 | kind = as99127f; | 1174 | kind = as99127f; |
1159 | else { | 1175 | else { |
1160 | if (kind == 0) | 1176 | if (kind == 0) |
@@ -1182,86 +1198,23 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) | |||
1182 | strlcpy(client->name, client_name, I2C_NAME_SIZE); | 1198 | strlcpy(client->name, client_name, I2C_NAME_SIZE); |
1183 | data->type = kind; | 1199 | data->type = kind; |
1184 | 1200 | ||
1185 | data->valid = 0; | ||
1186 | mutex_init(&data->update_lock); | ||
1187 | |||
1188 | /* Tell the I2C layer a new client has arrived */ | 1201 | /* Tell the I2C layer a new client has arrived */ |
1189 | if ((err = i2c_attach_client(client))) | 1202 | if ((err = i2c_attach_client(client))) |
1190 | goto ERROR2; | 1203 | goto ERROR2; |
1191 | 1204 | ||
1192 | /* attach secondary i2c lm75-like clients */ | 1205 | /* attach secondary i2c lm75-like clients */ |
1193 | if (!is_isa) { | 1206 | if ((err = w83781d_detect_subclients(adapter, address, |
1194 | if ((err = w83781d_detect_subclients(adapter, address, | 1207 | kind, client))) |
1195 | kind, client))) | 1208 | goto ERROR3; |
1196 | goto ERROR3; | ||
1197 | } else { | ||
1198 | data->lm75[0] = NULL; | ||
1199 | data->lm75[1] = NULL; | ||
1200 | } | ||
1201 | 1209 | ||
1202 | /* Initialize the chip */ | 1210 | /* Initialize the chip */ |
1203 | w83781d_init_client(client); | 1211 | w83781d_init_device(dev); |
1204 | |||
1205 | /* A few vars need to be filled upon startup */ | ||
1206 | for (i = 1; i <= 3; i++) { | ||
1207 | data->fan_min[i - 1] = w83781d_read_value(client, | ||
1208 | W83781D_REG_FAN_MIN(i)); | ||
1209 | } | ||
1210 | if (kind != w83781d && kind != as99127f) | ||
1211 | for (i = 0; i < 4; i++) | ||
1212 | data->pwmenable[i] = 1; | ||
1213 | 1212 | ||
1214 | /* Register sysfs hooks */ | 1213 | /* Register sysfs hooks */ |
1215 | if ((err = sysfs_create_group(&dev->kobj, &w83781d_group))) | 1214 | err = w83781d_create_files(dev, kind, 0); |
1215 | if (err) | ||
1216 | goto ERROR4; | 1216 | goto ERROR4; |
1217 | 1217 | ||
1218 | if (kind != w83783s) { | ||
1219 | if ((err = device_create_file(dev, &dev_attr_in1_input)) | ||
1220 | || (err = device_create_file(dev, &dev_attr_in1_min)) | ||
1221 | || (err = device_create_file(dev, &dev_attr_in1_max))) | ||
1222 | goto ERROR4; | ||
1223 | } | ||
1224 | if (kind != as99127f && kind != w83781d && kind != w83783s) { | ||
1225 | if ((err = device_create_file(dev, &dev_attr_in7_input)) | ||
1226 | || (err = device_create_file(dev, &dev_attr_in7_min)) | ||
1227 | || (err = device_create_file(dev, &dev_attr_in7_max)) | ||
1228 | || (err = device_create_file(dev, &dev_attr_in8_input)) | ||
1229 | || (err = device_create_file(dev, &dev_attr_in8_min)) | ||
1230 | || (err = device_create_file(dev, &dev_attr_in8_max))) | ||
1231 | goto ERROR4; | ||
1232 | } | ||
1233 | if (kind != w83783s) { | ||
1234 | if ((err = device_create_file(dev, &dev_attr_temp3_input)) | ||
1235 | || (err = device_create_file(dev, &dev_attr_temp3_max)) | ||
1236 | || (err = device_create_file(dev, | ||
1237 | &dev_attr_temp3_max_hyst))) | ||
1238 | goto ERROR4; | ||
1239 | } | ||
1240 | |||
1241 | if (kind != w83781d && kind != as99127f) { | ||
1242 | if ((err = device_create_file(dev, &dev_attr_pwm1)) | ||
1243 | || (err = device_create_file(dev, &dev_attr_pwm2)) | ||
1244 | || (err = device_create_file(dev, &dev_attr_pwm2_enable))) | ||
1245 | goto ERROR4; | ||
1246 | } | ||
1247 | if (kind == w83782d && !is_isa) { | ||
1248 | if ((err = device_create_file(dev, &dev_attr_pwm3)) | ||
1249 | || (err = device_create_file(dev, &dev_attr_pwm4))) | ||
1250 | goto ERROR4; | ||
1251 | } | ||
1252 | |||
1253 | if (kind != as99127f && kind != w83781d) { | ||
1254 | if ((err = device_create_file(dev, &dev_attr_temp1_type)) | ||
1255 | || (err = device_create_file(dev, | ||
1256 | &dev_attr_temp2_type))) | ||
1257 | goto ERROR4; | ||
1258 | if (kind != w83783s) { | ||
1259 | if ((err = device_create_file(dev, | ||
1260 | &dev_attr_temp3_type))) | ||
1261 | goto ERROR4; | ||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | data->class_dev = hwmon_device_register(dev); | 1218 | data->class_dev = hwmon_device_register(dev); |
1266 | if (IS_ERR(data->class_dev)) { | 1219 | if (IS_ERR(data->class_dev)) { |
1267 | err = PTR_ERR(data->class_dev); | 1220 | err = PTR_ERR(data->class_dev); |
@@ -1287,9 +1240,6 @@ ERROR3: | |||
1287 | ERROR2: | 1240 | ERROR2: |
1288 | kfree(data); | 1241 | kfree(data); |
1289 | ERROR1: | 1242 | ERROR1: |
1290 | if (is_isa) | ||
1291 | release_region(address, W83781D_EXTENT); | ||
1292 | ERROR0: | ||
1293 | return err; | 1243 | return err; |
1294 | } | 1244 | } |
1295 | 1245 | ||
@@ -1305,8 +1255,6 @@ w83781d_detach_client(struct i2c_client *client) | |||
1305 | sysfs_remove_group(&client->dev.kobj, &w83781d_group); | 1255 | sysfs_remove_group(&client->dev.kobj, &w83781d_group); |
1306 | sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt); | 1256 | sysfs_remove_group(&client->dev.kobj, &w83781d_group_opt); |
1307 | } | 1257 | } |
1308 | if (i2c_is_isa_client(client)) | ||
1309 | release_region(client->addr, W83781D_EXTENT); | ||
1310 | 1258 | ||
1311 | if ((err = i2c_detach_client(client))) | 1259 | if ((err = i2c_detach_client(client))) |
1312 | return err; | 1260 | return err; |
@@ -1322,6 +1270,88 @@ w83781d_detach_client(struct i2c_client *client) | |||
1322 | return 0; | 1270 | return 0; |
1323 | } | 1271 | } |
1324 | 1272 | ||
1273 | static int __devinit | ||
1274 | w83781d_isa_probe(struct platform_device *pdev) | ||
1275 | { | ||
1276 | int err, reg; | ||
1277 | struct w83781d_data *data; | ||
1278 | struct resource *res; | ||
1279 | const char *name; | ||
1280 | |||
1281 | /* Reserve the ISA region */ | ||
1282 | res = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
1283 | if (!request_region(res->start, W83781D_EXTENT, "w83781d")) { | ||
1284 | err = -EBUSY; | ||
1285 | goto exit; | ||
1286 | } | ||
1287 | |||
1288 | if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) { | ||
1289 | err = -ENOMEM; | ||
1290 | goto exit_release_region; | ||
1291 | } | ||
1292 | mutex_init(&data->lock); | ||
1293 | data->client.addr = res->start; | ||
1294 | i2c_set_clientdata(&data->client, data); | ||
1295 | platform_set_drvdata(pdev, data); | ||
1296 | |||
1297 | reg = w83781d_read_value(&data->client, W83781D_REG_WCHIPID); | ||
1298 | switch (reg) { | ||
1299 | case 0x21: | ||
1300 | data->type = w83627hf; | ||
1301 | name = "w83627hf"; | ||
1302 | break; | ||
1303 | case 0x30: | ||
1304 | data->type = w83782d; | ||
1305 | name = "w83782d"; | ||
1306 | break; | ||
1307 | default: | ||
1308 | data->type = w83781d; | ||
1309 | name = "w83781d"; | ||
1310 | } | ||
1311 | strlcpy(data->client.name, name, I2C_NAME_SIZE); | ||
1312 | |||
1313 | /* Initialize the W83781D chip */ | ||
1314 | w83781d_init_device(&pdev->dev); | ||
1315 | |||
1316 | /* Register sysfs hooks */ | ||
1317 | err = w83781d_create_files(&pdev->dev, data->type, 1); | ||
1318 | if (err) | ||
1319 | goto exit_remove_files; | ||
1320 | |||
1321 | data->class_dev = hwmon_device_register(&pdev->dev); | ||
1322 | if (IS_ERR(data->class_dev)) { | ||
1323 | err = PTR_ERR(data->class_dev); | ||
1324 | goto exit_remove_files; | ||
1325 | } | ||
1326 | |||
1327 | return 0; | ||
1328 | |||
1329 | exit_remove_files: | ||
1330 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
1331 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
1332 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
1333 | kfree(data); | ||
1334 | exit_release_region: | ||
1335 | release_region(res->start, W83781D_EXTENT); | ||
1336 | exit: | ||
1337 | return err; | ||
1338 | } | ||
1339 | |||
1340 | static int __devexit | ||
1341 | w83781d_isa_remove(struct platform_device *pdev) | ||
1342 | { | ||
1343 | struct w83781d_data *data = platform_get_drvdata(pdev); | ||
1344 | |||
1345 | hwmon_device_unregister(data->class_dev); | ||
1346 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group); | ||
1347 | sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt); | ||
1348 | device_remove_file(&pdev->dev, &dev_attr_name); | ||
1349 | release_region(data->client.addr, W83781D_EXTENT); | ||
1350 | kfree(data); | ||
1351 | |||
1352 | return 0; | ||
1353 | } | ||
1354 | |||
1325 | /* The SMBus locks itself, usually, but nothing may access the Winbond between | 1355 | /* The SMBus locks itself, usually, but nothing may access the Winbond between |
1326 | bank switches. ISA access must always be locked explicitly! | 1356 | bank switches. ISA access must always be locked explicitly! |
1327 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, | 1357 | We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, |
@@ -1336,7 +1366,7 @@ w83781d_read_value(struct i2c_client *client, u16 reg) | |||
1336 | struct i2c_client *cl; | 1366 | struct i2c_client *cl; |
1337 | 1367 | ||
1338 | mutex_lock(&data->lock); | 1368 | mutex_lock(&data->lock); |
1339 | if (i2c_is_isa_client(client)) { | 1369 | if (!client->driver) { /* ISA device */ |
1340 | word_sized = (((reg & 0xff00) == 0x100) | 1370 | word_sized = (((reg & 0xff00) == 0x100) |
1341 | || ((reg & 0xff00) == 0x200)) | 1371 | || ((reg & 0xff00) == 0x200)) |
1342 | && (((reg & 0x00ff) == 0x50) | 1372 | && (((reg & 0x00ff) == 0x50) |
@@ -1405,7 +1435,7 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) | |||
1405 | struct i2c_client *cl; | 1435 | struct i2c_client *cl; |
1406 | 1436 | ||
1407 | mutex_lock(&data->lock); | 1437 | mutex_lock(&data->lock); |
1408 | if (i2c_is_isa_client(client)) { | 1438 | if (!client->driver) { /* ISA device */ |
1409 | word_sized = (((reg & 0xff00) == 0x100) | 1439 | word_sized = (((reg & 0xff00) == 0x100) |
1410 | || ((reg & 0xff00) == 0x200)) | 1440 | || ((reg & 0xff00) == 0x200)) |
1411 | && (((reg & 0x00ff) == 0x53) | 1441 | && (((reg & 0x00ff) == 0x53) |
@@ -1462,9 +1492,10 @@ w83781d_write_value(struct i2c_client *client, u16 reg, u16 value) | |||
1462 | } | 1492 | } |
1463 | 1493 | ||
1464 | static void | 1494 | static void |
1465 | w83781d_init_client(struct i2c_client *client) | 1495 | w83781d_init_device(struct device *dev) |
1466 | { | 1496 | { |
1467 | struct w83781d_data *data = i2c_get_clientdata(client); | 1497 | struct w83781d_data *data = dev_get_drvdata(dev); |
1498 | struct i2c_client *client = &data->client; | ||
1468 | int i, p; | 1499 | int i, p; |
1469 | int type = data->type; | 1500 | int type = data->type; |
1470 | u8 tmp; | 1501 | u8 tmp; |
@@ -1477,7 +1508,7 @@ w83781d_init_client(struct i2c_client *client) | |||
1477 | It might even go away if nobody reports it as being useful, | 1508 | It might even go away if nobody reports it as being useful, |
1478 | as I see very little reason why this would be needed at | 1509 | as I see very little reason why this would be needed at |
1479 | all. */ | 1510 | all. */ |
1480 | dev_info(&client->dev, "If reset=1 solved a problem you were " | 1511 | dev_info(dev, "If reset=1 solved a problem you were " |
1481 | "having, please report!\n"); | 1512 | "having, please report!\n"); |
1482 | 1513 | ||
1483 | /* save these registers */ | 1514 | /* save these registers */ |
@@ -1527,7 +1558,7 @@ w83781d_init_client(struct i2c_client *client) | |||
1527 | /* Enable temp2 */ | 1558 | /* Enable temp2 */ |
1528 | tmp = w83781d_read_value(client, W83781D_REG_TEMP2_CONFIG); | 1559 | tmp = w83781d_read_value(client, W83781D_REG_TEMP2_CONFIG); |
1529 | if (tmp & 0x01) { | 1560 | if (tmp & 0x01) { |
1530 | dev_warn(&client->dev, "Enabling temp2, readings " | 1561 | dev_warn(dev, "Enabling temp2, readings " |
1531 | "might not make sense\n"); | 1562 | "might not make sense\n"); |
1532 | w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG, | 1563 | w83781d_write_value(client, W83781D_REG_TEMP2_CONFIG, |
1533 | tmp & 0xfe); | 1564 | tmp & 0xfe); |
@@ -1538,7 +1569,7 @@ w83781d_init_client(struct i2c_client *client) | |||
1538 | tmp = w83781d_read_value(client, | 1569 | tmp = w83781d_read_value(client, |
1539 | W83781D_REG_TEMP3_CONFIG); | 1570 | W83781D_REG_TEMP3_CONFIG); |
1540 | if (tmp & 0x01) { | 1571 | if (tmp & 0x01) { |
1541 | dev_warn(&client->dev, "Enabling temp3, " | 1572 | dev_warn(dev, "Enabling temp3, " |
1542 | "readings might not make sense\n"); | 1573 | "readings might not make sense\n"); |
1543 | w83781d_write_value(client, | 1574 | w83781d_write_value(client, |
1544 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); | 1575 | W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); |
@@ -1551,12 +1582,23 @@ w83781d_init_client(struct i2c_client *client) | |||
1551 | (w83781d_read_value(client, | 1582 | (w83781d_read_value(client, |
1552 | W83781D_REG_CONFIG) & 0xf7) | 1583 | W83781D_REG_CONFIG) & 0xf7) |
1553 | | 0x01); | 1584 | | 0x01); |
1585 | |||
1586 | /* A few vars need to be filled upon startup */ | ||
1587 | for (i = 1; i <= 3; i++) { | ||
1588 | data->fan_min[i - 1] = w83781d_read_value(client, | ||
1589 | W83781D_REG_FAN_MIN(i)); | ||
1590 | } | ||
1591 | if (type != w83781d && type != as99127f) | ||
1592 | for (i = 0; i < 4; i++) | ||
1593 | data->pwmenable[i] = 1; | ||
1594 | |||
1595 | mutex_init(&data->update_lock); | ||
1554 | } | 1596 | } |
1555 | 1597 | ||
1556 | static struct w83781d_data *w83781d_update_device(struct device *dev) | 1598 | static struct w83781d_data *w83781d_update_device(struct device *dev) |
1557 | { | 1599 | { |
1558 | struct i2c_client *client = to_i2c_client(dev); | 1600 | struct w83781d_data *data = dev_get_drvdata(dev); |
1559 | struct w83781d_data *data = i2c_get_clientdata(client); | 1601 | struct i2c_client *client = &data->client; |
1560 | int i; | 1602 | int i; |
1561 | 1603 | ||
1562 | mutex_lock(&data->update_lock); | 1604 | mutex_lock(&data->update_lock); |
@@ -1589,8 +1631,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) | |||
1589 | data->pwm[i - 1] = | 1631 | data->pwm[i - 1] = |
1590 | w83781d_read_value(client, | 1632 | w83781d_read_value(client, |
1591 | W83781D_REG_PWM(i)); | 1633 | W83781D_REG_PWM(i)); |
1592 | if ((data->type != w83782d | 1634 | if ((data->type != w83782d || !client->driver) |
1593 | || i2c_is_isa_client(client)) | ||
1594 | && i == 2) | 1635 | && i == 2) |
1595 | break; | 1636 | break; |
1596 | } | 1637 | } |
@@ -1672,6 +1713,133 @@ static struct w83781d_data *w83781d_update_device(struct device *dev) | |||
1672 | return data; | 1713 | return data; |
1673 | } | 1714 | } |
1674 | 1715 | ||
1716 | /* return 1 if a supported chip is found, 0 otherwise */ | ||
1717 | static int __init | ||
1718 | w83781d_isa_found(unsigned short address) | ||
1719 | { | ||
1720 | int val, save, found = 0; | ||
1721 | |||
1722 | if (!request_region(address, W83781D_EXTENT, "w83781d")) | ||
1723 | return 0; | ||
1724 | |||
1725 | #define REALLY_SLOW_IO | ||
1726 | /* We need the timeouts for at least some W83781D-like | ||
1727 | chips. But only if we read 'undefined' registers. */ | ||
1728 | val = inb_p(address + 1); | ||
1729 | if (inb_p(address + 2) != val | ||
1730 | || inb_p(address + 3) != val | ||
1731 | || inb_p(address + 7) != val) { | ||
1732 | pr_debug("w83781d: Detection failed at step 1\n"); | ||
1733 | goto release; | ||
1734 | } | ||
1735 | #undef REALLY_SLOW_IO | ||
1736 | |||
1737 | /* We should be able to change the 7 LSB of the address port. The | ||
1738 | MSB (busy flag) should be clear initially, set after the write. */ | ||
1739 | save = inb_p(address + W83781D_ADDR_REG_OFFSET); | ||
1740 | if (save & 0x80) { | ||
1741 | pr_debug("w83781d: Detection failed at step 2\n"); | ||
1742 | goto release; | ||
1743 | } | ||
1744 | val = ~save & 0x7f; | ||
1745 | outb_p(val, address + W83781D_ADDR_REG_OFFSET); | ||
1746 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) { | ||
1747 | outb_p(save, address + W83781D_ADDR_REG_OFFSET); | ||
1748 | pr_debug("w83781d: Detection failed at step 3\n"); | ||
1749 | goto release; | ||
1750 | } | ||
1751 | |||
1752 | /* We found a device, now see if it could be a W83781D */ | ||
1753 | outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET); | ||
1754 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1755 | if (val & 0x80) { | ||
1756 | pr_debug("w83781d: Detection failed at step 4\n"); | ||
1757 | goto release; | ||
1758 | } | ||
1759 | outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); | ||
1760 | save = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1761 | outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET); | ||
1762 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1763 | if ((!(save & 0x80) && (val != 0xa3)) | ||
1764 | || ((save & 0x80) && (val != 0x5c))) { | ||
1765 | pr_debug("w83781d: Detection failed at step 5\n"); | ||
1766 | goto release; | ||
1767 | } | ||
1768 | outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET); | ||
1769 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1770 | if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */ | ||
1771 | pr_debug("w83781d: Detection failed at step 6\n"); | ||
1772 | goto release; | ||
1773 | } | ||
1774 | |||
1775 | /* The busy flag should be clear again */ | ||
1776 | if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) { | ||
1777 | pr_debug("w83781d: Detection failed at step 7\n"); | ||
1778 | goto release; | ||
1779 | } | ||
1780 | |||
1781 | /* Determine the chip type */ | ||
1782 | outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); | ||
1783 | save = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1784 | outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET); | ||
1785 | outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET); | ||
1786 | val = inb_p(address + W83781D_DATA_REG_OFFSET); | ||
1787 | if ((val & 0xfe) == 0x10 /* W83781D */ | ||
1788 | || val == 0x30 /* W83782D */ | ||
1789 | || val == 0x21) /* W83627HF */ | ||
1790 | found = 1; | ||
1791 | |||
1792 | if (found) | ||
1793 | pr_info("w83781d: Found a %s chip at %#x\n", | ||
1794 | val == 0x21 ? "W83627HF" : | ||
1795 | val == 0x30 ? "W83782D" : "W83781D", (int)address); | ||
1796 | |||
1797 | release: | ||
1798 | release_region(address, W83781D_EXTENT); | ||
1799 | return found; | ||
1800 | } | ||
1801 | |||
1802 | static int __init | ||
1803 | w83781d_isa_device_add(unsigned short address) | ||
1804 | { | ||
1805 | struct resource res = { | ||
1806 | .start = address, | ||
1807 | .end = address + W83781D_EXTENT, | ||
1808 | .name = "w83781d", | ||
1809 | .flags = IORESOURCE_IO, | ||
1810 | }; | ||
1811 | int err; | ||
1812 | |||
1813 | pdev = platform_device_alloc("w83781d", address); | ||
1814 | if (!pdev) { | ||
1815 | err = -ENOMEM; | ||
1816 | printk(KERN_ERR "w83781d: Device allocation failed\n"); | ||
1817 | goto exit; | ||
1818 | } | ||
1819 | |||
1820 | err = platform_device_add_resources(pdev, &res, 1); | ||
1821 | if (err) { | ||
1822 | printk(KERN_ERR "w83781d: Device resource addition failed " | ||
1823 | "(%d)\n", err); | ||
1824 | goto exit_device_put; | ||
1825 | } | ||
1826 | |||
1827 | err = platform_device_add(pdev); | ||
1828 | if (err) { | ||
1829 | printk(KERN_ERR "w83781d: Device addition failed (%d)\n", | ||
1830 | err); | ||
1831 | goto exit_device_put; | ||
1832 | } | ||
1833 | |||
1834 | return 0; | ||
1835 | |||
1836 | exit_device_put: | ||
1837 | platform_device_put(pdev); | ||
1838 | exit: | ||
1839 | pdev = NULL; | ||
1840 | return err; | ||
1841 | } | ||
1842 | |||
1675 | static int __init | 1843 | static int __init |
1676 | sensors_w83781d_init(void) | 1844 | sensors_w83781d_init(void) |
1677 | { | 1845 | { |
@@ -1679,21 +1847,36 @@ sensors_w83781d_init(void) | |||
1679 | 1847 | ||
1680 | res = i2c_add_driver(&w83781d_driver); | 1848 | res = i2c_add_driver(&w83781d_driver); |
1681 | if (res) | 1849 | if (res) |
1682 | return res; | 1850 | goto exit; |
1851 | |||
1852 | if (w83781d_isa_found(isa_address)) { | ||
1853 | res = platform_driver_register(&w83781d_isa_driver); | ||
1854 | if (res) | ||
1855 | goto exit_unreg_i2c_driver; | ||
1683 | 1856 | ||
1684 | /* Don't exit if this one fails, we still want the I2C variants | 1857 | /* Sets global pdev as a side effect */ |
1685 | to work! */ | 1858 | res = w83781d_isa_device_add(isa_address); |
1686 | if (i2c_isa_add_driver(&w83781d_isa_driver)) | 1859 | if (res) |
1687 | isa_address = 0; | 1860 | goto exit_unreg_isa_driver; |
1861 | } | ||
1688 | 1862 | ||
1689 | return 0; | 1863 | return 0; |
1864 | |||
1865 | exit_unreg_isa_driver: | ||
1866 | platform_driver_unregister(&w83781d_isa_driver); | ||
1867 | exit_unreg_i2c_driver: | ||
1868 | i2c_del_driver(&w83781d_driver); | ||
1869 | exit: | ||
1870 | return res; | ||
1690 | } | 1871 | } |
1691 | 1872 | ||
1692 | static void __exit | 1873 | static void __exit |
1693 | sensors_w83781d_exit(void) | 1874 | sensors_w83781d_exit(void) |
1694 | { | 1875 | { |
1695 | if (isa_address) | 1876 | if (pdev) { |
1696 | i2c_isa_del_driver(&w83781d_isa_driver); | 1877 | platform_device_unregister(pdev); |
1878 | platform_driver_unregister(&w83781d_isa_driver); | ||
1879 | } | ||
1697 | i2c_del_driver(&w83781d_driver); | 1880 | i2c_del_driver(&w83781d_driver); |
1698 | } | 1881 | } |
1699 | 1882 | ||