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

Marek Vasut
2013-04-26T12:19:22Z

Dear Kuo-Jung Su,

> From: Kuo-Jung Su <dantesu@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@faraday-tech.com>
> CC: Marek Vasut <marex@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@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 */ …