Skip site navigation (1)Skip section navigation (2)
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>