[U-Boot] [PATCH V4 1/2] ehci-omap: driver for EHCI host on OMAP3

Igor Grinberg grinberg at compulab.co.il
Thu Dec 22 09:14:25 CET 2011


Hi Govindraj,

On 12/22/11 08:55, Govindraj wrote:
> Hi IIya Yanok,
> 
> Sorry for late comments.

Better late than never...

> 
> On Tue, Dec 13, 2011 at 4:45 AM, Ilya Yanok <yanok at emcraft.com> wrote:
>> Taken from Beagle code. Tested on mcx board (AM3517-based).
>>
>> Signed-off-by: Ilya Yanok <yanok at emcraft.com>
>> ---
>> Changes from V3:
>>  - None
>> Changes from V2:
>>  - None
>> Changes from V1:
>>  - CONFIG_OMAP_EHCI_PHYx_RESET changed to CONFIG_OMAP_EHCI_PHYx_RESET_GPIO
>>  - phy reset moved to separate function
>>  - Calls to gpio_set_value after gpio_direction_output removed
>>
> 
> Here I see lot of stuff are just being moved from beagle board to new file
> ehci-omap.c , but echi-omap.c is not generic enough for re-use
> I think we should maintain clock handling and any gpio reset in board
> file itself

Hmmm, not really...
Current clock handling is SoC specific and not board specific,
so if we are about to make this file generic for more then one
SoC (e.g. OMAP4), then we should also introduce a per SoC clock
handling files, and reuse them with various boards.

Probably the same should hold for the GPIO reset code, because
otherwise code duplication is unavoidable.

> and just implement stuff related to ehci only like tll reset and ulpi
> phy configuration or
> hsic mode configuration based on some data passed from board file.
> 
> So we can re-use most of ehci-omap.c, I have done a similar approach
> as said which
> is intending to provide generic ehci-omap.c usage, which I was planning to
> re-use for beagle board, But since you are at it already can we make ehci-omap.c
> more generic.

+1

> 
> As we are planning to re-use ehci-omap.c for panda and other board support.
> Reference to patch done for panda initially.
> 
> http://patchwork.ozlabs.org/patch/131362/
> 
> One thing that I planning to do in this patch is moving all reg
> offsets from asm/ehci.h to
> include/asm/arch-omap4/ehci.h and retain only generic stuff in ehci.h
> thus we can have offsets from beagle from */arch-omap3/ehci.h and
> re-use most code from
> ehci-omap.c
> 
> 
>>  board/ti/beagle/beagle.c       |  101 --------------------------
>>  drivers/usb/host/Makefile      |    1 +
>>  drivers/usb/host/ehci-omap.c   |  156 ++++++++++++++++++++++++++++++++++++++++
>>  include/configs/omap3_beagle.h |    3 +
>>  4 files changed, 160 insertions(+), 101 deletions(-)
>>  create mode 100644 drivers/usb/host/ehci-omap.c
>>
>> diff --git a/board/ti/beagle/beagle.c b/board/ti/beagle/beagle.c
>> index 6a457cb..3d63028 100644
>> --- a/board/ti/beagle/beagle.c
>> +++ b/board/ti/beagle/beagle.c
>> @@ -42,15 +42,6 @@
>>  #include <asm/arch/sys_proto.h>
>>  #include <asm/gpio.h>
>>  #include <asm/mach-types.h>
>> -#ifdef CONFIG_USB_EHCI
>> -#include <usb.h>
>> -#include <asm/arch/clocks.h>
>> -#include <asm/arch/clocks_omap3.h>
>> -#include <asm/arch/ehci_omap3.h>
>> -/* from drivers/usb/host/ehci-core.h */
>> -extern struct ehci_hccr *hccr;
>> -extern volatile struct ehci_hcor *hcor;
>> -#endif
>>  #include "beagle.h"
>>  #include <command.h>
>>
>> @@ -441,104 +432,12 @@ int board_mmc_init(bd_t *bis)
>>  #endif
>>
>>  #ifdef CONFIG_USB_EHCI
>> -
>> -#define GPIO_PHY_RESET 147
>> -
>> -/* Reset is needed otherwise the kernel-driver will throw an error. */
>> -int ehci_hcd_stop(void)
>> -{
>> -       pr_debug("Resetting OMAP3 EHCI\n");
>> -       gpio_set_value(GPIO_PHY_RESET, 0);
>> -       writel(OMAP_UHH_SYSCONFIG_SOFTRESET, OMAP3_UHH_BASE + OMAP_UHH_SYSCONFIG);
>> -       /* disable USB clocks */
>> -       struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
>> -       sr32(&prcm_base->iclken_usbhost, 0, 1, 0);
>> -       sr32(&prcm_base->fclken_usbhost, 0, 2, 0);
>> -       sr32(&prcm_base->iclken3_core, 2, 1, 0);
>> -       sr32(&prcm_base->fclken3_core, 2, 1, 0);
>> -       return 0;
>> -}
>> -
> 
> As said above only uhh reset should be done in ehci-omap and
> clock and gpio can be left in baird file itslef
> you can just implement ehci_omap_hcd_stop that will reset uhh.

