On Mon, May 10, 2010 at 08:13:40PM +0200, Philippe Rétornaz wrote: > On mx31 the OTG host initialisation fail if you need to have > an ULPI transfert to initialize the PHY. > > In order to be able to communicate with the PHY a complete reset > of the usb host is needed. After the PHY initialization the host > usb configuration registers need to be rewritten to avoid a host > controller lockup. Given that things are wired up correctly on the board, yes. Many boards don't, as they copy-pasted the schematics which got it wrong. Anyway, if it helps you, it should go in. Some commenty below ... > Signed-off-by: Philippe Rétornaz <philippe.retornaz@xxxxxxx> > --- > drivers/usb/host/ehci-mxc.c | 68 +++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 68 insertions(+), 0 deletions(-) > > diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c > index 544ccfd..39d28da 100644 > --- a/drivers/usb/host/ehci-mxc.c > +++ b/drivers/usb/host/ehci-mxc.c > @@ -29,6 +29,11 @@ > #define PORTSC_OFFSET 0x184 > #define USBMODE_OFFSET 0x1a8 > #define USBMODE_CM_HOST 3 > +#define USBCMD_OFFSET 0x140 > +#define USBCMD_RS (1 << 0) > +#define USBCMD_RST (1 << 1) > +#define USBSTS_OFFSET 0x144 > +#define USBSTS_HCH (1 << 12) > > struct ehci_mxc_priv { > struct clk *usbclk, *ahbclk; > @@ -120,6 +125,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) > int irq, ret, temp; > struct ehci_mxc_priv *priv; > struct device *dev = &pdev->dev; > + int i; > > dev_info(&pdev->dev, "initializing i.MX USB Controller\n"); > > @@ -204,6 +210,51 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) > if (ret < 0) > goto err_init; > > + /* i.Mx31 OTG host has a bug, if you don't do a reset, then ULPI > + * transfert timeout. */ > + if (cpu_is_mx31() && pdev->id == 0) { > + /* Wait for the controller to go idle */ > + for (i = 0; i < 10000; i++) { > + if (readl(hcd->regs + USBSTS_OFFSET) & USBSTS_HCH) > + break; > + udelay(1); > + } Please use a #defined value rather than the 10000 magic. Also, use cpu_relax() instead of the udelay(1). > + if (i == 10000) { > + dev_err(dev, "Timeout while stopping USB controller\n"); > + goto err_init; > + } > + > + /* Stop the usb controller */ > + temp = readl(hcd->regs + USBCMD_OFFSET); > + writel(temp & (~USBCMD_RS), hcd->regs + USBCMD_OFFSET); > + > + for (i = 0; i < 10000; i++) { > + if (!(readl(hcd->regs + USBCMD_OFFSET) & USBCMD_RS)) > + break; > + udelay(1); > + } > + > + if (i == 10000) { > + dev_err(dev, "Timeout while stopping USB controller\n"); > + goto err_init; > + } This seems to be done all over the place. Wouldn't a static inline function simplify the code a lot here? Daniel > + /* Reset the usb controller */ > + temp = readl(hcd->regs + USBCMD_OFFSET); > + writel(temp | USBCMD_RST, hcd->regs + USBCMD_OFFSET); > + > + for (i = 0; i < 10000; i++) { > + if (!(readl(hcd->regs + USBCMD_OFFSET) & USBCMD_RST)) > + break; > + udelay(1); > + } > + > + if (i == 10000) { > + dev_err(dev, "Timeout while reseting USB controller\n"); > + goto err_init; > + } > + } > + > /* Initialize the transceiver */ > if (pdata->otg) { > pdata->otg->io_priv = hcd->regs + ULPI_VIEWPORT_OFFSET; > @@ -213,6 +264,23 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) > dev_err(dev, "unable to enable vbus on transceiver\n"); > } > > + /* i.Mx31 OTG host has a bug, if you do an ULPI transfert then the host > + * controller stay busy. Rewriting the register is enough to make it > + * working */ > + if (cpu_is_mx31() && pdev->id == 0) { > + /* set USBMODE to host mode */ > + temp = readl(hcd->regs + USBMODE_OFFSET); > + writel(temp | USBMODE_CM_HOST, hcd->regs + USBMODE_OFFSET); > + > + /* set up the PORTSCx register */ > + writel(pdata->portsc, hcd->regs + PORTSC_OFFSET); > + > + /* setup USBCONTROL. */ > + ret = mxc_initialize_usb_hw(pdev->id, pdata->flags); > + if (ret < 0) > + goto err_init; > + } > + > priv->hcd = hcd; > platform_set_drvdata(pdev, priv); > > -- > 1.6.3.3 > -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html