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/de546638c158
branches:  trunk
changeset: 323949:de546638c158
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 46e5365da4a3 -r de546638c158 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