Or add SoC specific ehci_clk_disable()
and put the clock handling in it.

> 
> 
>>  /* Call usb_stop() before starting the kernel */
>>  void show_boot_progress(int val)
>>  {
>>        if(val == 15)
>>                usb_stop();
>>  }
>> -
>> -/*
>> - * Initialize the OMAP3 EHCI controller and PHY on the BeagleBoard.
>> - * Based on "drivers/usb/host/ehci-omap.c" from Linux 2.6.37.
>> - * See there for additional Copyrights.
>> - */
>> -int ehci_hcd_init(void)
>> -{
>> -       pr_debug("Initializing OMAP3 ECHI\n");
>> -
>> -       /* Put the PHY in RESET */
>> -       gpio_request(GPIO_PHY_RESET, "");
>> -       gpio_direction_output(GPIO_PHY_RESET, 0);
>> -       gpio_set_value(GPIO_PHY_RESET, 0);
>> -
>> -       /* Hold the PHY in RESET for enough time till DIR is high */
>> -       /* Refer: ISSUE1 */
>> -       udelay(10);
>> -
>> -       struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
>> -       /* Enable USBHOST_L3_ICLK (USBHOST_MICLK) */
>> -       sr32(&prcm_base->iclken_usbhost, 0, 1, 1);
>> -       /*
>> -        * Enable USBHOST_48M_FCLK (USBHOST_FCLK1)
>> -        * and USBHOST_120M_FCLK (USBHOST_FCLK2)
>> -        */
>> -       sr32(&prcm_base->fclken_usbhost, 0, 2, 3);
>> -       /* Enable USBTTL_ICLK */
>> -       sr32(&prcm_base->iclken3_core, 2, 1, 1);
>> -       /* Enable USBTTL_FCLK */
>> -       sr32(&prcm_base->fclken3_core, 2, 1, 1);
>> -       pr_debug("USB clocks enabled\n");
>> -
> 
> same here also must be left in beagle board file and
> implement omap_ehci_hcd_init() which will reset uhh, tll and
> configure phy_ulpi mode.

SoC specific ehci_clk_enable() should be better then in board code.

> 
>> -       /* perform TLL soft reset, and wait until reset is complete */
>> -       writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET,
>> -               OMAP3_USBTLL_BASE + OMAP_USBTLL_SYSCONFIG);
>> -       /* Wait for TLL reset to complete */
>> -       while (!(readl(OMAP3_USBTLL_BASE + OMAP_USBTLL_SYSSTATUS)
>> -                       & OMAP_USBTLL_SYSSTATUS_RESETDONE));
>> -       pr_debug("TLL reset done\n");
>> -
>> -       writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
>> -               OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
>> -               OMAP_USBTLL_SYSCONFIG_CACTIVITY,
>> -               OMAP3_USBTLL_BASE + OMAP_USBTLL_SYSCONFIG);
>> -
>> -       /* Put UHH in NoIdle/NoStandby mode */
>> -       writel(OMAP_UHH_SYSCONFIG_ENAWAKEUP
>> -               | OMAP_UHH_SYSCONFIG_SIDLEMODE
>> -               | OMAP_UHH_SYSCONFIG_CACTIVITY
>> -               | OMAP_UHH_SYSCONFIG_MIDLEMODE,
>> -               OMAP3_UHH_BASE + OMAP_UHH_SYSCONFIG);
>> -
>> -       /* setup burst configurations */
>> -       writel(OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
>> -               | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
>> -               | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN,
>> -               OMAP3_UHH_BASE + OMAP_UHH_HOSTCONFIG);
>> -
>> -       /*
>> -        * Refer ISSUE1:
>> -        * Hold the PHY in RESET for enough time till
>> -        * PHY is settled and ready
>> -        */
>> -       udelay(10);
>> -       gpio_set_value(GPIO_PHY_RESET, 1);
>> -
>> -       hccr = (struct ehci_hccr *)(OMAP3_EHCI_BASE);
>> -       hcor = (struct ehci_hcor *)(OMAP3_EHCI_BASE + 0x10);
>> -
>> -       pr_debug("OMAP3 EHCI init done\n");
>> -       return 0;
>> -}
>> -
>>  #endif /* CONFIG_USB_EHCI */
>>
>>  #ifndef CONFIG_SPL_BUILD
>> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
>> index 77e217f..975c3e5 100644
>> --- a/drivers/usb/host/Makefile
>> +++ b/drivers/usb/host/Makefile
>> @@ -43,6 +43,7 @@ endif
>>  COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
>>  COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o
>>  COBJS-$(CONFIG_USB_EHCI_MX5) += ehci-mx5.o
>> +COBJS-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o
>>  COBJS-$(CONFIG_USB_EHCI_PPC4XX) += ehci-ppc4xx.o
>>  COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o
>>  COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.o
>> diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
>> new file mode 100644
>> index 0000000..93d3bb7
>> --- /dev/null
>> +++ b/drivers/usb/host/ehci-omap.c
>> @@ -0,0 +1,156 @@
>> +/*
>> + * (C) Copyright 2011 Ilya Yanok, Emcraft Systems
>> + * (C) Copyright 2004-2008
>> + * Texas Instruments, <www.ti.com>
>> + *
>> + * Derived from Beagle Board code by
>> + *     Sunil Kumar <sunilsaini05 at gmail.com>
>> + *     Shashi Ranjan <shashiranjanmca05 at gmail.com>
>> + *
>> + *
>> + * See file CREDITS for list of people who contributed to this
>> + * project.
>> + *
>> + * 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 Free Software Foundation; either version 2 of
>> + * the License, or (at your option) any later version.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, Inc.
>> + */
>> +#include <common.h>
>> +#include <usb.h>
>> +#include <asm/io.h>
>> +#include <asm/gpio.h>
>> +#include <asm/arch/clocks.h>
>> +#include <asm/arch/clocks_omap3.h>
>> +#include <asm/arch/ehci_omap3.h>
> 
> if this can be renamed to just ehci.h it will be better
> from re-use perspective since I can add just ehci.h for omap4/5
> in the arch folders and based on config used it will pickup the
> file used.

