Author: avg
Date: Mon Oct 12 11:40:43 2020
New Revision: 366646
URL: https://svnweb.freebsd.org/changeset/base/366646

Log:
  MFC r365397: twsi: some variants clear interrupt flag by writing 0, others by 
writing 1
  
  Make that distinction more explicit and regular in the code.
  The difference in behavior is documented in the respective datasheets.
  
  Previously, the code handled the distinction by writing the control
  register multiple times where at least one write was zero and another
  was one.
  
  This can be considered a follow-up to r363021 (MFC-ed as r366645).

Modified:
  stable/12/sys/dev/iicbus/twsi/a10_twsi.c
  stable/12/sys/dev/iicbus/twsi/twsi.c
  stable/12/sys/dev/iicbus/twsi/twsi.h
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/iicbus/twsi/a10_twsi.c
==============================================================================
--- stable/12/sys/dev/iicbus/twsi/a10_twsi.c    Mon Oct 12 11:34:09 2020        
(r366645)
+++ stable/12/sys/dev/iicbus/twsi/a10_twsi.c    Mon Oct 12 11:40:43 2020        
(r366646)
@@ -122,6 +122,10 @@ a10_twsi_attach(device_t dev)
        sc->reg_soft_reset = TWI_SRST;
 
        sc->need_ack = true;
+
+       if (ofw_bus_is_compatible(dev, "allwinner,sun6i-a31-i2c") ||
+           ofw_bus_is_compatible(dev, "allwinner,sun6i-a83t-i2c"))
+               sc->iflag_w1c = true;
        return (twsi_attach(dev));
 }
 

Modified: stable/12/sys/dev/iicbus/twsi/twsi.c
==============================================================================
--- stable/12/sys/dev/iicbus/twsi/twsi.c        Mon Oct 12 11:34:09 2020        
(r366645)
+++ stable/12/sys/dev/iicbus/twsi/twsi.c        Mon Oct 12 11:40:43 2020        
(r366646)
@@ -147,7 +147,11 @@ twsi_clear_iflg(struct twsi_softc *sc)
 {
 
        DELAY(1000);
-       twsi_control_clear(sc, TWSI_CONTROL_IFLG);
+       /* There are two ways of clearing IFLAG. */
+       if (sc->iflag_w1c)
+               twsi_control_set(sc, TWSI_CONTROL_IFLG);
+       else
+               twsi_control_clear(sc, TWSI_CONTROL_IFLG);
        DELAY(1000);
 }
 
@@ -667,13 +671,11 @@ twsi_intr(void *arg)
        }
        debugf(sc->dev, "Refresh reg_control\n");
 
-       /* 
-        * Fix silicon bug on > Allwinner A20 by doing a read and writing
-        * again to the control register
+       /*
+        * Newer Allwinner chips clear IFLG after writing 1 to it.
         */
-       status = TWSI_READ(sc, sc->reg_status);
-       TWSI_WRITE(sc, sc->reg_control,
-         sc->control_val | TWSI_CONTROL_IFLG);
+       TWSI_WRITE(sc, sc->reg_control, sc->control_val |
+           (sc->iflag_w1c ? TWSI_CONTROL_IFLG : 0));
 
        debugf(sc->dev, "Done with interrupts\n\n");
        if (transfer_done == 1) {

Modified: stable/12/sys/dev/iicbus/twsi/twsi.h
==============================================================================
--- stable/12/sys/dev/iicbus/twsi/twsi.h        Mon Oct 12 11:34:09 2020        
(r366645)
+++ stable/12/sys/dev/iicbus/twsi/twsi.h        Mon Oct 12 11:40:43 2020        
(r366646)
@@ -66,6 +66,7 @@ struct twsi_softc {
        int                     error;
        uint32_t                control_val;
        bool                    need_ack;
+       bool                    iflag_w1c;
 
        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