[PATCH 5/7] usb: ehci-omap: Use PHY system to manage phy resets

Adam Ford aford173 at gmail.com
Sun Feb 20 00:08:45 CET 2022


There are a few boards that use hard-coded GPIO definitions in
their respective defconfig files.  If the GPIO's are listed
in their device trees, the nop-phy can toggle the GPIO's,
so the EHCI driver does not need to know anything about the
GPIO's. Add functions for getting the phys and remove the GPIO
toggles since the phy will now do that.

Signed-off-by: Adam Ford <aford173 at gmail.com>
---
 drivers/usb/host/ehci-omap.c | 106 ++++++++++++++++++-----------------
 1 file changed, 56 insertions(+), 50 deletions(-)

diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index 5f79279fe2..765336a3c4 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -128,47 +128,25 @@ static void omap_ehci_soft_phy_reset(int port)
 }
 #endif
 
-#if defined(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO) || \
-	defined(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO) || \
-	defined(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO)
-/* controls PHY(s) reset signal(s) */
-static inline void omap_ehci_phy_reset(int on, int delay)
-{
-	/*
-	 * Refer ISSUE1:
-	 * Hold the PHY in RESET for enough time till
-	 * PHY is settled and ready
-	 */
-	if (delay && !on)
-		udelay(delay);
-#ifdef CONFIG_OMAP_EHCI_PHY1_RESET_GPIO
-	gpio_request(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, "USB PHY1 reset");
-	gpio_direction_output(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, !on);
-#endif
-#ifdef CONFIG_OMAP_EHCI_PHY2_RESET_GPIO
-	gpio_request(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, "USB PHY2 reset");
-	gpio_direction_output(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, !on);
-#endif
-#ifdef CONFIG_OMAP_EHCI_PHY3_RESET_GPIO
-	gpio_request(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, "USB PHY3 reset");
-	gpio_direction_output(CONFIG_OMAP_EHCI_PHY3_RESET_GPIO, !on);
-#endif
-
-	/* Hold the PHY in RESET for enough time till DIR is high */
-	/* Refer: ISSUE1 */
-	if (delay && on)
-		udelay(delay);
-}
-#else
-#define omap_ehci_phy_reset(on, delay)	do {} while (0)
+struct ehci_omap_priv_data {
+	struct ehci_ctrl ctrl;
+	struct omap_ehci *ehci;
+#ifdef CONFIG_DM_REGULATOR
+	struct udevice *vbus_supply;
 #endif
+	enum usb_init_type init_type;
+	int portnr;
+	struct phy phy[OMAP_HS_USB_PORTS];
+	int nports;
+};
 
 /*
  * Initialize the OMAP EHCI controller and PHY.
  * Based on "drivers/usb/host/ehci-omap.c" from Linux 3.1
  * See there for additional Copyrights.
  */
-static int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata)
+static int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata,
+			      struct udevice *dev)
 {
 	int ret;
 	unsigned int i, reg = 0, rev = 0;
@@ -179,8 +157,9 @@ static int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pda
 	if (ret < 0)
 		return ret;
 
-	/* Put the PHY in RESET */
-	omap_ehci_phy_reset(1, 10);
+	/* Hold the PHY in RESET for enough time till DIR is high */
+	/* Refer: ISSUE1 */
+	udelay(10);
 
 	ret = omap_uhh_reset();
 	if (ret < 0)
@@ -259,7 +238,12 @@ static int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pda
 		if (is_ehci_hsic_mode(usbhs_pdata->port_mode[i]))
 			omap_usbhs_hsic_init(i);
 
-	omap_ehci_phy_reset(0, 10);
+	/*
+	 * Refer ISSUE1:
+	 * Hold the PHY in RESET for enough time till
+	 * PHY is settled and ready
+	 */
+	udelay(10);
 
 	/*
 	 * An undocumented "feature" in the OMAP3 EHCI controller,
@@ -328,18 +312,6 @@ U_BOOT_DRIVER(usb_omaphs_host) = {
 	.flags	= DM_FLAG_ALLOC_PRIV_DMA,
 };
 
-struct ehci_omap_priv_data {
-	struct ehci_ctrl ctrl;
-	struct omap_ehci *ehci;
-#ifdef CONFIG_DM_REGULATOR
-	struct udevice *vbus_supply;
-#endif
-	enum usb_init_type init_type;
-	int portnr;
-	struct phy phy[OMAP_HS_USB_PORTS];
-	int nports;
-};
-
 static int ehci_usb_of_to_plat(struct udevice *dev)
 {
 	struct usb_plat *plat = dev_get_plat(dev);
@@ -349,6 +321,26 @@ static int ehci_usb_of_to_plat(struct udevice *dev)
 	return 0;
 }
 
+/*
+ * This driver references phys based on the USB port.  If
+ * the port is unused, the corresponding phy is listed as NULL
+ * which generic_phy_init_bulk treats as an error, so we need
+ * a custom one that tolerates empty phys
+ */
+static int omap_ehci_phy_get(struct udevice *dev)
+{
+	struct ehci_omap_priv_data *priv = dev_get_priv(dev);
+	int i, ret;
+
+	for (i = 0; i < OMAP_HS_USB_PORTS; i++) {
+		ret = generic_phy_get_by_index(dev, i, &priv->phy[i]);
+		if (ret && ret != -ENOENT)
+			return ret;
+	};
+
+	return 0;
+};
+
 static int omap_ehci_probe(struct udevice *dev)
 {
 	struct usb_plat *plat = dev_get_plat(dev);
@@ -364,7 +356,21 @@ static int omap_ehci_probe(struct udevice *dev)
 	hccr = (struct ehci_hccr *)&priv->ehci->hccapbase;
 	hcor = (struct ehci_hcor *)&priv->ehci->usbcmd;
 
-	ret = omap_ehci_hcd_init(0, &usbhs_bdata);
+	/* Identify Phys */
+	ret = omap_ehci_phy_get(dev);
+	if (ret) {
+		printf("Failed to get phys\n");
+		return ret;
+	}
+
+	/* Register the EHCI */
+	ret = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
+	if (ret) {
+		printf("Failed to register EHCI\n");
+		return ret;
+	}
+
+	ret = omap_ehci_hcd_init(0, &usbhs_bdata, dev);
 	if (ret)
 		return ret;
 
-- 
2.32.0



More information about the U-Boot mailing list