* Patch by Jon Loeliger, 15 Jul 2004:
authorwdenk <wdenk>
Tue, 28 Sep 2004 21:26:26 +0000 (21:26 +0000)
committerwdenk <wdenk>
Tue, 28 Sep 2004 21:26:26 +0000 (21:26 +0000)
  Fix MPC85xx I2C driver

CHANGELOG
cpu/mpc85xx/i2c.c

index 4e7e1e4b8f44e2fb1e5bbd5a3e51d62b26241587..ac634299e01f948e5f1051aa3c422d1c3073ccd1 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -2,6 +2,9 @@
 Changes since U-Boot 1.1.1:
 ======================================================================
 
+* Patch by Jon Loeliger, 15 Jul 2004:
+  Fix MPC85xx I2C driver
+
 * Fix problems with CDROM drive as slave device on Lite5200 IDE bus.
 
 * Patch by Stephen Williams, 15 July 2004
index ae08d18832195b852452a4870818b8736e32af6f..2d0848799584164a7468948e1fc94ae9af541218 100644 (file)
 
 #include <common.h>
 #include <command.h>
-
-#define DEBUG
-
-#if defined(DEBUG)
-#define DEB(x)      x
-#else
-#define DEB(x)
-#endif
+#include <asm/io.h>
 
 #ifdef CONFIG_HARD_I2C
 #include <i2c.h>
 
 #define TIMEOUT (CFG_HZ/4)
 
-#define I2C_Addr ((unsigned *)(CFG_CCSRBAR + 0x3000))
+#define I2C_Addr ((u8 *)(CFG_CCSRBAR + 0x3000))
 
 #define I2CADR  &I2C_Addr[0]
-#define I2CFDR  &I2C_Addr[1]
-#define I2CCCR  &I2C_Addr[2]
-#define I2CCSR  &I2C_Addr[3]
-#define I2CCDR  &I2C_Addr[4]
-#define I2CDFSRR &I2C_Addr[5]
+#define I2CFDR  &I2C_Addr[4]
+#define I2CCCR  &I2C_Addr[8]
+#define I2CCSR  &I2C_Addr[12]
+#define I2CCDR  &I2C_Addr[16]
+#define I2CDFSRR &I2C_Addr[20]
 
 #define I2C_READ  1
 #define I2C_WRITE 0
 
-/* taken from linux include/asm-ppc/io.h */
-inline unsigned in_le32(volatile unsigned *addr)
+void
+i2c_init(int speed, int slaveadd)
 {
-  unsigned ret;
+       /* stop I2C controller */
+       writeb(0x0, I2CCCR);
 
-  __asm__ __volatile__("lwbrx %0,0,%1;\n"
-                      "twi 0,%0,0;\n"
-                      "isync" : "=r" (ret) :
-                      "r" (addr), "m" (*addr));
-  return ret;
-}
+       /* set clock */
+       writeb(0x3f, I2CFDR);
 
-inline void out_le32(volatile unsigned *addr, int val)
-{
-  __asm__ __volatile__("stwbrx %1,0,%2; eieio" : "=m" (*addr) :
-                      "r" (val), "r" (addr));
-}
+       /* set default filter */
+       writeb(0x10,I2CDFSRR);
 
-#define writel(val, addr) out_le32(addr, val)
-#define readl(addr) in_le32(addr)
+       /* write slave address */
+       writeb(slaveadd, I2CADR);
 
