Index | Thread | Search

From:
James Hastings <moosetek4@gmail.com>
Subject:
support MediaTek xHCI USB controller
To:
moosetek4@gmail.com,tech@openbsd.org
Date:
Sat, 22 Mar 2025 16:17:49 -0400

Download raw body.

Thread
This driver configures the MediaTek xHCI controller and usb(4) bus.
It is able to activate the host ports internally, but the USB T-PHY is not yet
supported and no devices will be found during bus explore.

mtxhci0 at mainbus0, xHCI 0.96
usb0 at mtxhci0: USB revision 3.0
uhub0 at usb0 configuration 1 interface 0 "MediaTek xHCI root hub" rev 3.00/1.00 addr 1

For now, the PHYs can be pre-activated in firmware with a 'usb start' command.
Dmesg and sysctl hw below are obtained via netboot over USB.

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	21 Mar 2025 00:18:05 -0000
@@ -0,0 +1,253 @@
+/*	$OpenBSD$	*/
+/*
+ * Copyright (c) 2025 James Hastings <hastings@openbsd.org>
+ *
+ * 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 <sys/types.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <machine/bus.h>
+#include <machine/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_clock.h>
+#include <dev/ofw/ofw_misc.h>
+#include <dev/ofw/ofw_power.h>
+#include <dev/ofw/fdt.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+
+#include <dev/usb/xhcireg.h>
+#include <dev/usb/xhcivar.h>
+
+#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 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;
+
+	if (faa->fa_nreg < 2) {
+		printf(": no registers\n");
+		return;
+	}
+
+	idx = OF_getindex(faa->fa_node, "ippc", "reg-names");
+	if (idx < 0 || idx > faa->fa_nreg) {
+		printf(": no 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(sc->sc_node, "mac", "reg-names");
+	if (idx == -1)
+		idx = 0;
+
+	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, val & 0x7);
+	sc->sc_ports_usb2 = MIN(MTXHCI_MAX_PORTS, (val >> 8) & 0x7);
+
+	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	21 Mar 2025 00:18:05 -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	21 Mar 2025 00:18:05 -0000
@@ -0,0 +1,49 @@
+.\"	$OpenBSD$
+.\"
+.\" Copyright (c) 2025 James Hastings <hastings@openbsd.org>
+.\"
+.\" 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	21 Mar 2025 00:18:05 -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	21 Mar 2025 00:18:05 -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	21 Mar 2025 00:18:05 -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	21 Mar 2025 00:18:05 -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	21 Mar 2025 00:18:05 -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


OpenBSD 7.7-beta (GENERIC.MP) #1: Mon Mar 17 18:00:11 EDT 2025
    hastings@rpi4a.moose-tek.test:/usr/src/sys/arch/arm64/compile/GENERIC.MP
real mem  = 1071976448 (1022MB)
avail mem = 998187008 (951MB)
random: good seed from bootblocks
mainbus0 at root: Bananapi BPI-R64
psci0 at mainbus0: PSCI 1.1, SMCCC 1.4, SYSTEM_SUSPEND
efi0 at mainbus0: UEFI 2.10
efi0: Das U-Boot rev 0x20241000
smbios0 at efi0: SMBIOS 3.7.0
smbios0: vendor U-Boot version "2024.10-OpenWrt-r28427-6df0e3d02a" date 10/01/2024
smbios0: mediatek mt7622-bpi-r64
cpu0 at mainbus0 mpidr 0: ARM Cortex-A53 r0p4
cpu0: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu0: 256KB 64b/line 16-way L2 cache
cpu0: CRC32,SHA2,SHA1,AES+PMULL,ASID16
cpu1 at mainbus0 mpidr 1: ARM Cortex-A53 r0p4
cpu1: 32KB 64b/line 2-way L1 VIPT I-cache, 32KB 64b/line 4-way L1 D-cache
cpu1: 256KB 64b/line 16-way L2 cache
"ramoops" at mainbus0 not configured
"secmon" at mainbus0 not configured
apm0 at mainbus0
syscon0 at mainbus0: "infracfg"
syscon1 at mainbus0: "pericfg"
syscon2 at mainbus0: "power-controller"
ampintc0 at mainbus0 nirq 288, ncpu 4 ipi: 0, 1, 2: "interrupt-controller"
syscon3 at mainbus0: "clock-controller"
syscon4 at mainbus0: "pciecfg"
syscon5 at mainbus0: "clock-controller"
syscon6 at mainbus0: "pcie-mirror"
syscon7 at mainbus0: "wed"
syscon8 at mainbus0: "wed"
syscon9 at mainbus0: "sgmiisys"
"opp-table" at mainbus0 not configured
"dummy40m" at mainbus0 not configured
"oscillator" at mainbus0 not configured
"pmu" at mainbus0 not configured
agtimer0 at mainbus0: 12500 kHz
"pwrap" at mainbus0 not configured
"ir-receiver" at mainbus0 not configured
mtintc0 at mainbus0 nirq 256
"efuse" at mainbus0 not configured
"clock-controller" at mainbus0 not configured
"clock-controller" at mainbus0 not configured
mtrng0 at mainbus0
"pinctrl" at mainbus0 not configured
"watchdog" at mainbus0 not configured
"rtc" at mainbus0 not configured
"cci" at mainbus0 not configured
"adc" at mainbus0 not configured
com0 at mainbus0: ns16550a, 16 byte fifo
com0: console
"pwm" at mainbus0 not configured
"i2c" at mainbus0 not configured
"i2c" at mainbus0 not configured
"spi" at mainbus0 not configured
"thermal" at mainbus0 not configured
"serial" at mainbus0 not configured
"spi" at mainbus0 not configured
"ecc" at mainbus0 not configured
"mmc" at mainbus0 not configured
"mmc" at mainbus0 not configured
"wmac" at mainbus0 not configured
"clock-controller" at mainbus0 not configured
mtxhci0 at mainbus0, xHCI 0.96
usb0 at mtxhci0: USB revision 3.0
uhub0 at usb0 configuration 1 interface 0 "MediaTek xHCI root hub" rev 3.00/1.00 addr 1
"t-phy" at mainbus0 not configured
"clock-controller" at mainbus0 not configured
"pcie" at mainbus0 not configured
"pcie" at mainbus0 not configured
"clock-controller" at mainbus0 not configured
"dma-controller" at mainbus0 not configured
"ethernet" at mainbus0 not configured
gpiokeys0 at mainbus0: "factory", "wps"
gpioleds0 at mainbus0: "bpi-r64:pio:green", "bpi-r64:pio:red"
"regulator-1p8v" at mainbus0 not configured
"regulator-3p3v" at mainbus0 not configured
"regulator-5v" at mainbus0 not configured
ure0 at uhub0 port 1 configuration 1 interface 0 "Realtek USB 10/100/1000 LAN" rev 3.00/31.00 addr 2
ure0: RTL8153B (0x6010), address 00:05:1b:db:11:26
rgephy0 at ure0 phy 0: RTL8251, rev. 0
vscsi0 at root
scsibus0 at vscsi0: 256 targets
softraid0 at root
scsibus1 at softraid0: 256 targets
root device: ure0
nfs_boot: using interface ure0, with revarp & bootparams
nfs_boot: client_addr=192.168.3.94
nfs_boot: server_addr=192.168.3.1 hostname=r64
root on 192.168.3.1:/_nfs/_root-arm64
WARNING: CHECK AND RESET THE DATE!
swap on 192.168.3.1:/_nfs/swap
cpu0: clock not implemented

hw.machine=arm64
hw.model=ARM Cortex-A53 r0p4
hw.ncpu=2
hw.byteorder=1234
hw.pagesize=4096
hw.disknames=
hw.diskcount=0
hw.cpuspeed=0
hw.vendor=mediatek
hw.product=mt7622-bpi-r64
hw.physmem=1071976448
hw.usermem=1071972352
hw.ncpufound=2
hw.allowpowerdown=1
hw.smt=0
hw.ncpuonline=2
hw.power=1
hw.ucomnames=