From ad7c7e2834fd15b4294b88c7b8e01ae127bc43d9 Mon Sep 17 00:00:00 2001 From: Philip Edelbrock Date: Fri, 7 May 1999 06:20:59 +0000 Subject: [PATCH] (Phil) Voodoo3 I2C bus driver works and now properly detects missed 'acks' during a transaction. It also can detect a 'hung' bus prior to starting a transaction. It seems to properly read and write to the BT869. Todo: support for multiple voodoo3 cards. Support for other transaction types (fairly simple). Use code as a start for a better algo-bit adapter template? Complete the bt869 driver. git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@452 7894878c-1315-0410-8ee3-d5d059ff63e0 --- kernel/busses/i2c-voodoo3.c | 107 ++++++++++++++++++++++++------------ kernel/chips/bt869.c | 4 +- 2 files changed, 76 insertions(+), 35 deletions(-) diff --git a/kernel/busses/i2c-voodoo3.c b/kernel/busses/i2c-voodoo3.c index 863cf274..b515c1b4 100644 --- a/kernel/busses/i2c-voodoo3.c +++ b/kernel/busses/i2c-voodoo3.c @@ -111,14 +111,13 @@ inline int rdat(void) void Voodoo3_I2CStart(void) { - dat(1); - out(); + dat(0); clkon(); out(); - dat(0); out(); clkoff(); out(); + clkon(); } void Voodoo3_I2CStop(void) @@ -129,38 +128,41 @@ void Voodoo3_I2CStop(void) out(); dat(1); out(); + clkoff(); + out(); + clkon(); + out(); } -int Voodoo3_I2CAck(int ack) +int Voodoo3_I2CAck() { -/* dat(ack); +int ack; + + dat(1); /* put data line in tristate/hi */ + clkon(); out(); - clkon();/ - out(); testing PAE */ ack=rdat(); clkoff(); out(); return ack; + } -int Voodoo3_I2CReadByte(int ack) +int Voodoo3_I2CReadByte() { int i,temp; unsigned char data=0; - clkoff(); - dat(1); - out(); for (i=7; i>=0; i--) { + out(); clkon(); - out(); data|=(rdat()<0x%X!\n",temp); + printk("i2c-voodoo3: Readbyte ack -->0x%X, read result -->0x%X\n",temp,data); #endif if (! temp) return data; @@ -171,49 +173,84 @@ int Voodoo3_I2CReadByte(int ack) int Voodoo3_I2CSendByte(unsigned char data) { - int i; - - clkoff(); - dat(0); - out(); + int i,temp; for (i=7; i>=0; i--) { - dat(data&(1<0x%X\n",temp); +#endif + return temp; +} + + +int Voodoo3_BusCheck(void) { +/* Check the bus to see if it is in use */ + + if (! rdat()) { + printk("i2c-voodoo3: I2C bus in use or hung! Try again later.\n"); + return 1; + } + return 0; } /* Note, this is actually a byte read and not a byte_data read */ /* I.e., the command value is dumped. */ -int Voodoo3_I2CRead(int adr,int command) +int Voodoo3_I2CRead(int addr,int command) { - int i,j,dat; + int dat=0; Voodoo3_I2CStart(); - Voodoo3_I2CSendByte(adr); - dat=Voodoo3_I2CReadByte(1); - Voodoo3_I2CStop(); + if (Voodoo3_I2CSendByte(addr)) { #ifdef DEBUG - printk("i2c-voodoo3: Byte read at addr:0x%X (command:0x%X) result:0x%X\n",adr,command,dat); + printk("i2c-voodoo3: No Ack on addr WriteByte to addr 0x%X\n",addr); +#endif + dat=-1; + goto ENDREAD; } + dat=Voodoo3_I2CReadByte(); +ENDREAD: Voodoo3_I2CStop(); +#ifdef DEBUG + printk("i2c-voodoo3: Byte read at addr:0x%X (command:0x%X) result:0x%X\n",addr,command,dat); #endif return dat; } -void Voodoo3_I2CWrite(int addr,int command,int data) +int Voodoo3_I2CWrite(int addr,int command,int data) { +int temp=0; + Voodoo3_I2CStart(); - Voodoo3_I2CSendByte(addr); - Voodoo3_I2CSendByte(command); - Voodoo3_I2CSendByte(data); - Voodoo3_I2CStop(); + if (Voodoo3_I2CSendByte(addr)) { +#ifdef DEBUG + printk("i2c-voodoo3: No Ack on addr WriteByte to addr 0x%X\n",addr); +#endif + temp=-1; + goto ENDWRITE; } + if (Voodoo3_I2CSendByte(command)) { +#ifdef DEBUG + printk("i2c-voodoo3: No Ack on command WriteByte to addr 0x%X\n",addr); +#endif + temp=-1; + goto ENDWRITE; } + if (Voodoo3_I2CSendByte(data)) { +#ifdef DEBUG + printk("i2c-voodoo3: No Ack on data WriteByte to addr 0x%X\n",addr); +#endif + } + temp=-1; +ENDWRITE: Voodoo3_I2CStop(); #ifdef DEBUG printk("i2c-voodoo3: Byte write at addr:0x%X command:0x%X data:0x%X\n",addr,command,data); #endif + return temp; } void config_v3(struct pci_dev *dev, int num) @@ -268,6 +305,8 @@ s32 voodoo3_access(u8 addr, char read_write, { int temp; + if (Voodoo3_BusCheck()) return -1; + if ((size == SMBUS_BYTE_DATA) || (size == SMBUS_BYTE)) { addr=((addr & 0x7f) << 1) | (read_write & 0x01); if (read_write == SMBUS_READ) { @@ -283,7 +322,7 @@ int temp; printk("i2c-voodoo3: access returning 0x%X\n",data->byte); #endif } else { - Voodoo3_I2CWrite(addr,command,data->byte); + return Voodoo3_I2CWrite(addr,command,data->byte); } return 0; } else { return -1; } /* The rest isn't implemented yet */ diff --git a/kernel/chips/bt869.c b/kernel/chips/bt869.c index fdc24573..597c0a21 100644 --- a/kernel/chips/bt869.c +++ b/kernel/chips/bt869.c @@ -31,6 +31,8 @@ /* Addresses to scan */ static unsigned short normal_i2c[] = {SENSORS_I2C_END}; + +/* also can be on 0x45 */ static unsigned short normal_i2c_range[] = {0x44,0x45,SENSORS_I2C_END}; static unsigned int normal_isa[] = {SENSORS_ISA_END}; static unsigned int normal_isa_range[] = {SENSORS_ISA_END}; @@ -169,7 +171,7 @@ printk("bt869.o: probing address %d .\n",address); new_client->addr,0xC4,0); /* set status bank 0 */ cur = smbus_read_byte_data(adapter,address,0); printk("bt869.o: address 0x%X testing-->0x%X\n",address,cur); - if ((cur | 0x27) != 0x27) + if (cur != 0x22) goto ERROR1; /* Determine the chip type */