diff options
Diffstat (limited to 'drivers/hwmon/w83627ehf.c')
-rw-r--r-- | drivers/hwmon/w83627ehf.c | 64 |
1 files changed, 31 insertions, 33 deletions
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 8a40b6976e1a..b60efe8f8b26 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
@@ -9,6 +9,9 @@ | |||
9 | Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help | 9 | Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help |
10 | in testing and debugging this driver. | 10 | in testing and debugging this driver. |
11 | 11 | ||
12 | This driver also supports the W83627EHG, which is the lead-free | ||
13 | version of the W83627EHF. | ||
14 | |||
12 | This program is free software; you can redistribute it and/or modify | 15 | This program is free software; you can redistribute it and/or modify |
13 | it under the terms of the GNU General Public License as published by | 16 | it under the terms of the GNU General Public License as published by |
14 | the Free Software Foundation; either version 2 of the License, or | 17 | the Free Software Foundation; either version 2 of the License, or |
@@ -37,17 +40,14 @@ | |||
37 | #include <linux/init.h> | 40 | #include <linux/init.h> |
38 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
39 | #include <linux/i2c.h> | 42 | #include <linux/i2c.h> |
40 | #include <linux/i2c-sensor.h> | 43 | #include <linux/i2c-isa.h> |
44 | #include <linux/hwmon.h> | ||
45 | #include <linux/err.h> | ||
41 | #include <asm/io.h> | 46 | #include <asm/io.h> |
42 | #include "lm75.h" | 47 | #include "lm75.h" |
43 | 48 | ||
44 | /* Addresses to scan | 49 | /* The actual ISA address is read from Super-I/O configuration space */ |
45 | The actual ISA address is read from Super-I/O configuration space */ | 50 | static unsigned short address; |
46 | static unsigned short normal_i2c[] = { I2C_CLIENT_END }; | ||
47 | static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END }; | ||
48 | |||
49 | /* Insmod parameters */ | ||
50 | SENSORS_INSMOD_1(w83627ehf); | ||
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Super-I/O constants and functions | 53 | * Super-I/O constants and functions |
@@ -174,6 +174,7 @@ temp1_to_reg(int temp) | |||
174 | 174 | ||
175 | struct w83627ehf_data { | 175 | struct w83627ehf_data { |
176 | struct i2c_client client; | 176 | struct i2c_client client; |
177 | struct class_device *class_dev; | ||
177 | struct semaphore lock; | 178 | struct semaphore lock; |
178 | 179 | ||
179 | struct semaphore update_lock; | 180 | struct semaphore update_lock; |
@@ -666,15 +667,12 @@ static void w83627ehf_init_client(struct i2c_client *client) | |||
666 | } | 667 | } |
667 | } | 668 | } |
668 | 669 | ||
669 | static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind) | 670 | static int w83627ehf_detect(struct i2c_adapter *adapter) |
670 | { | 671 | { |
671 | struct i2c_client *client; | 672 | struct i2c_client *client; |
672 | struct w83627ehf_data *data; | 673 | struct w83627ehf_data *data; |
673 | int i, err = 0; | 674 | int i, err = 0; |
674 | 675 | ||
675 | if (!i2c_is_isa_adapter(adapter)) | ||
676 | return 0; | ||
677 | |||
678 | if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) { | 676 | if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) { |
679 | err = -EBUSY; | 677 | err = -EBUSY; |
680 | goto exit; | 678 | goto exit; |
@@ -720,6 +718,12 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind) | |||
720 | data->has_fan |= (1 << 4); | 718 | data->has_fan |= (1 << 4); |
721 | 719 | ||
722 | /* Register sysfs hooks */ | 720 | /* Register sysfs hooks */ |
721 | data->class_dev = hwmon_device_register(&client->dev); | ||
722 | if (IS_ERR(data->class_dev)) { | ||
723 | err = PTR_ERR(data->class_dev); | ||
724 | goto exit_detach; | ||
725 | } | ||
726 | |||
723 | device_create_file(&client->dev, &dev_attr_fan1_input); | 727 | device_create_file(&client->dev, &dev_attr_fan1_input); |
724 | device_create_file(&client->dev, &dev_attr_fan1_min); | 728 | device_create_file(&client->dev, &dev_attr_fan1_min); |
725 | device_create_file(&client->dev, &dev_attr_fan1_div); | 729 | device_create_file(&client->dev, &dev_attr_fan1_div); |
@@ -753,6 +757,8 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind) | |||
753 | 757 | ||
754 | return 0; | 758 | return 0; |
755 | 759 | ||
760 | exit_detach: | ||
761 | i2c_detach_client(client); | ||
756 | exit_free: | 762 | exit_free: |
757 | kfree(data); | 763 | kfree(data); |
758 | exit_release: | 764 | exit_release: |
@@ -761,24 +767,17 @@ exit: | |||
761 | return err; | 767 | return err; |
762 | } | 768 | } |
763 | 769 | ||
764 | static int w83627ehf_attach_adapter(struct i2c_adapter *adapter) | ||
765 | { | ||
766 | if (!(adapter->class & I2C_CLASS_HWMON)) | ||
767 | return 0; | ||
768 | return i2c_detect(adapter, &addr_data, w83627ehf_detect); | ||
769 | } | ||
770 | |||
771 | static int w83627ehf_detach_client(struct i2c_client *client) | 770 | static int w83627ehf_detach_client(struct i2c_client *client) |
772 | { | 771 | { |
772 | struct w83627ehf_data *data = i2c_get_clientdata(client); | ||
773 | int err; | 773 | int err; |
774 | 774 | ||
775 | if ((err = i2c_detach_client(client))) { | 775 | hwmon_device_unregister(data->class_dev); |
776 | dev_err(&client->dev, "Client deregistration failed, " | 776 | |
777 | "client not detached.\n"); | 777 | if ((err = i2c_detach_client(client))) |
778 | return err; | 778 | return err; |
779 | } | ||
780 | release_region(client->addr, REGION_LENGTH); | 779 | release_region(client->addr, REGION_LENGTH); |
781 | kfree(i2c_get_clientdata(client)); | 780 | kfree(data); |
782 | 781 | ||
783 | return 0; | 782 | return 0; |
784 | } | 783 | } |
@@ -786,12 +785,11 @@ static int w83627ehf_detach_client(struct i2c_client *client) | |||
786 | static struct i2c_driver w83627ehf_driver = { | 785 | static struct i2c_driver w83627ehf_driver = { |
787 | .owner = THIS_MODULE, | 786 | .owner = THIS_MODULE, |
788 | .name = "w83627ehf", | 787 | .name = "w83627ehf", |
789 | .flags = I2C_DF_NOTIFY, | 788 | .attach_adapter = w83627ehf_detect, |
790 | .attach_adapter = w83627ehf_attach_adapter, | ||
791 | .detach_client = w83627ehf_detach_client, | 789 | .detach_client = w83627ehf_detach_client, |
792 | }; | 790 | }; |
793 | 791 | ||
794 | static int __init w83627ehf_find(int sioaddr, int *address) | 792 | static int __init w83627ehf_find(int sioaddr, unsigned short *addr) |
795 | { | 793 | { |
796 | u16 val; | 794 | u16 val; |
797 | 795 | ||
@@ -809,8 +807,8 @@ static int __init w83627ehf_find(int sioaddr, int *address) | |||
809 | superio_select(W83627EHF_LD_HWM); | 807 | superio_select(W83627EHF_LD_HWM); |
810 | val = (superio_inb(SIO_REG_ADDR) << 8) | 808 | val = (superio_inb(SIO_REG_ADDR) << 8) |
811 | | superio_inb(SIO_REG_ADDR + 1); | 809 | | superio_inb(SIO_REG_ADDR + 1); |
812 | *address = val & ~(REGION_LENGTH - 1); | 810 | *addr = val & ~(REGION_LENGTH - 1); |
813 | if (*address == 0) { | 811 | if (*addr == 0) { |
814 | superio_exit(); | 812 | superio_exit(); |
815 | return -ENODEV; | 813 | return -ENODEV; |
816 | } | 814 | } |
@@ -826,16 +824,16 @@ static int __init w83627ehf_find(int sioaddr, int *address) | |||
826 | 824 | ||
827 | static int __init sensors_w83627ehf_init(void) | 825 | static int __init sensors_w83627ehf_init(void) |
828 | { | 826 | { |
829 | if (w83627ehf_find(0x2e, &normal_isa[0]) | 827 | if (w83627ehf_find(0x2e, &address) |
830 | && w83627ehf_find(0x4e, &normal_isa[0])) | 828 | && w83627ehf_find(0x4e, &address)) |
831 | return -ENODEV; | 829 | return -ENODEV; |
832 | 830 | ||
833 | return i2c_add_driver(&w83627ehf_driver); | 831 | return i2c_isa_add_driver(&w83627ehf_driver); |
834 | } | 832 | } |
835 | 833 | ||
836 | static void __exit sensors_w83627ehf_exit(void) | 834 | static void __exit sensors_w83627ehf_exit(void) |
837 | { | 835 | { |
838 | i2c_del_driver(&w83627ehf_driver); | 836 | i2c_isa_del_driver(&w83627ehf_driver); |
839 | } | 837 | } |
840 | 838 | ||
841 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); | 839 | MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); |