[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Another I2C issue



On Monday 23 June 2003 07:28, Mikael Starvik wrote:
> Thanks for all your work on the PCF8563 driver! We have had some minor
> problems with PCF8563 ourslef lately but has not yet had the time to
> investigate it. Would it be possible for you to send your latest i2c.c or a
> diff?

These are the things I needed to change:

-added i2c_sendnack
-i2c_readreg now uses sendnack instead of sendack

BTW, I also added i2c_sendnack in i2c.h, if multi byte readreg's are
implemented, we have to call i2c_sendnack ourselves

-leave clock low after i2c_inbyte. Maybe a i2c_dir_out() is needed as well,
but it works fine without...

-i2c_getack could cause some devices (like DS75, thermal watchdog) to
see a stop condition; data changed from low to high while clock was high.

I'm not too happy with the fact that the interrupts are disabled during a
readreg / writereg.
Are problems to be expected when the interrupts stay enabled?

This is a diff from the 2.4.20 kernel, with the devboard_82 patch applied.
Sorry I'm not too familiar with how to generate proper diffs, 
I placed my i2c.c in devboard_82/os, and did
diff -uNr linux-2.4.20/arch/cris/drivers/i2c.c ./i2c.c > i2c.patch

Please find i2c.patch attached.

Regards,

Pieter
--- linux-2.4.20/arch/cris/drivers/i2c.c	Sat Jun 14 18:43:54 2003
+++ ./i2c.c	Mon Jun 23 12:04:21 2003
@@ -11,6 +11,12 @@
 *! Jan 14 2000  Johan Adolfsson    Fixed PB shadow register stuff - 
 *!                                 don't use PB_I2C if DS1302 uses same bits,
 *!                                 use PB.
+*| June 23 2003 Pieter Grimmerink  Added 'i2c_sendnack'. i2c_readreg now
+*|                                 generates nack on last received byte, 
+*|                                 instead of ack.
+*|                                 i2c_getack changed data level while clock
+*|                                 was high, causing DS75 to see  a stop condition
+*|
 *! $Log: i2c.c,v $
 *! Revision 1.10  2003/04/01 14:12:06  starvik
 *! Added loglevel for lots of printks
@@ -302,6 +308,12 @@
 	}
 	i2c_clk(I2C_CLOCK_HIGH);
 	i2c_delay(CLOCK_HIGH_TIME);
+	
+	/*
+	 * we leave the clock low, getbyte is usually followed
+	 * by sendack/nack, they assume the clock to be low
+	 */
+	i2c_clk(I2C_CLOCK_LOW);
 	return aBitByte;
 }
 
@@ -363,6 +375,13 @@
 		i2c_delay(CLOCK_HIGH_TIME/2);
 	}
 
+   /*
+    * our clock is high now, make sure data is low
+    * before we enable our output. If we keep data high
+    * and enable output, we would generate a stop condition.
+    */
+   i2c_data(I2C_DATA_LOW);
+   
 	/*
 	 * end clock pulse
 	 */
@@ -420,6 +439,37 @@
 
 /*#---------------------------------------------------------------------------
 *#
+*# FUNCTION NAME: i2c_sendnack
+*#
+*# DESCRIPTION  : Sends NACK on received data
+*#
+*#--------------------------------------------------------------------------*/
+void
+i2c_sendnack(void)
+{
+	/*
+	 * enable output
+	 */
+	i2c_delay(CLOCK_LOW_TIME);
+	i2c_dir_out();
+	/*
+	 * set data high
+	 */
+	i2c_data(I2C_DATA_HIGH);
+	/*
+	 * generate clock pulse
+	 */
+	i2c_delay(CLOCK_HIGH_TIME/6);
+	i2c_clk(I2C_CLOCK_HIGH);
+	i2c_delay(CLOCK_HIGH_TIME);
+	i2c_clk(I2C_CLOCK_LOW);
+	i2c_delay(CLOCK_LOW_TIME);
+	
+	i2c_dir_in();
+}
+
+/*#---------------------------------------------------------------------------
+*#
 *# FUNCTION NAME: i2c_writereg
 *#
 *# DESCRIPTION  : Writes a value to an I2C device
@@ -549,9 +599,10 @@
 		 */
 		b = i2c_inbyte();
 		/*
-		 * send Ack
+		 * last received byte needs to be nacked
+		 * instead of acked
 		 */
-		i2c_sendack();
+		i2c_sendnack();
 		/*
 		 * end sequence
 		 */