]> git.sur5r.net Git - u-boot/blobdiff - cpu/mpc5xxx/i2c.c
GCC-4.x fixes: clean up global data pointer initialization for all boards.
[u-boot] / cpu / mpc5xxx / i2c.c
index 640d14022fcc84bd763ed68f00e869b4a493fcf9..0f02e78a3bd3e25d04459b50c0b36c5d0e79cdc1 100644 (file)
 
 #include <common.h>
 
+DECLARE_GLOBAL_DATA_PTR;
+
 #ifdef CONFIG_HARD_I2C
 
 #include <mpc5xxx.h>
 #include <i2c.h>
 
-#ifdef CFG_I2C_MODULE
+#if (CFG_I2C_MODULE == 2)
 #define I2C_BASE       MPC5XXX_I2C2
-#else
+#elif (CFG_I2C_MODULE == 1)
 #define I2C_BASE       MPC5XXX_I2C1
+#else
+#error CFG_I2C_MODULE is not properly configured
 #endif
 
 #define I2C_TIMEOUT    100
 #define I2C_RETRIES    3
 
+struct mpc5xxx_i2c_tap {
+       int scl2tap;
+       int tap2tap;
+};
+
 static int  mpc_reg_in    (volatile u32 *reg);
 static void mpc_reg_out   (volatile u32 *reg, int val, int mask);
 static int  wait_for_bb   (void);
@@ -44,11 +53,13 @@ static int  wait_for_pin  (int *status);
 static int  do_address    (uchar chip, char rdwr_flag);
 static int  send_bytes    (uchar chip, char *buf, int len);
 static int  receive_bytes (uchar chip, char *buf, int len);
+static int  mpc_get_fdr   (int);
 
 static int mpc_reg_in(volatile u32 *reg)
 {
-       return *reg >> 24;
+       int ret = *reg >> 24;
        __asm__ __volatile__ ("eieio");
+       return ret;
 }
 
 static void mpc_reg_out(volatile u32 *reg, int val, int mask)
@@ -125,13 +136,13 @@ static int do_address(uchar chip, char rdwr_flag)
        mpc_reg_out(&regs->mcr, I2C_TX, I2C_TX);
        mpc_reg_out(&regs->mdr, chip, 0);
 
-        if (wait_for_pin(&status)) {
-                return -2;
-        }
+       if (wait_for_pin(&status)) {
+               return -2;
+       }
 
-        if (status & I2C_RXAK) {
-                return -3;
-        }
+       if (status & I2C_RXAK) {
+               return -3;
+       }
 
        return 0;
 }
@@ -207,7 +218,7 @@ void i2c_init(int speed, int saddr)
 
        /* Set clock
         */
-       mpc_reg_out(&regs->mfdr, speed, 0);
+       mpc_reg_out(&regs->mfdr, mpc_get_fdr(speed), 0);
 
        /* Enable module
         */
@@ -217,6 +228,55 @@ void i2c_init(int speed, int saddr)
        return;
 }
 
+static int mpc_get_fdr(int speed)
+{
+       static int fdr = -1;
+
+       if (fdr == -1) {
+               ulong best_speed = 0;
+               ulong divider;
+               ulong ipb, scl;
+               ulong bestmatch = 0xffffffffUL;
+               int best_i = 0, best_j = 0, i, j;
+               int SCL_Tap[] = { 9, 10, 12, 15, 5, 6, 7, 8};
+               struct mpc5xxx_i2c_tap scltap[] = {
+                       {4, 1},
+                       {4, 2},
+                       {6, 4},
+                       {6, 8},
+                       {14, 16},
+                       {30, 32},
+                       {62, 64},
+                       {126, 128}
+               };
+
+               ipb = gd->ipb_clk;
+               for (i = 7; i >= 0; i--) {
+                       for (j = 7; j >= 0; j--) {
+                               scl = 2 * (scltap[j].scl2tap +
+                                       (SCL_Tap[i] - 1) * scltap[j].tap2tap + 2);
+                               if (ipb <= speed*scl) {
+                                       if ((speed*scl - ipb) < bestmatch) {
+                                               bestmatch = speed*scl - ipb;
+                                               best_i = i;
+                                               best_j = j;
+                                               best_speed = ipb/scl;
+                                       }
+                               }
+                       }
+               }
+               divider = (best_i & 3) | ((best_i & 4) << 3) | (best_j << 2);
+               if (gd->flags & GD_FLG_RELOC) {
+                       fdr = divider;
+               } else {
+                       printf("%ld kHz, ", best_speed / 1000);
+                       return divider;
+               }
+       }
+
+       return fdr;
+}
+
 int i2c_probe(uchar chip)
 {
        struct mpc5xxx_i2c *regs = (struct mpc5xxx_i2c *)I2C_BASE;
@@ -227,6 +287,7 @@ int i2c_probe(uchar chip)
 
                if (! do_address(chip, 0)) {
                        mpc_reg_out(&regs->mcr, 0, I2C_STA);
+                       udelay(500);
                        break;
                }
 
@@ -239,7 +300,7 @@ int i2c_probe(uchar chip)
 
 int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
 {
-       uchar                xaddr[4];
+       char                xaddr[4];
        struct mpc5xxx_i2c * regs        = (struct mpc5xxx_i2c *)I2C_BASE;
        int                  ret         = -1;
 
@@ -270,7 +331,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
                goto Done;
        }
 
-       if (receive_bytes(chip, buf, len)) {
+       if (receive_bytes(chip, (char *)buf, len)) {
                printf("i2c_read: receive_bytes failed\n");
                goto Done;
        }
@@ -283,7 +344,7 @@ Done:
 
 int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
 {
-       uchar               xaddr[4];
+       char               xaddr[4];
        struct mpc5xxx_i2c *regs        = (struct mpc5xxx_i2c *)I2C_BASE;
        int                 ret         = -1;
 
@@ -292,13 +353,13 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
        xaddr[2] = (addr >>  8) & 0xFF;
        xaddr[3] =  addr        & 0xFF;
 
-        if (wait_for_bb()) {
+       if (wait_for_bb()) {
                printf("i2c_write: bus is busy\n");
                goto Done;
        }
 
-        mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
-        if (do_address(chip, 0)) {
+       mpc_reg_out(&regs->mcr, I2C_STA, I2C_STA);
+       if (do_address(chip, 0)) {
                printf("i2c_write: failed to address chip\n");
                goto Done;
        }
@@ -308,7 +369,7 @@ int i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
                goto Done;
        }
 
-       if (send_bytes(chip, buf, len)) {
+       if (send_bytes(chip, (char *)buf, len)) {
                printf("i2c_write: send_bytes failed\n");
                goto Done;
        }
@@ -321,7 +382,7 @@ Done:
 
 uchar i2c_reg_read(uchar chip, uchar reg)
 {
-       char buf;
+       uchar buf;
 
        i2c_read(chip, reg, 1, &buf, 1);