svn commit: r244496 - projects/efika_mx/sys/arm/freescale/imx
Aleksandr Rybalko
ray at FreeBSD.org
Thu Dec 20 18:12:40 UTC 2012
Author: ray
Date: Thu Dec 20 18:12:40 2012
New Revision: 244496
URL: http://svnweb.freebsd.org/changeset/base/244496
Log:
Copy from sys/powerpc/mpc85xx/i2c.c to keep log.
Sponsored by: FreeBSD Foundation
Added:
projects/efika_mx/sys/arm/freescale/imx/i2c.c
- copied, changed from r243507, projects/efika_mx/sys/powerpc/mpc85xx/i2c.c
Copied and modified: projects/efika_mx/sys/arm/freescale/imx/i2c.c (from r243507, projects/efika_mx/sys/powerpc/mpc85xx/i2c.c)
==============================================================================
--- projects/efika_mx/sys/powerpc/mpc85xx/i2c.c Sun Nov 25 12:11:09 2012 (r243507, copy source)
+++ projects/efika_mx/sys/arm/freescale/imx/i2c.c Thu Dec 20 18:12:40 2012 (r244496)
@@ -130,6 +130,7 @@ static __inline void
i2c_write_reg(struct i2c_softc *sc, bus_size_t off, uint8_t val)
{
+// printf("0x%08x = %02x\n", (uint32_t)(sc->bsh + off), val);
bus_space_write_1(sc->bst, sc->bsh, off, val);
}
@@ -158,7 +159,7 @@ i2c_do_wait(device_t dev, struct i2c_sof
status = i2c_read_reg(sc, I2C_STATUS_REG);
if (status & I2CSR_MIF) {
- if (write && start && (status & I2CSR_RXAK)) {
+ if (write && start && ((status & 0xa2) != (0xa2) )) {
debugf("no ack %s", start ?
"after sending slave address" : "");
err = IIC_ENOACK;
@@ -169,16 +170,19 @@ i2c_do_wait(device_t dev, struct i2c_sof
err = IIC_EBUSERR;
goto error;
}
- if (!write && !(status & I2CSR_MCF)) {
+ if (!write && ( (status & 0x82) != 0x82 )) {
debugf("transfer unfinished");
err = IIC_EBUSERR;
goto error;
}
}
+// i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+
return (IIC_NOERR);
error:
+ printf("wait: st=%02x\n", status);
i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
return (err);
@@ -251,6 +255,21 @@ i2c_attach(device_t dev)
bus_generic_attach(dev);
return (IIC_NOERR);
}
+
+static int
+wait_for_iif(struct i2c_softc *sc)
+{
+ int retry = 10000;
+
+ while (retry --) {
+ if (i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MIF)
+ return (IIC_NOERR);
+ DELAY(10);
+ }
+
+ return (IIC_ETIMEOUT);
+}
+
static int
i2c_repeated_start(device_t dev, u_char slave, int timeout)
{
@@ -261,12 +280,19 @@ i2c_repeated_start(device_t dev, u_char
mtx_lock(&sc->mutex);
/* Set repeated start condition */
- i2c_flag_set(sc, I2C_CONTROL_REG ,I2CCR_RSTA);
+ i2c_flag_set(sc, I2C_CONTROL_REG ,I2CCR_RSTA|I2CCR_TXAK);
+ /* Clear status */
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
/* Write target address - LSB is R/W bit */
i2c_write_reg(sc, I2C_DATA_REG, slave);
- DELAY(1250);
+//2 DELAY(1250);
+
+ if (0) error = i2c_do_wait(dev, sc, 1, 1);
+ error = wait_for_iif(sc);
+
+ /* Clear status */
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
- error = i2c_do_wait(dev, sc, 1, 1);
mtx_unlock(&sc->mutex);
if (error)
@@ -283,12 +309,17 @@ i2c_start(device_t dev, u_char slave, in
int error;
sc = device_get_softc(dev);
- DELAY(1000);
+//2 DELAY(1000);
mtx_lock(&sc->mutex);
status = i2c_read_reg(sc, I2C_STATUS_REG);
/* Check if bus is idle or busy */
if (status & I2CSR_MBB) {
+// i2c_write_reg(sc, I2C_CONTROL_REG, 0);
+// DELAY(1000);
+// i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
+
+
debugf("bus busy");
mtx_unlock(&sc->mutex);
i2c_stop(dev);
@@ -296,12 +327,21 @@ i2c_start(device_t dev, u_char slave, in
}
/* Set start condition */
- i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_MSTA | I2CCR_MTX);
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_MSTA | I2CCR_TXAK);
+//3 DELAY(1250);
+ DELAY(100);//3
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_MSTA | I2CCR_MTX | I2CCR_TXAK);
+ /* Clear status */
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
/* Write target address - LSB is R/W bit */
i2c_write_reg(sc, I2C_DATA_REG, slave);
- DELAY(1250);
+//1 DELAY(1250);
+
+ if (0) error = i2c_do_wait(dev, sc, 1, 1);
+ error = wait_for_iif(sc);
- error = i2c_do_wait(dev, sc, 1, 1);
+ /* Clear status */
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
mtx_unlock(&sc->mutex);
if (error)
@@ -311,6 +351,21 @@ i2c_start(device_t dev, u_char slave, in
}
static int
+wait_for_nibb(struct i2c_softc *sc)
+{
+ int retry = 1000;
+
+ while (retry --) {
+ if ((i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MBB) == 0)
+ return (IIC_NOERR);
+ DELAY(10);
+ }
+
+ return (IIC_ETIMEOUT);
+}
+
+
+static int
i2c_stop(device_t dev)
{
struct i2c_softc *sc;
@@ -318,7 +373,16 @@ i2c_stop(device_t dev)
sc = device_get_softc(dev);
mtx_lock(&sc->mutex);
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
- DELAY(1000);
+//4 DELAY(1000);
+ DELAY(100);//4
+ /* Reset controller if bus still busy after STOP */
+ if (wait_for_nibb(sc) == IIC_ETIMEOUT) {
+ i2c_write_reg(sc, I2C_CONTROL_REG, 0);
+ DELAY(1000);
+ i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN | I2CCR_TXAK);
+//1 DELAY(1000);
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+ }
mtx_unlock(&sc->mutex);
return (IIC_NOERR);
@@ -348,26 +412,44 @@ i2c_reset(device_t dev, u_char speed, u_
i2c_write_reg(sc, I2C_CONTROL_REG, 0x0);
i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
DELAY(1000);
- i2c_write_reg(sc, I2C_FDR_REG, baud_rate);
+// i2c_write_reg(sc, I2C_FDR_REG, baud_rate);
+ i2c_write_reg(sc, I2C_FDR_REG, 20);
if (!(sc->flags & FSL_IMX_I2C))
i2c_write_reg(sc, I2C_DFSRR_REG, I2C_DFSSR_DIV);
i2c_write_reg(sc, I2C_CONTROL_REG, I2C_ENABLE);
DELAY(1000);
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
mtx_unlock(&sc->mutex);
return (IIC_NOERR);
}
static int
+wait_for_icf(struct i2c_softc *sc)
+{
+ int retry = 1000;
+
+ while (retry --) {
+// if (i2c_read_reg(sc, I2C_STATUS_REG) & I2CSR_MCF)
+ if ((i2c_read_reg(sc, I2C_STATUS_REG) & (I2CSR_MCF|I2CSR_MIF)) == (I2CSR_MCF|I2CSR_MIF))
+ return (IIC_NOERR);
+ DELAY(10);
+ }
+
+ return (IIC_ETIMEOUT);
+}
+
+static int
i2c_read(device_t dev, char *buf, int len, int *read, int last, int delay)
{
struct i2c_softc *sc;
- int error;
+ int error, reg;
sc = device_get_softc(dev);
*read = 0;
mtx_lock(&sc->mutex);
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
if (len) {
if (len == 1)
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
@@ -377,18 +459,23 @@ i2c_read(device_t dev, char *buf, int le
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
I2CCR_MSTA);
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
/* dummy read */
+ //printf("RD %02x\n", i2c_read_reg(sc, I2C_DATA_REG));
i2c_read_reg(sc, I2C_DATA_REG);
DELAY(1000);
}
while (*read < len) {
- DELAY(1000);
- error = i2c_do_wait(dev, sc, 0, 0);
+//1 DELAY(1000);
+ if (0) error = i2c_do_wait(dev, sc, 0, 0);
+ error = wait_for_icf(sc);
if (error) {
mtx_unlock(&sc->mutex);
+ //printf("RE %02x\n", i2c_read_reg(sc, I2C_DATA_REG));
return (error);
}
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
if ((*read == len - 2) && last) {
i2c_write_reg(sc, I2C_CONTROL_REG, I2CCR_MEN |
I2CCR_MSTA | I2CCR_TXAK);
@@ -399,10 +486,14 @@ i2c_read(device_t dev, char *buf, int le
I2CCR_TXAK);
}
- *buf++ = i2c_read_reg(sc, I2C_DATA_REG);
+ reg = i2c_read_reg(sc, I2C_DATA_REG);
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
+ //printf("R %02x\n", reg);
+ *buf++ = reg;
(*read)++;
- DELAY(1250);
+//1 DELAY(1250);
}
+// printf("RA %02x\n", i2c_read_reg(sc, I2C_DATA_REG));
mtx_unlock(&sc->mutex);
return (IIC_NOERR);
@@ -419,10 +510,13 @@ i2c_write(device_t dev, const char *buf,
mtx_lock(&sc->mutex);
while (*sent < len) {
+ i2c_write_reg(sc, I2C_STATUS_REG, 0x0);
i2c_write_reg(sc, I2C_DATA_REG, *buf++);
- DELAY(1250);
+//1 DELAY(1250);
+
- error = i2c_do_wait(dev, sc, 1, 0);
+ if (0) error = i2c_do_wait(dev, sc, 1, 0);
+ error = wait_for_iif(sc);
if (error) {
mtx_unlock(&sc->mutex);
return (error);
More information about the svn-src-projects
mailing list