From patchwork Thu May 9 03:20:43 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: 242702 X-Patchwork-Delegate: marek.vasut@gmail.com 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 4714A2C00E1 for ; Thu, 9 May 2013 13:19:53 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0CD7F4A128; Thu, 9 May 2013 05:19:51 +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 H2zKPWWtLP9i; Thu, 9 May 2013 05:19:50 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 310474A131; Thu, 9 May 2013 05:19:31 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 5D3834A119 for ; Thu, 9 May 2013 05:19:25 +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 CGbTpBm4+hcN for ; Thu, 9 May 2013 05:19:20 +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-da0-f51.google.com (mail-da0-f51.google.com [209.85.210.51]) by theia.denx.de (Postfix) with ESMTPS id 405BE4A11B for ; Thu, 9 May 2013 05:19:12 +0200 (CEST) Received: by mail-da0-f51.google.com with SMTP id h15so1343533dan.10 for ; Wed, 08 May 2013 20:19:10 -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=t3ho4++dRx017yU6yc3xCXuQYtFUldITkNwOV/xQhVM=; b=JPxpabOA5tRq9Ozydz1CBIWmJ8aumcrScpOKYauoMbmy3GzFldKkJdjZWAO1IuRExM 5+SnmZFSbYgjQEFM67VdAW4+7+tzXTysy3sI5JwkReB9gmh08Gf+wzewwxBu+eLXMIIR KS9sn+cdD5MTkq4fpGGENXebnwsNVHOS00iB3ICo+ZRfcGZhwbt9/Unc/nRWchp7lDN4 j71lJaM/G+wcwpbgK7E10foNjQ0kiuoG00+LO8szM6XIkpD/SsVT31LDcLkAAbwJpker FX8QtJOe4TsC6kxwE0qCzTFkoHf+A2aIN4BSUFORZQxJpPHuWV2ylFDz6o/wa80yd9AE +k7g== X-Received: by 10.68.209.232 with SMTP id mp8mr10462910pbc.44.1368069550687; Wed, 08 May 2013 20:19:10 -0700 (PDT) Received: from localhost.localdomain ([220.132.37.35]) by mx.google.com with ESMTPSA id ag4sm1131452pbc.20.2013.05.08.20.19.08 for (version=TLSv1 cipher=DES-CBC3-SHA bits=168/168); Wed, 08 May 2013 20:19:10 -0700 (PDT) From: Kuo-Jung Su To: u-boot@lists.denx.de Date: Thu, 9 May 2013 11:20:43 +0800 Message-Id: <1368069645-14582-3-git-send-email-dantesu@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1368069645-14582-1-git-send-email-dantesu@gmail.com> References: <1368069645-14582-1-git-send-email-dantesu@gmail.com> In-Reply-To: <1367907970-11903-2-git-send-email-dantesu@gmail.com> References: <1367907970-11903-2-git-send-email-dantesu@gmail.com> Cc: Marek Vasut , Kuo-Jung Su Subject: [U-Boot] [PATCH v5 2/4] usb: ehci: add weak-aliased functions to portsc & tdi 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 There is at least one non-EHCI compliant controller (i.e. Faraday EHCI) known to implement a non-standard TDI stuff. Futhermore, it not only leave reserved and CONFIGFLAG registers un-implemented but also has their address spaces removed. And thus, we need weak-aliased functions to both TDI stuff and PORTSC registers for interface abstraction. Signed-off-by: Kuo-Jung Su CC: Marek Vasut --- Changes for v5: - Split up from Faraday EHCI patch Changes for v2 - v4: - See 'usb: ehci: add Faraday USB 2.0 EHCI support' drivers/usb/host/ehci-hcd.c | 100 +++++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 36 deletions(-) -- 1.7.9.5 diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c816878..b334173 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -117,10 +117,50 @@ static struct descriptor { }; #if defined(CONFIG_EHCI_IS_TDI) -#define ehci_is_TDI() (1) -#else -#define ehci_is_TDI() (0) +# define ehci_is_TDI() (1) + +/* put TDI/ARC silicon into EHCI mode */ +void __ehci_tdi_reset(struct ehci_hcor *hcor) +{ + uint32_t tmp, *reg_ptr; + + reg_ptr = (uint32_t *)((uint8_t *) + USBMODE); + tmp = ehci_readl(reg_ptr); + tmp |= USBMODE_CM_HC; +#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) + tmp |= USBMODE_BE; #endif + ehci_writel(reg_ptr, tmp); +} + +void ehci_tdi_reset(struct ehci_hcor *hcor) + __attribute__((weak, alias("__ehci_tdi_reset"))); + +int __ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc) +{ + int ret = 0; + + switch (PORTSC_PSPD(portsc)) { + case PORTSC_PSPD_FS: + break; + case PORTSC_PSPD_LS: + ret = USB_PORT_STAT_LOW_SPEED; + break; + case PORTSC_PSPD_HS: + default: + ret = USB_PORT_STAT_HIGH_SPEED; + break; + } + + return ret; +} + +int ehci_port_speed(struct ehci_hcor *hcor, unsigned int portsc) + __attribute__((weak, alias("__ehci_port_speed"))); + +#else /* CONFIG_EHCI_IS_TDI */ +# define ehci_is_TDI() (0) +#endif /* CONFIG_EHCI_IS_TDI */ void __ehci_powerup_fixup(uint32_t *status_reg, uint32_t *reg) { @@ -149,8 +189,6 @@ static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) static int ehci_reset(int index) { uint32_t cmd; - uint32_t tmp; - uint32_t *reg_ptr; int ret = 0; cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); @@ -163,15 +201,8 @@ static int ehci_reset(int index) goto out; } - if (ehci_is_TDI()) { - reg_ptr = (uint32_t *)((u8 *)ehcic[index].hcor + USBMODE); - tmp = ehci_readl(reg_ptr); - tmp |= USBMODE_CM_HC; -#if defined(CONFIG_EHCI_MMIO_BIG_ENDIAN) - tmp |= USBMODE_BE; -#endif - ehci_writel(reg_ptr, tmp); - } + if (ehci_is_TDI()) + ehci_tdi_reset(ehcic[index].hcor); #ifdef CONFIG_USB_EHCI_TXFIFO_THRESH cmd = ehci_readl(&ehcic[index].hcor->or_txfilltuning); @@ -597,6 +628,18 @@ static inline int min3(int a, int b, int c) return a; } +uint32_t *__ehci_get_portsc_register(struct ehci_hcor *hcor, int port) +{ + if (port >= CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { + printf("The request port(%d) is not configured\n", port); + return NULL; + } + + return (uint32_t *)&hcor->or_portsc[port]; +} +uint32_t *ehci_get_portsc_register(struct ehci_hcor *hcor, int port) + __attribute__((weak, alias("__ehci_get_portsc_register"))); + int ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, int length, struct devrequest *req) @@ -609,13 +652,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, uint32_t *status_reg; struct ehci_ctrl *ctrl = dev->controller; - if (le16_to_cpu(req->index) > CONFIG_SYS_USB_EHCI_MAX_ROOT_PORTS) { - printf("The request port(%d) is not configured\n", - le16_to_cpu(req->index) - 1); + status_reg = ehci_get_portsc_register(ctrl->hcor, + le16_to_cpu(req->index) - 1); + if (!status_reg) return -1; - } - status_reg = (uint32_t *)&ctrl->hcor->or_portsc[ - le16_to_cpu(req->index) - 1]; srclen = 0; debug("req=%u (%#x), type=%u (%#x), value=%u, index=%u\n", @@ -709,23 +749,10 @@ ehci_submit_root(struct usb_device *dev, unsigned long pipe, void *buffer, tmpbuf[0] |= USB_PORT_STAT_RESET; if (reg & EHCI_PS_PP) tmpbuf[1] |= USB_PORT_STAT_POWER >> 8; - - if (ehci_is_TDI()) { - switch (PORTSC_PSPD(reg)) { - case PORTSC_PSPD_FS: - break; - case PORTSC_PSPD_LS: - tmpbuf[1] |= USB_PORT_STAT_LOW_SPEED >> 8; - break; - case PORTSC_PSPD_HS: - default: - tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - break; - } - } else { + if (ehci_is_TDI()) + tmpbuf[1] |= ehci_port_speed(ctrl->hcor, reg) >> 8; + else tmpbuf[1] |= USB_PORT_STAT_HIGH_SPEED >> 8; - } - if (reg & EHCI_PS_CSC) tmpbuf[2] |= USB_PORT_STAT_C_CONNECTION; if (reg & EHCI_PS_PEC) @@ -954,6 +981,7 @@ int usb_lowlevel_init(int index, void **controller) cmd = ehci_readl(&ehcic[index].hcor->or_configflag); cmd |= FLAG_CF; ehci_writel(&ehcic[index].hcor->or_configflag, cmd); + /* unblock posted write */ cmd = ehci_readl(&ehcic[index].hcor->or_usbcmd); mdelay(5);