OMAP2/3: I2C: Add support for second and third bus
authorDirk Behme <dirk.behme@googlemail.com>
Mon, 2 Nov 2009 19:36:26 +0000 (20:36 +0100)
committerHeiko Schocher <hs@denx.de>
Mon, 16 Nov 2009 06:25:15 +0000 (07:25 +0100)
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.behme@googlemail.com>
drivers/i2c/omap24xx_i2c.c
include/asm-arm/arch-omap24xx/i2c.h
include/asm-arm/arch-omap3/i2c.h

index 1a4c8c9ad2701b550fc1ad0ab2a9fde741902080..ff18991f0e49d9bdf536f9703af33ad1cfe09feb 100644 (file)
@@ -29,6 +29,11 @@ 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];
+static unsigned int current_bus;
+
 void i2c_init (int speed, int slaveadd)
 {
        int psc, fsscll, fssclh;
@@ -95,30 +100,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 +137,19 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
        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 +158,28 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
 
        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 +187,17 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
                }
 
                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 +210,12 @@ static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
        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 +223,24 @@ static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
        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 +250,18 @@ static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
        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 +272,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 +290,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 +298,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 +377,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 +397,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 +405,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;
+       }
+
+#if I2C_BUS_MAX==3
+       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 44db7a2d45efc06dc8f757504331b40ae0484513..19046aaab456106d12358995e8328f059408cb84 100644 (file)
 #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 */
+       unsigned short res15;
+};
+
+#define I2C_BUS_MAX    2
 
 /* I2C masks */
 
index 8b339cce9ab553e650282e5fdddcc6252d44aad8..490e03bb65e401c222b76a1049c4eb8edfc6477a 100644 (file)
 
 #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 */
+       unsigned short res15;
+};
+
+#define I2C_BUS_MAX    3
 
 /* I2C masks */