Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 25 Apr 2021 18:41:31 +0300
From:      Daniel Braniss <danny@cs.huji.ac.il>
To:        Mark Murray <markm@FreeBSD.org>
Cc:        freebsd-arm <freebsd-arm@freebsd.org>
Subject:   Re: I2C/IIC working on RPI4 8GB?
Message-ID:  <C0038E5F-F218-425B-AFE6-84537CE10155@cs.huji.ac.il>
In-Reply-To: <1C2DD11C-B1F6-4C2A-9AB0-5F1553520FF5@FreeBSD.org>
References:  <1C2DD11C-B1F6-4C2A-9AB0-5F1553520FF5@FreeBSD.org>

next in thread | previous in thread | raw e-mail | index | archive | help


> On 25 Apr 2021, at 15:32, Mark Murray <markm@FreeBSD.org> wrote:
>=20
> Hi All,
>=20
> Does anyone here have IIC/I2C working on a CURRENT (I'm running =
latest) FreeBSD?
>=20
> I've never seen it work; Last time I had working IIC was on an RPI3.
>=20
> There is a /dev/iic0, and I have a known working RTC on it, but the =
scan just times out:
>=20
> [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>
>=20
>=20
> 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.
>=20
> Thanks!
>=20
> M
> --
> Mark R V Murray
>=20

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=E2=80=99=
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=20
	val =3D 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 /=3D 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=3D%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 =3D=3D 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=3D%x\n", status);

	if (status !=3D mask) {
-		debugf(dev, "wrong status (%02x) after sending %sSTART =
condition\n",
+		debug_(dev, "wrong status (%02x) after sending %sSTART =
condition\n",
		    status, mask =3D=3D 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=3D%d)\n", timeout);
+		debug_(dev, "timeout sending slave address =
(timeout=3D%d)\n", timeout);
		return (IIC_ETIMEOUT);
	}

@@ -239,7 +241,7 @@ twsi_locked_start(device_t dev, struct twsi_softc =
*sc, int32_t mask,
	status =3D TWSI_READ(sc, sc->reg_status);
	if (status !=3D (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 =3D device_get_softc(dev);
-
+	debug_(dev, "twsi_read: len=3D%d delay=3D%d", len, delay); // =
danny
+=09
	mtx_lock(&sc->mutex);
	*read =3D 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=3D%d)\n",=
 delay);
+			debug_(dev, "timeout reading data (delay=3D%d)\n",=
 delay);
			rv =3D IIC_ETIMEOUT;
			goto out;
		}
@@ -431,7 +434,7 @@ twsi_read(device_t dev, char *buf, int len, int =
*read, int last, int delay)
		status =3D TWSI_READ(sc, sc->reg_status);
		if (status !=3D (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 =3D 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=3D%d)\n", timeout);
+			debug_(dev, "timeout writing data =
(timeout=3D%d)\n", timeout);
			rv =3D IIC_ETIMEOUT;
			goto out;
		}

		status =3D TWSI_READ(sc, sc->reg_status);
		if (status !=3D TWSI_STATUS_DATA_WR_ACK) {
-			debugf(dev, "wrong status (%02x) while =
writing\n", status);
+			debug_(dev, "wrong status (%02x) while =
writing\n", status);
			rv =3D IIC_ESTATUS;
			goto out;
		}
@@ -496,8 +499,12 @@ twsi_transfer(device_t dev, struct iic_msg *msgs, =
uint32_t nmsgs)
	sc->control_val =3D 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=3D%x\n", TWSI_READ(sc, sc->reg_status));
+#if 0
+	debug_(dev, "transmitting %d messages\n", nmsgs);
+	debug_(sc->dev, "status=3D%x\n", TWSI_READ(sc, sc->reg_status));
+#else
+	DELAY(8000);
+#endif
	sc->nmsgs =3D nmsgs;
	sc->msgs =3D msgs;
	sc->msg_idx =3D 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=3D%x\n", TWSI_READ(sc, sc->reg_status));
+#if 0
+	debug_(sc->dev, "status=3D%x\n", TWSI_READ(sc, sc->reg_status)); =
//
	TWSI_WRITE(sc, sc->reg_control, 0);
-	debugf(sc->dev, "status=3D%x\n", TWSI_READ(sc, sc->reg_status));
-
+	debugf(sc->dev, "status=3D%x\n", TWSI_READ(sc, sc->reg_status)); =
//
+	debugf(sc->dev, "error=3D%d\n", sc->error); // danny
+#else
+	int status;
+	DELAY(8000); // danny: works!
+	status =3D TWSI_READ(sc, sc->reg_status);
+	TWSI_WRITE(sc, sc->reg_control, 0);
+	status =3D TWSI_READ(sc, sc->reg_status);
+	//debug_(sc->dev, "status=3D%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 =3D 0;
		sc->error =3D IIC_ENOACK;
		sc->control_val =3D 0;
@@ -662,7 +678,7 @@ twsi_intr(void *arg)
		break;

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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?C0038E5F-F218-425B-AFE6-84537CE10155>