[U-Boot] tftp booting the panda board

Hi,
I am trying to tftpboot the panda board, this basically works, but I still have some issues.
The panda board uses an SMSC95xx chip, and so requires USB2.0
Using the u-boot git head, we have support for network adapters over USB, and the patches from Simon Glass, we get support for the ethernet chip. So, the only missing piece of the puzzle is USB EHCI for OMAP4/Panda.
I tried to implement it, the patches will follow shortly, but have several remaining issues: - the EHCI stop routine, implemented as in the Linux kernel driver, has timeouts when trying to wait for the UHH reset; - the SMSC95XX is unstable, if I start USB, stop USB, then start again, the SMSC95XX initialization hangs, this does not happen without this driver - if I launch bootp, and say, the server does not answer to the bootp protocol, the smsc95xx driver does not seem to be able to recover from the first timeout, any further attempt causes a timeout.
Regards.

Copied from omap3.
Signed-off-by: Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org --- arch/arm/cpu/armv7/omap4/Makefile | 1 + arch/arm/cpu/armv7/omap4/gpio.c | 169 ++++++++++++++++++++++++++++++++ arch/arm/include/asm/arch-omap4/gpio.h | 93 +++++++++++++++++ 3 files changed, 263 insertions(+), 0 deletions(-) create mode 100644 arch/arm/cpu/armv7/omap4/gpio.c create mode 100644 arch/arm/include/asm/arch-omap4/gpio.h
diff --git a/arch/arm/cpu/armv7/omap4/Makefile b/arch/arm/cpu/armv7/omap4/Makefile index 987dc9d..c39693a 100644 --- a/arch/arm/cpu/armv7/omap4/Makefile +++ b/arch/arm/cpu/armv7/omap4/Makefile @@ -29,6 +29,7 @@ SOBJS += lowlevel_init.o
COBJS += board.o COBJS += mem.o +COBJS += gpio.o COBJS += sys_info.o
SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/arch/arm/cpu/armv7/omap4/gpio.c b/arch/arm/cpu/armv7/omap4/gpio.c new file mode 100644 index 0000000..40f1d5e --- /dev/null +++ b/arch/arm/cpu/armv7/omap4/gpio.c @@ -0,0 +1,169 @@ +/* + * Lifted from arch/arm/cpu/armv7/omap3/gpio.c + * + * Original Copyright (c) 2009 Wind River Systems, Inc. + * Tom Rix Tom.Rix@windriver.com + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * This work is derived from the linux 2.6.27 kernel source + * To fetch, use the kernel repository + * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + * Use the v2.6.27 tag. + * + * Below is the original's header including its copyright + * + * linux/arch/arm/plat-omap/gpio.c + * + * Support functions for OMAP GPIO + * + * Copyright (C) 2003-2005 Nokia Corporation + * Written by Juha Yrjölä juha.yrjola@nokia.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <common.h> +#include <asm/arch/gpio.h> +#include <asm/io.h> +#include <asm/errno.h> + +/* + * OMAP44XX specific GPIO registers + */ +#define OMAP44XX_GPIO1_BASE 0x4a310000 +#define OMAP44XX_GPIO2_BASE 0x48055000 +#define OMAP44XX_GPIO3_BASE 0x48057000 +#define OMAP44XX_GPIO4_BASE 0x48059000 +#define OMAP44XX_GPIO5_BASE 0x4805B000 +#define OMAP44XX_GPIO6_BASE 0x4805D000 + +static const struct gpio_bank gpio_bank_44xx[6] = { + { (void *)OMAP44XX_GPIO1_BASE }, + { (void *)OMAP44XX_GPIO2_BASE }, + { (void *)OMAP44XX_GPIO3_BASE }, + { (void *)OMAP44XX_GPIO4_BASE }, + { (void *)OMAP44XX_GPIO5_BASE }, + { (void *)OMAP44XX_GPIO6_BASE }, +}; + +static struct gpio_bank *gpio_bank = &gpio_bank_44xx[0]; + +static inline struct gpio_bank *get_gpio_bank(int gpio) +{ + return &gpio_bank[gpio >> 5]; +} + +static inline int get_gpio_index(int gpio) +{ + return gpio & 0x1f; +} + +static inline int gpio_valid(int gpio) +{ + if (gpio < 0) + return -1; + if (gpio < 192) + return 0; + return -1; +} + +static int check_gpio(int gpio) +{ + if (gpio_valid(gpio) < 0) { + printf("ERROR : check_gpio: invalid GPIO %d\n", gpio); + return -1; + } + return 0; +} + +static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) +{ + void *reg; + u32 l; + + reg = bank->base + OMAP4_GPIO_OE; + l = __raw_readl(reg); + if (is_input) + l |= 1 << gpio; + else + l &= ~(1 << gpio); + __raw_writel(l, reg); +} + +void omap_set_gpio_direction(int gpio, int is_input) +{ + struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return; + bank = get_gpio_bank(gpio); + _set_gpio_direction(bank, get_gpio_index(gpio), is_input); +} + +static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) +{ + if (enable) + __raw_writel(1 << gpio, bank->base + OMAP4_GPIO_SETDATAOUT); + else + __raw_writel(1 << gpio, bank->base + OMAP4_GPIO_CLEARDATAOUT); +} + +void omap_set_gpio_dataout(int gpio, int enable) +{ + struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return; + bank = get_gpio_bank(gpio); + _set_gpio_dataout(bank, get_gpio_index(gpio), enable); +} + +int omap_get_gpio_datain(int gpio) +{ + struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return -EINVAL; + bank = get_gpio_bank(gpio); + return (__raw_readl(bank->base + OMAP4_GPIO_DATAIN) + & (1 << get_gpio_index(gpio))) != 0; +} + +static void _reset_gpio(struct gpio_bank *bank, int gpio) +{ + _set_gpio_direction(bank, get_gpio_index(gpio), 1); +} + +int omap_request_gpio(int gpio) +{ + if (check_gpio(gpio) < 0) + return -EINVAL; + + return 0; +} + +void omap_free_gpio(int gpio) +{ + struct gpio_bank *bank; + + if (check_gpio(gpio) < 0) + return; + bank = get_gpio_bank(gpio); + + _reset_gpio(bank, gpio); +} diff --git a/arch/arm/include/asm/arch-omap4/gpio.h b/arch/arm/include/asm/arch-omap4/gpio.h new file mode 100644 index 0000000..d4dbea4 --- /dev/null +++ b/arch/arm/include/asm/arch-omap4/gpio.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2009 Wind River Systems, Inc. + * Tom Rix Tom.Rix@windriver.com + * + * 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., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * This work is derived from the linux 2.6.27 kernel source + * To fetch, use the kernel repository + * git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git + * Use the v2.6.27 tag. + * + * Below is the original's header including its copyright + * + * linux/arch/arm/plat-omap/gpio.c + * + * Support functions for OMAP GPIO + * + * Copyright (C) 2003-2005 Nokia Corporation + * Written by Juha Yrjölä juha.yrjola@nokia.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef _GPIO_H +#define _GPIO_H + +#define OMAP4_GPIO_REVISION 0x0000 +#define OMAP4_GPIO_SYSCONFIG 0x0010 +#define OMAP4_GPIO_EOI 0x0020 +#define OMAP4_GPIO_IRQSTATUSRAW0 0x0024 +#define OMAP4_GPIO_IRQSTATUSRAW1 0x0028 +#define OMAP4_GPIO_IRQSTATUS0 0x002c +#define OMAP4_GPIO_IRQSTATUS1 0x0030 +#define OMAP4_GPIO_IRQSTATUSSET0 0x0034 +#define OMAP4_GPIO_IRQSTATUSSET1 0x0038 +#define OMAP4_GPIO_IRQSTATUSCLR0 0x003c +#define OMAP4_GPIO_IRQSTATUSCLR1 0x0040 +#define OMAP4_GPIO_IRQWAKEN0 0x0044 +#define OMAP4_GPIO_IRQWAKEN1 0x0048 +#define OMAP4_GPIO_SYSSTATUS 0x0114 +#define OMAP4_GPIO_IRQENABLE1 0x011c +#define OMAP4_GPIO_WAKE_EN 0x0120 +#define OMAP4_GPIO_IRQSTATUS2 0x0128 +#define OMAP4_GPIO_IRQENABLE2 0x012c +#define OMAP4_GPIO_CTRL 0x0130 +#define OMAP4_GPIO_OE 0x0134 +#define OMAP4_GPIO_DATAIN 0x0138 +#define OMAP4_GPIO_DATAOUT 0x013c +#define OMAP4_GPIO_LEVELDETECT0 0x0140 +#define OMAP4_GPIO_LEVELDETECT1 0x0144 +#define OMAP4_GPIO_RISINGDETECT 0x0148 +#define OMAP4_GPIO_FALLINGDETECT 0x014c +#define OMAP4_GPIO_DEBOUNCENABLE 0x0150 +#define OMAP4_GPIO_DEBOUNCINGTIME 0x0154 +#define OMAP4_GPIO_CLEARIRQENABLE1 0x0160 +#define OMAP4_GPIO_SETIRQENABLE1 0x0164 +#define OMAP4_GPIO_CLEARWKUENA 0x0180 +#define OMAP4_GPIO_SETWKUENA 0x0184 +#define OMAP4_GPIO_CLEARDATAOUT 0x0190 +#define OMAP4_GPIO_SETDATAOUT 0x0194 + +struct gpio_bank { + void *base; +}; + +/* This is the interface */ + +/* Request a gpio before using it */ +int omap_request_gpio(int gpio); +/* Reset and free a gpio after using it */ +void omap_free_gpio(int gpio); +/* Sets the gpio as input or output */ +void omap_set_gpio_direction(int gpio, int is_input); +/* Set or clear a gpio output */ +void omap_set_gpio_dataout(int gpio, int enable); +/* Get the value of a gpio input */ +int omap_get_gpio_datain(int gpio); + +#endif /* _GPIO_H_ */

