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>
This commit is contained in:
Mugunthan V N 2016-07-18 15:11:00 +05:30 committed by Heiko Schocher
parent eff6b7731b
commit be243e4113

View File

@ -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
* The legacy I2C functions. These need to get removed once
* all users of this driver are converted to DM.
*/
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
*/
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