From patchwork Thu Apr 18 09:25:36 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuo-Jung Su X-Patchwork-Id: 237579 X-Patchwork-Delegate: albert.aribaud@free.fr Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 774912C0151 for ; Thu, 18 Apr 2013 19:28:19 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B09734A35A; Thu, 18 Apr 2013 11:27:03 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id P8owBaJmoM0d; Thu, 18 Apr 2013 11:27:03 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id DA9784A358; Thu, 18 Apr 2013 11:26:38 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 375F74A319 for ; Thu, 18 Apr 2013 11:26:05 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id l0BUncokNJIE for ; Thu, 18 Apr 2013 11:26:03 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-pa0-f48.google.com (mail-pa0-f48.google.com [209.85.220.48]) by theia.denx.de (Postfix) with ESMTPS id 3F1974A32A for ; Thu, 18 Apr 2013 11:25:32 +0200 (CEST) Received: by mail-pa0-f48.google.com with SMTP id lj1so1460359pab.35 for ; Thu, 18 Apr 2013 02:25:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references:in-reply-to:references; bh=JN0GbBEKISeSTWhTmV/Fsk1fW7XI+7TMEyJqx/lXn+c=; b=RRc0QiY23ZyHFAy7zMduTW3gVq0MXNilNJ/Z381gGEEHrfx28cUQLekfi6uO6I5uZe 1/4eleB4uvrZDtsWCpBgPQdubcYhFCsoqYA6uxeRR0nbxgf3VLObC7DkTBYudR1q6jnU LS9Bkh4nf9rKbk8kyOfOFFCalAd0nxXuVamKLaOqIDOaAUQY7hE3MCG+aVwA8MFED70O J4H5ulNYsnG8JWu6xgDleAzfuQdzG9zI7qWKhlSYoAW55PyDbV1tmbuGpsOCp0KaxagG vWRX0Ee1EfzkBiF4laljij32+O675PgHeWlrAog3ujU+IF4oq3Q8S32OWftgKYGjgDVb SeHw== X-Received: by 10.66.100.196 with SMTP id fa4mr12542197pab.140.1366277130502; Thu, 18 Apr 2013 02:25:30 -0700 (PDT) Received: from localhost.localdomain ([220.132.37.35]) by mx.google.com with ESMTPS id xl10sm10280496pac.15.2013.04.18.02.25.28 (version=TLSv1 cipher=DES-CBC3-SHA bits=168/168); Thu, 18 Apr 2013 02:25:29 -0700 (PDT) From: Kuo-Jung Su To: u-boot@lists.denx.de Date: Thu, 18 Apr 2013 17:25:36 +0800 Message-Id: <1366277139-29728-10-git-send-email-dantesu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1366277139-29728-1-git-send-email-dantesu@gmail.com> References: <1366277139-29728-1-git-send-email-dantesu@gmail.com> In-Reply-To: <1364540788-13943-2-git-send-email-dantesu@gmail.com> References: <1364540788-13943-2-git-send-email-dantesu@gmail.com> Cc: Marek Vasut , Kuo-Jung Su Subject: [U-Boot] [PATCH v2 09/12] usb: ehci: add Faraday USB 2.0 EHCI support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de From: Kuo-Jung Su This patch add supports to both Faraday FUSBH200 and FOTG210, these controllers slightly differ from standard EHCI specification. Signed-off-by: Kuo-Jung Su CC: Marek Vasut --- common/usb_hub.c | 5 ++ drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-faraday.c | 139 +++++++++++++++++++++++++++++++++++++++ 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, 260 insertions(+) create mode 100644 drivers/usb/host/ehci-faraday.c create mode 100644 include/usb/fotg210.h create mode 100644 include/usb/fusbh200.h -- 1.7.9.5 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 */ + 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..804e058 --- /dev/null +++ b/drivers/usb/host/ehci-faraday.c @@ -0,0 +1,139 @@ +/* + * Faraday USB 2.0 EHCI Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su + * + * 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 +#include +#include +#include +#include + +#include "ehci.h" + +union ehci_faraday_regs { + struct fusbh200_regs usb; + struct fotg210_regs otg; +}; + +struct ehci_faraday_chip { + union ehci_faraday_regs *iobase; +}; + +static struct ehci_faraday_chip hcd_list[] = { +#ifdef CONFIG_USB_EHCI_BASE + { .iobase = (union ehci_faraday_regs *)CONFIG_USB_EHCI_BASE, }, +#endif +#ifdef CONFIG_USB_EHCI_BASE1 + { .iobase = (union ehci_faraday_regs *)CONFIG_USB_EHCI_BASE1, }, +#endif +#ifdef CONFIG_USB_EHCI_BASE2 + { .iobase = (union ehci_faraday_regs *)CONFIG_USB_EHCI_BASE2, }, +#endif +#ifdef CONFIG_USB_EHCI_BASE3 + { .iobase = (union ehci_faraday_regs *)CONFIG_USB_EHCI_BASE3, }, +#endif +}; + +#define HCD_READ(r) le32_to_cpu(readl(r)) +#define HCD_WRITE(v, r) writel(cpu_to_le32(v), r) +#define HCD_SETBITS(m, r) setbits_le32(r, m) +#define HCD_CLRBITS(m, r) clrbits_le32(r, m) + +static inline int ehci_hci_fotg2xx(struct ehci_hccr *hccr) +{ + union ehci_faraday_regs *regs = (void *)hccr; + return !HCD_READ(®s->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_faraday_chip *hcd = &hcd_list[index]; + union ehci_faraday_regs *regs = hcd->iobase; + struct ehci_hccr *hccr; + struct ehci_hcor *hcor; + + hccr = (struct ehci_hccr *)®s->usb.hccr; + hcor = (struct ehci_hcor *)®s->usb.hcor; + + if (ehci_hci_fotg2xx(hccr)) { + /* A-device bus reset */ + /* ... Power off A-device */ + HCD_SETBITS(BIT_MASK(5), ®s->otg.otgcsr); + /* ... Drop vbus and bus traffic */ + HCD_CLRBITS(BIT_MASK(4), ®s->otg.otgcsr); + mdelay(1); + /* ... Power on A-device */ + HCD_CLRBITS(BIT_MASK(5), ®s->otg.otgcsr); + /* ... Drive vbus and bus traffic */ + HCD_SETBITS(BIT_MASK(4), ®s->otg.otgcsr); + mdelay(1); + /* Disable OTG & device interrupts, interrupt=level-high */ + HCD_WRITE(0x0b, ®s->otg.imr); + /* Clear all interrupt status */ + HCD_WRITE(0x07, ®s->otg.isr); + } else { + /* Interrupt=level-high */ + HCD_SETBITS(BIT_MASK(3), ®s->usb.bmcsr); + /* VBUS on */ + HCD_CLRBITS(BIT_MASK(4), ®s->usb.bmcsr); + /* Disable all interrupts */ + HCD_WRITE(0x00, ®s->usb.bmier); + HCD_WRITE(0x1f, ®s->usb.bmisr); + } + + *ret_hccr = hccr; + *ret_hcor = hcor; + + return 0; +} + +/* + * Destroy the appropriate control structures corresponding + * the the EHCI host controller. + */ +int ehci_hcd_stop(int index) +{ + return 0; +} + +int ehci_hcd_port_speed(struct ehci_hccr *hccr) +{ + int ret = 0; + int speed; + union ehci_faraday_regs *regs = (void *)hccr; + + if (ehci_hci_fotg2xx(hccr)) + speed = (HCD_READ(®s->otg.otgcsr) >> 22) & 0x03; + else + speed = (HCD_READ(®s->usb.bmcsr) >> 9) & 0x03; + + 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 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 */ #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); @@ -711,6 +715,9 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; if (ehci_is_TDI()) { +#ifdef CONFIG_USB_EHCI_FARADAY + tmpbuf[1] |= ehci_hcd_port_speed(ctrl->hccr) >> 8; +#else switch (PORTSC_PSPD(reg)) { case PORTSC_PSPD_FS: break; @@ -722,6 +729,7 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; break; } +#endif } else { tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; } @@ -950,10 +958,13 @@ int usb_lowlevel_init(int index, void **controller) cmd |= CMD_RUN; ehci_writel(&ehcic[index].hcor->or_usbcmd, cmd); +#ifndef CONFIG_USB_EHCI_FARADAY /* take control over the ports */ cmd = ehci_readl(&ehcic[index].hcor->or_configflag); cmd |= FLAG_CF; ehci_writel(&ehcic[index].hcor->or_configflag, cmd); +#endif + /* unblock posted write */ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); mdelay(5); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index d090f0a..9309ede 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -82,6 +82,7 @@ struct ehci_hcor { uint32_t or_periodiclistbase; uint32_t or_asynclistaddr; uint32_t _reserved_0_; +#ifndef CONFIG_USB_EHCI_FARADAY uint32_t or_burstsize; uint32_t or_txfilltuning; #define TXFIFO_THRESH_MASK (0x3f << 16) @@ -89,6 +90,7 @@ struct ehci_hcor { uint32_t _reserved_1_[6]; uint32_t or_configflag; #define FLAG_CF (1 << 0) /* true: we'll support "high speed" */ +#endif /* #ifndef CONFIG_USB_EHCI_FARADAY */ uint32_t or_portsc[CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS]; #define PORTSC_PSPD(x) (((x) >> 26) & 0x3) #define PORTSC_PSPD_FS 0x0 @@ -255,5 +257,8 @@ struct QH { /* Low level init functions */ int ehci_hcd_init(int index, struct ehci_hccr **hccr, struct ehci_hcor **hcor); int ehci_hcd_stop(int index); +#ifdef CONFIG_USB_EHCI_FARADAY +int ehci_hcd_port_speed(struct ehci_hccr *hccr); +#endif #endif /* USB_EHCI_H */ diff --git a/include/usb/fotg210.h b/include/usb/fotg210.h new file mode 100644 index 0000000..0249afd --- /dev/null +++ b/include/usb/fotg210.h @@ -0,0 +1,71 @@ +/* + * Faraday USB 2.0 OTG Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su + * + * 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. + */ + +#ifndef _FOTG210_H +#define _FOTG210_H + +struct fotg210_regs { + /* USB Host Controller */ + struct { + uint32_t data[4]; + } hccr; /* 0x00 - 0x0f: hccr */ + struct { + uint32_t data[9]; + } hcor; /* 0x10 - 0x33: hcor */ + uint32_t rsvd1[3]; + uint32_t msicr; /* 0x40: Miscellaneous Register */ + uint32_t rsvd2[15]; + /* USB OTG Controller */ + uint32_t otgcsr;/* 0x80: OTG Control Status Register */ + uint32_t otgisr;/* 0x84: OTG Interrupt Status Register */ + uint32_t otgier;/* 0x88: OTG Interrupt Enable Register */ + uint32_t rsvd3[13]; + uint32_t isr; /* 0xC0: Global Interrupt Status Register */ + uint32_t imr; /* 0xC4: Global Interrupt Mask Register */ + uint32_t rsvd4[14]; + /* USB Device Controller */ + uint32_t dev_ctrl;/* 0x100: Device Control Register */ + uint32_t dev_addr;/* 0x104: Device Address Register */ + uint32_t dev_test;/* 0x108: Device Test Register */ + uint32_t sof_fnr; /* 0x10c: SOF Frame Number Register */ + uint32_t sof_mtr; /* 0x110: SOF Mask Timer Register */ + uint32_t phy_tmsr;/* 0x114: PHY Test Mode Selector Register */ + uint32_t rsvd5[1]; + uint32_t cxsr; /* 0x11c: CX Status Register */ + uint32_t cxfifo;/* 0x120: CX FIFO Register */ + uint32_t idle; /* 0x124: IDLE Counter Register */ + uint32_t rsvd6[2]; + uint32_t gimr; /* 0x130: Group Interrupt Mask Register */ + uint32_t gimr0; /* 0x134: Group Interrupt Mask Register 0 */ + uint32_t gimr1; /* 0x138: Group Interrupt Mask Register 1 */ + uint32_t gimr2; /* 0x13c: Group Interrupt Mask Register 2 */ + uint32_t gisr; /* 0x140: Group Interrupt Status Register */ + uint32_t gisr0; /* 0x144: Group Interrupt Status Register 0 */ + uint32_t gisr1; /* 0x148: Group Interrupt Status Register 1 */ + uint32_t gisr2; /* 0x14c: Group Interrupt Status Register 2 */ + uint32_t rxzlp; /* 0x150: Receive Zero-Length-Packet Register */ + uint32_t txzlp; /* 0x154: Transfer Zero-Length-Packet Register */ + uint32_t ioseasr;/* 0x158: ISOC Error/Abort Status Register */ + uint32_t rsvd7[1]; + uint32_t iep[8]; /* 0x160 - 0x17f: IN Endpoint Register */ + uint32_t oep[8]; /* 0x180 - 0x19f: OUT Endpoint Register */ + uint32_t epmap14;/* 0x1a0: Endpoint Map Register (EP1 ~ 4) */ + uint32_t epmap58;/* 0x1a4: Endpoint Map Register (EP5 ~ 8) */ + uint32_t fifomap;/* 0x1a8: FIFO Map Register */ + uint32_t fifocfg; /* 0x1ac: FIFO Configuration Register */ + uint32_t fifocsr[4];/* 0x1b0 - 0x1bf: FIFO Control Status Register */ + uint32_t dma_fifo; /* 0x1c0: DMA Target FIFO Register */ + uint32_t rsvd8[1]; + uint32_t dma_ctrl; /* 0x1c8: DMA Control Register */ + uint32_t dma_addr; /* 0x1cc: DMA Address Register */ + uint32_t dma_data; /* 0x1d0: DMA CX Data Register */ +}; + +#endif diff --git a/include/usb/fusbh200.h b/include/usb/fusbh200.h new file mode 100644 index 0000000..2d514b8 --- /dev/null +++ b/include/usb/fusbh200.h @@ -0,0 +1,28 @@ +/* + * Faraday USB 2.0 EHCI Controller + * + * (C) Copyright 2010 Faraday Technology + * Dante Su + * + * 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. + */ + +#ifndef _FUSBH200_H +#define _FUSBH200_H + +struct fusbh200_regs { + struct { + uint32_t data[4]; + } hccr; /* 0x00 - 0x0f: hccr */ + struct { + uint32_t data[9]; + } hcor; /* 0x10 - 0x33: hcor */ + uint32_t easstr;/* 0x34: EOF&Async. Schedule Sleep Timer Register */ + uint32_t rsvd[2]; + uint32_t bmcsr; /* 0x40: Bus Monitor Control Status Register */ + uint32_t bmisr; /* 0x44: Bus Monitor Interrupt Status Register */ + uint32_t bmier; /* 0x48: Bus Monitor Interrupt Enable Register */ +}; + +#endif