All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kishon Vijay Abraham I <kishon@ti.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [UBOOT RFC PATCH 06/13] usb: dwc3: TI PHY: PHY driver for dwc3 in TI platforms
Date: Mon, 18 Aug 2014 19:58:28 +0530	[thread overview]
Message-ID: <1408372115-4570-7-git-send-email-kishon@ti.com> (raw)
In-Reply-To: <1408372115-4570-1-git-send-email-kishon@ti.com>

Added a single driver for both USB2 PHY programming and USB3 PHY
programming.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/usb/dwc3/Makefile     |   1 +
 drivers/usb/dwc3/ti_usb_phy.c | 269 ++++++++++++++++++++++++++++++++++++++++++
 include/ti-usb-phy-uboot.h    |  22 ++++
 3 files changed, 292 insertions(+)
 create mode 100644 drivers/usb/dwc3/ti_usb_phy.c
 create mode 100644 include/ti-usb-phy-uboot.h

diff --git a/drivers/usb/dwc3/Makefile b/drivers/usb/dwc3/Makefile
index 5533546..6b55b9f 100644
--- a/drivers/usb/dwc3/Makefile
+++ b/drivers/usb/dwc3/Makefile
@@ -7,3 +7,4 @@ dwc3-y					:= core.o
 dwc3-$(CONFIG_USB_DWC3_GADGET)		+= gadget.o ep0.o
 
 obj-$(CONFIG_USB_DWC3_OMAP)		+= dwc3-omap.o
