Add support to use second and third I2C bus, too.

Bus 0 is still the default, but by calling i2c_set_bus_num(1/2) before doing
I2C accesses, code can switch to bus 1 and 2, too. Don't forget to switch
back afterwards, then. 

Signed-off-by: Dirk Behme <dirk.be...@googlemail.com>
---

Based on Hugo Vincent's patch

http://lists.denx.de/pipermail/u-boot/2009-June/055029.html

(this patch only contains the multibus support)

Compile tested with omap2_beagle and omap2420h4_config.

Boot tested with Zippy (I2C bus 1).

 drivers/i2c/omap24xx_i2c.c          |  170 +++++++++++++++++++++---------------
 include/asm-arm/arch-omap24xx/i2c.h |   53 +++++++----
 include/asm-arm/arch-omap3/i2c.h    |   50 +++++++---
 3 files changed, 175 insertions(+), 98 deletions(-)

Index: u-boot-main/drivers/i2c/omap24xx_i2c.c
===================================================================
--- u-boot-main.orig/drivers/i2c/omap24xx_i2c.c
+++ u-boot-main/drivers/i2c/omap24xx_i2c.c
@@ -29,6 +29,15 @@ static void wait_for_bb (void);
 static u16 wait_for_pin (void);
 static void flush_fifo(void);
 
+static struct i2c *i2c_base = (struct i2c *)I2C_DEFAULT_BASE;
+
+static unsigned int bus_initialized[I2C_BUS_MAX] = {0,
+#if I2C_BUS_MAX==3
+                                                   0,
+#endif
+                                                   0};
+static unsigned int current_bus = 0;
+
 void i2c_init (int speed, int slaveadd)
 {
        int psc, fsscll, fssclh;
@@ -95,30 +104,32 @@ void i2c_init (int speed, int slaveadd)
                sclh = (unsigned int)fssclh;
        }
 
-       writew(0x2, I2C_SYSC); /* for ES2 after soft reset */
+       writew(0x2, &i2c_base->sysc); /* for ES2 after soft reset */
        udelay(1000);
-       writew(0x0, I2C_SYSC); /* will probably self clear but */
+       writew(0x0, &i2c_base->sysc); /* will probably self clear but */
 
-       if (readw (I2C_CON) & I2C_CON_EN) {
-               writew (0, I2C_CON);
+       if (readw (&i2c_base->con) & I2C_CON_EN) {
+               writew (0, &i2c_base->con);
                udelay (50000);
        }
 
-       writew(psc, I2C_PSC);
-       writew(scll, I2C_SCLL);
-       writew(sclh, I2C_SCLH);
+       writew(psc, &i2c_base->psc);
+       writew(scll, &i2c_base->scll);
+       writew(sclh, &i2c_base->sclh);
 
        /* own address */
-       writew (slaveadd, I2C_OA);
-       writew (I2C_CON_EN, I2C_CON);
+       writew (slaveadd, &i2c_base->oa);
+       writew (I2C_CON_EN, &i2c_base->con);
 
        /* have to enable intrrupts or OMAP i2c module doesn't work */
        writew (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
-               I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
+               I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie);
        udelay (1000);
        flush_fifo();
-       writew (0xFFFF, I2C_STAT);
-       writew (0, I2C_CNT);
+       writew (0xFFFF, &i2c_base->stat);
+       writew (0, &i2c_base->cnt);
+
+       bus_initialized[current_bus] = 1;
 }
 
 static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
