Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 5 Apr 2019 14:44:23 +0000 (UTC)
From:      Emmanuel Vadot <manu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r345948 - head/sys/dev/iicbus/twsi
Message-ID:  <201904051444.x35EiNvP037666@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: manu
Date: Fri Apr  5 14:44:23 2019
New Revision: 345948
URL: https://svnweb.freebsd.org/changeset/base/345948

Log:
  twsi: Add interrupt mode
  
  Add the ability to use interrupts for i2c message.
  We still use polling for early boot i2c transfer (for PMIC
  for example) but as soon as interrupts are available use them.
  On Allwinner SoC >A20 is seems that polling mode is broken for some
  reason, this is now fixed by using interrupt mode.
  For Allwinner also fix the frequency calculation, the one in the code
  was for when the APB frequency is at 48Mhz while it is at 24Mhz on most
  (all?) Allwinner SoCs. We now support both cases.
  
  While here add more debug info when it's compiled in.
  
  Tested On: A20, H3, A64
  MFC after:	1 month

Modified:
  head/sys/dev/iicbus/twsi/a10_twsi.c
  head/sys/dev/iicbus/twsi/twsi.c
  head/sys/dev/iicbus/twsi/twsi.h

Modified: head/sys/dev/iicbus/twsi/a10_twsi.c
==============================================================================
--- head/sys/dev/iicbus/twsi/a10_twsi.c	Fri Apr  5 14:27:48 2019	(r345947)
+++ head/sys/dev/iicbus/twsi/a10_twsi.c	Fri Apr  5 14:44:23 2019	(r345948)
@@ -1,6 +1,5 @@
 /*-
- * Copyright (c) 2016 Emmanuel Vadot <manu@freebsd.org>
- * All rights reserved.
+ * Copyright (c) 2016-2019 Emmanuel Vadot <manu@freebsd.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -90,6 +89,7 @@ a10_twsi_attach(device_t dev)
 	struct twsi_softc *sc;
 	clk_t clk;
 	hwreset_t rst;
+	uint64_t freq;
 	int error;
 
 	sc = device_get_softc(dev);
@@ -124,10 +124,31 @@ a10_twsi_attach(device_t dev)
 	sc->reg_soft_reset = TWI_SRST;
 
 	/* Setup baud rate params */
-	sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 2);
-	sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 2);
-	sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2);
+	clk_get_freq(clk, &freq);
+	switch (freq) {
+		/* 
+		 * Formula is
+		 * F0 = FINT / 2 ^ CLK_N
+		 * F1 = F0 / (CLK_M + 1)
+		 * 
+		 * Doc says that the output freq is F1/10 but my logic analyzer says otherwise
+		 */
+	case 48000000:
+		sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(11, 1);
+		sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(11, 1);
+		sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 1);
+		break;
+	case 24000000:
+		sc->baud_rate[IIC_SLOW].param = TWSI_BAUD_RATE_PARAM(5, 2);
+		sc->baud_rate[IIC_FAST].param = TWSI_BAUD_RATE_PARAM(5, 2);
+		sc->baud_rate[IIC_FASTEST].param = TWSI_BAUD_RATE_PARAM(2, 2);
+		break;
+	default:
+		device_printf(dev, "Non supported frequency\n");
+		return (ENXIO);
+	}
 
+	sc->need_ack = true;
 	return (twsi_attach(dev));
 }
 
