[U-Boot] [PATCH] 5/12 Multiadapter/multibus I2C, drivers part 2, fixed
ksi at koi8.net
ksi at koi8.net
Fri Feb 13 22:52:05 CET 2009
Initial multiadapter/multibus I2C support.
Signed-off-by: Sergey Kubushyn <ksi at koi8.net>
---
diff -purN u-boot-i2c.orig/drivers/i2c/omap1510_i2c.c u-boot-i2c/drivers/i2c/omap1510_i2c.c
--- u-boot-i2c.orig/drivers/i2c/omap1510_i2c.c 2009-02-12 10:43:41.000000000 -0800
+++ u-boot-i2c/drivers/i2c/omap1510_i2c.c 2009-02-12 10:46:00.000000000 -0800
@@ -1,4 +1,8 @@
/*
+ * Copyright (c) 2009 Sergey Kubushyn <ksi at koi8.net>
+ *
+ * Changes for multibus/multiadapter I2C support.
+ *
* Basic I2C functions
*
* Copyright (c) 2003 Texas Instruments
@@ -19,11 +23,51 @@
*/
#include <common.h>
+#include <i2c.h>
+
+i2c_adap_t omap1510_i2c_adap;
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void wait_for_bb (void)
+{
+ int timeout = 10;
+
+ while ((inw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
+ inw (I2C_IV);
+ udelay (1000);
+ }
+
+ if (timeout <= 0) {
+ printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
+ inw (I2C_STAT));
+ }
+}
+
+static u16 wait_for_pin (void)
+{
+ u16 status, iv;
+ int timeout = 10;
+
+ do {
+ udelay (1000);
+ status = inw (I2C_STAT);
+ iv = inw (I2C_IV);
+ } while (!iv &&
+ !(status &
+ (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
+ I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
+ I2C_STAT_AL)) && timeout--);
+
+ if (timeout <= 0) {
+ printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
+ inw (I2C_STAT));
+ }
-static void wait_for_bb (void);
-static u16 wait_for_pin (void);
+ return status;
+}
-void i2c_init (int speed, int slaveadd)
+static void omap1510_i2c_init (int speed, int slaveadd)
{
u16 scl;
@@ -46,6 +90,10 @@ void i2c_init (int speed, int slaveadd)
outw (slaveadd, I2C_OA);
outw (0, I2C_CNT);
udelay (1000);
+
+ if (gd->flags & GD_FLG_RELOC) {
+ omap1510_i2c_adap.init_done = 1;
+ }
}
static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
@@ -158,7 +206,7 @@ static int i2c_write_byte (u8 devaddr, u
return i2c_error;
}
-int i2c_probe (uchar chip)
+static int omap1510_i2c_probe (uchar chip)
{
int res = 1;
@@ -188,24 +236,24 @@ int i2c_probe (uchar chip)
return res;
}
-int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
+static int omap1510_i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
{
int i;
if (alen > 1) {
- printf ("I2C read: addr len %d not supported\n", alen);
+ printf ("%s: addr len %d not supported\n", __FUNCTION__, alen);
return 1;
}
if (addr + len > 256) {
- printf ("I2C read: address out of range\n");
+ printf ("%s: address out of range\n", __FUNCTION__);
return 1;
}
for (i = 0; i < len; i++) {
if (i2c_read_byte (chip, addr + i, &buffer[i])) {
- printf ("I2C read: I/O error\n");
- i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+ printf ("%s: I/O error\n", __FUNCTION__);
+ i2c_init (CONFIG_SYS_OMAP1510_I2C_SPEED, CONFIG_SYS_OMAP1510_I2C_SLAVE);
return 1;
}
}
@@ -213,24 +261,24 @@ int i2c_read (uchar chip, uint addr, int
return 0;
}
-int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
+static int omap1510_i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
{
int i;
if (alen > 1) {
- printf ("I2C read: addr len %d not supported\n", alen);
+ printf ("%s: addr len %d not supported\n", __FUNCTION__, alen);
return 1;
}
if (addr + len > 256) {
- printf ("I2C read: address out of range\n");
+ printf ("%s: address out of range\n", __FUNCTION__);
return 1;
}
for (i = 0; i < len; i++) {
if (i2c_write_byte (chip, addr + i, buffer[i])) {
- printf ("I2C read: I/O error\n");
- i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+ printf ("%s: I/O error\n", __FUNCTION__);
+ i2c_init (CONFIG_SYS_OMAP1510_I2C_SPEED, CONFIG_SYS_OMAP1510_I2C_SLAVE);
return 1;
}
}
@@ -238,40 +286,25 @@ int i2c_write (uchar chip, uint addr, in
return 0;
}
-static void wait_for_bb (void)
+static unsigned int omap1510_i2c_set_bus_speed(unsigned int speed)
{
- int timeout = 10;
-
- while ((inw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
- inw (I2C_IV);
- udelay (1000);
- }
-
- if (timeout <= 0) {
- printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
- inw (I2C_STAT));
- }
+ return(omap1510_i2c_adap.speed);
}
-static u16 wait_for_pin (void)
+static unsigned int omap1510_i2c_get_bus_speed(void)
{
- u16 status, iv;
- int timeout = 10;
-
- do {
- udelay (1000);
- status = inw (I2C_STAT);
- iv = inw (I2C_IV);
- } while (!iv &&
- !(status &
- (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
- I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
- I2C_STAT_AL)) && timeout--);
-
- if (timeout <= 0) {
- printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
- inw (I2C_STAT));
- }
-
- return status;
+ return(omap1510_i2c_adap.speed);
}
+
+i2c_adap_t omap1510_i2c_adap = {
+ .init = omap1510_i2c_init,
+ .probe = omap1510_i2c_probe,
+ .read = omap1510_i2c_read,
+ .write = omap1510_i2c_write,
+ .set_bus_speed = omap1510_i2c_set_bus_speed,
+ .get_bus_speed = omap1510_i2c_get_bus_speed,
+ .speed = CONFIG_SYS_OMAP1510_I2C_SPEED,
+ .slaveaddr = CONFIG_SYS_OMAP1510_I2C_SLAVE,
+ .init_done = 0,
+ .name = "omap1510_i2c"
+};
diff -purN u-boot-i2c.orig/drivers/i2c/omap24xx_i2c.c u-boot-i2c/drivers/i2c/omap24xx_i2c.c
--- u-boot-i2c.orig/drivers/i2c/omap24xx_i2c.c 2009-02-12 10:43:41.000000000 -0800
+++ u-boot-i2c/drivers/i2c/omap24xx_i2c.c 2009-02-12 10:46:00.000000000 -0800
@@ -1,4 +1,8 @@
/*
+ * Copyright (c) 2009 Sergey Kubushyn <ksi at koi8.net>
+ *
+ * Changes for multibus/multiadapter I2C support.
+ *
* Basic I2C functions
*
* Copyright (c) 2004 Texas Instruments
@@ -24,65 +28,134 @@
#include <asm/arch/i2c.h>
#include <asm/io.h>
+#include <i2c.h>
-static void wait_for_bb (void);
-static u16 wait_for_pin (void);
-static void flush_fifo(void);
+#define OMAP24XX_NAME(arg) "omap24xx_i2c@" MK_NAME(arg)
+#define MK_NAME(arg) #arg
+
+#ifndef CONFIG_SYS_OMAP24XX_I2C_BASE
+#define CONFIG_SYS_OMAP24XX_I2C_BASE I2C_BASE1
+#endif
-void i2c_init (int speed, int slaveadd)
+i2c_adap_t omap24xx_i2c_adap[];
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static void flush_fifo(ulong base)
+{
+ u16 stat;
+
+ /* note: if you try and read data when its not there or ready
+ * you get a bus error
+ */
+ while(1){
+ stat = readw(base + I2C_STAT);
+ if(stat == I2C_STAT_RRDY){
+#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
+ readb(base + I2C_DATA);
+#else
+ readw(base + I2C_DATA);
+#endif
+ writew(I2C_STAT_RRDY, base + I2C_STAT);
+ udelay(1000);
+ }else
+ break;
+ }
+}
+
+static void wait_for_bb (ulong base)
+{
+ int timeout = 10;
+ u16 stat;
+
+ writew(0xFFFF, base + I2C_STAT); /* clear current interruts...*/
+ while ((stat = readw (base + I2C_STAT) & I2C_STAT_BB) && timeout--) {
+ writew (stat, base + I2C_STAT);
+ udelay (50000);
+ }
+
+ if (timeout <= 0) {
+ printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
+ readw (base + I2C_STAT));
+ }
+ writew(0xFFFF, base + I2C_STAT); /* clear delayed stuff*/
+}
+
+static u16 wait_for_pin (ulong base)
+{
+ u16 status;
+ int timeout = 10;
+
+ do {
+ udelay (1000);
+ status = readw (base + I2C_STAT);
+ } while ( !(status &
+ (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
+ I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
+ I2C_STAT_AL)) && timeout--);
+
+ if (timeout <= 0) {
+ printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
+ readw (base + I2C_STAT));
+ writew(0xFFFF, base + I2C_STAT);
+ }
+ return status;
+}
+
+static void _i2c_init (int speed, int slaveadd, ulong base)
{
u16 scl;
- writew(0x2, I2C_SYSC); /* for ES2 after soft reset */
+ writew(0x2, base + I2C_SYSC); /* for ES2 after soft reset */
udelay(1000);
- writew(0x0, I2C_SYSC); /* will probably self clear but */
+ writew(0x0, base + I2C_SYSC); /* will probably self clear but */
- if (readw (I2C_CON) & I2C_CON_EN) {
- writew (0, I2C_CON);
+ if (readw (base + I2C_CON) & I2C_CON_EN) {
+ writew (0, base + I2C_CON);
udelay (50000);
}
/* 12MHz I2C module clock */
- writew (0, I2C_PSC);
+ writew (0, base + I2C_PSC);
speed = speed/1000; /* 100 or 400 */
scl = ((12000/(speed*2)) - 7); /* use 7 when PSC = 0 */
- writew (scl, I2C_SCLL);
- writew (scl, I2C_SCLH);
+ writew (scl, base + I2C_SCLL);
+ writew (scl, base + I2C_SCLH);
/* own address */
- writew (slaveadd, I2C_OA);
- writew (I2C_CON_EN, I2C_CON);
+ writew (slaveadd, base + I2C_OA);
+ writew (I2C_CON_EN, base + I2C_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, base + I2C_IE);
udelay (1000);
- flush_fifo();
- writew (0xFFFF, I2C_STAT);
- writew (0, I2C_CNT);
+ flush_fifo(base);
+ writew (0xFFFF, base + I2C_STAT);
+ writew (0, base + I2C_CNT);
}
-static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
+static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value, ulong base)
{
int i2c_error = 0;
u16 status;
/* wait until bus not busy */
- wait_for_bb ();
+ wait_for_bb (base);
/* one byte only */
- writew (1, I2C_CNT);
+ writew (1, base + I2C_CNT);
/* set slave address */
- writew (devaddr, I2C_SA);
+ writew (devaddr, base + I2C_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, base + I2C_CON);
- status = wait_for_pin ();
+ status = wait_for_pin (base);
if (status & I2C_STAT_XRDY) {
/* Important: have to use byte access */
- writeb (regoffset, I2C_DATA);
+ writeb (regoffset, base + I2C_DATA);
udelay (20000);
- if (readw (I2C_STAT) & I2C_STAT_NACK) {
+ if (readw (base + I2C_STAT) & I2C_STAT_NACK) {
i2c_error = 1;
}
} else {
@@ -91,28 +164,29 @@ 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, base + I2C_CON);
+ while (readw (base + I2C_STAT) ||
+ (readw (base + I2C_CON) & I2C_CON_MST)) {
udelay (10000);
/* Have to clear pending interrupt to clear I2C_STAT */
- writew (0xFFFF, I2C_STAT);
+ writew (0xFFFF, base + I2C_STAT);
}
- wait_for_bb ();
+ wait_for_bb (base);
/* set slave address */
- writew (devaddr, I2C_SA);
+ writew (devaddr, base + I2C_SA);
/* read one byte from slave */
- writew (1, I2C_CNT);
+ writew (1, base + I2C_CNT);
/* need stop bit here */
writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
- I2C_CON);
+ base + I2C_CON);
- status = wait_for_pin ();
+ status = wait_for_pin (base);
if (status & I2C_STAT_RRDY) {
#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
- *value = readb (I2C_DATA);
+ *value = readb (base + I2C_DATA);
#else
- *value = readw (I2C_DATA);
+ *value = readw (base + I2C_DATA);
#endif
udelay (20000);
} else {
@@ -120,60 +194,60 @@ 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, base + I2C_CON);
+ while (readw (base + I2C_STAT)
+ || (readw (base + I2C_CON) & I2C_CON_MST)) {
udelay (10000);
- writew (0xFFFF, I2C_STAT);
+ writew (0xFFFF, base + I2C_STAT);
}
}
}
- flush_fifo();
- writew (0xFFFF, I2C_STAT);
- writew (0, I2C_CNT);
+ flush_fifo(base);
+ writew (0xFFFF, base + I2C_STAT);
+ writew (0, base + I2C_CNT);
return i2c_error;
}
-static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
+static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value, ulong base)
{
int i2c_error = 0;
u16 status, stat;
/* wait until bus not busy */
- wait_for_bb ();
+ wait_for_bb (base);
/* two bytes */
- writew (2, I2C_CNT);
+ writew (2, base + I2C_CNT);
/* set slave address */
- writew (devaddr, I2C_SA);
+ writew (devaddr, base + I2C_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, base + I2C_CON);
/* wait until state change */
- status = wait_for_pin ();
+ status = wait_for_pin (base);
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, base + I2C_DATA);
+ writew (I2C_STAT_XRDY, base + I2C_STAT);
- status = wait_for_pin ();
+ status = wait_for_pin (base);
if ((status & I2C_STAT_XRDY)) {
/* send out next 1 byte */
- writeb (value, I2C_DATA);
- writew (I2C_STAT_XRDY, I2C_STAT);
+ writeb (value, base + I2C_DATA);
+ writew (I2C_STAT_XRDY, base + I2C_STAT);
} else {
i2c_error = 1;
}
#else
/* send out two bytes */
- writew ((value << 8) + regoffset, I2C_DATA);
+ writew ((value << 8) + regoffset, base + I2C_DATA);
#endif
/* must have enough delay to allow BB bit to go low */
udelay (50000);
- if (readw (I2C_STAT) & I2C_STAT_NACK) {
+ if (readw (base + I2C_STAT) & I2C_STAT_NACK) {
i2c_error = 1;
}
} else {
@@ -183,96 +257,96 @@ 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, base + I2C_CON);
+ while ((stat = readw (base + I2C_STAT)) ||
+ (readw (base + I2C_CON) & I2C_CON_MST)) {
udelay (1000);
/* have to read to clear intrrupt */
- writew (0xFFFF, I2C_STAT);
+ writew (0xFFFF, base + I2C_STAT);
if(--eout == 0) /* better leave with error than hang */
break;
}
}
- flush_fifo();
- writew (0xFFFF, I2C_STAT);
- writew (0, I2C_CNT);
+ flush_fifo(base);
+ writew (0xFFFF, base + I2C_STAT);
+ writew (0, base + I2C_CNT);
return i2c_error;
}
-static void flush_fifo(void)
-{ u16 stat;
-
- /* note: if you try and read data when its not there or ready
- * you get a bus error
- */
- while(1){
- stat = readw(I2C_STAT);
- if(stat == I2C_STAT_RRDY){
-#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
- readb(I2C_DATA);
-#else
- readw(I2C_DATA);
-#endif
- writew(I2C_STAT_RRDY,I2C_STAT);
- udelay(1000);
- }else
- break;
- }
-}
-int i2c_probe (uchar chip)
+static int _i2c_probe (uchar chip, ulong base)
{
int res = 1; /* default = fail */
- if (chip == readw (I2C_OA)) {
+ if (chip == readw (base + I2C_OA)) {
return res;
}
/* wait until bus not busy */
- wait_for_bb ();
+ wait_for_bb (base);
/* try to read one byte */
- writew (1, I2C_CNT);
+ writew (1, base + I2C_CNT);
/* set slave address */
- writew (chip, I2C_SA);
+ writew (chip, base + I2C_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, base + I2C_CON);
/* enough delay for the NACK bit set */
udelay (50000);
- if (!(readw (I2C_STAT) & I2C_STAT_NACK)) {
+ if (!(readw (base + I2C_STAT) & I2C_STAT_NACK)) {
res = 0; /* success case */
- flush_fifo();
- writew(0xFFFF, I2C_STAT);
+ flush_fifo(base);
+ writew(0xFFFF, base + I2C_STAT);
} else {
- writew(0xFFFF, I2C_STAT); /* failue, clear sources*/
- writew (readw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */
+ writew(0xFFFF, base + I2C_STAT); /* failure, clear sources*/
+ writew (readw (base + I2C_CON) | I2C_CON_STP, base + I2C_CON); /* finish up xfer */
udelay(20000);
- wait_for_bb ();
+ wait_for_bb (base);
}
- flush_fifo();
- writew (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/
- writew(0xFFFF, I2C_STAT);
+ flush_fifo(base);
+ writew (0, base + I2C_CNT); /* don't allow any more data in...we don't want it.*/
+ writew(0xFFFF, base + I2C_STAT);
return res;
}
-int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
+
+static void omap24xx_i2c_init (int speed, int slaveadd)
+{
+ _i2c_init(speed, slaveadd, CONFIG_SYS_OMAP24XX_I2C_BASE);
+
+ if (gd->flags & GD_FLG_RELOC) {
+ omap24xx_i2c_adap[0].speed = speed;
+ omap24xx_i2c_adap[0].slaveaddr = slaveadd;
+ omap24xx_i2c_adap[0].init_done = 1;
+ }
+}
+
+static int omap24xx_i2c_probe (uchar chip)
+{
+ return(_i2c_probe(chip, CONFIG_SYS_OMAP24XX_I2C_BASE));
+}
+
+static int omap24xx_i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
{
int i;
if (alen > 1) {
- printf ("I2C read: addr len %d not supported\n", alen);
+ printf ("%s: addr len %d not supported\n", __FUNCTION__, alen);
return 1;
}
if (addr + len > 256) {
- printf ("I2C read: address out of range\n");
+ printf ("%s: address out of range\n", __FUNCTION__);
return 1;
}
for (i = 0; i < len; i++) {
- if (i2c_read_byte (chip, addr + i, &buffer[i])) {
- printf ("I2C read: I/O error\n");
- i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+ if (i2c_read_byte (chip, addr + i, &buffer[i], CONFIG_SYS_OMAP24XX_I2C_BASE)) {
+ printf ("%s: I/O error\n", __FUNCTION__);
+ _i2c_init (CONFIG_SYS_OMAP24XX_I2C_SPEED,
+ CONFIG_SYS_OMAP24XX_I2C_SLAVE,
+ CONFIG_SYS_OMAP24XX_I2C_BASE);
return 1;
}
}
@@ -280,24 +354,26 @@ int i2c_read (uchar chip, uint addr, int
return 0;
}
-int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
+static int omap24xx_i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
{
int i;
if (alen > 1) {
- printf ("I2C read: addr len %d not supported\n", alen);
+ printf ("%s: addr len %d not supported\n", __FUNCTION__, alen);
return 1;
}
if (addr + len > 256) {
- printf ("I2C read: address out of range\n");
+ printf ("%s: address out of range\n", __FUNCTION__);
return 1;
}
for (i = 0; i < len; i++) {
- if (i2c_write_byte (chip, addr + i, buffer[i])) {
- printf ("I2C read: I/O error\n");
- i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
+ if (i2c_write_byte (chip, addr + i, buffer[i], CONFIG_SYS_OMAP24XX_I2C_BASE)) {
+ printf ("%s: I/O error\n", __FUNCTION__);
+ _i2c_init (CONFIG_SYS_OMAP24XX_I2C_SPEED,
+ CONFIG_SYS_OMAP24XX_I2C_SLAVE,
+ CONFIG_SYS_OMAP24XX_I2C_BASE);
return 1;
}
}
@@ -305,41 +381,219 @@ int i2c_write (uchar chip, uint addr, in
return 0;
}
-static void wait_for_bb (void)
+static unsigned int omap24xx_i2c_set_bus_speed(unsigned int speed)
{
- int timeout = 10;
- u16 stat;
+ return(omap24xx_i2c_adap[0].speed);
+}
- writew(0xFFFF, I2C_STAT); /* clear current interruts...*/
- while ((stat = readw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
- writew (stat, I2C_STAT);
- udelay (50000);
+static unsigned int omap24xx_i2c_get_bus_speed(void)
+{
+ return(omap24xx_i2c_adap[0].speed);
+}
+
+#ifdef CONFIG_SYS_OMAP24XX_I2C2_BASE
+static void omap24xx_i2c2_init (int speed, int slaveadd)
+{
+ _i2c_init(speed, slaveadd, CONFIG_SYS_OMAP24XX_I2C2_BASE);
+
+ if (gd->flags & GD_FLG_RELOC) {
+ omap24xx_i2c_adap[1].speed = speed;
+ omap24xx_i2c_adap[1].slaveaddr = slaveadd;
+ omap24xx_i2c_adap[1].init_done = 1;
+ }
+}
+
+static int omap24xx_i2c2_probe (uchar chip)
+{
+ return(_i2c_probe(chip, CONFIG_SYS_OMAP24XX_I2C2_BASE));
+}
+
+static int omap24xx_i2c2_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+ int i;
+
+ if (alen > 1) {
+ printf ("%s: addr len %d not supported\n", __FUNCTION__, alen);
+ return 1;
}
- if (timeout <= 0) {
- printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
- readw (I2C_STAT));
+ if (addr + len > 256) {
+ printf ("%s: address out of range\n", __FUNCTION__);
+ return 1;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i2c_read_byte (chip, addr + i, &buffer[i], CONFIG_SYS_OMAP24XX_I2C2_BASE)) {
+ printf ("%s: I/O error\n", __FUNCTION__);
+ _i2c_init (CONFIG_SYS_OMAP24XX_I2C2_SPEED,
+ CONFIG_SYS_OMAP24XX_I2C2_SLAVE,
+ CONFIG_SYS_OMAP24XX_I2C2_BASE);
+ return 1;
+ }
}
- writew(0xFFFF, I2C_STAT); /* clear delayed stuff*/
+
+ return 0;
}
-static u16 wait_for_pin (void)
+static int omap24xx_i2c2_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
{
- u16 status;
- int timeout = 10;
+ int i;
- do {
- udelay (1000);
- status = readw (I2C_STAT);
- } while ( !(status &
- (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
- I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
- I2C_STAT_AL)) && timeout--);
+ if (alen > 1) {
+ printf ("%s: addr len %d not supported\n", __FUNCTION__, alen);
+ return 1;
+ }
- if (timeout <= 0) {
- printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
- readw (I2C_STAT));
- writew(0xFFFF, I2C_STAT);
+ if (addr + len > 256) {
+ printf ("%s: address out of range\n", __FUNCTION__);
+ return 1;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i2c_write_byte (chip, addr + i, buffer[i], CONFIG_SYS_OMAP24XX_I2C2_BASE)) {
+ printf ("%s: I/O error\n", __FUNCTION__);
+ _i2c_init (CONFIG_SYS_OMAP24XX_I2C2_SPEED,
+ CONFIG_SYS_OMAP24XX_I2C2_SLAVE,
+ CONFIG_SYS_OMAP24XX_I2C2_BASE);
+ return 1;
+ }
+ }
+
+ return 0;
}
- return status;
+
+static unsigned int omap24xx_i2c2_set_bus_speed(unsigned int speed)
+{
+ return(omap24xx_i2c_adap[1].speed);
+}
+
+static unsigned int omap24xx_i2c2_get_bus_speed(void)
+{
+ return(omap24xx_i2c_adap[1].speed);
+}
+#endif
+
+#ifdef CONFIG_SYS_OMAP24XX_I2C3_BASE
+static void omap24xx_i2c3_init (int speed, int slaveadd)
+{
+ _i2c_init(speed, slaveadd, CONFIG_SYS_OMAP24XX_I2C3_BASE);
+
+ if (gd->flags & GD_FLG_RELOC) {
+ omap24xx_i2c_adap[2].speed = speed;
+ omap24xx_i2c_adap[2].slaveaddr = slaveadd;
+ omap24xx_i2c_adap[2].init_done = 1;
+ }
+}
+
+static int omap24xx_i2c3_probe (uchar chip)
+{
+ return(_i2c_probe(chip, CONFIG_SYS_OMAP24XX_I2C3_BASE));
}
+
+static int omap24xx_i2c3_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+ int i;
+
+ if (alen > 1) {
+ printf ("%s: addr len %d not supported\n", __FUNCTION__, alen);
+ return 1;
+ }
+
+ if (addr + len > 256) {
+ printf ("%s: address out of range\n", __FUNCTION__);
+ return 1;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i2c_read_byte (chip, addr + i, &buffer[i], CONFIG_SYS_OMAP24XX_I2C3_BASE)) {
+ printf ("%s: I/O error\n", __FUNCTION__);
+ _i2c_init (CONFIG_SYS_OMAP24XX_I2C3_SPEED,
+ CONFIG_SYS_OMAP24XX_I2C3_SLAVE,
+ CONFIG_SYS_OMAP24XX_I2C3_BASE);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static int omap24xx_i2c3_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
+{
+ int i;
+
+ if (alen > 1) {
+ printf ("%s: addr len %d not supported\n", __FUNCTION__, alen);
+ return 1;
+ }
+
+ if (addr + len > 256) {
+ printf ("%s: address out of range\n", __FUNCTION__);
+ return 1;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (i2c_write_byte (chip, addr + i, buffer[i], CONFIG_SYS_OMAP24XX_I2C3_BASE)) {
+ printf ("%s: I/O error\n", __FUNCTION__);
+ _i2c_init (CONFIG_SYS_OMAP24XX_I2C3_SPEED,
+ CONFIG_SYS_OMAP24XX_I2C3_SLAVE,
+ CONFIG_SYS_OMAP24XX_I2C3_BASE);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+static unsigned int omap24xx_i2c3_set_bus_speed(unsigned int speed)
+{
+ return(omap24xx_i2c_adap[2].speed);
+}
+
+static unsigned int omap24xx_i2c3_get_bus_speed(void)
+{
+ return(omap24xx_i2c_adap[2].speed);
+}
+#endif
+
+i2c_adap_t omap24xx_i2c_adap[3] = {
+ {
+ .init = omap24xx_i2c_init,
+ .probe = omap24xx_i2c_probe,
+ .read = omap24xx_i2c_read,
+ .write = omap24xx_i2c_write,
+ .set_bus_speed = omap24xx_i2c_set_bus_speed,
+ .get_bus_speed = omap24xx_i2c_get_bus_speed,
+ .speed = CONFIG_SYS_OMAP24XX_I2C_SPEED,
+ .slaveaddr = CONFIG_SYS_OMAP24XX_I2C_SLAVE,
+ .init_done = 0,
+ .name = OMAP24XX_NAME(CONFIG_SYS_OMAP24XX_I2C_BASE)
+ },
+#ifdef CONFIG_SYS_OMAP24XX_I2C2_BASE
+ {
+ .init = omap24xx_i2c2_init,
+ .probe = omap24xx_i2c2_probe,
+ .read = omap24xx_i2c2_read,
+ .write = omap24xx_i2c2_write,
+ .set_bus_speed = omap24xx_i2c2_set_bus_speed,
+ .get_bus_speed = omap24xx_i2c2_get_bus_speed,
+ .speed = CONFIG_SYS_OMAP24XX_I2C2_SPEED,
+ .slaveaddr = CONFIG_SYS_OMAP24XX_I2C2_SLAVE,
+ .init_done = 0,
+ .name = OMAP24XX_NAME(CONFIG_SYS_OMAP24XX_I2C2_BASE)
+ },
+#endif
+#ifdef CONFIG_SYS_OMAP24XX_I2C3_BASE
+ {
+ .init = omap24xx_i2c3_init,
+ .probe = omap24xx_i2c3_probe,
+ .read = omap24xx_i2c3_read,
+ .write = omap24xx_i2c3_write,
+ .set_bus_speed = omap24xx_i2c3_set_bus_speed,
+ .get_bus_speed = omap24xx_i2c3_get_bus_speed,
+ .speed = CONFIG_SYS_OMAP24XX_I2C3_SPEED,
+ .slaveaddr = CONFIG_SYS_OMAP24XX_I2C3_SLAVE,
+ .init_done = 0,
+ .name = OMAP24XX_NAME(CONFIG_SYS_OMAP24XX_I2C3_BASE)
+ }
+#endif
+};
diff -purN u-boot-i2c.orig/drivers/i2c/tsi108_i2c.c u-boot-i2c/drivers/i2c/tsi108_i2c.c
--- u-boot-i2c.orig/drivers/i2c/tsi108_i2c.c 2009-02-12 10:43:41.000000000 -0800
+++ u-boot-i2c/drivers/i2c/tsi108_i2c.c 2009-02-12 10:46:00.000000000 -0800
@@ -1,4 +1,8 @@
/*
+ * Copyright (c) 2009 Sergey Kubushyn <ksi at koi8.net>
+ *
+ * Changes for multibus/multiadapter I2C support.
+ *
* (C) Copyright 2004 Tundra Semiconductor Corp.
* Author: Alex Bounine
*
@@ -26,8 +30,7 @@
#include <common.h>
#include <tsi108.h>
-
-#if defined(CONFIG_CMD_I2C)
+#include <i2c.h>
#define I2C_DELAY 100000
#undef DEBUG_I2C
@@ -38,6 +41,8 @@
#define DPRINT(x)
#endif
+i2c_adap_t tsi108_i2c_adap;
+
/* All functions assume that Tsi108 I2C block is the only master on the bus */
/* I2C read helper function */
@@ -132,7 +137,7 @@ static int i2c_read_byte (
* Returns: 0 on success, not 0 on failure
*/
-int i2c_read (uchar chip_addr, uint byte_addr, int alen,
+static int tsi108_i2c_read (uchar chip_addr, uint byte_addr, int alen,
uchar * buffer, int len)
{
u32 op_status = TSI108_I2C_PARAM_ERR;
@@ -238,7 +243,7 @@ static int i2c_write_byte (uchar chip_ad
* Returns: 0 on success, not 0 on failure
*/
-int i2c_write (uchar chip_addr, uint byte_addr, int alen, uchar * buffer,
+static int tsi108_i2c_write (uchar chip_addr, uint byte_addr, int alen, uchar * buffer,
int len)
{
u32 op_status = TSI108_I2C_PARAM_ERR;
@@ -266,7 +271,7 @@ int i2c_write (uchar chip_addr, uint byt
* Returns 0 if a chip responded, not 0 on failure.
*/
-int i2c_probe (uchar chip)
+static int tsi108_i2c_probe (uchar chip)
{
u32 tmp;
@@ -278,4 +283,31 @@ int i2c_probe (uchar chip)
return i2c_read (chip, 0, 1, (uchar *)&tmp, 1);
}
-#endif
+static unsigned int tsi108_i2c_set_bus_speed(unsigned int speed)
+{
+ return(tsi108_i2c_adap.speed);
+}
+
+static unsigned int tsi108_i2c_get_bus_speed(void)
+{
+ return(tsi108_i2c_adap.speed);
+}
+
+static void tsi108_i2c_init(int speed, int slaveaddr)
+{
+ /* Dummy */
+}
+
+i2c_adap_t tsi108_i2c_adap = {
+ .init = tsi108_i2c_init,
+ .probe = tsi108_i2c_probe,
+ .read = tsi108_i2c_read,
+ .write = tsi108_i2c_write,
+ .set_bus_speed = tsi108_i2c_set_bus_speed,
+ .get_bus_speed = tsi108_i2c_get_bus_speed,
+ .speed = CONFIG_SYS_TSI108_I2C_SPEED,
+ .slaveaddr = CONFIG_SYS_TSI108_I2C_SLAVE,
+ .init_done = 0,
+ .name = "tsi108_i2c"
+};
+
diff -purN u-boot-i2c.orig/include/asm-arm/arch-omap24xx/i2c.h u-boot-i2c/include/asm-arm/arch-omap24xx/i2c.h
--- u-boot-i2c.orig/include/asm-arm/arch-omap24xx/i2c.h 2009-02-12 10:43:41.000000000 -0800
+++ u-boot-i2c/include/asm-arm/arch-omap24xx/i2c.h 2009-02-12 10:46:00.000000000 -0800
@@ -23,24 +23,24 @@
#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_REV (0x00)
+#define I2C_IE (0x04)
+#define I2C_STAT (0x08)
+#define I2C_IV (0x0c)
+#define I2C_BUF (0x14)
+#define I2C_CNT (0x18)
+#define I2C_DATA (0x1c)
+#define I2C_SYSC (0x20)
+#define I2C_CON (0x24)
+#define I2C_OA (0x28)
+#define I2C_SA (0x2c)
+#define I2C_PSC (0x30)
+#define I2C_SCLL (0x34)
+#define I2C_SCLH (0x38)
+#define I2C_SYSTEST (0x3c)
/* I2C masks */
diff -purN u-boot-i2c.orig/include/asm-arm/arch-omap3/i2c.h u-boot-i2c/include/asm-arm/arch-omap3/i2c.h
--- u-boot-i2c.orig/include/asm-arm/arch-omap3/i2c.h 2009-02-12 10:43:41.000000000 -0800
+++ u-boot-i2c/include/asm-arm/arch-omap3/i2c.h 2009-02-12 10:46:00.000000000 -0800
@@ -20,26 +20,24 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
-#ifndef _I2C_H_
-#define _I2C_H_
+#ifndef _OMAP3_I2C_H_
+#define _OMAP3_I2C_H_
-#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)
+#define I2C_REV (0x00)
+#define I2C_IE (0x04)
+#define I2C_STAT (0x08)
+#define I2C_IV (0x0c)
+#define I2C_BUF (0x14)
+#define I2C_CNT (0x18)
+#define I2C_DATA (0x1c)
+#define I2C_SYSC (0x20)
+#define I2C_CON (0x24)
+#define I2C_OA (0x28)
+#define I2C_SA (0x2c)
+#define I2C_PSC (0x30)
+#define I2C_SCLL (0x34)
+#define I2C_SCLH (0x38)
+#define I2C_SYSTEST (0x3c)
/* I2C masks */
@@ -125,4 +123,4 @@
#define I2C_PSC_MAX 0x0f
#define I2C_PSC_MIN 0x00
-#endif /* _I2C_H_ */
+#endif /* _OMAP3_I2C_H_ */
More information about the U-Boot
mailing list