git: a4fe8922085d - main - twsi: unify error handling, explicitly handle more conditions
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 26 Nov 2021 14:24:02 UTC
The branch main has been updated by avg:
URL: https://cgit.FreeBSD.org/src/commit/?id=a4fe8922085dfc1e5e6a6bac73ccc738e373165f
commit a4fe8922085dfc1e5e6a6bac73ccc738e373165f
Author: Andriy Gapon <avg@FreeBSD.org>
AuthorDate: 2021-11-26 07:44:30 +0000
Commit: Andriy Gapon <avg@FreeBSD.org>
CommitDate: 2021-11-26 14:16:21 +0000
twsi: unify error handling, explicitly handle more conditions
twsi_error() is a new function that stops the current transfer and sets
up softc when an error condition is detected.
TWSI_STATUS_DATA_WR_NACK, TWSI_STATUS_BUS_ERROR and
TWSI_STATUS_ARBITRATION_LOST are now handled explicitly rather than
via the catch-all unknown status.
Also, twsi_intr() now calls wakeup() in a single place when the
transfer is finished.
MFC after: 2 weeks
---
sys/dev/iicbus/twsi/twsi.c | 46 ++++++++++++++++++++++++++++++++--------------
1 file changed, 32 insertions(+), 14 deletions(-)
diff --git a/sys/dev/iicbus/twsi/twsi.c b/sys/dev/iicbus/twsi/twsi.c
index 384e19e120b9..ecadfade04d9 100644
--- a/sys/dev/iicbus/twsi/twsi.c
+++ b/sys/dev/iicbus/twsi/twsi.c
@@ -543,6 +543,19 @@ twsi_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
return (error);
}
+static void
+twsi_error(struct twsi_softc *sc, int err)
+{
+ /*
+ * Must send stop condition to abort the current transfer.
+ */
+ debugf(sc, "Sending STOP condition for error %d\n", err);
+ sc->transfer = 0;
+ sc->error = err;
+ sc->control_val = 0;
+ TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_STOP);
+}
+
static void
twsi_intr(void *arg)
{
@@ -604,13 +617,13 @@ twsi_intr(void *arg)
case TWSI_STATUS_ADDR_W_NACK:
case TWSI_STATUS_ADDR_R_NACK:
- debugf(sc, "No ack received after transmitting the address\n");
- sc->transfer = 0;
- sc->error = IIC_ENOACK;
- sc->control_val = 0;
- wakeup(sc);
+ debugf(sc, "Address NACK-ed\n");
+ twsi_error(sc, IIC_ENOACK);
+ break;
+ case TWSI_STATUS_DATA_WR_NACK:
+ debugf(sc, "Data byte NACK-ed\n");
+ twsi_error(sc, IIC_ENOACK);
break;
-
case TWSI_STATUS_DATA_WR_ACK:
debugf(sc, "Ack received after transmitting data\n");
if (sc->sent_bytes == sc->msgs[sc->msg_idx].len) {
@@ -684,12 +697,17 @@ twsi_intr(void *arg)
sc->error = 0;
break;
+ case TWSI_STATUS_BUS_ERROR:
+ debugf(sc, "Bus error\n");
+ twsi_error(sc, IIC_EBUSERR);
+ break;
+ case TWSI_STATUS_ARBITRATION_LOST:
+ debugf(sc, "Arbitration lost\n");
+ twsi_error(sc, IIC_EBUSBSY);
+ break;
default:
- debugf(sc, "status=%x hot handled\n", status);
- sc->transfer = 0;
- sc->error = IIC_EBUSERR;
- sc->control_val = 0;
- wakeup(sc);
+ debugf(sc, "unexpected status 0x%x\n", status);
+ twsi_error(sc, IIC_ESTATUS);
break;
}
debugf(sc, "Refresh reg_control\n");
@@ -701,11 +719,11 @@ end:
TWSI_WRITE(sc, sc->reg_control, sc->control_val |
(sc->iflag_w1c ? TWSI_CONTROL_IFLG : 0));
- debugf(sc, "Done with interrupts\n\n");
- if (transfer_done == 1) {
+ if (transfer_done == 1)
sc->transfer = 0;
+ debugf(sc, "Done with interrupt, transfer = %d\n", sc->transfer);
+ if (sc->transfer == 0)
wakeup(sc);
- }
mtx_unlock(&sc->mutex);
}