Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/arch/arm/sunxi Put RSB controller into known state at th...
details: https://anonhg.NetBSD.org/src/rev/cfde08cdee44
branches: trunk
changeset: 991334:cfde08cdee44
user: jmcneill <jmcneill%NetBSD.org@localhost>
date: Mon Jul 09 10:24:44 2018 +0000
description:
Put RSB controller into known state at the start of every transfer.
diffstat:
sys/arch/arm/sunxi/sunxi_rsb.c | 79 ++++++++++++++++++++++++++++-------------
1 files changed, 53 insertions(+), 26 deletions(-)
diffs (170 lines):
diff -r a70869e38cc8 -r cfde08cdee44 sys/arch/arm/sunxi/sunxi_rsb.c
--- a/sys/arch/arm/sunxi/sunxi_rsb.c Mon Jul 09 10:08:35 2018 +0000
+++ b/sys/arch/arm/sunxi/sunxi_rsb.c Mon Jul 09 10:24:44 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sunxi_rsb.c,v 1.3 2018/07/01 21:15:02 jmcneill Exp $ */
+/* $NetBSD: sunxi_rsb.c,v 1.4 2018/07/09 10:24:44 jmcneill Exp $ */
/*-
* Copyright (c) 2014-2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunxi_rsb.c,v 1.3 2018/07/01 21:15:02 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunxi_rsb.c,v 1.4 2018/07/09 10:24:44 jmcneill Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -191,14 +191,6 @@
}
aprint_normal_dev(self, "interrupting on %s\n", intrstr);
- /* Enable interrupts */
- RSB_WRITE(sc, RSB_INTE_REG,
- RSB_INTE_LOAD_BSY_ENB |
- RSB_INTE_TRANS_ERR_ENB |
- RSB_INTE_TRANS_OVER_ENB);
- RSB_WRITE(sc, RSB_CTRL_REG,
- RSB_CTRL_GLOBAL_INT_ENB);
-
sc->sc_ic.ic_cookie = sc;
sc->sc_ic.ic_acquire_bus = sunxi_rsb_acquire_bus;
sc->sc_ic.ic_release_bus = sunxi_rsb_release_bus;
@@ -230,6 +222,23 @@
}
static int
+sunxi_rsb_soft_reset(struct sunxi_rsb_softc *sc)
+{
+ int retry = 1000;
+
+ RSB_WRITE(sc, RSB_CTRL_REG, RSB_CTRL_SOFT_RESET);
+ while (--retry > 0) {
+ if ((RSB_READ(sc, RSB_CTRL_REG) & RSB_CTRL_SOFT_RESET) == 0)
+ break;
+ delay(10);
+ }
+ if (retry == 0)
+ return EIO;
+
+ return 0;
+}
+
+static int
sunxi_rsb_wait(struct sunxi_rsb_softc *sc, int flags)
{
int error = 0, retry;
@@ -317,12 +326,7 @@
{
struct sunxi_rsb_softc *sc = priv;
- if (flags & I2C_F_POLL) {
- if (!mutex_tryenter(&sc->sc_lock))
- return EBUSY;
- } else {
- mutex_enter(&sc->sc_lock);
- }
+ mutex_enter(&sc->sc_lock);
return 0;
}
@@ -349,6 +353,22 @@
if (cmdlen != 1 || (len != 1 && len != 2 && len != 4))
return EINVAL;
+ error = sunxi_rsb_soft_reset(sc);
+ if (error != 0) {
+ device_printf(sc->sc_dev, "soft reset timed out\n");
+ return error;
+ }
+
+ if ((flags & I2C_F_POLL) == 0) {
+ /* Enable interrupts */
+ RSB_WRITE(sc, RSB_INTE_REG,
+ RSB_INTE_LOAD_BSY_ENB |
+ RSB_INTE_TRANS_ERR_ENB |
+ RSB_INTE_TRANS_OVER_ENB);
+ RSB_WRITE(sc, RSB_CTRL_REG,
+ RSB_CTRL_GLOBAL_INT_ENB);
+ }
+
if (sc->sc_type == SUNXI_RSB && sc->sc_rsb_last_da != addr) {
/* Lookup run-time address for given device address */
for (rta = 0, i = 0; rsb_rtamap[i].rta != 0; i++)
@@ -367,7 +387,7 @@
"SRTA failed, flags = %x, error = %d\n",
flags, error);
sc->sc_rsb_last_da = 0;
- return error;
+ goto done;
}
sc->sc_rsb_last_da = addr;
@@ -392,7 +412,8 @@
(pbuf[2] << 16) | (pbuf[3] << 24);
break;
default:
- return EINVAL;
+ error = EINVAL;
+ goto done;
}
RSB_WRITE(sc, RSB_DATA0_REG, data);
}
@@ -404,14 +425,14 @@
case 1: cmd = RSB_CMD_IDX_WR8; break;
case 2: cmd = RSB_CMD_IDX_WR16; break;
case 4: cmd = RSB_CMD_IDX_WR32; break;
- default: return EINVAL;
+ default: error = EINVAL; goto done;
}
} else {
switch (len) {
case 1: cmd = RSB_CMD_IDX_RD8; break;
case 2: cmd = RSB_CMD_IDX_RD16; break;
case 4: cmd = RSB_CMD_IDX_RD32; break;
- default: return EINVAL;
+ default: error = EINVAL; goto done;
}
}
RSB_WRITE(sc, RSB_CMD_REG, cmd);
@@ -428,7 +449,8 @@
ctrl = RSB_READ(sc, RSB_CTRL_REG);
if (ctrl & RSB_CTRL_START_TRANS) {
device_printf(sc->sc_dev, "device is busy\n");
- return EBUSY;
+ error = EBUSY;
+ goto done;
}
/* Start the transfer */
@@ -436,9 +458,8 @@
ctrl | RSB_CTRL_START_TRANS);
error = sunxi_rsb_wait(sc, flags);
- if (error) {
- return error;
- }
+ if (error)
+ goto done;
if (I2C_OP_READ_P(op)) {
uint32_t data = RSB_READ(sc, RSB_DATA0_REG);
@@ -453,9 +474,15 @@
*(uint8_t *)buf = data & 0xff;
break;
default:
- return EINVAL;
+ error = EINVAL;
+ goto done;
}
}
- return 0;
+ error = 0;
+
+done:
+ RSB_WRITE(sc, RSB_CTRL_REG, 0);
+
+ return error;
}
Home |
Main Index |
Thread Index |
Old Index