|
@@ -53,10 +53,6 @@ DECLARE_GLOBAL_DATA_PTR;
|
|
/* Absolutely safe for status update at 100 kHz I2C: */
|
|
/* Absolutely safe for status update at 100 kHz I2C: */
|
|
#define I2C_WAIT 200
|
|
#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)
|
|
static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
|
|
{
|
|
{
|
|
unsigned int sampleclk, prescaler;
|
|
unsigned int sampleclk, prescaler;
|
|
@@ -90,9 +86,96 @@ static int omap24_i2c_findpsc(u32 *pscl, u32 *psch, uint speed)
|
|
}
|
|
}
|
|
return -1;
|
|
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 psc, fsscll = 0, fssclh = 0;
|
|
int hsscll = 0, hssclh = 0;
|
|
int hsscll = 0, hssclh = 0;
|
|
u32 scll = 0, sclh = 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(0, &i2c_base->con);
|
|
writew(psc, &i2c_base->psc);
|
|
writew(psc, &i2c_base->psc);
|
|
writew(scll, &i2c_base->scll);
|
|
writew(scll, &i2c_base->scll);
|
|
@@ -154,9 +236,8 @@ static uint omap24_i2c_setspeed(struct i2c_adapter *adap, uint speed)
|
|
return 0;
|
|
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;
|
|
int i;
|
|
u16 systest;
|
|
u16 systest;
|
|
u16 orgsystest;
|
|
u16 orgsystest;
|
|
@@ -200,9 +281,9 @@ static void omap24_i2c_deblock(struct i2c_adapter *adap)
|
|
writew(orgsystest, &i2c_base->systest);
|
|
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 timeout = I2C_TIMEOUT;
|
|
int deblock = 1;
|
|
int deblock = 1;
|
|
|
|
|
|
@@ -224,7 +305,7 @@ retry:
|
|
udelay(1000);
|
|
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");
|
|
printf("ERROR: failed to setup I2C bus-speed!\n");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -241,45 +322,24 @@ retry:
|
|
I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie);
|
|
I2C_IE_NACK_IE | I2C_IE_AL_IE, &i2c_base->ie);
|
|
#endif
|
|
#endif
|
|
udelay(1000);
|
|
udelay(1000);
|
|
- flush_fifo(adap);
|
|
|
|
|
|
+ flush_fifo(i2c_base);
|
|
writew(0xFFFF, &i2c_base->stat);
|
|
writew(0xFFFF, &i2c_base->stat);
|
|
|
|
|
|
/* Handle possible failed I2C state */
|
|
/* Handle possible failed I2C state */
|
|
- if (wait_for_bb(adap))
|
|
|
|
|
|
+ if (wait_for_bb(i2c_base, *waitdelay))
|
|
if (deblock == 1) {
|
|
if (deblock == 1) {
|
|
- omap24_i2c_deblock(adap);
|
|
|
|
|
|
+ omap24_i2c_deblock(i2c_base);
|
|
deblock = 0;
|
|
deblock = 0;
|
|
goto retry;
|
|
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
|
|
* i2c_probe: Use write access. Allows to identify addresses that are
|
|
* write-only (like the config register of dual-port EEPROMs)
|
|
* 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;
|
|
u16 status;
|
|
int res = 1; /* default = fail */
|
|
int res = 1; /* default = fail */
|
|
|
|
|
|
@@ -287,7 +347,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
|
|
return res;
|
|
return res;
|
|
|
|
|
|
/* Wait until bus is free */
|
|
/* Wait until bus is free */
|
|
- if (wait_for_bb(adap))
|
|
|
|
|
|
+ if (wait_for_bb(i2c_base, waitdelay))
|
|
return res;
|
|
return res;
|
|
|
|
|
|
/* No data transfer, slave addr only */
|
|
/* 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 |
|
|
writew(I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
|
|
I2C_CON_STP, &i2c_base->con);
|
|
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)) {
|
|
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:
|
|
* following 'if' section:
|
|
*/
|
|
*/
|
|
if (status == I2C_STAT_XRDY)
|
|
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;
|
|
goto pr_exit;
|
|
}
|
|
}
|
|
@@ -315,7 +375,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
|
|
/* Check for ACK (!NAK) */
|
|
/* Check for ACK (!NAK) */
|
|
if (!(status & I2C_STAT_NACK)) {
|
|
if (!(status & I2C_STAT_NACK)) {
|
|
res = 0; /* Device found */
|
|
res = 0; /* Device found */
|
|
- udelay(adap->waitdelay);/* Required by AM335X in SPL */
|
|
|
|
|
|
+ udelay(waitdelay);/* Required by AM335X in SPL */
|
|
/* Abort transfer (force idle state) */
|
|
/* Abort transfer (force idle state) */
|
|
writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */
|
|
writew(I2C_CON_MST | I2C_CON_TRX, &i2c_base->con); /* Reset */
|
|
udelay(1000);
|
|
udelay(1000);
|
|
@@ -323,7 +383,7 @@ static int omap24_i2c_probe(struct i2c_adapter *adap, uchar chip)
|
|
I2C_CON_STP, &i2c_base->con); /* STP */
|
|
I2C_CON_STP, &i2c_base->con); /* STP */
|
|
}
|
|
}
|
|
pr_exit:
|
|
pr_exit:
|
|
- flush_fifo(adap);
|
|
|
|
|
|
+ flush_fifo(i2c_base);
|
|
writew(0xFFFF, &i2c_base->stat);
|
|
writew(0xFFFF, &i2c_base->stat);
|
|
return res;
|
|
return res;
|
|
}
|
|
}
|
|
@@ -341,10 +401,9 @@ pr_exit:
|
|
* or that do not need a register address at all (such as some clock
|
|
* or that do not need a register address at all (such as some clock
|
|
* distributors).
|
|
* 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;
|
|
int i2c_error = 0;
|
|
u16 status;
|
|
u16 status;
|
|
|
|
|
|
@@ -389,7 +448,7 @@ static int omap24_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr,
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* Wait until bus not busy */
|
|
/* Wait until bus not busy */
|
|
- if (wait_for_bb(adap))
|
|
|
|
|
|
+ if (wait_for_bb(i2c_base, waitdelay))
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
/* Zero, one or two bytes reg address (offset) */
|
|
/* 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
|
|
#endif
|
|
/* Send register offset */
|
|
/* Send register offset */
|
|
while (1) {
|
|
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 */
|
|
/* Try to identify bus that is not padconf'd for I2C */
|
|
if (status == I2C_STAT_XRDY) {
|
|
if (status == I2C_STAT_XRDY) {
|
|
i2c_error = 2;
|
|
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;
|
|
goto rd_exit;
|
|
}
|
|
}
|
|
if (status == 0 || (status & I2C_STAT_NACK)) {
|
|
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 */
|
|
/* Receive data */
|
|
while (1) {
|
|
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
|
|
* Try to identify bus that is not padconf'd for I2C. This
|
|
* state could be left over from previous transactions if
|
|
* 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) {
|
|
if (status == I2C_STAT_XRDY) {
|
|
i2c_error = 2;
|
|
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;
|
|
goto rd_exit;
|
|
}
|
|
}
|
|
if (status == 0 || (status & I2C_STAT_NACK)) {
|
|
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:
|
|
rd_exit:
|
|
- flush_fifo(adap);
|
|
|
|
|
|
+ flush_fifo(i2c_base);
|
|
writew(0xFFFF, &i2c_base->stat);
|
|
writew(0xFFFF, &i2c_base->stat);
|
|
return i2c_error;
|
|
return i2c_error;
|
|
}
|
|
}
|
|
|
|
|
|
/* i2c_write: Address (reg offset) may be 0, 1 or 2 bytes long. */
|
|
/* 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;
|
|
int i;
|
|
u16 status;
|
|
u16 status;
|
|
int i2c_error = 0;
|
|
int i2c_error = 0;
|
|
@@ -536,7 +594,7 @@ static int omap24_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr,
|
|
#endif
|
|
#endif
|
|
|
|
|
|
/* Wait until bus not busy */
|
|
/* Wait until bus not busy */
|
|
- if (wait_for_bb(adap))
|
|
|
|
|
|
+ if (wait_for_bb(i2c_base, waitdelay))
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
/* Start address phase - will write regoffset + len bytes data */
|
|
/* 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) {
|
|
while (alen) {
|
|
/* Must write reg offset (one or two bytes) */
|
|
/* 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 */
|
|
/* Try to identify bus that is not padconf'd for I2C */
|
|
if (status == I2C_STAT_XRDY) {
|
|
if (status == I2C_STAT_XRDY) {
|
|
i2c_error = 2;
|
|
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;
|
|
goto wr_exit;
|
|
}
|
|
}
|
|
if (status == 0 || (status & I2C_STAT_NACK)) {
|
|
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 */
|
|
/* Address phase is over, now write data */
|
|
for (i = 0; i < len; i++) {
|
|
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)) {
|
|
if (status == 0 || (status & I2C_STAT_NACK)) {
|
|
i2c_error = 1;
|
|
i2c_error = 1;
|
|
printf("i2c_write: error waiting for data ACK (status=0x%x)\n",
|
|
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.
|
|
* transferred on the bus.
|
|
*/
|
|
*/
|
|
do {
|
|
do {
|
|
- status = wait_for_event(adap);
|
|
|
|
|
|
+ status = wait_for_event(i2c_base, waitdelay);
|
|
} while (!(status & I2C_STAT_ARDY) && timeout--);
|
|
} while (!(status & I2C_STAT_ARDY) && timeout--);
|
|
if (timeout <= 0)
|
|
if (timeout <= 0)
|
|
printf("i2c_write: timed out writig last byte!\n");
|
|
printf("i2c_write: timed out writig last byte!\n");
|
|
|
|
|
|
wr_exit:
|
|
wr_exit:
|
|
- flush_fifo(adap);
|
|
|
|
|
|
+ flush_fifo(i2c_base);
|
|
writew(0xFFFF, &i2c_base->stat);
|
|
writew(0xFFFF, &i2c_base->stat);
|
|
return i2c_error;
|
|
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)
|
|
static struct i2c *omap24_get_base(struct i2c_adapter *adap)
|
|
{
|
|
{
|
|
switch (adap->hwadapnr) {
|
|
switch (adap->hwadapnr) {
|
|
@@ -710,6 +702,56 @@ static struct i2c *omap24_get_base(struct i2c_adapter *adap)
|
|
return NULL;
|
|
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)
|
|
#if !defined(CONFIG_SYS_OMAP24_I2C_SPEED1)
|
|
#define CONFIG_SYS_OMAP24_I2C_SPEED1 CONFIG_SYS_OMAP24_I2C_SPEED
|
|
#define CONFIG_SYS_OMAP24_I2C_SPEED1 CONFIG_SYS_OMAP24_I2C_SPEED
|
|
#endif
|
|
#endif
|