Module Name: src Committed By: jmcneill Date: Sun Dec 7 00:36:26 UTC 2014
Modified Files: src/sys/arch/arm/allwinner: awin_intr.h awin_io.c awin_p2wi.c awin_reg.h awin_var.h src/sys/arch/evbarm/awin: awin_machdep.c platform.h Log Message: A80 reduced serial bus (RSB) support. Similar to A31 P2WI but supports more than one attached slave device. To generate a diff of this commit: cvs rdiff -u -r1.12 -r1.13 src/sys/arch/arm/allwinner/awin_intr.h cvs rdiff -u -r1.37 -r1.38 src/sys/arch/arm/allwinner/awin_io.c cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/allwinner/awin_p2wi.c cvs rdiff -u -r1.66 -r1.67 src/sys/arch/arm/allwinner/awin_reg.h cvs rdiff -u -r1.31 -r1.32 src/sys/arch/arm/allwinner/awin_var.h cvs rdiff -u -r1.33 -r1.34 src/sys/arch/evbarm/awin/awin_machdep.c cvs rdiff -u -r1.3 -r1.4 src/sys/arch/evbarm/awin/platform.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/allwinner/awin_intr.h diff -u src/sys/arch/arm/allwinner/awin_intr.h:1.12 src/sys/arch/arm/allwinner/awin_intr.h:1.13 --- src/sys/arch/arm/allwinner/awin_intr.h:1.12 Fri Dec 5 11:53:22 2014 +++ src/sys/arch/arm/allwinner/awin_intr.h Sun Dec 7 00:36:26 2014 @@ -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 Index: src/sys/arch/arm/allwinner/awin_io.c diff -u src/sys/arch/arm/allwinner/awin_io.c:1.37 src/sys/arch/arm/allwinner/awin_io.c:1.38 --- src/sys/arch/arm/allwinner/awin_io.c:1.37 Fri Dec 5 19:06:41 2014 +++ src/sys/arch/arm/allwinner/awin_io.c Sun Dec 7 00:36:26 2014 @@ -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 @@ static struct awinio_softc { 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 @@ static const struct awin_locators awin_l { "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 @@ awinio_attach(device_t parent, device_t 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 @@ awinio_attach(device_t parent, device_t .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, }; Index: src/sys/arch/arm/allwinner/awin_p2wi.c diff -u src/sys/arch/arm/allwinner/awin_p2wi.c:1.1 src/sys/arch/arm/allwinner/awin_p2wi.c:1.2 --- src/sys/arch/arm/allwinner/awin_p2wi.c:1.1 Sun Oct 12 23:57:58 2014 +++ src/sys/arch/arm/allwinner/awin_p2wi.c Sun Dec 7 00:36:26 2014 @@ -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 <jmcne...@invisible.ca> @@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: awin_p2wi.c, #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 @@ struct awin_p2wi_softc { device_t sc_i2cdev; void *sc_ih; uint32_t sc_stat; + + bool sc_rsb_p; }; #define P2WI_READ(sc, reg) \ @@ -66,6 +74,9 @@ static int awin_p2wi_exec(void *, i2c_op 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 @@ awin_p2wi_attach(device_t parent, device 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 @@ awin_p2wi_intr(void *priv) } 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 @@ awin_p2wi_exec(void *priv, i2c_op_t op, { 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 @@ awin_p2wi_exec(void *priv, i2c_op_t op, 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 @@ awin_p2wi_exec(void *priv, i2c_op_t op, 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) { - device_printf(sc->sc_dev, "transfer error, id 0x%02llx\n", - __SHIFTOUT(sc->sc_stat, AWIN_A31_P2WI_STAT_TRANS_ERR_ID)); - return EIO; - } - if (I2C_OP_READ_P(op)) { *(uint8_t *)buf = P2WI_READ(sc, AWIN_A31_P2WI_DATA0_REG) & 0xff; } Index: src/sys/arch/arm/allwinner/awin_reg.h diff -u src/sys/arch/arm/allwinner/awin_reg.h:1.66 src/sys/arch/arm/allwinner/awin_reg.h:1.67 --- src/sys/arch/arm/allwinner/awin_reg.h:1.66 Fri Dec 5 23:25:17 2014 +++ src/sys/arch/arm/allwinner/awin_reg.h Sun Dec 7 00:36:26 2014 @@ -58,6 +58,8 @@ #define AWIN_A80_CORE2_SIZE 0x00005000 #define AWIN_A80_USB_PBASE 0x00a00000 #define AWIN_A80_USB_SIZE 0x00010000 +#define AWIN_A80_RCPUS_PBASE 0x08000000 +#define AWIN_A80_RCPUS_SIZE 0x00010000 #else #define AWIN_CORE_SIZE 0x00400000 #endif @@ -2702,6 +2704,12 @@ struct awin_a31_dma_desc { #define AWIN_A80_DMA_OFFSET 0x00002000 #define AWIN_A80_GMAC_OFFSET 0x00030000 +/* + * These offsets are relative to AWIN_A80_RCPUS_PBASE + */ +#define AWIN_A80_RPRCM_OFFSET 0x00001400 +#define AWIN_A80_RSB_OFFSET 0x00003400 + #define AWIN_A80_SDMMC_COMM_SDC_RESET_SW __BIT(18) #define AWIN_A80_SDMMC_COMM_SDC_CLOCK_SW __BIT(16) @@ -2805,6 +2813,21 @@ struct awin_a31_dma_desc { #define AWIN_A80_SYS_CTRL_EMAC_CLK_REG 0x0030 #define AWIN_A80_SYS_CTRL_DISP_MUX_CTRL_REG 0x0038 +#define AWIN_A80_RSB_CMD_REG 0x002c +#define AWIN_A80_RSB_DAR_REG 0x0030 + +#define AWIN_A80_RSB_CMD_IDX __BITS(7,0) +#define AWIN_A80_RSB_CMD_IDX_SRTA 0xe8 +#define AWIN_A80_RSB_CMD_IDX_RD8 0x8b +#define AWIN_A80_RSB_CMD_IDX_RD16 0x9c +#define AWIN_A80_RSB_CMD_IDX_RD32 0xa6 +#define AWIN_A80_RSB_CMD_IDX_WR8 0x4e +#define AWIN_A80_RSB_CMD_IDX_WR16 0x59 +#define AWIN_A80_RSB_CMD_IDX_WR32 0x63 + +#define AWIN_A80_RSB_DAR_RTA __BITS(23,16) +#define AWIN_A80_RSB_DAR_DA __BITS(15,0) + #define AWIN_A80_PIO_PA_PINS 18 #define AWIN_A80_PIO_PA_GMAC_FUNC 2 #define AWIN_A80_PIO_PA_GMAC_PINS 0x0003f7bf /* PA pins 17-12,10-7,5-0 */ Index: src/sys/arch/arm/allwinner/awin_var.h diff -u src/sys/arch/arm/allwinner/awin_var.h:1.31 src/sys/arch/arm/allwinner/awin_var.h:1.32 --- src/sys/arch/arm/allwinner/awin_var.h:1.31 Fri Dec 5 18:41:41 2014 +++ src/sys/arch/arm/allwinner/awin_var.h Sun Dec 7 00:36:26 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: awin_var.h,v 1.31 2014/12/05 18:41:41 jmcneill Exp $ */ +/* $NetBSD: awin_var.h,v 1.32 2014/12/07 00:36:26 jmcneill Exp $ */ /*- * Copyright (c) 2013 The NetBSD Foundation, Inc. * All rights reserved. @@ -61,6 +61,7 @@ struct awinio_attach_args { bus_space_handle_t aio_ccm_bsh; bus_space_handle_t aio_a80_usb_bsh; bus_space_handle_t aio_a80_core2_bsh; + bus_space_handle_t aio_a80_rcpus_bsh; bus_dma_tag_t aio_dmat; bus_dma_tag_t aio_coherent_dmat; }; Index: src/sys/arch/evbarm/awin/awin_machdep.c diff -u src/sys/arch/evbarm/awin/awin_machdep.c:1.33 src/sys/arch/evbarm/awin/awin_machdep.c:1.34 --- src/sys/arch/evbarm/awin/awin_machdep.c:1.33 Fri Dec 5 17:32:08 2014 +++ src/sys/arch/evbarm/awin/awin_machdep.c Sun Dec 7 00:36:26 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: awin_machdep.c,v 1.33 2014/12/05 17:32:08 jmcneill Exp $ */ +/* $NetBSD: awin_machdep.c,v 1.34 2014/12/07 00:36:26 jmcneill Exp $ */ /* * Machine dependent functions for kernel setup for TI OSK5912 board. @@ -125,7 +125,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: awin_machdep.c,v 1.33 2014/12/05 17:32:08 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: awin_machdep.c,v 1.34 2014/12/07 00:36:26 jmcneill Exp $"); #include "opt_machdep.h" #include "opt_ddb.h" @@ -308,6 +308,16 @@ static const struct pmap_devmap devmap[] .pd_prot = VM_PROT_READ|VM_PROT_WRITE, .pd_cache = PTE_NOCACHE }, + { + /* + * A80 RSB, RPRCM + */ + .pd_va = _A(AWIN_A80_RCPUS_VBASE), + .pd_pa = _A(AWIN_A80_RCPUS_PBASE), + .pd_size = _S(AWIN_A80_RCPUS_SIZE), + .pd_prot = VM_PROT_READ|VM_PROT_WRITE, + .pd_cache = PTE_NOCACHE + }, #endif { /* Index: src/sys/arch/evbarm/awin/platform.h diff -u src/sys/arch/evbarm/awin/platform.h:1.3 src/sys/arch/evbarm/awin/platform.h:1.4 --- src/sys/arch/evbarm/awin/platform.h:1.3 Fri Dec 5 17:32:08 2014 +++ src/sys/arch/evbarm/awin/platform.h Sun Dec 7 00:36:26 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: platform.h,v 1.3 2014/12/05 17:32:08 jmcneill Exp $ */ +/* $NetBSD: platform.h,v 1.4 2014/12/07 00:36:26 jmcneill Exp $ */ /* * Copyright (c) 2007 Microsoft * All rights reserved. @@ -55,7 +55,8 @@ #if defined(ALLWINNER_A80) #define AWIN_A80_CORE2_VBASE (AWIN_SRAM_VBASE + AWIN_SRAM_SIZE) #define AWIN_A80_USB_VBASE (AWIN_A80_CORE2_VBASE + AWIN_A80_CORE2_SIZE) -#define AWIN_KERNEL_IO_VEND (AWIN_A80_USB_VBASE + AWIN_A80_USB_SIZE) +#define AWIN_A80_RCPUS_VBASE (AWIN_A80_USB_VBASE + AWIN_A80_USB_SIZE) +#define AWIN_KERNEL_IO_VEND (AWIN_A80_RCPUS_VBASE + AWIN_A80_RCPUS_SIZE) #else #define AWIN_KERNEL_IO_VEND (AWIN_SRAM_VBASE + AWIN_SRAM_SIZE) #endif