From: daniel@caiaq.de (Daniel Mack)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/1] ehci-mxc: Fix mx31 OTG host initialisation
Date: Mon, 10 May 2010 20:35:09 +0200 [thread overview]
Message-ID: <20100510183509.GP30801@buzzloop.caiaq.de> (raw)
In-Reply-To: <1273515220-18909-2-git-send-email-philippe.retornaz@epfl.ch>
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@epfl.ch>
> ---
> 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
>
next prev parent reply other threads:[~2010-05-10 18:35 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-10 18:13 [PATCH 0/1] mx31: Fix usb otg host initialisation Philippe Rétornaz
2010-05-10 18:13 ` [PATCH 1/1] ehci-mxc: Fix mx31 OTG " Philippe Rétornaz
2010-05-10 18:35 ` Daniel Mack [this message]
2010-05-11 11:06 ` Philippe Rétornaz
2010-05-10 18:58 ` Nguyen Dinh-R00091
2010-05-11 9:11 ` Valentin Longchamp
2010-05-11 11:06 ` Philippe Rétornaz
2010-05-11 6:39 ` Sascha Hauer
2010-05-11 9:03 ` Valentin Longchamp
2010-05-11 11:05 ` Philippe Rétornaz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100510183509.GP30801@buzzloop.caiaq.de \
--to=daniel@caiaq.de \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.