diff options
-rw-r--r-- | drivers/usb/host/ehci-omap.c | 106 |
1 files changed, 56 insertions, 50 deletions
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 5f79279fe2f..765336a3c42 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; |