@@ -154,7 +175,7 @@ DEFINE_CLASS_1(iichb, a10_twsi_driver, a10_twsi_method
 static devclass_t a10_twsi_devclass;
 
 EARLY_DRIVER_MODULE(a10_twsi, simplebus, a10_twsi_driver, a10_twsi_devclass,
-    0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+    0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
 EARLY_DRIVER_MODULE(iicbus, a10_twsi, iicbus_driver, iicbus_devclass,
-    0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
+    0, 0, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE);
 MODULE_DEPEND(a10_twsi, iicbus, 1, 1, 1);

Modified: head/sys/dev/iicbus/twsi/twsi.c
==============================================================================
--- head/sys/dev/iicbus/twsi/twsi.c	Fri Apr  5 14:27:48 2019	(r345947)
+++ head/sys/dev/iicbus/twsi/twsi.c	Fri Apr  5 14:44:23 2019	(r345948)
@@ -31,7 +31,7 @@
 
 /*
  * Driver for the TWSI (aka I2C, aka IIC) bus controller found on Marvell
- * and Allwinner SoCs. Supports master operation only, and works in polling mode.
+ * and Allwinner SoCs. Supports master operation only.
  *
  * Calls to DELAY() are needed per Application Note AN-179 "TWSI Software
  * Guidelines for Discovery(TM), Horizon (TM) and Feroceon(TM) Devices".
@@ -75,8 +75,11 @@ __FBSDID("$FreeBSD$");
 #define	TWSI_STATUS_START		0x08
 #define	TWSI_STATUS_RPTD_START		0x10
 #define	TWSI_STATUS_ADDR_W_ACK		0x18
+#define	TWSI_STATUS_ADDR_W_NACK		0x20
 #define	TWSI_STATUS_DATA_WR_ACK		0x28
+#define	TWSI_STATUS_DATA_WR_NACK	0x30
 #define	TWSI_STATUS_ADDR_R_ACK		0x40
+#define	TWSI_STATUS_ADDR_R_NACK		0x48
 #define	TWSI_STATUS_DATA_RD_ACK		0x50
 #define	TWSI_STATUS_DATA_RD_NOACK	0x58
 
@@ -84,27 +87,32 @@ __FBSDID("$FreeBSD$");
 #undef TWSI_DEBUG
 
 #ifdef TWSI_DEBUG
-#define	debugf(fmt, args...) do { printf("%s(): ", __func__); printf(fmt,##args); } while (0)
+#define	debugf(dev, fmt, args...) device_printf(dev, "%s: " fmt, __func__, ##args)
 #else
-#define	debugf(fmt, args...)
+#define	debugf(dev, fmt, args...)
 #endif
 
 static struct resource_spec res_spec[] = {
 	{ SYS_RES_MEMORY, 0, RF_ACTIVE },
+	{ SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE},
 	{ -1, 0 }
 };
 
 static __inline uint32_t
 TWSI_READ(struct twsi_softc *sc, bus_size_t off)
 {
+	uint32_t val;
 
-	return (bus_read_4(sc->res[0], off));
+	val = bus_read_4(sc->res[0], off);
+	debugf(sc->dev, "read %x from %lx\n", val, off);
+	return (val);
 }
 
 static __inline void
 TWSI_WRITE(struct twsi_softc *sc, bus_size_t off, uint32_t val)
 {
 
+	debugf(sc->dev, "Writing %x to %lx\n", val, off);
 	bus_write_4(sc->res[0], off, val);
 }
 
@@ -114,8 +122,10 @@ twsi_control_clear(struct twsi_softc *sc, uint32_t mas
 	uint32_t val;
 
 	val = TWSI_READ(sc, sc->reg_control);
+	debugf(sc->dev, "read val=%x\n", val);
 	val &= ~(TWSI_CONTROL_STOP | TWSI_CONTROL_START);
 	val &= ~mask;
+	debugf(sc->dev, "write val=%x\n", val);
 	TWSI_WRITE(sc, sc->reg_control, val);
 }
 
@@ -125,8 +135,10 @@ twsi_control_set(struct twsi_softc *sc, uint32_t mask)
 	uint32_t val;
 
 	val = TWSI_READ(sc, sc->reg_control);
+	debugf(sc->dev, "read val=%x\n", val);
 	val &= ~(TWSI_CONTROL_STOP | TWSI_CONTROL_START);
 	val |= mask;
+	debugf(sc->dev, "write val=%x\n", val);
 	TWSI_WRITE(sc, sc->reg_control, val);
 }
 
@@ -151,11 +163,13 @@ twsi_poll_ctrl(struct twsi_softc *sc, int timeout, uin
 {
 
 	timeout /= 10;
+	debugf(sc->dev, "Waiting for ctrl reg to match mask %x\n", mask);
 	while (!(TWSI_READ(sc, sc->reg_control) & mask)) {
 		DELAY(10);
 		if (--timeout < 0)
 			return (timeout);
 	}
+	debugf(sc->dev, "done\n");
 	return (0);
 }
 
@@ -179,10 +193,11 @@ twsi_locked_start(device_t dev, struct twsi_softc *sc,
 		/* read IFLG to know if it should be cleared later; from NBSD */
 		iflg_set = TWSI_READ(sc, sc->reg_control) & TWSI_CONTROL_IFLG;
 
+	debugf(dev, "send start\n");
 	twsi_control_set(sc, TWSI_CONTROL_START);
 
 	if (mask == TWSI_STATUS_RPTD_START && iflg_set) {
-		debugf("IFLG set, clearing\n");
+		debugf(dev, "IFLG set, clearing (mask=%x)\n", mask);
 		twsi_clear_iflg(sc);
 	}
 
@@ -193,14 +208,16 @@ twsi_locked_start(device_t dev, struct twsi_softc *sc,
 	DELAY(1000);
 
 	if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
-		debugf("timeout sending %sSTART condition\n",
+		debugf(dev, "timeout sending %sSTART condition\n",
 		    mask == TWSI_STATUS_START ? "" : "repeated ");
 		return (IIC_ETIMEOUT);
 	}
 
 	status = TWSI_READ(sc, sc->reg_status);
+	debugf(dev, "status=%x\n", status);
+
 	if (status != mask) {
-		debugf("wrong status (%02x) after sending %sSTART condition\n",
+		debugf(dev, "wrong status (%02x) after sending %sSTART condition\n",
 		    status, mask == TWSI_STATUS_START ? "" : "repeated ");
 		return (IIC_ESTATUS);
 	}
@@ -210,15 +227,15 @@ twsi_locked_start(device_t dev, struct twsi_softc *sc,
 	DELAY(1000);
 
 	if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
-		debugf("timeout sending slave address\n");
+		debugf(dev, "timeout sending slave address (timeout=%d)\n", timeout);
 		return (IIC_ETIMEOUT);
 	}
-	
+
 	read_access = (slave & 0x1) ? 1 : 0;
 	status = TWSI_READ(sc, sc->reg_status);
 	if (status != (read_access ?
 	    TWSI_STATUS_ADDR_R_ACK : TWSI_STATUS_ADDR_W_ACK)) {
-		debugf("no ACK (status: %02x) after sending slave address\n",
+		debugf(dev, "no ACK (status: %02x) after sending slave address\n",
 		    status);
 		return (IIC_ENOACK);
 	}
@@ -234,6 +251,7 @@ twsi_reset(device_t dev, u_char speed, u_char addr, u_
 {
 	struct twsi_softc *sc;
 	uint32_t param;
+	/* uint32_t val; */
 
 	sc = device_get_softc(dev);
 
@@ -241,17 +259,18 @@ twsi_reset(device_t dev, u_char speed, u_char addr, u_
 	case IIC_SLOW:
 	case IIC_FAST:
 		param = sc->baud_rate[speed].param;
+		debugf(dev, "Using IIC_FAST mode with speed param=%x\n", param);
 		break;
 	case IIC_FASTEST:
 	case IIC_UNKNOWN:
 	default:
 		param = sc->baud_rate[IIC_FAST].param;
+		debugf(dev, "Using IIC_FASTEST/UNKNOWN mode with speed param=%x\n", param);
 		break;
 	}
 
 	mtx_lock(&sc->mutex);
 	TWSI_WRITE(sc, sc->reg_soft_reset, 0x0);
-	DELAY(2000);
 	TWSI_WRITE(sc, sc->reg_baud_rate, param);
 	TWSI_WRITE(sc, sc->reg_control, TWSI_CONTROL_TWSIEN);
 	DELAY(1000);
@@ -267,6 +286,7 @@ twsi_stop(device_t dev)
 
 	sc = device_get_softc(dev);
 
+	debugf(dev, "%s\n", __func__);
 	mtx_lock(&sc->mutex);
 	twsi_control_clear(sc, TWSI_CONTROL_ACK);
 	twsi_control_set(sc, TWSI_CONTROL_STOP);
@@ -288,6 +308,7 @@ twsi_repeated_start(device_t dev, u_char slave, int ti
 
 	sc = device_get_softc(dev);
 
+	debugf(dev, "%s: slave=%x\n", __func__, slave);
 	mtx_lock(&sc->mutex);
 	rv = twsi_locked_start(dev, sc, TWSI_STATUS_RPTD_START, slave,
 	    timeout);
@@ -311,6 +332,7 @@ twsi_start(device_t dev, u_char slave, int timeout)
 
 	sc = device_get_softc(dev);
 
+	debugf(dev, "%s: slave=%x\n", __func__, slave);
 	mtx_lock(&sc->mutex);
 	rv = twsi_locked_start(dev, sc, TWSI_STATUS_START, slave, timeout);
 	mtx_unlock(&sc->mutex);
@@ -348,7 +370,7 @@ twsi_read(device_t dev, char *buf, int len, int *read,
 		DELAY(1000);
 
 		if (twsi_poll_ctrl(sc, delay, TWSI_CONTROL_IFLG)) {
-			debugf("timeout reading data\n");
+			debugf(dev, "timeout reading data (delay=%d)\n", delay);
 			rv = IIC_ETIMEOUT;
 			goto out;
 		}
@@ -356,7 +378,7 @@ twsi_read(device_t dev, char *buf, int len, int *read,
 		status = TWSI_READ(sc, sc->reg_status);
 		if (status != (last_byte ?
 		    TWSI_STATUS_DATA_RD_NOACK : TWSI_STATUS_DATA_RD_ACK)) {
-			debugf("wrong status (%02x) while reading\n", status);
+			debugf(dev, "wrong status (%02x) while reading\n", status);
 			rv = IIC_ESTATUS;
 			goto out;
 		}
@@ -387,14 +409,14 @@ twsi_write(device_t dev, const char *buf, int len, int
 		twsi_clear_iflg(sc);
 		DELAY(1000);
 		if (twsi_poll_ctrl(sc, timeout, TWSI_CONTROL_IFLG)) {
-			debugf("timeout writing data\n");
+			debugf(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("wrong status (%02x) while writing\n", status);
+			debugf(dev, "wrong status (%02x) while writing\n", status);
 			rv = IIC_ESTATUS;
 			goto out;
 		}
@@ -406,6 +428,202 @@ out:
 	return (rv);
 }
 
+static int
+twsi_transfer(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+	struct twsi_softc *sc;
+	int i;
+
+	sc = device_get_softc(dev);
+
+	if (sc->have_intr == false)
+		return (iicbus_transfer_gen(dev, msgs, nmsgs));
+
+	sc->error = 0;
+
+	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));
+	for (i = 0; i < nmsgs && sc->error == 0; i++) {
+		sc->transfer = 1;
+		sc->msg = &msgs[i];
+		debugf(dev, "msg[%d] flags: %x\n", i, msgs[i].flags);
+		debugf(dev, "msg[%d] len: %d\n", i, msgs[i].len);
+
+		/* Send start and re-enable interrupts */
+		sc->control_val = TWSI_CONTROL_TWSIEN |
+			TWSI_CONTROL_INTEN | TWSI_CONTROL_ACK;
+		if (sc->msg->len == 1)
+			sc->control_val &= ~TWSI_CONTROL_ACK;
+		TWSI_WRITE(sc, sc->reg_control, sc->control_val | TWSI_CONTROL_START);
+		while (sc->error == 0 && sc->transfer != 0) {
+			pause_sbt("twsi", SBT_1MS * 30, SBT_1MS, 0);
+		}
+
+		debugf(dev, "Done with msg[%d]\n", i);
+		if (sc->error) {
+			debugf(sc->dev, "Error, aborting (%d)\n", sc->error);
+			TWSI_WRITE(sc, sc->reg_control, 0);
+			goto out;
+		}
+	}
+
+	/* Disable module and interrupts */
+	debugf(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));
+
+out:
+	return (sc->error);
+}
+
+static void
+twsi_intr(void *arg)
+{
+	struct twsi_softc *sc;
+	uint32_t status;
+	int transfer_done = 0;
+
+	sc = arg;
+
+	debugf(sc->dev, "Got interrupt\n");
+
+	while (TWSI_READ(sc, sc->reg_control) & TWSI_CONTROL_IFLG) {
+		status = TWSI_READ(sc, sc->reg_status);
+		debugf(sc->dev, "status=%x\n", status);
+
+		switch (status) {
+		case TWSI_STATUS_START:
+		case TWSI_STATUS_RPTD_START:
+			/* Transmit the address */
+			debugf(sc->dev, "Send the address\n");
+
+			if (sc->msg->flags & IIC_M_RD)
+				TWSI_WRITE(sc, sc->reg_data,
+				    sc->msg->slave | LSB);
+			else
+				TWSI_WRITE(sc, sc->reg_data,
+				    sc->msg->slave & ~LSB);
+
+			TWSI_WRITE(sc, sc->reg_control, sc->control_val);
+			break;
+
+		case TWSI_STATUS_ADDR_W_ACK:
+			debugf(sc->dev, "Ack received after transmitting the address\n");
+			/* Directly send the first byte */
+			sc->sent_bytes = 0;
+			debugf(sc->dev, "Sending byte 0 = %x\n", sc->msg->buf[0]);
+			TWSI_WRITE(sc, sc->reg_data, sc->msg->buf[0]);
+
+			TWSI_WRITE(sc, sc->reg_control, sc->control_val);
+			break;
+
+		case TWSI_STATUS_ADDR_R_ACK:
+			sc->recv_bytes = 0;
+
+			TWSI_WRITE(sc, sc->reg_control, sc->control_val);
+			break;
+
+		case TWSI_STATUS_ADDR_W_NACK:
+		case TWSI_STATUS_ADDR_R_NACK:
+			debugf(sc->dev, "No ack received after transmitting the address\n");
+			sc->transfer = 0;
+			sc->error = ETIMEDOUT;
+			sc->control_val = 0;
+			wakeup(sc);
+			break;
+
+		case TWSI_STATUS_DATA_WR_ACK:
+			debugf(sc->dev, "Ack received after transmitting data\n");
+			if (sc->sent_bytes++ == (sc->msg->len - 1)) {
+				debugf(sc->dev, "Done sending all the bytes\n");
+				/* Send stop, no interrupts on stop */
+				if (!(sc->msg->flags & IIC_M_NOSTOP)) {
+					debugf(sc->dev, "Done TX data, send stop\n");
+					TWSI_WRITE(sc, sc->reg_control,
+					  sc->control_val | TWSI_CONTROL_STOP);
+				} else {
+					sc->control_val &= ~TWSI_CONTROL_INTEN;
+					TWSI_WRITE(sc, sc->reg_control,
+					    sc->control_val);
+				}
+				transfer_done = 1;
+			} else {
+				debugf(sc->dev, "Sending byte %d = %x\n",
+				    sc->sent_bytes,
+				    sc->msg->buf[sc->sent_bytes]);
+				TWSI_WRITE(sc, sc->reg_data,
+				    sc->msg->buf[sc->sent_bytes]);
+				TWSI_WRITE(sc, sc->reg_control,
+				    sc->control_val);
+			}
+
+			break;
+		case TWSI_STATUS_DATA_RD_ACK:
+			debugf(sc->dev, "Ack received after receiving data\n");
+			debugf(sc->dev, "msg_len=%d recv_bytes=%d\n", sc->msg->len, sc->recv_bytes);
+			sc->msg->buf[sc->recv_bytes++] = TWSI_READ(sc, sc->reg_data);
+
+			/* If we only have one byte left, disable ACK */
+			if (sc->msg->len - sc->recv_bytes == 1)
+				sc->control_val &= ~TWSI_CONTROL_ACK;
+			TWSI_WRITE(sc, sc->reg_control, sc->control_val);
+			break;
+
+		case TWSI_STATUS_DATA_RD_NOACK:
+			if (sc->msg->len - sc->recv_bytes == 1) {
+				sc->msg->buf[sc->recv_bytes++] = TWSI_READ(sc, sc->reg_data);
+				debugf(sc->dev, "Done RX data, send stop (2)\n");
+				if (!(sc->msg->flags & IIC_M_NOSTOP))
+					TWSI_WRITE(sc, sc->reg_control,
+					  sc->control_val | TWSI_CONTROL_STOP);
+			} else {
+				debugf(sc->dev, "No ack when receiving data\n");
+				sc->error = ENXIO;
+				sc->control_val = 0;
+			}
+			sc->transfer = 0;
+			transfer_done = 1;
+			break;
+
+		default:
+			debugf(sc->dev, "status=%x hot handled\n", status);
+			sc->transfer = 0;
+			sc->error = ENXIO;
+			sc->control_val = 0;
+			wakeup(sc);
+			break;
+		}
+
+		if (sc->need_ack)
+			TWSI_WRITE(sc, sc->reg_control,
+			    sc->control_val | TWSI_CONTROL_IFLG);
+	}
+
+	debugf(sc->dev, "Done with interrupts\n");
+	if (transfer_done == 1) {
+		sc->transfer = 0;
+		wakeup(sc);
+	}
+}
+
+static void
+twsi_intr_start(void *pdev)
+{
+	struct twsi_softc *sc;
+
+	sc = device_get_softc(pdev);
+
+	if ((bus_setup_intr(pdev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
+	      NULL, twsi_intr, sc, &sc->intrhand)))
+		device_printf(pdev, "unable to register interrupt handler\n");
+
+	sc->have_intr = true;
+	config_intrhook_disestablish(&sc->intr_hook);
+}
+
 int
 twsi_attach(device_t dev)
 {
@@ -430,6 +648,12 @@ twsi_attach(device_t dev)
 	}
 	bus_generic_attach(dev);
 
+	sc->intr_hook.ich_func = twsi_intr_start;
+	sc->intr_hook.ich_arg = dev;
+
+	if (config_intrhook_establish(&sc->intr_hook) != 0)
+		return (ENOMEM);
+
 	return (0);
 }
 
@@ -440,7 +664,6 @@ twsi_detach(device_t dev)
 	int rv;
 
 	sc = device_get_softc(dev);
-	debugf("");
 
 	if ((rv = bus_generic_detach(dev)) != 0)
 		return (rv);
@@ -449,6 +672,9 @@ twsi_detach(device_t dev)
 		if ((rv = device_delete_child(dev, sc->iicbus)) != 0)
 			return (rv);
 
+	if (sc->intrhand != NULL)
+		bus_teardown_intr(sc->dev, sc->res[1], sc->intrhand);
+
 	bus_release_resources(dev, res_spec, sc->res);
 
 	mtx_destroy(&sc->mutex);
@@ -478,7 +704,7 @@ static device_method_t twsi_methods[] = {
 	DEVMETHOD(iicbus_write,		twsi_write),
 	DEVMETHOD(iicbus_read,		twsi_read),
 	DEVMETHOD(iicbus_reset,		twsi_reset),
-	DEVMETHOD(iicbus_transfer,	iicbus_transfer_gen),
+	DEVMETHOD(iicbus_transfer,	twsi_transfer),
 	{ 0, 0 }
 };
 

Modified: head/sys/dev/iicbus/twsi/twsi.h
==============================================================================
--- head/sys/dev/iicbus/twsi/twsi.h	Fri Apr  5 14:27:48 2019	(r345947)
+++ head/sys/dev/iicbus/twsi/twsi.h	Fri Apr  5 14:44:23 2019	(r345948)
@@ -47,13 +47,24 @@ struct twsi_baud_rate {
 
 struct twsi_softc {
 	device_t	dev;
-	struct resource	*res[1];	/* SYS_RES_MEMORY */
+	struct resource	*res[2];
 	struct mtx	mutex;
 	device_t	iicbus;
 #ifdef EXT_RESOURCES
 	clk_t		clk_core;
 	clk_t		clk_reg;
 #endif
+	void *			intrhand;
+	struct intr_config_hook	intr_hook;
+	bool			have_intr;
+
+	struct iic_msg		*msg;
+	uint16_t		sent_bytes;
+	uint16_t		recv_bytes;
+	int			transfer;
+	int			error;
+	uint32_t		control_val;
+	bool			need_ack;
 
 	bus_size_t	reg_data;
 	bus_size_t	reg_slave_addr;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904051444.x35EiNvP037666>