+1

> 
>> +#include <asm/arch/sys_proto.h>
>> +#include "ehci-core.h"
>> +
>> +inline int __board_usb_init(void)
>> +{
>> +       return 0;
>> +}
>> +int board_usb_init(void) __attribute__((weak, alias("__board_usb_init")));
>> +
>> +#if defined(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO) || \
>> +       defined(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO)
>> +/* controls PHY(s) reset signal(s) */
>> +static inline void omap_ehci_phy_reset(int on, int delay)
>> +{
>> +       /*
>> +        * Refer ISSUE1:
>> +        * Hold the PHY in RESET for enough time till
>> +        * PHY is settled and ready
>> +        */
>> +       if (delay && !on)
>> +               udelay(delay);
>> +#ifdef CONFIG_OMAP_EHCI_PHY1_RESET_GPIO
>> +       gpio_request(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, "USB PHY1 reset");
>> +       gpio_direction_output(CONFIG_OMAP_EHCI_PHY1_RESET_GPIO, !on);
>> +#endif
>> +#ifdef CONFIG_OMAP_EHCI_PHY2_RESET_GPIO
>> +       gpio_request(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, "USB PHY2 reset");
>> +       gpio_direction_output(CONFIG_OMAP_EHCI_PHY2_RESET_GPIO, !on);
>> +#endif
>> +
>> +       /* Hold the PHY in RESET for enough time till DIR is high */
>> +       /* Refer: ISSUE1 */
>> +       if (delay && on)
>> +               udelay(delay);
>> +}
>> +#else
>> +#define omap_ehci_phy_reset(on, delay) do {} while (0)
>> +#endif
>> +
>> +/* Reset is needed otherwise the kernel-driver will throw an error. */
>> +int ehci_hcd_stop(void)
>> +{
>> +       debug("Resetting OMAP3 EHCI\n");
>> +       omap_ehci_phy_reset(1, 0);
>> +       writel(OMAP_UHH_SYSCONFIG_SOFTRESET,
>> +                       OMAP3_UHH_BASE + OMAP_UHH_SYSCONFIG);
>> +       /* disable USB clocks */
>> +       struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
>> +       sr32(&prcm_base->iclken_usbhost, 0, 1, 0);
>> +       sr32(&prcm_base->fclken_usbhost, 0, 2, 0);
>> +       sr32(&prcm_base->iclken3_core, 2, 1, 0);
>> +       sr32(&prcm_base->fclken3_core, 2, 1, 0);
>> +       return 0;
>> +}
>> +
>> +/*
>> + * Initialize the OMAP3 EHCI controller and PHY.
>> + * Based on "drivers/usb/host/ehci-omap.c" from Linux 2.6.37.
>> + * See there for additional Copyrights.
>> + */
>> +int ehci_hcd_init(void)
>> +{
>> +       int ret;
>> +
>> +       debug("Initializing OMAP3 EHCI\n");
>> +
>> +       ret = board_usb_init();
>> +       if (ret < 0)
>> +               return ret;
>> +
>> +       /* Put the PHY in RESET */
>> +       omap_ehci_phy_reset(1, 10);
>> +
>> +       struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
>> +       /* Enable USBHOST_L3_ICLK (USBHOST_MICLK) */
>> +       sr32(&prcm_base->iclken_usbhost, 0, 1, 1);
>> +       /*
>> +        * Enable USBHOST_48M_FCLK (USBHOST_FCLK1)
>> +        * and USBHOST_120M_FCLK (USBHOST_FCLK2)
>> +        */
>> +       sr32(&prcm_base->fclken_usbhost, 0, 2, 3);
>> +       /* Enable USBTTL_ICLK */
>> +       sr32(&prcm_base->iclken3_core, 2, 1, 1);
>> +       /* Enable USBTTL_FCLK */
>> +       sr32(&prcm_base->fclken3_core, 2, 1, 1);
>> +       debug("USB clocks enabled\n");
>> +
>> +       /* perform TLL soft reset, and wait until reset is complete */
>> +       writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET,
>> +               OMAP3_USBTLL_BASE + OMAP_USBTLL_SYSCONFIG);
>> +       /* Wait for TLL reset to complete */
>> +       while (!(readl(OMAP3_USBTLL_BASE + OMAP_USBTLL_SYSSTATUS)
>> +                       & OMAP_USBTLL_SYSSTATUS_RESETDONE))
>> +               ;
>> +       debug("TLL reset done\n");
>> +
>> +       writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
>> +               OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
>> +               OMAP_USBTLL_SYSCONFIG_CACTIVITY,
>> +               OMAP3_USBTLL_BASE + OMAP_USBTLL_SYSCONFIG);
>> +
>> +       /* Put UHH in NoIdle/NoStandby mode */
>> +       writel(OMAP_UHH_SYSCONFIG_ENAWAKEUP
>> +               | OMAP_UHH_SYSCONFIG_SIDLEMODE
>> +               | OMAP_UHH_SYSCONFIG_CACTIVITY
>> +               | OMAP_UHH_SYSCONFIG_MIDLEMODE,
>> +               OMAP3_UHH_BASE + OMAP_UHH_SYSCONFIG);
>> +
>> +       /* setup burst configurations */
>> +       writel(OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
>> +               | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
>> +               | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN,
>> +               OMAP3_UHH_BASE + OMAP_UHH_HOSTCONFIG);
>> +
>> +       omap_ehci_phy_reset(0, 10);
>> +
>> +       hccr = (struct ehci_hccr *)(OMAP3_EHCI_BASE);
>> +       hcor = (struct ehci_hcor *)(OMAP3_EHCI_BASE + 0x10);
>> +
>> +       debug("OMAP3 EHCI init done\n");
>> +       return 0;
>> +}
>> diff --git a/include/configs/omap3_beagle.h b/include/configs/omap3_beagle.h
>> index 91af8a0..b4d6443 100644
>> --- a/include/configs/omap3_beagle.h
>> +++ b/include/configs/omap3_beagle.h
>> @@ -129,6 +129,9 @@
>>  /* USB EHCI */
>>  #define CONFIG_CMD_USB
>>  #define CONFIG_USB_EHCI
>> +#define CONFIG_USB_EHCI_OMAP
>> +/*#define CONFIG_EHCI_DCACHE*/ /* leave it disabled for now */
> 
> Any reason for this?
> 
> Probably we are missing #define CONFIG_EHCI_DCACHE
> 
> Let me know if you intend to clean up it up or I can take up and
> re-base my stuff by
> moving back the clock and gpio stuff back to beagle board.

Please, don't move the clocks handling code back to board file.
It should not be there. It should be available to all boards
having OMAP3 SoC.
I think this also stands for OMAP4 boards unless it is so panda
specific, which I think is not the case.

> or can we re-use ehci-omap.c done for panda for beagle?

Agreed, but please, understand - the world is not only beagle
and panda. You need to let other boards benefit from that code
(that is the intension in generalizing stuff, right?) which is not
board specific.


-- 
Regards,
Igor.


More information about the U-Boot mailing list