On Mon, May 9, 2011 at 11:04 PM, Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org wrote:
Copied from omap3.
I have not looked at the code but if it truly is a copy (other than some base addresses) is there a way to share with omap3?
--john

On 05/10/2011 04:08 PM, John Rigby wrote:
On Mon, May 9, 2011 at 11:04 PM, Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org wrote:
Copied from omap3.
I have not looked at the code but if it truly is a copy (other than some base addresses) is there a way to share with omap3?
Yes, probably. The linux code is full of switch/cases, but that is because it has to support compiling one kernel for all omaps. We can do something simple with a header defining the same defines to different values depending on the actual processor.

On 05/10/2011 04:08 PM, John Rigby wrote:
On Mon, May 9, 2011 at 11:04 PM, Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org wrote:
Copied from omap3.
I have not looked at the code but if it truly is a copy (other than some base addresses) is there a way to share with omap3?
I am going to fix this and resend another round of patches. But, it this the only thing I should fix?
For instance, in part of the patch, I used hardcoded hardware addresses, in other part, I put some #define for register addresses in the .c file, in other part, the #define are in a common header. What is the policy in u-boot for this particular point?

On 05/13/2011 07:31 AM, John Rigby wrote:
I am going to fix this and resend another round of patches. But, it this the only thing I should fix?
My comment was not a complete review only a comment about sharing.
I got that, I am just trying to get more comments before I send another round of patches, in order to avoid having to send 10 rounds of patches.
Maybe the patches were sent to the wrong person?

