X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=drivers%2Fi2c%2Fomap24xx_i2c.c;h=ff18991f0e49d9bdf536f9703af33ad1cfe09feb;hb=b46b353b901a45ebe860f8bf874ca99f018cd410;hp=7dab78685dfb44102295a2cf138d49f48118b9ac;hpb=6a40ef62c4300e9f606deef0a4618cbc4b514a51;p=oweals%2Fu-boot.git diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 7dab78685d..ff18991f0e 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -22,48 +22,110 @@ #include -#ifdef CONFIG_DRIVER_OMAP24XX_I2C - #include #include -#define inw(a) __raw_readw(a) -#define outw(a,v) __raw_writew(a,v) - 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) { - u16 scl; + int psc, fsscll, fssclh; + int hsscll = 0, hssclh = 0; + u32 scll, sclh; + + /* Only handle standard, fast and high speeds */ + if ((speed != OMAP_I2C_STANDARD) && + (speed != OMAP_I2C_FAST_MODE) && + (speed != OMAP_I2C_HIGH_SPEED)) { + printf("Error : I2C unsupported speed %d\n", speed); + return; + } + + psc = I2C_IP_CLK / I2C_INTERNAL_SAMPLING_CLK; + psc -= 1; + if (psc < I2C_PSC_MIN) { + printf("Error : I2C unsupported prescalar %d\n", psc); + return; + } + + if (speed == OMAP_I2C_HIGH_SPEED) { + /* High speed */ + + /* For first phase of HS mode */ + fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / + (2 * OMAP_I2C_FAST_MODE); + + fsscll -= I2C_HIGHSPEED_PHASE_ONE_SCLL_TRIM; + fssclh -= I2C_HIGHSPEED_PHASE_ONE_SCLH_TRIM; + if (((fsscll < 0) || (fssclh < 0)) || + ((fsscll > 255) || (fssclh > 255))) { + printf("Error : I2C initializing first phase clock\n"); + return; + } + + /* For second phase of HS mode */ + hsscll = hssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); + + hsscll -= I2C_HIGHSPEED_PHASE_TWO_SCLL_TRIM; + hssclh -= I2C_HIGHSPEED_PHASE_TWO_SCLH_TRIM; + if (((fsscll < 0) || (fssclh < 0)) || + ((fsscll > 255) || (fssclh > 255))) { + printf("Error : I2C initializing second phase clock\n"); + return; + } + + scll = (unsigned int)hsscll << 8 | (unsigned int)fsscll; + sclh = (unsigned int)hssclh << 8 | (unsigned int)fssclh; + + } else { + /* Standard and fast speed */ + fsscll = fssclh = I2C_INTERNAL_SAMPLING_CLK / (2 * speed); + + fsscll -= I2C_FASTSPEED_SCLL_TRIM; + fssclh -= I2C_FASTSPEED_SCLH_TRIM; + if (((fsscll < 0) || (fssclh < 0)) || + ((fsscll > 255) || (fssclh > 255))) { + printf("Error : I2C initializing clock\n"); + return; + } - outw(0x2, I2C_SYSC); /* for ES2 after soft reset */ + scll = (unsigned int)fsscll; + sclh = (unsigned int)fssclh; + } + + writew(0x2, &i2c_base->sysc); /* for ES2 after soft reset */ udelay(1000); - outw(0x0, I2C_SYSC); /* will probably self clear but */ + writew(0x0, &i2c_base->sysc); /* will probably self clear but */ - if (inw (I2C_CON) & I2C_CON_EN) { - outw (0, I2C_CON); + if (readw (&i2c_base->con) & I2C_CON_EN) { + writew (0, &i2c_base->con); udelay (50000); } - /* 12Mhz I2C module clock */ - 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); + writew(psc, &i2c_base->psc); + writew(scll, &i2c_base->scll); + writew(sclh, &i2c_base->sclh); + /* own address */ - outw (slaveadd, I2C_OA); - outw (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 */ - outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | - I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE); + writew (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE | + I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie); udelay (1000); flush_fifo(); - outw (0xFFFF, I2C_STAT); - outw (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) @@ -75,19 +137,19 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value) wait_for_bb (); /* one byte only */ - outw (1, I2C_CNT); + writew (1, &i2c_base->cnt); /* set slave address */ - outw (devaddr, I2C_SA); + writew (devaddr, &i2c_base->sa); /* no stop bit needed here */ - outw (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 */ - *(volatile u8 *) (I2C_DATA) = regoffset; + writeb (regoffset, &i2c_base->data); udelay (20000); - if (inw (I2C_STAT) & I2C_STAT_NACK) { + if (readw (&i2c_base->stat) & I2C_STAT_NACK) { i2c_error = 1; } } else { @@ -96,42 +158,46 @@ static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value) 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)) { + 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 */ - outw (0xFFFF, I2C_STAT); + writew (0xFFFF, &i2c_base->stat); } wait_for_bb (); /* set slave address */ - outw (devaddr, I2C_SA); + writew (devaddr, &i2c_base->sa); /* read one byte from slave */ - outw (1, I2C_CNT); + writew (1, &i2c_base->cnt); /* need stop bit here */ - outw (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); status = wait_for_pin (); if (status & I2C_STAT_RRDY) { - *value = inw (I2C_DATA); +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + *value = readb (&i2c_base->data); +#else + *value = readw (&i2c_base->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)) { + writew (I2C_CON_EN, &i2c_base->con); + while (readw (&i2c_base->stat) + || (readw (&i2c_base->con) & I2C_CON_MST)) { udelay (10000); - outw (0xFFFF, I2C_STAT); + writew (0xFFFF, &i2c_base->stat); } } } flush_fifo(); - outw (0xFFFF, I2C_STAT); - outw (0, I2C_CNT); + writew (0xFFFF, &i2c_base->stat); + writew (0, &i2c_base->cnt); return i2c_error; } @@ -144,22 +210,37 @@ static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value) wait_for_bb (); /* two bytes */ - outw (2, I2C_CNT); + writew (2, &i2c_base->cnt); /* set slave address */ - outw (devaddr, I2C_SA); + writew (devaddr, &i2c_base->sa); /* stop bit needed here */ - outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | - I2C_CON_STP, I2C_CON); + writew (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | + I2C_CON_STP, &i2c_base->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 */ + 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_base->data); + writew (I2C_STAT_XRDY, &i2c_base->stat); + } else { + i2c_error = 1; + } +#else /* send out two bytes */ - outw ((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 (inw (I2C_STAT) & I2C_STAT_NACK) { + if (readw (&i2c_base->stat) & I2C_STAT_NACK) { i2c_error = 1; } } else { @@ -169,18 +250,18 @@ static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value) if (!i2c_error) { int eout = 200; - outw (I2C_CON_EN, I2C_CON); - while ((stat = inw (I2C_STAT)) || (inw (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 */ - outw (0xFFFF, I2C_STAT); + writew (0xFFFF, &i2c_base->stat); if(--eout == 0) /* better leave with error than hang */ break; } } flush_fifo(); - outw (0xFFFF, I2C_STAT); - outw (0, I2C_CNT); + writew (0xFFFF, &i2c_base->stat); + writew (0, &i2c_base->cnt); return i2c_error; } @@ -191,10 +272,14 @@ static void flush_fifo(void) * you get a bus error */ while(1){ - stat = inw(I2C_STAT); + stat = readw(&i2c_base->stat); if(stat == I2C_STAT_RRDY){ - inw(I2C_DATA); - outw(I2C_STAT_RRDY,I2C_STAT); +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + readb(&i2c_base->data); +#else + readw(&i2c_base->data); +#endif + writew(I2C_STAT_RRDY,&i2c_base->stat); udelay(1000); }else break; @@ -205,7 +290,7 @@ int i2c_probe (uchar chip) { int res = 1; /* default = fail */ - if (chip == inw (I2C_OA)) { + if (chip == readw (&i2c_base->oa)) { return res; } @@ -213,27 +298,27 @@ int i2c_probe (uchar chip) wait_for_bb (); /* try to read one byte */ - outw (1, I2C_CNT); + writew (1, &i2c_base->cnt); /* set slave address */ - outw (chip, I2C_SA); + writew (chip, &i2c_base->sa); /* stop bit needed here */ - outw (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 (!(inw (I2C_STAT) & I2C_STAT_NACK)) { + if (!(readw (&i2c_base->stat) & I2C_STAT_NACK)) { res = 0; /* success case */ flush_fifo(); - outw(0xFFFF, I2C_STAT); + writew(0xFFFF, &i2c_base->stat); } else { - outw(0xFFFF, I2C_STAT); /* failue, clear sources*/ - outw (inw (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(); - outw (0, I2C_CNT); /* don't allow any more data in...we don't want it.*/ - outw(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; } @@ -254,7 +339,7 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) for (i = 0; i < len; i++) { if (i2c_read_byte (chip, addr + i, &buffer[i])) { printf ("I2C read: I/O error\n"); - i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); return 1; } } @@ -279,7 +364,7 @@ int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) for (i = 0; i < len; i++) { if (i2c_write_byte (chip, addr + i, buffer[i])) { printf ("I2C read: I/O error\n"); - i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE); return 1; } } @@ -292,17 +377,17 @@ static void wait_for_bb (void) int timeout = 10; u16 stat; - outw(0xFFFF, I2C_STAT); /* clear current interruts...*/ - while ((stat = inw (I2C_STAT) & I2C_STAT_BB) && timeout--) { - outw (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", - inw (I2C_STAT)); + readw (&i2c_base->stat)); } - outw(0xFFFF, I2C_STAT); /* clear delayed stuff*/ + writew(0xFFFF, &i2c_base->stat); /* clear delayed stuff*/ } static u16 wait_for_pin (void) @@ -312,7 +397,7 @@ static u16 wait_for_pin (void) do { udelay (1000); - status = inw (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 | @@ -320,10 +405,33 @@ static u16 wait_for_pin (void) if (timeout <= 0) { printf ("timed out in wait_for_pin: I2C_STAT=%x\n", - inw (I2C_STAT)); - outw(0xFFFF, I2C_STAT); + readw (&i2c_base->stat)); + writew(0xFFFF, &i2c_base->stat); } return status; } -#endif /* CONFIG_DRIVER_OMAP24XX_I2C */ +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; +}