aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2009-12-16 21:38:27 +0100
committerJean Delvare <khali@linux-fr.org>2009-12-16 21:38:27 +0100
commitfa0bff02239abdad446effef22e5db281cf3d562 (patch)
treeb6bc68dd9e32660a73b2155ad209919040b80195
parent3ecf44b312758d10be20539b06b2df5d77d59cdb (diff)
downloadkernel_samsung_smdk4412-fa0bff02239abdad446effef22e5db281cf3d562.zip
kernel_samsung_smdk4412-fa0bff02239abdad446effef22e5db281cf3d562.tar.gz
kernel_samsung_smdk4412-fa0bff02239abdad446effef22e5db281cf3d562.tar.bz2
hwmon: (smsc47m1) Enable device if needed
If the address is set but the device isn't enabled, attempt to enable it. If it won't work for any reason (resource conflict, no function enabled) the initial state is restored. The initial state is also restored on module unloading. Signed-off-by: Jean Delvare <khali@linux-fr.org> Tested-by: Sean Fidler <fidlersean@gmail.com>
-rw-r--r--drivers/hwmon/smsc47m1.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 92cca51..9ca9781 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -136,6 +136,7 @@ struct smsc47m1_data {
struct smsc47m1_sio_data {
enum chips type;
+ u8 activate; /* Remember initial device state */
};
@@ -468,17 +469,38 @@ static int __init smsc47m1_find(unsigned short *addr,
superio_select();
*addr = (superio_inb(SUPERIO_REG_BASE) << 8)
| superio_inb(SUPERIO_REG_BASE + 1);
- val = superio_inb(SUPERIO_REG_ACT);
- if (*addr == 0 || (val & 0x01) == 0) {
- pr_info(DRVNAME ": Device is disabled, will not use\n");
+ if (*addr == 0) {
+ pr_info(DRVNAME ": Device address not set, will not use\n");
superio_exit();
return -ENODEV;
}
+ /* Enable only if address is set (needed at least on the
+ * Compaq Presario S4000NX) */
+ sio_data->activate = superio_inb(SUPERIO_REG_ACT);
+ if ((sio_data->activate & 0x01) == 0) {
+ pr_info(DRVNAME ": Enabling device\n");
+ superio_outb(SUPERIO_REG_ACT, sio_data->activate | 0x01);
+ }
+
superio_exit();
return 0;
}
+/* Restore device to its initial state */
+static void __init smsc47m1_restore(const struct smsc47m1_sio_data *sio_data)
+{
+ if ((sio_data->activate & 0x01) == 0) {
+ superio_enter();
+ superio_select();
+
+ pr_info(DRVNAME ": Disabling device\n");
+ superio_outb(SUPERIO_REG_ACT, sio_data->activate);
+
+ superio_exit();
+ }
+}
+
#define CHECK 1
#define REQUEST 2
#define RELEASE 3
@@ -856,6 +878,7 @@ static int __init sm_smsc47m1_init(void)
exit_device:
platform_device_unregister(pdev);
+ smsc47m1_restore(&sio_data);
exit:
return err;
}
@@ -863,6 +886,7 @@ exit:
static void __exit sm_smsc47m1_exit(void)
{
platform_driver_unregister(&smsc47m1_driver);
+ smsc47m1_restore(pdev->dev.platform_data);
platform_device_unregister(pdev);
}