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

Kuo-Jung Su dantesu at gmail.com
Mon Apr 29 05:10:19 CEST 2013


2013/4/26 Marek Vasut <marex at denx.de>:
> 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?
>

1. The reserved registers (0x1C - 0x3F) and CONFIGFLAG (0x40) register
    are not only un-implemented, but also removed from its register address
    space, which means we have to update the 'struct ehci_hcor' of ehci.h

2. FUSBH200/FOTG210 doesn't properly follow the ECHI for ISOC implementations.
    (It should be a hardware bug, but no one wants to fix it.)

I'll add these description to commit log at next patch.

>> 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?
>

root hub only.

>> +     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?
>
> [...]
>

Sorry for my laziness, they'll be fixed later.

>> +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?
>

Sorry for my laziness, they'll be fixed later.

>> +     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 ?
>

No, it's surely a TDI design, although we use private registers for
speed detection
(see ehci_hcd_port_speed()) rather then BIT26-27 of PORTSC registers.

>>       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 */
>
> [...]



--
Best wishes,
Kuo-Jung Su


More information about the U-Boot mailing list