As board may need some specific support, implement inner functions to be called by the boards implementaions of ehci_hcd_start, ehci_hcd_stop.
Signed-off-by: Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org --- arch/arm/include/asm/arch-omap4/ehci.h | 8 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-omap4.c | 268 ++++++++++++++++++++++++++++++++ 3 files changed, 277 insertions(+), 0 deletions(-) create mode 100644 arch/arm/include/asm/arch-omap4/ehci.h create mode 100644 drivers/usb/host/ehci-omap4.c
diff --git a/arch/arm/include/asm/arch-omap4/ehci.h b/arch/arm/include/asm/arch-omap4/ehci.h new file mode 100644 index 0000000..fc84f6a --- /dev/null +++ b/arch/arm/include/asm/arch-omap4/ehci.h @@ -0,0 +1,8 @@ +#ifndef EHCI_H +#define EHCI_H + +int omap4_ehci_hcd_init(void); + +int omap4_ehci_hcd_stop(void); + +#endif /* EHCI_H */ diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 51b2494..5a5b971 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -46,6 +46,7 @@ COBJS-$(CONFIG_USB_EHCI_IXP4XX) += ehci-ixp.o COBJS-$(CONFIG_USB_EHCI_KIRKWOOD) += ehci-kirkwood.o COBJS-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o COBJS-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o +COBJS-$(CONFIG_USB_EHCI_OMAP4) += ehci-omap4.o
COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/usb/host/ehci-omap4.c b/drivers/usb/host/ehci-omap4.c new file mode 100644 index 0000000..19cd286 --- /dev/null +++ b/drivers/usb/host/ehci-omap4.c @@ -0,0 +1,268 @@ +/* + * OMAP4 EHCI port, copied from linux/drivers/usb/host/ehci-omap.c + * + * Copyright (C) 2007-2010 Texas Instruments, Inc. + * Author: Vikram Pandita vikram.pandita@ti.com + * Author: Anand Gadiyar gadiyar@ti.com + */ + +#include <common.h> +#include <usb.h> +#include <errno.h> +#include <asm/io.h> +#include <asm/arch/gpio.h> +#include <asm/arch/omap4.h> +#include <asm/arch/sys_proto.h> + +#include "ehci.h" +#include "ehci-core.h" + +#define EHCI_BASE (OMAP44XX_L4_CORE_BASE + 0x64C00) +#define UHH_BASE (OMAP44XX_L4_CORE_BASE + 0x64000) +#define TLL_BASE (OMAP44XX_L4_CORE_BASE + 0x62000) + +/* ULPI */ +#define ULPI_SET(a) (a + 1) +#define ULPI_CLR(a) (a + 2) + +#define ULPI_FUNC_CTRL 0x04 + +#define ULPI_FUNC_CTRL_RESET (1 << 5) + +/* TLL Register Set */ +#define OMAP_USBTLL_REVISION (0x00) +#define OMAP_USBTLL_SYSCONFIG (0x10) +#define OMAP_USBTLL_SYSCONFIG_CACTIVITY (1 << 8) +#define OMAP_USBTLL_SYSCONFIG_SIDLEMODE (1 << 3) +#define OMAP_USBTLL_SYSCONFIG_ENAWAKEUP (1 << 2) +#define OMAP_USBTLL_SYSCONFIG_SOFTRESET (1 << 1) +#define OMAP_USBTLL_SYSCONFIG_AUTOIDLE (1 << 0) + +#define OMAP_USBTLL_SYSSTATUS (0x14) +#define OMAP_USBTLL_SYSSTATUS_RESETDONE (1 << 0) + +#define OMAP_USBTLL_IRQSTATUS (0x18) +#define OMAP_USBTLL_IRQENABLE (0x1C) + +#define OMAP_TLL_SHARED_CONF (0x30) +#define OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN (1 << 6) +#define OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN (1 << 5) +#define OMAP_TLL_SHARED_CONF_USB_DIVRATION (1 << 2) +#define OMAP_TLL_SHARED_CONF_FCLK_REQ (1 << 1) +#define OMAP_TLL_SHARED_CONF_FCLK_IS_ON (1 << 0) + +#define OMAP_TLL_CHANNEL_CONF(num) (0x040 + 0x004 * num) +#define OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF (1 << 11) +#define OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE (1 << 10) +#define OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE (1 << 9) +#define OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE (1 << 8) +#define OMAP_TLL_CHANNEL_CONF_CHANEN (1 << 0) + +#define OMAP_TLL_ULPI_FUNCTION_CTRL(num) (0x804 + 0x100 * num) +#define OMAP_TLL_ULPI_INTERFACE_CTRL(num) (0x807 + 0x100 * num) +#define OMAP_TLL_ULPI_OTG_CTRL(num) (0x80A + 0x100 * num) +#define OMAP_TLL_ULPI_INT_EN_RISE(num) (0x80D + 0x100 * num) +#define OMAP_TLL_ULPI_INT_EN_FALL(num) (0x810 + 0x100 * num) +#define OMAP_TLL_ULPI_INT_STATUS(num) (0x813 + 0x100 * num) +#define OMAP_TLL_ULPI_INT_LATCH(num) (0x814 + 0x100 * num) +#define OMAP_TLL_ULPI_DEBUG(num) (0x815 + 0x100 * num) +#define OMAP_TLL_ULPI_SCRATCH_REGISTER(num) (0x816 + 0x100 * num) + +#define OMAP_TLL_CHANNEL_COUNT 3 +#define OMAP_TLL_CHANNEL_1_EN_MASK (1 << 1) +#define OMAP_TLL_CHANNEL_2_EN_MASK (1 << 2) +#define OMAP_TLL_CHANNEL_3_EN_MASK (1 << 4) + +/* UHH Register Set */ +#define OMAP_UHH_REVISION (0x00) +#define OMAP_UHH_SYSCONFIG (0x10) +#define OMAP_UHH_SYSCONFIG_MIDLEMODE (1 << 12) +#define OMAP_UHH_SYSCONFIG_CACTIVITY (1 << 8) +#define OMAP_UHH_SYSCONFIG_SIDLEMODE (1 << 3) +#define OMAP_UHH_SYSCONFIG_ENAWAKEUP (1 << 2) +#define OMAP_UHH_SYSCONFIG_SOFTRESET (1 << 1) +#define OMAP_UHH_SYSCONFIG_AUTOIDLE (1 << 0) + +#define OMAP_UHH_SYSSTATUS (0x14) +#define OMAP_UHH_HOSTCONFIG (0x40) +#define OMAP_UHH_HOSTCONFIG_ULPI_BYPASS (1 << 0) +#define OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS (1 << 0) +#define OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS (1 << 11) +#define OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS (1 << 12) +#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN (1 << 2) +#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN (1 << 3) +#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN (1 << 4) +#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN (1 << 5) +#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS (1 << 8) +#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS (1 << 9) +#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS (1 << 10) + +/* OMAP4-specific defines */ +#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR (3 << 2) +#define OMAP4_UHH_SYSCONFIG_NOIDLE (1 << 2) + +#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR (3 << 4) +#define OMAP4_UHH_SYSCONFIG_NOSTDBY (1 << 4) +#define OMAP4_UHH_SYSCONFIG_SOFTRESET (1 << 0) + +#define OMAP4_P1_MODE_CLEAR (3 << 16) +#define OMAP4_P1_MODE_TLL (1 << 16) +#define OMAP4_P1_MODE_HSIC (3 << 16) +#define OMAP4_P2_MODE_CLEAR (3 << 18) +#define OMAP4_P2_MODE_TLL (1 << 18) +#define OMAP4_P2_MODE_HSIC (3 << 18) + +#define OMAP_REV2_TLL_CHANNEL_COUNT 2 + +#define OMAP_UHH_DEBUG_CSR (0x44) + +/* EHCI Register Set */ +#define EHCI_INSNREG04 (0xA0) +#define EHCI_INSNREG04_DISABLE_UNSUSPEND (1 << 5) +#define EHCI_INSNREG05_ULPI (0xA4) +#define EHCI_INSNREG05_ULPI_CONTROL_SHIFT 31 +#define EHCI_INSNREG05_ULPI_PORTSEL_SHIFT 24 +#define EHCI_INSNREG05_ULPI_OPSEL_SHIFT 22 +#define EHCI_INSNREG05_ULPI_REGADD_SHIFT 16 +#define EHCI_INSNREG05_ULPI_EXTREGADD_SHIFT 8 +#define EHCI_INSNREG05_ULPI_WRDATA_SHIFT 0 + +int omap4_ehci_hcd_init(void) +{ + unsigned long base = get_timer(0); + unsigned reg = 0, port = 0; + int rc; + + /* USB host, with clock from external phy as port 1 UTMI clock */ + sr32((void *)0x4A009358, 0, 32, 0x01000002); + + /* FSUSB clk */ + sr32((void *)0x4a0093d0, 0, 32, 0x2); + + /* USB TLL clock */ + sr32((void *)0x4a009368, 0, 32, 0x1); + + /* enable the 32K, 48M optional clocks and enable the module */ + sr32((void *)0x4a0093e0, 0, 32, 0x301); + + /* perform TLL soft reset, and wait until reset is complete */ + writel(OMAP_USBTLL_SYSCONFIG_SOFTRESET, + TLL_BASE + OMAP_USBTLL_SYSCONFIG); + + /* Wait for TLL reset to complete */ + while (!(readl(TLL_BASE + OMAP_USBTLL_SYSSTATUS) + & OMAP_USBTLL_SYSSTATUS_RESETDONE)) + if (get_timer(base) > CONFIG_SYS_HZ) { + printf("OMAP4 EHCI error: timeout resetting TLL\n"); + return -1; + } + + writel(OMAP_USBTLL_SYSCONFIG_ENAWAKEUP | + OMAP_USBTLL_SYSCONFIG_SIDLEMODE | + OMAP_USBTLL_SYSCONFIG_CACTIVITY, + TLL_BASE + OMAP_USBTLL_SYSCONFIG); + + /* Put UHH in NoIdle/NoStandby mode */ + reg = readl(UHH_BASE + OMAP_UHH_SYSCONFIG); + reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR; + reg |= OMAP4_UHH_SYSCONFIG_NOIDLE; + reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR; + reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY; + writel(reg, UHH_BASE + OMAP_UHH_SYSCONFIG); + + reg = readl(UHH_BASE + OMAP_UHH_HOSTCONFIG); + + /* setup ULPI bypass and burst configurations */ + reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN + | OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN + | OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN); + reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN; + + /* Clear port mode fields for PHY mode*/ + reg &= ~OMAP4_P1_MODE_CLEAR; + reg &= ~OMAP4_P2_MODE_CLEAR; + writel(reg, UHH_BASE + OMAP_UHH_HOSTCONFIG); + + /* + * An undocumented "feature" in the OMAP3 EHCI controller, + * causes suspended ports to be taken out of suspend when + * the USBCMD.Run/Stop bit is cleared (for example when + * we do ehci_bus_suspend). + * This breaks suspend-resume if the root-hub is allowed + * to suspend. Writing 1 to this undocumented register bit + * disables this feature and restores normal behavior. + */ + writel(EHCI_INSNREG04_DISABLE_UNSUSPEND, EHCI_BASE + EHCI_INSNREG04); + + reg = ULPI_FUNC_CTRL_RESET + /* FUNCTION_CTRL_SET register */ + | (ULPI_SET(ULPI_FUNC_CTRL) << EHCI_INSNREG05_ULPI_REGADD_SHIFT) + /* Write */ + | (2 << EHCI_INSNREG05_ULPI_OPSEL_SHIFT) + /* PORTn */ + | ((port + 1) << EHCI_INSNREG05_ULPI_PORTSEL_SHIFT) + /* start ULPI access*/ + | (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT); + + base = get_timer(0); + + writel(reg, EHCI_BASE + EHCI_INSNREG05_ULPI); + + /* Wait for ULPI access completion */ + while ((readl(EHCI_BASE + EHCI_INSNREG05_ULPI) + & (1 << EHCI_INSNREG05_ULPI_CONTROL_SHIFT))) + if (get_timer(base) > CONFIG_SYS_HZ) { + printf("OMAP4 EHCI error: timeout resetting phy\n"); + return -1; + } + + hccr = (struct ehci_hccr *)(EHCI_BASE); + hcor = (struct ehci_hcor *)((uint32_t) hccr + + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); + return 0; +} + +int omap4_ehci_hcd_stop(void) +{ + unsigned base = get_timer(0); + + writel(OMAP4_UHH_SYSCONFIG_SOFTRESET, UHH_BASE + OMAP_UHH_SYSCONFIG); + +#if 0 + /* We get timeout here */ + while (!(readl(UHH_BASE + OMAP_UHH_SYSSTATUS) & (1 << 0))) + if (get_timer(base) > CONFIG_SYS_HZ) { + printf("OMAP4 EHCI error: reset UHH 0 timeout\n"); + return -ETIMEDOUT; + } + + while (!(readl(UHH_BASE + OMAP_UHH_SYSSTATUS) & (1 << 1))) + if (get_timer(base) > CONFIG_SYS_HZ) { + printf("OMAP4 EHCI error: reset UHH 1 timeout\n"); + return -ETIMEDOUT; + } + + while (!(readl(UHH_BASE + OMAP_UHH_SYSSTATUS) & (1 << 2))) + if (get_timer(base) > CONFIG_SYS_HZ) { + printf("OMAP4 EHCI error: reset UHH 2 timeout\n"); + return -ETIMEDOUT; + } +#endif + + + writel((1 << 1), TLL_BASE + OMAP_USBTLL_SYSCONFIG); + + while (!(readl(TLL_BASE + OMAP_USBTLL_SYSSTATUS) & (1 << 0))) + if (get_timer(base) > CONFIG_SYS_HZ) { + printf("OMAP4 EHCI error: reset TLL timeout\n"); + return -ETIMEDOUT; + } + + /* Disable clocks */ + sr32((void *)0x4a0093e0, 0, 32, 0); + sr32((void *)0x4a009368, 0, 32, 0); + sr32((void *)0x4a0093d0, 0, 32, 0); + sr32((void *)0x4A009358, 0, 32, 0); + + return 0; +}

