Re: I2C/IIC working on RPI4 8GB?

Daniel Braniss <[email protected]>
Newsgroups gmane.os.freebsd.devel.arm
Message-ID <[email protected]>

> On 25 Apr 2021, at 15:32, Mark Murray <[email protected]> wrote:
> 
> Hi All,
> 
> Does anyone here have IIC/I2C working on a CURRENT (I'm running latest) FreeBSD?
> 
> I've never seen it work; Last time I had working IIC was on an RPI3.
> 
> There is a /dev/iic0, and I have a known working RTC on it, but the scan just times out:
> 
> [root@grasshopper ~]# i2c -s
> Hardware may not support START/STOP scanning; trying less-reliable read method.
> <TIMEOUT>
> Scanning I2C devices on /dev/iic0: <none found>
> 
> 
> I suspect something not-quite-right in DTS land, but I lack the knowledge to investigate. I've done some random stumbling around in the dark with overlays and the like, but I've either seen the above error, or a total lack of /dev/iic0.
> 
> Thanks!
> 
> M
> --
> Mark R V Murray
> 

Q1: do you see /dev/iic?
Q2: i2c -s shows anything?

fianlly, you can try my patch, it works for me, but I understand it’s a five kilo hammer :-)

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;
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-arm
To unsubscribe, send any mail to "[email protected]"
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.