+obj-$(CONFIG_USB_DWC3_PHY_OMAP)		+= ti_usb_phy.o
diff --git a/drivers/usb/dwc3/ti_usb_phy.c b/drivers/usb/dwc3/ti_usb_phy.c
new file mode 100644
index 0000000..05052c3
--- /dev/null
+++ b/drivers/usb/dwc3/ti_usb_phy.c
@@ -0,0 +1,269 @@
+/**
+ * ti_usb_phy.c - USB3 and USB3 PHY programming for dwc3
+ *
+ * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * Taken from Linux Kernel v3.16 (drivers/phy/phy-ti-pipe3.c and
+ * drivers/phy/phy-omap-usb2.c) and ported to uboot.
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#include <linux/compat.h>
+#include "linux-compat.h"
+#include <ti-usb-phy-uboot.h>
+#include <linux/ioport.h>
+#include <asm/io.h>
+#include <asm/arch/sys_proto.h>
+
+#define PLL_STATUS		0x00000004
+#define PLL_GO			0x00000008
+#define PLL_CONFIGURATION1	0x0000000C
+#define PLL_CONFIGURATION2	0x00000010
+#define PLL_CONFIGURATION3	0x00000014
+#define PLL_CONFIGURATION4	0x00000020
+
+#define PLL_REGM_MASK		0x001FFE00
+#define PLL_REGM_SHIFT		0x9
+#define PLL_REGM_F_MASK		0x0003FFFF
+#define PLL_REGM_F_SHIFT	0x0
+#define PLL_REGN_MASK		0x000001FE
+#define PLL_REGN_SHIFT		0x1
+#define PLL_SELFREQDCO_MASK	0x0000000E
+#define PLL_SELFREQDCO_SHIFT	0x1
+#define PLL_SD_MASK		0x0003FC00
+#define PLL_SD_SHIFT		10
+#define SET_PLL_GO		0x1
+#define PLL_LDOPWDN		BIT(15)
+#define PLL_TICOPWDN		BIT(16)
+#define PLL_LOCK		0x2
+#define PLL_IDLE		0x1
+
+#define OMAP_CTRL_DEV_PHY_PD				BIT(0)
+#define OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_MASK		0x003FC000
+#define OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_SHIFT		0xE
+
+#define OMAP_CTRL_USB3_PHY_PWRCTL_CLK_FREQ_MASK		0xFFC00000
+#define OMAP_CTRL_USB3_PHY_PWRCTL_CLK_FREQ_SHIFT	0x16
+
+#define OMAP_CTRL_USB3_PHY_TX_RX_POWERON	0x3
+#define OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF	0x0
+
+static LIST_HEAD(ti_usb_phy_list);
+typedef unsigned int u32;
+
+struct usb3_dpll_params {
+	u16	m;
+	u8	n;
+	u8	freq:3;
+	u8	sd;
+	u32	mf;
+};
+
+struct usb3_dpll_map {
+	unsigned long rate;
+	struct usb3_dpll_params params;
+	struct usb3_dpll_map *dpll_map;
+};
+
+struct ti_usb_phy {
+	void __iomem *pll_ctrl_base;
+	void __iomem *usb2_phy_power;
+	void __iomem *usb3_phy_power;
+	struct usb3_dpll_map *dpll_map;
+	struct list_head list;
+	int index;
+};
+
+static struct usb3_dpll_map dpll_map_usb[] = {
+	{12000000, {1250, 5, 4, 20, 0} },	/* 12 MHz */
+	{16800000, {3125, 20, 4, 20, 0} },	/* 16.8 MHz */
+	{19200000, {1172, 8, 4, 20, 65537} },	/* 19.2 MHz */
+	{20000000, {1000, 7, 4, 10, 0} },	/* 20 MHz */
+	{26000000, {1250, 12, 4, 20, 0} },	/* 26 MHz */
+	{38400000, {3125, 47, 4, 20, 92843} },	/* 38.4 MHz */
+	{ },					/* Terminator */
+};
+
+static inline unsigned int ti_usb3_readl(void __iomem *base, u32 offset)
+{
+	return readl(base + offset);
+}
+
+static inline void ti_usb3_writel(void __iomem *base, u32 offset, u32 value)
+{
+	writel(value, base + offset);
+}
+
+static struct usb3_dpll_params *ti_usb3_get_dpll_params(struct ti_usb_phy *phy)
+{
+	unsigned long rate;
+	struct usb3_dpll_map *dpll_map = phy->dpll_map;
+
+	rate = get_sys_clk_freq();
+
+	for (; dpll_map->rate; dpll_map++) {
+		if (rate == dpll_map->rate)
+			return &dpll_map->params;
+	}
+
+	dev_err(phy->dev, "No DPLL configuration for %lu Hz SYS CLK\n", rate);
+
+	return NULL;
+}
+
+static int ti_usb3_dpll_wait_lock(struct ti_usb_phy *phy)
+{
+	u32 val;
+	do {
+		val = ti_usb3_readl(phy->pll_ctrl_base, PLL_STATUS);
+			if (val & PLL_LOCK)
+				break;
+	} while (1);
+
+	return 0;
+}
+
+static int ti_usb3_dpll_program(struct ti_usb_phy *phy)
+{
+	u32			val;
+	struct usb3_dpll_params	*dpll_params;
+
+	if (!phy->pll_ctrl_base)
+		return -EINVAL;
+		
+	dpll_params = ti_usb3_get_dpll_params(phy);
+	if (!dpll_params)
+		return -EINVAL;
+
+	val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+	val &= ~PLL_REGN_MASK;
+	val |= dpll_params->n << PLL_REGN_SHIFT;
+	ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+
+	val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
+	val &= ~PLL_SELFREQDCO_MASK;
+	val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
+	ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
+
+	val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
+	val &= ~PLL_REGM_MASK;
+	val |= dpll_params->m << PLL_REGM_SHIFT;
+	ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
+
+	val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
+	val &= ~PLL_REGM_F_MASK;
+	val |= dpll_params->mf << PLL_REGM_F_SHIFT;
+	ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
+
+	val = ti_usb3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
+	val &= ~PLL_SD_MASK;
+	val |= dpll_params->sd << PLL_SD_SHIFT;
+	ti_usb3_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
+
+	ti_usb3_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
+
+	return ti_usb3_dpll_wait_lock(phy);
+}
+
+void ti_usb2_phy_power(struct ti_usb_phy *phy, int on)
+{
+	u32 val;
+
+	val = readl(phy->usb2_phy_power);
+	if (on)
+		val &= ~OMAP_CTRL_DEV_PHY_PD;
+	else
+		val |= OMAP_CTRL_DEV_PHY_PD;
+	writel(val, phy->usb2_phy_power);
+}
+
+void ti_usb3_phy_power(struct ti_usb_phy *phy, int on)
+{
+	u32 val;
+	u32 rate;
+	rate = get_sys_clk_freq();
+	rate = rate/1000000;
+
+	if (!phy->usb3_phy_power)
+		return;
+
+	val = readl(phy->usb3_phy_power);
+	if (on) {
+		val &= ~(OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_MASK |
+			OMAP_CTRL_USB3_PHY_PWRCTL_CLK_FREQ_MASK);
+		val |= (OMAP_CTRL_USB3_PHY_TX_RX_POWERON) <<
+			OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_SHIFT;
+		val |= rate <<
+			OMAP_CTRL_USB3_PHY_PWRCTL_CLK_FREQ_SHIFT;
+	} else {
+		val &= ~OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_MASK;
+		val |= OMAP_CTRL_USB3_PHY_TX_RX_POWEROFF <<
+			OMAP_CTRL_USB3_PHY_PWRCTL_CLK_CMD_SHIFT;
+	}
+	writel(val, phy->usb3_phy_power);
+}
+
+/**
+ * ti_usb_phy_uboot_init - usb phy uboot initialization code
+ * @dev: struct ti_usb_phy_device containing initialization data
+ *
+ * Entry point for ti usb phy driver. This driver handles initialization
+ * of both usb2 phy and usb3 phy. Pointer to ti_usb_phy_device should be
+ * passed containing base address and other initialization data.
+ * Returns '0' on success and a negative value on failure.
+ *
+ * Generally called from board_usb_init() implemented in board file.
+ */
+int ti_usb_phy_uboot_init(struct ti_usb_phy_device *dev)
+{
+	struct ti_usb_phy *phy;
+
+	phy = devm_kzalloc(NULL, sizeof(*phy), GFP_KERNEL);
+	if (!phy) {
+		dev_err(NULL, "unable to alloc mem for TI USB3 PHY\n");
+		return -ENOMEM;
+	}
+
+	phy->dpll_map = dpll_map_usb;
+	phy->index = dev->index;
+	phy->pll_ctrl_base = dev->pll_ctrl_base;
+	phy->usb2_phy_power = dev->usb2_phy_power;
+	phy->usb3_phy_power = dev->usb3_phy_power;
+
+	ti_usb3_dpll_program(phy);
+	ti_usb2_phy_power(phy, 1);
+	ti_usb3_phy_power(phy, 1);
+	mdelay(150);
+	list_add_tail(&phy->list, &ti_usb_phy_list);
+
+	return 0;
+}
+
+/**
+ * ti_usb_phy_uboot_exit - usb phy uboot cleanup code
+ * @index: index of this controller
+ *
+ * Performs cleanup of memory allocated in ti_usb_phy_uboot_init.
+ * index of _this_ controller should be passed and should match with
+ * the index passed in ti_usb_phy_device during init. 
+ *
+ * Generally called from board file.
+ */
+void ti_usb_phy_uboot_exit(int index)
+{
+	struct ti_usb_phy *phy = NULL;
+
+	list_for_each_entry(phy, &ti_usb_phy_list, list) {
+		if (phy->index != index)
+			continue;
+
+		ti_usb2_phy_power(phy, 0);
+		ti_usb3_phy_power(phy, 0);
+		list_del(&phy->list);
+		kfree(phy);
+		break;
+	}
+}
diff --git a/include/ti-usb-phy-uboot.h b/include/ti-usb-phy-uboot.h
new file mode 100644
index 0000000..93f7101
--- /dev/null
+++ b/include/ti-usb-phy-uboot.h
@@ -0,0 +1,22 @@
+/* include/ti_usb_phy_uboot.h
+ *
+ * Copyright (c) 2014 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * USB2 and USB3 PHY uboot init
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#ifndef __TI_USB_PHY_UBOOT_H_
+#define __TI_USB_PHY_UBOOT_H_
+
+struct ti_usb_phy_device {
+	void *pll_ctrl_base;
+	void *usb2_phy_power;
+	void *usb3_phy_power;
+	int index;
+};
+
+int ti_usb_phy_uboot_init(struct ti_usb_phy_device *dev);
+void ti_usb_phy_uboot_exit(int index);
+#endif /* __TI_USB_PHY_UBOOT_H_ */
-- 
1.9.1

  parent reply	other threads:[~2014-08-18 14:28 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-18 14:28 [U-Boot] [UBOOT RFC PATCH 00/13] DRA7xx: Add DWC3 USB driver and enable DFU Kishon Vijay Abraham I
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 01/13] include: linux: preparation for porting dwc3 from linux kernel Kishon Vijay Abraham I
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 02/13] usb: gadget: udc-core: Add minimal udc-core " Kishon Vijay Abraham I
2014-08-18 14:36   ` Felipe Balbi
2014-08-19 14:58     ` Kishon Vijay Abraham I
2014-08-19  8:52   ` Lukasz Majewski
2014-08-19 15:11     ` Felipe Balbi
2014-08-19 15:18     ` Kishon Vijay Abraham I
2014-08-19 15:28       ` Felipe Balbi
2014-08-19 15:38         ` Lukasz Majewski
2014-08-19 16:06         ` Kishon Vijay Abraham I
2014-08-20  7:02           ` Lukasz Majewski
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 03/13] ARM: DRA7: Enable clocks for USB OTGSS and USB PHY Kishon Vijay Abraham I
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 04/13] usb: dwc3: Add dwc3 driver Kishon Vijay Abraham I
2014-08-18 14:37   ` Felipe Balbi
2014-08-19 15:19     ` Kishon Vijay Abraham I
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 05/13] usb: dwc3-omap: Add dwc3 glue driver for OMAP Kishon Vijay Abraham I
2014-08-18 14:28 ` Kishon Vijay Abraham I [this message]
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 07/13] usb: gadget: g_dnl: Explicitly set the max packet size in descriptor Kishon Vijay Abraham I
2014-08-18 14:38   ` Felipe Balbi
2014-08-18 14:49     ` Lukasz Majewski
2014-08-18 14:56     ` Lukasz Majewski
2014-08-19 15:38       ` Kishon Vijay Abraham I
2014-08-19 15:44         ` Felipe Balbi
2014-08-20  7:34           ` Lukasz Majewski
2014-08-20 16:11             ` Felipe Balbi
2014-08-21  8:00               ` Lukasz Majewski
2014-08-21 13:50                 ` Felipe Balbi
2014-08-20  7:23         ` Lukasz Majewski
2014-08-19 15:34     ` Kishon Vijay Abraham I
2014-08-19 15:39       ` Felipe Balbi
2014-08-19 15:42         ` Kishon Vijay Abraham I
2014-08-19 15:48           ` Felipe Balbi
2014-08-19 15:53             ` Kishon Vijay Abraham I
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 08/13] common: cmd_dfu: invoke board_usb_cleanup() for cleaning up Kishon Vijay Abraham I
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 09/13] common: cmd_dfu: add an API that takes controller index for handling interrupts Kishon Vijay Abraham I
2014-08-19  8:53   ` Lukasz Majewski
2014-08-19 16:09     ` Kishon Vijay Abraham I
2014-08-20  7:37       ` Lukasz Majewski
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 10/13] board: ti: DRA7: added USB initializtion code Kishon Vijay Abraham I
2014-08-18 14:40   ` Felipe Balbi
2014-08-19 16:13     ` Kishon Vijay Abraham I
2014-08-19 16:26       ` Felipe Balbi
2014-08-22 10:47         ` Kishon Vijay Abraham I
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 11/13] commom: usb: implement "__weak" functions to make compiler happy Kishon Vijay Abraham I
2014-08-19  8:28   ` Lukasz Majewski
2014-08-19 16:14     ` Kishon Vijay Abraham I
2014-08-21 17:32       ` Tom Rini
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 12/13] include: configs: Enable DWC3 and DFU in DRA7xx Kishon Vijay Abraham I
2014-08-18 14:28 ` [U-Boot] [UBOOT RFC PATCH 13/13] dwc3: core: Change the bounce buffer size to 4096 Kishon Vijay Abraham I
2014-08-18 14:41   ` Felipe Balbi
2014-08-19 16:15     ` Kishon Vijay Abraham I
2014-08-19 16:27       ` Felipe Balbi
2014-08-22 11:02         ` Kishon Vijay Abraham I
2014-08-22 13:54           ` Felipe Balbi
2014-08-18 15:29 ` [U-Boot] [UBOOT RFC PATCH 00/13] DRA7xx: Add DWC3 USB driver and enable DFU Tom Rini
2014-08-19  8:56 ` Lukasz Majewski

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=1408372115-4570-7-git-send-email-kishon@ti.com \
    --to=kishon@ti.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.