Hi,
diff does add the quirk needed on sun6i-a31, and above including sun8i-h3,
for which it does also add related gates+resets.
-Artturi
diff --git a/sys/dev/fdt/sxiccmu_clocks.h b/sys/dev/fdt/sxiccmu_clocks.h
index 8b25ac42bd4..f82613e0125 100644
--- a/sys/dev/fdt/sxiccmu_clocks.h
+++ b/sys/dev/fdt/sxiccmu_clocks.h
@@ -95,6 +95,10 @@ struct sxiccmu_ccu_bit sun50i_a64_gates[] = {
#define H3_CLK_BUS_PIO 54
+#define H3_CLK_BUS_I2C0 59
+#define H3_CLK_BUS_I2C1 60
+#define H3_CLK_BUS_I2C2 61
+
#define H3_CLK_BUS_UART0 62
#define H3_CLK_BUS_UART1 63
#define H3_CLK_BUS_UART2 64
@@ -128,6 +132,9 @@ struct sxiccmu_ccu_bit sun8i_h3_gates[] = {
[H3_CLK_BUS_OHCI2] = { 0x0060, 30 },
[H3_CLK_BUS_OHCI3] = { 0x0060, 31 },
[H3_CLK_BUS_PIO] = { 0x0068, 5 },
+ [H3_CLK_BUS_I2C0] = { 0x006c, 0, H3_CLK_APB2 },
+ [H3_CLK_BUS_I2C1] = { 0x006c, 1, H3_CLK_APB2 },
+ [H3_CLK_BUS_I2C2] = { 0x006c, 2, H3_CLK_APB2 },
[H3_CLK_BUS_UART0] = { 0x006c, 16, H3_CLK_APB2 },
[H3_CLK_BUS_UART1] = { 0x006c, 17, H3_CLK_APB2 },
[H3_CLK_BUS_UART2] = { 0x006c, 18, H3_CLK_APB2 },
@@ -195,6 +202,10 @@ struct sxiccmu_ccu_bit sun50i_a64_resets[] = {
#define H3_RST_BUS_EPHY 39
+#define H3_RST_BUS_I2C0 46
+#define H3_RST_BUS_I2C1 47
+#define H3_RST_BUS_I2C2 48
+
struct sxiccmu_ccu_bit sun8i_h3_resets[] = {
[H3_RST_USB_PHY0] = { 0x00cc, 0 },
[H3_RST_USB_PHY1] = { 0x00cc, 1 },
@@ -213,4 +224,7 @@ struct sxiccmu_ccu_bit sun8i_h3_resets[] = {
[H3_RST_BUS_OHCI2] = { 0x02c0, 30 },
[H3_RST_BUS_OHCI3] = { 0x02c0, 31 },
[H3_RST_BUS_EPHY] = { 0x02c8, 2 },
+ [H3_RST_BUS_I2C0] = { 0x02d8, 0 },
+ [H3_RST_BUS_I2C1] = { 0x02d8, 1 },
+ [H3_RST_BUS_I2C2] = { 0x02d8, 2 },
};
diff --git a/sys/dev/fdt/sxitwi.c b/sys/dev/fdt/sxitwi.c
index f53f2bfd594..e98b36f9588 100644
--- a/sys/dev/fdt/sxitwi.c
+++ b/sys/dev/fdt/sxitwi.c
@@ -144,6 +144,7 @@ struct sxitwi_softc {
bus_space_handle_t sc_ioh;
int sc_node;
u_int sc_started;
+ u_int sc_twsien_iflg;
struct i2c_controller sc_ic;
struct rwlock sc_buslock;
void *sc_ih;
@@ -179,7 +180,8 @@ sxitwi_match(struct device *parent, void *match, void *aux)
struct fdt_attach_args *faa = aux;
return (OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-i2c") ||
- OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-i2c"));
+ OF_is_compatible(faa->fa_node, "allwinner,sun7i-a20-i2c") ||
+ OF_is_compatible(faa->fa_node, "allwinner,sun6i-a31-i2c"));
}
void
@@ -206,6 +208,8 @@ sxitwi_attach(struct device *parent, struct device *self,
void *aux)
rw_init(&sc->sc_buslock, sc->sc_dev.dv_xname);
sc->sc_started = 0;
+ sc->sc_twsien_iflg = CONTROL_TWSIEN | (OF_is_compatible(sc->sc_node,
+ "allwinner,sun6i-a31-i2c") ? CONTROL_IFLG : 0);
sc->sc_ic.ic_cookie = sc;
sc->sc_ic.ic_acquire_bus = sxitwi_acquire_bus;
sc->sc_ic.ic_release_bus = sxitwi_release_bus;
@@ -220,6 +224,7 @@ sxitwi_attach(struct device *parent, struct device *self,
void *aux)
/* Enable clock */
clock_enable(faa->fa_node, NULL);
+ reset_deassert_all(faa->fa_node);
/*
* Set clock rate to 100kHz. From the datasheet:
@@ -358,13 +363,11 @@ sxitwi_send_stop(void *v, int flags)
{
struct sxitwi_softc *sc = v;
int retry = TWSI_RETRY_COUNT;
- u_int control;
sc->sc_started = 0;
/* Interrupt is not generated for STAT_NRS. */
- control = CONTROL_STOP | CONTROL_TWSIEN;
- sxitwi_write_4(sc, TWSI_CONTROL, control);
+ sxitwi_write_4(sc, TWSI_CONTROL, CONTROL_STOP | sc->sc_twsien_iflg);
while (--retry > 0) {
if (sxitwi_read_4(sc, TWSI_STATUS) == STAT_NRS)
return 0;
@@ -458,7 +461,7 @@ sxitwi_wait(struct sxitwi_softc *sc, u_int control, u_int
expect, int flags)
delay(5);
if (!(flags & I2C_F_POLL))
control |= CONTROL_INTEN;
- sxitwi_write_4(sc, TWSI_CONTROL, control | CONTROL_TWSIEN);
+ sxitwi_write_4(sc, TWSI_CONTROL, control | sc->sc_twsien_iflg);
timo = 0;
do {