From: s.hauer@pengutronix.de (Sascha Hauer)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCHv7 2.6.34-rc5 4/5] mxc: Add generic USB HW initialization for MX51
Date: Thu, 22 Apr 2010 16:45:43 +0200 [thread overview]
Message-ID: <20100422144543.GU7882@pengutronix.de> (raw)
In-Reply-To: <1271862795-7986-4-git-send-email-Dinh.Nguyen@freescale.com>
On Wed, Apr 21, 2010 at 10:13:14AM -0500, Dinh.Nguyen at freescale.com wrote:
> From: Dinh Nguyen <Dinh.Nguyen@freescale.com>
>
> This patch adds USB HW initializiation code to /plat-mxc/ehci.c.
> -Stops and resets USB HW
> -Sets some specific PHY settings
> -Stop and restart the USB HW.
> Renames mxc_set_usbcontrol to mxc_initialize_usb_hw.
> The placing of the mxc_initialize_usb_hw needs to be before setting
> the USBMODE register to host, since a reset and restart is done in
> mxc_initialize_usb_hw.
> Adds new register bit defines for the USB HW on Freescale
> SoCs.
>
> This patch applies to 2.6.34-rc5.
>
> Signed-off-by: Dinh Nguyen <Dinh.Nguyen@freescale.com>
> Reviewed-by: Daniel Mack <daniel@caiaq.de>
> ---
> arch/arm/plat-mxc/ehci.c | 149 ++++++++++++++++++++++++++++-
> arch/arm/plat-mxc/include/mach/mxc_ehci.h | 58 +++++++++++-
> drivers/usb/host/ehci-mxc.c | 10 +-
> 3 files changed, 209 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c
> index cb0b638..b52335d 100644
> --- a/arch/arm/plat-mxc/ehci.c
> +++ b/arch/arm/plat-mxc/ehci.c
> @@ -1,5 +1,6 @@
> /*
> * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
> + * Copyright (C) 2010 Freescale Semiconductor, Inc.
> *
> * This program is free software; you can redistribute it and/or modify it
> * under the terms of the GNU General Public License as published by the
> @@ -18,6 +19,7 @@
>
> #include <linux/platform_device.h>
> #include <linux/io.h>
> +#include <linux/delay.h>
>
> #include <mach/hardware.h>
> #include <mach/mxc_ehci.h>
> @@ -50,7 +52,29 @@
> #define MX35_H1_TLL_BIT (1 << 5)
> #define MX35_H1_USBTE_BIT (1 << 4)
>
> -int mxc_set_usbcontrol(int port, unsigned int flags)
> +/* This function is a version of David Brownell's handshake function in
> + * ehci-hcd.c. This function uses cpu_relax instead of udelay().
> + *
> + * @addr: Address of register
> + * @mask: bits to look at in result of read
> + * @done: value of those bits when handshake succeeds
> + * @timeout: timeout in count
> + *
> + * This function waits for certain bits in the HW to stick before moving
> + * on and provides a timeout in the case where those bits do not stick.
> + */
> +static inline int hw_handshake(u32 addr, u32 mask, int done, int timeout)
> +{
> + while (--timeout && ((__raw_readl(addr) & mask) != done))
> + cpu_relax();
> +
> + if (timeout)
> + return 0;
> + else
> + return -ETIMEDOUT;
> +}
> +
> +int mxc_initialize_usb_hw(int port, unsigned int flags)
> {
> unsigned int v;
> #ifdef CONFIG_ARCH_MX3
> @@ -186,9 +210,130 @@ int mxc_set_usbcontrol(int port, unsigned int flags)
> return 0;
> }
> #endif /* CONFIG_MACH_MX27 */
> +#ifdef CONFIG_ARCH_MX51
> + if (cpu_is_mx51()) {
> + void __iomem *usb_base;
> + u32 usbotg_base;
> + u32 usbother_base;
> + int ret = 0;
> +
> + usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
> +
> + switch (port) {
> + case 0: /* OTG port */
> + usbotg_base = usb_base + USBOTG_OFFSET;
> + break;
> + case 1: /* Host 1 port */
> + usbotg_base = usb_base + USBH1_OFFSET;
> + break;
> + default:
> + printk(KERN_ERR"%s no such port %d\n", __func__, port);
> + ret = -ENOENT;
> + goto error;
> + }
> + usbother_base = usb_base + USBOTHER_REGS_OFFSET;
> +
> + /* Stop then Reset */
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + v &= ~UCMD_RUN_STOP;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + ret = hw_handshake(usbotg_base + USBCMD_OFFSET, UCMD_RUN_STOP, 0, 500);
> + if (ret) {
> + printk(KERN_ERR "%s could not stop usb hardware\n", __func__);
> + goto error;
> + }
> +
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + v |= UCMD_RESET;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + ret = hw_handshake(usbotg_base + USBCMD_OFFSET, UCMD_RESET, 0, 500);
> + if (ret) {
> + printk(KERN_ERR "%s could not reset usb hardware\n", __func__);
> + goto error;
> + }
> +
> + switch (port) {
> + case 0: /*OTG port */
> + if (flags & MXC_EHCI_INTERNAL_PHY) {
> + v = __raw_readl(usbother_base + USB_PHY_CTR_FUNC_OFFSET);
> +
> + if (flags & MXC_EHCI_POWER_PINS_ENABLED)
> + v |= (USB_UTMI_PHYCTRL_OC_DIS | UCTRL_OPM); /* OC/USBPWR is not used */
> + else
> + v &= ~(USB_UTMI_PHYCTRL_OC_DIS | UCTRL_OPM); /* OC/USBPWR is used */
> + __raw_writel(v, usbother_base + USB_PHY_CTR_FUNC_OFFSET);
> +
> + v = __raw_readl(usbother_base + USBCTRL_OFFSET);
> + if (flags & MXC_EHCI_WAKEUP_ENABLED)
> + v |= UCTRL_OWIE;/* OTG wakeup enable */
> + else
> + v &= ~UCTRL_OWIE;/* OTG wakeup disable */
> + __raw_writel(v, usbother_base + USBCTRL_OFFSET);
> + }
> + break;
> + case 1: /* Host 1 */
> + /*Host ULPI */
> + v = __raw_readl(usbother_base + USBCTRL_OFFSET);
> + if (flags & MXC_EHCI_WAKEUP_ENABLED)
> + v &= ~(UCTRL_H1WIE | UCTRL_H1UIE);/* HOST1 wakeup/ULPI intr disable */
> + else
> + v &= ~(UCTRL_H1WIE | UCTRL_H1UIE);/* HOST1 wakeup/ULPI intr disable */
> +
> + if (flags & MXC_EHCI_POWER_PINS_ENABLED)
> + v &= ~UCTRL_H1PM; /* HOST1 power mask used*/
> + else
> + v |= UCTRL_H1PM; /* HOST1 power mask used*/
> + __raw_writel(v, usbother_base + USBCTRL_OFFSET);
> +
> + v = __raw_readl(usbother_base + USB_PHY_CTR_FUNC_OFFSET);
> + if (flags & MXC_EHCI_POWER_PINS_ENABLED)
> + v &= ~USB_UH1_OC_DIS; /* OC is used */
> + else
> + v |= USB_UH1_OC_DIS; /* OC is not used */
> + __raw_writel(v, usbother_base + USB_PHY_CTR_FUNC_OFFSET);
> +
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
> + /* Interrupt Threshold Control:Immediate (no threshold) */
> + v &= UCMD_ITC_NO_THRESHOLD;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + break;
> + }
> +
> + /* need to reset the controller here so that the ID pin
> + * is correctly detected.
> + */
> + /* Stop then Reset */
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + v &= ~UCMD_RUN_STOP;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + ret = hw_handshake(usbotg_base + USBCMD_OFFSET, UCMD_RUN_STOP, 0, 500);
> + if (ret) {
> + printk(KERN_ERR "%s could not stop usb hardware\n", __func__);
> + goto error;
> + }
> +
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + v |= UCMD_RESET;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + ret = hw_handshake(usbotg_base + USBCMD_OFFSET, UCMD_RESET, 0, 500);
> + if (ret) {
> + printk(KERN_ERR "%s could not reset usb hardware\n", __func__);
> + goto error;
> + }
> +
> + /* allow controller to reset, and leave time for
> + * the ULPI transceiver to reset too.
> + */
> + msleep(100);
> +error:
> + iounmap(usb_base);
> + return ret;
> + }
> +#endif
> printk(KERN_WARNING
> "%s() unable to setup USBCONTROL for this CPU\n", __func__);
> return -EINVAL;
> }
> -EXPORT_SYMBOL(mxc_set_usbcontrol);
> +EXPORT_SYMBOL(mxc_initialize_usb_hw);
>
> diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
> index 4b9b836..0ec88bb 100644
> --- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h
> +++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
> @@ -1,6 +1,30 @@
> #ifndef __INCLUDE_ASM_ARCH_MXC_EHCI_H
> #define __INCLUDE_ASM_ARCH_MXC_EHCI_H
>
> +#define USBOTG_OFFSET 0
> +#define USBH1_OFFSET 0x200
> +#define USBH2_OFFSET 0x400
> +#define USBH3_OFFSET 0x600
> +#define USBOTHER_REGS_OFFSET 0x800
> +
> +#define USBCMD_OFFSET 0x140
> +
> +#define ULPI_VIEWPORT_OFFSET 0x170
> +#define PORTSC_OFFSET 0x184
> +#define USBMODE_OFFSET 0x1a8
> +#define USBMODE_CM_HOST 3
> +
> +#define USBCTRL_OFFSET 0
> +#define USB_PHY_CTR_FUNC_OFFSET 0x8
> +#define USB_PHY_CTR_FUNC2_OFFSET 0xc
> +#define USB_CTRL_1_OFFSET 0x10
> +
> +
> +/* USBCMD */
> +#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */
> +#define UCMD_RESET (1 << 1) /* controller reset */
> +#define UCMD_ITC_NO_THRESHOLD (~(0xff << 16)) /* Interrupt Threshold Control */
> +
> /* values for portsc field */
> #define MXC_EHCI_PHY_LOW_POWER_SUSPEND (1 << 23)
> #define MXC_EHCI_FORCE_FS (1 << 24)
> @@ -25,6 +49,38 @@
> #define MXC_EHCI_INTERNAL_PHY (1 << 7)
> #define MXC_EHCI_IPPUE_DOWN (1 << 8)
> #define MXC_EHCI_IPPUE_UP (1 << 9)
> +#define MXC_EHCI_WAKEUP_ENABLED (1 << 10)
> +#define MXC_EHCI_ITC_NO_THRESHOLD (1 << 11)
> +
> +/* USB_CTRL */
> +#define UCTRL_OUIE (1 << 28) /* OTG ULPI intr enable */
> +#define UCTRL_OWIE (1 << 27) /* OTG wakeup intr enable */
> +#define UCTRL_OBPVAL_RXDP (1 << 26) /* OTG RxDp status in bypass mode */
> +#define UCTRL_OBPVAL_RXDM (1 << 25) /* OTG RxDm status in bypass mode */
> +#define UCTRL_OPM (1 << 24) /* OTG power mask */
> +#define UCTRL_H1UIE (1 << 12) /* Host1 ULPI interrupt enable */
> +#define UCTRL_H1WIE (1 << 11) /* HOST1 wakeup intr enable */
> +#define UCTRL_H1PM (1 << 8) /* HOST1 power mask */
> +
> +/* USB_PHY_CTRL_FUNC */
> +#define USB_UTMI_PHYCTRL_OC_DIS (1 << 8) /* OTG Disable Overcurrent Event */
> +#define USB_UH1_OC_DIS (1 << 5) /* UH1 Disable Overcurrent Event */
> +
> +/* USB_CTRL_1 */
> +#define USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
> +#define USB_CTRL_UH2_EXT_CLK_EN (1 << 26)
> +
> +/* USB_PHY_CTRL_FUNC2*/
> +#define USB_UTMI_PHYCTRL2_PLLDIV_MASK 0x3
> +#define USB_UTMI_PHYCTRL2_PLLDIV_SHIFT 0
> +#define USB_UTMI_PHYCTRL2_HSDEVSEL_MASK 0x3
> +#define USB_UTMI_PHYCTRL2_HSDEVSEL_SHIFT 19
> +
> +#ifdef CONFIG_ARCH_MX51
> +#define USB_PLLDIV_12_MHZ 0x00
> +#define USB_PLL_DIV_19_2_MHZ 0x01
> +#define USB_PLL_DIV_24_MHZ 0x02
> +#endif
Please have a general look over these defines. All defines in
include/mach should at least have a MXC_ prefix. Most of these are
i.MX51 specific and thus should have a MX51_ prefix.
I think many of these do not have to be here anyway since they are
already in drivers/usb/host/ehci-mxc.c, are unused, or are only used
in plat-mxc/ehci.c.
> @@ -191,6 +191,11 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
> clk_enable(priv->ahbclk);
> }
>
> + /* setup specific usb hw */
> + ret = mxc_initialize_usb_hw(pdev->id, pdata->flags);
> + if (ret < 0)
> + goto err_init;
> +
> /* set USBMODE to host mode */
> temp = readl(hcd->regs + USBMODE_OFFSET);
> writel(temp | USBMODE_CM_HOST, hcd->regs + USBMODE_OFFSET);
> @@ -199,11 +204,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
> writel(pdata->portsc, hcd->regs + PORTSC_OFFSET);
> mdelay(10);
>
> - /* setup USBCONTROL. */
> - ret = mxc_set_usbcontrol(pdev->id, pdata->flags);
> - if (ret < 0)
> - goto err_init;
Has somebody tested if this works on other i.MXs? I remember it was quite
difficult to get the correct order of initialization. I don't want to
break this.
We should at least make a seperate patch from it so that anybody
bisecting this only finds this change and not the i.MX51 support also
added in this patch.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
WARNING: multiple messages have this Message-ID (diff)
From: Sascha Hauer <s.hauer@pengutronix.de>
To: Dinh.Nguyen@freescale.com
Cc: linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, linux@arm.linux.org.uk,
valentin.longchamp@epfl.ch, daniel@caiaq.de,
grant.likely@secretlab.ca, bryan.wu@canonical.com,
amit.kucheria@canonical.com, Jun.Li@freescale.com,
xiao-lizhang@freescale.com
Subject: Re: [PATCHv7 2.6.34-rc5 4/5] mxc: Add generic USB HW initialization for MX51
Date: Thu, 22 Apr 2010 16:45:43 +0200 [thread overview]
Message-ID: <20100422144543.GU7882@pengutronix.de> (raw)
In-Reply-To: <1271862795-7986-4-git-send-email-Dinh.Nguyen@freescale.com>
On Wed, Apr 21, 2010 at 10:13:14AM -0500, Dinh.Nguyen@freescale.com wrote:
> From: Dinh Nguyen <Dinh.Nguyen@freescale.com>
>
> This patch adds USB HW initializiation code to /plat-mxc/ehci.c.
> -Stops and resets USB HW
> -Sets some specific PHY settings
> -Stop and restart the USB HW.
> Renames mxc_set_usbcontrol to mxc_initialize_usb_hw.
> The placing of the mxc_initialize_usb_hw needs to be before setting
> the USBMODE register to host, since a reset and restart is done in
> mxc_initialize_usb_hw.
> Adds new register bit defines for the USB HW on Freescale
> SoCs.
>
> This patch applies to 2.6.34-rc5.
>
> Signed-off-by: Dinh Nguyen <Dinh.Nguyen@freescale.com>
> Reviewed-by: Daniel Mack <daniel@caiaq.de>
> ---
> arch/arm/plat-mxc/ehci.c | 149 ++++++++++++++++++++++++++++-
> arch/arm/plat-mxc/include/mach/mxc_ehci.h | 58 +++++++++++-
> drivers/usb/host/ehci-mxc.c | 10 +-
> 3 files changed, 209 insertions(+), 8 deletions(-)
>
> diff --git a/arch/arm/plat-mxc/ehci.c b/arch/arm/plat-mxc/ehci.c
> index cb0b638..b52335d 100644
> --- a/arch/arm/plat-mxc/ehci.c
> +++ b/arch/arm/plat-mxc/ehci.c
> @@ -1,5 +1,6 @@
> /*
> * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
> + * Copyright (C) 2010 Freescale Semiconductor, Inc.
> *
> * This program is free software; you can redistribute it and/or modify it
> * under the terms of the GNU General Public License as published by the
> @@ -18,6 +19,7 @@
>
> #include <linux/platform_device.h>
> #include <linux/io.h>
> +#include <linux/delay.h>
>
> #include <mach/hardware.h>
> #include <mach/mxc_ehci.h>
> @@ -50,7 +52,29 @@
> #define MX35_H1_TLL_BIT (1 << 5)
> #define MX35_H1_USBTE_BIT (1 << 4)
>
> -int mxc_set_usbcontrol(int port, unsigned int flags)
> +/* This function is a version of David Brownell's handshake function in
> + * ehci-hcd.c. This function uses cpu_relax instead of udelay().
> + *
> + * @addr: Address of register
> + * @mask: bits to look at in result of read
> + * @done: value of those bits when handshake succeeds
> + * @timeout: timeout in count
> + *
> + * This function waits for certain bits in the HW to stick before moving
> + * on and provides a timeout in the case where those bits do not stick.
> + */
> +static inline int hw_handshake(u32 addr, u32 mask, int done, int timeout)
> +{
> + while (--timeout && ((__raw_readl(addr) & mask) != done))
> + cpu_relax();
> +
> + if (timeout)
> + return 0;
> + else
> + return -ETIMEDOUT;
> +}
> +
> +int mxc_initialize_usb_hw(int port, unsigned int flags)
> {
> unsigned int v;
> #ifdef CONFIG_ARCH_MX3
> @@ -186,9 +210,130 @@ int mxc_set_usbcontrol(int port, unsigned int flags)
> return 0;
> }
> #endif /* CONFIG_MACH_MX27 */
> +#ifdef CONFIG_ARCH_MX51
> + if (cpu_is_mx51()) {
> + void __iomem *usb_base;
> + u32 usbotg_base;
> + u32 usbother_base;
> + int ret = 0;
> +
> + usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
> +
> + switch (port) {
> + case 0: /* OTG port */
> + usbotg_base = usb_base + USBOTG_OFFSET;
> + break;
> + case 1: /* Host 1 port */
> + usbotg_base = usb_base + USBH1_OFFSET;
> + break;
> + default:
> + printk(KERN_ERR"%s no such port %d\n", __func__, port);
> + ret = -ENOENT;
> + goto error;
> + }
> + usbother_base = usb_base + USBOTHER_REGS_OFFSET;
> +
> + /* Stop then Reset */
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + v &= ~UCMD_RUN_STOP;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + ret = hw_handshake(usbotg_base + USBCMD_OFFSET, UCMD_RUN_STOP, 0, 500);
> + if (ret) {
> + printk(KERN_ERR "%s could not stop usb hardware\n", __func__);
> + goto error;
> + }
> +
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + v |= UCMD_RESET;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + ret = hw_handshake(usbotg_base + USBCMD_OFFSET, UCMD_RESET, 0, 500);
> + if (ret) {
> + printk(KERN_ERR "%s could not reset usb hardware\n", __func__);
> + goto error;
> + }
> +
> + switch (port) {
> + case 0: /*OTG port */
> + if (flags & MXC_EHCI_INTERNAL_PHY) {
> + v = __raw_readl(usbother_base + USB_PHY_CTR_FUNC_OFFSET);
> +
> + if (flags & MXC_EHCI_POWER_PINS_ENABLED)
> + v |= (USB_UTMI_PHYCTRL_OC_DIS | UCTRL_OPM); /* OC/USBPWR is not used */
> + else
> + v &= ~(USB_UTMI_PHYCTRL_OC_DIS | UCTRL_OPM); /* OC/USBPWR is used */
> + __raw_writel(v, usbother_base + USB_PHY_CTR_FUNC_OFFSET);
> +
> + v = __raw_readl(usbother_base + USBCTRL_OFFSET);
> + if (flags & MXC_EHCI_WAKEUP_ENABLED)
> + v |= UCTRL_OWIE;/* OTG wakeup enable */
> + else
> + v &= ~UCTRL_OWIE;/* OTG wakeup disable */
> + __raw_writel(v, usbother_base + USBCTRL_OFFSET);
> + }
> + break;
> + case 1: /* Host 1 */
> + /*Host ULPI */
> + v = __raw_readl(usbother_base + USBCTRL_OFFSET);
> + if (flags & MXC_EHCI_WAKEUP_ENABLED)
> + v &= ~(UCTRL_H1WIE | UCTRL_H1UIE);/* HOST1 wakeup/ULPI intr disable */
> + else
> + v &= ~(UCTRL_H1WIE | UCTRL_H1UIE);/* HOST1 wakeup/ULPI intr disable */
> +
> + if (flags & MXC_EHCI_POWER_PINS_ENABLED)
> + v &= ~UCTRL_H1PM; /* HOST1 power mask used*/
> + else
> + v |= UCTRL_H1PM; /* HOST1 power mask used*/
> + __raw_writel(v, usbother_base + USBCTRL_OFFSET);
> +
> + v = __raw_readl(usbother_base + USB_PHY_CTR_FUNC_OFFSET);
> + if (flags & MXC_EHCI_POWER_PINS_ENABLED)
> + v &= ~USB_UH1_OC_DIS; /* OC is used */
> + else
> + v |= USB_UH1_OC_DIS; /* OC is not used */
> + __raw_writel(v, usbother_base + USB_PHY_CTR_FUNC_OFFSET);
> +
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
> + /* Interrupt Threshold Control:Immediate (no threshold) */
> + v &= UCMD_ITC_NO_THRESHOLD;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + break;
> + }
> +
> + /* need to reset the controller here so that the ID pin
> + * is correctly detected.
> + */
> + /* Stop then Reset */
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + v &= ~UCMD_RUN_STOP;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + ret = hw_handshake(usbotg_base + USBCMD_OFFSET, UCMD_RUN_STOP, 0, 500);
> + if (ret) {
> + printk(KERN_ERR "%s could not stop usb hardware\n", __func__);
> + goto error;
> + }
> +
> + v = __raw_readl(usbotg_base + USBCMD_OFFSET);
> + v |= UCMD_RESET;
> + __raw_writel(v, usbotg_base + USBCMD_OFFSET);
> + ret = hw_handshake(usbotg_base + USBCMD_OFFSET, UCMD_RESET, 0, 500);
> + if (ret) {
> + printk(KERN_ERR "%s could not reset usb hardware\n", __func__);
> + goto error;
> + }
> +
> + /* allow controller to reset, and leave time for
> + * the ULPI transceiver to reset too.
> + */
> + msleep(100);
> +error:
> + iounmap(usb_base);
> + return ret;
> + }
> +#endif
> printk(KERN_WARNING
> "%s() unable to setup USBCONTROL for this CPU\n", __func__);
> return -EINVAL;
> }
> -EXPORT_SYMBOL(mxc_set_usbcontrol);
> +EXPORT_SYMBOL(mxc_initialize_usb_hw);
>
> diff --git a/arch/arm/plat-mxc/include/mach/mxc_ehci.h b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
> index 4b9b836..0ec88bb 100644
> --- a/arch/arm/plat-mxc/include/mach/mxc_ehci.h
> +++ b/arch/arm/plat-mxc/include/mach/mxc_ehci.h
> @@ -1,6 +1,30 @@
> #ifndef __INCLUDE_ASM_ARCH_MXC_EHCI_H
> #define __INCLUDE_ASM_ARCH_MXC_EHCI_H
>
> +#define USBOTG_OFFSET 0
> +#define USBH1_OFFSET 0x200
> +#define USBH2_OFFSET 0x400
> +#define USBH3_OFFSET 0x600
> +#define USBOTHER_REGS_OFFSET 0x800
> +
> +#define USBCMD_OFFSET 0x140
> +
> +#define ULPI_VIEWPORT_OFFSET 0x170
> +#define PORTSC_OFFSET 0x184
> +#define USBMODE_OFFSET 0x1a8
> +#define USBMODE_CM_HOST 3
> +
> +#define USBCTRL_OFFSET 0
> +#define USB_PHY_CTR_FUNC_OFFSET 0x8
> +#define USB_PHY_CTR_FUNC2_OFFSET 0xc
> +#define USB_CTRL_1_OFFSET 0x10
> +
> +
> +/* USBCMD */
> +#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */
> +#define UCMD_RESET (1 << 1) /* controller reset */
> +#define UCMD_ITC_NO_THRESHOLD (~(0xff << 16)) /* Interrupt Threshold Control */
> +
> /* values for portsc field */
> #define MXC_EHCI_PHY_LOW_POWER_SUSPEND (1 << 23)
> #define MXC_EHCI_FORCE_FS (1 << 24)
> @@ -25,6 +49,38 @@
> #define MXC_EHCI_INTERNAL_PHY (1 << 7)
> #define MXC_EHCI_IPPUE_DOWN (1 << 8)
> #define MXC_EHCI_IPPUE_UP (1 << 9)
> +#define MXC_EHCI_WAKEUP_ENABLED (1 << 10)
> +#define MXC_EHCI_ITC_NO_THRESHOLD (1 << 11)
> +
> +/* USB_CTRL */
> +#define UCTRL_OUIE (1 << 28) /* OTG ULPI intr enable */
> +#define UCTRL_OWIE (1 << 27) /* OTG wakeup intr enable */
> +#define UCTRL_OBPVAL_RXDP (1 << 26) /* OTG RxDp status in bypass mode */
> +#define UCTRL_OBPVAL_RXDM (1 << 25) /* OTG RxDm status in bypass mode */
> +#define UCTRL_OPM (1 << 24) /* OTG power mask */
> +#define UCTRL_H1UIE (1 << 12) /* Host1 ULPI interrupt enable */
> +#define UCTRL_H1WIE (1 << 11) /* HOST1 wakeup intr enable */
> +#define UCTRL_H1PM (1 << 8) /* HOST1 power mask */
> +
> +/* USB_PHY_CTRL_FUNC */
> +#define USB_UTMI_PHYCTRL_OC_DIS (1 << 8) /* OTG Disable Overcurrent Event */
> +#define USB_UH1_OC_DIS (1 << 5) /* UH1 Disable Overcurrent Event */
> +
> +/* USB_CTRL_1 */
> +#define USB_CTRL_UH1_EXT_CLK_EN (1 << 25)
> +#define USB_CTRL_UH2_EXT_CLK_EN (1 << 26)
> +
> +/* USB_PHY_CTRL_FUNC2*/
> +#define USB_UTMI_PHYCTRL2_PLLDIV_MASK 0x3
> +#define USB_UTMI_PHYCTRL2_PLLDIV_SHIFT 0
> +#define USB_UTMI_PHYCTRL2_HSDEVSEL_MASK 0x3
> +#define USB_UTMI_PHYCTRL2_HSDEVSEL_SHIFT 19
> +
> +#ifdef CONFIG_ARCH_MX51
> +#define USB_PLLDIV_12_MHZ 0x00
> +#define USB_PLL_DIV_19_2_MHZ 0x01
> +#define USB_PLL_DIV_24_MHZ 0x02
> +#endif
Please have a general look over these defines. All defines in
include/mach should at least have a MXC_ prefix. Most of these are
i.MX51 specific and thus should have a MX51_ prefix.
I think many of these do not have to be here anyway since they are
already in drivers/usb/host/ehci-mxc.c, are unused, or are only used
in plat-mxc/ehci.c.
> @@ -191,6 +191,11 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
> clk_enable(priv->ahbclk);
> }
>
> + /* setup specific usb hw */
> + ret = mxc_initialize_usb_hw(pdev->id, pdata->flags);
> + if (ret < 0)
> + goto err_init;
> +
> /* set USBMODE to host mode */
> temp = readl(hcd->regs + USBMODE_OFFSET);
> writel(temp | USBMODE_CM_HOST, hcd->regs + USBMODE_OFFSET);
> @@ -199,11 +204,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev)
> writel(pdata->portsc, hcd->regs + PORTSC_OFFSET);
> mdelay(10);
>
> - /* setup USBCONTROL. */
> - ret = mxc_set_usbcontrol(pdev->id, pdata->flags);
> - if (ret < 0)
> - goto err_init;
Has somebody tested if this works on other i.MXs? I remember it was quite
difficult to get the correct order of initialization. I don't want to
break this.
We should at least make a seperate patch from it so that anybody
bisecting this only finds this change and not the i.MX51 support also
added in this patch.
Sascha
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
next prev parent reply other threads:[~2010-04-22 14:45 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-04-21 15:13 [PATCHv7 2.6.34-rc5 1/5] mxc: Update GPIO for USB support on Freescale MX51 Babbage HW Dinh.Nguyen at freescale.com
2010-04-21 15:13 ` Dinh.Nguyen
2010-04-21 15:13 ` [PATCHv7 2.6.34-rc5 2/5] mx5: Add USB device definitions for " Dinh.Nguyen at freescale.com
2010-04-21 15:13 ` Dinh.Nguyen
2010-04-21 15:13 ` [PATCHv7 2.6.34-rc5 3/5] mx5: Enable board specific functions for enabling USB host on Babbage Dinh.Nguyen at freescale.com
2010-04-21 15:13 ` Dinh.Nguyen
2010-04-21 15:13 ` [PATCHv7 2.6.34-rc5 4/5] mxc: Add generic USB HW initialization for MX51 Dinh.Nguyen at freescale.com
2010-04-21 15:13 ` Dinh.Nguyen
2010-04-21 15:13 ` [PATCHv7 2.6.34-rc5 5/5] mx5: Add USB to Freescale MX51 defconfig Dinh.Nguyen at freescale.com
2010-04-21 15:13 ` Dinh.Nguyen
2010-04-22 14:45 ` Sascha Hauer [this message]
2010-04-22 14:45 ` [PATCHv7 2.6.34-rc5 4/5] mxc: Add generic USB HW initialization for MX51 Sascha Hauer
2010-04-22 15:02 ` Daniel Mack
2010-04-22 15:02 ` Daniel Mack
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=20100422144543.GU7882@pengutronix.de \
--to=s.hauer@pengutronix.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.