From patchwork Wed Apr 1 09:54:22 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sanchayan Maity X-Patchwork-Id: 457217 X-Patchwork-Delegate: trini@ti.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 B77B214008F for ; Wed, 1 Apr 2015 21:21:12 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="verification failed; unprotected key" header.d=gmail.com header.i=@gmail.com header.b=TdCTVT5d; dkim-adsp=none (unprotected policy); dkim-atps=neutral Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id B622BA7443; Wed, 1 Apr 2015 12:20:55 +0200 (CEST) X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" 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 v5nBaNOnZy5j; Wed, 1 Apr 2015 12:20:55 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C14A8A741C; Wed, 1 Apr 2015 12:20:37 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BF9904B61F for ; Wed, 1 Apr 2015 11:56:56 +0200 (CEST) X-Amavis-Alert: BAD HEADER SECTION, Duplicate header field: "References" 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 f2g_5xn-nQiv for ; Wed, 1 Apr 2015 11:56:56 +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-f41.google.com (mail-pa0-f41.google.com [209.85.220.41]) by theia.denx.de (Postfix) with ESMTPS id 245B44A04E for ; Wed, 1 Apr 2015 11:56:52 +0200 (CEST) Received: by pacgg7 with SMTP id gg7so47694861pac.0 for ; Wed, 01 Apr 2015 02:56:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references :in-reply-to:references; bh=t114QmHY6SBx4+mJS0hFtp1kFXEUDH1Wwn7TYjKn7wY=; b=TdCTVT5dqegW/ZX+iuZt8GjgQA5ikUOoKfUKhXU4LOo3KWftK9zhFeanM4y78FlFGT 3Io8jYd+FQaPz5N5kerzRkWUy1zxhj7+bA9aH0xgjeKQscy7h5pIVjuEckReERqSGCA4 OF8+JOVNeB3l6uS/BZD3u43foXjN5N62Jd1NeyzZzT4pif/JEptQW7Y9+qcMiCyvdhqq T3Dx0YcmdSEuheLGr8m30QaXVbbQ9V4nKoqE+p55/xM3XkJMFNPYsQPUWFJCSdg60AQR bXnmiJbfB+eOxAEYz1YeAmo0rNG2u/U9zWGaQ+AqK2WLfynoeRU6rRodD7Srap67Ug7w bvAA== X-Received: by 10.68.248.39 with SMTP id yj7mr76503065pbc.58.1427882211321; Wed, 01 Apr 2015 02:56:51 -0700 (PDT) Received: from localhost ([115.115.225.206]) by mx.google.com with ESMTPSA id bz3sm1596044pab.2.2015.04.01.02.56.49 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 01 Apr 2015 02:56:50 -0700 (PDT) From: Sanchayan Maity To: u-boot@lists.denx.de, sbabic@denx.de Date: Wed, 1 Apr 2015 15:24:22 +0530 Message-Id: X-Mailer: git-send-email 2.3.4 In-Reply-To: References: In-Reply-To: References: X-Mailman-Approved-At: Wed, 01 Apr 2015 12:20:23 +0200 Cc: marex@denx.de, bhuvanchandra.dv@toradex.com, trini@konsulko.com, marcel@ziswiler.com Subject: [U-Boot] [RESEND PATCH 5/6] usb: host: Add ehci-vf USB driver for ARM Vybrid SoC's X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.15 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: Sanchayan Maity --- arch/arm/include/asm/arch-vf610/crm_regs.h | 14 ++ arch/arm/include/asm/arch-vf610/imx-regs.h | 4 + drivers/usb/host/Makefile | 1 + drivers/usb/host/ehci-vf.c | 204 +++++++++++++++++++++++++++++ 4 files changed, 223 insertions(+) create mode 100644 drivers/usb/host/ehci-vf.c diff --git a/arch/arm/include/asm/arch-vf610/crm_regs.h b/arch/arm/include/asm/arch-vf610/crm_regs.h index 78708e2..851c3b9 100644 --- a/arch/arm/include/asm/arch-vf610/crm_regs.h +++ b/arch/arm/include/asm/arch-vf610/crm_regs.h @@ -124,6 +124,10 @@ struct anadig_reg { #define CCM_CCSR_PLL1_PFD_CLK_SEL_MASK (0x7 << 16) #define CCM_CCSR_PLL1_PFD_CLK_SEL(v) (((v) & 0x7) << 16) +#define CCM_CCSR_PLL3_PFD4_EN (1 << 31) +#define CCM_CCSR_PLL3_PFD3_EN (1 << 30) +#define CCM_CCSR_PLL3_PFD2_EN (1 << 29) +#define CCM_CCSR_PLL3_PFD1_EN (1 << 28) #define CCM_CCSR_PLL2_PFD4_EN (1 << 15) #define CCM_CCSR_PLL2_PFD3_EN (1 << 14) #define CCM_CCSR_PLL2_PFD2_EN (1 << 13) @@ -189,6 +193,7 @@ struct anadig_reg { #define CCM_REG_CTRL_MASK 0xffffffff #define CCM_CCGR0_UART0_CTRL_MASK (0x3 << 14) #define CCM_CCGR0_UART1_CTRL_MASK (0x3 << 16) +#define CCM_CCGR1_USBC0_CTRL_MASK (0x3 << 8) #define CCM_CCGR1_PIT_CTRL_MASK (0x3 << 14) #define CCM_CCGR1_WDOGA5_CTRL_MASK (0x3 << 28) #define CCM_CCGR2_QSPI0_CTRL_MASK (0x3 << 8) @@ -207,14 +212,23 @@ struct anadig_reg { #define CCM_CCGR6_OCOTP_CTRL_MASK (0x3 << 10) #define CCM_CCGR6_DDRMC_CTRL_MASK (0x3 << 28) #define CCM_CCGR7_SDHC1_CTRL_MASK (0x3 << 4) +#define CCM_CCGR7_USBC1_CTRL_MASK (0x3 << 8) #define CCM_CCGR9_FEC0_CTRL_MASK 0x3 #define CCM_CCGR9_FEC1_CTRL_MASK (0x3 << 2) #define CCM_CCGR10_NFC_CTRL_MASK 0x3 +#define ANADIG_PLL7_CTRL_BYPASS (1 << 16) +#define ANADIG_PLL7_CTRL_ENABLE (1 << 13) +#define ANADIG_PLL7_CTRL_POWERDOWN (1 << 12) +#define ANADIG_PLL7_CTRL_DIV_SELECT (1 << 1) #define ANADIG_PLL5_CTRL_BYPASS (1 << 16) #define ANADIG_PLL5_CTRL_ENABLE (1 << 13) #define ANADIG_PLL5_CTRL_POWERDOWN (1 << 12) #define ANADIG_PLL5_CTRL_DIV_SELECT 1 +#define ANADIG_PLL3_CTRL_BYPASS (1 << 16) +#define ANADIG_PLL3_CTRL_ENABLE (1 << 13) +#define ANADIG_PLL3_CTRL_POWERDOWN (1 << 12) +#define ANADIG_PLL3_CTRL_DIV_SELECT (1 << 1) #define ANADIG_PLL2_CTRL_ENABLE (1 << 13) #define ANADIG_PLL2_CTRL_POWERDOWN (1 << 12) #define ANADIG_PLL2_CTRL_DIV_SELECT 1 diff --git a/arch/arm/include/asm/arch-vf610/imx-regs.h b/arch/arm/include/asm/arch-vf610/imx-regs.h index a5908ca..26057fe 100644 --- a/arch/arm/include/asm/arch-vf610/imx-regs.h +++ b/arch/arm/include/asm/arch-vf610/imx-regs.h @@ -52,6 +52,7 @@ #define SAI2_BASE_ADDR (AIPS0_BASE_ADDR + 0x00031000) #define SAI3_BASE_ADDR (AIPS0_BASE_ADDR + 0x00032000) #define CRC_BASE_ADDR (AIPS0_BASE_ADDR + 0x00033000) +#define USBC0_BASE_ADDR (AIPS0_BASE_ADDR + 0x00034000) #define PDB_BASE_ADDR (AIPS0_BASE_ADDR + 0x00036000) #define PIT_BASE_ADDR (AIPS0_BASE_ADDR + 0x00037000) #define FTM0_BASE_ADDR (AIPS0_BASE_ADDR + 0x00038000) @@ -65,6 +66,8 @@ #define QSPI0_BASE_ADDR (AIPS0_BASE_ADDR + 0x00044000) #define IOMUXC_BASE_ADDR (AIPS0_BASE_ADDR + 0x00048000) #define ANADIG_BASE_ADDR (AIPS0_BASE_ADDR + 0x00050000) +#define USB_PHY0_BASE_ADDR (AIPS0_BASE_ADDR + 0x00050800) +#define USB_PHY1_BASE_ADDR (AIPS0_BASE_ADDR + 0x00050C00) #define SCSC_BASE_ADDR (AIPS0_BASE_ADDR + 0x00052000) #define ASRC_BASE_ADDR (AIPS0_BASE_ADDR + 0x00060000) #define SPDIF_BASE_ADDR (AIPS0_BASE_ADDR + 0x00061000) @@ -84,6 +87,7 @@ #define DDR_BASE_ADDR (AIPS1_BASE_ADDR + 0x0002E000) #define ESDHC0_BASE_ADDR (AIPS1_BASE_ADDR + 0x00031000) #define ESDHC1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00032000) +#define USBC1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00034000) #define ENET_BASE_ADDR (AIPS1_BASE_ADDR + 0x00050000) #define ENET1_BASE_ADDR (AIPS1_BASE_ADDR + 0x00051000) #define NFC_BASE_ADDR (AIPS1_BASE_ADDR + 0x00060000) diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index eb6f34b..4bd9321 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_USB_EHCI_SUNXI) += ehci-sunxi.o obj-$(CONFIG_USB_EHCI_TEGRA) += ehci-tegra.o obj-$(CONFIG_USB_EHCI_UNIPHIER) += ehci-uniphier.o 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 diff --git a/drivers/usb/host/ehci-vf.c b/drivers/usb/host/ehci-vf.c new file mode 100644 index 0000000..4aa3b9c --- /dev/null +++ b/drivers/usb/host/ehci-vf.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2015 Sanchayan Maity + * Copyright (C) 2015 Toradex AG + * + * Based on ehci-mx6 driver + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ehci.h" + +#define USB_NC_REG_OFFSET 0x00000800 +#define USBCx_CTRL_OFFSET 0x00000000 +#define USBCx_PHY_CTRL_OFFSET 0x00000018 + +#define USBPHY_CTRL 0x00000030 +#define USBPHY_CTRL_SET 0x00000034 +#define USBPHY_CTRL_CLR 0x00000038 +#define USBPHY_CTRL_TOG 0x0000003c + +#define USBPHY_PWD 0x00000000 +#define USBPHY_TX 0x00000010 +#define USBPHY_RX 0x00000020 +#define USBPHY_DEBUG 0x00000050 +#define USBPHY_CTRL_SFTRST 0x80000000 +#define USBPHY_CTRL_CLKGATE 0x40000000 +#define USBPHY_CTRL_ENUTMILEVEL3 0x00008000 +#define USBPHY_CTRL_ENUTMILEVEL2 0x00004000 +#define USBPHY_CTRL_OTG_ID 0x08000000 + +#define ANADIG_PLL_CTRL_BYPASS 0x00010000 +#define ANADIG_PLL_CTRL_ENABLE 0x00002000 +#define ANADIG_PLL_CTRL_POWER 0x00001000 +#define ANADIG_PLL_CTRL_EN_USB_CLKS 0x00000040 + +#define UCTRL_OVER_CUR_POL (1 << 8) /* OTG Polarity of Overcurrent */ +#define UCTRL_OVER_CUR_DIS (1 << 7) /* Disable OTG Overcurrent Detection */ + +/* USBCMD */ +#define UCMD_RUN_STOP (1 << 0) /* controller run/stop */ +#define UCMD_RESET (1 << 1) /* controller reset */ + +static const unsigned phy_bases[] = { + USB_PHY0_BASE_ADDR, + USB_PHY1_BASE_ADDR, +}; + +static const unsigned nc_reg_bases[] = { + USBC0_BASE_ADDR, + USBC1_BASE_ADDR, +}; + +static void usb_internal_phy_clock_gate(int index) +{ + u32 reg; + void __iomem *phy_reg; + + phy_reg = (void __iomem *)phy_bases[index]; + reg = __raw_readl(phy_reg + USBPHY_CTRL); + reg &= ~USBPHY_CTRL_CLKGATE; + __raw_writel(reg, phy_reg + USBPHY_CTRL_SET); +} + +static void usb_power_config(int index) +{ + struct anadig_reg __iomem *anadig = + (struct anadig_reg __iomem *)ANADIG_BASE_ADDR; + void __iomem *pll_ctrl; + u32 reg; + + switch (index) { + case 0: + pll_ctrl = &anadig->pll3_ctrl; + break; + case 1: + pll_ctrl = &anadig->pll7_ctrl; + break; + default: + return; + } + + reg = __raw_readl(pll_ctrl); + reg &= ~ANADIG_PLL_CTRL_BYPASS; + __raw_writel(reg, pll_ctrl); + + reg = __raw_readl(pll_ctrl); + reg |= ANADIG_PLL_CTRL_ENABLE | ANADIG_PLL_CTRL_POWER + | ANADIG_PLL_CTRL_EN_USB_CLKS; + __raw_writel(reg, pll_ctrl); +} + +static void usb_phy_enable(int index, struct usb_ehci *ehci) +{ + void __iomem *phy_reg; + void __iomem *phy_ctrl; + void __iomem *usb_cmd; + u32 val; + + phy_reg = (void __iomem *)phy_bases[index]; + phy_ctrl = (void __iomem *)(phy_reg + USBPHY_CTRL); + usb_cmd = (void __iomem *)&ehci->usbcmd; + + /* Stop then Reset */ + val = __raw_readl(usb_cmd); + val &= ~UCMD_RUN_STOP; + __raw_writel(val, usb_cmd); + while (__raw_readl(usb_cmd) & UCMD_RUN_STOP) + ; + + val = __raw_readl(usb_cmd); + val |= UCMD_RESET; + __raw_writel(val, usb_cmd); + while (__raw_readl(usb_cmd) & UCMD_RESET) + ; + + /* Reset USBPHY module */ + val = __raw_readl(phy_ctrl); + val |= USBPHY_CTRL_SFTRST; + __raw_writel(val, phy_ctrl); + udelay(10); + + /* Remove CLKGATE and SFTRST */ + val = __raw_readl(phy_ctrl); + val &= ~(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST); + __raw_writel(val, phy_ctrl); + udelay(10); + + /* Power up the PHY */ + __raw_writel(0, phy_reg + USBPHY_PWD); + /* enable FS/LS device */ + val = __raw_readl(phy_ctrl); + val |= (USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3); + __raw_writel(val, phy_ctrl); +} + +static void usb_oc_config(int index) +{ + void __iomem *ctrl; + u32 val; + + ctrl = (void __iomem *)(nc_reg_bases[index] + USB_NC_REG_OFFSET + + USBCx_CTRL_OFFSET); + + val = __raw_readl(ctrl); + val |= UCTRL_OVER_CUR_POL; + __raw_writel(val, ctrl); + + val = __raw_readl(ctrl); + val |= UCTRL_OVER_CUR_DIS; + __raw_writel(val, ctrl); +} + +int ehci_hcd_init(int index, enum usb_init_type init, + struct ehci_hccr **hccr, struct ehci_hcor **hcor) +{ + struct usb_ehci *ehci; + + if (index >= ARRAY_SIZE(nc_reg_bases)) + return -EINVAL; + + if (init == USB_INIT_DEVICE && index == 1) + return -ENODEV; + if (init == USB_INIT_HOST && index == 0) + return -ENODEV; + + ehci = (struct usb_ehci *)nc_reg_bases[index]; + + usb_power_config(index); + usb_oc_config(index); + usb_internal_phy_clock_gate(index); + usb_phy_enable(index, ehci); + + *hccr = (struct ehci_hccr *)((uint32_t)&ehci->caplength); + *hcor = (struct ehci_hcor *)((uint32_t)*hccr + + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); + + if (init == USB_INIT_DEVICE) { + setbits_le32(&ehci->usbmode, CM_DEVICE); + __raw_writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc); + setbits_le32(&ehci->portsc, USB_EN); + } else if (init == USB_INIT_HOST) { + setbits_le32(&ehci->usbmode, CM_HOST); + __raw_writel((PORT_PTS_UTMI | PORT_PTS_PTW), &ehci->portsc); + setbits_le32(&ehci->portsc, USB_EN); + } + + return 0; +} + +int ehci_hcd_stop(int index) +{ + return 0; +}