From: Alice Guo <[email protected]> Extract USB PHY initialization code from ehci-mx6.c into a new function ehci_mx6_phy_init() that can be shared with the ChipIdea UDC driver.
Signed-off-by: Alice Guo <[email protected]> --- drivers/usb/host/ehci-mx6.c | 73 ++++++++++++++++++++++++++++++++++++++++++++- include/usb/ci_udc.h | 9 ++++++ 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 03ff4ce10d5..52f14e6eca0 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -12,6 +12,7 @@ #include <asm/global_data.h> #include <linux/compiler.h> #include <linux/delay.h> +#include <usb/ci_udc.h> #include <usb/ehci-ci.h> #include <asm/io.h> #include <asm/arch/imx-regs.h> @@ -168,6 +169,54 @@ static void __maybe_unused usb_power_config_mx7ulp(void *usbphy) { } #endif +#if defined(CONFIG_IMX8) +static void usb_power_config_imx8(void __iomem *usbphy_base) +{ + struct usbphy_regs __iomem *usbphy = (struct usbphy_regs __iomem *)usbphy_base; + + if (!is_imx8()) + return; + + int timeout = 1000000; + + if (!(readl(&usbphy->usb1_pll_480_ctrl) & PLL_USB_LOCK_MASK)) { + /* Enable the regulator first */ + writel(PLL_USB_REG_ENABLE_MASK, + &usbphy->usb1_pll_480_ctrl_set); + + /* Wait at least 25us */ + udelay(25); + + /* Enable the power */ + writel(PLL_USB_PWR_MASK, &usbphy->usb1_pll_480_ctrl_set); + + /* Wait lock */ + while (timeout--) { + if (readl(&usbphy->usb1_pll_480_ctrl) & + PLL_USB_LOCK_MASK) + break; + udelay(10); + } + + if (timeout <= 0) { + /* If timeout, we power down the pll */ + writel(PLL_USB_PWR_MASK, + &usbphy->usb1_pll_480_ctrl_clr); + return; + } + } + + /* Clear the bypass */ + writel(PLL_USB_BYPASS_MASK, &usbphy->usb1_pll_480_ctrl_clr); + + /* Enable the PLL clock out to USB */ + writel((PLL_USB_EN_USB_CLKS_MASK | PLL_USB_ENABLE_MASK), + &usbphy->usb1_pll_480_ctrl_set); +} +#else +static void __maybe_unused usb_power_config_imx8(void __iomem *usbphy_base) { } +#endif + #if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMXRT) || \ defined(CONFIG_IMX8ULP) static const ulong phy_bases[] = { @@ -276,7 +325,6 @@ static void ehci_mx6_powerup_fixup(struct ehci_ctrl *ctrl, uint32_t *status_reg, *reg = ehci_readl(status_reg); } -#if !defined(CONFIG_PHY) /* Should be done in the MXS PHY driver */ static void usb_oc_config(struct usbnc_regs *usbnc, int index) { @@ -298,7 +346,30 @@ static void usb_oc_config(struct usbnc_regs *usbnc, int index) clrbits_le32(ctrl, UCTRL_PWR_POL); #endif } + +void ehci_mx6_phy_init(struct usb_ehci *ehci, struct ehci_mx6_phy_data *phy_data, int index) +{ + u32 portsc; + + portsc = readl(&ehci->portsc); + if (portsc & PORT_PTS_PHCD) { + debug("suspended: portsc %x, enabled it.\n", portsc); + clrbits_le32(&ehci->portsc, PORT_PTS_PHCD); + } + + usb_power_config_mx6(phy_data->anatop_addr, index); + usb_power_config_mx7(phy_data->misc_addr); + usb_power_config_mx7ulp(phy_data->phy_addr); + usb_power_config_imx8(phy_data->phy_addr); + + usb_oc_config(phy_data->misc_addr, index); + +#if defined(CONFIG_MX6) || defined(CONFIG_MX7ULP) || defined(CONFIG_IMXRT) || \ + defined(CONFIG_IMX8) || defined(CONFIG_IMX8ULP) + usb_internal_phy_clock_gate(phy_data->phy_addr, 1); + usb_phy_enable(ehci, phy_data->phy_addr); #endif +} #if !CONFIG_IS_ENABLED(DM_USB) /** diff --git a/include/usb/ci_udc.h b/include/usb/ci_udc.h index 9f15dbabe53..ccef4daf741 100644 --- a/include/usb/ci_udc.h +++ b/include/usb/ci_udc.h @@ -6,7 +6,16 @@ #ifndef __CI_UDC_H__ #define __CI_UDC_H__ +#include <usb/ehci-ci.h> #define EP_MAX_PACKET_SIZE 0x200 #define EP0_MAX_PACKET_SIZE 64 + +struct ehci_mx6_phy_data { + void __iomem *phy_addr; + void __iomem *misc_addr; + void __iomem *anatop_addr; +}; + +void ehci_mx6_phy_init(struct usb_ehci *ehci, struct ehci_mx6_phy_data *phy_data, int index); #endif /* __CI_UDC_H__ */ -- 2.43.0

