[U-Boot] [PATCH v3 08/11] usb: ehci: add Faraday USB 2.0 EHCI support

Marek Vasut marex at denx.de
Fri Apr 26 14:19:22 CEST 2013


Dear Kuo-Jung Su,

> From: Kuo-Jung Su <dantesu at faraday-tech.com>
> 
> This patch add supports to both Faraday FUSBH200 and FOTG210,
> these controllers slightly differ from standard EHCI specification.

How do they differ?

> Signed-off-by: Kuo-Jung Su <dantesu at faraday-tech.com>
> CC: Marek Vasut <marex at denx.de>
> ---
>  common/usb_hub.c                |    5 ++
>  drivers/usb/host/Makefile       |    1 +
>  drivers/usb/host/ehci-faraday.c |  122
> +++++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci-hcd.c     | 
>  11 ++++
>  drivers/usb/host/ehci.h         |    5 ++
>  include/usb/fotg210.h           |   71 +++++++++++++++++++++++
>  include/usb/fusbh200.h          |   28 +++++++++
>  7 files changed, 243 insertions(+)
>  create mode 100644 drivers/usb/host/ehci-faraday.c
>  create mode 100644 include/usb/fotg210.h
>  create mode 100644 include/usb/fusbh200.h
> 
> diff --git a/common/usb_hub.c b/common/usb_hub.c
> index b5eeb62..26d66b8 100644
> --- a/common/usb_hub.c
> +++ b/common/usb_hub.c
> @@ -375,6 +375,11 @@ static int usb_hub_configure(struct usb_device *dev)
>  		return -1;
>  	}
> 
> +#ifdef CONFIG_USB_EHCI_FARADAY
> +	/* Faraday USB 2.0 EHCI chips need a long long delay here */

Why? Do they need it only for root hub or for all the hub down the road as well?

> +	mdelay(250);
> +#endif
> +
>  	if (usb_get_hub_status(dev, buffer) < 0) {
>  		USB_HUB_PRINTF("usb_hub_configure: failed to get Status %lX\n",
>  				dev->status);
> diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
> index 87a5970..98f2a10 100644
> --- a/drivers/usb/host/Makefile
> +++ b/drivers/usb/host/Makefile
> @@ -43,6 +43,7 @@ COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-mpc512x.o
>  else
>  COBJS-$(CONFIG_USB_EHCI_FSL) += ehci-fsl.o
>  endif
> +COBJS-$(CONFIG_USB_EHCI_FARADAY) += ehci-faraday.o
>  COBJS-$(CONFIG_USB_EHCI_EXYNOS) += ehci-exynos.o
>  COBJS-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o
>  COBJS-$(CONFIG_USB_EHCI_MXS) += ehci-mxs.o
> diff --git a/drivers/usb/host/ehci-faraday.c
> b/drivers/usb/host/ehci-faraday.c new file mode 100644
> index 0000000..adf57d1
> --- /dev/null
> +++ b/drivers/usb/host/ehci-faraday.c
> @@ -0,0 +1,122 @@
> +/*
> + * Faraday USB 2.0 EHCI Controller
> + *
> + * (C) Copyright 2010 Faraday Technology
> + * Dante Su <dantesu at faraday-tech.com>
> + *
> + * This file is released under the terms of GPL v2 and any later version.
> + * See the file COPYING in the root directory of the source tree for
> details. + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <usb.h>
> +#include <usb/fusbh200.h>
> +#include <usb/fotg210.h>
> +
> +#include "ehci.h"
> +
> +union ehci_faraday_regs {
> +	struct fusbh200_regs usb;
> +	struct fotg210_regs  otg;
> +};
> +
> +static inline int ehci_hci_fotg2xx(struct ehci_hccr *hccr)
> +{
> +	union ehci_faraday_regs __iomem *regs = (void *)hccr;
> +	return !readl(&regs->usb.easstr);
> +}
> +
> +/*
> + * Create the appropriate control structures to manage
> + * a new EHCI host controller.
> + */
> +int ehci_hcd_init(int index, struct ehci_hccr **ret_hccr,
> +		struct ehci_hcor **ret_hcor)
> +{
> +	struct ehci_hccr *hccr;
> +	struct ehci_hcor *hcor;
> +	union ehci_faraday_regs __iomem *regs;
> +#ifdef CONFIG_USB_EHCI_BASE_LIST
> +	uint32_t base_list[] = CONFIG_USB_EHCI_BASE_LIST;
> +#else
> +	uint32_t base_list[] = { CONFIG_USB_EHCI_BASE };
> +#endif
> +
> +	if (index < 0 || index >= ARRAY_SIZE(base_list))
> +		return -1;
> +	regs = (void __iomem *)base_list[index];
> +	hccr = (struct ehci_hccr *)&regs->usb.hccr;
> +	hcor = (struct ehci_hcor *)&regs->usb.hcor;
> +
> +	if (ehci_hci_fotg2xx(hccr)) {
> +		/* A-device bus reset */
> +		/* ... Power off A-device */
> +		setbits_le32(&regs->otg.otgcsr, BIT_MASK(5));

Do these bits not have names?

[...]

> +int ehci_hcd_port_speed(struct ehci_hccr *hccr)
> +{
> +	int ret = 0;
> +	int speed;
> +	union ehci_faraday_regs __iomem *regs = (void *)hccr;
> +
> +	if (ehci_hci_fotg2xx(hccr))
> +		speed = (readl(&regs->otg.otgcsr) >> 22) & 0x03;
> +	else
> +		speed = (readl(&regs->usb.bmcsr) >>  9) & 0x03;

Same here, what're these magic numbers?

> +	switch (speed) {
> +	case 0:    /* full speed */
> +		break;
> +
> +	case 1:    /* low  speed */
> +		ret = USB_PORT_STAT_LOW_SPEED;
> +		break;
> +
> +	case 2:    /* high speed */
> +		ret = USB_PORT_STAT_HIGH_SPEED;
> +		break;
> +
> +	default:
> +		printf("ehci-faraday: invalid device speed\n");
> +		break;
> +	}
> +
> +	return ret;
> +}
> diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
> index c816878..450d217 100644
> --- a/drivers/usb/host/ehci-hcd.c
> +++ b/drivers/usb/host/ehci-hcd.c
> @@ -149,8 +149,10 @@ static int handshake(uint32_t *ptr, uint32_t mask,
> uint32_t done, int usec) static int ehci_reset(int index)
>  {
>  	uint32_t cmd;
> +#ifndef CONFIG_USB_EHCI_FARADAY
>  	uint32_t tmp;
>  	uint32_t *reg_ptr;
> +#endif
>  	int ret = 0;
> 
>  	cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd);
> @@ -163,6 +165,7 @@ static int ehci_reset(int index)
>  		goto out;
>  	}
> 
> +#ifndef CONFIG_USB_EHCI_FARADAY

Wouldn't it suffice to set your EHCI is not TDI ?

>  	if (ehci_is_TDI()) {
>  		reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE);
>  		tmp = ehci_readl(reg_ptr);
> @@ -172,6 +175,7 @@ static int ehci_reset(int index)
>  #endif
>  		ehci_writel(reg_ptr, tmp);
>  	}
> +#endif	/* !CONFIG_USB_EHCI_FARADAY */

[...]


More information about the U-Boot mailing list