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 <m...@freebsd.org>
- * All rights reserved.
+ * Copyright (c) 2016-2019 Emmanuel Vadot <m...@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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to