[rtems-libbsd commit] ehci_imx: Set/clear ENHOSTDISCONNECT in USB PHY.

Christian Mauderer christianm at rtems.org
Wed Apr 15 15:11:43 UTC 2020


Module:    rtems-libbsd
Branch:    master
Commit:    9dfb3bdef2dceae556e8079e744c317163ac0dcd
Changeset: http://git.rtems.org/rtems-libbsd/commit/?id=9dfb3bdef2dceae556e8079e744c317163ac0dcd

Author:    Christian Mauderer <christian.mauderer at embedded-brains.de>
Date:      Mon Feb 11 09:35:37 2019 +0100

ehci_imx: Set/clear ENHOSTDISCONNECT in USB PHY.

This is not a nice solution but it should work on all chips. As soon as
FreeBSD has a nice solution via the USB PHY driver, this should be
replaced.

Update #3869.

---

 freebsd/sys/dev/usb/controller/ehci_imx.c | 59 +++++++++++++++++++++++++++++++
 1 file changed, 59 insertions(+)

diff --git a/freebsd/sys/dev/usb/controller/ehci_imx.c b/freebsd/sys/dev/usb/controller/ehci_imx.c
index d158df1..544a63b 100644
--- a/freebsd/sys/dev/usb/controller/ehci_imx.c
+++ b/freebsd/sys/dev/usb/controller/ehci_imx.c
@@ -50,6 +50,9 @@ __FBSDID("$FreeBSD$");
 
 #include <dev/ofw/ofw_bus.h>
 #include <dev/ofw/ofw_bus_subr.h>
+#ifdef __rtems__
+#include <dev/fdt/fdt_common.h>
+#endif /* __rtems__ */
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -270,6 +273,9 @@ struct imx_ehci_softc {
 	device_t	dev;
 	struct resource	*ehci_mem_res;	/* EHCI core regs. */
 	struct resource	*ehci_irq_res;	/* EHCI core IRQ. */ 
+#ifdef __rtems__
+	void		*phy_regs;
+#endif /* __rtems__ */
 };
 
 static struct ofw_compat_data compat_data[] = {
@@ -380,6 +386,32 @@ imx_ehci_disable_oc(struct imx_ehci_softc *sc)
 	index = usbmprops[1];
 	imx_usbmisc_set_ctrl(usbmdev, index, USBNC_OVER_CUR_DIS);
 }
+#ifdef __rtems__
+#define BUS_SPACE_PHYSADDR(res, offs) \
+	((u_int)(rman_get_start(res)+(offs)))
+
+static uint16_t
+imx_ehci_get_port_speed_portsc(struct ehci_softc *sc, uint16_t index)
+{
+	uint32_t v;
+	struct imx_ehci_softc *isc = (struct imx_ehci_softc *)sc;
+
+	v = ehci_get_port_speed_portsc(sc, index);
+
+	/* Set/clear ENHOSTDISCONDETECT in USBPHY CTRL register */
+	/* FIXME: This is a very hacky method. It should be done by the phy
+	 * driver instead. */
+	volatile uint32_t *ctrl_set = isc->phy_regs + 0x34;
+	volatile uint32_t *ctrl_clr = isc->phy_regs + 0x38;
+	if (v == UPS_HIGH_SPEED) {
+		*ctrl_set = 0x2;
+	} else {
+		*ctrl_clr = 0x2;
+	}
+
+	return (v);
+}
+#endif /* __rtems__ */
 
 static int
 imx_ehci_attach(device_t dev)
@@ -474,6 +506,33 @@ imx_ehci_attach(device_t dev)
 	esc->sc_flags |= EHCI_SCFLG_NORESTERM | EHCI_SCFLG_TT;
 	esc->sc_vendor_post_reset = imx_ehci_post_reset;
 	esc->sc_vendor_get_port_speed = ehci_get_port_speed_portsc;
+#ifdef __rtems__
+	/*
+	 * FIXME: This is a big hack to get the PHY regs and set one bit during
+	 * changes of the port speed.
+	 */
+	sc->phy_regs = 0;
+	if (OF_hasprop(ofw_bus_get_node(sc->dev), "fsl,usbphy")) {
+		phandle_t *cells;
+		int len;
+		phandle_t phynode;
+
+		cells = NULL;
+		len = OF_getencprop_alloc_multi(ofw_bus_get_node(sc->dev),
+		    "fsl,usbphy", sizeof(*cells), (void **)&cells);
+		if (len > 0
+		    && (phynode = OF_node_from_xref(cells[0])) != -1 &&
+		    ofw_bus_node_is_compatible(phynode, "fsl,imx6ul-usbphy")) {
+			u_long base, size;
+			if (fdt_regsize(phynode, &base, &size) == 0) {
+				sc->phy_regs = (void*)base;
+				esc->sc_vendor_get_port_speed =
+				    imx_ehci_get_port_speed_portsc;
+			}
+		}
+		OF_prop_free(cells);
+	}
+#endif /* __rtems__ */
 
 	err = ehci_init(esc);
 	if (err != 0) {



More information about the vc mailing list