Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch A80 reduced serial bus (RSB) support. Similar to A3...



details:   https://anonhg.NetBSD.org/src/rev/d5afe89babb9
branches:  trunk
changeset: 334787:d5afe89babb9
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Dec 07 00:36:26 2014 +0000

description:
A80 reduced serial bus (RSB) support. Similar to A31 P2WI but supports
more than one attached slave device.

diffstat:

 sys/arch/arm/allwinner/awin_intr.h  |    3 +-
 sys/arch/arm/allwinner/awin_io.c    |    7 +-
 sys/arch/arm/allwinner/awin_p2wi.c  |  161 ++++++++++++++++++++++++++++-------
 sys/arch/arm/allwinner/awin_reg.h   |   23 +++++
 sys/arch/arm/allwinner/awin_var.h   |    3 +-
 sys/arch/evbarm/awin/awin_machdep.c |   14 ++-
 sys/arch/evbarm/awin/platform.h     |    5 +-
 7 files changed, 177 insertions(+), 39 deletions(-)

diffs (truncated from 426 to 300 lines):

diff -r 6d46dcfaab64 -r d5afe89babb9 sys/arch/arm/allwinner/awin_intr.h
--- a/sys/arch/arm/allwinner/awin_intr.h        Sun Dec 07 00:33:26 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_intr.h        Sun Dec 07 00:36:26 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_intr.h,v 1.12 2014/12/05 11:53:22 jmcneill Exp $ */
+/* $NetBSD: awin_intr.h,v 1.13 2014/12/07 00:36:26 jmcneill Exp $ */
 /*-
  * Copyright (c) 2013 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -198,6 +198,7 @@
 #define AWIN_A80_IRQ_WATCHDOG  56
 #define AWIN_A80_IRQ_KEYADC    62
 #define AWIN_A80_IRQ_NMI       64
+#define AWIN_A80_IRQ_R_RSB     71
 #define AWIN_A80_IRQ_DMA       82
 #define AWIN_A80_IRQ_HSTIMER0  83
 #define AWIN_A80_IRQ_HSTIMER1  84
diff -r 6d46dcfaab64 -r d5afe89babb9 sys/arch/arm/allwinner/awin_io.c
--- a/sys/arch/arm/allwinner/awin_io.c  Sun Dec 07 00:33:26 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_io.c  Sun Dec 07 00:36:26 2014 +0000
@@ -31,7 +31,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: awin_io.c,v 1.37 2014/12/05 19:06:41 jmcneill Exp $");
+__KERNEL_RCSID(1, "$NetBSD: awin_io.c,v 1.38 2014/12/07 00:36:26 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -57,6 +57,7 @@
        bus_space_handle_t sc_ccm_bsh;
        bus_space_handle_t sc_a80_usb_bsh;
        bus_space_handle_t sc_a80_core2_bsh;
+       bus_space_handle_t sc_a80_rcpus_bsh;
        bus_dma_tag_t sc_dmat;
        bus_dma_tag_t sc_coherent_dmat;
 } awinio_sc;
@@ -163,6 +164,7 @@
        { "awiniic", OFFANDSIZE(A80_TWI3), 3, AWIN_A80_IRQ_TWI3, A80 },
        { "awiniic", OFFANDSIZE(A80_TWI4), 4, AWIN_A80_IRQ_TWI4, A80 },
        { "awinp2wi", OFFANDSIZE(A31_P2WI), NOPORT, AWIN_A31_IRQ_P2WI, A31 },
+       { "awinp2wi", OFFANDSIZE(A80_RSB), NOPORT, AWIN_A80_IRQ_R_RSB, A80 },
        { "spi", OFFANDSIZE(SPI0), 0, AWIN_IRQ_SPI0, AANY },
        { "spi", OFFANDSIZE(SPI1), 1, AWIN_IRQ_SPI1, AANY },
        { "spi", OFFANDSIZE(SPI2), 1, AWIN_IRQ_SPI2, AANY },
@@ -225,6 +227,8 @@
                    AWIN_A80_USB_SIZE, 0, &sc->sc_a80_usb_bsh);
                bus_space_map(sc->sc_bst, AWIN_A80_CORE2_PBASE,
                    AWIN_A80_CORE2_SIZE, 0, &sc->sc_a80_core2_bsh);
+               bus_space_map(sc->sc_bst, AWIN_A80_RCPUS_PBASE,
+                   AWIN_A80_RCPUS_SIZE, 0, &sc->sc_a80_rcpus_bsh);
                break;
 #endif
        default:
@@ -274,6 +278,7 @@
                        .aio_ccm_bsh = sc->sc_ccm_bsh,
                        .aio_a80_usb_bsh = sc->sc_a80_usb_bsh,
                        .aio_a80_core2_bsh = sc->sc_a80_core2_bsh,
+                       .aio_a80_rcpus_bsh = sc->sc_a80_rcpus_bsh,
                        .aio_dmat = sc->sc_dmat,
                        .aio_coherent_dmat = sc->sc_coherent_dmat,
                };
diff -r 6d46dcfaab64 -r d5afe89babb9 sys/arch/arm/allwinner/awin_p2wi.c
--- a/sys/arch/arm/allwinner/awin_p2wi.c        Sun Dec 07 00:33:26 2014 +0000
+++ b/sys/arch/arm/allwinner/awin_p2wi.c        Sun Dec 07 00:36:26 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: awin_p2wi.c,v 1.1 2014/10/12 23:57:58 jmcneill Exp $ */
+/* $NetBSD: awin_p2wi.c,v 1.2 2014/12/07 00:36:26 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2014 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: awin_p2wi.c,v 1.1 2014/10/12 23:57:58 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: awin_p2wi.c,v 1.2 2014/12/07 00:36:26 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -43,6 +43,12 @@
 
 #include <dev/i2c/i2cvar.h>
 
+#define AWIN_RSB_ADDR_AXP809   0x3a3
+#define AWIN_RSB_ADDR_AXP806   0x745
+
+#define AWIN_RSB_RTA_AXP809    0x2d
+#define AWIN_RSB_RTA_AXP806    0x3a
+
 struct awin_p2wi_softc {
        device_t sc_dev;
        bus_space_tag_t sc_bst;
@@ -53,6 +59,8 @@
        device_t sc_i2cdev;
        void *sc_ih;
        uint32_t sc_stat;
+
+       bool sc_rsb_p;
 };
 
 #define P2WI_READ(sc, reg) \
@@ -66,6 +74,9 @@
                               size_t, void *, size_t, int);
 
 static int     awin_p2wi_intr(void *);
+static int     awin_p2wi_wait(struct awin_p2wi_softc *, int);
+static int     awin_p2wi_rsb_config(struct awin_p2wi_softc *,
+                                    uint8_t, i2c_addr_t, int);
 
 static int     awin_p2wi_match(device_t, cfdata_t, void *);
 static void    awin_p2wi_attach(device_t, device_t, void *);
@@ -95,13 +106,15 @@
 
        sc->sc_dev = self;
        sc->sc_bst = aio->aio_core_bst;
+       sc->sc_rsb_p = awin_chip_id() == AWIN_CHIP_ID_A80;
        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SCHED);
        cv_init(&sc->sc_cv, "awinp2wi");
-       bus_space_subregion(sc->sc_bst, aio->aio_core_bsh,
+       bus_space_subregion(sc->sc_bst,
+           sc->sc_rsb_p ? aio->aio_a80_rcpus_bsh : aio->aio_core_bsh,
            loc->loc_offset, loc->loc_size, &sc->sc_bsh);
 
        aprint_naive("\n");
-       aprint_normal(": P2WI\n");
+       aprint_normal(": %s\n", sc->sc_rsb_p ? "RSB" : "P2WI");
 
        sc->sc_ih = intr_establish(loc->loc_intr, IPL_SCHED, IST_LEVEL,
            awin_p2wi_intr, sc);
@@ -151,6 +164,89 @@
 }
 
 static int
+awin_p2wi_wait(struct awin_p2wi_softc *sc, int flags)
+{
+       int error = 0, retry;
+
+       /* Wait up to 5 seconds for a transfer to complete */
+       sc->sc_stat = 0;
+       for (retry = (flags & I2C_F_POLL) ? 100 : 5; retry > 0; retry--) {
+               if (flags & I2C_F_POLL) {
+                       sc->sc_stat |= P2WI_READ(sc, AWIN_A31_P2WI_STAT_REG);
+               } else {
+                       error = cv_timedwait(&sc->sc_cv, &sc->sc_lock, hz);
+                       if (error && error != EWOULDBLOCK) {
+                               break;
+                       }
+               }
+               if (sc->sc_stat & AWIN_A31_P2WI_STAT_MASK) {
+                       break;
+               }
+               if (flags & I2C_F_POLL) {
+                       delay(10000);
+               }
+       }
+       if (retry == 0)
+               error = EAGAIN;
+
+       if (flags & I2C_F_POLL) {
+               P2WI_WRITE(sc, AWIN_A31_P2WI_STAT_REG,
+                   sc->sc_stat & AWIN_A31_P2WI_STAT_MASK);
+       }
+
+       if (error) {
+               /* Abort transaction */
+               device_printf(sc->sc_dev, "transfer timeout, error = %d\n",
+                   error);
+               P2WI_WRITE(sc, AWIN_A31_P2WI_CTRL_REG,
+                   AWIN_A31_P2WI_CTRL_ABORT_TRANS);
+               return error;
+       }
+
+       if (sc->sc_stat & AWIN_A31_P2WI_STAT_LOAD_BSY) {
+               device_printf(sc->sc_dev, "transfer busy\n");
+               return EBUSY;
+       }
+       if (sc->sc_stat & AWIN_A31_P2WI_STAT_TRANS_ERR) {
+               device_printf(sc->sc_dev, "transfer error, id 0x%02llx\n",
+                   __SHIFTOUT(sc->sc_stat, AWIN_A31_P2WI_STAT_TRANS_ERR_ID));
+               return EIO;
+       }
+
+       return 0;
+}
+
+static int
+awin_p2wi_rsb_config(struct awin_p2wi_softc *sc, uint8_t rta, i2c_addr_t da,
+    int flags)
+{
+       uint32_t dar, ctrl;
+
+       KASSERT(mutex_owned(&sc->sc_lock));
+
+       P2WI_WRITE(sc, AWIN_A31_P2WI_STAT_REG,
+           P2WI_READ(sc, AWIN_A31_P2WI_STAT_REG) & AWIN_A31_P2WI_STAT_MASK);
+
+       dar = __SHIFTIN(rta, AWIN_A80_RSB_DAR_RTA);
+       dar |= __SHIFTIN(da, AWIN_A80_RSB_DAR_DA);
+       P2WI_WRITE(sc, AWIN_A80_RSB_DAR_REG, dar);
+       P2WI_WRITE(sc, AWIN_A80_RSB_CMD_REG, AWIN_A80_RSB_CMD_IDX_SRTA);
+
+       /* Make sure the controller is idle */
+       ctrl = P2WI_READ(sc, AWIN_A31_P2WI_CTRL_REG);
+       if (ctrl & AWIN_A31_P2WI_CTRL_START_TRANS) {
+               device_printf(sc->sc_dev, "device is busy\n");
+               return EBUSY;
+       }
+
+       /* Start the transfer */
+       P2WI_WRITE(sc, AWIN_A31_P2WI_CTRL_REG,
+           ctrl | AWIN_A31_P2WI_CTRL_START_TRANS);
+
+       return awin_p2wi_wait(sc, flags);
+}
+
+static int
 awin_p2wi_acquire_bus(void *priv, int flags)
 {
        struct awin_p2wi_softc *sc = priv;
@@ -179,13 +275,34 @@
 {
        struct awin_p2wi_softc *sc = priv;
        uint32_t dlen, ctrl;
-       int error, retry;
+       uint8_t rta;
+       int error;
 
        KASSERT(mutex_owned(&sc->sc_lock));
 
        if (cmdlen != 1 || len != 1)
                return EINVAL;
 
+       if (sc->sc_rsb_p) {
+               switch (addr) {
+               case AWIN_RSB_ADDR_AXP809:
+                       rta = AWIN_RSB_RTA_AXP809;
+                       break;
+               case AWIN_RSB_ADDR_AXP806:
+                       rta = AWIN_RSB_RTA_AXP806;
+                       break;
+               default:
+                       return ENXIO;
+               }
+               error = awin_p2wi_rsb_config(sc, rta, addr, flags);
+               if (error) {
+                       device_printf(sc->sc_dev,
+                           "SRTA failed, flags = %x, error = %d\n",
+                           flags, error);
+                       return error;
+               }
+       }
+
        /* Data byte register */
        P2WI_WRITE(sc, AWIN_A31_P2WI_DADDR0_REG, *(const uint8_t *)cmdbuf);
 
@@ -194,6 +311,12 @@
                P2WI_WRITE(sc, AWIN_A31_P2WI_DATA0_REG, *(uint8_t *)buf);
        }
 
+       if (sc->sc_rsb_p) {
+               uint8_t cmd = I2C_OP_WRITE_P(op) ? AWIN_A80_RSB_CMD_IDX_WR8 :
+                                                  AWIN_A80_RSB_CMD_IDX_RD8;
+               P2WI_WRITE(sc, AWIN_A80_RSB_CMD_REG, cmd);
+       }
+
        /* Program data length register; if reading, set read/write bit */
        dlen = __SHIFTIN(len - 1, AWIN_A31_P2WI_DLEN_ACCESS_LENGTH);
        if (I2C_OP_READ_P(op)) {
@@ -212,37 +335,11 @@
        P2WI_WRITE(sc, AWIN_A31_P2WI_CTRL_REG,
            ctrl | AWIN_A31_P2WI_CTRL_START_TRANS);
 
-       /* Wait up to 5 seconds for an interrupt */
-       sc->sc_stat = 0;
-       for (retry = 5; retry > 0; retry--) {
-               error = cv_timedwait(&sc->sc_cv, &sc->sc_lock, hz);
-               if (error && error != EWOULDBLOCK) {
-                       break;
-               }
-               if (sc->sc_stat & AWIN_A31_P2WI_STAT_MASK) {
-                       break;
-               }
-       }
-
+       error = awin_p2wi_wait(sc, flags);
        if (error) {
-               /* Abort transaction */
-               device_printf(sc->sc_dev, "transfer timeout, error = %d\n",
-                   error);
-               P2WI_WRITE(sc, AWIN_A31_P2WI_CTRL_REG,
-                   AWIN_A31_P2WI_CTRL_ABORT_TRANS);
                return error;
        }
 
-       if (sc->sc_stat & AWIN_A31_P2WI_STAT_LOAD_BSY) {
-               device_printf(sc->sc_dev, "transfer busy\n");
-               return EBUSY;
-       }
-       if (sc->sc_stat & AWIN_A31_P2WI_STAT_TRANS_ERR) {



Home | Main Index | Thread Index | Old Index