svn commit: r365397 - head/sys/dev/iicbus/twsi

Andriy Gapon avg at FreeBSD.org
Mon Sep 7 06:32:04 UTC 2020


Author: avg
Date: Mon Sep  7 06:32:03 2020
New Revision: 365397
URL: https://svnweb.freebsd.org/changeset/base/365397

Log:
  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.
  
  Reviewed by:	manu
  MFC after:	4 weeks
  Differential Revision: https://reviews.freebsd.org/D26308

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	Mon Sep  7 06:29:41 2020	(r365396)
+++ head/sys/dev/iicbus/twsi/a10_twsi.c	Mon Sep  7 06:32:03 2020	(r365397)
@@ -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: head/sys/dev/iicbus/twsi/twsi.c
==============================================================================
--- head/sys/dev/iicbus/twsi/twsi.c	Mon Sep  7 06:29:41 2020	(r365396)
+++ head/sys/dev/iicbus/twsi/twsi.c	Mon Sep  7 06:32:03 2020	(r365397)
@@ -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: head/sys/dev/iicbus/twsi/twsi.h
==============================================================================
--- head/sys/dev/iicbus/twsi/twsi.h	Mon Sep  7 06:29:41 2020	(r365396)
+++ head/sys/dev/iicbus/twsi/twsi.h	Mon Sep  7 06:32:03 2020	(r365397)
@@ -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;


More information about the svn-src-all mailing list