- OMAP EHCI updates
This commit is contained in:
commit
90de95f744
@ -123,17 +123,4 @@ struct omap_ehci {
|
||||
u32 insreg08; /* 0xb0 */
|
||||
};
|
||||
|
||||
#if !CONFIG_IS_ENABLED(DM_USB) || !CONFIG_IS_ENABLED(OF_CONTROL)
|
||||
/*
|
||||
* FIXME: forward declaration of this structs needed because omap got the
|
||||
* ehci implementation backwards. move out ehci_hcd_x from board files
|
||||
*/
|
||||
struct ehci_hccr;
|
||||
struct ehci_hcor;
|
||||
|
||||
int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata,
|
||||
struct ehci_hccr **hccr, struct ehci_hcor **hcor);
|
||||
int omap_ehci_hcd_stop(void);
|
||||
#endif
|
||||
|
||||
#endif /* _OMAP_COMMON_EHCI_H_ */
|
||||
|
@ -84,8 +84,6 @@ CONFIG_DM_SPI=y
|
||||
CONFIG_OMAP3_SPI=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_HAS_OMAP_EHCI_PHY1_RESET_GPIO=y
|
||||
CONFIG_OMAP_EHCI_PHY1_RESET_GPIO=57
|
||||
CONFIG_USB_MUSB_HOST=y
|
||||
CONFIG_USB_MUSB_AM35X=y
|
||||
CONFIG_BCH=y
|
||||
|
@ -90,8 +90,6 @@ CONFIG_OMAP3_SPI=y
|
||||
CONFIG_USB=y
|
||||
# CONFIG_SPL_DM_USB is not set
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_HAS_OMAP_EHCI_PHY1_RESET_GPIO=y
|
||||
CONFIG_OMAP_EHCI_PHY1_RESET_GPIO=4
|
||||
CONFIG_USB_MUSB_HOST=y
|
||||
CONFIG_USB_MUSB_OMAP2PLUS=y
|
||||
CONFIG_TWL4030_USB=y
|
||||
|
@ -89,8 +89,6 @@ CONFIG_OMAP3_SPI=y
|
||||
CONFIG_USB=y
|
||||
# CONFIG_SPL_DM_USB is not set
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_HAS_OMAP_EHCI_PHY1_RESET_GPIO=y
|
||||
CONFIG_OMAP_EHCI_PHY1_RESET_GPIO=147
|
||||
CONFIG_USB_OMAP3=y
|
||||
CONFIG_USB_MUSB_GADGET=y
|
||||
CONFIG_USB_MUSB_OMAP2PLUS=y
|
||||
|
@ -91,8 +91,6 @@ CONFIG_OMAP3_SPI=y
|
||||
CONFIG_USB=y
|
||||
# CONFIG_SPL_DM_USB is not set
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_HAS_OMAP_EHCI_PHY1_RESET_GPIO=y
|
||||
CONFIG_OMAP_EHCI_PHY1_RESET_GPIO=4
|
||||
CONFIG_USB_MUSB_HOST=y
|
||||
CONFIG_USB_MUSB_OMAP2PLUS=y
|
||||
CONFIG_TWL4030_USB=y
|
||||
|
@ -42,10 +42,6 @@ CONFIG_CONS_INDEX=3
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_HAS_OMAP_EHCI_PHY1_RESET_GPIO=y
|
||||
CONFIG_OMAP_EHCI_PHY1_RESET_GPIO=1
|
||||
CONFIG_HAS_OMAP_EHCI_PHY2_RESET_GPIO=y
|
||||
CONFIG_OMAP_EHCI_PHY2_RESET_GPIO=62
|
||||
CONFIG_USB_OMAP3=y
|
||||
CONFIG_USB_HOST_ETHER=y
|
||||
CONFIG_USB_ETHER_SMSC95XX=y
|
||||
|
@ -52,10 +52,6 @@ CONFIG_CONS_INDEX=3
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_HAS_OMAP_EHCI_PHY2_RESET_GPIO=y
|
||||
CONFIG_OMAP_EHCI_PHY2_RESET_GPIO=80
|
||||
CONFIG_HAS_OMAP_EHCI_PHY3_RESET_GPIO=y
|
||||
CONFIG_OMAP_EHCI_PHY3_RESET_GPIO=79
|
||||
CONFIG_USB_DWC3=y
|
||||
CONFIG_USB_DWC3_OMAP=y
|
||||
CONFIG_USB_DWC3_PHY_OMAP=y
|
||||
|
@ -28,7 +28,7 @@ static int nop_phy_reset(struct phy *phy)
|
||||
if (!dm_gpio_is_valid(&priv->reset_gpio))
|
||||
return 0;
|
||||
|
||||
return dm_gpio_set_value(&priv->reset_gpio, false);
|
||||
return dm_gpio_set_value(&priv->reset_gpio, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -44,7 +44,8 @@ static int nop_phy_init(struct phy *phy)
|
||||
}
|
||||
|
||||
#if CONFIG_IS_ENABLED(DM_GPIO)
|
||||
ret = nop_phy_reset(phy);
|
||||
/* Take phy out of reset */
|
||||
ret = dm_gpio_set_value(&priv->reset_gpio, false);
|
||||
if (ret) {
|
||||
if (CONFIG_IS_ENABLED(CLK))
|
||||
clk_disable_bulk(&priv->bulk);
|
||||
|
@ -191,45 +191,13 @@ config USB_EHCI_MXS
|
||||
config USB_EHCI_OMAP
|
||||
bool "Support for OMAP3+ on-chip EHCI USB controller"
|
||||
depends on ARCH_OMAP2PLUS
|
||||
select PHY
|
||||
imply NOP_PHY
|
||||
default y
|
||||
---help---
|
||||
Enables support for the on-chip EHCI controller on OMAP3 and later
|
||||
SoCs.
|
||||
|
||||
if USB_EHCI_OMAP
|
||||
|
||||
config HAS_OMAP_EHCI_PHY1_RESET_GPIO
|
||||
bool "PHY #1 requires a GPIO hold to it in RESET while PHY settles"
|
||||
help
|
||||
Enable this to be able to configure the GPIO number used to hold the
|
||||
PHY in RESET for enough time until the PHY is settled and ready.
|
||||
|
||||
config OMAP_EHCI_PHY1_RESET_GPIO
|
||||
int "GPIO number to hold PHY #1 in RESET"
|
||||
depends on HAS_OMAP_EHCI_PHY1_RESET_GPIO
|
||||
|
||||
config HAS_OMAP_EHCI_PHY2_RESET_GPIO
|
||||
bool "PHY #2 requires a GPIO hold to it in RESET while PHY settles"
|
||||
help
|
||||
Enable this to be able to configure the GPIO number used to hold the
|
||||
PHY in RESET for enough time until the PHY is settled and ready.
|
||||
|
||||
config OMAP_EHCI_PHY2_RESET_GPIO
|
||||
int "GPIO number to hold PHY #2 in RESET"
|
||||
depends on HAS_OMAP_EHCI_PHY2_RESET_GPIO
|
||||
|
||||
config HAS_OMAP_EHCI_PHY3_RESET_GPIO
|
||||
bool "PHY #3 requires a GPIO hold to it in RESET while PHY settles"
|
||||
help
|
||||
Enable this to be able to configure the GPIO number used to hold the
|
||||
PHY in RESET for enough time until the PHY is settled and ready.
|
||||
|
||||
config OMAP_EHCI_PHY3_RESET_GPIO
|
||||
int "GPIO number to hold PHY #3 in RESET"
|
||||
depends on HAS_OMAP_EHCI_PHY3_RESET_GPIO
|
||||
|
||||
endif
|
||||
|
||||
config USB_EHCI_VF
|
||||
bool "Support for Vybrid on-chip EHCI USB controller"
|
||||
depends on ARCH_VF610
|
||||
|
@ -128,62 +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);
|
||||
struct ehci_omap_priv_data {
|
||||
struct ehci_ctrl ctrl;
|
||||
struct omap_ehci *ehci;
|
||||
#ifdef CONFIG_DM_REGULATOR
|
||||
struct udevice *vbus_supply;
|
||||
#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)
|
||||
#endif
|
||||
|
||||
/* Reset is needed otherwise the kernel-driver will throw an error. */
|
||||
int omap_ehci_hcd_stop(void)
|
||||
{
|
||||
debug("Resetting OMAP EHCI\n");
|
||||
omap_ehci_phy_reset(1, 0);
|
||||
|
||||
if (omap_uhh_reset() < 0)
|
||||
return -1;
|
||||
|
||||
if (omap_ehci_tll_reset() < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
@ -194,8 +157,9 @@ int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata)
|
||||
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)
|
||||
@ -274,7 +238,12 @@ int omap_ehci_hcd_init(int index, struct omap_usbhs_board_data *usbhs_pdata)
|
||||
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,
|
||||
@ -327,7 +296,7 @@ static int omap_usbhs_probe(struct udevice *dev)
|
||||
omap_usbhs_set_mode(i, mode);
|
||||
}
|
||||
|
||||
return omap_ehci_hcd_init(0, &usbhs_bdata);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct udevice_id omap_usbhs_dt_ids[] = {
|
||||
@ -343,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);
|
||||
@ -364,12 +321,33 @@ 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);
|
||||
struct ehci_omap_priv_data *priv = dev_get_priv(dev);
|
||||
struct ehci_hccr *hccr;
|
||||
struct ehci_hcor *hcor;
|
||||
int ret;
|
||||
|
||||
priv->ehci = dev_read_addr_ptr(dev);
|
||||
priv->portnr = dev_seq(dev);
|
||||
@ -378,6 +356,24 @@ static int omap_ehci_probe(struct udevice *dev)
|
||||
hccr = (struct ehci_hccr *)&priv->ehci->hccapbase;
|
||||
hcor = (struct ehci_hcor *)&priv->ehci->usbcmd;
|
||||
|
||||
/* 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;
|
||||
|
||||
return ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user