PR 60404: Beaglebone Black: nonfunctional usb wifi

Brook Milligan <[email protected]> Thu, 9 Jul 2026 21:23:55 -0600
Newsgroups gmane.os.netbsd.current
Message-ID <[email protected]>
The attached patch (see below) fixes the non-functional USB controller =
on the Beaglebone Black.  With this patch, mass storage devices seem to =
work fine, and wifi devices are detected by both the run and urtwn =
drivers.

At the moment, this patch is really verbose, because I am reporting =
various bits along the way.  Thus, there are obvious cleanups to be =
made.

More importantly, however, I would very much appreciate feedback on how =
to improve the functional code parts.  For example, it seems that it =
should be possible to access some of the relevant contants from the =
device tree, but I am not seeing how that can be done.  The BBB memory =
map separates control registers from the main device registers, so the =
same mapped memory cannot be used for both, and the device tree seems =
not to have a way to extract the base address of the control module.  I =
may, however, be not understanding or there may be other ways to access =
these registers or to differentiate between the instances of the driver =
attachments.  All code improvements welcome.

Thank you very much for any feedback you can offer.

Cheers,
Brook

P.S. While mass storage devices seem to work fine with this patch, none =
of the wifi adapters do.  They still exhibit the problems reported in PR =
60404 [1].

[1] https://gnats.netbsd.org/cgi-bin/query-pr-single.pl?number=3D60404


Index: ti_motg.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
RCS file: /cvsroot/src/sys/arch/arm/ti/ti_motg.c,v
retrieving revision 1.5
diff -u -r1.5 ti_motg.c
--- ti_motg.c	2 Feb 2024 22:14:04 -0000	1.5
+++ ti_motg.c	10 Jul 2026 02:36:15 -0000
@@ -165,6 +165,79 @@
=20
 	aprint_normal_dev(self, "interrupting on %s\n", intrstr);
=20
+/*
+ * XXX - some of these constants should be read from the device tree
+ */
+
+/*
+ * control module
+ *
+ * see Spruh TRM Table 2-2. L4_WKUP Peripheral Memory Map, page 180 and
+ *     sys/external/gpl2/dts/dist/arch/arm/boot/dts/am33xx-l4.dtsi, =
line 281
+ *     segment@200000:target-module@10000
+ */
+#define CTRL_MODULE_BASE		0x44e10000
+
+/* see sys/external/gpl2/dts/dist/arch/arm/boot/dts/am33xx-l4.dtsi, =
line 327: usb_ctrl_mod:control@620 */
+#define USB_CTRL_MOD_PHY_CTRL_BASE	0x620
+#define USB_CTRL_MOD_PHY_CTRL_SIZE	0x10=20
+
+/*
+ * control register bits
+ * see Spruh TRM section 9.3.1.20, pages 1483-1484 and section =
9.3.1.22, pages 1486-1487
+ */
+#define USBPHY_CM_PWRDN			(1 << 0)
+#define USBPHY_OTG_PWRDN		(1 << 1)
+#define USBPHY_OTG_VDET_EN		(1 << 19)
+#define USBPHY_OTG_SESSENDEN		(1 << 20)
+
+/*
+ * names based on USB control registers
+ * see Spruh TRM Table 2-1, page 178
+ */
+#define USB0_BASE			"usb@47401000"
+#define USB1_BASE			"usb@47401800"
+
+	int usb_index =3D strcmp(faa->faa_name, USB0_BASE) =3D=3D 0 ? 0
+	  : strcmp(faa->faa_name, USB1_BASE) =3D=3D 0 ? 1
+	  : -1;
+	if (usb_index < 0) {
+		return;
+	}
+
+	aprint_normal("\n");
+	aprint_normal("=3D=3D=3D> ti_motg::attach(): %s (usb%d)\n", =
faa->faa_name, usb_index);
+
+	bus_space_handle_t handle;
+	bus_addr_t ctrl_base_addr =3D CTRL_MODULE_BASE + =
USB_CTRL_MOD_PHY_CTRL_BASE;	/* control registers base address */
+	bus_size_t ctrl_size =3D USB_CTRL_MOD_PHY_CTRL_SIZE;			=
	/* control registers size */
+	bus_size_t ctrl_offset =3D ctrl_base_addr + usb_index * 2 * =
sizeof(uint32_t);	/* control register offset */
+
+	if (bus_space_map(faa->faa_bst, ctrl_base_addr, ctrl_size, 0, =
&handle) !=3D 0) {
+		aprint_error(": couldn't map USB control registers\n");
+		return;
+	}
+
+	uint32_t usb_ctrl =3D bus_space_read_4(faa->faa_bst, handle, =
ctrl_offset - ctrl_base_addr);
+	aprint_normal("0x%08x: usb_ctrl%d: 0x%08x (upper 8 =
bits=3D0x3c)\n", (uint32_t)ctrl_offset, usb_index, usb_ctrl);
+	aprint_normal("    0: %x (0?)\n", (usb_ctrl & USBPHY_CM_PWRDN) =
!=3D 0);
+	aprint_normal("    1: %x (0?)\n", (usb_ctrl & USBPHY_OTG_PWRDN) =
!=3D 0);
+	aprint_normal("   19: %x (1?)\n", (usb_ctrl & =
USBPHY_OTG_VDET_EN) !=3D 0);
+	aprint_normal("   20: %x (1?)\n", (usb_ctrl & =
USBPHY_OTG_SESSENDEN) !=3D 0);
+
+	aprint_normal("=3D=3D=3D> ti_motg::attach(): writing =
usb_ctrl%d\n", usb_index);
+	usb_ctrl &=3D ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN);
+	usb_ctrl |=3D (USBPHY_OTG_VDET_EN | USBPHY_OTG_SESSENDEN);
+	bus_space_write_4(faa->faa_bst, handle, ctrl_offset - =
ctrl_base_addr, usb_ctrl);
+
+	usb_ctrl =3D bus_space_read_4(faa->faa_bst, handle, ctrl_offset =
- ctrl_base_addr);
+	aprint_normal("0x%08x: usb_ctrl%d: 0x%08x (upper 8 =
bits=3D0x3c)\n", (uint32_t)ctrl_offset, usb_index, usb_ctrl);
+	aprint_normal("    0: %x (0?)\n", (usb_ctrl & USBPHY_CM_PWRDN) =
!=3D 0);
+	aprint_normal("    1: %x (0?)\n", (usb_ctrl & USBPHY_OTG_PWRDN) =
!=3D 0);
+	aprint_normal("   19: %x (1?)\n", (usb_ctrl & =
USBPHY_OTG_VDET_EN) !=3D 0);
+	aprint_normal("   20: %x (1?)\n", (usb_ctrl & =
USBPHY_OTG_SESSENDEN) !=3D 0);
+	aprint_normal("\n");
+
 	sc->sc_motg.sc_iot =3D faa->faa_bst;
 	if (bus_space_map(sc->sc_motg.sc_iot, addr[0], size[0], 0,
 	    &sc->sc_motg.sc_ioh) !=3D 0) {