* [ patch .24-rc0 5/5 ] SuperIO locks coordinator - use in other hwmon/*.c
@ 2007-10-15 5:11 ` Jim Cromie
0 siblings, 0 replies; 19+ messages in thread
From: Jim Cromie @ 2007-10-15 5:11 UTC (permalink / raw)
To: Linux kernel, LM Sensors
05 - use superio-locks in rest of drivers/hwmon/*.c
this patch is compile-tested only, please review for sanity before you
try running them. Things to look for - missing superio_release(),
opportunities to use superio_devid(), superio_inw(), etc.
Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
---
hwmon-superio-others
Kconfig | 6 +++
f71805f.c | 86 +++++++++++++++-------------------------------
it87.c | 80 +++++++++++++++---------------------------
smsc47b397.c | 63 ++++++++++++---------------------
smsc47m1.c | 69 +++++++++++++------------------------
vt1211.c | 70 +++++++++++++------------------------
w83627ehf.c | 110 +++++++++++++++++++++++++----------------------------------
7 files changed, 188 insertions(+), 296 deletions(-)
diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/f71805f.c hwmon-superio.old/drivers/hwmon/f71805f.c
--- hwmon-fan-push-offset/drivers/hwmon/f71805f.c 2007-10-14 13:00:24.000000000 -0600
+++ hwmon-superio.old/drivers/hwmon/f71805f.c 2007-10-14 17:22:23.000000000 -0600
@@ -39,6 +39,7 @@
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/ioport.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
static struct platform_device *pdev;
@@ -52,8 +53,6 @@ enum kinds { f71805f, f71872f };
#define F71805F_LD_HWM 0x04
-#define SIO_REG_LDSEL 0x07 /* Logical device select */
-#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
#define SIO_REG_DEVREV 0x22 /* Device revision */
#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
#define SIO_REG_FNSEL1 0x29 /* Multi Function Select 1 (F71872F) */
@@ -64,43 +63,15 @@ enum kinds { f71805f, f71872f };
#define SIO_F71805F_ID 0x0406
#define SIO_F71872F_ID 0x0341
-static inline int
-superio_inb(int base, int reg)
-{
- outb(reg, base);
- return inb(base + 1);
-}
-
-static int
-superio_inw(int base, int reg)
-{
- int val;
- outb(reg++, base);
- val = inb(base + 1) << 8;
- outb(reg, base);
- val |= inb(base + 1);
- return val;
-}
+static struct superio* gate;
-static inline void
-superio_select(int base, int ld)
-{
- outb(SIO_REG_LDSEL, base);
- outb(ld, base + 1);
-}
-
-static inline void
-superio_enter(int base)
-{
- outb(0x87, base);
- outb(0x87, base);
-}
-
-static inline void
-superio_exit(int base)
-{
- outb(0xaa, base);
-}
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2e, 0x4e },
+ .device_ids = { SIO_F71805F_ID, SIO_F71872F_ID, 0 },
+ .devid_word = 1,
+ .enter_seq = { 0x87, 0x87 },
+ .exit_seq = { 0xAA }
+};
/*
* ISA constants
@@ -1480,31 +1451,33 @@ exit:
return err;
}
-static int __init f71805f_find(int sioaddr, unsigned short *address,
- struct f71805f_sio_data *sio_data)
+static int __init f71805f_find(struct f71805f_sio_data *sio_data)
{
int err = -ENODEV;
- u16 devid;
+ u16 devid, address;
static const char *names[] = {
"F71805F/FG",
"F71872F/FG or F71806F/FG",
};
-
- superio_enter(sioaddr);
-
- devid = superio_inw(sioaddr, SIO_REG_MANID);
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING "pc87360: superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
+ devid = superio_inw(gate, SIO_REG_MANID);
if (devid != SIO_FINTEK_ID)
goto exit;
- devid = superio_inw(sioaddr, SIO_REG_DEVID);
switch (devid) {
case SIO_F71805F_ID:
sio_data->kind = f71805f;
break;
case SIO_F71872F_ID:
sio_data->kind = f71872f;
- sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
+ sio_data->fnsel1 = superio_inb(gate, SIO_REG_FNSEL1);
break;
default:
printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
@@ -1512,28 +1485,28 @@ static int __init f71805f_find(int sioad
goto exit;
}
- superio_select(sioaddr, F71805F_LD_HWM);
- if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+ superio_select(gate, F71805F_LD_HWM);
+ if (!(superio_inb(gate, SIO_REG_ENABLE) & 0x01)) {
printk(KERN_WARNING DRVNAME ": Device not activated, "
"skipping\n");
goto exit;
}
- *address = superio_inw(sioaddr, SIO_REG_ADDR);
- if (*address == 0) {
+ address = superio_inw(gate, SIO_REG_ADDR);
+ if (address == 0) {
printk(KERN_WARNING DRVNAME ": Base address not set, "
"skipping\n");
goto exit;
}
- *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
+ address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
err = 0;
printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
- names[sio_data->kind], *address,
- superio_inb(sioaddr, SIO_REG_DEVREV));
+ names[sio_data->kind], address,
+ superio_inb(gate, SIO_REG_DEVREV));
exit:
- superio_exit(sioaddr);
+ superio_exit(gate);
return err;
}
@@ -1543,8 +1516,7 @@ static int __init f71805f_init(void)
unsigned short address;
struct f71805f_sio_data sio_data;
- if (f71805f_find(0x2e, &address, &sio_data)
- && f71805f_find(0x4e, &address, &sio_data))
+ if (f71805f_find(&sio_data))
return -ENODEV;
err = platform_driver_register(&f71805f_driver);
diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/it87.c hwmon-superio.old/drivers/hwmon/it87.c
--- hwmon-fan-push-offset/drivers/hwmon/it87.c 2007-10-14 13:00:24.000000000 -0600
+++ hwmon-superio.old/drivers/hwmon/it87.c 2007-10-14 17:22:23.000000000 -0600
@@ -38,6 +38,7 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
#define DRVNAME "it87"
@@ -54,46 +55,6 @@ static struct platform_device *pdev;
#define DEVID 0x20 /* Register: Device ID */
#define DEVREV 0x22 /* Register: Device Revision */
-static inline int
-superio_inb(int reg)
-{
- outb(reg, REG);
- return inb(VAL);
-}
-
-static int superio_inw(int reg)
-{
- int val;
- outb(reg++, REG);
- val = inb(VAL) << 8;
- outb(reg, REG);
- val |= inb(VAL);
- return val;
-}
-
-static inline void
-superio_select(int ldn)
-{
- outb(DEV, REG);
- outb(ldn, VAL);
-}
-
-static inline void
-superio_enter(void)
-{
- outb(0x87, REG);
- outb(0x01, REG);
- outb(0x55, REG);
- outb(0x55, REG);
-}
-
-static inline void
-superio_exit(void)
-{
- outb(0x02, REG);
- outb(0x02, VAL);
-}
-
/* Logical device 4 registers */
#define IT8712F_DEVID 0x8712
#define IT8705F_DEVID 0x8705
@@ -103,6 +64,17 @@ superio_exit(void)
#define IT87_ACT_REG 0x30
#define IT87_BASE_REG 0x60
+static struct superio* gate;
+
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { REG, 0 },
+ .device_ids = { IT8712F_DEVID, IT8716F_DEVID, IT8718F_DEVID,
+ IT8705F_DEVID, IT8726F_DEVID, 0 },
+ .devid_word = 1,
+ .enter_seq = { 0x87, 0x01, 0x55, 0x55, 0 },
+ .exit_seq = { 0x02, 0x02, 0 }
+};
+
/* Logical device 7 registers (IT8712F and later) */
#define IT87_SIO_PINX2_REG 0x2c /* Pin selection */
#define IT87_SIO_VID_REG 0xfc /* VID value */
@@ -890,10 +862,16 @@ static int __init it87_find(unsigned sho
{
int err = -ENODEV;
u16 chip_type;
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING "pc87360: superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
- superio_enter();
- chip_type = superio_inw(DEVID);
-
+ /* can get this from gate */
+ chip_type = superio_inw(gate, DEVID);
switch (chip_type) {
case IT8705F_DEVID:
sio_data->type = it87;
@@ -916,13 +894,13 @@ static int __init it87_find(unsigned sho
goto exit;
}
- superio_select(PME);
- if (!(superio_inb(IT87_ACT_REG) & 0x01)) {
+ superio_select(gate, PME);
+ if (!(superio_inb(gate, IT87_ACT_REG) & 0x01)) {
pr_info("it87: Device not activated, skipping\n");
goto exit;
}
- *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1);
+ *address = superio_inw(gate, IT87_BASE_REG) & ~(IT87_EXTENT - 1);
if (*address == 0) {
pr_info("it87: Base address not set, skipping\n");
goto exit;
@@ -930,17 +908,17 @@ static int __init it87_find(unsigned sho
err = 0;
pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n",
- chip_type, *address, superio_inb(DEVREV) & 0x0f);
+ chip_type, *address, superio_inb(gate, DEVREV) & 0x0f);
/* Read GPIO config and VID value from LDN 7 (GPIO) */
if (chip_type != IT8705F_DEVID) {
int reg;
- superio_select(GPIO);
+ superio_select(gate, GPIO);
if (chip_type == it8718)
- sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
+ sio_data->vid_value = superio_inb(gate, IT87_SIO_VID_REG);
- reg = superio_inb(IT87_SIO_PINX2_REG);
+ reg = superio_inb(gate, IT87_SIO_PINX2_REG);
if (reg & (1 << 0))
pr_info("it87: in3 is VCC (+5V)\n");
if (reg & (1 << 1))
@@ -948,7 +926,7 @@ static int __init it87_find(unsigned sho
}
exit:
- superio_exit();
+ superio_exit(gate);
return err;
}
diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/Kconfig hwmon-superio.old/drivers/hwmon/Kconfig
--- hwmon-fan-push-offset/drivers/hwmon/Kconfig 2007-10-14 13:00:24.000000000 -0600
+++ hwmon-superio.old/drivers/hwmon/Kconfig 2007-10-14 17:22:23.000000000 -0600
@@ -218,6 +218,7 @@ config SENSORS_DS1621
config SENSORS_F71805F
tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
depends on EXPERIMENTAL
+ select SUPERIO_LOCKS
help
If you say yes here you get support for hardware monitoring
features of the Fintek F71805F/FG, F71806F/FG and F71872F/FG
@@ -325,6 +328,7 @@ config SENSORS_IBMPEX
config SENSORS_IT87
tristate "ITE IT87xx and compatibles"
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here you get support for ITE IT8705F, IT8712F,
IT8716F, IT8718F and IT8726F sensor chips, and the SiS960 clone.
@@ -554,6 +564,7 @@ config SENSORS_SMSC47M192
tristate "SMSC LPC47M192 and compatibles"
depends on I2C && EXPERIMENTAL
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here you get support for the temperature and
voltage sensors of the SMSC LPC47M192, LPC47M15x, LPC47M292
@@ -570,6 +581,7 @@ config SENSORS_SMSC47M192
config SENSORS_SMSC47B397
tristate "SMSC LPC47B397-NC"
depends on EXPERIMENTAL
+ select SUPERIO_LOCKS
help
If you say yes here you get support for the SMSC LPC47B397-NC
sensor chip.
@@ -601,6 +613,7 @@ config SENSORS_VT1211
tristate "VIA VT1211"
depends on EXPERIMENTAL
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here then you get support for hardware monitoring
features of the VIA VT1211 Super-I/O chip.
@@ -686,6 +700,7 @@ config SENSORS_W83627HF
config SENSORS_W83627EHF
tristate "Winbond W83627EHF/DHG"
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here you get support for the hardware
monitoring functionality of the Winbond W83627EHF Super-I/O chip.
diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/smsc47b397.c hwmon-superio.old/drivers/hwmon/smsc47b397.c
--- hwmon-fan-push-offset/drivers/hwmon/smsc47b397.c 2007-10-14 13:00:24.000000000 -0600
+++ hwmon-superio.old/drivers/hwmon/smsc47b397.c 2007-10-14 17:22:23.000000000 -0600
@@ -36,6 +36,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/mutex.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
static struct platform_device *pdev;
@@ -44,37 +45,6 @@ static struct platform_device *pdev;
/* Super-I/0 registers and commands */
-#define REG 0x2e /* The register to read/write */
-#define VAL 0x2f /* The value to read/write */
-
-static inline void superio_outb(int reg, int val)
-{
- outb(reg, REG);
- outb(val, VAL);
-}
-
-static inline int superio_inb(int reg)
-{
- outb(reg, REG);
- return inb(VAL);
-}
-
-/* select superio logical device */
-static inline void superio_select(int ld)
-{
- superio_outb(0x07, ld);
-}
-
-static inline void superio_enter(void)
-{
- outb(0x55, REG);
-}
-
-static inline void superio_exit(void)
-{
- outb(0xAA, REG);
-}
-
#define SUPERIO_REG_DEVID 0x20
#define SUPERIO_REG_DEVREV 0x21
#define SUPERIO_REG_BASE_MSB 0x60
@@ -83,6 +53,15 @@ static inline void superio_exit(void)
#define SMSC_EXTENT 0x02
+static struct superio* gate;
+
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2e, 0x4e },
+ .device_ids = { 0x6f, 0x81, 0 },
+ .enter_seq = { 0x55, 0 },
+ .exit_seq = { 0xAA, 0 },
+};
+
/* 0 <= nr <= 3 */
static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
#define SMSC47B397_REG_TEMP(nr) (smsc47b397_reg_temp[(nr)])
@@ -332,26 +311,32 @@ static int __init smsc47b397_find(unsign
{
u8 id, rev;
- superio_enter();
- id = superio_inb(SUPERIO_REG_DEVID);
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING "pc87360: superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
+ id = superio_inb(gate, SUPERIO_REG_DEVID);
if ((id != 0x6f) && (id != 0x81) && (id != 0x85)) {
- superio_exit();
+ superio_exit(gate);
return -ENODEV;
}
- rev = superio_inb(SUPERIO_REG_DEVREV);
+ rev = superio_inb(gate, SUPERIO_REG_DEVREV);
- superio_select(SUPERIO_REG_LD8);
- *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
- | superio_inb(SUPERIO_REG_BASE_LSB);
+ superio_select(gate, SUPERIO_REG_LD8);
+ *addr = (superio_inb(gate, SUPERIO_REG_BASE_MSB) << 8)
+ | superio_inb(gate, SUPERIO_REG_BASE_LSB);
printk(KERN_INFO DRVNAME ": found SMSC %s "
"(base address 0x%04x, revision %u)\n",
id == 0x81 ? "SCH5307-NS" : id == 0x85 ? "SCH5317" :
"LPC47B397-NC", *addr, rev);
- superio_exit();
+ superio_exit(gate);
return 0;
}
diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/smsc47m1.c hwmon-superio.old/drivers/hwmon/smsc47m1.c
--- hwmon-fan-push-offset/drivers/hwmon/smsc47m1.c 2007-10-14 13:00:24.000000000 -0600
+++ hwmon-superio.old/drivers/hwmon/smsc47m1.c 2007-10-14 17:22:23.000000000 -0600
@@ -37,6 +37,7 @@
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
static struct platform_device *pdev;
@@ -46,41 +47,18 @@ enum chips { smsc47m1, smsc47m2 };
/* Super-I/0 registers and commands */
-#define REG 0x2e /* The register to read/write */
-#define VAL 0x2f /* The value to read/write */
-
-static inline void
-superio_outb(int reg, int val)
-{
- outb(reg, REG);
- outb(val, VAL);
-}
-
-static inline int
-superio_inb(int reg)
-{
- outb(reg, REG);
- return inb(VAL);
-}
-
-/* logical device for fans is 0x0A */
-#define superio_select() superio_outb(0x07, 0x0A)
-
-static inline void
-superio_enter(void)
-{
- outb(0x55, REG);
-}
-
-static inline void
-superio_exit(void)
-{
- outb(0xAA, REG);
-}
-
#define SUPERIO_REG_ACT 0x30
#define SUPERIO_REG_BASE 0x60
-#define SUPERIO_REG_DEVID 0x20
+
+static struct superio* gate;
+
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2e, 0x4e },
+ .device_ids = { 0x51, 0x59, 0x5F, 0x60, 0x6B, 0 },
+ .devid_word = 1,
+ .enter_seq = { 0x55, 0 },
+ .exit_seq = { 0xAA, 0 }
+};
/* Logical device registers */
@@ -398,8 +376,14 @@ static int __init smsc47m1_find(unsigned
{
u8 val;
- superio_enter();
- val = superio_inb(SUPERIO_REG_DEVID);
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING "pc87360: superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
+ val = superio_devid(gate);
/*
* SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
@@ -434,21 +418,20 @@ static int __init smsc47m1_find(unsigned
sio_data->type = smsc47m2;
break;
default:
- superio_exit();
+ superio_exit(gate);
return -ENODEV;
}
-
- superio_select();
- *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
- | superio_inb(SUPERIO_REG_BASE + 1);
- val = superio_inb(SUPERIO_REG_ACT);
+ superio_select(gate, 0x0A);
+ *addr = (superio_inb(gate, SUPERIO_REG_BASE) << 8)
+ | superio_inb(gate, SUPERIO_REG_BASE + 1);
+ val = superio_inb(gate, SUPERIO_REG_ACT);
if (*addr == 0 || (val & 0x01) == 0) {
pr_info(DRVNAME ": Device is disabled, will not use\n");
- superio_exit();
+ superio_exit(gate);
return -ENODEV;
}
- superio_exit();
+ superio_exit(gate);
return 0;
}
diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/vt1211.c hwmon-superio.old/drivers/hwmon/vt1211.c
--- hwmon-fan-push-offset/drivers/hwmon/vt1211.c 2007-10-14 13:00:24.000000000 -0600
+++ hwmon-superio.old/drivers/hwmon/vt1211.c 2007-10-14 17:22:23.000000000 -0600
@@ -32,6 +32,7 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/ioport.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
static int uch_config = -1;
@@ -195,34 +196,15 @@ struct vt1211_data {
/* VT1211 logical device numbers */
#define SIO_VT1211_LDN_HWMON 0x0b /* HW monitor */
-static inline void superio_outb(int sio_cip, int reg, int val)
-{
- outb(reg, sio_cip);
- outb(val, sio_cip + 1);
-}
-
-static inline int superio_inb(int sio_cip, int reg)
-{
- outb(reg, sio_cip);
- return inb(sio_cip + 1);
-}
+static struct superio* gate;
-static inline void superio_select(int sio_cip, int ldn)
-{
- outb(SIO_VT1211_LDN, sio_cip);
- outb(ldn, sio_cip + 1);
-}
-
-static inline void superio_enter(int sio_cip)
-{
- outb(0x87, sio_cip);
- outb(0x87, sio_cip);
-}
-
-static inline void superio_exit(int sio_cip)
-{
- outb(0xaa, sio_cip);
-}
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { SIO_REG_CIP1, SIO_REG_CIP2 },
+ .device_ids = { SIO_VT1211_ID, 0 },
+ .devid_addr = SIO_VT1211_DEVID,
+ .enter_seq = { 0x87, 0x87, 0 },
+ .exit_seq = { 0xAA, 0 }
+};
/* ---------------------------------------------------------------------
* Device I/O access
@@ -1277,27 +1259,29 @@ EXIT:
return err;
}
-static int __init vt1211_find(int sio_cip, unsigned short *address)
+static int __init vt1211_find(void)
{
int err = -ENODEV;
+ u16 address;
- superio_enter(sio_cip);
-
- if (superio_inb(sio_cip, SIO_VT1211_DEVID) != SIO_VT1211_ID) {
- goto EXIT;
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING DRVNAME ": superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
}
+ superio_enter(gate);
+ superio_select(gate, SIO_VT1211_LDN_HWMON);
- superio_select(sio_cip, SIO_VT1211_LDN_HWMON);
-
- if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) {
+ if ((superio_inb(gate, SIO_VT1211_ACTIVE) & 1) == 0) {
printk(KERN_WARNING DRVNAME ": HW monitor is disabled, "
"skipping\n");
goto EXIT;
}
- *address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) |
- (superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00;
- if (*address == 0) {
+ address = superio_inw(gate, SIO_VT1211_BADDR);
+
+ if (address == 0) {
printk(KERN_WARNING DRVNAME ": Base address is not set, "
"skipping\n");
goto EXIT;
@@ -1305,11 +1289,11 @@ static int __init vt1211_find(int sio_ci
err = 0;
printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, "
- "revision %u\n", *address,
- superio_inb(sio_cip, SIO_VT1211_DEVREV));
+ "revision %u\n", address,
+ superio_inb(gate, SIO_VT1211_DEVREV));
EXIT:
- superio_exit(sio_cip);
+ superio_exit(gate);
return err;
}
@@ -1318,10 +1302,8 @@ static int __init vt1211_init(void)
int err;
unsigned short address = 0;
- if ((err = vt1211_find(SIO_REG_CIP1, &address)) &&
- (err = vt1211_find(SIO_REG_CIP2, &address))) {
+ if ((err = vt1211_find()))
goto EXIT;
- }
if ((uch_config < -1) || (uch_config > 31)) {
err = -EINVAL;
diff -ruNp -X dontdiff -X exclude-diffs hwmon-fan-push-offset/drivers/hwmon/w83627ehf.c hwmon-superio.old/drivers/hwmon/w83627ehf.c
--- hwmon-fan-push-offset/drivers/hwmon/w83627ehf.c 2007-10-14 13:00:24.000000000 -0600
+++ hwmon-superio.old/drivers/hwmon/w83627ehf.c 2007-10-14 17:22:23.000000000 -0600
@@ -48,6 +48,7 @@
#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
#include "lm75.h"
@@ -80,39 +81,23 @@ static const char * w83627ehf_device_nam
#define SIO_W83627DHG_ID 0xa020
#define SIO_ID_MASK 0xFFF0
-static inline void
-superio_outb(int ioreg, int reg, int val)
-{
- outb(reg, ioreg);
- outb(val, ioreg + 1);
-}
+static struct superio* gate;
-static inline int
-superio_inb(int ioreg, int reg)
-{
- outb(reg, ioreg);
- return inb(ioreg + 1);
-}
-
-static inline void
-superio_select(int ioreg, int ld)
-{
- outb(SIO_REG_LDSEL, ioreg);
- outb(ld, ioreg + 1);
-}
-
-static inline void
-superio_enter(int ioreg)
-{
- outb(0x87, ioreg);
- outb(0x87, ioreg);
-}
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2E, 0x4E },
+ .device_ids = { SIO_W83627EHF_ID, SIO_W83627EHG_ID,
+ SIO_W83627DHG_ID, 0 },
+ .devid_mask = SIO_ID_MASK,
+ .devid_word = 1,
+ .enter_seq = { 0x87, 0x87, 0 },
+ .exit_seq = { 0 } /* exit handled by my_superio_exit */
+};
static inline void
-superio_exit(int ioreg)
+my_superio_exit(struct superio * gate)
{
- outb(0x02, ioreg);
- outb(0x02, ioreg + 1);
+ outb(0x02, gate->sioaddr);
+ outb(0x02, gate->sioaddr + 1);
}
/*
@@ -1275,23 +1260,21 @@ static int __devinit w83627ehf_probe(str
w83627ehf_init_device(data);
data->vrm = vid_which_vrm();
- superio_enter(sio_data->sioreg);
+ superio_enter(gate); /*, sio_data->sioreg); */
/* Set VID input sensibility if needed. In theory the BIOS should
have set it, but in practice it's not always the case. */
- en_vrm10 = superio_inb(sio_data->sioreg, SIO_REG_EN_VRM10);
+ en_vrm10 = superio_inb(gate, SIO_REG_EN_VRM10);
if ((en_vrm10 & 0x08) && data->vrm != 100) {
dev_warn(dev, "Setting VID input voltage to TTL\n");
- superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
- en_vrm10 & ~0x08);
+ superio_outb(gate, SIO_REG_EN_VRM10, en_vrm10 & ~0x08);
} else if (!(en_vrm10 & 0x08) && data->vrm == 100) {
dev_warn(dev, "Setting VID input voltage to VRM10\n");
- superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
- en_vrm10 | 0x08);
+ superio_outb(gate, SIO_REG_EN_VRM10, en_vrm10 | 0x08);
}
/* Read VID value */
- superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
- if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80)
- data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA) & 0x3f;
+ superio_select(gate, W83627EHF_LD_HWM);
+ if (superio_inb(gate, SIO_REG_VID_CTRL) & 0x80)
+ data->vid = superio_inb(gate, SIO_REG_VID_DATA) & 0x3f;
else {
dev_info(dev, "VID pins in output mode, CPU VID not "
"available\n");
@@ -1300,9 +1283,9 @@ static int __devinit w83627ehf_probe(str
/* fan4 and fan5 share some pins with the GPIO and serial flash */
- fan5pin = superio_inb(sio_data->sioreg, 0x24) & 0x2;
- fan4pin = superio_inb(sio_data->sioreg, 0x29) & 0x6;
- superio_exit(sio_data->sioreg);
+ fan5pin = superio_inb(gate, 0x24) & 0x2;
+ fan4pin = superio_inb(gate, 0x29) & 0x6;
+ my_superio_exit(gate);
/* It looks like fan4 and fan5 pins can be alternatively used
as fan on/off switches, but fan5 control is write only :/
@@ -1425,20 +1408,24 @@ static struct platform_driver w83627ehf_
};
/* w83627ehf_find() looks for a '627 in the Super-I/O config space */
-static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
- struct w83627ehf_sio_data *sio_data)
+static int __init w83627ehf_find(struct w83627ehf_sio_data *sio_data)
{
static const char __initdata sio_name_W83627EHF[] = "W83627EHF";
static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
- u16 val;
+ u16 val, addr;
const char *sio_name;
- superio_enter(sioaddr);
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING "pc87360: superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
+ val = superio_devid(gate);
- val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
- | superio_inb(sioaddr, SIO_REG_DEVID + 1);
switch (val & SIO_ID_MASK) {
case SIO_W83627EHF_ID:
sio_data->kind = w83627ehf;
@@ -1456,33 +1443,33 @@ static int __init w83627ehf_find(int sio
if (val != 0xffff)
pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n",
val);
- superio_exit(sioaddr);
+ my_superio_exit(gate);
return -ENODEV;
}
/* We have a known chip, find the HWM I/O address */
- superio_select(sioaddr, W83627EHF_LD_HWM);
- val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
- | superio_inb(sioaddr, SIO_REG_ADDR + 1);
- *addr = val & IOREGION_ALIGNMENT;
- if (*addr == 0) {
+ superio_select(gate, W83627EHF_LD_HWM);
+ val = (superio_inb(gate, SIO_REG_ADDR) << 8)
+ | superio_inb(gate, SIO_REG_ADDR + 1);
+ addr = val & IOREGION_ALIGNMENT;
+ if (addr == 0) {
printk(KERN_ERR DRVNAME ": Refusing to enable a Super-I/O "
"device with a base I/O port 0.\n");
- superio_exit(sioaddr);
+ my_superio_exit(gate);
return -ENODEV;
}
/* Activate logical device if needed */
- val = superio_inb(sioaddr, SIO_REG_ENABLE);
+ val = superio_inb(gate, SIO_REG_ENABLE);
if (!(val & 0x01)) {
printk(KERN_WARNING DRVNAME ": Forcibly enabling Super-I/O. "
"Sensor is probably unusable.\n");
- superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
+ superio_outb(gate, SIO_REG_ENABLE, val | 0x01);
}
- superio_exit(sioaddr);
- pr_info(DRVNAME ": Found %s chip at %#x\n", sio_name, *addr);
- sio_data->sioreg = sioaddr;
+ my_superio_exit(gate);
+ pr_info(DRVNAME ": Found %s chip at %#x\n", sio_name, addr);
+ sio_data->sioreg = gate->sioaddr;
return 0;
}
@@ -1496,7 +1483,7 @@ static struct platform_device *pdev;
static int __init sensors_w83627ehf_init(void)
{
int err;
- unsigned short address;
+ unsigned short address = 0;
struct resource res;
struct w83627ehf_sio_data sio_data;
@@ -1505,8 +1492,7 @@ static int __init sensors_w83627ehf_init
* when Super-I/O functions move to a separate file, the Super-I/O
* driver will probe 0x2e and 0x4e and auto-detect the presence of a
* w83627ehf hardware monitor, and call probe() */
- if (w83627ehf_find(0x2e, &address, &sio_data) &&
- w83627ehf_find(0x4e, &address, &sio_data))
+ if (w83627ehf_find(&sio_data))
return -ENODEV;
err = platform_driver_register(&w83627ehf_driver);
^ permalink raw reply [flat|nested] 19+ messages in thread* Re: [lm-sensors] [ patch .24-rc0 5/5 ] SuperIO locks coordinator -
2007-10-15 5:11 ` [ patch .24-rc0 5/5 ] SuperIO locks coordinator - use in other hwmon/*.c Jim Cromie
` (12 preceding siblings ...)
(?)
@ 2007-11-16 1:00 ` David Hubbard
-1 siblings, 0 replies; 19+ messages in thread
From: David Hubbard @ 2007-11-16 1:00 UTC (permalink / raw)
To: lm-sensors
[-- Attachment #1: Type: text/plain, Size: 3315 bytes --]
Hi Jim,
I pulled the w83627ehf.c patch out of patch #5, so patch #5 is
(mostly) unchanged, and then put some of the superio-locks.c changes
in patch #1 to support changes to w83627ehf. So w83627ehf changes are
in my patch #6, where I did the things we have talked about.
> > 1) This appears to be pasted in and needs to be updated for each driver:
> > printk(KERN_WARNING "pc87360: superio port not detected, "
> >
>
> fixed here, thanks
Full changelog for patches 1-5:
1. Patches are now based on 2.6.24-rc2-git5. Since this patchset
touches so many drivers, it needs some heavy testing. So I also made a
patchset for 2.6.24-rc2-mm1, and I can post that set if I've based off
the wrong kernel version. (Both patchsets are compile-tested.)
1. I renamed drivers/hwmon/superio_locks.c to
drivers/hwmon/superio-locks.c (it seems to be the convention)
2. I updated patch #3 and #5 to use DRVNAME
3. I trimmed down patch #5 so that new stuff is in patch #6
4. I added a parameter enter_exit_method to struct superio_search &
struct superio which specifies what enter method to use. 0 = default,
the exit_seq is sent to the superio-port in a sequence. 1 = register
offset is first byte, followed by value. So W83627EHF has an exit_seq
of [ 0, 2, 1, 2 ]. Other methods can be added, if there are other
chips as weird as the W83627EHF.
5. I looked around superio-locks.c and I couldn't find code to copy
enter_seq, exit_seq, devid_word, and ldn_addr from struct
superio_search to struct superio. I added something to do this at the
end of superio_probe_reserve().
6. I renamed struct superio_search devid_mask to devid_mask_inverse
7. I fixed a bug in superio-locks.h:
for (i = 0; i < SEQ_SZ && gate->enter_seq[i]; i++)
outb(gate->exit_seq[i], gate->sioaddr);
The termination condition in the for loop in superio_exit() checks
enter_seq for zeros. It should check exit_seq, like this:
for (i = 0; i < SEQ_SZ && gate->exit_seq[i]; i++)
outb(gate->exit_seq[i], gate->sioaddr);
Patch #6 is the stuff in w83627ehf.c:
8. I removed SIO_ID_MASK and used superio_devid() instead in
w83627ehf_find(), because the devid is saved after having been masked
by struct superio_search devid_mask_inverse. I initialize struct
superio_search with 0xF, instead of ~SIO_ID_MASK where SIO_ID_MASK was
0xFFF0.
9. I removed my_superio_exit(), since superio-locks.c can now do the
superio_exit() for the w83627ehf.
10. I removed SIO_REG_LDSEL and SIO_REG_DEVID, since they are part of
superio-locks.c now. Other drivers might be able to do this too.
11. I moved struct superio * gate into struct w83627ehf_sio_data,
where it replaces int sioreg there. int sioreg was where the probed
superio address was stored, so that's where the gate should be stored
now.
12. I use superio_inw to get the ISA address
13. I release the superio slot reservation after successfully probing
the device and finding its ISA address. The code that releases it is
at the end of sensors_w83627ehf_init().
14. w83627ehf_find() return value is the ISA address or a negative
error code, as we discussed.
I tested everything on a w83627ehf and it works ok. I can test on a
w83627dhg in a few days.
Jim, when you have some time, please test on the motherboards you have.
Jean, if you have a chance, can you please review these patches?
Regards,
David
[-- Attachment #2: 01_hwmon_superio_module.patch.txt --]
[-- Type: text/plain, Size: 12736 bytes --]
hwmon_superio_module
Applies on top of linux-2.6.24-rc2
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig
--- linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig 2007-11-15 15:24:06.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig 2007-11-15 15:24:11.000000000 -0800
@@ -763,4 +763,13 @@
a problem with I2C support and want to see more of what is going
on.
+config SUPERIO_LOCKS
+ tristate "Super-IO port sharing"
+ default n
+ help
+ This module provides a shared reservation for use by drivers
+ which need to share access to a multi-function device via
+ its superio port, and which register that port.
+
endif # HWMON
+
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/Makefile linux-2.6.24-rc2-git5/drivers/hwmon/Makefile
--- linux-2.6.24-rc2-git5/drivers/hwmon/Makefile 2007-11-15 15:24:18.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/Makefile 2007-11-15 16:28:23.000000000 -0800
@@ -73,3 +73,4 @@
EXTRA_CFLAGS += -DDEBUG
endif
+obj-$(CONFIG_SUPERIO_LOCKS) += superio-locks.o
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/superio-locks.c linux-2.6.24-rc2-git5/drivers/hwmon/superio-locks.c
--- linux-2.6.24-rc2-git5/drivers/hwmon/superio-locks.c 2007-11-09 15:10:02.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/superio-locks.c 2007-11-15 17:41:01.000000000 -0800
@@ -0,0 +1,240 @@
+
+#define DRVNAME "superio_locks"
+#define DEBUG 1
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/mutex.h>
+#include <linux/ioport.h>
+#include <linux/superio-locks.h>
+
+MODULE_AUTHOR("Jim Cromie <jim.cromie@gmail.com");
+MODULE_LICENSE("GPL");
+
+/*
+ * This module allows multiple driver modules to coordinate their use
+ * of a Super-IO port to control the multiple logical devices behind
+ * it. Drivers will superio_find() their port, and 2 such modules
+ * will share a slot containing the lock.
+ */
+static int max_locks = 3; /* 3 is enough for 90% uses */
+module_param(max_locks, int, 0);
+MODULE_PARM_DESC(max_locks,
+ " Number of sio-lock clients to serve (default=3)");
+
+static int paranoid;
+module_param(paranoid, int, 0);
+MODULE_PARM_DESC(paranoid,
+ " when true, fails if superio-port region is claimed");
+
+static struct superio *sio_locks;
+static struct mutex reservation_lock;
+
+#define SIO_DEVID_ADDR_STD 0x20
+#define SIO_LDN_ADDR_STD 0x07
+
+struct superio* superio_probe_reserve(const struct superio_search * const where,
+ int cmd_addr, int want_devid)
+{
+ struct superio *gate;
+ u16 devid_addr = where->devid_addr;
+ u16 mydevid;
+ int slot, rc, i;
+
+ if (!devid_addr)
+ devid_addr = SIO_DEVID_ADDR_STD;
+
+
+ /* send superio-enter sequence for devices which need them */
+ for (i = 0; i < SEQ_SZ && where->enter_seq[i]; i++)
+ outb(where->enter_seq[i], cmd_addr);
+
+ outb(devid_addr, cmd_addr);
+
+ /* sanity check that cmd-reg remembers the val just written
+ rc = inb(cmd_addr);
+ if (rc != (devid_addr & 0xFF)) {
+ pr_debug("cmd-reg absent at %x, got %x\n", cmd_addr, rc);
+ return NULL;
+ }
+ */
+ /* Read the device-id register(s), using cmd written above */
+ if (!where->devid_word) {
+ mydevid = inb(cmd_addr+1);
+ } else {
+ /* want 16 bit devid, so get it */
+ mydevid = inb(cmd_addr+1) << 8;
+ outb(devid_addr+1, cmd_addr);
+ mydevid |= inb(cmd_addr+1);
+ }
+
+ /* most drivers will ignore this mask (defaults to 0) so we invert it */
+ mydevid &= ~ where->devid_mask_inverse;
+ /* test for the desired device id value */
+ if (mydevid != want_devid) {
+ pr_debug("got devid %x, want %x\n", mydevid, want_devid);
+ return NULL;
+ }
+ /* find 1st unused slot */
+ for (slot = 0; slot < max_locks; slot++)
+ if (!sio_locks[slot].users) {
+ gate = &sio_locks[slot];
+ break;
+ }
+ if (slot >= max_locks) {
+ printk(KERN_ERR DRVNAME
+ ": No superio-locks left. increase max_locks\n");
+ return NULL;
+ }
+ /* grab the io-port region */
+ if (!request_region(cmd_addr, 2, DRVNAME)) {
+ printk(KERN_ERR DRVNAME
+ ": superio port region already claimed\n");
+ if (paranoid)
+ return NULL;
+ }
+
+ pr_debug("allocating slot %d, addr %x for device %x\n",
+ slot, cmd_addr, want_devid);
+
+ gate->sioaddr = cmd_addr;
+ gate->devid = want_devid;
+ gate->users = 1;
+ memcpy(gate->enter_seq, where->enter_seq, sizeof(gate->enter_seq));
+ memcpy(gate->exit_seq, where->exit_seq, sizeof(gate->exit_seq));
+ gate->devid_word = where->devid_word;
+ gate->ldn_addr = where->ldn_addr;
+
+ return gate;
+}
+/*
+ * superio_get() checks whether the desired SuperIO device has been
+ * reserved, and shares that reservation. Otherwize it calls
+ * superio_probe_reserve to make a new reservation.
+ */
+static struct superio* superio_get(const struct superio_search * const where,
+ int cmd_addr, int want_devid)
+{
+ int slot;
+ struct superio *gate;
+
+ /* share any already allocated lock for this cmd_addr, device-id */
+ for (slot = 0; slot < max_locks; slot++) {
+ gate = &sio_locks[slot];
+
+ if (gate->users && cmd_addr == gate->sioaddr
+ && want_devid == gate->devid) {
+
+ if (gate->users >= 255) {
+ pr_info("too many drivers sharing port %x\n",
+ gate->sioaddr);
+ return NULL;
+ }
+ gate->users++;
+ pr_debug("sharing port:%x dev:%x users:%d\n",
+ gate->sioaddr, gate->devid, gate->users);
+ return gate;
+ }
+ }
+ /* no existing reservation found */
+ return superio_probe_reserve(where, cmd_addr, want_devid);
+}
+
+/**
+ * superio_find: find a superio-port, share a reservation on it.
+ * @search-criterion : device-id addrs, values that driver supports.
+ * Description: searches for a superio-port with one of the specified
+ * device-ids at one of the command-addresses. If port is found,
+ * creates an sio-locks reservation, or shares the one previously
+ * created (by another user-driver)
+ */
+struct superio* superio_find(const struct superio_search * const where)
+{
+ int ci, di;
+ struct superio* gate = NULL;
+
+ mutex_lock(&reservation_lock);
+
+ for (ci = 0; ci < ARRAY_SIZE(where->cmdreg_addrs)
+ && where->cmdreg_addrs[ci]; ci++) {
+
+ for (di = 0; di < ARRAY_SIZE(where->device_ids)
+ && where->device_ids[di]; di++) {
+
+ gate = superio_get(where, where->cmdreg_addrs[ci],
+ where->device_ids[di]);
+ if (!gate) {
+ pr_debug("no devid:%x at port:%x\n",
+ where->device_ids[di],
+ where->cmdreg_addrs[ci]);
+ } else
+ goto OUT;
+ }
+ }
+OUT:
+ if (gate)
+ pr_info("found devid:%x port:%x users:%d\n",
+ gate->devid, gate->sioaddr, gate->users);
+
+ mutex_unlock(&reservation_lock);
+ return gate;
+}
+EXPORT_SYMBOL_GPL(superio_find);
+
+/**
+ * superio_release:
+ * @gate : sio-lock reservation
+ * Description: releases the sio-lock reservation taken previously.
+ */
+void superio_release(struct superio* const gate)
+{
+ mutex_lock(&reservation_lock);
+
+ if (gate < &sio_locks[0] || gate >= &sio_locks[max_locks]) {
+ printk(KERN_ERR
+ " superio: attempt to release corrupted superio-lock"
+ " %p vs %p\n", gate, &sio_locks);
+ mutex_unlock(&reservation_lock);
+ return;
+ }
+ if (!(--gate->users)) {
+ release_region(gate->sioaddr, 2);
+ pr_debug("releasing last user of superio-port %x\n",
+ gate->sioaddr);
+ } else
+ pr_debug("released superio-port %x user, now have %d\n",
+ gate->sioaddr, gate->users);
+
+
+ mutex_unlock(&reservation_lock);
+ return;
+}
+EXPORT_SYMBOL_GPL(superio_release);
+
+static int superio_locks_init_module(void)
+{
+ int i;
+
+ pr_debug("initializing with %d reservation slots\n", max_locks);
+ sio_locks = kzalloc(max_locks*sizeof(struct superio), GFP_KERNEL);
+ if (!sio_locks) {
+ printk(KERN_ERR "superio: no memory\n");
+ return -ENOMEM;
+ }
+ for (i = 0; i < max_locks; i++)
+ mutex_init(&sio_locks[i].lock);
+
+ mutex_init(&reservation_lock);
+ return 0;
+}
+
+static void superio_locks_cleanup_module(void)
+{
+ pr_debug("releasing %d superio reservation slots\n", max_locks);
+ kfree(sio_locks);
+}
+
+module_init(superio_locks_init_module);
+module_exit(superio_locks_cleanup_module);
diff -u linux-2.6.24-rc2-git5/include/linux/superio-locks.h linux-2.6.24-rc2-git5/include/linux/superio-locks.h
--- linux-2.6.24-rc2-git5/include/linux/superio-locks.h 2007-11-09 15:10:00.000000000 -0800
+++ linux-2.6.24-rc2-git5/include/linux/superio-locks.h 2007-11-15 19:30:14.000000000 -0800
@@ -0,0 +1,139 @@
+#include <linux/mutex.h>
+#include <asm/io.h>
+
+#define SEQ_SZ 8
+
+/* Super-IO ports are found in low-pin-count hardware (typically ISA,
+ * any others ?). They usually provide access to many functional
+ * units, so many drivers must share the superio port. This struct
+ * provides a lock that allows the drivers to coordinate access to
+ * that port.
+ */
+struct superio {
+ struct mutex lock; /* lock shared amongst user drivers */
+ u16 sioaddr; /* port's tested cmd-address */
+ u16 devid; /* devid found by the registering driver */
+ u16 users; /* count client drivers */
+ u8 enter_seq[SEQ_SZ]; /* activate the superio-port */
+ u8 exit_seq[SEQ_SZ]; /* idle the superio-port */
+ u8 enter_exit_method; /* for the occasional odd driver */
+ u8 devid_word; /* some devices have 2 byte device id */
+ u8 ldn_addr; /* logical device select reg */
+};
+
+struct superio_search {
+ u16 cmdreg_addrs[4]; /* maybe default to 0x2e, 0x4e */
+ u16 device_ids[8]; /* 0 ends scan early */
+ u16 devid_addr; /* LSB of device-id. default addr: 0x20 */
+ u16 devid_mask_inverse; /* dont-care bits */
+ u8 enter_seq[SEQ_SZ]; /* activate the superio-port */
+ u8 exit_seq[SEQ_SZ]; /* idle the superio-port */
+ u8 enter_exit_method; /* see superio_exit() */
+ u8 devid_word; /* some devices have 2 byte device id */
+ u8 ldn_addr; /* logical device select reg */
+};
+
+struct superio* superio_find(const struct superio_search * const where);
+void superio_release(struct superio* const gate);
+
+/* superio_inb(), superio_outb() are also former client funcs */
+
+static inline int superio_inb(struct superio * const sio_port, u8 reg)
+{
+ outb(reg, sio_port->sioaddr);
+ return inb(sio_port->sioaddr+1);
+}
+
+static inline void superio_outb(struct superio * const sio_port, u8 reg, u8 val)
+{
+ outb(reg, sio_port->sioaddr);
+ outb(val, sio_port->sioaddr+1);
+}
+
+static inline int superio_inw(struct superio * const sio_port, u8 reg)
+{
+ int val;
+
+ outb(reg++, sio_port->sioaddr);
+ val = inb(sio_port->sioaddr) << 8;
+ outb(reg, sio_port->sioaddr);
+ val |= inb(sio_port->sioaddr+1);
+
+ return val;
+}
+
+static inline int superio_inw2(struct superio * const sio_port, u8 reg)
+{
+ int val;
+
+ outb(reg++, sio_port->sioaddr);
+ val = inb(sio_port->sioaddr+1) << 8;
+ outb(reg, sio_port->sioaddr);
+ val |= inb(sio_port->sioaddr+1);
+
+ return val;
+}
+
+/* superio_enter() and superio_exit() were formerly implemented in the
+ * client drivers, and managed the superio port by sending idling &
+ * activation sequences, which differ per device. However, the
+ * protection was incomplete, since any driver would activate the port
+ * before using it, thus defeating the idling done by another driver
+ * to 'lock' the port. We therefore claim 'eminent domain', and
+ * re-implement them here to properly manage the mutex.
+ */
+
+static inline void superio_enter(struct superio * const gate)
+{
+ int i;
+ mutex_lock(&gate->lock);
+ for (i = 0; i < SEQ_SZ && gate->enter_seq[i]; i++)
+ outb(gate->enter_seq[i], gate->sioaddr);
+}
+
+static inline void superio_exit(struct superio * const gate)
+{
+ int i;
+ if (gate->enter_exit_method == 0) {
+ /* default exit method */
+ for (i = 0; i < SEQ_SZ && gate->exit_seq[i]; i++)
+ outb(gate->exit_seq[i], gate->sioaddr);
+ }
+ else if (gate->enter_exit_method == 1) {
+ /* exit_seq includes register offsets */
+ for (i = 0; i < (SEQ_SZ-1); i += 2) {
+ if (!gate->exit_seq[i] && !gate->exit_seq[i+1]) break;
+ outb(gate->exit_seq[i+1],
+ gate->sioaddr + gate->exit_seq[i]);
+ }
+ }
+ else printk(KERN_ERR "superio-locks: invalid enter_exit_method %u\n",
+ (unsigned) gate->enter_exit_method);
+ mutex_unlock(&gate->lock);
+}
+
+/* maybe dont need these 2 */
+
+static inline void superio_lock(struct superio * const sio_port)
+{
+ mutex_lock(&sio_port->lock);
+}
+
+static inline void superio_unlock(struct superio * const sio_port)
+{
+ mutex_unlock(&sio_port->lock);
+}
+
+
+static inline u16 superio_devid(struct superio * const gate)
+{
+ return gate->devid;
+}
+
+#define LPC_LDN 0x07 /* Logical device select register */
+
+static inline void superio_select(struct superio * const gate, int ld)
+{
+ superio_outb(gate, (gate->ldn_addr) ? gate->ldn_addr : LPC_LDN, ld);
+}
+
[-- Attachment #3: 02_hwmon_superio_w83627hf.patch.txt --]
[-- Type: text/plain, Size: 7611 bytes --]
hwmon-superio-w83627hf
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig
--- linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig 2007-11-15 15:24:11.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig 2007-11-15 15:52:36.000000000 -0800
@@ -686,6 +686,7 @@
config SENSORS_W83627HF
tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF"
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here you get support for the Winbond W836X7 series
of sensor chips: the W83627HF, W83627THF, W83637HF, W83687THF and
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/w83627hf.c linux-2.6.24-rc2-git5/drivers/hwmon/w83627hf.c
--- linux-2.6.24-rc2-git5/drivers/hwmon/w83627hf.c 2007-11-15 15:44:17.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/w83627hf.c 2007-11-15 17:51:47.000000000 -0800
@@ -50,6 +50,7 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/ioport.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
#include "lm75.h"
@@ -75,11 +76,6 @@
module_param(init, bool, 0);
MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
-/* modified from kernel/include/traps.c */
-static int REG; /* The register to read/write */
-#define DEV 0x07 /* Register: Logical device select */
-static int VAL; /* The value to read/write */
-
/* logical device numbers for superio_select (below) */
#define W83627HF_LD_FDC 0x00
#define W83627HF_LD_PRT 0x01
@@ -97,8 +93,6 @@
#define W83627HF_LD_ACPI 0x0a
#define W83627HF_LD_HWM 0x0b
-#define DEVID 0x20 /* Register: Device ID */
-
#define W83627THF_GPIO5_EN 0x30 /* w83627thf only */
#define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */
#define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */
@@ -107,47 +101,26 @@
#define W83687THF_VID_CFG 0xF0 /* w83687thf only */
#define W83687THF_VID_DATA 0xF1 /* w83687thf only */
-static inline void
-superio_outb(int reg, int val)
-{
- outb(reg, REG);
- outb(val, VAL);
-}
-
-static inline int
-superio_inb(int reg)
-{
- outb(reg, REG);
- return inb(VAL);
-}
-
-static inline void
-superio_select(int ld)
-{
- outb(DEV, REG);
- outb(ld, VAL);
-}
-
-static inline void
-superio_enter(void)
-{
- outb(0x87, REG);
- outb(0x87, REG);
-}
-
-static inline void
-superio_exit(void)
-{
- outb(0xAA, REG);
-}
+#define W627_DEVID 0x52
+#define W627THF_DEVID 0x82
+#define W697_DEVID 0x60
+#define W637_DEVID 0x70
+#define W687THF_DEVID 0x85
+
+#define WINB_ACT_REG 0x30
+#define WINB_BASE_REG 0x60
+
+static struct superio* gate;
+
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2e, 0x4e },
+ .device_ids = { W627_DEVID, W627THF_DEVID, W697_DEVID,
+ W637_DEVID, W687THF_DEVID, 0 },
+ .enter_seq = { 0x87, 0x87, 0 },
+ .exit_seq = { 0xAA, 0 },
+ .enter_exit_method = 0,
+};
-#define W627_DEVID 0x52
-#define W627THF_DEVID 0x82
-#define W697_DEVID 0x60
-#define W637_DEVID 0x70
-#define W687THF_DEVID 0x85
-#define WINB_ACT_REG 0x30
-#define WINB_BASE_REG 0x60
/* Constants specified below */
/* Alignment of the base address */
@@ -995,12 +968,10 @@
return sprintf(buf, "%s\n", data->name);
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
-
-static int __init w83627hf_find(int sioaddr, unsigned short *addr,
- struct w83627hf_sio_data *sio_data)
+
+static u16 __init w83627hf_find(struct w83627hf_sio_data *sio_data)
{
- int err = -ENODEV;
- u16 val;
+ u16 val, addr = 0;
static const __initdata char *names[] = {
"W83627HF",
@@ -1010,11 +981,15 @@
"W83687THF",
};
- REG = sioaddr;
- VAL = sioaddr + 1;
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING DRVNAME ": superio port not detected, "
+ "module not intalled.\n");
+ return 0;
+ }
+ superio_enter(gate);
+ val = superio_devid(gate);
- superio_enter();
- val= superio_inb(DEVID);
switch (val) {
case W627_DEVID:
sio_data->type = w83627hf;
@@ -1038,36 +1013,34 @@
goto exit;
}
- superio_select(W83627HF_LD_HWM);
+ superio_select(gate, W83627HF_LD_HWM);
force_addr &= WINB_ALIGNMENT;
if (force_addr) {
printk(KERN_WARNING DRVNAME ": Forcing address 0x%x\n",
force_addr);
- superio_outb(WINB_BASE_REG, force_addr >> 8);
- superio_outb(WINB_BASE_REG + 1, force_addr & 0xff);
+ superio_outb(gate, WINB_BASE_REG, force_addr >> 8);
+ superio_outb(gate, WINB_BASE_REG + 1, force_addr & 0xff);
}
- val = (superio_inb(WINB_BASE_REG) << 8) |
- superio_inb(WINB_BASE_REG + 1);
- *addr = val & WINB_ALIGNMENT;
- if (*addr == 0) {
+ val = superio_inw(gate, WINB_BASE_REG);
+ addr = val & WINB_ALIGNMENT;
+ if (addr == 0) {
printk(KERN_WARNING DRVNAME ": Base address not set, "
"skipping\n");
goto exit;
}
- val = superio_inb(WINB_ACT_REG);
+ val = superio_inb(gate, WINB_ACT_REG);
if (!(val & 0x01)) {
printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n");
- superio_outb(WINB_ACT_REG, val | 0x01);
+ superio_outb(gate, WINB_ACT_REG, val | 0x01);
}
- err = 0;
pr_info(DRVNAME ": Found %s chip at %#x\n",
- names[sio_data->type], *addr);
+ names[sio_data->type], addr);
exit:
- superio_exit();
- return err;
+ superio_exit(gate);
+ return addr;
}
#define VIN_UNIT_ATTRS(_X_) \
@@ -1337,18 +1310,18 @@
{
int res = 0xff, sel;
- superio_enter();
- superio_select(W83627HF_LD_GPIO5);
+ superio_enter(gate);
+ superio_select(gate, W83627HF_LD_GPIO5);
/* Make sure these GPIO pins are enabled */
- if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) {
+ if (!(superio_inb(gate, W83627THF_GPIO5_EN) & (1<<3))) {
dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
goto exit;
}
/* Make sure the pins are configured for input
There must be at least five (VRM 9), and possibly 6 (VRM 10) */
- sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f;
+ sel = superio_inb(gate, W83627THF_GPIO5_IOSR) & 0x3f;
if ((sel & 0x1f) != 0x1f) {
dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
"function\n");
@@ -1356,10 +1329,10 @@
}
dev_info(&pdev->dev, "Reading VID from GPIO5\n");
- res = superio_inb(W83627THF_GPIO5_DR) & sel;
+ res = superio_inb(gate, W83627THF_GPIO5_DR) & sel;
exit:
- superio_exit();
+ superio_exit(gate);
return res;
}
@@ -1367,26 +1340,26 @@
{
int res = 0xff;
- superio_enter();
- superio_select(W83627HF_LD_HWM);
+ superio_enter(gate);
+ superio_select(gate, W83627HF_LD_HWM);
/* Make sure these GPIO pins are enabled */
- if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) {
+ if (!(superio_inb(gate, W83687THF_VID_EN) & (1 << 2))) {
dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
goto exit;
}
/* Make sure the pins are configured for input */
- if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) {
+ if (!(superio_inb(gate, W83687THF_VID_CFG) & (1 << 4))) {
dev_dbg(&pdev->dev, "VID configured as output, "
"no VID function\n");
goto exit;
}
- res = superio_inb(W83687THF_VID_DATA) & 0x3f;
+ res = superio_inb(gate, W83687THF_VID_DATA) & 0x3f;
exit:
- superio_exit();
+ superio_exit(gate);
return res;
}
@@ -1669,8 +1642,8 @@
unsigned short address;
struct w83627hf_sio_data sio_data;
- if (w83627hf_find(0x2e, &address, &sio_data)
- && w83627hf_find(0x4e, &address, &sio_data))
+ address = w83627hf_find(&sio_data);
+ if (!address)
return -ENODEV;
err = platform_driver_register(&w83627hf_driver);
@@ -1692,6 +1665,8 @@
static void __exit sensors_w83627hf_exit(void)
{
+ if (gate)
+ superio_release(gate);
platform_device_unregister(pdev);
platform_driver_unregister(&w83627hf_driver);
}
[-- Attachment #4: 03_hwmon_superio_pc87360.patch.txt --]
[-- Type: text/plain, Size: 7701 bytes --]
hwmon-superio-pc87360
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig
--- linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig 2007-11-15 15:52:36.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig 2007-11-15 15:53:28.000000000 -0800
@@ -500,6 +500,7 @@
config SENSORS_PC87360
tristate "National Semiconductor PC87360 family"
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here you get access to the hardware monitoring
functions of the National Semiconductor PC8736x Super-I/O chips.
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/pc87360.c linux-2.6.24-rc2-git5/drivers/hwmon/pc87360.c
--- linux-2.6.24-rc2-git5/drivers/hwmon/pc87360.c 2007-11-15 15:53:01.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/pc87360.c 2007-11-15 16:11:56.000000000 -0800
@@ -41,6 +41,7 @@
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/hwmon-vid.h>
+#include <linux/superio-locks.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <asm/io.h>
@@ -50,6 +51,8 @@
static unsigned short extra_isa[3];
static u8 confreg[4];
+#define DRVNAME "pc87360"
+
static int init = 1;
module_param(init, int, 0);
MODULE_PARM_DESC(init,
@@ -64,10 +67,14 @@
*/
#define DEV 0x07 /* Register: Logical device select */
-#define DEVID 0x20 /* Register: Device ID */
#define ACT 0x30 /* Register: Device activation */
#define BASE 0x60 /* Register: Base address */
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2E, 0x4E },
+ .device_ids = { 0xE1, 0xE8, 0xE4, 0xE5, 0xE9, 0 },
+};
+
#define FSCM 0x09 /* Logical device: fans */
#define VLM 0x0d /* Logical device: voltages */
#define TMS 0x0e /* Logical device: temperatures */
@@ -77,24 +84,6 @@
#define LD_IN 1
#define LD_TEMP 2
-static inline void superio_outb(int sioaddr, int reg, int val)
-{
- outb(reg, sioaddr);
- outb(val, sioaddr+1);
-}
-
-static inline int superio_inb(int sioaddr, int reg)
-{
- outb(reg, sioaddr);
- return inb(sioaddr+1);
-}
-
-static inline void superio_exit(int sioaddr)
-{
- outb(0x02, sioaddr);
- outb(0x02, sioaddr+1);
-}
-
/*
* Logical devices
*/
@@ -237,7 +226,7 @@
static struct platform_driver pc87360_driver = {
.driver = {
.owner = THIS_MODULE,
- .name = "pc87360",
+ .name = DRVNAME,
},
.probe = pc87360_probe,
.remove = __devexit_p(pc87360_remove),
@@ -817,17 +806,22 @@
* Device detection, registration and update
*/
-static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses)
+static int __init pc87360_find(unsigned short *addresses)
{
u16 val;
- int i;
- int nrdev; /* logical device count */
+ int i, nrdev; /* logical device count */
- /* No superio_enter */
+ struct superio* const gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING DRVNAME ": superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
+ devid = gate->devid; /* Remember the device id */
/* Identify device */
- val = superio_inb(sioaddr, DEVID);
- switch (val) {
+ switch (devid) {
case 0xE1: /* PC87360 */
case 0xE8: /* PC87363 */
case 0xE4: /* PC87364 */
@@ -838,27 +832,25 @@
nrdev = 3;
break;
default:
- superio_exit(sioaddr);
+ superio_exit(gate);
return -ENODEV;
}
- /* Remember the device id */
- *devid = val;
for (i = 0; i < nrdev; i++) {
/* select logical device */
- superio_outb(sioaddr, DEV, logdev[i]);
+ superio_select(gate, logdev[i]);
- val = superio_inb(sioaddr, ACT);
+ val = superio_inb(gate, ACT);
if (!(val & 0x01)) {
- printk(KERN_INFO "pc87360: Device 0x%02x not "
+ printk(KERN_INFO DRVNAME ": Device 0x%02x not "
"activated\n", logdev[i]);
continue;
}
- val = (superio_inb(sioaddr, BASE) << 8)
- | superio_inb(sioaddr, BASE + 1);
+ val = (superio_inb(gate, BASE) << 8)
+ | superio_inb(gate, BASE + 1);
if (!val) {
- printk(KERN_INFO "pc87360: Base address not set for "
+ printk(KERN_INFO DRVNAME ": Base address not set for "
"device 0x%02x\n", logdev[i]);
continue;
}
@@ -866,36 +858,36 @@
addresses[i] = val;
if (i==0) { /* Fans */
- confreg[0] = superio_inb(sioaddr, 0xF0);
- confreg[1] = superio_inb(sioaddr, 0xF1);
+ confreg[0] = superio_inb(gate, 0xF0);
+ confreg[1] = superio_inb(gate, 0xF1);
#ifdef DEBUG
- printk(KERN_DEBUG "pc87360: Fan 1: mon=%d "
+ printk(KERN_DEBUG DRVNAME ": Fan 1: mon=%d "
"ctrl=%d inv=%d\n", (confreg[0]>>2)&1,
(confreg[0]>>3)&1, (confreg[0]>>4)&1);
- printk(KERN_DEBUG "pc87360: Fan 2: mon=%d "
+ printk(KERN_DEBUG DRVNAME ": Fan 2: mon=%d "
"ctrl=%d inv=%d\n", (confreg[0]>>5)&1,
(confreg[0]>>6)&1, (confreg[0]>>7)&1);
- printk(KERN_DEBUG "pc87360: Fan 3: mon=%d "
+ printk(KERN_DEBUG DRVNAME ": Fan 3: mon=%d "
"ctrl=%d inv=%d\n", confreg[1]&1,
(confreg[1]>>1)&1, (confreg[1]>>2)&1);
#endif
} else if (i==1) { /* Voltages */
/* Are we using thermistors? */
- if (*devid == 0xE9) { /* PC87366 */
+ if (devid == 0xE9) { /* PC87366 */
/* These registers are not logical-device
specific, just that we won't need them if
we don't use the VLM device */
- confreg[2] = superio_inb(sioaddr, 0x2B);
- confreg[3] = superio_inb(sioaddr, 0x25);
+ confreg[2] = superio_inb(gate, 0x2B);
+ confreg[3] = superio_inb(gate, 0x25);
if (confreg[2] & 0x40) {
- printk(KERN_INFO "pc87360: Using "
+ printk(KERN_INFO DRVNAME ": Using "
"thermistors for temperature "
"monitoring\n");
}
if (confreg[3] & 0xE0) {
- printk(KERN_INFO "pc87360: VID "
+ printk(KERN_INFO DRVNAME ": VID "
"inputs routed (mode %u)\n",
confreg[3] >> 5);
}
@@ -903,7 +895,8 @@
}
}
- superio_exit(sioaddr);
+ superio_exit(gate);
+ superio_release(gate); /* not needed for any post-load operations */
return 0;
}
@@ -912,7 +905,7 @@
int i;
struct pc87360_data *data;
int err = 0;
- const char *name = "pc87360";
+ const char *name = DRVNAME;
int use_thermistors = 0;
struct device *dev = &pdev->dev;
@@ -1409,10 +1402,10 @@
};
int err, i;
- pdev = platform_device_alloc("pc87360", address);
+ pdev = platform_device_alloc(DRVNAME, address);
if (!pdev) {
err = -ENOMEM;
- printk(KERN_ERR "pc87360: Device allocation failed\n");
+ printk(KERN_ERR DRVNAME ": Device allocation failed\n");
goto exit;
}
@@ -1423,7 +1416,7 @@
res.end = extra_isa[i] + PC87360_EXTENT - 1;
err = platform_device_add_resources(pdev, &res, 1);
if (err) {
- printk(KERN_ERR "pc87360: Device resource[%d] "
+ printk(KERN_ERR DRVNAME ": Device resource[%d] "
"addition failed (%d)\n", i, err);
goto exit_device_put;
}
@@ -1431,7 +1424,7 @@
err = platform_device_add(pdev);
if (err) {
- printk(KERN_ERR "pc87360: Device addition failed (%d)\n",
+ printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
err);
goto exit_device_put;
}
@@ -1449,12 +1442,8 @@
int err, i;
unsigned short address = 0;
- if (pc87360_find(0x2e, &devid, extra_isa)
- && pc87360_find(0x4e, &devid, extra_isa)) {
- printk(KERN_WARNING "pc87360: PC8736x not detected, "
- "module not inserted.\n");
+ if (pc87360_find(extra_isa))
return -ENODEV;
- }
/* Arbitrarily pick one of the addresses */
for (i = 0; i < 3; i++) {
@@ -1465,7 +1454,7 @@
}
if (address == 0x0000) {
- printk(KERN_WARNING "pc87360: No active logical device, "
+ printk(KERN_WARNING DRVNAME ": No active logical device, "
"module not inserted.\n");
return -ENODEV;
}
[-- Attachment #5: 04_hwmon_superio_pc8736x_gpio.patch.txt --]
[-- Type: text/plain, Size: 6091 bytes --]
hwmon-superio-pc8736x-gpio
diff -u linux-2.6.24-rc2-git5/drivers/char/Kconfig linux-2.6.24-rc2-git5/drivers/char/Kconfig
--- linux-2.6.24-rc2-git5/drivers/char/Kconfig 2007-11-15 15:54:57.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/char/Kconfig 2007-11-15 15:55:05.000000000 -0800
@@ -941,6 +941,7 @@
depends on X86
default SCx200_GPIO # mostly N
select NSC_GPIO # needed for support routines
+ select SUPERIO_LOCKS
help
Give userspace access to the GPIO pins on the National
Semiconductor PC-8736x (x=[03456]) SuperIO chip. The chip
diff -u linux-2.6.24-rc2-git5/drivers/char/pc8736x_gpio.c linux-2.6.24-rc2-git5/drivers/char/pc8736x_gpio.c
--- linux-2.6.24-rc2-git5/drivers/char/pc8736x_gpio.c 2007-11-15 15:54:12.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/char/pc8736x_gpio.c 2007-11-15 15:55:11.000000000 -0800
@@ -20,6 +20,7 @@
#include <linux/mutex.h>
#include <linux/nsc_gpio.h>
#include <linux/platform_device.h>
+#include <linux/superio-locks.h>
#include <asm/uaccess.h>
#define DEVNAME "pc8736x_gpio"
@@ -36,13 +37,12 @@
static unsigned pc8736x_gpio_base;
static u8 pc8736x_gpio_shadow[4];
-#define SIO_BASE1 0x2E /* 1st command-reg to check */
-#define SIO_BASE2 0x4E /* alt command-reg to check */
+static struct superio* gate;
-#define SIO_SID 0x20 /* SuperI/O ID Register */
-#define SIO_SID_VALUE 0xe9 /* Expected value in SuperI/O ID Register */
-
-#define SIO_CF1 0x21 /* chip config, bit0 is chip enable */
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2E, 0x4E },
+ .device_ids = { 0xE1, 0xE8, 0xE4, 0xE5, 0xE9, 0 },
+};
#define PC8736X_GPIO_RANGE 16 /* ioaddr range */
#define PC8736X_GPIO_CT 32 /* minors matching 4 8 bit ports */
@@ -52,6 +52,7 @@
#define SIO_GPIO_UNIT 0x7 /* unit number of GPIO */
#define SIO_VLM_UNIT 0x0D
#define SIO_TMS_UNIT 0x0E
+#define SIO_CF1 0x21 /* chip config, bit0 is chip enable */
/* config-space addrs to read/write each unit's runtime addr */
#define SIO_BASE_HADDR 0x60
@@ -62,7 +63,6 @@
#define SIO_GPIO_PIN_CONFIG 0xF1
#define SIO_GPIO_PIN_EVENT 0xF2
-static unsigned char superio_cmd = 0;
static unsigned char selected_device = 0xFF; /* bogus start val */
/* GPIO port runtime access, functionality */
@@ -76,35 +76,9 @@
static struct platform_device *pdev; /* use in dev_*() */
-static inline void superio_outb(int addr, int val)
-{
- outb_p(addr, superio_cmd);
- outb_p(val, superio_cmd + 1);
-}
-
-static inline int superio_inb(int addr)
-{
- outb_p(addr, superio_cmd);
- return inb_p(superio_cmd + 1);
-}
-
-static int pc8736x_superio_present(void)
-{
- /* try the 2 possible values, read a hardware reg to verify */
- superio_cmd = SIO_BASE1;
- if (superio_inb(SIO_SID) == SIO_SID_VALUE)
- return superio_cmd;
-
- superio_cmd = SIO_BASE2;
- if (superio_inb(SIO_SID) == SIO_SID_VALUE)
- return superio_cmd;
-
- return 0;
-}
-
static void device_select(unsigned devldn)
{
- superio_outb(SIO_UNIT_SEL, devldn);
+ superio_select(gate, devldn);
selected_device = devldn;
}
@@ -112,7 +86,7 @@
{
/* select GPIO port/pin from device minor number */
device_select(SIO_GPIO_UNIT);
- superio_outb(SIO_GPIO_PIN_SELECT,
+ superio_outb(gate, SIO_GPIO_PIN_SELECT,
((iminor << 1) & 0xF0) | (iminor & 0x7));
}
@@ -121,19 +95,19 @@
{
u32 config, new_config;
+ superio_enter(gate);
mutex_lock(&pc8736x_gpio_config_lock);
- device_select(SIO_GPIO_UNIT);
+ /* read pin's current config value */
select_pin(index);
-
- /* read current config value */
- config = superio_inb(func_slct);
+ config = superio_inb(gate, func_slct);
/* set new config */
new_config = (config & mask) | bits;
- superio_outb(func_slct, new_config);
+ superio_outb(gate, func_slct, new_config);
mutex_unlock(&pc8736x_gpio_config_lock);
+ superio_exit(gate);
return config;
}
@@ -259,40 +233,44 @@
rc = -ENODEV;
goto undo_platform_dev_alloc;
}
+ pc8736x_gpio_ops.dev = &pdev->dev;
+
dev_info(&pdev->dev, "NatSemi pc8736x GPIO Driver Initializing\n");
- if (!pc8736x_superio_present()) {
+ gate = superio_find(&where);
+ if (!gate) {
rc = -ENODEV;
- dev_err(&pdev->dev, "no device found\n");
+ dev_err(&pdev->dev, "no superio port found\n");
+ // goto err2;
goto undo_platform_dev_add;
}
- pc8736x_gpio_ops.dev = &pdev->dev;
/* Verify that chip and it's GPIO unit are both enabled.
My BIOS does this, so I take minimum action here
*/
- rc = superio_inb(SIO_CF1);
+ superio_enter(gate);
+ rc = superio_inb(gate, SIO_CF1);
if (!(rc & 0x01)) {
rc = -ENODEV;
dev_err(&pdev->dev, "device not enabled\n");
- goto undo_platform_dev_add;
+ goto undo_superio_enter;
}
device_select(SIO_GPIO_UNIT);
- if (!superio_inb(SIO_UNIT_ACT)) {
+ if (!superio_inb(gate, SIO_UNIT_ACT)) {
rc = -ENODEV;
dev_err(&pdev->dev, "GPIO unit not enabled\n");
- goto undo_platform_dev_add;
+ goto undo_superio_enter;
}
/* read the GPIO unit base addr that chip responds to */
- pc8736x_gpio_base = (superio_inb(SIO_BASE_HADDR) << 8
- | superio_inb(SIO_BASE_LADDR));
+ pc8736x_gpio_base = (superio_inb(gate, SIO_BASE_HADDR) << 8
+ | superio_inb(gate, SIO_BASE_LADDR));
if (!request_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE, DEVNAME)) {
rc = -ENODEV;
dev_err(&pdev->dev, "GPIO ioport %x busy\n",
pc8736x_gpio_base);
- goto undo_platform_dev_add;
+ goto undo_superio_enter;
}
dev_info(&pdev->dev, "GPIO ioport %x reserved\n", pc8736x_gpio_base);
@@ -319,10 +297,14 @@
cdev_init(&pc8736x_gpio_cdev, &pc8736x_gpio_fileops);
cdev_add(&pc8736x_gpio_cdev, devid, PC8736X_GPIO_CT);
+ superio_exit(gate); /* no release, we need to stay registered */
return 0;
undo_request_region:
release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE);
+undo_superio_enter:
+ superio_exit(gate);
+ superio_release(gate);
undo_platform_dev_add:
platform_device_del(pdev);
undo_platform_dev_alloc:
@@ -341,6 +323,7 @@
platform_device_del(pdev);
platform_device_put(pdev);
+ superio_release(gate);
}
module_init(pc8736x_gpio_init);
[-- Attachment #6: 05_hwmon_superio_others.patch.txt --]
[-- Type: text/plain, Size: 18070 bytes --]
hwmon-superio-others
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig
--- linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig 2007-11-15 15:53:28.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/Kconfig 2007-11-15 15:58:42.000000000 -0800
@@ -229,6 +229,7 @@
config SENSORS_F71805F
tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG"
depends on EXPERIMENTAL
+ select SUPERIO_LOCKS
help
If you say yes here you get support for hardware monitoring
features of the Fintek F71805F/FG, F71806F/FG and F71872F/FG
@@ -336,6 +337,7 @@
config SENSORS_IT87
tristate "ITE IT87xx and compatibles"
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here you get support for ITE IT8705F, IT8712F,
IT8716F, IT8718F and IT8726F sensor chips, and the SiS960 clone.
@@ -566,6 +568,7 @@
tristate "SMSC LPC47M192 and compatibles"
depends on I2C && EXPERIMENTAL
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here you get support for the temperature and
voltage sensors of the SMSC LPC47M192, LPC47M15x, LPC47M292
@@ -582,6 +585,7 @@
config SENSORS_SMSC47B397
tristate "SMSC LPC47B397-NC"
depends on EXPERIMENTAL
+ select SUPERIO_LOCKS
help
If you say yes here you get support for the SMSC LPC47B397-NC
sensor chip.
@@ -613,6 +617,7 @@
tristate "VIA VT1211"
depends on EXPERIMENTAL
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here then you get support for hardware monitoring
features of the VIA VT1211 Super-I/O chip.
@@ -699,6 +704,7 @@
config SENSORS_W83627EHF
tristate "Winbond W83627EHF/DHG"
select HWMON_VID
+ select SUPERIO_LOCKS
help
If you say yes here you get support for the hardware
monitoring functionality of the Winbond W83627EHF Super-I/O chip.
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/f71805f.c linux-2.6.24-rc2-git5/drivers/hwmon/f71805f.c
--- linux-2.6.24-rc2-git5/drivers/hwmon/f71805f.c 2007-11-15 15:57:33.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/f71805f.c 2007-11-15 17:50:48.000000000 -0800
@@ -39,6 +39,7 @@
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/ioport.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
static struct platform_device *pdev;
@@ -52,8 +53,6 @@
#define F71805F_LD_HWM 0x04
-#define SIO_REG_LDSEL 0x07 /* Logical device select */
-#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
#define SIO_REG_DEVREV 0x22 /* Device revision */
#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
#define SIO_REG_FNSEL1 0x29 /* Multi Function Select 1 (F71872F) */
@@ -64,43 +63,16 @@
#define SIO_F71805F_ID 0x0406
#define SIO_F71872F_ID 0x0341
-static inline int
-superio_inb(int base, int reg)
-{
- outb(reg, base);
- return inb(base + 1);
-}
-
-static int
-superio_inw(int base, int reg)
-{
- int val;
- outb(reg++, base);
- val = inb(base + 1) << 8;
- outb(reg, base);
- val |= inb(base + 1);
- return val;
-}
+static struct superio* gate;
-static inline void
-superio_select(int base, int ld)
-{
- outb(SIO_REG_LDSEL, base);
- outb(ld, base + 1);
-}
-
-static inline void
-superio_enter(int base)
-{
- outb(0x87, base);
- outb(0x87, base);
-}
-
-static inline void
-superio_exit(int base)
-{
- outb(0xaa, base);
-}
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2e, 0x4e },
+ .device_ids = { SIO_F71805F_ID, SIO_F71872F_ID, 0 },
+ .devid_word = 1,
+ .enter_seq = { 0x87, 0x87 },
+ .exit_seq = { 0xAA },
+ .enter_exit_method = 0,
+};
/*
* ISA constants
@@ -1480,31 +1452,33 @@
return err;
}
-static int __init f71805f_find(int sioaddr, unsigned short *address,
- struct f71805f_sio_data *sio_data)
+static int __init f71805f_find(struct f71805f_sio_data *sio_data)
{
int err = -ENODEV;
- u16 devid;
+ u16 devid, address;
static const char *names[] = {
"F71805F/FG",
"F71872F/FG or F71806F/FG",
};
-
- superio_enter(sioaddr);
-
- devid = superio_inw(sioaddr, SIO_REG_MANID);
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING DRVNAME ": superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
+ devid = superio_inw(gate, SIO_REG_MANID);
if (devid != SIO_FINTEK_ID)
goto exit;
- devid = superio_inw(sioaddr, SIO_REG_DEVID);
switch (devid) {
case SIO_F71805F_ID:
sio_data->kind = f71805f;
break;
case SIO_F71872F_ID:
sio_data->kind = f71872f;
- sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1);
+ sio_data->fnsel1 = superio_inb(gate, SIO_REG_FNSEL1);
break;
default:
printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
@@ -1512,28 +1486,28 @@
goto exit;
}
- superio_select(sioaddr, F71805F_LD_HWM);
- if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+ superio_select(gate, F71805F_LD_HWM);
+ if (!(superio_inb(gate, SIO_REG_ENABLE) & 0x01)) {
printk(KERN_WARNING DRVNAME ": Device not activated, "
"skipping\n");
goto exit;
}
- *address = superio_inw(sioaddr, SIO_REG_ADDR);
- if (*address == 0) {
+ address = superio_inw(gate, SIO_REG_ADDR);
+ if (address == 0) {
printk(KERN_WARNING DRVNAME ": Base address not set, "
"skipping\n");
goto exit;
}
- *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
+ address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */
err = 0;
printk(KERN_INFO DRVNAME ": Found %s chip at %#x, revision %u\n",
- names[sio_data->kind], *address,
- superio_inb(sioaddr, SIO_REG_DEVREV));
+ names[sio_data->kind], address,
+ superio_inb(gate, SIO_REG_DEVREV));
exit:
- superio_exit(sioaddr);
+ superio_exit(gate);
return err;
}
@@ -1543,8 +1517,7 @@
unsigned short address;
struct f71805f_sio_data sio_data;
- if (f71805f_find(0x2e, &address, &sio_data)
- && f71805f_find(0x4e, &address, &sio_data))
+ if (f71805f_find(&sio_data))
return -ENODEV;
err = platform_driver_register(&f71805f_driver);
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/it87.c linux-2.6.24-rc2-git5/drivers/hwmon/it87.c
--- linux-2.6.24-rc2-git5/drivers/hwmon/it87.c 2007-11-15 15:57:42.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/it87.c 2007-11-15 17:50:31.000000000 -0800
@@ -38,6 +38,7 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
#define DRVNAME "it87"
@@ -54,46 +55,6 @@
#define DEVID 0x20 /* Register: Device ID */
#define DEVREV 0x22 /* Register: Device Revision */
-static inline int
-superio_inb(int reg)
-{
- outb(reg, REG);
- return inb(VAL);
-}
-
-static int superio_inw(int reg)
-{
- int val;
- outb(reg++, REG);
- val = inb(VAL) << 8;
- outb(reg, REG);
- val |= inb(VAL);
- return val;
-}
-
-static inline void
-superio_select(int ldn)
-{
- outb(DEV, REG);
- outb(ldn, VAL);
-}
-
-static inline void
-superio_enter(void)
-{
- outb(0x87, REG);
- outb(0x01, REG);
- outb(0x55, REG);
- outb(0x55, REG);
-}
-
-static inline void
-superio_exit(void)
-{
- outb(0x02, REG);
- outb(0x02, VAL);
-}
-
/* Logical device 4 registers */
#define IT8712F_DEVID 0x8712
#define IT8705F_DEVID 0x8705
@@ -103,6 +64,18 @@
#define IT87_ACT_REG 0x30
#define IT87_BASE_REG 0x60
+static struct superio* gate;
+
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { REG, 0 },
+ .device_ids = { IT8712F_DEVID, IT8716F_DEVID, IT8718F_DEVID,
+ IT8705F_DEVID, IT8726F_DEVID, 0 },
+ .devid_word = 1,
+ .enter_seq = { 0x87, 0x01, 0x55, 0x55, 0 },
+ .exit_seq = { 0x02, 0x02, 0 },
+ .enter_exit_method = 0,
+};
+
/* Logical device 7 registers (IT8712F and later) */
#define IT87_SIO_PINX2_REG 0x2c /* Pin selection */
#define IT87_SIO_VID_REG 0xfc /* VID value */
@@ -890,10 +863,16 @@
{
int err = -ENODEV;
u16 chip_type;
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING DRVNAME ": superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
- superio_enter();
- chip_type = superio_inw(DEVID);
-
+ /* can get this from gate */
+ chip_type = superio_inw(gate, DEVID);
switch (chip_type) {
case IT8705F_DEVID:
sio_data->type = it87;
@@ -916,13 +895,13 @@
goto exit;
}
- superio_select(PME);
- if (!(superio_inb(IT87_ACT_REG) & 0x01)) {
+ superio_select(gate, PME);
+ if (!(superio_inb(gate, IT87_ACT_REG) & 0x01)) {
pr_info("it87: Device not activated, skipping\n");
goto exit;
}
- *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1);
+ *address = superio_inw(gate, IT87_BASE_REG) & ~(IT87_EXTENT - 1);
if (*address == 0) {
pr_info("it87: Base address not set, skipping\n");
goto exit;
@@ -930,17 +909,17 @@
err = 0;
pr_info("it87: Found IT%04xF chip at 0x%x, revision %d\n",
- chip_type, *address, superio_inb(DEVREV) & 0x0f);
+ chip_type, *address, superio_inb(gate, DEVREV) & 0x0f);
/* Read GPIO config and VID value from LDN 7 (GPIO) */
if (chip_type != IT8705F_DEVID) {
int reg;
- superio_select(GPIO);
+ superio_select(gate, GPIO);
if (chip_type == it8718)
- sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
+ sio_data->vid_value = superio_inb(gate, IT87_SIO_VID_REG);
- reg = superio_inb(IT87_SIO_PINX2_REG);
+ reg = superio_inb(gate, IT87_SIO_PINX2_REG);
if (reg & (1 << 0))
pr_info("it87: in3 is VCC (+5V)\n");
if (reg & (1 << 1))
@@ -948,7 +927,7 @@
}
exit:
- superio_exit();
+ superio_exit(gate);
return err;
}
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/smsc47b397.c linux-2.6.24-rc2-git5/drivers/hwmon/smsc47b397.c
--- linux-2.6.24-rc2-git5/drivers/hwmon/smsc47b397.c 2007-11-15 15:57:59.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/smsc47b397.c 2007-11-15 17:50:09.000000000 -0800
@@ -36,6 +36,7 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/mutex.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
static struct platform_device *pdev;
@@ -44,37 +45,6 @@
/* Super-I/0 registers and commands */
-#define REG 0x2e /* The register to read/write */
-#define VAL 0x2f /* The value to read/write */
-
-static inline void superio_outb(int reg, int val)
-{
- outb(reg, REG);
- outb(val, VAL);
-}
-
-static inline int superio_inb(int reg)
-{
- outb(reg, REG);
- return inb(VAL);
-}
-
-/* select superio logical device */
-static inline void superio_select(int ld)
-{
- superio_outb(0x07, ld);
-}
-
-static inline void superio_enter(void)
-{
- outb(0x55, REG);
-}
-
-static inline void superio_exit(void)
-{
- outb(0xAA, REG);
-}
-
#define SUPERIO_REG_DEVID 0x20
#define SUPERIO_REG_DEVREV 0x21
#define SUPERIO_REG_BASE_MSB 0x60
@@ -83,6 +53,16 @@
#define SMSC_EXTENT 0x02
+static struct superio* gate;
+
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2e, 0x4e },
+ .device_ids = { 0x6f, 0x81, 0 },
+ .enter_seq = { 0x55, 0 },
+ .exit_seq = { 0xAA, 0 },
+ .enter_exit_method = 0,
+};
+
/* 0 <= nr <= 3 */
static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
#define SMSC47B397_REG_TEMP(nr) (smsc47b397_reg_temp[(nr)])
@@ -332,26 +312,32 @@
{
u8 id, rev;
- superio_enter();
- id = superio_inb(SUPERIO_REG_DEVID);
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING DRVNAME ": superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
+ id = superio_inb(gate, SUPERIO_REG_DEVID);
if ((id != 0x6f) && (id != 0x81) && (id != 0x85)) {
- superio_exit();
+ superio_exit(gate);
return -ENODEV;
}
- rev = superio_inb(SUPERIO_REG_DEVREV);
+ rev = superio_inb(gate, SUPERIO_REG_DEVREV);
- superio_select(SUPERIO_REG_LD8);
- *addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8)
- | superio_inb(SUPERIO_REG_BASE_LSB);
+ superio_select(gate, SUPERIO_REG_LD8);
+ *addr = (superio_inb(gate, SUPERIO_REG_BASE_MSB) << 8)
+ | superio_inb(gate, SUPERIO_REG_BASE_LSB);
printk(KERN_INFO DRVNAME ": found SMSC %s "
"(base address 0x%04x, revision %u)\n",
id == 0x81 ? "SCH5307-NS" : id == 0x85 ? "SCH5317" :
"LPC47B397-NC", *addr, rev);
- superio_exit();
+ superio_exit(gate);
return 0;
}
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/smsc47m1.c linux-2.6.24-rc2-git5/drivers/hwmon/smsc47m1.c
--- linux-2.6.24-rc2-git5/drivers/hwmon/smsc47m1.c 2007-11-15 15:58:11.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/smsc47m1.c 2007-11-15 17:49:55.000000000 -0800
@@ -37,6 +37,7 @@
#include <linux/init.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
static struct platform_device *pdev;
@@ -46,41 +47,19 @@
/* Super-I/0 registers and commands */
-#define REG 0x2e /* The register to read/write */
-#define VAL 0x2f /* The value to read/write */
-
-static inline void
-superio_outb(int reg, int val)
-{
- outb(reg, REG);
- outb(val, VAL);
-}
-
-static inline int
-superio_inb(int reg)
-{
- outb(reg, REG);
- return inb(VAL);
-}
-
-/* logical device for fans is 0x0A */
-#define superio_select() superio_outb(0x07, 0x0A)
-
-static inline void
-superio_enter(void)
-{
- outb(0x55, REG);
-}
-
-static inline void
-superio_exit(void)
-{
- outb(0xAA, REG);
-}
-
#define SUPERIO_REG_ACT 0x30
#define SUPERIO_REG_BASE 0x60
-#define SUPERIO_REG_DEVID 0x20
+
+static struct superio* gate;
+
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2e, 0x4e },
+ .device_ids = { 0x51, 0x59, 0x5F, 0x60, 0x6B, 0 },
+ .devid_word = 1,
+ .enter_seq = { 0x55, 0 },
+ .exit_seq = { 0xAA, 0 },
+ .enter_exit_method = 0,
+};
/* Logical device registers */
@@ -398,8 +377,14 @@
{
u8 val;
- superio_enter();
- val = superio_inb(SUPERIO_REG_DEVID);
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING DRVNAME ": superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ superio_enter(gate);
+ val = superio_devid(gate);
/*
* SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
@@ -434,21 +419,20 @@
sio_data->type = smsc47m2;
break;
default:
- superio_exit();
+ superio_exit(gate);
return -ENODEV;
}
-
- superio_select();
- *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
- | superio_inb(SUPERIO_REG_BASE + 1);
- val = superio_inb(SUPERIO_REG_ACT);
+ superio_select(gate, 0x0A);
+ *addr = (superio_inb(gate, SUPERIO_REG_BASE) << 8)
+ | superio_inb(gate, SUPERIO_REG_BASE + 1);
+ val = superio_inb(gate, SUPERIO_REG_ACT);
if (*addr == 0 || (val & 0x01) == 0) {
pr_info(DRVNAME ": Device is disabled, will not use\n");
- superio_exit();
+ superio_exit(gate);
return -ENODEV;
}
- superio_exit();
+ superio_exit(gate);
return 0;
}
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/vt1211.c linux-2.6.24-rc2-git5/drivers/hwmon/vt1211.c
--- linux-2.6.24-rc2-git5/drivers/hwmon/vt1211.c 2007-11-15 15:58:18.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/vt1211.c 2007-11-15 17:49:40.000000000 -0800
@@ -32,6 +32,7 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/ioport.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
static int uch_config = -1;
@@ -195,34 +196,16 @@
/* VT1211 logical device numbers */
#define SIO_VT1211_LDN_HWMON 0x0b /* HW monitor */
-static inline void superio_outb(int sio_cip, int reg, int val)
-{
- outb(reg, sio_cip);
- outb(val, sio_cip + 1);
-}
-
-static inline int superio_inb(int sio_cip, int reg)
-{
- outb(reg, sio_cip);
- return inb(sio_cip + 1);
-}
+static struct superio* gate;
-static inline void superio_select(int sio_cip, int ldn)
-{
- outb(SIO_VT1211_LDN, sio_cip);
- outb(ldn, sio_cip + 1);
-}
-
-static inline void superio_enter(int sio_cip)
-{
- outb(0x87, sio_cip);
- outb(0x87, sio_cip);
-}
-
-static inline void superio_exit(int sio_cip)
-{
- outb(0xaa, sio_cip);
-}
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { SIO_REG_CIP1, SIO_REG_CIP2 },
+ .device_ids = { SIO_VT1211_ID, 0 },
+ .devid_addr = SIO_VT1211_DEVID,
+ .enter_seq = { 0x87, 0x87, 0 },
+ .exit_seq = { 0xAA, 0 },
+ .enter_exit_method = 0,
+};
/* ---------------------------------------------------------------------
* Device I/O access
@@ -1277,27 +1260,29 @@
return err;
}
-static int __init vt1211_find(int sio_cip, unsigned short *address)
+static int __init vt1211_find(void)
{
int err = -ENODEV;
+ u16 address;
- superio_enter(sio_cip);
-
- if (superio_inb(sio_cip, SIO_VT1211_DEVID) != SIO_VT1211_ID) {
- goto EXIT;
+ gate = superio_find(&where);
+ if (!gate) {
+ printk(KERN_WARNING DRVNAME ": superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
}
+ superio_enter(gate);
+ superio_select(gate, SIO_VT1211_LDN_HWMON);
- superio_select(sio_cip, SIO_VT1211_LDN_HWMON);
-
- if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) {
+ if ((superio_inb(gate, SIO_VT1211_ACTIVE) & 1) == 0) {
printk(KERN_WARNING DRVNAME ": HW monitor is disabled, "
"skipping\n");
goto EXIT;
}
- *address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) |
- (superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00;
- if (*address == 0) {
+ address = superio_inw(gate, SIO_VT1211_BADDR);
+
+ if (address == 0) {
printk(KERN_WARNING DRVNAME ": Base address is not set, "
"skipping\n");
goto EXIT;
@@ -1305,11 +1290,11 @@
err = 0;
printk(KERN_INFO DRVNAME ": Found VT1211 chip at 0x%04x, "
- "revision %u\n", *address,
- superio_inb(sio_cip, SIO_VT1211_DEVREV));
+ "revision %u\n", address,
+ superio_inb(gate, SIO_VT1211_DEVREV));
EXIT:
- superio_exit(sio_cip);
+ superio_exit(gate);
return err;
}
@@ -1318,10 +1303,8 @@
int err;
unsigned short address = 0;
- if ((err = vt1211_find(SIO_REG_CIP1, &address)) &&
- (err = vt1211_find(SIO_REG_CIP2, &address))) {
+ if ((err = vt1211_find()))
goto EXIT;
- }
if ((uch_config < -1) || (uch_config > 31)) {
err = -EINVAL;
[-- Attachment #7: 06_hwmon_superio_w83627ehf.patch.txt --]
[-- Type: text/plain, Size: 8339 bytes --]
hwmon-superio-w83627ehf
diff -u linux-2.6.24-rc2-git5/drivers/hwmon/w83627ehf.c linux-2.6.24-rc2-git5/drivers/hwmon/w83627ehf.c
--- linux-2.6.24-rc2-git5/drivers/hwmon/w83627ehf.c 2007-11-15 17:23:20.000000000 -0800
+++ linux-2.6.24-rc2-git5/drivers/hwmon/w83627ehf.c 2007-11-15 19:31:09.000000000 -0800
@@ -48,6 +48,7 @@
#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/superio-locks.h>
#include <asm/io.h>
#include "lm75.h"
@@ -67,8 +68,6 @@
#define W83627EHF_LD_HWM 0x0b
-#define SIO_REG_LDSEL 0x07 /* Logical device select */
-#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
#define SIO_REG_EN_VRM10 0x2C /* GPIO3, GPIO4 selection */
#define SIO_REG_ENABLE 0x30 /* Logical device enable */
#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
@@ -78,42 +77,18 @@
#define SIO_W83627EHF_ID 0x8850
#define SIO_W83627EHG_ID 0x8860
#define SIO_W83627DHG_ID 0xa020
-#define SIO_ID_MASK 0xFFF0
-static inline void
-superio_outb(int ioreg, int reg, int val)
-{
- outb(reg, ioreg);
- outb(val, ioreg + 1);
-}
-
-static inline int
-superio_inb(int ioreg, int reg)
-{
- outb(reg, ioreg);
- return inb(ioreg + 1);
-}
-static inline void
-superio_select(int ioreg, int ld)
-{
- outb(SIO_REG_LDSEL, ioreg);
- outb(ld, ioreg + 1);
-}
-
-static inline void
-superio_enter(int ioreg)
-{
- outb(0x87, ioreg);
- outb(0x87, ioreg);
-}
-
-static inline void
-superio_exit(int ioreg)
-{
- outb(0x02, ioreg);
- outb(0x02, ioreg + 1);
-}
+static __devinit struct superio_search where = {
+ .cmdreg_addrs = { 0x2E, 0x4E },
+ .device_ids = { SIO_W83627EHF_ID, SIO_W83627EHG_ID,
+ SIO_W83627DHG_ID, 0 },
+ .devid_mask_inverse = 0xF,
+ .devid_word = 1,
+ .enter_seq = { 0x87, 0x87, 0 },
+ .exit_seq = { 0, 2, 1, 2 },
+ .enter_exit_method = 1,
+};
/*
* ISA constants
@@ -295,11 +270,6 @@
u8 vrm;
};
-struct w83627ehf_sio_data {
- int sioreg;
- enum kinds kind;
-};
-
static inline int is_word_sized(u16 reg)
{
return (((reg & 0xff00) == 0x100
@@ -1239,11 +1209,17 @@
}
}
+struct w83627ehf_sio_data {
+ struct superio * gate;
+ enum kinds kind;
+};
+
static int __devinit w83627ehf_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct w83627ehf_sio_data *sio_data = dev->platform_data;
struct w83627ehf_data *data;
+ struct superio * gate = sio_data->gate;
struct resource *res;
u8 fan4pin, fan5pin, en_vrm10;
int i, err = 0;
@@ -1275,23 +1251,21 @@
w83627ehf_init_device(data);
data->vrm = vid_which_vrm();
- superio_enter(sio_data->sioreg);
+ superio_enter(gate);
/* Set VID input sensibility if needed. In theory the BIOS should
have set it, but in practice it's not always the case. */
- en_vrm10 = superio_inb(sio_data->sioreg, SIO_REG_EN_VRM10);
+ en_vrm10 = superio_inb(gate, SIO_REG_EN_VRM10);
if ((en_vrm10 & 0x08) && data->vrm != 100) {
dev_warn(dev, "Setting VID input voltage to TTL\n");
- superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
- en_vrm10 & ~0x08);
+ superio_outb(gate, SIO_REG_EN_VRM10, en_vrm10 & ~0x08);
} else if (!(en_vrm10 & 0x08) && data->vrm == 100) {
dev_warn(dev, "Setting VID input voltage to VRM10\n");
- superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
- en_vrm10 | 0x08);
+ superio_outb(gate, SIO_REG_EN_VRM10, en_vrm10 | 0x08);
}
/* Read VID value */
- superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
- if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80)
- data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA) & 0x3f;
+ superio_select(gate, W83627EHF_LD_HWM);
+ if (superio_inb(gate, SIO_REG_VID_CTRL) & 0x80)
+ data->vid = superio_inb(gate, SIO_REG_VID_DATA) & 0x3f;
else {
dev_info(dev, "VID pins in output mode, CPU VID not "
"available\n");
@@ -1300,9 +1274,9 @@
/* fan4 and fan5 share some pins with the GPIO and serial flash */
- fan5pin = superio_inb(sio_data->sioreg, 0x24) & 0x2;
- fan4pin = superio_inb(sio_data->sioreg, 0x29) & 0x6;
- superio_exit(sio_data->sioreg);
+ fan5pin = superio_inb(gate, 0x24) & 0x2;
+ fan4pin = superio_inb(gate, 0x29) & 0x6;
+ superio_exit(gate);
/* It looks like fan4 and fan5 pins can be alternatively used
as fan on/off switches, but fan5 control is write only :/
@@ -1424,22 +1398,26 @@
.remove = __devexit_p(w83627ehf_remove),
};
-/* w83627ehf_find() looks for a '627 in the Super-I/O config space */
-static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
- struct w83627ehf_sio_data *sio_data)
+/* w83627ehf_find() looks for a '627 in the Super-I/O config space. Return value
+ * is a negative number if an error occured, or else the ISA address */
+static resource_size_t __init w83627ehf_find(struct w83627ehf_sio_data *sio_data)
{
static const char __initdata sio_name_W83627EHF[] = "W83627EHF";
static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
- u16 val;
+ u16 val, addr;
const char *sio_name;
+ struct superio * gate = superio_find(&where);
- superio_enter(sioaddr);
+ if (!gate) {
+ printk(KERN_WARNING "pc87360: superio port not detected, "
+ "module not intalled.\n");
+ return -ENODEV;
+ }
+ sio_data->gate = gate;
- val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
- | superio_inb(sioaddr, SIO_REG_DEVID + 1);
- switch (val & SIO_ID_MASK) {
+ switch (superio_devid(gate)) {
case SIO_W83627EHF_ID:
sio_data->kind = w83627ehf;
sio_name = sio_name_W83627EHF;
@@ -1453,38 +1431,36 @@
sio_name = sio_name_W83627DHG;
break;
default:
- if (val != 0xffff)
+ if (superio_devid(gate) != 0xffff)
pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n",
- val);
- superio_exit(sioaddr);
+ superio_devid(gate));
+ superio_exit(gate);
return -ENODEV;
}
/* We have a known chip, find the HWM I/O address */
- superio_select(sioaddr, W83627EHF_LD_HWM);
- val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
- | superio_inb(sioaddr, SIO_REG_ADDR + 1);
- *addr = val & IOREGION_ALIGNMENT;
- if (*addr == 0) {
+ superio_select(gate, W83627EHF_LD_HWM);
+ val = superio_inw2(gate, SIO_REG_ADDR);
+ addr = val & IOREGION_ALIGNMENT;
+ if (addr == 0) {
printk(KERN_ERR DRVNAME ": Refusing to enable a Super-I/O "
"device with a base I/O port 0.\n");
- superio_exit(sioaddr);
+ superio_exit(gate);
return -ENODEV;
}
/* Activate logical device if needed */
- val = superio_inb(sioaddr, SIO_REG_ENABLE);
+ val = superio_inb(gate, SIO_REG_ENABLE);
if (!(val & 0x01)) {
printk(KERN_WARNING DRVNAME ": Forcibly enabling Super-I/O. "
"Sensor is probably unusable.\n");
- superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
+ superio_outb(gate, SIO_REG_ENABLE, val | 0x01);
}
- superio_exit(sioaddr);
- pr_info(DRVNAME ": Found %s chip at %#x\n", sio_name, *addr);
- sio_data->sioreg = sioaddr;
+ superio_exit(gate);
+ pr_info(DRVNAME ": Found %s chip at %#x\n", sio_name, addr);
- return 0;
+ return addr;
}
/* when Super-I/O functions move to a separate file, the Super-I/O
@@ -1496,7 +1472,7 @@
static int __init sensors_w83627ehf_init(void)
{
int err;
- unsigned short address;
+ resource_size_t address;
struct resource res;
struct w83627ehf_sio_data sio_data;
@@ -1505,13 +1481,13 @@
* when Super-I/O functions move to a separate file, the Super-I/O
* driver will probe 0x2e and 0x4e and auto-detect the presence of a
* w83627ehf hardware monitor, and call probe() */
- if (w83627ehf_find(0x2e, &address, &sio_data) &&
- w83627ehf_find(0x4e, &address, &sio_data))
- return -ENODEV;
+ address = w83627ehf_find(&sio_data);
+ if ((int) address < 0)
+ return address;
err = platform_driver_register(&w83627ehf_driver);
if (err)
- goto exit;
+ return err;
if (!(pdev = platform_device_alloc(DRVNAME, address))) {
err = -ENOMEM;
@@ -1546,13 +1522,18 @@
goto exit_device_put;
}
+ /* release superio-locks slot reservation */
+ superio_release(sio_data.gate);
+
+ /* gate in platform_data is no longer valid. null it out. */
+ ((struct w83627ehf_sio_data *) (pdev->dev.platform_data))->gate = 0;
+
return 0;
exit_device_put:
platform_device_put(pdev);
exit_unregister:
platform_driver_unregister(&w83627ehf_driver);
-exit:
return err;
}
[-- Attachment #8: Type: text/plain, Size: 153 bytes --]
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
^ permalink raw reply [flat|nested] 19+ messages in thread