From ded7e313b1c5d8d128977a3adc1d6a608ed44ae5 Mon Sep 17 00:00:00 2001 From: "Mark D. Studebaker" Date: Sun, 14 Dec 2003 00:54:10 +0000 Subject: [PATCH] add superio detection and driver support for it8712. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Subject: [PATCH] Re: SOLVED: Ticket #1409 Date: Fri, 03 Oct 2003 16:48:32 +0200 From: Bjørn Mork Organization: m To: Mark Studebaker CC: lm78@stimpy.netroedge.com, LM_Sensors developers References: 1 , 2 , 3 Bjørn Mork writes: > Mark Studebaker writes: > >> If you port over the super i/o code from one of the 3 drivers listed >> above >> and send us a patch we'll include it. > > OK. Will do. Here's the patch as promised. Took the code from smsc47m1.c. It currently only changes behaviour for the IT8712F since I cannot test on any other IT87-chips, and the comments in sensors-detect made me uncertain whether they really use the same key/exit sequence. Also changed sensors-detect somewhat to support longer devids and exit sequences. Don't know if you'll approve my perl though... Bjørn git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@2170 7894878c-1315-0410-8ee3-d5d059ff63e0 --- kernel/chips/it87.c | 84 ++++++++++++++++++++++++++++++++++++++ prog/detect/sensors-detect | 53 ++++++++++++++++-------- 2 files changed, 120 insertions(+), 17 deletions(-) diff --git a/kernel/chips/it87.c b/kernel/chips/it87.c index 3d6ecc26..a6c21fcc 100644 --- a/kernel/chips/it87.c +++ b/kernel/chips/it87.c @@ -63,6 +63,61 @@ static unsigned int normal_isa_range[] = { SENSORS_ISA_END }; SENSORS_INSMOD_4(it87, it8705, it8712, sis950); +#define REG 0x2e /* The register to read/write */ +#define DEV 0x07 /* Register: Logical device select */ +#define VAL 0x2f /* The value to read/write */ +#define PME 0x04 /* The device with the fan registers in it */ +#define DEVID 0x20 /* Register: Device ID */ + +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(void) +{ + outb(DEV, REG); + outb(PME, 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) +{ + /* safety precaution in case we put some other super IO chip + in config mode by accident */ + outb(0xAA, REG); + + /* documented exit sequence */ + outb(0x02, REG); + outb(0x02, VAL); +} + +/* just IT8712F for now - this should be extended to support the other + chips as well */ +#define IT87_DEVID_MATCH(id) ((id) == 0x8712) + +#define IT87_ACT_REG 0x30 +#define IT87_BASE_REG 0x60 + /* Update battery voltage after every reading if true */ static int update_vbat = 0; @@ -210,6 +265,7 @@ struct it87_data { static int it87_attach_adapter(struct i2c_adapter *adapter); +static int it87_find(int *address); static int it87_detect(struct i2c_adapter *adapter, int address, unsigned short flags, int kind); static int it87_detach_client(struct i2c_client *client); @@ -386,6 +442,29 @@ static int it87_attach_adapter(struct i2c_adapter *adapter) return i2c_detect(adapter, &addr_data, it87_detect); } +static int it87_find(int *address) +{ + u16 val; + + superio_enter(); + val = (superio_inb(DEVID) << 8) | + superio_inb(DEVID + 1); + if (!IT87_DEVID_MATCH(val)) { + superio_exit(); + return -ENODEV; + } + + superio_select(); + val = (superio_inb(IT87_BASE_REG) << 8) | + superio_inb(IT87_BASE_REG + 1); + superio_exit(); + *address = val & ~(IT87_EXTENT - 1); + if (*address == 0) { + return -ENODEV; + } + return 0; +} + /* This function is called by i2c_detect */ int it87_detect(struct i2c_adapter *adapter, int address, unsigned short flags, int kind) @@ -1036,7 +1115,12 @@ void it87_sens(struct i2c_client *client, int operation, int ctl_name, static int __init sm_it87_init(void) { + int addr; + printk("it87.o version %s (%s)\n", LM_VERSION, LM_DATE); + if (!it87_find(&addr)) { + normal_isa[0] = addr; + } return i2c_add_driver(&it87_driver); } diff --git a/prog/detect/sensors-detect b/prog/detect/sensors-detect index 7bf4285e..833417d0 100755 --- a/prog/detect/sensors-detect +++ b/prog/detect/sensors-detect @@ -1293,8 +1293,7 @@ use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect # actreg (optional): The activation register within the logical device # actmask (optional): The activation bit in the activation register # basereg: The I/O base register within the logical device -# exitreg: The register to write the exit value to -# exit: The value to write to the exit register to exit +# exitseq: Sequence of addr,val pairs which exits config modem # alias_detect (optional): For chips which can be both on the ISA and the # I2C bus, a function which detectes whether two entries are the same. # The function should take three parameters: The ISA address, the @@ -1305,19 +1304,34 @@ use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect # driver => "it87", # addrreg => 0x2e, # datareg => 0x2f, -# enter => [0x55, 0x01, 0x55, 0x55]. +# enter => [0x55, 0x01, 0x55, 0x55], # code doesn't handle multiple devid regs yet -# devidreg => [0x20, 0x21], -# devid => [0x87, 0x05], +# devidreg => 0x20, +# devid => 0x8705, # logdevreg => 0x07, # logdev => 0x04, # actreg => 0x30, # actmask => 0x01, # basereg => 0x60, -# exit is writing 0x01 to reg 0x02. - not compatible with other superio chips -# exitreg => 0x02, -# exit => 0x01, +# exit is writing 0x01(?) to reg 0x02. - not compatible with other superio chips +# exitseq => [0x2e, 0xaa, 0x2e, 0x02, 0x2f, 0x01], # }, + { + name => "ITE 8712F Super IO Sensors", + driver => "it87", + addrreg => 0x2e, + datareg => 0x2f, + enter => [0x87, 0x01, 0x55, 0x55], + devidreg => 0x20, + devid => 0x8712, + logdevreg => 0x07, + logdev => 0x04, + actreg => 0x30, + actmask => 0x01, + basereg => 0x60, +# exit is writing 0x02 to reg 0x02. - not compatible with other superio chips + exitseq => [0x2e, 0xaa, 0x2e, 0x02, 0x2f, 0x02], + }, # Nat'l untested # { # name => "Nat. Semi. PC87366 Super I/O Sensors", @@ -1333,8 +1347,7 @@ use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect # actmask => 0x01, # basereg => 0x60, # exit is writing 0x01 to reg 0x02. - not compatible with other superio chips -# exitreg => ?? none req'd?? -# exit => ?? +# exitseq => ??, # }, { name => "SMSC 47M10x Super IO Fan Sensors", @@ -1350,7 +1363,7 @@ use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect actreg => 0x20, actmask => 0x01, basereg => 0x60, - exit => 0xaa, + exitseq => [0x2e, 0xaa], }, { name => "SMSC 47M14x Super IO Fan Sensors", @@ -1366,7 +1379,7 @@ use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect actreg => 0x20, actmask => 0x01, basereg => 0x60, - exit => 0xaa, + exitseq => [0x2e, 0xaa], }, { name => "VT1211 Super IO Sensors", @@ -1382,7 +1395,7 @@ use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect actreg => 0x30, actmask => 0x01, basereg => 0x60, - exit => 0xaa, + exitseq => [0x2e, 0xaa], }, { name => "Winbond W83627HF Super IO Sensors", @@ -1398,7 +1411,7 @@ use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect actreg => 0x30, actmask => 0x01, basereg => 0x60, - exit => 0xaa, + exitseq => [0x2e, 0xaa], }, { name => "Winbond W83627THF Super IO Sensors", @@ -1430,7 +1443,7 @@ use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect actreg => 0x30, actmask => 0x01, basereg => 0x60, - exit => 0xaa, + exitseq => [0x2e, 0xaa], }, { name => "Winbond W83697HF Super IO Sensors", @@ -1462,7 +1475,7 @@ use subs qw(mtp008_detect lm78_detect lm78_isa_detect lm78_alias_detect actreg => 0x30, actmask => 0x01, basereg => 0x60, - exit => 0xaa, + exitseq => [0x2e, 0xaa], }, ); @@ -2345,6 +2358,10 @@ sub scan_superio # check the device ID outb($$chip{addrreg}, $$chip{devidreg}); $val = inb($$chip{datareg}); + if($$chip{devid}>0xff) { + outb($$chip{addrreg}, $$chip{devidreg} + 1); + $val = ($val << 8) | inb($$chip{datareg}); + } if($val == $$chip{devid}) { print " Success..."; # switch to the sensor logical device @@ -2384,7 +2401,9 @@ sub scan_superio printf " Failed! (0x%02x)\n", $val; } } - outb($$chip{exitreg}, $$chip{exit}); + while ($addr = shift(@{$$chip{exitseq}})) { + outb($addr, shift(@{$$chip{exitseq}})); + } } }