On Mon, May 9, 2011 at 3:04 PM, Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org wrote:
diff --git a/drivers/usb/host/ehci-omap4.c b/drivers/usb/host/ehci-omap4.c new file mode 100644 index 0000000..19cd286 --- /dev/null +++ b/drivers/usb/host/ehci-omap4.c @@ -0,0 +1,268 @@ +/*
- OMAP4 EHCI port, copied from linux/drivers/usb/host/ehci-omap.c
So the file in linux is for both omap[34] yet here in u-boot it is only for omap4. I admittedly know very little about EHCI internals but it seems to me that it would be nice if this could support both in u-boot.
I see from git history that omap3 support went in some months ago with only some new routines in beagle.c and no new usb files so could some omap usb expert explain.
Thanks, John

On 05/18/2011 09:50 PM, John Rigby wrote:
On Mon, May 9, 2011 at 3:04 PM, Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org wrote:
diff --git a/drivers/usb/host/ehci-omap4.c b/drivers/usb/host/ehci-omap4.c new file mode 100644 index 0000000..19cd286 --- /dev/null +++ b/drivers/usb/host/ehci-omap4.c @@ -0,0 +1,268 @@ +/*
- OMAP4 EHCI port, copied from linux/drivers/usb/host/ehci-omap.c
So the file in linux is for both omap[34] yet here in u-boot it is only for omap4. I admittedly know very little about EHCI internals but it seems to me that it would be nice if this could support both in u-boot.
I see from git history that omap3 support went in some months ago with only some new routines in beagle.c and no new usb files so could some omap usb expert explain.
I am far from an expert. But I saw a previous post for EHCI on omap3 saying "this file is sufficiently specific to be specific for each board". So, I started writing a panda specific board, but found that there was not really much code specific to panda, and most of the code was specific to omap4.
This said, there is more than one way to do it on omap4, the processor can be configured different ways to get EHCI support (as far as I understood the processor even has two different EHCI controllers). So maybe a panda-only file was not a bad idea after all...

Dear Gilles Chanteperdrix,
In message 1304975091-21848-2-git-send-email-gilles.chanteperdrix@xenomai.org you wrote:
As board may need some specific support, implement inner functions to be called by the boards implementaions of ehci_hcd_start, ehci_hcd_stop.
Signed-off-by: Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org
...
- OMAP4 EHCI port, copied from linux/drivers/usb/host/ehci-omap.c
Can you please provide exact reference? Please see http://www.denx.de/wiki/view/U-Boot/Patches#Attributing_Code_Copyrights_Sign bullet # 4
Thanks.
Best regards,
Wolfgang Denk

Signed-off-by: Gilles Chanteperdrix gilles.chanteperdrix@xenomai.org --- board/ti/panda/Makefile | 4 ++- board/ti/panda/ehci-panda.c | 59 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletions(-) create mode 100644 board/ti/panda/ehci-panda.c
diff --git a/board/ti/panda/Makefile b/board/ti/panda/Makefile index 2186403..253567c 100644 --- a/board/ti/panda/Makefile +++ b/board/ti/panda/Makefile @@ -25,7 +25,9 @@ include $(TOPDIR)/config.mk
LIB = $(obj)lib$(BOARD).o
-COBJS := panda.o +COBJS-$(CONFIG_USB_EHCI) += ehci-panda.o + +COBJS := $(COBJS-y) panda.o
SRCS := $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) diff --git a/board/ti/panda/ehci-panda.c b/board/ti/panda/ehci-panda.c new file mode 100644 index 0000000..b1e247c --- /dev/null +++ b/board/ti/panda/ehci-panda.c @@ -0,0 +1,59 @@ +/* + * OMAP4 EHCI port, copied from linux/drivers/usb/host/ehci-omap.c + * + * Copyright (C) 2007-2010 Texas Instruments, Inc. + * Author: Vikram Pandita vikram.pandita@ti.com + * Author: Anand Gadiyar gadiyar@ti.com + */ + +#include <asm/arch/gpio.h> +#include <asm/arch/ehci.h> + +#define GPIO_HUB_POWER 1 +#define GPIO_HUB_NRESET 62 + +int ehci_hcd_init(void) +{ + unsigned long base = get_timer(0); + unsigned reg = 0, port = 0; + int rc; + + /* disable the power to the usb hub prior to init */ + rc = omap_request_gpio(GPIO_HUB_POWER); + if (rc < 0) { + printf("Could not request gpio %d\n", GPIO_HUB_POWER); + return rc; + } + + rc = omap_request_gpio(GPIO_HUB_NRESET); + if (rc < 0) { + printf("Could not request gpio %d\n", GPIO_HUB_NRESET); + omap_free_gpio(GPIO_HUB_POWER); + return rc; + } + + omap_set_gpio_direction(GPIO_HUB_POWER, 0); + omap_set_gpio_dataout(GPIO_HUB_POWER, 0); + omap_set_gpio_direction(GPIO_HUB_NRESET, 0); + omap_set_gpio_dataout(GPIO_HUB_NRESET, 0); + omap_set_gpio_dataout(GPIO_HUB_NRESET, 1); + + rc = omap4_ehci_hcd_init(); + + if (rc < 0) + return rc; + + omap_set_gpio_dataout(GPIO_HUB_POWER, 1); + + return 0; +} + +int ehci_hcd_stop(void) +{ + omap4_ehci_hcd_stop(); + + omap_set_gpio_dataout(GPIO_HUB_POWER, 0); + omap_set_gpio_dataout(GPIO_HUB_NRESET, 0); + omap_free_gpio(GPIO_HUB_POWER); + omap_free_gpio(GPIO_HUB_NRESET); +}