@@ -130,19 +141,19 @@ static int i2c_read_byte (u8 devaddr, u8
        wait_for_bb ();
 
        /* one byte only */
-       writew (1, I2C_CNT);
+       writew (1, &i2c_base->cnt);
        /* set slave address */
-       writew (devaddr, I2C_SA);
+       writew (devaddr, &i2c_base->sa);
        /* no stop bit needed here */
-       writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
+       writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, 
&i2c_base->con);
 
        status = wait_for_pin ();
 
        if (status & I2C_STAT_XRDY) {
                /* Important: have to use byte access */
-               writeb (regoffset, I2C_DATA);
+               writeb (regoffset, &i2c_base->data);
                udelay (20000);
-               if (readw (I2C_STAT) & I2C_STAT_NACK) {
+               if (readw (&i2c_base->stat) & I2C_STAT_NACK) {
                        i2c_error = 1;
                }
        } else {
@@ -151,28 +162,28 @@ static int i2c_read_byte (u8 devaddr, u8
 
        if (!i2c_error) {
                /* free bus, otherwise we can't use a combined transction */
-               writew (0, I2C_CON);
-               while (readw (I2C_STAT) || (readw (I2C_CON) & I2C_CON_MST)) {
+               writew (0, &i2c_base->con);
+               while (readw (&i2c_base->stat) || (readw (&i2c_base->con) & 
I2C_CON_MST)) {
                        udelay (10000);
                        /* Have to clear pending interrupt to clear I2C_STAT */
-                       writew (0xFFFF, I2C_STAT);
+                       writew (0xFFFF, &i2c_base->stat);
                }
 
                wait_for_bb ();
                /* set slave address */
-               writew (devaddr, I2C_SA);
+               writew (devaddr, &i2c_base->sa);
                /* read one byte from slave */
-               writew (1, I2C_CNT);
+               writew (1, &i2c_base->cnt);
                /* need stop bit here */
                writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
-                       I2C_CON);
+                       &i2c_base->con);
 
                status = wait_for_pin ();
                if (status & I2C_STAT_RRDY) {
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
-                       *value = readb (I2C_DATA);
+                       *value = readb (&i2c_base->data);
 #else
-                       *value = readw (I2C_DATA);
+                       *value = readw (&i2c_base->data);
 #endif
                        udelay (20000);
                } else {
@@ -180,17 +191,17 @@ static int i2c_read_byte (u8 devaddr, u8
                }
 
                if (!i2c_error) {
-                       writew (I2C_CON_EN, I2C_CON);
-                       while (readw (I2C_STAT)
-                              || (readw (I2C_CON) & I2C_CON_MST)) {
+                       writew (I2C_CON_EN, &i2c_base->con);
+                       while (readw (&i2c_base->stat)
+                              || (readw (&i2c_base->con) & I2C_CON_MST)) {
                                udelay (10000);
-                               writew (0xFFFF, I2C_STAT);
+                               writew (0xFFFF, &i2c_base->stat);
                        }
                }
        }
        flush_fifo();
-       writew (0xFFFF, I2C_STAT);
-       writew (0, I2C_CNT);
+       writew (0xFFFF, &i2c_base->stat);
+       writew (0, &i2c_base->cnt);
        return i2c_error;
 }
 
@@ -203,12 +214,12 @@ static int i2c_write_byte (u8 devaddr, u
        wait_for_bb ();
 
        /* two bytes */
-       writew (2, I2C_CNT);
+       writew (2, &i2c_base->cnt);
        /* set slave address */
-       writew (devaddr, I2C_SA);
+       writew (devaddr, &i2c_base->sa);
        /* stop bit needed here */
        writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
-               I2C_CON_STP, I2C_CON);
+               I2C_CON_STP, &i2c_base->con);
 
        /* wait until state change */
        status = wait_for_pin ();
@@ -216,24 +227,24 @@ static int i2c_write_byte (u8 devaddr, u
        if (status & I2C_STAT_XRDY) {
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
                /* send out 1 byte */
-               writeb (regoffset, I2C_DATA);
-               writew (I2C_STAT_XRDY, I2C_STAT);
+               writeb (regoffset, &i2c_base->data);
+               writew (I2C_STAT_XRDY, &i2c_base->stat);
 
                status = wait_for_pin ();
                if ((status & I2C_STAT_XRDY)) {
                        /* send out next 1 byte */
-                       writeb (value, I2C_DATA);
-                       writew (I2C_STAT_XRDY, I2C_STAT);
+                       writeb (value, &i2c_base->data);
+                       writew (I2C_STAT_XRDY, &i2c_base->stat);
                } else {
                        i2c_error = 1;
                }
 #else
                /* send out two bytes */
-               writew ((value << 8) + regoffset, I2C_DATA);
+               writew ((value << 8) + regoffset, &i2c_base->data);
 #endif
                /* must have enough delay to allow BB bit to go low */
                udelay (50000);
-               if (readw (I2C_STAT) & I2C_STAT_NACK) {
+               if (readw (&i2c_base->stat) & I2C_STAT_NACK) {
                        i2c_error = 1;
                }
        } else {
@@ -243,18 +254,18 @@ static int i2c_write_byte (u8 devaddr, u
        if (!i2c_error) {
                int eout = 200;
 
-               writew (I2C_CON_EN, I2C_CON);
-               while ((stat = readw (I2C_STAT)) || (readw (I2C_CON) & 
I2C_CON_MST)) {
+               writew (I2C_CON_EN, &i2c_base->con);
+               while ((stat = readw (&i2c_base->stat)) || (readw 
(&i2c_base->con) & I2C_CON_MST)) {
                        udelay (1000);
                        /* have to read to clear intrrupt */
-                       writew (0xFFFF, I2C_STAT);
+                       writew (0xFFFF, &i2c_base->stat);
                        if(--eout == 0) /* better leave with error than hang */
                                break;
                }
        }
        flush_fifo();
-       writew (0xFFFF, I2C_STAT);
-       writew (0, I2C_CNT);
+       writew (0xFFFF, &i2c_base->stat);
+       writew (0, &i2c_base->cnt);
        return i2c_error;
 }
 
@@ -265,14 +276,14 @@ static void flush_fifo(void)
         * you get a bus error
         */
        while(1){
-               stat = readw(I2C_STAT);
+               stat = readw(&i2c_base->stat);
                if(stat == I2C_STAT_RRDY){
 #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
-                       readb(I2C_DATA);
+                       readb(&i2c_base->data);
 #else
-                       readw(I2C_DATA);
+                       readw(&i2c_base->data);
 #endif
-                       writew(I2C_STAT_RRDY,I2C_STAT);
+                       writew(I2C_STAT_RRDY,&i2c_base->stat);
                        udelay(1000);
                }else
                        break;
@@ -283,7 +294,7 @@ int i2c_probe (uchar chip)
 {
        int res = 1; /* default = fail */
 
-       if (chip == readw (I2C_OA)) {
+       if (chip == readw (&i2c_base->oa)) {
                return res;
        }
 
@@ -291,27 +302,27 @@ int i2c_probe (uchar chip)
        wait_for_bb ();
 
        /* try to read one byte */
-       writew (1, I2C_CNT);
+       writew (1, &i2c_base->cnt);
        /* set slave address */
-       writew (chip, I2C_SA);
+       writew (chip, &i2c_base->sa);
        /* stop bit needed here */
-       writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
+       writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, 
&i2c_base->con);
        /* enough delay for the NACK bit set */
        udelay (50000);
 
-       if (!(readw (I2C_STAT) & I2C_STAT_NACK)) {
+       if (!(readw (&i2c_base->stat) & I2C_STAT_NACK)) {
                res = 0;      /* success case */
                flush_fifo();
-               writew(0xFFFF, I2C_STAT);
+               writew(0xFFFF, &i2c_base->stat);
        } else {
-               writew(0xFFFF, I2C_STAT);        /* failue, clear sources*/
-               writew (readw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up 
xfer */
+               writew(0xFFFF, &i2c_base->stat);         /* failue, clear 
sources*/
+               writew (readw (&i2c_base->con) | I2C_CON_STP, &i2c_base->con); 
/* finish up xfer */
                udelay(20000);
                wait_for_bb ();
        }
        flush_fifo();
-       writew (0, I2C_CNT); /* don't allow any more data in...we don't want 
it.*/
-       writew(0xFFFF, I2C_STAT);
+       writew (0, &i2c_base->cnt); /* don't allow any more data in...we don't 
want it.*/
+       writew(0xFFFF, &i2c_base->stat);
        return res;
 }
 
@@ -370,17 +381,17 @@ static void wait_for_bb (void)
        int timeout = 10;
        u16 stat;
 
-       writew(0xFFFF, I2C_STAT);        /* clear current interruts...*/
-       while ((stat = readw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
-               writew (stat, I2C_STAT);
+       writew(0xFFFF, &i2c_base->stat);         /* clear current interruts...*/
+       while ((stat = readw (&i2c_base->stat) & I2C_STAT_BB) && timeout--) {
+               writew (stat, &i2c_base->stat);
                udelay (50000);
        }
 
        if (timeout <= 0) {
                printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
-                       readw (I2C_STAT));
+                       readw (&i2c_base->stat));
        }
-       writew(0xFFFF, I2C_STAT);        /* clear delayed stuff*/
+       writew(0xFFFF, &i2c_base->stat);         /* clear delayed stuff*/
 }
 
 static u16 wait_for_pin (void)
@@ -390,7 +401,7 @@ static u16 wait_for_pin (void)
 
        do {
                udelay (1000);
-               status = readw (I2C_STAT);
+               status = readw (&i2c_base->stat);
        } while (  !(status &
                   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
                    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
@@ -398,8 +409,33 @@ static u16 wait_for_pin (void)
 
        if (timeout <= 0) {
                printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
-                       readw (I2C_STAT));
-                       writew(0xFFFF, I2C_STAT);
+                       readw (&i2c_base->stat));
+                       writew(0xFFFF, &i2c_base->stat);
 }
        return status;
 }
+
+int i2c_set_bus_num(unsigned int bus)
+{
+       if ((bus < 0) || (bus >= I2C_BUS_MAX)) {
+               printf("Bad bus: %d\n", bus);
+               return -1;
+       }
+
+#ifdef CONFIG_OMAP34XX
+       if (bus == 2)
+               i2c_base = (struct i2c *)I2C_BASE3;
+       else
+#endif
+       if (bus == 1)
+               i2c_base = (struct i2c *)I2C_BASE2;
+       else
+               i2c_base = (struct i2c *)I2C_BASE1;
+
+       current_bus = bus;
+
+       if(!bus_initialized[current_bus])
+               i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+
+       return 0;
+}
Index: u-boot-main/include/asm-arm/arch-omap3/i2c.h
===================================================================
--- u-boot-main.orig/include/asm-arm/arch-omap3/i2c.h
+++ u-boot-main/include/asm-arm/arch-omap3/i2c.h
@@ -25,21 +25,39 @@
 
 #define I2C_DEFAULT_BASE       I2C_BASE1
 
-#define I2C_REV                (I2C_DEFAULT_BASE + 0x00)
-#define I2C_IE                 (I2C_DEFAULT_BASE + 0x04)
-#define I2C_STAT       (I2C_DEFAULT_BASE + 0x08)
-#define I2C_IV                 (I2C_DEFAULT_BASE + 0x0c)
-#define I2C_BUF                (I2C_DEFAULT_BASE + 0x14)
-#define I2C_CNT                (I2C_DEFAULT_BASE + 0x18)
-#define I2C_DATA       (I2C_DEFAULT_BASE + 0x1c)
-#define I2C_SYSC       (I2C_DEFAULT_BASE + 0x20)
-#define I2C_CON                (I2C_DEFAULT_BASE + 0x24)
-#define I2C_OA                 (I2C_DEFAULT_BASE + 0x28)
-#define I2C_SA                 (I2C_DEFAULT_BASE + 0x2c)
-#define I2C_PSC                (I2C_DEFAULT_BASE + 0x30)
-#define I2C_SCLL       (I2C_DEFAULT_BASE + 0x34)
-#define I2C_SCLH       (I2C_DEFAULT_BASE + 0x38)
-#define I2C_SYSTEST    (I2C_DEFAULT_BASE + 0x3c)
+struct i2c {
+       unsigned short rev;     /* 0x00 */
+       unsigned short res1;
+       unsigned short ie;      /* 0x04 */
+       unsigned short res2;
+       unsigned short stat;    /* 0x08 */
+       unsigned short res3;
+       unsigned short iv;      /* 0x0C */
+       unsigned short res4[3];
+       unsigned short buf;     /* 0x14 */
+       unsigned short res5;
+       unsigned short cnt;     /* 0x18 */
+       unsigned short res6;
+       unsigned short data;    /* 0x1C */
+       unsigned short res7;
+       unsigned short sysc;    /* 0x20 */
+       unsigned short res8;
+       unsigned short con;     /* 0x24 */
+       unsigned short res9;
+       unsigned short oa;      /* 0x28 */
+       unsigned short res10;
+       unsigned short sa;      /* 0x2C */
+       unsigned short res11;
+       unsigned short psc;     /* 0x30 */
+       unsigned short res12;
+       unsigned short scll;    /* 0x34 */
+       unsigned short res13;
+       unsigned short sclh;    /* 0x38 */
+       unsigned short res14;
+       unsigned short systest; /* 0x3c */
+};
+
+#define I2C_BUS_MAX    3
 
 /* I2C masks */
 
@@ -181,4 +199,6 @@
 #define I2C_PSC_MAX            0x0f
 #define I2C_PSC_MIN            0x00
 
+extern int i2c_set_bus_num(unsigned int);
+
 #endif /* _I2C_H_ */
Index: u-boot-main/include/asm-arm/arch-omap24xx/i2c.h
===================================================================
--- u-boot-main.orig/include/asm-arm/arch-omap24xx/i2c.h
+++ u-boot-main/include/asm-arm/arch-omap24xx/i2c.h
@@ -23,24 +23,44 @@
 #ifndef _OMAP24XX_I2C_H_
 #define _OMAP24XX_I2C_H_
 
-#define I2C_BASE                0x48070000
+#define I2C_BASE1              0x48070000
 #define I2C_BASE2               0x48072000 /* nothing hooked up on h4 */
 
-#define I2C_REV                 (I2C_BASE + 0x00)
-#define I2C_IE                  (I2C_BASE + 0x04)
-#define I2C_STAT                (I2C_BASE + 0x08)
-#define I2C_IV                  (I2C_BASE + 0x0c)
-#define I2C_BUF                 (I2C_BASE + 0x14)
-#define I2C_CNT                 (I2C_BASE + 0x18)
-#define I2C_DATA                (I2C_BASE + 0x1c)
-#define I2C_SYSC                (I2C_BASE + 0x20)
-#define I2C_CON                 (I2C_BASE + 0x24)
-#define I2C_OA                  (I2C_BASE + 0x28)
-#define I2C_SA                  (I2C_BASE + 0x2c)
-#define I2C_PSC                 (I2C_BASE + 0x30)
-#define I2C_SCLL                (I2C_BASE + 0x34)
-#define I2C_SCLH                (I2C_BASE + 0x38)
-#define I2C_SYSTEST             (I2C_BASE + 0x3c)
+#define I2C_DEFAULT_BASE       I2C_BASE1
+
+struct i2c {
+       unsigned short rev;     /* 0x00 */
+       unsigned short res1;
+       unsigned short ie;      /* 0x04 */
+       unsigned short res2;
+       unsigned short stat;    /* 0x08 */
+       unsigned short res3;
+       unsigned short iv;      /* 0x0C */
+       unsigned short res4[3];
+       unsigned short buf;     /* 0x14 */
+       unsigned short res5;
+       unsigned short cnt;     /* 0x18 */
+       unsigned short res6;
+       unsigned short data;    /* 0x1C */
+       unsigned short res7;
+       unsigned short sysc;    /* 0x20 */
+       unsigned short res8;
+       unsigned short con;     /* 0x24 */
+       unsigned short res9;
+       unsigned short oa;      /* 0x28 */
+       unsigned short res10;
+       unsigned short sa;      /* 0x2C */
+       unsigned short res11;
+       unsigned short psc;     /* 0x30 */
+       unsigned short res12;
+       unsigned short scll;    /* 0x34 */
+       unsigned short res13;
+       unsigned short sclh;    /* 0x38 */
+       unsigned short res14;
+       unsigned short systest; /* 0x3c */
+};
+
+#define I2C_BUS_MAX    2
 
 /* I2C masks */
 
@@ -147,5 +167,6 @@
 #define I2C_PSC_MAX                    0x0f
 #define I2C_PSC_MIN                    0x00
 
+extern int i2c_set_bus_num(unsigned int);
 
 #endif
_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to