-void
-i2c_init(int speed, int slaveadd)
-{
-  /* stop I2C controller */
-  writel (0x0, I2CCCR);
-  /* set clock */
-  writel (0x3f, I2CFDR);
-  /* set default filter */
-  writel (0x10,I2CDFSRR);
-  /* write slave address */
-  writel (slaveadd, I2CADR);
-  /* clear status register */
-  writel (0x0, I2CCSR);
-  /* start I2C controller */
-  writel (MPC85xx_I2CCR_MEN, I2CCCR);
+       /* clear status register */
+       writeb(0x0, I2CCSR);
+
+       /* start I2C controller */
+       writeb(MPC85xx_I2CCR_MEN, I2CCCR);
 }
 
 static __inline__ int
 i2c_wait4bus (void)
 {
-  ulong timeval = get_timer (0);
+       ulong timeval = get_timer (0);
 
-  while (readl (I2CCSR) & MPC85xx_I2CSR_MBB)
-    if (get_timer (timeval) > TIMEOUT)
-      return -1;
+       while (readb(I2CCSR) & MPC85xx_I2CSR_MBB) {
+               if (get_timer (timeval) > TIMEOUT) {
+                       return -1;
+               }
+       }
 
   return 0;
 }
@@ -109,153 +88,151 @@ i2c_wait4bus (void)
 static __inline__ int
 i2c_wait (int write)
 {
-  u32 csr;
-  ulong timeval = get_timer (0);
+       u32 csr;
+       ulong timeval = get_timer (0);
 
-  do
-    {
-      csr  = readl (I2CCSR);
+       do {
+               csr = readb(I2CCSR);
 
-      if (!(csr & MPC85xx_I2CSR_MIF))
-       continue;
+               if (!(csr & MPC85xx_I2CSR_MIF))
+                       continue;
 
-      writel (0x0, I2CCSR);
+               writeb(0x0, I2CCSR);
 
-      if (csr & MPC85xx_I2CSR_MAL)
-       {
-         DEB(printf ("i2c_wait: MAL\n"));
-         return -1;
-       }
+               if (csr & MPC85xx_I2CSR_MAL) {
+                       debug("i2c_wait: MAL\n");
+                       return -1;
+               }
 
-      if (!(csr & MPC85xx_I2CSR_MCF))
-       {
-         DEB(printf ("i2c_wait: unfinished\n"));
-         return -1;
-       }
+               if (!(csr & MPC85xx_I2CSR_MCF)) {
+                       debug("i2c_wait: unfinished\n");
+                       return -1;
+               }
 
-      if (write == I2C_WRITE && (csr & MPC85xx_I2CSR_RXAK))
-       {
-         DEB(printf ("i2c_wait: No RXACK\n"));
-         return -1;
-       }
+               if (write == I2C_WRITE && (csr & MPC85xx_I2CSR_RXAK)) {
+                       debug("i2c_wait: No RXACK\n");
+                       return -1;
+               }
 
-      return 0;
-    } while (get_timer (timeval) < TIMEOUT);
+               return 0;
+       } while (get_timer (timeval) < TIMEOUT);
 
-  DEB(printf ("i2c_wait: timed out\n"));
-  return -1;
+       debug("i2c_wait: timed out\n");
+       return -1;
 }
 
 static __inline__ int
 i2c_write_addr (u8 dev, u8 dir, int rsta)
 {
-  writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX |
-         (rsta?MPC85xx_I2CCR_RSTA:0), I2CCCR);
+       writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX |
+              (rsta?MPC85xx_I2CCR_RSTA:0),
+              I2CCCR);
 
-  writel ((dev << 1) | dir, I2CCDR);
+       writeb((dev << 1) | dir, I2CCDR);
 
-  if (i2c_wait (I2C_WRITE) < 0)
-    return 0;
+       if (i2c_wait (I2C_WRITE) < 0)
+               return 0;
 
-  return 1;
+       return 1;
 }
 
 static __inline__ int
 __i2c_write (u8 *data, int length)
 {
-  int i;
+       int i;
 
-  writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX, I2CCCR);
+       writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA | MPC85xx_I2CCR_MTX,
+              I2CCCR);
 
-  for (i=0; i < length; i++)
-    {
-      writel (data[i], I2CCDR);
+       for (i=0; i < length; i++) {
+               writeb(data[i], I2CCDR);
 
-      if (i2c_wait (I2C_WRITE) < 0)
-       break;
-    }
+               if (i2c_wait (I2C_WRITE) < 0)
+                       break;
+       }
 