On Mon, May 9, 2011 at 2:02 PM, Gilles Chanteperdrix < gilles.chanteperdrix@xenomai.org> wrote:
Hi,
I am trying to tftpboot the panda board, this basically works, but I still have some issues.
The panda board uses an SMSC95xx chip, and so requires USB2.0
Using the u-boot git head, we have support for network adapters over USB, and the patches from Simon Glass, we get support for the ethernet chip. So, the only missing piece of the puzzle is USB EHCI for OMAP4/Panda.
I tried to implement it, the patches will follow shortly, but have several remaining issues:
- the EHCI stop routine, implemented as in the Linux kernel driver, has
timeouts when trying to wait for the UHH reset;
- the SMSC95XX is unstable, if I start USB, stop USB, then start again,
the SMSC95XX initialization hangs, this does not happen without this driver
This is a bug in USB net I think, rather than just this driver. I have not looked at it yet but patches are welcome!
- if I launch bootp, and say, the server does not answer to the bootp
protocol, the smsc95xx driver does not seem to be able to recover from the first timeout, any further attempt causes a timeout.
This may or may not be related - again I have seen this and it also happens with Asix.
Regards, Simon
Regards.
-- Gilles. _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
participants (4)
-
Gilles Chanteperdrix
-
John Rigby
-
Simon Glass
-
Wolfgang Denk