Index: arch/arm64/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/arm64/conf/GENERIC,v retrieving revision 1.228 diff -u -p -r1.228 GENERIC --- arch/arm64/conf/GENERIC 31 Mar 2022 14:44:49 -0000 1.228 +++ arch/arm64/conf/GENERIC 21 May 2022 23:58:22 -0000 @@ -261,6 +261,8 @@ moxtet* at spi? mvsw* at fdt? mvtemp* at fdt? mvuart* at fdt? +mvehci* at fdt? +usb* at mvehci? sfp* at fdt? # Rockchip SoCs Index: dev/fdt/files.fdt =================================================================== RCS file: /cvs/src/sys/dev/fdt/files.fdt,v retrieving revision 1.162 diff -u -p -r1.162 files.fdt --- dev/fdt/files.fdt 30 Jan 2022 21:40:50 -0000 1.162 +++ dev/fdt/files.fdt 21 May 2022 23:58:22 -0000 @@ -474,6 +474,10 @@ device mvuart attach mvuart at fdt file dev/fdt/mvuart.c mvuart +device mvehci: usbus +attach mvehci at fdt +file dev/fdt/mvehci.c mvehci + device dwxe: ether, ifnet, mii, ifmedia attach dwxe at fdt file dev/fdt/if_dwxe.c dwxe Index: dev/fdt/mvehci.c =================================================================== RCS file: dev/fdt/mvehci.c diff -N dev/fdt/mvehci.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dev/fdt/mvehci.c 21 May 2022 23:58:22 -0000 @@ -0,0 +1,178 @@ +/* $OpenBSD$ */ + +/* + * Copyright (c) 2005, 2022 David Gwynne + * Copyright (c) 2017 Mark Kettenis + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define MVEHCI_HOST_OFFSET 0x0100 + +struct mvehci_softc { + struct ehci_softc sc; + int sc_node; + bus_space_handle_t sc_ioh; + void *sc_ih; +}; + +static int mvehci_match(struct device *, void *, void *); +static void mvehci_attach(struct device *, struct device *, void *); +static int mvehci_detach(struct device *, int); + +const struct cfattach mvehci_ca = { + sizeof(struct mvehci_softc), + mvehci_match, + mvehci_attach, + mvehci_detach, + ehci_activate +}; + +struct cfdriver mvehci_cd = { + NULL, "mvehci", DV_DULL +}; + +static int +mvehci_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + return OF_is_compatible(faa->fa_node, "marvell,armada-3700-ehci"); +} + +static void +mvehci_attach(struct device *parent, struct device *self, void *aux) +{ + struct mvehci_softc *sc = (struct mvehci_softc *)self; + struct fdt_attach_args *faa = aux; + char *devname = sc->sc.sc_bus.bdev.dv_xname; + usbd_status r; + uint32_t usbmode; + + if (faa->fa_nreg < 1) { + printf(": no registers\n"); + return; + } + + sc->sc_node = faa->fa_node; + sc->sc.iot = faa->fa_iot; + sc->sc.sc_bus.dmatag = faa->fa_dmat; + + if (bus_space_map(sc->sc.iot, faa->fa_reg[0].addr, + faa->fa_reg[0].size, 0, &sc->sc_ioh)) { + printf(": can't map registers\n"); + goto out; + } + + sc->sc.sc_size = faa->fa_reg[0].size - MVEHCI_HOST_OFFSET; + if (bus_space_subregion(sc->sc.iot, sc->sc_ioh, MVEHCI_HOST_OFFSET, + sc->sc.sc_size, &sc->sc.ioh)) { + printf(": cannot map mem space\n"); + goto unmap; + } + + pinctrl_byname(sc->sc_node, "default"); + + clock_enable_all(sc->sc_node); + reset_deassert_all(sc->sc_node); + + /* Disable interrupts, so we don't get any spurious ones. */ + sc->sc.sc_offs = EREAD1(&sc->sc, EHCI_CAPLENGTH); + EOWRITE2(&sc->sc, EHCI_USBINTR, 0); + + sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_USB, + ehci_intr, &sc->sc, devname); + if (sc->sc_ih == NULL) { + printf(": can't establish interrupt\n"); + clock_disable_all(sc->sc_node); + goto unmap; + } + + printf("\n"); + + /* force HOST mode */ + sc->sc.sc_flags = EHCIF_USBMODE; + + usbmode = EOREAD4(&sc->sc, EHCI_USBMODE); + CLR(usbmode, EHCI_USBMODE_CM_M); + SET(usbmode, EHCI_USBMODE_CM_HOST); + EOWRITE4(&sc->sc, EHCI_USBMODE, usbmode); + + strlcpy(sc->sc.sc_vendor, "Marvell", sizeof(sc->sc.sc_vendor)); + r = ehci_init(&sc->sc); + if (r != USBD_NORMAL_COMPLETION) { + printf("%s: init failed, error=%d\n", devname, r); + clock_disable_all(sc->sc_node); + goto disestablish_intr; + } + + /* Attach usb device. */ + config_found(self, &sc->sc.sc_bus, usbctlprint); + return; + +disestablish_intr: + fdt_intr_disestablish(sc->sc_ih); + sc->sc_ih = NULL; +unmap: + bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); + sc->sc.sc_size = 0; +out: + return; +} + +int +mvehci_detach(struct device *self, int flags) +{ + struct mvehci_softc *sc = (struct mvehci_softc *)self; + int rv; + + rv = ehci_detach(self, flags); + if (rv) + return rv; + + if (sc->sc_ih != NULL) { + fdt_intr_disestablish(sc->sc_ih); + sc->sc_ih = NULL; + } + + if (sc->sc.sc_size) { + bus_space_unmap(sc->sc.iot, sc->sc.ioh, sc->sc.sc_size); + sc->sc.sc_size = 0; + } + + clock_disable_all(sc->sc_node); + return 0; +}