X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;ds=sidebyside;f=drivers%2Fusb%2Fhost%2Fehci-mx6.c;h=602fec53948270676213b77a95736a32035151d8;hb=2f1eb66e2881a780e622e7fd50b3a497677fd373;hp=2666351391431e091a761fb92f7879777bde2625;hpb=f0c89d5463d9d27679ca66b5bb86c161da15a3f7;p=oweals%2Fu-boot.git diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index 2666351391..602fec5394 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -8,12 +8,14 @@ #include #include #include +#include #include -#include +#include #include #include #include #include +#include #include "ehci.h" @@ -48,7 +50,7 @@ #define USBNC_OFFSET 0x200 #define USBNC_PHYSTATUS_ID_DIG (1 << 4) /* otg_id status */ #define USBNC_PHYCFG2_ACAENB (1 << 4) /* otg_id detection enable */ -#define UCTRL_PM (1 << 9) /* OTG Power Mask */ +#define UCTRL_PWR_POL (1 << 9) /* OTG Polarity of Power Pin */ #define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ #define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ @@ -117,32 +119,6 @@ static void usb_power_config(int index) pll_480_ctrl_set); } -static int wait_for_bit(u32 *reg, const u32 mask, bool set) -{ - u32 val; - const unsigned int timeout = 10000; - unsigned long start = get_timer(0); - - while(1) { - val = readl(reg); - if (!set) - val = ~val; - - if ((val & mask) == mask) - return 0; - - if (get_timer(start) > timeout) - break; - - udelay(1); - } - - debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n", - __func__, reg, mask, set); - - return -ETIMEDOUT; -} - /* Return 0 : host node, <>0 : device mode */ static int usb_phy_enable(int index, struct usb_ehci *ehci) { @@ -160,12 +136,13 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci) /* Stop then Reset */ clrbits_le32(usb_cmd, UCMD_RUN_STOP); - ret = wait_for_bit(usb_cmd, UCMD_RUN_STOP, 0); + ret = wait_for_bit(__func__, usb_cmd, UCMD_RUN_STOP, false, 10000, + false); if (ret) return ret; setbits_le32(usb_cmd, UCMD_RESET); - ret = wait_for_bit(usb_cmd, UCMD_RESET, 0); + ret = wait_for_bit(__func__, usb_cmd, UCMD_RESET, false, 10000, false); if (ret) return ret; @@ -218,8 +195,9 @@ struct usbnc_regs { u32 reserve1[10]; u32 phy_cfg1; u32 phy_cfg2; + u32 reserve2; u32 phy_status; - u32 reserve2[4]; + u32 reserve3[4]; u32 adp_cfg1; u32 adp_cfg2; u32 adp_status; @@ -230,9 +208,20 @@ static void usb_power_config(int index) struct usbnc_regs *usbnc = (struct usbnc_regs *)(USB_BASE_ADDR + (0x10000 * index) + USBNC_OFFSET); void __iomem *phy_cfg2 = (void __iomem *)(&usbnc->phy_cfg2); + void __iomem *ctrl = (void __iomem *)(&usbnc->ctrl1); - /* Enable usb_otg_id detection */ - setbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB); + /* + * Clear the ACAENB to enable usb_otg_id detection, + * otherwise it is the ACA detection enabled. + */ + clrbits_le32(phy_cfg2, USBNC_PHYCFG2_ACAENB); + + /* Set power polarity to high active */ +#ifdef CONFIG_MXC_USB_OTG_HACTIVE + setbits_le32(ctrl, UCTRL_PWR_POL); +#else + clrbits_le32(ctrl, UCTRL_PWR_POL); +#endif } int usb_phy_mode(int port) @@ -270,15 +259,11 @@ static void usb_oc_config(int index) setbits_le32(ctrl, UCTRL_OVER_CUR_POL); #endif -#if defined(CONFIG_MX6) setbits_le32(ctrl, UCTRL_OVER_CUR_DIS); -#elif defined(CONFIG_MX7) - setbits_le32(ctrl, UCTRL_OVER_CUR_DIS | UCTRL_PM); -#endif } /** - * board_ehci_hcd_init - override usb phy mode + * board_usb_phy_mode - override usb phy mode * @port: usb host/otg port * * Target board specific, override usb_phy_mode. @@ -323,6 +308,30 @@ int __weak board_ehci_power(int port, int on) return 0; } +int ehci_mx6_common_init(struct usb_ehci *ehci, int index) +{ + int ret; + + enable_usboh3_clk(1); + mdelay(1); + + /* Do board specific initialization */ + ret = board_ehci_hcd_init(index); + if (ret) + return ret; + + usb_power_config(index); + usb_oc_config(index); + +#if defined(CONFIG_MX6) + usb_internal_phy_clock_gate(index, 1); + usb_phy_enable(index, ehci); +#endif + + return 0; +} + +#ifndef CONFIG_DM_USB int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { @@ -334,27 +343,22 @@ int ehci_hcd_init(int index, enum usb_init_type init, #endif struct usb_ehci *ehci = (struct usb_ehci *)(USB_BASE_ADDR + (controller_spacing * index)); + int ret; if (index > 3) return -EINVAL; - enable_usboh3_clk(1); - mdelay(1); - /* Do board specific initialization */ - board_ehci_hcd_init(index); - - usb_power_config(index); - usb_oc_config(index); + ret = ehci_mx6_common_init(ehci, index); + if (ret) + return ret; -#if defined(CONFIG_MX6) - usb_internal_phy_clock_gate(index, 1); - usb_phy_enable(index, ehci); -#endif type = board_usb_phy_mode(index); - *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); - *hcor = (struct ehci_hcor *)((uint32_t)*hccr + - HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + if (hccr && hcor) { + *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); + *hcor = (struct ehci_hcor *)((uint32_t)*hccr + + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + } if ((type == init) || (type == USB_INIT_DEVICE)) board_ehci_power(index, (type == USB_INIT_DEVICE) ? 0 : 1); @@ -376,3 +380,102 @@ int ehci_hcd_stop(int index) { return 0; } +#else +struct ehci_mx6_priv_data { + struct ehci_ctrl ctrl; + struct usb_ehci *ehci; + enum usb_init_type init_type; + int portnr; +}; + +static int mx6_init_after_reset(struct ehci_ctrl *dev) +{ + struct ehci_mx6_priv_data *priv = dev->priv; + enum usb_init_type type = priv->init_type; + struct usb_ehci *ehci = priv->ehci; + int ret; + + ret = ehci_mx6_common_init(priv->ehci, priv->portnr); + if (ret) + return ret; + + board_ehci_power(priv->portnr, (type == USB_INIT_DEVICE) ? 0 : 1); + + if (type == USB_INIT_DEVICE) + return 0; + + setbits_le32(&ehci->usbmode, CM_HOST); + writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); + setbits_le32(&ehci->portsc, USB_EN); + + mdelay(10); + + return 0; +} + +static const struct ehci_ops mx6_ehci_ops = { + .init_after_reset = mx6_init_after_reset +}; + +static int ehci_usb_probe(struct udevice *dev) +{ + struct usb_platdata *plat = dev_get_platdata(dev); + struct usb_ehci *ehci = (struct usb_ehci *)dev_get_addr(dev); + struct ehci_mx6_priv_data *priv = dev_get_priv(dev); + struct ehci_hccr *hccr; + struct ehci_hcor *hcor; + int ret; + + priv->ehci = ehci; + priv->portnr = dev->seq; + priv->init_type = plat->init_type; + + ret = ehci_mx6_common_init(ehci, priv->portnr); + if (ret) + return ret; + + board_ehci_power(priv->portnr, (priv->init_type == USB_INIT_DEVICE) ? 0 : 1); + + if (priv->init_type == USB_INIT_HOST) { + setbits_le32(&ehci->usbmode, CM_HOST); + writel(CONFIG_MXC_USB_PORTSC, &ehci->portsc); + setbits_le32(&ehci->portsc, USB_EN); + } + + mdelay(10); + + hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); + hcor = (struct ehci_hcor *)((uint32_t)hccr + + HC_LENGTH(ehci_readl(&(hccr)->cr_capbase))); + + return ehci_register(dev, hccr, hcor, &mx6_ehci_ops, 0, priv->init_type); +} + +static int ehci_usb_remove(struct udevice *dev) +{ + int ret; + + ret = ehci_deregister(dev); + if (ret) + return ret; + + return 0; +} + +static const struct udevice_id mx6_usb_ids[] = { + { .compatible = "fsl,imx27-usb" }, + { } +}; + +U_BOOT_DRIVER(usb_mx6) = { + .name = "ehci_mx6", + .id = UCLASS_USB, + .of_match = mx6_usb_ids, + .probe = ehci_usb_probe, + .remove = ehci_usb_remove, + .ops = &ehci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct ehci_mx6_priv_data), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; +#endif