Skip to content
Snippets Groups Projects
Commit 70dbff1f authored by Adam Ford's avatar Adam Ford Committed by Marek Vasut
Browse files

usb: ehci-omap: Use PHY system to manage phy resets


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: default avatarAdam Ford <aford173@gmail.com>
parent d11f995c
No related branches found
No related tags found
1 merge request!14Draft: Merge u-boot uplitft to mediatek branch
......@@ -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;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment