All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sanchayan Maity <maitysanchayan@gmail.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH v2 5/6] usb: host: Add ehci-vf USB driver for ARM Vybrid SoC's
Date: Wed,  8 Apr 2015 18:50:09 +0530	[thread overview]
Message-ID: <46735d5d2cbe2d946742db50728198c19dd781ff.1428497492.git.maitysanchayan@gmail.com> (raw)
In-Reply-To: <cover.1428497492.git.maitysanchayan@gmail.com>

This driver adds support for the USB peripheral on Freescale Vybrid
SoC's.

Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
---
 arch/arm/include/asm/arch-vf610/crm_regs.h    |  10 ++
 arch/arm/include/asm/arch-vf610/imx-regs.h    |   4 +
 arch/arm/include/asm/arch-vf610/regs-usbphy.h |  31 ++++
 drivers/usb/host/Makefile                     |   1 +
 drivers/usb/host/ehci-vf.c                    | 196 ++++++++++++++++++++++++++
 5 files changed, 242 insertions(+)
 create mode 100644 arch/arm/include/asm/arch-vf610/regs-usbphy.h
 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..bc6db2a 100644
--- a/arch/arm/include/asm/arch-vf610/crm_regs.h
+++ b/arch/arm/include/asm/arch-vf610/crm_regs.h
@@ -189,6 +189,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 +208,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/arch/arm/include/asm/arch-vf610/regs-usbphy.h b/arch/arm/include/asm/arch-vf610/regs-usbphy.h
new file mode 100644
index 0000000..b1b8876
--- /dev/null
+++ b/arch/arm/include/asm/arch-vf610/regs-usbphy.h
@@ -0,0 +1,31 @@
+/*
+ * Freescale Vybrid USB PHY Register Definitions
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __REGS_USBPHY_H__
+#define __REGS_USBPHY_H__
+
+#include <asm/imx-common/regs-common.h>
+
+struct vf_usbphy_regs {
+	mxs_reg_32(hw_usbphy_pwd)
+	mxs_reg_32(hw_usbphy_tx)
+	mxs_reg_32(hw_usbphy_rx)
+	mxs_reg_32(hw_usbphy_ctrl)
+	mxs_reg_32(hw_usbphy_status)
+	mxs_reg_32(hw_usbphy_debug)
+	mxs_reg_32(hw_usbphy_debug0_status)
+	mxs_reg_32(hw_usbphy_debug1)
+	mxs_reg_32(hw_usbphy_version)
+	mxs_reg_32(hw_usbphy_ip)
+};
+
+#define USBPHY_CTRL_ENUTMILEVEL2		(1 << 14)
+#define USBPHY_CTRL_ENUTMILEVEL3		(1 << 15)
+#define USBPHY_CTRL_OTG_ID              (1 << 27)
+#define USBPHY_CTRL_CLKGATE				(1 << 30)
+#define USBPHY_CTRL_SFTRST				(1 << 31)
+
+#endif	/* __REGS_USBPHY_H__ */
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..cbd3c8c
--- /dev/null
+++ b/drivers/usb/host/ehci-vf.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2015 Sanchayan Maity <sanchayan.maity@toradex.com>
+ * Copyright (C) 2015 Toradex AG
+ *
+ * Based on ehci-mx6 and ehci-mxs driver
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <usb.h>
+#include <errno.h>
+#include <linux/compiler.h>
+#include <asm/io.h>
+#include <asm/arch/clock.h>
+#include <asm/arch/imx-regs.h>
+#include <asm/arch/crm_regs.h>
+#include <asm/arch/regs-usbphy.h>
+#include <asm/imx-common/iomux-v3.h>
+#include <usb/ehci-fsl.h>
+
+#include "ehci.h"
+
+#define ANADIG_PLL_CTRL_EN_USB_CLKS     (1 << 6)
+
+#define USB_NC_REG_OFFSET				0x00000800
+
+#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 */
+
+struct ehci_vf_port {
+	uint32_t                 usb_regs;
+	struct vf_usbphy_regs   *phy_regs;
+	struct anadig_reg       *pll;
+	uint32_t                 pll_en_bits;
+};
+
+static const struct ehci_vf_port vf_port[] = {
+	{
+		USBC0_BASE_ADDR,
+		(struct vf_usbphy_regs *)USB_PHY0_BASE_ADDR,
+		(struct anadig_reg *)ANADIG_BASE_ADDR,
+		ANADIG_PLL3_CTRL_ENABLE | ANADIG_PLL3_CTRL_POWERDOWN
+		| ANADIG_PLL_CTRL_EN_USB_CLKS,
+	},
+	{
+		USBC1_BASE_ADDR,
+		(struct vf_usbphy_regs *)USB_PHY1_BASE_ADDR,
+		(struct anadig_reg *)ANADIG_BASE_ADDR,
+		ANADIG_PLL7_CTRL_ENABLE | ANADIG_PLL7_CTRL_POWERDOWN
+		| ANADIG_PLL_CTRL_EN_USB_CLKS,
+	},
+};
+
+static void usb_internal_phy_clock_gate(int index)
+{
+	const struct ehci_vf_port *port;
+
+	port = &vf_port[index];
+	writel(USBPHY_CTRL_CLKGATE, &port->phy_regs->hw_usbphy_ctrl_clr);
+}
+
+static void usb_power_config(int index)
+{
+	u32 reg;
+	const struct ehci_vf_port *port;
+
+	port = &vf_port[index];
+
+	switch (index) {
+	case 0:
+			reg = readl(&port->pll->pll3_ctrl);
+			reg &= ~ANADIG_PLL3_CTRL_BYPASS;
+			writel(reg, &port->pll->pll3_ctrl);
+
+			reg = readl(&port->pll->pll3_ctrl);
+			reg |= port->pll_en_bits;
+			writel(reg, &port->pll->pll3_ctrl);
+		break;
+	case 1:
+			reg = readl(&port->pll->pll7_ctrl);
+			reg &= ~ANADIG_PLL7_CTRL_BYPASS;
+			writel(reg, &port->pll->pll7_ctrl);
+
+			reg = readl(&port->pll->pll7_ctrl);
+			reg |= port->pll_en_bits;
+			writel(reg, &port->pll->pll7_ctrl);
+		break;
+	default:
+		return;
+	}
+}
+
+static void usb_phy_enable(int index, struct usb_ehci *ehci)
+{
+	u32 val;
+	void __iomem *usb_cmd;
+	const struct ehci_vf_port *port;
+
+	port = &vf_port[index];
+	usb_cmd = (void __iomem *)&ehci->usbcmd;
+
+	/* Stop then Reset */
+	val = readl(usb_cmd);
+	val &= ~UCMD_RUN_STOP;
+	writel(val, usb_cmd);
+	while (readl(usb_cmd) & UCMD_RUN_STOP)
+		;
+
+	val = readl(usb_cmd);
+	val |= UCMD_RESET;
+	writel(val, usb_cmd);
+	while (readl(usb_cmd) & UCMD_RESET)
+		;
+
+	/* Reset USBPHY module */
+	writel(USBPHY_CTRL_SFTRST, &port->phy_regs->hw_usbphy_ctrl_set);
+	udelay(10);
+
+	/* Remove CLKGATE and SFTRST */
+	writel(USBPHY_CTRL_CLKGATE | USBPHY_CTRL_SFTRST,
+	       &port->phy_regs->hw_usbphy_ctrl_clr);
+	udelay(10);
+
+	/* Power up the PHY */
+	writel(0, &port->phy_regs->hw_usbphy_pwd);
+
+	/* enable FS/LS device */
+	writel(USBPHY_CTRL_ENUTMILEVEL2 | USBPHY_CTRL_ENUTMILEVEL3,
+	       &port->phy_regs->hw_usbphy_ctrl_set);
+}
+
+static void usb_oc_config(int index)
+{
+	u32 val;
+	const struct ehci_vf_port *port;
+
+	port = &vf_port[index];
+
+	val = readl(&port->usb_regs + USB_NC_REG_OFFSET);
+	val |= UCTRL_OVER_CUR_POL;
+	writel(val, &port->usb_regs + USB_NC_REG_OFFSET);
+
+	val = readl(&port->usb_regs + USB_NC_REG_OFFSET);
+	val |= UCTRL_OVER_CUR_DIS;
+	writel(val, &port->usb_regs + USB_NC_REG_OFFSET);
+}
+
+int ehci_hcd_init(int index, enum usb_init_type init,
+		struct ehci_hccr **hccr, struct ehci_hcor **hcor)
+{
+	struct usb_ehci *ehci;
+	const struct ehci_vf_port *port;
+
+	if (index >= ARRAY_SIZE(vf_port))
+		return -EINVAL;
+
+	if (init == USB_INIT_DEVICE && index == 1)
+		return -ENODEV;
+	if (init == USB_INIT_HOST && index == 0)
+		return -ENODEV;
+
+	port = &vf_port[index];
+
+	ehci = (struct usb_ehci *)(port->usb_regs);
+
+	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);
+		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);
+		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;
+}
-- 
2.3.5

  parent reply	other threads:[~2015-04-08 13:20 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-08 13:20 [U-Boot] [PATCH v2 0/6] Add support for Colibri Vybrid Modules Sanchayan Maity
2015-04-08 13:20 ` [U-Boot] [PATCH v2 1/6] ARM: vf610: Move DDR3 initialization to imx-common Sanchayan Maity
2015-04-08 13:20 ` [U-Boot] [PATCH v2 2/6] ARM: vf610: Enable external 32KHz oscillator Sanchayan Maity
2015-04-08 13:20 ` [U-Boot] [PATCH v2 3/6] ARM: vf610: Add SoC and CPU type detection Sanchayan Maity
2015-04-08 13:20 ` [U-Boot] [PATCH v2 4/6] ARM: vf610: Enable caches Sanchayan Maity
2015-04-08 13:20 ` Sanchayan Maity [this message]
2015-04-12 23:29   ` [U-Boot] [PATCH v2 5/6] usb: host: Add ehci-vf USB driver for ARM Vybrid SoC's Marek Vasut
2015-04-13  5:37     ` maitysanchayan at gmail.com
2015-04-13  5:49       ` Marek Vasut
2015-04-08 13:20 ` [U-Boot] [PATCH v2 6/6] ARM: vf610: Initial integration for Colibri VF50/VF61 Sanchayan Maity
2015-04-11 16:46 ` [U-Boot] [PATCH v2 0/6] Add support for Colibri Vybrid Modules Marek Vasut
2015-04-12  5:33   ` maitysanchayan at gmail.com
2015-04-12 23:28     ` Marek Vasut
2015-04-13  1:36       ` Fabio Estevam
2015-04-13  3:41         ` Marek Vasut
2015-04-13  6:21       ` maitysanchayan at gmail.com
2015-04-13  8:44         ` Marek Vasut
2015-04-13  8:50           ` Peter Chen
2015-04-13  8:52             ` Marek Vasut
2015-04-14  9:06               ` Peter Chen
2015-04-14 10:18                 ` maitysanchayan at gmail.com
2015-04-15  5:41                   ` Marek Vasut

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46735d5d2cbe2d946742db50728198c19dd781ff.1428497492.git.maitysanchayan@gmail.com \
    --to=maitysanchayan@gmail.com \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.