- OMAP EHCI updates
This commit is contained in:
Tom Rini 2022-02-23 13:34:14 -05:00
commit 90de95f744
10 changed files with 66 additions and 130 deletions

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);
}