-  return i;
+       return i;
 }
 
 static __inline__ int
 __i2c_read (u8 *data, int length)
 {
-  int i;
+       int i;
 
-  writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
-         ((length == 1) ? MPC85xx_I2CCR_TXAK : 0), I2CCCR);
+       writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
+              ((length == 1) ? MPC85xx_I2CCR_TXAK : 0),
+              I2CCCR);
 
-  /* dummy read */
-  readl (I2CCDR);
+       /* dummy read */
+       readb(I2CCDR);
 
-  for (i=0; i < length; i++)
-    {
-      if (i2c_wait (I2C_READ) < 0)
-       break;
+       for (i=0; i < length; i++) {
+               if (i2c_wait (I2C_READ) < 0)
+                       break;
 
-      /* Generate ack on last next to last byte */
-      if (i == length - 2)
-       writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
-               MPC85xx_I2CCR_TXAK, I2CCCR);
+               /* Generate ack on last next to last byte */
+               if (i == length - 2)
+                       writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_MSTA |
+                              MPC85xx_I2CCR_TXAK,
+                              I2CCCR);
 
-      /* Generate stop on last byte */
-      if (i == length - 1)
-       writel (MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_TXAK, I2CCCR);
+               /* Generate stop on last byte */
+               if (i == length - 1)
+                       writeb(MPC85xx_I2CCR_MEN | MPC85xx_I2CCR_TXAK, I2CCCR);
 
-      data[i] = readl (I2CCDR);
-    }
+               data[i] = readb(I2CCDR);
+       }
 
-  return i;
+       return i;
 }
 
 int
 i2c_read (u8 dev, uint addr, int alen, u8 *data, int length)
 {
-  int i = 0;
-  u8 *a = (u8*)&addr;
+       int i = 0;
+       u8 *a = (u8*)&addr;
 
-  if (i2c_wait4bus () < 0)
-    goto exit;
+       if (i2c_wait4bus () < 0)
+               goto exit;
 
-  if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
-    goto exit;
+       if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+               goto exit;
 
-  if (__i2c_write (&a[4 - alen], alen) != alen)
-    goto exit;
+       if (__i2c_write (&a[4 - alen], alen) != alen)
+               goto exit;
 
-  if (i2c_write_addr (dev, I2C_READ, 1) == 0)
-    goto exit;
+       if (i2c_write_addr (dev, I2C_READ, 1) == 0)
+               goto exit;
 
-  i = __i2c_read (data, length);
+       i = __i2c_read (data, length);
 
  exit:
-  writel (MPC85xx_I2CCR_MEN, I2CCCR);
+       writeb(MPC85xx_I2CCR_MEN, I2CCCR);
 
-  return !(i == length);
+       return !(i == length);
 }
 
 int
 i2c_write (u8 dev, uint addr, int alen, u8 *data, int length)
 {
-  int i = 0;
-  u8 *a = (u8*)&addr;
+       int i = 0;
+       u8 *a = (u8*)&addr;
 
-  if (i2c_wait4bus () < 0)
-    goto exit;
+       if (i2c_wait4bus () < 0)
+               goto exit;
 
-  if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
-    goto exit;
+       if (i2c_write_addr (dev, I2C_WRITE, 0) == 0)
+               goto exit;
 
-  if (__i2c_write (&a[4 - alen], alen) != alen)
-    goto exit;
+       if (__i2c_write (&a[4 - alen], alen) != alen)
+               goto exit;
 
-  i = __i2c_write (data, length);
+       i = __i2c_write (data, length);
 
  exit:
-  writel (MPC85xx_I2CCR_MEN, I2CCCR);
+       writeb(MPC85xx_I2CCR_MEN, I2CCCR);
 
-  return !(i == length);
+       return !(i == length);
 }
 
 int i2c_probe (uchar chip)