-/* $OpenBSD: sxitwi.c,v 1.7 2018/01/06 11:23:14 kettenis Exp $ */
+/* $OpenBSD: sxitwi.c,v 1.8 2018/07/24 16:11:33 patrick Exp $ */
/* $NetBSD: gttwsi_core.c,v 1.2 2014/11/23 13:37:27 jmcneill Exp $ */
/*
* Copyright (c) 2008 Eiji Kawauchi.
#include <dev/ofw/ofw_pinctrl.h>
#include <dev/ofw/fdt.h>
-#define TWI_CCR_REG 0x14
-#define TWI_CCR_CLK_M (0x0f << 3)
-#define TWI_CCR_CLK_N (0x07 << 0)
-
-#define TWSI_SLAVEADDR 0x00
-#define TWSI_EXTEND_SLAVEADDR 0x04
-#define TWSI_DATA 0x08
-#define TWSI_CONTROL 0x0c
-#define TWSI_STATUS 0x10
-#define TWSI_BAUDRATE 0x14
-#define TWSI_SOFTRESET 0x18
+#define TWSI_SLAVEADDR 0
+#define TWSI_EXTEND_SLAVEADDR 1
+#define TWSI_DATA 2
+#define TWSI_CONTROL 3
+#define TWSI_STATUS 4
+#define TWSI_CLOCK 5
+#define TWSI_SOFTRESET 6
+#define TWSI_NREG 7
#define SLAVEADDR_GCE_MASK 0x01
#define SLAVEADDR_SADDR_MASK 0xfe
struct i2c_controller sc_ic;
struct rwlock sc_buslock;
void *sc_ih;
+ uint8_t sc_regs[TWSI_NREG];
+ int sc_delay;
};
void sxitwi_attach(struct device *, struct device *, void *);
return (OF_is_compatible(faa->fa_node, "allwinner,sun4i-a10-i2c") ||
OF_is_compatible(faa->fa_node, "allwinner,sun6i-a31-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, "marvell,mv78230-a0-i2c"));
}
void
struct fdt_attach_args *faa = aux;
struct i2cbus_attach_args iba;
uint32_t freq, parent_freq;
- uint32_t m, n;
+ uint32_t m, n, nbase;
if (faa->fa_nreg < 1) {
printf(": no registers\n");
return;
}
+ nbase = 1;
+ sc->sc_regs[TWSI_SLAVEADDR] = 0x00;
+ sc->sc_regs[TWSI_EXTEND_SLAVEADDR] = 0x04;
+ sc->sc_regs[TWSI_DATA] = 0x08;
+ sc->sc_regs[TWSI_CONTROL] = 0x0c;
+ sc->sc_regs[TWSI_STATUS] = 0x10;
+ sc->sc_regs[TWSI_CLOCK] = 0x14;
+ sc->sc_regs[TWSI_SOFTRESET] = 0x18;
+
+ if (OF_is_compatible(faa->fa_node, "marvell,mv78230-a0-i2c")) {
+ nbase = 2;
+ sc->sc_delay = 1;
+ sc->sc_regs[TWSI_SLAVEADDR] = 0x00;
+ sc->sc_regs[TWSI_EXTEND_SLAVEADDR] = 0x10;
+ sc->sc_regs[TWSI_DATA] = 0x04;
+ sc->sc_regs[TWSI_CONTROL] = 0x08;
+ sc->sc_regs[TWSI_STATUS] = 0x0c;
+ sc->sc_regs[TWSI_CLOCK] = 0x0c;
+ sc->sc_regs[TWSI_SOFTRESET] = 0x1c;
+ }
+
/*
* Calculate clock dividers up front such that we can bail out
* early if the desired clock rate can't be obtained. Make
return;
}
n = 0, m = 0;
- while ((freq * (1 << n) * 16 * 10) < parent_freq)
+ while ((freq * (nbase << n) * 16 * 10) < parent_freq)
n++;
- while ((freq * (1 << n) * (m + 1) * 10) < parent_freq)
+ while ((freq * (nbase << n) * (m + 1) * 10) < parent_freq)
m++;
if (n > 8 || m > 16) {
printf(": clock frequency too high\n");
reset_deassert_all(faa->fa_node);
/* Set clock rate. */
- sxitwi_write_4(sc, TWI_CCR_REG, (m << 3) | (n << 0));
+ sxitwi_write_4(sc, TWSI_CLOCK, (m << 3) | (n << 0));
/* Put the controller into Soft Reset. */
sxitwi_write_4(sc, TWSI_SOFTRESET, SOFTRESET_VAL);
u_int
sxitwi_read_4(struct sxitwi_softc *sc, u_int reg)
{
- return bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg);
+ KASSERT(reg < TWSI_NREG);
+ return bus_space_read_4(sc->sc_iot, sc->sc_ioh, sc->sc_regs[reg]);
}
void
sxitwi_write_4(struct sxitwi_softc *sc, u_int reg, u_int val)
{
- bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, val);
+ KASSERT(reg < TWSI_NREG);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, sc->sc_regs[reg], val);
}
int
* START condition until the bus is free.
*/
sxitwi_write_4(sc, TWSI_CONTROL, CONTROL_STOP | sc->sc_twsien_iflg);
+ if (sc->sc_delay)
+ delay(5);
return 0;
}
if (timo == 0)
return ETIMEDOUT;
+ if (sc->sc_delay)
+ delay(5);
+
status = sxitwi_read_4(sc, TWSI_STATUS);
if (status != expect)
return EIO;