Subject: [PATCH 10/13 v3] ARM: OMAP3: Add I2C support From: Dirk Behme <[EMAIL PROTECTED]>
Add I2C support Signed-off-by: Dirk Behme <[EMAIL PROTECTED]> --- Changes in version v2: - Remove SMC911X network init as proposed by Ben Warren. Thanks! drivers/i2c/Makefile | 1 drivers/i2c/omap24xx_i2c.c | 132 ++++++++++++++++++++++++++------------------- drivers/net/Makefile | 1 3 files changed, 80 insertions(+), 54 deletions(-) Index: u-boot-arm/drivers/i2c/Makefile =================================================================== --- u-boot-arm.orig/drivers/i2c/Makefile +++ u-boot-arm/drivers/i2c/Makefile @@ -29,6 +29,7 @@ COBJS-$(CONFIG_FSL_I2C) += fsl_i2c.o COBJS-$(CONFIG_I2C_MXC) += mxc_i2c.o COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o +COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_SOFT_I2C) += soft_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o Index: u-boot-arm/drivers/i2c/omap24xx_i2c.c =================================================================== --- u-boot-arm.orig/drivers/i2c/omap24xx_i2c.c +++ u-boot-arm/drivers/i2c/omap24xx_i2c.c @@ -25,8 +25,10 @@ #include <asm/arch/i2c.h> #include <asm/io.h> +#define inb(a) __raw_readb(a) +#define outb(a, v) __raw_writeb(a, v) #define inw(a) __raw_readw(a) -#define outw(a,v) __raw_writew(a,v) +#define outw(a, v) __raw_writew(a, v) static void wait_for_bb (void); static u16 wait_for_pin (void); @@ -40,28 +42,28 @@ void i2c_init (int speed, int slaveadd) udelay(1000); outw(0x0, I2C_SYSC); /* will probably self clear but */ - if (inw (I2C_CON) & I2C_CON_EN) { - outw (0, I2C_CON); + if (inw(I2C_CON) & I2C_CON_EN) { + outw(0, I2C_CON); udelay (50000); } /* 12Mhz I2C module clock */ - outw (0, I2C_PSC); + outw(0, I2C_PSC); speed = speed/1000; /* 100 or 400 */ scl = ((12000/(speed*2)) - 7); /* use 7 when PSC = 0 */ - outw (scl, I2C_SCLL); - outw (scl, I2C_SCLH); + outw(scl, I2C_SCLL); + outw(scl, I2C_SCLH); /* own address */ - outw (slaveadd, I2C_OA); - outw (I2C_CON_EN, I2C_CON); + outw(slaveadd, I2C_OA); + outw(I2C_CON_EN, I2C_CON); /* have to enable intrrupts or OMAP i2c module doesn't work */ - outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | - I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE); + outw(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(); - outw (0xFFFF, I2C_STAT); - outw (0, I2C_CNT); + outw(0xFFFF, I2C_STAT); + outw(0, I2C_CNT); } static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value) @@ -73,11 +75,11 @@ static int i2c_read_byte (u8 devaddr, u8 wait_for_bb (); /* one byte only */ - outw (1, I2C_CNT); + outw(1, I2C_CNT); /* set slave address */ - outw (devaddr, I2C_SA); + outw(devaddr, I2C_SA); /* no stop bit needed here */ - outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON); + outw(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON); status = wait_for_pin (); @@ -85,7 +87,7 @@ static int i2c_read_byte (u8 devaddr, u8 /* Important: have to use byte access */ *(volatile u8 *) (I2C_DATA) = regoffset; udelay (20000); - if (inw (I2C_STAT) & I2C_STAT_NACK) { + if (inw(I2C_STAT) & I2C_STAT_NACK) { i2c_error = 1; } } else { @@ -94,42 +96,46 @@ static int i2c_read_byte (u8 devaddr, u8 if (!i2c_error) { /* free bus, otherwise we can't use a combined transction */ - outw (0, I2C_CON); - while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) { + outw(0, I2C_CON); + while (inw(I2C_STAT) || (inw(I2C_CON) & I2C_CON_MST)) { udelay (10000); /* Have to clear pending interrupt to clear I2C_STAT */ - outw (0xFFFF, I2C_STAT); + outw(0xFFFF, I2C_STAT); } wait_for_bb (); /* set slave address */ - outw (devaddr, I2C_SA); + outw(devaddr, I2C_SA); /* read one byte from slave */ - outw (1, I2C_CNT); + outw(1, I2C_CNT); /* need stop bit here */ - outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, - I2C_CON); + outw(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, + I2C_CON); status = wait_for_pin (); if (status & I2C_STAT_RRDY) { - *value = inw (I2C_DATA); +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + *value = inb(I2C_DATA); +#else + *value = inw(I2C_DATA); +#endif udelay (20000); } else { i2c_error = 1; } if (!i2c_error) { - outw (I2C_CON_EN, I2C_CON); - while (inw (I2C_STAT) - || (inw (I2C_CON) & I2C_CON_MST)) { + outw(I2C_CON_EN, I2C_CON); + while (inw(I2C_STAT) + || (inw(I2C_CON) & I2C_CON_MST)) { udelay (10000); - outw (0xFFFF, I2C_STAT); + outw(0xFFFF, I2C_STAT); } } } flush_fifo(); - outw (0xFFFF, I2C_STAT); - outw (0, I2C_CNT); + outw(0xFFFF, I2C_STAT); + outw(0, I2C_CNT); return i2c_error; } @@ -142,22 +148,37 @@ static int i2c_write_byte (u8 devaddr, u wait_for_bb (); /* two bytes */ - outw (2, I2C_CNT); + outw(2, I2C_CNT); /* set slave address */ - outw (devaddr, I2C_SA); + outw(devaddr, I2C_SA); /* stop bit needed here */ - outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | - I2C_CON_STP, I2C_CON); + outw(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) { +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + /* send out 1 byte */ + outb(regoffset, I2C_DATA); + outw(I2C_STAT_XRDY, I2C_STAT); + status = wait_for_pin(); + if ((status & I2C_STAT_XRDY)) { + /* send out next 1 byte */ + outb(value, I2C_DATA); + outw(I2C_STAT_XRDY, I2C_STAT); + } else { + i2c_error = 1; + } +#else /* send out two bytes */ - outw ((value << 8) + regoffset, I2C_DATA); + outw((value << 8) + regoffset, I2C_DATA); +#endif + /* must have enough delay to allow BB bit to go low */ udelay (50000); - if (inw (I2C_STAT) & I2C_STAT_NACK) { + if (inw(I2C_STAT) & I2C_STAT_NACK) { i2c_error = 1; } } else { @@ -167,18 +188,18 @@ static int i2c_write_byte (u8 devaddr, u if (!i2c_error) { int eout = 200; - outw (I2C_CON_EN, I2C_CON); - while ((stat = inw (I2C_STAT)) || (inw (I2C_CON) & I2C_CON_MST)) { + outw(I2C_CON_EN, I2C_CON); + while ((stat = inw(I2C_STAT)) || (inw(I2C_CON) & I2C_CON_MST)) { udelay (1000); /* have to read to clear intrrupt */ - outw (0xFFFF, I2C_STAT); + outw(0xFFFF, I2C_STAT); if(--eout == 0) /* better leave with error than hang */ break; } } flush_fifo(); - outw (0xFFFF, I2C_STAT); - outw (0, I2C_CNT); + outw(0xFFFF, I2C_STAT); + outw(0, I2C_CNT); return i2c_error; } @@ -191,7 +212,11 @@ static void flush_fifo(void) while(1){ stat = inw(I2C_STAT); if(stat == I2C_STAT_RRDY){ +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + inb(I2C_DATA); +#else inw(I2C_DATA); +#endif outw(I2C_STAT_RRDY,I2C_STAT); udelay(1000); }else @@ -203,34 +228,33 @@ int i2c_probe (uchar chip) { int res = 1; /* default = fail */ - if (chip == inw (I2C_OA)) { + if (chip == inw(I2C_OA)) return res; - } /* wait until bus not busy */ wait_for_bb (); /* try to read one byte */ - outw (1, I2C_CNT); + outw(1, I2C_CNT); /* set slave address */ - outw (chip, I2C_SA); + outw(chip, I2C_SA); /* stop bit needed here */ - outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON); + outw(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON); /* enough delay for the NACK bit set */ udelay (50000); - if (!(inw (I2C_STAT) & I2C_STAT_NACK)) { + if (!(inw(I2C_STAT) & I2C_STAT_NACK)) { res = 0; /* success case */ flush_fifo(); outw(0xFFFF, I2C_STAT); } else { outw(0xFFFF, I2C_STAT); /* failue, clear sources*/ - outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */ + outw(inw(I2C_CON) | I2C_CON_STP, I2C_CON); /* finish up xfer */ udelay(20000); wait_for_bb (); } flush_fifo(); - outw (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/ + outw(0, I2C_CNT); /* don't allow any more data in...we don't want it.*/ outw(0xFFFF, I2C_STAT); return res; } @@ -291,14 +315,14 @@ static void wait_for_bb (void) u16 stat; outw(0xFFFF, I2C_STAT); /* clear current interruts...*/ - while ((stat = inw (I2C_STAT) & I2C_STAT_BB) && timeout--) { - outw (stat, I2C_STAT); + while ((stat = inw(I2C_STAT) & I2C_STAT_BB) && timeout--) { + outw(stat, I2C_STAT); udelay (50000); } if (timeout <= 0) { printf ("timed out in wait_for_bb: I2C_STAT=%x\n", - inw (I2C_STAT)); + inw(I2C_STAT)); } outw(0xFFFF, I2C_STAT); /* clear delayed stuff*/ } @@ -310,7 +334,7 @@ static u16 wait_for_pin (void) do { udelay (1000); - status = inw (I2C_STAT); + status = inw(I2C_STAT); } while ( !(status & (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY | I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK | @@ -318,7 +342,7 @@ static u16 wait_for_pin (void) if (timeout <= 0) { printf ("timed out in wait_for_pin: I2C_STAT=%x\n", - inw (I2C_STAT)); + inw(I2C_STAT)); outw(0xFFFF, I2C_STAT); } return status; _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot