Index: head/sys/dev/iicbus/twsi/a10_twsi.c =================================================================== --- head/sys/dev/iicbus/twsi/a10_twsi.c +++ head/sys/dev/iicbus/twsi/a10_twsi.c @@ -122,6 +122,10 @@ 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)); } Index: head/sys/dev/iicbus/twsi/twsi.h =================================================================== --- head/sys/dev/iicbus/twsi/twsi.h +++ head/sys/dev/iicbus/twsi/twsi.h @@ -66,6 +66,7 @@ int error; uint32_t control_val; bool need_ack; + bool iflag_w1c; bus_size_t reg_data; bus_size_t reg_slave_addr; Index: head/sys/dev/iicbus/twsi/twsi.c =================================================================== --- head/sys/dev/iicbus/twsi/twsi.c +++ head/sys/dev/iicbus/twsi/twsi.c @@ -147,7 +147,11 @@ { 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 @@ } 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) {