i2c/twsi/allwinner problems.

Daniel Braniss danny at cs.huji.ac.il
Wed Mar 31 05:06:18 UTC 2021


hi all,
after some time, I decided to try FreeBSD 13 on my all winner (nano neo) and got it working only with
debugging on, so I started cherry picking till I got it working, replacing printfs with DELAY
and this is is now working, of course not the correct solution, but if someone with better
i2c knowledge can propose a better solution I’m willing to test if with my program (it reads RFIDs using
a board with PN532),

this are the diffs:
diff --git a/sys/dev/iicbus/twsi/twsi.c b/sys/dev/iicbus/twsi/twsi.c
index a606c2aef..8ede62073 100644
--- a/sys/dev/iicbus/twsi/twsi.c
+++ b/sys/dev/iicbus/twsi/twsi.c
@@ -86,6 +86,8 @@ __FBSDID("$FreeBSD$");
#define	TWSI_DEBUG
#undef TWSI_DEBUG

+#define	debug_(dev, fmt, args...) device_printf(dev, "%s: " fmt, __func__, ##args)
+
#ifdef TWSI_DEBUG
#define	debugf(dev, fmt, args...) device_printf(dev, "%s: " fmt, __func__, ##args)
#else
@@ -103,6 +105,7 @@ TWSI_READ(struct twsi_softc *sc, bus_size_t off)
{
	uint32_t val;

+	DELAY(1000); // danny: needed 
	val = bus_read_4(sc->res[0], off);
	debugf(sc->dev, "read %x from %lx\n", val, off);
	return (val);
@@ -165,15 +168,14 @@ twsi_clear_iflg(struct twsi_softc *sc)
static int
twsi_poll_ctrl(struct twsi_softc *sc, int timeout, uint32_t mask)
{
-
	timeout /= 10;
-	debugf(sc->dev, "Waiting for ctrl reg to match mask %x\n", mask);
+	debug_(sc->dev, "Waiting for ctrl reg to match mask %x timeout=%d\n", mask, timeout);
	while (!(TWSI_READ(sc, sc->reg_control) & mask)) {
-		DELAY(10);
+		 // DELAY(10);
		if (--timeout < 0)
			return (timeout);
	}
-	debugf(sc->dev, "done\n");
+	debug_(sc->dev, "done\n");
	return (0);
}

@@ -212,7 +214,7 @@ twsi_locked_start(device_t dev, struct twsi_softc *sc, int32_t mask,
	DELAY(1000);

	if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
-		debugf(dev, "timeout sending %sSTART condition\n",
+		debug_(dev, "timeout sending %sSTART condition\n",
		    mask == TWSI_STATUS_START ? "" : "repeated ");
		return (IIC_ETIMEOUT);
	}
@@ -221,7 +223,7 @@ twsi_locked_start(device_t dev, struct twsi_softc *sc, int32_t mask,
	debugf(dev, "status=%x\n", status);

	if (status != mask) {
-		debugf(dev, "wrong status (%02x) after sending %sSTART condition\n",
+		debug_(dev, "wrong status (%02x) after sending %sSTART condition\n",
		    status, mask == TWSI_STATUS_START ? "" : "repeated ");
		return (IIC_ESTATUS);
	}
@@ -231,7 +233,7 @@ twsi_locked_start(device_t dev, struct twsi_softc *sc, int32_t mask,
	DELAY(1000);

	if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
-		debugf(dev, "timeout sending slave address (timeout=%d)\n", timeout);
+		debug_(dev, "timeout sending slave address (timeout=%d)\n", timeout);
		return (IIC_ETIMEOUT);
	}

@@ -239,7 +241,7 @@ twsi_locked_start(device_t dev, struct twsi_softc *sc, int32_t mask,
	status = TWSI_READ(sc, sc->reg_status);
	if (status != (read_access ?
	    TWSI_STATUS_ADDR_R_ACK : TWSI_STATUS_ADDR_W_ACK)) {
-		debugf(dev, "no ACK (status: %02x) after sending slave address\n",
+		debug_(dev, "no ACK (status: %02x) after sending slave address\n",
		    status);
		return (IIC_ENOACK);
	}
@@ -405,7 +407,8 @@ twsi_read(device_t dev, char *buf, int len, int *read, int last, int delay)
	int last_byte, rv;

	sc = device_get_softc(dev);
-
+	debug_(dev, "twsi_read: len=%d delay=%d", len, delay); // danny
+	
	mtx_lock(&sc->mutex);
	*read = 0;
	while (*read < len) {
@@ -423,7 +426,7 @@ twsi_read(device_t dev, char *buf, int len, int *read, int last, int delay)
		DELAY(1000);

		if (twsi_poll_ctrl(sc, delay, TWSI_CONTROL_IFLG)) {
-			debugf(dev, "timeout reading data (delay=%d)\n", delay);
+			debug_(dev, "timeout reading data (delay=%d)\n", delay);
			rv = IIC_ETIMEOUT;
			goto out;
		}
@@ -431,7 +434,7 @@ twsi_read(device_t dev, char *buf, int len, int *read, int last, int delay)
		status = TWSI_READ(sc, sc->reg_status);
		if (status != (last_byte ?
		    TWSI_STATUS_DATA_RD_NOACK : TWSI_STATUS_DATA_RD_ACK)) {
-			debugf(dev, "wrong status (%02x) while reading\n", status);
+			debug_(dev, "wrong status (%02x) while reading\n", status);
			rv = IIC_ESTATUS;
			goto out;
		}
@@ -462,14 +465,14 @@ twsi_write(device_t dev, const char *buf, int len, int *sent, int timeout)
		twsi_clear_iflg(sc);
		DELAY(1000);
		if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
-			debugf(dev, "timeout writing data (timeout=%d)\n", timeout);
+			debug_(dev, "timeout writing data (timeout=%d)\n", timeout);
			rv = IIC_ETIMEOUT;
			goto out;
		}

		status = TWSI_READ(sc, sc->reg_status);
		if (status != TWSI_STATUS_DATA_WR_ACK) {
-			debugf(dev, "wrong status (%02x) while writing\n", status);
+			debug_(dev, "wrong status (%02x) while writing\n", status);
			rv = IIC_ESTATUS;
			goto out;
		}
@@ -496,8 +499,12 @@ twsi_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
	sc->control_val = TWSI_CONTROL_TWSIEN |
		TWSI_CONTROL_INTEN | TWSI_CONTROL_ACK;
	TWSI_WRITE(sc, sc->reg_control, sc->control_val);
-	debugf(dev, "transmitting %d messages\n", nmsgs);
-	debugf(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status));
+#if 0
+	debug_(dev, "transmitting %d messages\n", nmsgs);
+	debug_(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status));
+#else
+	DELAY(8000);
+#endif
	sc->nmsgs = nmsgs;
	sc->msgs = msgs;
	sc->msg_idx = 0;
@@ -519,15 +526,24 @@ twsi_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
	debugf(sc->dev, "pause finish\n");

	if (sc->error) {
-		debugf(sc->dev, "Error, aborting (%d)\n", sc->error);
+		debug_(sc->dev, "Error, aborting (%d)\n", sc->error);
		TWSI_WRITE(sc, sc->reg_control, 0);
	}

	/* Disable module and interrupts */
-	debugf(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status));
+#if 0
+	debug_(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status)); //
	TWSI_WRITE(sc, sc->reg_control, 0);
-	debugf(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status));
-
+	debugf(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status)); //
+	debugf(sc->dev, "error=%d\n", sc->error); // danny
+#else
+	int status;
+	DELAY(8000); // danny: works!
+	status = TWSI_READ(sc, sc->reg_status);
+	TWSI_WRITE(sc, sc->reg_control, 0);
+	status = TWSI_READ(sc, sc->reg_status);
+	//debug_(sc->dev, "status=%x\n", TWSI_READ(sc, sc->reg_status));
+#endif
	return (sc->error);
}

@@ -581,7 +597,7 @@ twsi_intr(void *arg)

	case TWSI_STATUS_ADDR_W_NACK:
	case TWSI_STATUS_ADDR_R_NACK:
-		debugf(sc->dev, "No ack received after transmitting the address\n");
+		debug_(sc->dev, "No ack received after transmitting the address\n");
		sc->transfer = 0;
		sc->error = IIC_ENOACK;
		sc->control_val = 0;
@@ -662,7 +678,7 @@ twsi_intr(void *arg)
		break;

	default:
-		debugf(sc->dev, "status=%x hot handled\n", status);
+		debug_(sc->dev, "status=%x hot handled\n", status);
		sc->transfer = 0;
		sc->error = IIC_EBUSERR;
		sc->control_val = 0;



More information about the freebsd-arm mailing list