From patchwork Thu May 4 13:47:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jorge Ramirez-Ortiz X-Patchwork-Id: 98537 Delivered-To: patch@linaro.org Received: by 10.140.89.200 with SMTP id v66csp596523qgd; Thu, 4 May 2017 06:49:12 -0700 (PDT) X-Received: by 10.80.177.246 with SMTP id n51mr29150589edd.14.1493905752348; Thu, 04 May 2017 06:49:12 -0700 (PDT) Return-Path: Received: from lists.denx.de (dione.denx.de. [81.169.180.215]) by mx.google.com with ESMTP id g31si1340164edd.259.2017.05.04.06.49.12; Thu, 04 May 2017 06:49:12 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) client-ip=81.169.180.215; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of u-boot-bounces@lists.denx.de designates 81.169.180.215 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.denx.de (Postfix, from userid 105) id ED4E6C21C61; Thu, 4 May 2017 13:49:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 41AF3C21C3E; Thu, 4 May 2017 13:48:18 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id AD358C21BE6; Thu, 4 May 2017 13:47:17 +0000 (UTC) Received: from mail-wr0-f181.google.com (mail-wr0-f181.google.com [209.85.128.181]) by lists.denx.de (Postfix) with ESMTPS id 447B8C21BE5 for ; Thu, 4 May 2017 13:47:17 +0000 (UTC) Received: by mail-wr0-f181.google.com with SMTP id l9so8210442wre.1 for ; Thu, 04 May 2017 06:47:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=27rYhUzr2s/rtHZptwrf0aVFtQ4uXM20gGjNjgFqnEg=; b=Qn+5BpPNiC9NUfpsxDc7myNLdPPnjJiMP7mg5IpuXOaYeTrY926Mfi3UGwLms2BMTu KtgoYa2VGgijIF8eaxWE+Aiyc4ln2PnOdmgj/dCMxugzsKhTcVLVBgRqVCMM7C6GVJM/ RYVnD81aL+58pmQ0Y2unMr9rJ7ugb4P6RruyA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=27rYhUzr2s/rtHZptwrf0aVFtQ4uXM20gGjNjgFqnEg=; b=BtI1U2OyPUZbAheRZdp2y/X1HWbmJDAVtkzLJo2KZ5GjLEly3GCFdnNZNqCmUs0XnG Vcdu/D88+If8qUvqZEmNNL23eO5miHTBsWfJaFezbL7QCwEEwK9NdbvJN3DgfpWJssF4 CTWZ7L+j+bgk7/UQoQTEIebEYlJxGiRcOt98sS9MN6J0Iy1ACD/ZTN5ungWpKXLfXf7V q86uTYT1los8v89Sdciw87hKdsvpDFQNISR4AAV7+cruJhG9rZ5yGSTOLZ3SR146hUBV yCuHbQIKbtnbg3tNSd/lugAW0DEa7x4i/Y3aI3n9Qp8MRiMrfBAgm16HCnTISGwBTDHn cB5g== X-Gm-Message-State: AN3rC/41irogs2OapsqWsxNGu/nYvLdoZXqP1xW8XyQQhPWeNYBw1Jh8 2oZ5nIA7PYEKPCXK X-Received: by 10.223.150.74 with SMTP id c10mr27845076wra.85.1493905636825; Thu, 04 May 2017 06:47:16 -0700 (PDT) Received: from igloo.80.58.61.254 (161.red-88-1-72.dynamicip.rima-tde.net. [88.1.72.161]) by smtp.gmail.com with ESMTPSA id l29sm1093753wmi.8.2017.05.04.06.47.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 04 May 2017 06:47:16 -0700 (PDT) From: Jorge Ramirez-Ortiz To: jorge.ramirez-ortiz@linaro.org, u-boot@lists.denx.de Date: Thu, 4 May 2017 15:47:07 +0200 Message-Id: <1493905630-8788-2-git-send-email-jorge.ramirez-ortiz@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1493905630-8788-1-git-send-email-jorge.ramirez-ortiz@linaro.org> References: <1493905630-8788-1-git-send-email-jorge.ramirez-ortiz@linaro.org> X-Mailman-Approved-At: Thu, 04 May 2017 13:48:16 +0000 Cc: daniel.thompson@linaro.org, elder@linaro.org Subject: [U-Boot] [PATCH 2/5] driver: usb: add EHCI driver for hi3787cv200 SoC X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Signed-off-by: Jorge Ramirez-Ortiz --- .../arm/include/asm/arch-hi3798cv200/hi3798cv200.h | 93 ++++++++++ drivers/usb/host/Kconfig | 6 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-hi3798cv200.c | 196 +++++++++++++++++++++ 4 files changed, 296 insertions(+) create mode 100644 arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h create mode 100644 drivers/usb/host/ehci-hi3798cv200.c diff --git a/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h b/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h new file mode 100644 index 0000000..c67fda1 --- /dev/null +++ b/arch/arm/include/asm/arch-hi3798cv200/hi3798cv200.h @@ -0,0 +1,93 @@ +/* + * (C) Copyright 2017 Linaro + * Jorge Ramirez-Ortiz + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __HI3798cv200_H__ +#define __HI3798cv200_H__ + +#define REG_BASE_CRG 0xF8A22000 +#define REG_BASE_SCTL 0xF8000000 +#define REG_BASE_CRG 0xF8A22000 +#define REG_BASE_PERI_CTRL 0xF8A20000 + +/* DEVICES */ +#define REG_BASE_UART0 0xF8B00000 +#define REG_BASE_EHCI 0XF9890000 +#define REG_BASE_MCI 0xF9830000 +#define REG_BASE_MMC0 0xF9830000 + +/* SC */ +#define REG_SC_CTRL 0x0000 +#define REG_SC_SYSRES 0x0004 +#define REG_SC_GEN0 0x0080 +#define REG_SC_GEN1 0x0084 +#define REG_SC_GEN2 0x0088 +#define REG_SC_GEN12 0x00B0 + +/* USB EHCI driver */ +#define PERI_USB0 (0xF8A20000 + 0x120) +#define PERI_USB1 (0xF8A20000 + 0x124) +#define PERI_USB3 (0xF8A20000 + 0x12c) +#define PERI_USB4 (0xF8A20000 + 0x130) + +#define WORDINTERFACE (1 << 0) +#define ULPI_BYPASS_EN_PORT0 (1 << 3) +#define SS_BURST16_EN (1 << 9) +#define TEST_WRDATA (0x4) +#define TEST_ADDR (0x6 << 8) +#define TEST_WREN (1 << 21) +#define TEST_CLK (1 << 22) +#define TEST_RSTN (1 << 23) + +#define PERI_CRG46 (0xF8A22000 + 0xb8) +#define USB2_BUS_CKEN (1<<0) +#define USB2_OHCI48M_CKEN (1<<1) +#define USB2_OHCI12M_CKEN (1<<2) +#define USB2_OTG_UTMI_CKEN (1<<3) +#define USB2_HST_PHY_CKEN (1<<4) +#define USB2_UTMI0_CKEN (1<<5) +#define USB2_BUS_SRST_REQ (1<<12) +#define USB2_UTMI0_SRST_REQ (1<<13) +#define USB2_HST_PHY_SYST_REQ (1<<16) +#define USB2_OTG_PHY_SYST_REQ (1<<17) +#define USB2_CLK48_SEL (1<<20) + +#define PERI_CRG47 (0xF8A22000 + 0xbc) +#define USB2_PHY01_REF_CKEN (1 << 0) +#define USB2_PHY2_REF_CKEN (1 << 2) +#define USB2_PHY01_SRST_REQ (1 << 4) +#define USB2_PHY2_SRST_REQ (1 << 6) +#define USB2_PHY01_SRST_TREQ0 (1 << 8) +#define USB2_PHY01_SRST_TREQ1 (1 << 9) +#define USB2_PHY2_SRST_TREQ (1 << 10) +#define USB2_PHY01_REFCLK_SEL (1 << 12) +#define USB2_PHY2_REFCLK_SEL (1 << 14) + +#define REG_START_MODE 0x0000 +#define REG_PERI_STAT 0x0004 +#define REG_PERI_CTRL 0x0008 +#define REG_PERI_CRG26 0x00A8 +#define NF_BOOTBW_MASK (1<<12) + +#define HI3798CV200_EHCI_CTRL (PERI_USB0) + +/* Generate padding data ranges with unique identifiers. */ +#define ___cat(a,b) a##b +#define __cat(a,b) ___cat(a,b) +#define __padding(__words) struct { __u32 __cat(__pad, __COUNTER__)[__words]; } + +struct hi3798cv200_ehci_ctrl_regs { + u32 peri_usb0; + u32 peri_usb1; + u32 peri_usb2; + u32 peri_usb3; + u32 peri_usb4; + __padding(0x7e1); + u32 peri_crg46; + u32 peri_crg47; +}; + +#endif diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 0bf8274..a749d0e 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -128,6 +128,12 @@ config USB_EHCI_ZYNQ ---help--- Enable support for Zynq on-chip EHCI USB controller +config USB_EHCI_POPLAR + bool "Support for HI3798cv200 EHCI USB controller" + default y + ---help--- + Enable support for Poplar on-chip EHCI USB controller + config USB_EHCI_GENERIC bool "Support for generic EHCI USB controller" depends on OF_CONTROL diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 58c0cf5..3661636 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_USB_EHCI_VCT) += ehci-vct.o obj-$(CONFIG_USB_EHCI_VF) += ehci-vf.o obj-$(CONFIG_USB_EHCI_RMOBILE) += ehci-rmobile.o obj-$(CONFIG_USB_EHCI_ZYNQ) += ehci-zynq.o +obj-$(CONFIG_USB_EHCI_POPLAR) += ehci-hi3798cv200.o # xhci obj-$(CONFIG_USB_XHCI_HCD) += xhci.o xhci-mem.o xhci-ring.o diff --git a/drivers/usb/host/ehci-hi3798cv200.c b/drivers/usb/host/ehci-hi3798cv200.c new file mode 100644 index 0000000..c535de1 --- /dev/null +++ b/drivers/usb/host/ehci-hi3798cv200.c @@ -0,0 +1,196 @@ +/* + * (C) Copyright 2017 Linaro + * Jorge Ramirez-Ortiz + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include + +#include "ehci.h" + +static struct hi3798cv200_ehci_ctrl_regs *ctrl = (void *) HI3798CV200_EHCI_CTRL; + +static void inno_phy_config_2p_1(void) +{ + u32 reg; + /* write 0x4 to addr 0x06 + * config 2P PHY clk output + * delay 1ms for waiting PLL stable + */ + reg = TEST_WRDATA|TEST_ADDR|TEST_WREN|TEST_RSTN; + writel(reg, &ctrl->peri_usb0); + reg = TEST_WRDATA|TEST_ADDR|TEST_WREN|TEST_RSTN|TEST_CLK; + writel(reg, &ctrl->peri_usb0); + reg = TEST_WRDATA|TEST_ADDR|TEST_WREN|TEST_RSTN; + writel(reg, &ctrl->peri_usb0); + mdelay(1); + + /* write 0x1c to addr 0x00 + * 0x00[0] = 0 : close EOP pre-emphasis + * 0x00[2] = 1 : open Data pre-emphasis + */ + writel(0xa1001c, &ctrl->peri_usb0); + writel(0xe1001c, &ctrl->peri_usb0); + writel(0xa1001c, &ctrl->peri_usb0); + udelay(20); + + /* write 0x07 to 0x06 + * {0x06[1:0],0x05[7]} = 110 : Rcomp = 150mV , increase DC level + */ + writel(0xa00607, &ctrl->peri_usb0); + writel(0xe00607, &ctrl->peri_usb0); + writel(0xa00607, &ctrl->peri_usb0); + udelay(20); + + /* write 0x00 to addr 0x07 + * 0x07[1] = 0 : Keep Rcomp working + */ + writel(0xa10700, &ctrl->peri_usb0); + writel(0xe10700, &ctrl->peri_usb0); + writel(0xa10700, &ctrl->peri_usb0); + udelay(20); + + /* write 0xab to 0x0a + * 0x0a[7:5] = 101 : Icomp = 212mV , increase current drive + */ + writel(0xa00aab, &ctrl->peri_usb0); + writel(0xe00aab, &ctrl->peri_usb0); + writel(0xa00aab, &ctrl->peri_usb0); + udelay(20); + + /* write 0x40 to addr 0x11 + * 0x11[6:5] = 10 : sovle EMI problem, rx_active will + * not stay at 1 when error packets received + */ + writel(0xa11140, &ctrl->peri_usb0); + writel(0xe11140, &ctrl->peri_usb0); + writel(0xa11140, &ctrl->peri_usb0); + udelay(20); + + /* write 0x41 to addr 0x10 + * 0x10[0] = 1 : Comp Mode Select + */ + writel(0xa11041, &ctrl->peri_usb0); + writel(0xe11041, &ctrl->peri_usb0); + writel(0xa11041, &ctrl->peri_usb0); + udelay(20); + + /* + * {0x00a[0],0x009[7:6]} = 110 : Eye Diagram Adjust + * {0x10a[0],0x109[7:6]} = 000 : Eye Diagram Adjust + */ + writel(0xa0098c, &ctrl->peri_usb0); + writel(0xe0098c, &ctrl->peri_usb0); + writel(0xa0098c, &ctrl->peri_usb0); + writel(0xa10a0a, &ctrl->peri_usb0); + writel(0xe10a0a, &ctrl->peri_usb0); + writel(0xa10a0a, &ctrl->peri_usb0); + udelay(20); +} + +#ifndef CONFIG_DM_USB +int ehci_hcd_init(int index, enum usb_init_type init, + struct ehci_hccr **hccr, struct ehci_hcor **hcor) +{ + int reg; + + *hccr = (struct ehci_hccr *) REG_BASE_EHCI; + *hcor = (struct ehci_hcor *)( (void *) REG_BASE_EHCI + + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + + /* reset controller bus/utmi/roothub */ + reg = readl(&ctrl->peri_crg46); + reg |= (USB2_BUS_SRST_REQ + | USB2_UTMI0_SRST_REQ + | USB2_HST_PHY_SYST_REQ + | USB2_OTG_PHY_SYST_REQ); + writel(reg, &ctrl->peri_crg46); + udelay(200); + + /* reset phy por/utmi */ + reg = readl(&ctrl->peri_crg47); + reg |= (USB2_PHY01_SRST_REQ + | USB2_PHY01_SRST_TREQ1); + writel(reg, &ctrl->peri_crg47); + udelay(200); + + reg = readl(&ctrl->peri_usb3); + reg |= ULPI_BYPASS_EN_PORT0; + reg &= ~(WORDINTERFACE); + reg &= ~(SS_BURST16_EN); + writel(reg, &ctrl->peri_usb3); + udelay(100); + + /* open ref clk */ + reg = readl(&ctrl->peri_crg47); + reg |= (USB2_PHY01_REF_CKEN); + writel(reg, &ctrl->peri_crg47); + udelay(300); + + /* cancel power on reset */ + reg = readl(&ctrl->peri_crg47); + reg &= ~(USB2_PHY01_SRST_REQ); + writel(reg, &ctrl->peri_crg47); + udelay(500); + + inno_phy_config_2p_1(); + + /* cancel port reset + * delay 10ms for waiting comp circuit stable + */ + reg = readl(&ctrl->peri_crg47); + reg &= ~(USB2_PHY01_SRST_TREQ1); + writel(reg, &ctrl->peri_crg47); + mdelay(10); + + /* open controller clk */ + reg = readl(&ctrl->peri_crg46); + reg |= (USB2_BUS_CKEN + | USB2_OHCI48M_CKEN + | USB2_OHCI12M_CKEN + | USB2_OTG_UTMI_CKEN + | USB2_HST_PHY_CKEN + | USB2_UTMI0_CKEN); + writel(reg, &ctrl->peri_crg46); + udelay(200); + + /* cancel control reset */ + reg = readl(&ctrl->peri_crg46); + reg &= ~(USB2_BUS_SRST_REQ + | USB2_UTMI0_SRST_REQ + | USB2_HST_PHY_SYST_REQ + | USB2_OTG_PHY_SYST_REQ); + writel(reg, &ctrl->peri_crg46); + udelay(200); + + + return 0; +} + +int ehci_hcd_stop(int index) +{ + int reg; + + reg = readl(&ctrl->peri_crg46); + reg |= (USB2_BUS_SRST_REQ + | USB2_UTMI0_SRST_REQ + | USB2_HST_PHY_SYST_REQ); + writel(reg, &ctrl->peri_crg46); + + udelay(200); + + reg = readl(&ctrl->peri_crg47); + reg |= (USB2_PHY01_SRST_REQ + | USB2_PHY01_SRST_TREQ1); + writel(reg, &ctrl->peri_crg47); + + udelay(100); + + return 0; +} +#else +error "CONFIG_DM_USB not supported for hi3798cv200" +#endif