diff options
author | Mugunthan V N <mugunthanvnm@ti.com> | 2016-07-18 15:11:00 +0530 |
---|---|---|
committer | Heiko Schocher <hs@denx.de> | 2016-07-26 08:39:57 +0200 |
commit | be243e4113b6c3c302ee03050726358714f40ffe (patch) | |
tree | 3093919d0486d00940f21c3bbae96bf926bb7a41 /drivers | |
parent | eff6b7731b03f3a387d83a2a5b7b78a3037e74b0 (diff) | |
download | u-boot-be243e4113b6c3c302ee03050726358714f40ffe.zip u-boot-be243e4113b6c3c302ee03050726358714f40ffe.tar.gz u-boot-be243e4113b6c3c302ee03050726358714f40ffe.tar.bz2 |
drivers: i2c: omap24xx_i2c: prepare driver for DM conversion
Prepare the driver for DM conversion.
Signed-off-by: Mugunthan V N <mugunthanvnm@ti.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/omap24xx_i2c.c | 308 |
1 files changed, 175 insertions, 133 deletions
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index a7f3fb4..8dea5fa 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -53,10 +53,6 @@ DECLARE_GLOBAL_DATA_PTR; /* Absolutely safe for status update at 100 kHz I2C: */ #define I2C_WAIT 200 -static int wait_for_bb(struct i2c_adapter *adap); -static struct i2c *omap24_get_base(struct i2c_adapter *adap); -static u16 wait_for_event(struct i2c_adapter *adap); -static void flush_fifo(struct i2c_adapter *adap); static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed) { unsigned int sampleclk, prescaler; @@ -90,9 +86,96 @@ static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed) } return -1; } -static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) + +/* + * Wait for the bus to be free by checking the Bus Busy (BB) + * bit to become clear + */ +static int wait_for_bb(struct i2c *i2c_base, int waitdelay) +{ + int timeout = I2C_TIMEOUT; + u16 stat; + + writew(0xFFFF, &i2c_base->stat); /* clear current interrupts...*/ +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) { +#else + /* Read RAW status */ + while ((stat = readw(&i2c_base->irqstatus_raw) & + I2C_STAT_BB) && timeout--) { +#endif + writew(stat, &i2c_base->stat); + udelay(waitdelay); + } + + if (timeout <= 0) { + printf("Timed out in wait_for_bb: status=%04x\n", + stat); + return 1; + } + writew(0xFFFF, &i2c_base->stat); /* clear delayed stuff*/ + return 0; +} + +/* + * Wait for the I2C controller to complete current action + * and update status + */ +static u16 wait_for_event(struct i2c *i2c_base, int waitdelay) +{ + u16 status; + int timeout = I2C_TIMEOUT; + + do { + udelay(waitdelay); +#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) + status = readw(&i2c_base->stat); +#else + /* Read RAW status */ + status = readw(&i2c_base->irqstatus_raw); +#endif + } 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_event: status=%04x\n", + status); + /* + * If status is still 0 here, probably the bus pads have + * not been configured for I2C, and/or pull-ups are missing. + */ + printf("Check if pads/pull-ups of bus are properly configured\n"); + writew(0xFFFF, &i2c_base->stat); + status = 0; + } + + return status; +} + +static void flush_fifo(struct i2c *i2c_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(&i2c_base->stat); + if (stat == I2C_STAT_RRDY) { + readb(&i2c_base->data); + writew(I2C_STAT_RRDY, &i2c_base->stat); + udelay(1000); + } else + break; + } +} + +static int __omap24_i2c_setspeed(struct i2c *i2c_base, uint speed, + int *waitdelay) { - struct i2c *i2c_base = omap24_get_base(adap); int psc, fsscll = 0, fssclh = 0; int hsscll = 0, hssclh = 0; u32 scll = 0, sclh = 0; @@ -142,8 +225,7 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) } } - adap->speed = speed; - adap->waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */ + *waitdelay = (10000000 / speed) * 2; /* wait for 20 clkperiods */ writew(0, &i2c_base->con); writew(psc, &i2c_base->psc); writew(scll, &i2c_base->scll); @@ -154,9 +236,8 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) return 0; } -static void omap24_i2c_deblock(struct i2c_adapter *adap) +static void omap24_i2c_deblock(struct i2c *i2c_base) { - struct i2c *i2c_base = omap24_get_base(adap); int i; u16 systest; u16 orgsystest; @@ -200,9 +281,9 @@ static void omap24_i2c_deblock(struct i2c_adapter *adap) writew(orgsystest, &i2c_base->systest); } -static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +static void __omap24_i2c_init(struct i2c *i2c_base, int speed, int slaveadd, + int *waitdelay) { - struct i2c *i2c_base = omap24_get_base(adap); int timeout = I2C_TIMEOUT; int deblock = 1; @@ -224,7 +305,7 @@ retry: udelay(1000); } - if (0 != omap24_i2c_setspeed(adap, speed)) { + if (0 != __omap24_i2c_setspeed(i2c_base, speed, waitdelay)) { printf("ERROR: failed to setup I2C bus-speed!\n"); return; } @@ -241,45 +322,24 @@ retry: I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie); #endif udelay(1000); - flush_fifo(adap); + flush_fifo(i2c_base); writew(0xFFFF, &i2c_base->stat); /* Handle possible failed I2C state */ - if (wait_for_bb(adap)) + if (wait_for_bb(i2c_base, *waitdelay)) if (deblock == 1) { - omap24_i2c_deblock(adap); + omap24_i2c_deblock(i2c_base); deblock = 0; goto retry; } } -static void flush_fifo(struct i2c_adapter *adap) -{ - struct i2c *i2c_base = omap24_get_base(adap); - 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_base->stat); - if (stat == I2C_STAT_RRDY) { - readb(&i2c_base->data); - writew(I2C_STAT_RRDY, &i2c_base->stat); - udelay(1000); - } else - break; - } -} - /* * i2c_probe: Use write access. Allows to identify addresses that are * write-only (like the config register of dual-port EEPROMs) */ -static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) +static int __omap24_i2c_probe(struct i2c *i2c_base, int waitdelay, uchar chip) { - struct i2c *i2c_base = omap24_get_base(adap); u16 status; int res = 1; /* default = fail */ @@ -287,7 +347,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) return res; /* Wait until bus is free */ - if (wait_for_bb(adap)) + if (wait_for_bb(i2c_base, waitdelay)) return res; /* No data transfer, slave addr only */ @@ -296,7 +356,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX | I2C_CON_STP, &i2c_base->con); - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); if ((status & ~I2C_STAT_XRDY) == 0 || (status & I2C_STAT_AL)) { /* @@ -306,8 +366,8 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) * following 'if' section: */ if (status == I2C_STAT_XRDY) - printf("i2c_probe: pads on bus %d probably not configured (status=0x%x)\n", - adap->hwadapnr, status); + printf("i2c_probe: pads on bus probably not configured (status=0x%x)\n", + status); goto pr_exit; } @@ -315,7 +375,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) /* Check for ACK (!NAK) */ if (!(status & I2C_STAT_NACK)) { res = 0; /* Device found */ - udelay(adap->waitdelay);/* Required by AM335X in SPL */ + udelay(waitdelay);/* Required by AM335X in SPL */ /* Abort transfer (force idle state) */ writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */ udelay(1000); @@ -323,7 +383,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) I2C_CON_STP, &i2c_base->con); /* STP */ } pr_exit: - flush_fifo(adap); + flush_fifo(i2c_base); writew(0xFFFF, &i2c_base->stat); return res; } @@ -341,10 +401,9 @@ pr_exit: * or that do not need a register address at all (such as some clock * distributors). */ -static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, - int alen, uchar *buffer, int len) +static int __omap24_i2c_read(struct i2c *i2c_base, int waitdelay, uchar chip, + uint addr, int alen, uchar *buffer, int len) { - struct i2c *i2c_base = omap24_get_base(adap); int i2c_error = 0; u16 status; @@ -389,7 +448,7 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, #endif /* Wait until bus not busy */ - if (wait_for_bb(adap)) + if (wait_for_bb(i2c_base, waitdelay)) return 1; /* Zero, one or two bytes reg address (offset) */ @@ -410,12 +469,12 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, #endif /* Send register offset */ while (1) { - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); /* Try to identify bus that is not padconf'd for I2C */ if (status == I2C_STAT_XRDY) { i2c_error = 2; - printf("i2c_read (addr phase): pads on bus %d probably not configured (status=0x%x)\n", - adap->hwadapnr, status); + printf("i2c_read (addr phase): pads on bus probably not configured (status=0x%x)\n", + status); goto rd_exit; } if (status == 0 || (status & I2C_STAT_NACK)) { @@ -450,7 +509,7 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, /* Receive data */ while (1) { - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); /* * Try to identify bus that is not padconf'd for I2C. This * state could be left over from previous transactions if @@ -458,8 +517,8 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, */ if (status == I2C_STAT_XRDY) { i2c_error = 2; - printf("i2c_read (data phase): pads on bus %d probably not configured (status=0x%x)\n", - adap->hwadapnr, status); + printf("i2c_read (data phase): pads on bus probably not configured (status=0x%x)\n", + status); goto rd_exit; } if (status == 0 || (status & I2C_STAT_NACK)) { @@ -477,16 +536,15 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, } rd_exit: - flush_fifo(adap); + flush_fifo(i2c_base); writew(0xFFFF, &i2c_base->stat); return i2c_error; } /* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */ -static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, - int alen, uchar *buffer, int len) +static int __omap24_i2c_write(struct i2c *i2c_base, int waitdelay, uchar chip, + uint addr, int alen, uchar *buffer, int len) { - struct i2c *i2c_base = omap24_get_base(adap); int i; u16 status; int i2c_error = 0; @@ -536,7 +594,7 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, #endif /* Wait until bus not busy */ - if (wait_for_bb(adap)) + if (wait_for_bb(i2c_base, waitdelay)) return 1; /* Start address phase - will write regoffset + len bytes data */ @@ -549,12 +607,12 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, while (alen) { /* Must write reg offset (one or two bytes) */ - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); /* Try to identify bus that is not padconf'd for I2C */ if (status == I2C_STAT_XRDY) { i2c_error = 2; - printf("i2c_write: pads on bus %d probably not configured (status=0x%x)\n", - adap->hwadapnr, status); + printf("i2c_write: pads on bus probably not configured (status=0x%x)\n", + status); goto wr_exit; } if (status == 0 || (status & I2C_STAT_NACK)) { @@ -576,7 +634,7 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, } /* Address phase is over, now write data */ for (i = 0; i < len; i++) { - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); if (status == 0 || (status & I2C_STAT_NACK)) { i2c_error = 1; printf("i2c_write: error waiting for data ACK (status=0x%x)\n", @@ -598,87 +656,21 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, * transferred on the bus. */ do { - status = wait_for_event(adap); + status = wait_for_event(i2c_base, waitdelay); } while (!(status & I2C_STAT_ARDY) && timeout--); if (timeout <= 0) printf("i2c_write: timed out writig last byte!\n"); wr_exit: - flush_fifo(adap); + flush_fifo(i2c_base); writew(0xFFFF, &i2c_base->stat); return i2c_error; } /* - * Wait for the bus to be free by checking the Bus Busy (BB) - * bit to become clear - */ -static int wait_for_bb(struct i2c_adapter *adap) -{ - struct i2c *i2c_base = omap24_get_base(adap); - int timeout = I2C_TIMEOUT; - u16 stat; - - writew(0xFFFF, &i2c_base->stat); /* clear current interrupts...*/ -#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) - while ((stat = readw(&i2c_base->stat) & I2C_STAT_BB) && timeout--) { -#else - /* Read RAW status */ - while ((stat = readw(&i2c_base->irqstatus_raw) & - I2C_STAT_BB) && timeout--) { -#endif - writew(stat, &i2c_base->stat); - udelay(adap->waitdelay); - } - - if (timeout <= 0) { - printf("Timed out in wait_for_bb: status=%04x\n", - stat); - return 1; - } - writew(0xFFFF, &i2c_base->stat); /* clear delayed stuff*/ - return 0; -} - -/* - * Wait for the I2C controller to complete current action - * and update status + * The legacy I2C functions. These need to get removed once + * all users of this driver are converted to DM. */ -static u16 wait_for_event(struct i2c_adapter *adap) -{ - struct i2c *i2c_base = omap24_get_base(adap); - u16 status; - int timeout = I2C_TIMEOUT; - - do { - udelay(adap->waitdelay); -#if defined(CONFIG_OMAP243X) || defined(CONFIG_OMAP34XX) - status = readw(&i2c_base->stat); -#else - /* Read RAW status */ - status = readw(&i2c_base->irqstatus_raw); -#endif - } 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_event: status=%04x\n", - status); - /* - * If status is still 0 here, probably the bus pads have - * not been configured for I2C, and/or pull-ups are missing. - */ - printf("Check if pads/pull-ups of bus %d are properly configured\n", - adap->hwadapnr); - writew(0xFFFF, &i2c_base->stat); - status = 0; - } - - return status; -} - static struct i2c *omap24_get_base(struct i2c_adapter *adap) { switch (adap->hwadapnr) { @@ -710,6 +702,56 @@ static struct i2c *omap24_get_base(struct i2c_adapter *adap) return NULL; } + +static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) +{ + struct i2c *i2c_base = omap24_get_base(adap); + + return __omap24_i2c_read(i2c_base, adap->waitdelay, chip, addr, + alen, buffer, len); +} + + +static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) +{ + struct i2c *i2c_base = omap24_get_base(adap); + + return __omap24_i2c_write(i2c_base, adap->waitdelay, chip, addr, + alen, buffer, len); +} + +static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed) +{ + struct i2c *i2c_base = omap24_get_base(adap); + int ret; + + ret = __omap24_i2c_setspeed(i2c_base, speed, &adap->waitdelay); + if (ret) { + error("%s: set i2c speed failed\n", __func__); + return ret; + } + + adap->speed = speed; + + return 0; +} + +static void omap24_i2c_init(struct i2c_adapter *adap, int speed, int slaveadd) +{ + struct i2c *i2c_base = omap24_get_base(adap); + + return __omap24_i2c_init(i2c_base, speed, slaveadd, &adap->waitdelay); +} + +static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip) +{ + struct i2c *i2c_base = omap24_get_base(adap); + + return __omap24_i2c_probe(i2c_base, adap->waitdelay, chip); +} + #if !defined(CONFIG_SYS_OMAP24_I2C_SPEED1) #define CONFIG_SYS_OMAP24_I2C_SPEED1 CONFIG_SYS_OMAP24_I2C_SPEED #endif |