Date: Thu, 20 Dec 2012 18:12:40 +0000 (UTC) From: Aleksandr Rybalko <ray@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r244496 - projects/efika_mx/sys/arm/freescale/imx Message-ID: <201212201812.qBKICesG096209@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212201812.qBKICesG096209>