Index: ehci_fdt.c =================================================================== RCS file: /cvs/src/sys/dev/fdt/ehci_fdt.c,v retrieving revision 1.4 diff -u -p -u -r1.4 ehci_fdt.c --- ehci_fdt.c 6 Aug 2018 10:52:30 -0000 1.4 +++ ehci_fdt.c 23 Feb 2019 17:25:57 -0000 @@ -254,6 +254,57 @@ ehci_init_phys(struct ehci_fdt_softc *sc #define SUNXI_AHB_INCR8 (1 << 10) #define SUNXI_AHB_INCR16 (1 << 11) +#define SUNXI_OTG_CTL 0x020 +#define SUNXI_ROUTE_MUSB (1 << 0) + +/* + * Allwinner V3s shares one USB port with MUSB OTG module and OHCI/EHCI. + * Different from other Allwinner SoCs, V3s has no dedicated port connected + * to host controller. And default port routing is to MUSB OTG. + * So this workaround is needed. + */ +void +sun4i_port_routing(struct ehci_fdt_softc *sc, uint32_t *cells) +{ + bus_space_tag_t iot; + bus_space_handle_t ioh; + int idx, len, node; + uint32_t *reg; + uint32_t val; + + node = OF_getnodebyphandle(cells[0]); + if (node == 0) + return; + + if (!OF_is_compatible(node, "allwinner,sun8i-v3s-usb-phy")) + return; + + idx = OF_getindex(node, "phy_ctrl", "reg-names"); + if (idx < 0) + return; + + len = OF_getproplen(node, "reg"); + if (len <= 0) + return; + + reg = malloc(len, M_TEMP, M_WAITOK); + OF_getpropintarray(node, "reg", reg, len); + + iot = sc->sc.iot; + if (bus_space_map(iot, reg[idx], reg[idx + 1], 0, &ioh)) { + free(reg, M_TEMP, len); + return; + } + + /* assign USB port to OHCI/EHCI */ + val = bus_space_read_4(iot, ioh, SUNXI_OTG_CTL); + val &= ~SUNXI_ROUTE_MUSB; + bus_space_write_4(iot, ioh, SUNXI_OTG_CTL, val); + + bus_space_unmap(iot, ioh, reg[idx + 1]); + free(reg, M_TEMP, len); +} + void sun4i_phy_init(struct ehci_fdt_softc *sc, uint32_t *cells) { @@ -278,6 +329,7 @@ sun4i_phy_init(struct ehci_fdt_softc *sc */ if (OF_is_compatible(node, "allwinner,sun8i-h3-usb-phy") || OF_is_compatible(node, "allwinner,sun8i-r40-usb-phy") || + OF_is_compatible(node, "allwinner,sun8i-v3s-usb-phy") || OF_is_compatible(node, "allwinner,sun50i-a64-usb-phy")) { val = bus_space_read_4(sc->sc.iot, sc->sc.ioh, 0x810); val &= ~(1 << 1); @@ -306,6 +358,8 @@ sun4i_phy_init(struct ehci_fdt_softc *sc vbus_supply = OF_getpropint(node, name, 0); if (vbus_supply) regulator_enable(vbus_supply); + + sun4i_port_routing(sc, cells); } void