Index | Thread | Search

From:
James Hastings <moosetek4@gmail.com>
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

Download raw body.

Thread
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 <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  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 <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	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