
Hello Hugo,
Hugo Vincent wrote:
This patch improves I2C support on OMAP3 platforms, including supporting the second and third I2C controllers (mainline only supports the first controller), and supporting writes where alen=0 (i.e. no register address - this was needed for some I2C devices I needed to drive from u-boot).
Tested on Gumstix Overo with several I2C devices, on I2C1 and 3.
The multi-bus support is mostly from this patch: http://www.beagleboard.org/gitweb/?p=u-boot-arm.git;a=commit;h=52eddcd07c2e7...
Best regards, Hugo Vincent
Signed-off-by: Hugo Vincent hugo.vincent@gmail.com
diff --git a/board/omap3/common/power.c b/board/omap3/common/power.c index 4908e5b..efc5dd4 100644 --- a/board/omap3/common/power.c +++ b/board/omap3/common/power.c @@ -42,6 +42,7 @@ void power_init_r(void) unsigned char byte;
#ifdef CONFIG_DRIVER_OMAP34XX_I2C
- i2c_set_bus_num(0); i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); #endif
diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index 16439ac..6332965 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -1324,6 +1324,7 @@ U_BOOT_CMD( #endif ); #endif /* CONFIG_I2C_CMD_TREE */ +#if !defined(CONFIG_I2C_CMD_TREE)
no longer needed, see commit:
d48eb5131d287f52bb85b4c58c8680a2e8e3b641
U_BOOT_CMD( imd, 4, 1, do_i2c_md, \ "i2c memory display", \ @@ -1378,6 +1379,7 @@ U_BOOT_CMD( " (valid chip values 50..57)\n" ); #endif +#endif /* !defined(CONFIG_I2C_CMD_TREE) */
#if defined(CONFIG_I2C_MUX)
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 6784603..424f172 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -1,7 +1,7 @@ /*
- Basic I2C functions
- Copyright (c) 2004 Texas Instruments
- Copyright (c) 2004, 2009 Texas Instruments
- This package is free software; you can redistribute it and/or
- modify it under the terms of the license found in the file
@@ -18,6 +18,7 @@
- Adapted for OMAP2420 I2C, r-woodruff2@ti.com
- Some additions by Hugo Vincent hugo.vincent@gmail.com June 2009
*/
#include <common.h>
@@ -25,40 +24,44 @@ #include <asm/arch/i2c.h> #include <asm/io.h>
+#ifdef CONFIG_OMAP34XX +#define I2C_NUM_IF 3 +#else +#define I2C_NUM_IF 2 +#endif
- static void wait_for_bb (void); static u16 wait_for_pin (void); static void flush_fifo(void);
+static i2c_t *i2c = (i2c_t *)I2C_DEFAULT_BASE;
- void i2c_init (int speed, int slaveadd)
^ Seems to me something is wrong with your patch, because here and on other places in your patch is a space, which I couldn;t find in the original file. Please check.
{
- u16 scl;
- writew(0x2, I2C_SYSC); /* for ES2 after soft reset */
- writew(0x2, &i2c->sysc); /* for ES2 after soft reset */ udelay(1000);
- writew(0x0, I2C_SYSC); /* will probably self clear but */
- writew(0x0, &i2c->sysc); /* will probably self clear but */
- if (readw (I2C_CON) & I2C_CON_EN) {
writew (0, I2C_CON);
udelay (50000);
- if (readw (&i2c->con) & I2C_CON_EN) {
writew (0, &i2c->con);
}udelay (10000);
- /* 12MHz I2C module clock */
- writew (0, 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);
- /* Timings from TRM, tested with scope - 100 kHz standard speed */
- writew (23, &i2c->psc);
- writew (13, &i2c->scll);
- writew (15, &i2c->sclh); /* own address */
- writew (slaveadd, I2C_OA);
- writew (I2C_CON_EN, I2C_CON);
writew (slaveadd, &i2c->oa);
writew (I2C_CON_EN, &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);
udelay (1000); flush_fifo();I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c->ie);
- writew (0xFFFF, I2C_STAT);
- writew (0, I2C_CNT);
writew (0xFFFF, &i2c->stat);
writew (0, &i2c->cnt); }
static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
@@ -70,19 +77,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->cnt); /* set slave address */
- writew (devaddr, I2C_SA);
- writew (devaddr, &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, &i2c-
con);
This lines are wrapped, please check.
status = wait_for_pin ();
if (status & I2C_STAT_XRDY) { /* Important: have to use byte access */
writeb (regoffset, I2C_DATA);
udelay (20000);writeb (regoffset, &i2c->data);
if (readw (I2C_STAT) & I2C_STAT_NACK) {
}if (readw (&i2c->stat) & I2C_STAT_NACK) { i2c_error = 1;
no brackets necessary.
} else { @@ -91,28 +98,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->con);
while (readw (&i2c->stat) || (readw (&i2c->con) & I2C_CON_MST)) { udelay (10000); /* Have to clear pending interrupt to clear I2C_STAT */
writew (0xFFFF, I2C_STAT);
writew (0xFFFF, &i2c->stat);
}
wait_for_bb (); /* set slave address */
writew (devaddr, I2C_SA);
/* read one byte from slave */writew (devaddr, &i2c->sa);
writew (1, I2C_CNT);
/* need stop bit here */ writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,writew (1, &i2c->cnt);
I2C_CON);
&i2c->con);
status = wait_for_pin (); if (status & I2C_STAT_RRDY) { #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)
*value = readb (I2C_DATA);
#else*value = readb (&i2c->data);
*value = readw (I2C_DATA);
#endif udelay (20000); } else {*value = readw (&i2c->data);
@@ -120,17 +127,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->con);
while (readw (&i2c->stat)
|| (readw (&i2c->con) & I2C_CON_MST)) { udelay (10000);
writew (0xFFFF, I2C_STAT);
} } flush_fifo();writew (0xFFFF, &i2c->stat); }
- writew (0xFFFF, I2C_STAT);
- writew (0, I2C_CNT);
- writew (0xFFFF, &i2c->stat);
- writew (0, &i2c->cnt); return i2c_error; }
@@ -143,12 +150,12 @@ static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value) wait_for_bb ();
/* two bytes */
- writew (2, I2C_CNT);
- writew (2, &i2c->cnt); /* set slave address */
- writew (devaddr, I2C_SA);
- writew (devaddr, &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, &i2c->con);
/* wait until state change */ status = wait_for_pin ();
@@ -156,24 +163,78 @@ 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->data);
writew (I2C_STAT_XRDY, &i2c->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->data);
} else { i2c_error = 1; } #else /* send out two bytes */writew (I2C_STAT_XRDY, &i2c->stat);
writew ((value << 8) + regoffset, I2C_DATA);
#endif /* must have enough delay to allow BB bit to go low */writew ((value << 8) + regoffset, &i2c->data);
udelay (50000);
if (readw (I2C_STAT) & I2C_STAT_NACK) {
udelay (1000);
if (readw (&i2c->stat) & I2C_STAT_NACK) {
i2c_error = 1;
}
please no brackets
- } else {
i2c_error = 1;
- }
here too, no brackets. Please check everywhere.
- if (!i2c_error) {
int eout = 200;
writew (I2C_CON_EN, &i2c->con);
while ((stat = readw (&i2c->stat)) || (readw (&i2c->con) &
I2C_CON_MST)) {
line wrapped, please check your mailer.
udelay (1000);
/* have to read to clear intrrupt */
writew (0xFFFF, &i2c->stat);
if(--eout == 0) /* better leave with error than hang */
break;
}
- }
- flush_fifo();
- writew (0xFFFF, &i2c->stat);
- writew (0, &i2c->cnt);
- return i2c_error;
+}
+/* Write just one byte (no reg offset) */ +static int i2c_write_byte_raw (u8 devaddr, u8 value) +{
- int i2c_error = 0;
- u16 status, stat;
- /* wait until bus not busy */
- wait_for_bb ();
- /* one bytes */
- writew (1, &i2c->cnt);
- /* set slave address */
- writew (devaddr, &i2c->sa);
- /* stop bit needed here */
- writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
I2C_CON_STP, &i2c->con);
- /* wait until state change */
- status = wait_for_pin ();
- if (status & I2C_STAT_XRDY) {
/* send out 1 byte */
writeb (value, &i2c->data);
writew (I2C_STAT_XRDY, &i2c->stat);
status = wait_for_pin ();
/* must have enough delay to allow BB bit to go low */
udelay (1000);
} } else {if (readw (&i2c->stat) & I2C_STAT_NACK) { i2c_error = 1;
@@ -183,18 +244,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)) {
line wrapped
writew (I2C_CON_EN, &i2c->con);
while ((stat = readw (&i2c->stat)) || (readw (&i2c->con) &
I2C_CON_MST)) {
line wrapped
udelay (1000); /* have to read to clear intrrupt */
writew (0xFFFF, I2C_STAT);
} } flush_fifo();writew (0xFFFF, &i2c->stat); if(--eout == 0) /* better leave with error than hang */ break;
- writew (0xFFFF, I2C_STAT);
- writew (0, I2C_CNT);
- writew (0xFFFF, &i2c->stat);
- writew (0, &i2c->cnt); return i2c_error; }
^ no space.
@@ -205,14 +266,14 @@ static void flush_fifo(void) * you get a bus error */ while(1){
stat = readw(I2C_STAT);
if(stat == I2C_STAT_RRDY){ #if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX)stat = readw(&i2c->stat);
readb(I2C_DATA);
#elsereadb(&i2c->data);
readw(I2C_DATA);
#endifreadw(&i2c->data);
writew(I2C_STAT_RRDY,I2C_STAT);
}else break;writew(I2C_STAT_RRDY,&i2c->stat); udelay(1000);
@@ -223,7 +284,7 @@ int i2c_probe (uchar chip) { int res = 1; /* default = fail */
- if (chip == readw (I2C_OA)) {
- if (chip == readw (&i2c->oa)) { return res; }
@@ -231,27 +292,27 @@ int i2c_probe (uchar chip) wait_for_bb ();
/* try to read one byte */
- writew (1, I2C_CNT);
- writew (1, &i2c->cnt); /* set slave address */
- writew (chip, I2C_SA);
- writew (chip, &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, &i2c-
con);
lines wrapped
/* enough delay for the NACK bit set */
- udelay (50000);
- udelay (1000);
- if (!(readw (I2C_STAT) & I2C_STAT_NACK)) {
- if (!(readw (&i2c->stat) & I2C_STAT_NACK)) { res = 0; /* success case */ flush_fifo();
writew(0xFFFF, I2C_STAT);
} else {writew(0xFFFF, &i2c->stat);
writew(0xFFFF, I2C_STAT); /* failue, clear sources*/
writew (readw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */
writew(0xFFFF, &i2c->stat); /* failue, clear sources*/
writew (readw (&i2c->con) | I2C_CON_STP, &i2c->con); /* finish up
xfer */
line wrapped
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->cnt); /* don't allow any more data in...we don't
want it.*/
lines wrapped
- writew(0xFFFF, &i2c->stat); return res; }
@@ -284,23 +345,34 @@ int 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);
if (alen > 1 || alen < 0) {
printf ("I2C write: addr len %d not supported\n", alen);
return 1; }
if (addr + len > 256) {
printf ("I2C read: address out of range\n");
return 1; }printf ("I2C write: address out of range\n");
- 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);
return 1;
- if (alen == 1)
for (i = 0; i < len; i++)
{
if (i2c_write_byte (chip, addr + i, buffer[i])) {
printf ("I2C write: I/O error\n");
i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
return 1;
}
}
- else if (alen == 0)
for (i = 0; i < len; i++)
{
if (i2c_write_byte_raw (chip, buffer[i])) {
printf ("I2C write: I/O error\n");
i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
return 1;
}}
}
return 0; }
@@ -310,17 +382,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);
udelay (50000);
writew(0xFFFF, &i2c->stat); /* clear current interruts...*/
while ((stat = readw (&i2c->stat) & I2C_STAT_BB) && timeout--) {
writew (stat, &i2c->stat);
udelay (1000);
}
if (timeout <= 0) { printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
readw (I2C_STAT));
}readw (&i2c->stat));
- writew(0xFFFF, I2C_STAT); /* clear delayed stuff*/
writew(0xFFFF, &i2c->stat); /* clear delayed stuff*/ }
static u16 wait_for_pin (void)
@@ -330,7 +402,7 @@ static u16 wait_for_pin (void)
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 |status = readw (&i2c->stat);
@@ -338,8 +410,55 @@ 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->stat));
} return status; }writew(0xFFFF, &i2c->stat);
+int i2c_set_bus_num(unsigned int bus) +{
- if ((bus < 0) || (bus >= I2C_NUM_IF)) {
printf("Bad bus: %d\n", bus);
return -1;
- }
+#ifdef CONFIG_OMAP34XX
- if (bus == 2)
i2c = (i2c_t *)I2C_BASE3;
- else
+#endif
- if (bus == 1)
i2c = (i2c_t *)I2C_BASE2;
- else
i2c = (i2c_t *)I2C_BASE1;
- return 0;
+}
+int i2c_get_bus_num(void) +{ +#ifdef CONFIG_OMAP34XX
- if (i2c == (i2c_t *)I2C_BASE3)
return 2;
- else
+#endif
- if (i2c == (i2c_t *)I2C_BASE2)
return 1;
- else if (i2c == (i2c_t *)I2C_BASE1)
return 0;
- else
return -1;
+}
+int i2c_get_bus_speed() +{
- return 100000;
+}
+int i2c_set_bus_speed(int speed) +{
- printf("Not yet implemented\n");
- return -1;
+}
diff --git a/drivers/mmc/omap3_mmc.c b/drivers/mmc/omap3_mmc.c index e90db7e..234fddf 100644 --- a/drivers/mmc/omap3_mmc.c +++ b/drivers/mmc/omap3_mmc.c @@ -62,6 +62,9 @@ void twl4030_mmc_config(void) { unsigned char data;
- i2c_set_bus_num(0);
- i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
- data = DEV_GRP_P1; i2c_write(PWRMGT_ADDR_ID4, VMMC1_DEV_GRP, 1, &data, 1); data = VMMC1_VSEL_30;
diff --git a/include/asm-arm/arch-omap3/i2c.h b/include/asm-arm/arch- omap3/i2c.h index 3937f35..9638abc 100644 --- a/include/asm-arm/arch-omap3/i2c.h +++ b/include/asm-arm/arch-omap3/i2c.h @@ -25,21 +25,24 @@
#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) +typedef struct i2c {
unsigned int rev; /* 0x00 */
please use tab for identation.
unsigned int ie; /* 0x04 */
unsigned int stat; /* 0x08 */
unsigned int iv; /* 0x0c */
unsigned int res1; /* 0x10 */
unsigned int buf; /* 0x14 */
unsigned int cnt; /* 0x18 */
unsigned int data; /* 0x1c */
unsigned int sysc; /* 0x20 */
unsigned int con; /* 0x24 */
unsigned int oa; /* 0x28 */
unsigned int sa; /* 0x2c */
unsigned int psc; /* 0x30 */
unsigned int scll; /* 0x34 */
unsigned int sclh; /* 0x38 */
unsigned int systest; /* 0x3c */
+} i2c_t;
/* I2C masks */
diff --git a/include/configs/omap3_overo.h b/include/configs/ omap3_overo.h index b2c42fa..d8f7a9e 100644 --- a/include/configs/omap3_overo.h +++ b/include/configs/omap3_overo.h @@ -103,6 +103,7 @@ "4m(kernel),-(fs)"
#define CONFIG_CMD_I2C /* I2C serial bus support */ +#define CONFIG_I2C_CMD_TREE /* New-style command interface */
no longer needed, please remove.
#define CONFIG_CMD_MMC /* MMC support */ #define CONFIG_CMD_NAND /* NAND support */
@@ -113,6 +114,7 @@ #undef CONFIG_CMD_NET /* bootp, tftpboot, rarpboot */ #undef CONFIG_CMD_NFS /* NFS support */
+#define CONFIG_I2C_MULTI_BUS #define CONFIG_SYS_NO_FLASH #define CONFIG_SYS_I2C_SPEED 100000 #define CONFIG_SYS_I2C_SLAVE 1
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
bye, Heiko