Module Name: src Committed By: jmcneill Date: Sun Oct 29 16:02:46 UTC 2017
Modified Files: src/sys/arch/arm/sunxi: sunxi_musb.c src/sys/arch/evbarm/conf: SUNXI Log Message: Create a custom bus space tag and use it to remap registers instead of relying on options MOTG_ALLWINNER. To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/sunxi/sunxi_musb.c cvs rdiff -u -r1.49 -r1.50 src/sys/arch/evbarm/conf/SUNXI 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/sunxi/sunxi_musb.c diff -u src/sys/arch/arm/sunxi/sunxi_musb.c:1.1 src/sys/arch/arm/sunxi/sunxi_musb.c:1.2 --- src/sys/arch/arm/sunxi/sunxi_musb.c:1.1 Sat Sep 9 12:01:04 2017 +++ src/sys/arch/arm/sunxi/sunxi_musb.c Sun Oct 29 16:02:46 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: sunxi_musb.c,v 1.1 2017/09/09 12:01:04 jmcneill Exp $ */ +/* $NetBSD: sunxi_musb.c,v 1.2 2017/10/29 16:02:46 jmcneill Exp $ */ /*- * Copyright (c) 2017 Jared McNeill <jmcne...@invisible.ca> @@ -26,8 +26,13 @@ * SUCH DAMAGE. */ +#include "opt_motg.h" +#ifdef MOTG_ALLWINNER +# error Do not define MOTG_ALLWINNER when using this driver +#endif + #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sunxi_musb.c,v 1.1 2017/09/09 12:01:04 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunxi_musb.c,v 1.2 2017/10/29 16:02:46 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -41,18 +46,23 @@ __KERNEL_RCSID(0, "$NetBSD: sunxi_musb.c #include <dev/usb/usbdi.h> #include <dev/usb/usbdivar.h> #include <dev/usb/motgvar.h> +#include <dev/usb/motgreg.h> #include <dev/fdt/fdtvar.h> +#include <machine/bus_defs.h> + #define MUSB2_REG_AWIN_VEND0 0x43 -#define MUSB2_REG_INTTX 0x44 -#define MUSB2_REG_INTRX 0x46 -#define MUSB2_REG_INTUSB 0x4c static int sunxi_musb_match(device_t, cfdata_t, void *); static void sunxi_musb_attach(device_t, device_t, void *); -CFATTACH_DECL_NEW(sunxi_musb, sizeof(struct motg_softc), +struct sunxi_musb_softc { + struct motg_softc sc_otg; + struct bus_space sc_bs; +}; + +CFATTACH_DECL_NEW(sunxi_musb, sizeof(struct sunxi_musb_softc), sunxi_musb_match, sunxi_musb_attach, NULL, NULL); static const struct of_compat_data compat_data[] = { @@ -63,6 +73,217 @@ static const struct of_compat_data compa { NULL } }; +#define REMAPFLAG 0x8000 +#define REGDECL(a, b) [(a)] = ((b) | REMAPFLAG) + +/* Allwinner USB DRD register mappings */ +static const uint16_t sunxi_musb_regmap[] = { + REGDECL(MUSB2_REG_EPFIFO(0), 0x0000), + REGDECL(MUSB2_REG_EPFIFO(1), 0x0004), + REGDECL(MUSB2_REG_EPFIFO(2), 0x0008), + REGDECL(MUSB2_REG_EPFIFO(3), 0x000c), + REGDECL(MUSB2_REG_EPFIFO(4), 0x0010), + REGDECL(MUSB2_REG_EPFIFO(5), 0x0014), + REGDECL(MUSB2_REG_POWER, 0x0040), + REGDECL(MUSB2_REG_DEVCTL, 0x0041), + REGDECL(MUSB2_REG_EPINDEX, 0x0042), + REGDECL(MUSB2_REG_AWIN_VEND0, 0x0043), + REGDECL(MUSB2_REG_INTTX, 0x0044), + REGDECL(MUSB2_REG_INTRX, 0x0046), + REGDECL(MUSB2_REG_INTTXE, 0x0048), + REGDECL(MUSB2_REG_INTRXE, 0x004a), + REGDECL(MUSB2_REG_INTUSB, 0x004c), + REGDECL(MUSB2_REG_INTUSBE, 0x0050), + REGDECL(MUSB2_REG_FRAME, 0x0054), + REGDECL(MUSB2_REG_TESTMODE, 0x007c), + REGDECL(MUSB2_REG_TXMAXP, 0x0080), + REGDECL(MUSB2_REG_TXCSRL, 0x0082), + REGDECL(MUSB2_REG_TXCSRH, 0x0083), + REGDECL(MUSB2_REG_RXMAXP, 0x0084), + REGDECL(MUSB2_REG_RXCSRL, 0x0086), + REGDECL(MUSB2_REG_RXCSRH, 0x0087), + REGDECL(MUSB2_REG_RXCOUNT, 0x0088), + REGDECL(MUSB2_REG_TXTI, 0x008c), + REGDECL(MUSB2_REG_TXNAKLIMIT, 0x008d), + REGDECL(MUSB2_REG_RXNAKLIMIT, 0x008d), + REGDECL(MUSB2_REG_RXTI, 0x008e), + REGDECL(MUSB2_REG_TXFIFOSZ, 0x0090), + REGDECL(MUSB2_REG_TXFIFOADD, 0x0092), + REGDECL(MUSB2_REG_RXFIFOSZ, 0x0094), + REGDECL(MUSB2_REG_RXFIFOADD, 0x0096), + REGDECL(MUSB2_REG_FADDR, 0x0098), + REGDECL(MUSB2_REG_TXFADDR(0), 0x0098), + REGDECL(MUSB2_REG_TXHADDR(0), 0x009a), + REGDECL(MUSB2_REG_TXHUBPORT(0), 0x009b), + REGDECL(MUSB2_REG_RXFADDR(0), 0x009c), + REGDECL(MUSB2_REG_RXHADDR(0), 0x009e), + REGDECL(MUSB2_REG_RXHUBPORT(0), 0x009f), + REGDECL(MUSB2_REG_TXFADDR(1), 0x0098), + REGDECL(MUSB2_REG_TXHADDR(1), 0x009a), + REGDECL(MUSB2_REG_TXHUBPORT(1), 0x009b), + REGDECL(MUSB2_REG_RXFADDR(1), 0x009c), + REGDECL(MUSB2_REG_RXHADDR(1), 0x009e), + REGDECL(MUSB2_REG_RXHUBPORT(1), 0x009f), + REGDECL(MUSB2_REG_TXFADDR(2), 0x0098), + REGDECL(MUSB2_REG_TXHADDR(2), 0x009a), + REGDECL(MUSB2_REG_TXHUBPORT(2), 0x009b), + REGDECL(MUSB2_REG_RXFADDR(2), 0x009c), + REGDECL(MUSB2_REG_RXHADDR(2), 0x009e), + REGDECL(MUSB2_REG_RXHUBPORT(2), 0x009f), + REGDECL(MUSB2_REG_TXFADDR(3), 0x0098), + REGDECL(MUSB2_REG_TXHADDR(3), 0x009a), + REGDECL(MUSB2_REG_TXHUBPORT(3), 0x009b), + REGDECL(MUSB2_REG_RXFADDR(3), 0x009c), + REGDECL(MUSB2_REG_RXHADDR(3), 0x009e), + REGDECL(MUSB2_REG_RXHUBPORT(3), 0x009f), + REGDECL(MUSB2_REG_TXFADDR(4), 0x0098), + REGDECL(MUSB2_REG_TXHADDR(4), 0x009a), + REGDECL(MUSB2_REG_TXHUBPORT(4), 0x009b), + REGDECL(MUSB2_REG_RXFADDR(4), 0x009c), + REGDECL(MUSB2_REG_RXHADDR(4), 0x009e), + REGDECL(MUSB2_REG_RXHUBPORT(4), 0x009f), + REGDECL(MUSB2_REG_TXFADDR(5), 0x0098), + REGDECL(MUSB2_REG_TXHADDR(5), 0x009a), + REGDECL(MUSB2_REG_TXHUBPORT(5), 0x009b), + REGDECL(MUSB2_REG_RXFADDR(5), 0x009c), + REGDECL(MUSB2_REG_RXHADDR(5), 0x009e), + REGDECL(MUSB2_REG_RXHUBPORT(5), 0x009f), + REGDECL(MUSB2_REG_CONFDATA, 0x00c0), +}; + +static bus_size_t +sunxi_musb_reg(bus_size_t o) +{ + bus_size_t v; + + if (o >= __arraycount(sunxi_musb_regmap)) + return o; + + v = sunxi_musb_regmap[o]; + KASSERTMSG((v & REMAPFLAG) != 0, "%s: reg %#lx not in regmap", + __func__, o); + + return v & ~REMAPFLAG; +} + +static int +sunxi_musb_filt(bus_size_t o) +{ + switch (o) { + case MUSB2_REG_MISC: + case MUSB2_REG_RXDBDIS: + case MUSB2_REG_TXDBDIS: + return 1; + default: + return 0; + } +} + +static uint8_t +sunxi_musb_bs_r_1(void *t, bus_space_handle_t h, bus_size_t o) +{ + const struct bus_space *bs = t; + const struct bus_space *bs_parent = bs->bs_cookie; + + switch (o) { + case MUSB2_REG_HWVERS: + return 0; /* no known equivalent */ + } + + return bus_space_read_1(bs_parent, h, sunxi_musb_reg(o)); +} + +static uint16_t +sunxi_musb_bs_r_2(void *t, bus_space_handle_t h, bus_size_t o) +{ + const struct bus_space *bs = t; + const struct bus_space *bs_parent = bs->bs_cookie; + + return bus_space_read_2(bs_parent, h, sunxi_musb_reg(o)); +} + +static void +sunxi_musb_bs_w_1(void *t, bus_space_handle_t h, bus_size_t o, + uint8_t v) +{ + const struct bus_space *bs = t; + const struct bus_space *bs_parent = bs->bs_cookie; + + if (sunxi_musb_filt(o) != 0) + return; + + bus_space_write_1(bs_parent, h, sunxi_musb_reg(o), v); +} + +static void +sunxi_musb_bs_w_2(void *t, bus_space_handle_t h, bus_size_t o, + uint16_t v) +{ + const struct bus_space *bs = t; + const struct bus_space *bs_parent = bs->bs_cookie; + + if (sunxi_musb_filt(o) != 0) + return; + + bus_space_write_2(bs_parent, h, sunxi_musb_reg(o), v); +} + +static void +sunxi_musb_bs_rm_1(void *t, bus_space_handle_t h, bus_size_t o, + uint8_t *d, bus_size_t c) +{ + const struct bus_space *bs = t; + const struct bus_space *bs_parent = bs->bs_cookie; + + bus_space_read_multi_1(bs_parent, h, sunxi_musb_reg(o), d, c); +} + +static void +sunxi_musb_bs_rm_4(void *t, bus_space_handle_t h, bus_size_t o, + uint32_t *d, bus_size_t c) +{ + const struct bus_space *bs = t; + const struct bus_space *bs_parent = bs->bs_cookie; + + bus_space_read_multi_4(bs_parent, h, sunxi_musb_reg(o), d, c); +} + +static void +sunxi_musb_bs_wm_1(void *t, bus_space_handle_t h, bus_size_t o, + const uint8_t *d, bus_size_t c) +{ + const struct bus_space *bs = t; + const struct bus_space *bs_parent = bs->bs_cookie; + + if (sunxi_musb_filt(o) != 0) + return; + + bus_space_write_multi_1(bs_parent, h, sunxi_musb_reg(o), d, c); +} + +static void +sunxi_musb_bs_wm_4(void *t, bus_space_handle_t h, bus_size_t o, + const uint32_t *d, bus_size_t c) +{ + const struct bus_space *bs = t; + const struct bus_space *bs_parent = bs->bs_cookie; + + if (sunxi_musb_filt(o) != 0) + return; + + bus_space_write_multi_4(bs_parent, h, sunxi_musb_reg(o), d, c); +} + +static void +sunxi_musb_bs_barrier(void *t, bus_space_handle_t h, bus_size_t o, + bus_size_t l, int f) +{ + const struct bus_space *bs = t; + const struct bus_space *bs_parent = bs->bs_cookie; + + bus_space_barrier(bs_parent, h, o, l, f); +} + static int sunxi_musb_intr(void *priv) { @@ -111,7 +332,8 @@ sunxi_musb_match(device_t parent, cfdata static void sunxi_musb_attach(device_t parent, device_t self, void *aux) { - struct motg_softc * const sc = device_private(self); + struct sunxi_musb_softc * const msc = device_private(self); + struct motg_softc * const sc = &msc->sc_otg; struct fdt_attach_args * const faa = aux; const int phandle = faa->faa_phandle; struct fdtbus_reset *rst; @@ -156,13 +378,25 @@ sunxi_musb_attach(device_t parent, devic return; } + /* Create custom bus space tag for remapping registers */ + msc->sc_bs.bs_cookie = faa->faa_bst; + msc->sc_bs.bs_r_1 = sunxi_musb_bs_r_1; + msc->sc_bs.bs_r_2 = sunxi_musb_bs_r_2; + msc->sc_bs.bs_w_1 = sunxi_musb_bs_w_1; + msc->sc_bs.bs_w_2 = sunxi_musb_bs_w_2; + msc->sc_bs.bs_rm_1 = sunxi_musb_bs_rm_1; + msc->sc_bs.bs_rm_4 = sunxi_musb_bs_rm_4; + msc->sc_bs.bs_wm_1 = sunxi_musb_bs_wm_1; + msc->sc_bs.bs_wm_4 = sunxi_musb_bs_wm_4; + msc->sc_bs.bs_barrier = sunxi_musb_bs_barrier; + sc->sc_dev = self; sc->sc_bus.ub_hcpriv = sc; sc->sc_bus.ub_dmatag = faa->faa_dmat; strlcpy(sc->sc_vendor, "Allwinner", sizeof(sc->sc_vendor)); sc->sc_size = size; - sc->sc_iot = faa->faa_bst; - if (bus_space_map(sc->sc_iot, addr, size, 0, &sc->sc_ioh) != 0) { + sc->sc_iot = &msc->sc_bs; + if (bus_space_map(faa->faa_bst, addr, size, 0, &sc->sc_ioh) != 0) { aprint_error(": couldn't map registers\n"); return; } Index: src/sys/arch/evbarm/conf/SUNXI diff -u src/sys/arch/evbarm/conf/SUNXI:1.49 src/sys/arch/evbarm/conf/SUNXI:1.50 --- src/sys/arch/evbarm/conf/SUNXI:1.49 Sun Oct 29 15:00:00 2017 +++ src/sys/arch/evbarm/conf/SUNXI Sun Oct 29 16:02:46 2017 @@ -1,5 +1,5 @@ # -# $NetBSD: SUNXI,v 1.49 2017/10/29 15:00:00 jmcneill Exp $ +# $NetBSD: SUNXI,v 1.50 2017/10/29 16:02:46 jmcneill Exp $ # # Allwinner sunxi family # @@ -239,7 +239,6 @@ sunxiusbphy* at fdt? pass 9 # USB PHY ehci* at fdt? # EHCI ohci* at fdt? # OHCI motg* at fdt? # USB OTG -options MOTG_ALLWINNER # XXX this should be a driver flag usb* at ehci? usb* at ohci? usb* at motg?