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