}
#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;
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)
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,
.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);
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);
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;