From 7a6ba966ed5b53e46f6790d60a08bf849ca97a52 Mon Sep 17 00:00:00 2001 From: "Mark D. Studebaker" Date: Sat, 26 May 2001 21:23:40 +0000 Subject: [PATCH] Apply tristate patch from Jesus Arias which ensures i2c Bus is tristated correctly. It isn't clear from the datasheet if the 586's GPIO pins are open drain or not, but if they aren't, then the driver was driving the pins high rather than letting them get pulled high as the spec requires. This is corrected by toggling the direction rather than the data register to control the bus. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@1093 7894878c-1315-0410-8ee3-d5d059ff63e0 --- CHANGES | 1 + kernel/busses/i2c-via.c | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index 3d01f9ae..4190e9e4 100644 --- a/CHANGES +++ b/CHANGES @@ -40,6 +40,7 @@ ask CVS about it: Module i2c-i801: Chip detection cleanup Module i2c-i810: Fixed i2c_i810_init() not found in patched kernel Module i2c-sis5595: Allow force_addr=0xaddr; enable if not enabled. + Module i2c-via: Ensure i2c bus is tristated correctly. Module lm78: Recognize chipid=0x20 Module lm87: Fix in0, in1 (2.5V and Vccp1) calculations Module mtp008: Fix temp initializations; diff --git a/kernel/busses/i2c-via.c b/kernel/busses/i2c-via.c index a55066c2..b98a2669 100644 --- a/kernel/busses/i2c-via.c +++ b/kernel/busses/i2c-via.c @@ -63,16 +63,24 @@ static u16 pm_io_base; +/* + It does not appear from the datasheet that the GPIO pins are + open drain. So a we set a low value by setting the direction to + output and a high value by setting the direction to input and + relying on the required I2C pullup. The data value is initialized + to 0 in i2c_via_init() and never changed. +*/ + static void bit_via_setscl(void *data, int state) { - outb(state ? inb(I2C_OUT) | I2C_SCL : inb(I2C_OUT) & ~I2C_SCL, - I2C_OUT); + outb(state ? inb(I2C_DIR) & ~I2C_SCL : inb(I2C_DIR) | I2C_SCL, + I2C_DIR); } static void bit_via_setsda(void *data, int state) { - outb(state ? inb(I2C_OUT) | I2C_SDA : inb(I2C_OUT) & ~I2C_SDA, - I2C_OUT); + outb(state ? inb(I2C_DIR) & ~I2C_SDA : inb(I2C_DIR) | I2C_SDA, + I2C_DIR); } static int bit_via_getscl(void *data) @@ -179,15 +187,14 @@ int __init i2c_via_init(void) return -EBUSY; } else { request_region(I2C_DIR, IOSPACE, IOTEXT); - outb(inb(I2C_DIR) | I2C_SDA | I2C_SCL, I2C_DIR); - outb(inb(I2C_OUT) | I2C_SDA | I2C_SCL, I2C_OUT); + outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR); + outb(inb(I2C_OUT) & ~(I2C_SDA | I2C_SCL), I2C_OUT); } if (i2c_bit_add_bus(&bit_via_ops) == 0) { printk("i2c-via.o: Module succesfully loaded\n"); return 0; } else { - outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR); release_region(I2C_DIR, IOSPACE); printk ("i2c-via.o: Algo-bit error, couldn't register bus\n");