From: James Hastings Subject: support MediaTek xHCI USB controller To: moosetek4@gmail.com,kettenis@openbsd.org,tech@openbsd.org Date: Mon, 24 Mar 2025 01:25:39 -0400 Diff v2 with changes from kettenis@. ok? Index: sys/dev/fdt/mtxhci.c =================================================================== RCS file: sys/dev/fdt/mtxhci.c diff -N sys/dev/fdt/mtxhci.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ sys/dev/fdt/mtxhci.c 24 Mar 2025 01:53:18 -0000 @@ -0,0 +1,252 @@ +/* $OpenBSD$ */ +/* + * Copyright (c) 2025 James Hastings + * + * 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 + +#define MTXHCI_MAX_PORTS 4 + +/* registers */ +#define MTXHCI_RESET 0x00 +#define RESET_ASSERT (1 << 0) +#define MTXHCI_CFG_HOST 0x04 +#define MTXHCI_CFG_DEV 0x08 +#define MTXHCI_CFG_PCIE 0x0c +#define CFG_PWRDN (1 << 0) +#define MTXHCI_STA 0x10 +#define STA_USB3 (1 << 16) +#define STA_XHCI (1 << 11) +#define STA_SYS (1 << 10) +#define STA_REF (1 << 8) +#define STA_PLL (1 << 0) +#define MTXHCI_CAPS 0x24 +#define CAP_USB2_PORTS(x) (((x) >> 8) & 0x7) +#define CAP_USB3_PORTS(x) (((x) >> 0) & 0x7) +#define MTXHCI_USB3_PORT(x) 0x30 + (x) * 8 +#define MTXHCI_USB2_PORT(x) 0x50 + (x) * 8 +#define CFG_PORT_HOST (1 << 2) +#define CFG_PORT_PWRDN (1 << 1) +#define CFG_PORT_DISABLE (1 << 0) + +#define HREAD4(sc, reg) \ + bus_space_read_4((sc)->sc.iot, (sc)->sc_port_ioh, (reg)) +#define HWRITE4(sc, reg, val) \ + bus_space_write_4((sc)->sc.iot, (sc)->sc_port_ioh, (reg), (val)) + +struct mtxhci_softc { + struct xhci_softc sc; + int sc_node; + + bus_space_handle_t sc_port_ioh; + bus_size_t sc_port_ios; + int sc_port_node; + + int sc_ports_usb2; + int sc_ports_usb3; + + void *sc_ih; +}; + +int mtxhci_match(struct device *, void *, void *); +void mtxhci_attach(struct device *, struct device *, void *); + +const struct cfattach mtxhci_ca = { + sizeof(struct mtxhci_softc), mtxhci_match, mtxhci_attach +}; + +struct cfdriver mtxhci_cd = { + NULL, "mtxhci", DV_DULL +}; + +int mtxhci_host_init(struct mtxhci_softc *); + +int +mtxhci_match(struct device *parent, void *match, void *aux) +{ + struct fdt_attach_args *faa = aux; + + if (OF_is_compatible(faa->fa_node, "mediatek,mtk-xhci")) + return 1; + + return 0; +} + +void +mtxhci_attach(struct device *parent, struct device *self, void *aux) +{ + struct mtxhci_softc *sc = (struct mtxhci_softc *)self; + struct fdt_attach_args *faa = aux; + int error = 0, idx; + + idx = OF_getindex(faa->fa_node, "ippc", "reg-names"); + if (idx < 0 || idx >= faa->fa_nreg) { + printf(": no ippc registers\n"); + return; + } + + if (bus_space_map(faa->fa_iot, faa->fa_reg[idx].addr, + faa->fa_reg[idx].size, 0, &sc->sc_port_ioh)) { + printf(": can't map registers\n"); + return; + } + + sc->sc_port_node = faa->fa_node; + sc->sc_port_ios = faa->fa_reg[idx].size; + + idx = OF_getindex(faa->fa_node, "mac", "reg-names"); + if (idx < 0 || idx >= faa->fa_nreg) { + printf(": no mac registers\n"); + goto unmap_port; + } + + if (bus_space_map(faa->fa_iot, faa->fa_reg[idx].addr, + faa->fa_reg[idx].size, 0, &sc->sc.ioh)) { + printf(": can't map registers\n"); + goto unmap_port; + } + + sc->sc_node = faa->fa_node; + sc->sc.iot = faa->fa_iot; + sc->sc.sc_size = faa->fa_reg[idx].size; + sc->sc.sc_bus.dmatag = faa->fa_dmat; + + sc->sc_ih = fdt_intr_establish(sc->sc_node, IPL_USB, + xhci_intr, sc, sc->sc.sc_bus.bdev.dv_xname); + if (sc->sc_ih == NULL) { + printf(": can't establish interrupt\n"); + goto unmap; + } + + power_domain_enable(sc->sc_node); + reset_deassert_all(sc->sc_node); + clock_set_assigned(sc->sc_node); + clock_enable_all(sc->sc_node); + + if ((error = mtxhci_host_init(sc)) != 0) { + printf(": host init failed, error=%d\n", error); + goto disestablish_ret; + } + + strlcpy(sc->sc.sc_vendor, "MediaTek", sizeof(sc->sc.sc_vendor)); + if ((error = xhci_init(&sc->sc)) != 0) { + printf("%s: init failed, error=%d\n", + sc->sc.sc_bus.bdev.dv_xname, error); + goto disestablish_ret; + } + + config_found(self, &sc->sc.sc_bus, usbctlprint); + + xhci_config(&sc->sc); + + return; + +disestablish_ret: + fdt_intr_disestablish(sc->sc_ih); +unmap: + bus_space_unmap(faa->fa_iot, sc->sc.ioh, sc->sc.sc_size); +unmap_port: + bus_space_unmap(faa->fa_iot, sc->sc_port_ioh, sc->sc_port_ios); +} + +int +mtxhci_host_init(struct mtxhci_softc *sc) +{ + uint32_t mask, val; + int i, ntries; + + /* port capabilities */ + val = HREAD4(sc, MTXHCI_CAPS); + sc->sc_ports_usb3 = MIN(MTXHCI_MAX_PORTS, CAP_USB3_PORTS(val)); + sc->sc_ports_usb2 = MIN(MTXHCI_MAX_PORTS, CAP_USB2_PORTS(val)); + + if (sc->sc_ports_usb3 == 0 && sc->sc_ports_usb2 == 0) + return ENXIO; + + /* enable phys */ + phy_enable_idx(sc->sc_port_node, -1); + + /* reset */ + val = HREAD4(sc, MTXHCI_RESET); + val |= RESET_ASSERT; + HWRITE4(sc, MTXHCI_RESET, val); + delay(10); + val &= ~RESET_ASSERT; + HWRITE4(sc, MTXHCI_RESET, val); + delay(10); + + /* disable device mode */ + val = HREAD4(sc, MTXHCI_CFG_DEV); + val |= CFG_PWRDN; + HWRITE4(sc, MTXHCI_CFG_DEV, val); + + /* enable host mode */ + val = HREAD4(sc, MTXHCI_CFG_HOST); + val &= ~CFG_PWRDN; + HWRITE4(sc, MTXHCI_CFG_HOST, val); + + mask = (STA_XHCI | STA_PLL | STA_SYS | STA_REF); + if (sc->sc_ports_usb3) { + mask |= STA_USB3; + + /* disable PCIe mode */ + val = HREAD4(sc, MTXHCI_CFG_PCIE); + val |= CFG_PWRDN; + HWRITE4(sc, MTXHCI_CFG_PCIE, val); + } + + /* configure host ports */ + for (i = 0; i < sc->sc_ports_usb3; i++) { + val = HREAD4(sc, MTXHCI_USB3_PORT(i)); + val &= ~(CFG_PORT_DISABLE | CFG_PORT_PWRDN); + val |= CFG_PORT_HOST; + HWRITE4(sc, MTXHCI_USB3_PORT(i), val); + } + for (i = 0; i < sc->sc_ports_usb2; i++) { + val = HREAD4(sc, MTXHCI_USB2_PORT(i)); + val &= ~(CFG_PORT_DISABLE | CFG_PORT_PWRDN); + val |= CFG_PORT_HOST; + HWRITE4(sc, MTXHCI_USB2_PORT(i), val); + } + + for (ntries = 0; ntries < 100; ntries++) { + val = HREAD4(sc, MTXHCI_STA); + if ((val & mask) == mask) + break; + delay(50); + } + if (ntries == 100) + return ETIMEDOUT; + + return 0; +} Index: sys/dev/fdt/files.fdt =================================================================== RCS file: /cvs/src/sys/dev/fdt/files.fdt,v retrieving revision 1.206 diff -u -p -r1.206 files.fdt --- sys/dev/fdt/files.fdt 14 Feb 2025 03:11:05 -0000 1.206 +++ sys/dev/fdt/files.fdt 24 Mar 2025 01:53:18 -0000 @@ -344,6 +344,10 @@ device mtrng attach mtrng at fdt file dev/fdt/mtrng.c mtrng +device mtxhci: usbus +attach mtxhci at fdt +file dev/fdt/mtxhci.c mtxhci + device rkanxdp attach rkanxdp at fdt file dev/fdt/rkanxdp.c rkanxdp Index: share/man/man4/mtxhci.4 =================================================================== RCS file: share/man/man4/mtxhci.4 diff -N share/man/man4/mtxhci.4 --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ share/man/man4/mtxhci.4 24 Mar 2025 01:53:18 -0000 @@ -0,0 +1,49 @@ +.\" $OpenBSD$ +.\" +.\" Copyright (c) 2025 James Hastings +.\" +.\" 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. +.\" +.Dd $Mdocdate$ +.Dt MTXHCI 4 +.Os +.Sh NAME +.Nm mtxhci +.Nd MediaTek USB xHCI controller +.Sh SYNOPSIS +.Cd "mtxhci* at fdt?" +.Cd "usb* at mtxhci?" +.Sh DESCRIPTION +The +.Nm +driver controls the interface logic and supports +the USB eXtensible Host Controller Interface +integrated on MediaTek SoCs. +.Pp +It provides an interface to +.Xr usb 4 +devices and supports all USB 3.0, 2.0 and 1.x device speeds. +.Sh SEE ALSO +.Xr intro 4 , +.Xr usb 4 +.Sh HISTORY +The +.Nm +device driver first appeared in +.Ox 7.7 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An James Hastings Aq Mt hastings@openbsd.org . Index: share/man/man4/Makefile =================================================================== RCS file: /cvs/src/share/man/man4/Makefile,v retrieving revision 1.859 diff -u -p -r1.859 Makefile --- share/man/man4/Makefile 14 Feb 2025 03:15:06 -0000 1.859 +++ share/man/man4/Makefile 24 Mar 2025 01:53:18 -0000 @@ -59,7 +59,7 @@ MAN= aac.4 abcrtc.4 abl.4 ac97.4 acphy.4 mcprtc.4 mcx.4 midi.4 mii.4 mfi.4 mfii.4 mfokrtc.4 \ mlphy.4 moscom.4 mos.4 mpe.4 mpath.4 mpi.4 mpii.4 \ mpip.4 mpu.4 msk.4 mpw.4 msts.4 mtd.4 mtdphy.4 \ - mtintc.4 mtio.4 mtrng.4 mtw.4 mue.4 \ + mtintc.4 mtio.4 mtrng.4 mtw.4 mtxhci.4 mue.4 \ multicast.4 mvclock.4 mvdog.4 mvgicp.4 mvgpio.4 mvicu.4 mviic.4 \ mvkpcie.4 mvneta.4 mvpinctrl.4 mvpp.4 mvrng.4 mvrtc.4 mvspi.4 \ mvtemp.4 mvsw.4 mvuart.4 myx.4 \ Index: sys/arch/arm64/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/arm64/conf/GENERIC,v retrieving revision 1.292 diff -u -p -r1.292 GENERIC --- sys/arch/arm64/conf/GENERIC 14 Feb 2025 04:56:26 -0000 1.292 +++ sys/arch/arm64/conf/GENERIC 24 Mar 2025 01:53:18 -0000 @@ -275,6 +275,8 @@ hitemp* at fdt? # MediaTek SoCs mtintc* at fdt? mtrng* at fdt? +mtxhci* at fdt? +usb* at mtxhci? # Marvell SoCs mvclock* at fdt? early 1 Index: sys/arch/arm64/conf/RAMDISK =================================================================== RCS file: /cvs/src/sys/arch/arm64/conf/RAMDISK,v retrieving revision 1.221 diff -u -p -r1.221 RAMDISK --- sys/arch/arm64/conf/RAMDISK 14 Feb 2025 04:56:26 -0000 1.221 +++ sys/arch/arm64/conf/RAMDISK 24 Mar 2025 01:53:18 -0000 @@ -207,6 +207,8 @@ hireset* at fdt? early 1 # MediaTek SoCs mtintc* at fdt? mtrng* at fdt? +mtxhci* at fdt? +usb* at mtxhci? # Marvell SoCs mvclock* at fdt? early 1 Index: sys/arch/armv7/conf/GENERIC =================================================================== RCS file: /cvs/src/sys/arch/armv7/conf/GENERIC,v retrieving revision 1.144 diff -u -p -r1.144 GENERIC --- sys/arch/armv7/conf/GENERIC 14 Feb 2025 04:56:34 -0000 1.144 +++ sys/arch/armv7/conf/GENERIC 24 Mar 2025 01:53:19 -0000 @@ -187,6 +187,8 @@ usb* at dwctwo? # MediaTek SoCs mtintc* at fdt? mtrng* at fdt? +mtxhci* at fdt? +usb* at mtxhci? # Marvell SoC mvacc* at fdt? early 1 Index: sys/arch/armv7/conf/RAMDISK =================================================================== RCS file: /cvs/src/sys/arch/armv7/conf/RAMDISK,v retrieving revision 1.132 diff -u -p -r1.132 RAMDISK --- sys/arch/armv7/conf/RAMDISK 14 Feb 2025 04:56:34 -0000 1.132 +++ sys/arch/armv7/conf/RAMDISK 24 Mar 2025 01:53:19 -0000 @@ -173,6 +173,8 @@ usb* at dwctwo? # MediaTek SoCs mtintc* at fdt? mtrng* at fdt? +mtxhci* at fdt? +usb* at mtxhci? # Marvell SoC mvacc* at fdt? early 1