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