linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250
@ 2013-01-14 12:59 Vivek Gautam
  2013-01-14 12:59 ` [PATCH v3 1/2] usb: phy: samsung: Common out the generic stuff Vivek Gautam
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Vivek Gautam @ 2013-01-14 12:59 UTC (permalink / raw)
  To: linux-usb
  Cc: devicetree-discuss, linux-kernel, linux-samsung-soc, gregkh,
	balbi, kgene.kim, grant.likely, sylvester.nawrocki, dianders,
	av.tikhomirov, p.paneri

Changes from v2:
 - Renaming 'samsung-usbphy.c' driver to 'samsung-usb2.c' indicating
   usb 2.0 phy controller's driver for Samsung's SoCs.
 - Moving the register definitions and strcuture definitions to
   common header file 'samsung-usbphy.h' to be used across
   usb 2.0 and usb 3.0 phy.
 - Keeping common exported function definitions in samsung-usbphy.c
   which can be used across usb 2.0 and usb 3.0 phy.
 - Writting separate driver file for Samsung's USB 3.0 phy controller.
   and making it dependent on USB_DWC3.

Rebased on top of usb-next followed by following patches/patch-threads:
	-- [PATCH v9 1/2] usb: phy: samsung: Introducing usb phy driver for hsotg
	-- [PATCH] usb: phy: samsung: Add support to set pmu isolation (version 6)
	-- [PATCH v6 0/4] Adding usb2.0 host-phy support for exynos5250

Changes form v1:
 - Moved architecture related patch out of this patch-set.
 - Replaced unnecessary multi-line macro definitions by
   single line definitions.
 - Creating new data structure for USB 3.0 phy type and embedding
   it in 'samsung_usbphy' structure.
 - Adding a flag in 'samsung_usbphy' structure to check if device
   has usb 3.0 type phy or not.
 - Restructuring probe sequence for USB 3.0 phy, such that we are
   initializing only when device has usb3.0 type phy.

Vivek Gautam (2):
  usb: phy: samsung: Common out the generic stuff
  usb: phy: samsung: Add PHY support for USB 3.0 controller

 drivers/usb/phy/Kconfig          |    8 +
 drivers/usb/phy/Makefile         |    3 +-
 drivers/usb/phy/samsung-usb2.c   |  511 +++++++++++++++++++++++++++
 drivers/usb/phy/samsung-usb3.c   |  349 +++++++++++++++++++
 drivers/usb/phy/samsung-usbphy.c |  713 +-------------------------------------
 drivers/usb/phy/samsung-usbphy.h |  328 +++++++++++++++++
 6 files changed, 1205 insertions(+), 707 deletions(-)
 create mode 100644 drivers/usb/phy/samsung-usb2.c
 create mode 100644 drivers/usb/phy/samsung-usb3.c
 create mode 100644 drivers/usb/phy/samsung-usbphy.h

-- 
1.7.6.5


^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v3 1/2] usb: phy: samsung: Common out the generic stuff
  2013-01-14 12:59 [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250 Vivek Gautam
@ 2013-01-14 12:59 ` Vivek Gautam
  2013-01-28 10:24   ` [PATCH v4 " Vivek Gautam
  2013-01-14 12:59 ` [PATCH v3 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller Vivek Gautam
  2013-01-21  6:45 ` [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250 Vivek Gautam
  2 siblings, 1 reply; 14+ messages in thread
From: Vivek Gautam @ 2013-01-14 12:59 UTC (permalink / raw)
  To: linux-usb
  Cc: devicetree-discuss, linux-kernel, linux-samsung-soc, gregkh,
	balbi, kgene.kim, grant.likely, sylvester.nawrocki, dianders,
	av.tikhomirov, p.paneri

Moving register and structure definitions to header file,
and keeping the generic functions to be used across
multiple PHYs in common file "samsung-usbphy.c".
Also renaming the usb 2.0 phy driver to "samsung-usb2.c"

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---
 drivers/usb/phy/Makefile         |    2 +-
 drivers/usb/phy/samsung-usb2.c   |  511 +++++++++++++++++++++++++++
 drivers/usb/phy/samsung-usbphy.c |  713 +-------------------------------------
 drivers/usb/phy/samsung-usbphy.h |  247 +++++++++++++
 4 files changed, 766 insertions(+), 707 deletions(-)
 create mode 100644 drivers/usb/phy/samsung-usb2.c
 create mode 100644 drivers/usb/phy/samsung-usbphy.h

diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index ec304f6..0f4fd4f 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -9,4 +9,4 @@ obj-$(CONFIG_USB_ISP1301)		+= isp1301.o
 obj-$(CONFIG_MV_U3D_PHY)		+= mv_u3d_phy.o
 obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
 obj-$(CONFIG_USB_RCAR_PHY)		+= rcar-phy.o
-obj-$(CONFIG_SAMSUNG_USBPHY)		+= samsung-usbphy.o
+obj-$(CONFIG_SAMSUNG_USBPHY)		+= samsung-usbphy.o samsung-usb2.o
diff --git a/drivers/usb/phy/samsung-usb2.c b/drivers/usb/phy/samsung-usb2.c
new file mode 100644
index 0000000..ffde341
--- /dev/null
+++ b/drivers/usb/phy/samsung-usb2.c
@@ -0,0 +1,511 @@
+/* linux/drivers/usb/phy/samsung-usbphy.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Praveen Paneri <p.paneri@samsung.com>
+ *
+ * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "samsung-usbphy.h"
+
+int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	if (!otg)
+		return -ENODEV;
+
+	if (!otg->host)
+		otg->host = host;
+
+	return 0;
+}
+
+static bool exynos5_phyhost_is_on(void *regs)
+{
+	u32 reg;
+
+	reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	return !(reg & HOST_CTRL0_SIDDQ);
+}
+
+static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phyclk = sphy->ref_clk_freq;
+	u32 phyhost;
+	u32 phyotg;
+	u32 phyhsic;
+	u32 ehcictrl;
+	u32 ohcictrl;
+
+	/*
+	 * phy_usage helps in keeping usage count for phy
+	 * so that the first consumer enabling the phy is also
+	 * the last consumer to disable it.
+	 */
+
+	atomic_inc(&sphy->phy_usage);
+
+	if (exynos5_phyhost_is_on(regs)) {
+		dev_info(sphy->dev, "Already power on PHY\n");
+		return;
+	}
+
+	/* Host configuration */
+	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	/* phy reference clock configuration */
+	phyhost &= ~HOST_CTRL0_FSEL_MASK;
+	phyhost |= HOST_CTRL0_FSEL(phyclk);
+
+	/* host phy reset */
+	phyhost &= ~(HOST_CTRL0_PHYSWRST |
+			HOST_CTRL0_PHYSWRSTALL |
+			HOST_CTRL0_SIDDQ |
+			/* Enable normal mode of operation */
+			HOST_CTRL0_FORCESUSPEND |
+			HOST_CTRL0_FORCESLEEP);
+
+	/* Link reset */
+	phyhost |= (HOST_CTRL0_LINKSWRST |
+			HOST_CTRL0_UTMISWRST |
+			/* COMMON Block configuration during suspend */
+			HOST_CTRL0_COMMONON_N);
+	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+	udelay(10);
+	phyhost &= ~(HOST_CTRL0_LINKSWRST |
+			HOST_CTRL0_UTMISWRST);
+	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	/* OTG configuration */
+	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+
+	/* phy reference clock configuration */
+	phyotg &= ~OTG_SYS_FSEL_MASK;
+	phyotg |= OTG_SYS_FSEL(phyclk);
+
+	/* Enable normal mode of operation */
+	phyotg &= ~(OTG_SYS_FORCESUSPEND |
+			OTG_SYS_SIDDQ_UOTG |
+			OTG_SYS_FORCESLEEP |
+			OTG_SYS_REFCLKSEL_MASK |
+			/* COMMON Block configuration during suspend */
+			OTG_SYS_COMMON_ON);
+
+	/* OTG phy & link reset */
+	phyotg |= (OTG_SYS_PHY0_SWRST |
+			OTG_SYS_LINKSWRST_UOTG |
+			OTG_SYS_PHYLINK_SWRESET |
+			OTG_SYS_OTGDISABLE |
+			/* Set phy refclk */
+			OTG_SYS_REFCLKSEL_CLKCORE);
+
+	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+	udelay(10);
+	phyotg &= ~(OTG_SYS_PHY0_SWRST |
+			OTG_SYS_LINKSWRST_UOTG |
+			OTG_SYS_PHYLINK_SWRESET);
+	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+
+	/* HSIC phy configuration */
+	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+			HSIC_CTRL_REFCLKSEL |
+			HSIC_CTRL_PHYSWRST);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+	udelay(10);
+	phyhsic &= ~HSIC_CTRL_PHYSWRST;
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+	udelay(80);
+
+	/* enable EHCI DMA burst */
+	ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
+	ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
+				HOST_EHCICTRL_ENAINCR4 |
+				HOST_EHCICTRL_ENAINCR8 |
+				HOST_EHCICTRL_ENAINCR16);
+	writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
+
+	/* set ohci_suspend_on_n */
+	ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
+	ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
+	writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
+}
+
+static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phypwr;
+	u32 phyclk;
+	u32 rstcon;
+
+	/* set clock frequency for PLL */
+	phyclk = sphy->ref_clk_freq;
+	phypwr = readl(regs + SAMSUNG_PHYPWR);
+	rstcon = readl(regs + SAMSUNG_RSTCON);
+
+	switch (sphy->drv_data->cpu_type) {
+	case TYPE_S3C64XX:
+		phyclk &= ~PHYCLK_COMMON_ON_N;
+		phypwr &= ~PHYPWR_NORMAL_MASK;
+		rstcon |= RSTCON_SWRST;
+		break;
+	case TYPE_EXYNOS4210:
+		phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
+		rstcon |= RSTCON_SWRST;
+	default:
+		break;
+	}
+
+	writel(phyclk, regs + SAMSUNG_PHYCLK);
+	/* Configure PHY0 for normal operation*/
+	writel(phypwr, regs + SAMSUNG_PHYPWR);
+	/* reset all ports of PHY and Link */
+	writel(rstcon, regs + SAMSUNG_RSTCON);
+	udelay(10);
+	rstcon &= ~RSTCON_SWRST;
+	writel(rstcon, regs + SAMSUNG_RSTCON);
+}
+
+static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phyhost;
+	u32 phyotg;
+	u32 phyhsic;
+
+	if (atomic_dec_return(&sphy->phy_usage) > 0) {
+		dev_info(sphy->dev, "still being used\n");
+		return;
+	}
+
+	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+			HSIC_CTRL_REFCLKSEL |
+			HSIC_CTRL_SIDDQ |
+			HSIC_CTRL_FORCESLEEP |
+			HSIC_CTRL_FORCESUSPEND);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+	phyhost |= (HOST_CTRL0_SIDDQ |
+			HOST_CTRL0_FORCESUSPEND |
+			HOST_CTRL0_FORCESLEEP |
+			HOST_CTRL0_PHYSWRST |
+			HOST_CTRL0_PHYSWRSTALL);
+	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+	phyotg |= (OTG_SYS_FORCESUSPEND |
+			OTG_SYS_SIDDQ_UOTG |
+			OTG_SYS_FORCESLEEP);
+	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+}
+
+static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phypwr;
+
+	phypwr = readl(regs + SAMSUNG_PHYPWR);
+
+	switch (sphy->drv_data->cpu_type) {
+	case TYPE_S3C64XX:
+		phypwr |= PHYPWR_NORMAL_MASK;
+		break;
+	case TYPE_EXYNOS4210:
+		phypwr |= PHYPWR_NORMAL_MASK_PHY0;
+	default:
+		break;
+	}
+
+	/* Disable analog and otg block power */
+	writel(phypwr, regs + SAMSUNG_PHYPWR);
+}
+
+/*
+ * The function passed to the usb driver for phy initialization
+ */
+static int samsung_usbphy_init(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	struct usb_bus *host = NULL;
+	unsigned long flags;
+	int ret = 0;
+
+	sphy = phy_to_sphy(phy);
+
+	host = phy->otg->host;
+
+	/* Enable the phy clock */
+	ret = clk_prepare_enable(sphy->clk);
+	if (ret) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return ret;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	if (host) {
+		/* setting default phy-type for USB 2.0 */
+		if (!strstr(dev_name(host->controller), "ehci") ||
+				!strstr(dev_name(host->controller), "ohci"))
+			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+	} else {
+		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+	}
+
+	/* Disable phy isolation */
+	if (sphy->plat && sphy->plat->pmu_isolation)
+		sphy->plat->pmu_isolation(false);
+	else
+		samsung_usbphy_set_isolation(sphy, false);
+
+	/* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
+	samsung_usbphy_cfg_sel(sphy);
+
+	/* Initialize usb phy registers */
+	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+		samsung_exynos5_usbphy_enable(sphy);
+	else
+		samsung_usbphy_enable(sphy);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	/* Disable the phy clock */
+	clk_disable_unprepare(sphy->clk);
+
+	return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usbphy_shutdown(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	struct usb_bus *host = NULL;
+	unsigned long flags;
+
+	sphy = phy_to_sphy(phy);
+
+	host = phy->otg->host;
+
+	if (clk_prepare_enable(sphy->clk)) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	if (host) {
+		/* setting default phy-type for USB 2.0 */
+		if (!strstr(dev_name(host->controller), "ehci") ||
+				!strstr(dev_name(host->controller), "ohci"))
+			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+	} else {
+		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+	}
+
+	/* De-initialize usb phy registers */
+	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+		samsung_exynos5_usbphy_disable(sphy);
+	else
+		samsung_usbphy_disable(sphy);
+
+	/* Enable phy isolation */
+	if (sphy->plat && sphy->plat->pmu_isolation)
+		sphy->plat->pmu_isolation(true);
+	else
+		samsung_usbphy_set_isolation(sphy, true);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	clk_disable_unprepare(sphy->clk);
+}
+
+static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy;
+	struct usb_otg *otg;
+	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+	const struct samsung_usbphy_drvdata *drv_data;
+	struct device *dev = &pdev->dev;
+	struct resource *phy_mem;
+	void __iomem	*phy_base;
+	struct clk *clk;
+	int ret;
+
+	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!phy_mem) {
+		dev_err(dev, "%s: missing mem resource\n", __func__);
+		return -ENODEV;
+	}
+
+	phy_base = devm_request_and_ioremap(dev, phy_mem);
+	if (!phy_base) {
+		dev_err(dev, "%s: register mapping failed\n", __func__);
+		return -ENXIO;
+	}
+
+	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+	if (!sphy)
+		return -ENOMEM;
+
+	otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg)
+		return -ENOMEM;
+
+	drv_data = samsung_usbphy_get_driver_data(pdev);
+
+	if (drv_data->cpu_type == TYPE_EXYNOS5250)
+		clk = devm_clk_get(dev, "usbhost");
+	else
+		clk = devm_clk_get(dev, "otg");
+
+	if (IS_ERR(clk)) {
+		dev_err(dev, "Failed to get otg clock\n");
+		return PTR_ERR(clk);
+	}
+
+	sphy->dev = dev;
+
+	if (dev->of_node) {
+		ret = samsung_usbphy_parse_dt(sphy);
+		if (ret < 0)
+			return ret;
+	} else {
+		if (!pdata) {
+			dev_err(dev, "no platform data specified\n");
+			return -EINVAL;
+		}
+	}
+
+	sphy->plat		= pdata;
+	sphy->regs		= phy_base;
+	sphy->clk		= clk;
+	sphy->drv_data		= drv_data;
+	sphy->phy.dev		= sphy->dev;
+	sphy->phy.label		= "samsung-usbphy";
+	sphy->phy.init		= samsung_usbphy_init;
+	sphy->phy.shutdown	= samsung_usbphy_shutdown;
+	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy);
+
+	sphy->phy.otg		= otg;
+	sphy->phy.otg->phy	= &sphy->phy;
+	sphy->phy.otg->set_host = samsung_usbphy_set_host;
+
+	spin_lock_init(&sphy->lock);
+
+	platform_set_drvdata(pdev, sphy);
+
+	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
+}
+
+static int __exit samsung_usbphy_remove(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&sphy->phy);
+
+	if (sphy->pmuregs)
+		iounmap(sphy->pmuregs);
+	if (sphy->sysreg)
+		iounmap(sphy->sysreg);
+
+	return 0;
+}
+
+static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
+	.cpu_type		= TYPE_S3C64XX,
+	.devphy_en_mask		= S3C64XX_USBPHY_ENABLE,
+};
+
+static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
+	.cpu_type		= TYPE_EXYNOS4210,
+	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE,
+	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
+};
+
+static struct samsung_usbphy_drvdata usbphy_exynos5 = {
+	.cpu_type		= TYPE_EXYNOS5250,
+	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
+	.hostphy_reg_offset	= EXYNOS_USBHOST_PHY_CTRL_OFFSET,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+	{
+		.compatible = "samsung,s3c64xx-usbphy",
+		.data = &usbphy_s3c64xx,
+	}, {
+		.compatible = "samsung,exynos4210-usbphy",
+		.data = &usbphy_exynos4,
+	}, {
+		.compatible = "samsung,exynos5250-usbphy",
+		.data = &usbphy_exynos5
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+	{
+		.name		= "s3c64xx-usbphy",
+		.driver_data	= (unsigned long)&usbphy_s3c64xx,
+	}, {
+		.name		= "exynos4210-usbphy",
+		.driver_data	= (unsigned long)&usbphy_exynos4,
+	}, {
+		.name		= "exynos5250-usbphy",
+		.driver_data	= (unsigned long)&usbphy_exynos5,
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usbphy_driver = {
+	.probe		= samsung_usbphy_probe,
+	.remove		= __devexit_p(samsung_usbphy_remove),
+	.id_table	= samsung_usbphy_driver_ids,
+	.driver		= {
+		.name	= "samsung-usbphy",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+	},
+};
+
+module_platform_driver(samsung_usbphy_driver);
+
+MODULE_DESCRIPTION("Samsung USB phy controller");
+MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usbphy");
diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
index 355c6b2..83ca60e 100644
--- a/drivers/usb/phy/samsung-usbphy.c
+++ b/drivers/usb/phy/samsung-usbphy.c
@@ -5,7 +5,7 @@
  *
  * Author: Praveen Paneri <p.paneri@samsung.com>
  *
- * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
  * OHCI-EXYNOS controllers.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,233 +21,16 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/usb/otg.h>
 #include <linux/usb/samsung_usb_phy.h>
-#include <linux/platform_data/samsung-usbphy.h>
 
-/* Register definitions */
+#include "samsung-usbphy.h"
 
-#define SAMSUNG_PHYPWR				(0x00)
-
-#define PHYPWR_NORMAL_MASK			(0x19 << 0)
-#define PHYPWR_OTG_DISABLE			(0x1 << 4)
-#define PHYPWR_ANALOG_POWERDOWN			(0x1 << 3)
-#define PHYPWR_FORCE_SUSPEND			(0x1 << 1)
-/* For Exynos4 */
-#define PHYPWR_NORMAL_MASK_PHY0			(0x39 << 0)
-#define PHYPWR_SLEEP_PHY0			(0x1 << 5)
-
-#define SAMSUNG_PHYCLK				(0x04)
-
-#define PHYCLK_MODE_USB11			(0x1 << 6)
-#define PHYCLK_EXT_OSC				(0x1 << 5)
-#define PHYCLK_COMMON_ON_N			(0x1 << 4)
-#define PHYCLK_ID_PULL				(0x1 << 2)
-#define PHYCLK_CLKSEL_MASK			(0x3 << 0)
-#define PHYCLK_CLKSEL_48M			(0x0 << 0)
-#define PHYCLK_CLKSEL_12M			(0x2 << 0)
-#define PHYCLK_CLKSEL_24M			(0x3 << 0)
-
-#define SAMSUNG_RSTCON				(0x08)
-
-#define RSTCON_PHYLINK_SWRST			(0x1 << 2)
-#define RSTCON_HLINK_SWRST			(0x1 << 1)
-#define RSTCON_SWRST				(0x1 << 0)
-
-/* EXYNOS5 */
-#define EXYNOS5_PHY_HOST_CTRL0			(0x00)
-
-#define HOST_CTRL0_PHYSWRSTALL			(0x1 << 31)
-
-#define HOST_CTRL0_REFCLKSEL_MASK		(0x3 << 19)
-#define HOST_CTRL0_REFCLKSEL_XTAL		(0x0 << 19)
-#define HOST_CTRL0_REFCLKSEL_EXTL		(0x1 << 19)
-#define HOST_CTRL0_REFCLKSEL_CLKCORE		(0x2 << 19)
-
-#define HOST_CTRL0_FSEL_MASK			(0x7 << 16)
-#define HOST_CTRL0_FSEL(_x)			((_x) << 16)
-
-#define FSEL_CLKSEL_50M				(0x7)
-#define FSEL_CLKSEL_24M				(0x5)
-#define FSEL_CLKSEL_20M				(0x4)
-#define FSEL_CLKSEL_19200K			(0x3)
-#define FSEL_CLKSEL_12M				(0x2)
-#define FSEL_CLKSEL_10M				(0x1)
-#define FSEL_CLKSEL_9600K			(0x0)
-
-#define HOST_CTRL0_TESTBURNIN			(0x1 << 11)
-#define HOST_CTRL0_RETENABLE			(0x1 << 10)
-#define HOST_CTRL0_COMMONON_N			(0x1 << 9)
-#define HOST_CTRL0_SIDDQ			(0x1 << 6)
-#define HOST_CTRL0_FORCESLEEP			(0x1 << 5)
-#define HOST_CTRL0_FORCESUSPEND			(0x1 << 4)
-#define HOST_CTRL0_WORDINTERFACE		(0x1 << 3)
-#define HOST_CTRL0_UTMISWRST			(0x1 << 2)
-#define HOST_CTRL0_LINKSWRST			(0x1 << 1)
-#define HOST_CTRL0_PHYSWRST			(0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_TUNE0			(0x04)
-
-#define EXYNOS5_PHY_HSIC_CTRL1			(0x10)
-
-#define EXYNOS5_PHY_HSIC_TUNE1			(0x14)
-
-#define EXYNOS5_PHY_HSIC_CTRL2			(0x20)
-
-#define EXYNOS5_PHY_HSIC_TUNE2			(0x24)
-
-#define HSIC_CTRL_REFCLKSEL_MASK		(0x3 << 23)
-#define HSIC_CTRL_REFCLKSEL			(0x2 << 23)
-
-#define HSIC_CTRL_REFCLKDIV_MASK		(0x7f << 16)
-#define HSIC_CTRL_REFCLKDIV(_x)			((_x) << 16)
-#define HSIC_CTRL_REFCLKDIV_12			(0x24 << 16)
-#define HSIC_CTRL_REFCLKDIV_15			(0x1c << 16)
-#define HSIC_CTRL_REFCLKDIV_16			(0x1a << 16)
-#define HSIC_CTRL_REFCLKDIV_19_2		(0x15 << 16)
-#define HSIC_CTRL_REFCLKDIV_20			(0x14 << 16)
-
-#define HSIC_CTRL_SIDDQ				(0x1 << 6)
-#define HSIC_CTRL_FORCESLEEP			(0x1 << 5)
-#define HSIC_CTRL_FORCESUSPEND			(0x1 << 4)
-#define HSIC_CTRL_WORDINTERFACE			(0x1 << 3)
-#define HSIC_CTRL_UTMISWRST			(0x1 << 2)
-#define HSIC_CTRL_PHYSWRST			(0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_EHCICTRL		(0x30)
-
-#define HOST_EHCICTRL_ENAINCRXALIGN		(0x1 << 29)
-#define HOST_EHCICTRL_ENAINCR4			(0x1 << 28)
-#define HOST_EHCICTRL_ENAINCR8			(0x1 << 27)
-#define HOST_EHCICTRL_ENAINCR16			(0x1 << 26)
-
-#define EXYNOS5_PHY_HOST_OHCICTRL		(0x34)
-
-#define HOST_OHCICTRL_SUSPLGCY			(0x1 << 3)
-#define HOST_OHCICTRL_APPSTARTCLK		(0x1 << 2)
-#define HOST_OHCICTRL_CNTSEL			(0x1 << 1)
-#define HOST_OHCICTRL_CLKCKTRST			(0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_SYS			(0x38)
-
-#define OTG_SYS_PHYLINK_SWRESET			(0x1 << 14)
-#define OTG_SYS_LINKSWRST_UOTG			(0x1 << 13)
-#define OTG_SYS_PHY0_SWRST			(0x1 << 12)
-
-#define OTG_SYS_REFCLKSEL_MASK			(0x3 << 9)
-#define OTG_SYS_REFCLKSEL_XTAL			(0x0 << 9)
-#define OTG_SYS_REFCLKSEL_EXTL			(0x1 << 9)
-#define OTG_SYS_REFCLKSEL_CLKCORE		(0x2 << 9)
-
-#define OTG_SYS_IDPULLUP_UOTG			(0x1 << 8)
-#define OTG_SYS_COMMON_ON			(0x1 << 7)
-
-#define OTG_SYS_FSEL_MASK			(0x7 << 4)
-#define OTG_SYS_FSEL(_x)			((_x) << 4)
-
-#define OTG_SYS_FORCESLEEP			(0x1 << 3)
-#define OTG_SYS_OTGDISABLE			(0x1 << 2)
-#define OTG_SYS_SIDDQ_UOTG			(0x1 << 1)
-#define OTG_SYS_FORCESUSPEND			(0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_TUNE			(0x40)
-
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#ifndef KHZ
-#define KHZ (1000)
-#endif
-
-#define EXYNOS_USBHOST_PHY_CTRL_OFFSET		(0x4)
-#define S3C64XX_USBPHY_ENABLE			(0x1 << 16)
-#define EXYNOS_USBPHY_ENABLE			(0x1 << 0)
-#define EXYNOS_USB20PHY_CFG_HOST_LINK		(0x1 << 0)
-
-enum samsung_cpu_type {
-	TYPE_S3C64XX,
-	TYPE_EXYNOS4210,
-	TYPE_EXYNOS5250,
-};
-
-/*
- * struct samsung_usbphy_drvdata - driver data for various SoC variants
- * @cpu_type: machine identifier
- * @devphy_en_mask: device phy enable mask for PHY CONTROL register
- * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
- * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
- *		       mapped address of system controller.
- * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
- *		       mapped address of system controller.
- *
- *	Here we have a separate mask for device type phy.
- *	Having different masks for host and device type phy helps
- *	in setting independent masks in case of SoCs like S5PV210,
- *	in which PHY0 and PHY1 enable bits belong to same register
- *	placed at position 0 and 1 respectively.
- *	Although for newer SoCs like exynos these bits belong to
- *	different registers altogether placed at position 0.
- */
-struct samsung_usbphy_drvdata {
-	int cpu_type;
-	int devphy_en_mask;
-	int hostphy_en_mask;
-	u32 devphy_reg_offset;
-	u32 hostphy_reg_offset;
-};
-
-/*
- * struct samsung_usbphy - transceiver driver state
- * @phy: transceiver structure
- * @plat: platform data
- * @dev: The parent device supplied to the probe function
- * @clk: usb phy clock
- * @regs: usb phy controller registers memory base
- * @pmuregs: USB device PHY_CONTROL register memory base
- * @sysreg: USB2.0 PHY_CFG register memory base
- * @ref_clk_freq: reference clock frequency selection
- * @drv_data: driver data available for different SoCs
- * @phy_type: Samsung SoCs specific phy types:	#HOST
- *						#DEVICE
- * @phy_usage: usage count for phy
- * @lock: lock for phy operations
- */
-struct samsung_usbphy {
-	struct usb_phy	phy;
-	struct samsung_usbphy_data *plat;
-	struct device	*dev;
-	struct clk	*clk;
-	void __iomem	*regs;
-	void __iomem	*pmuregs;
-	void __iomem	*sysreg;
-	int		ref_clk_freq;
-	const struct samsung_usbphy_drvdata *drv_data;
-	enum samsung_usb_phy_type phy_type;
-	atomic_t	phy_usage;
-	spinlock_t	lock;
-};
-
-#define phy_to_sphy(x)		container_of((x), struct samsung_usbphy, phy)
-
-int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	if (!otg)
-		return -ENODEV;
-
-	if (!otg->host)
-		otg->host = host;
-
-	return 0;
-}
-
-static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
+int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
 {
 	struct device_node *usbphy_sys;
 
@@ -286,7 +69,7 @@ err0:
  * Here 'on = true' would mean USB PHY block is isolated, hence
  * de-activated and vice-versa.
  */
-static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
+void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
 {
 	void __iomem *reg = NULL;
 	u32 reg_val;
@@ -338,7 +121,7 @@ static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
 /*
  * Configure the mode of working of usb-phy here: HOST/DEVICE.
  */
-static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
+void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
 {
 	u32 reg;
 
@@ -362,7 +145,7 @@ static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
  * This make sure that correct PHY type is selected before
  * any operation on PHY.
  */
-static int samsung_usbphy_set_type(struct usb_phy *phy,
+int samsung_usbphy_set_type(struct usb_phy *phy,
 				enum samsung_usb_phy_type phy_type)
 {
 	struct samsung_usbphy *sphy = phy_to_sphy(phy);
@@ -375,7 +158,7 @@ static int samsung_usbphy_set_type(struct usb_phy *phy,
 /*
  * Returns reference clock frequency selection value
  */
-static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
+int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
 {
 	struct clk *ref_clk;
 	int refclk_freq = 0;
@@ -444,485 +227,3 @@ static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
 	return refclk_freq;
 }
 
-static bool exynos5_phyhost_is_on(void *regs)
-{
-	u32 reg;
-
-	reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	return !(reg & HOST_CTRL0_SIDDQ);
-}
-
-static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phyclk = sphy->ref_clk_freq;
-	u32 phyhost;
-	u32 phyotg;
-	u32 phyhsic;
-	u32 ehcictrl;
-	u32 ohcictrl;
-
-	/*
-	 * phy_usage helps in keeping usage count for phy
-	 * so that the first consumer enabling the phy is also
-	 * the last consumer to disable it.
-	 */
-
-	atomic_inc(&sphy->phy_usage);
-
-	if (exynos5_phyhost_is_on(regs)) {
-		dev_info(sphy->dev, "Already power on PHY\n");
-		return;
-	}
-
-	/* Host configuration */
-	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	/* phy reference clock configuration */
-	phyhost &= ~HOST_CTRL0_FSEL_MASK;
-	phyhost |= HOST_CTRL0_FSEL(phyclk);
-
-	/* host phy reset */
-	phyhost &= ~(HOST_CTRL0_PHYSWRST |
-			HOST_CTRL0_PHYSWRSTALL |
-			HOST_CTRL0_SIDDQ |
-			/* Enable normal mode of operation */
-			HOST_CTRL0_FORCESUSPEND |
-			HOST_CTRL0_FORCESLEEP);
-
-	/* Link reset */
-	phyhost |= (HOST_CTRL0_LINKSWRST |
-			HOST_CTRL0_UTMISWRST |
-			/* COMMON Block configuration during suspend */
-			HOST_CTRL0_COMMONON_N);
-	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-	udelay(10);
-	phyhost &= ~(HOST_CTRL0_LINKSWRST |
-			HOST_CTRL0_UTMISWRST);
-	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	/* OTG configuration */
-	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
-
-	/* phy reference clock configuration */
-	phyotg &= ~OTG_SYS_FSEL_MASK;
-	phyotg |= OTG_SYS_FSEL(phyclk);
-
-	/* Enable normal mode of operation */
-	phyotg &= ~(OTG_SYS_FORCESUSPEND |
-			OTG_SYS_SIDDQ_UOTG |
-			OTG_SYS_FORCESLEEP |
-			OTG_SYS_REFCLKSEL_MASK |
-			/* COMMON Block configuration during suspend */
-			OTG_SYS_COMMON_ON);
-
-	/* OTG phy & link reset */
-	phyotg |= (OTG_SYS_PHY0_SWRST |
-			OTG_SYS_LINKSWRST_UOTG |
-			OTG_SYS_PHYLINK_SWRESET |
-			OTG_SYS_OTGDISABLE |
-			/* Set phy refclk */
-			OTG_SYS_REFCLKSEL_CLKCORE);
-
-	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-	udelay(10);
-	phyotg &= ~(OTG_SYS_PHY0_SWRST |
-			OTG_SYS_LINKSWRST_UOTG |
-			OTG_SYS_PHYLINK_SWRESET);
-	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-
-	/* HSIC phy configuration */
-	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
-			HSIC_CTRL_REFCLKSEL |
-			HSIC_CTRL_PHYSWRST);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-	udelay(10);
-	phyhsic &= ~HSIC_CTRL_PHYSWRST;
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
-	udelay(80);
-
-	/* enable EHCI DMA burst */
-	ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
-	ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
-				HOST_EHCICTRL_ENAINCR4 |
-				HOST_EHCICTRL_ENAINCR8 |
-				HOST_EHCICTRL_ENAINCR16);
-	writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
-
-	/* set ohci_suspend_on_n */
-	ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
-	ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
-	writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
-}
-
-static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phypwr;
-	u32 phyclk;
-	u32 rstcon;
-
-	/* set clock frequency for PLL */
-	phyclk = sphy->ref_clk_freq;
-	phypwr = readl(regs + SAMSUNG_PHYPWR);
-	rstcon = readl(regs + SAMSUNG_RSTCON);
-
-	switch (sphy->drv_data->cpu_type) {
-	case TYPE_S3C64XX:
-		phyclk &= ~PHYCLK_COMMON_ON_N;
-		phypwr &= ~PHYPWR_NORMAL_MASK;
-		rstcon |= RSTCON_SWRST;
-		break;
-	case TYPE_EXYNOS4210:
-		phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
-		rstcon |= RSTCON_SWRST;
-	default:
-		break;
-	}
-
-	writel(phyclk, regs + SAMSUNG_PHYCLK);
-	/* Configure PHY0 for normal operation*/
-	writel(phypwr, regs + SAMSUNG_PHYPWR);
-	/* reset all ports of PHY and Link */
-	writel(rstcon, regs + SAMSUNG_RSTCON);
-	udelay(10);
-	rstcon &= ~RSTCON_SWRST;
-	writel(rstcon, regs + SAMSUNG_RSTCON);
-}
-
-static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phyhost;
-	u32 phyotg;
-	u32 phyhsic;
-
-	if (atomic_dec_return(&sphy->phy_usage) > 0) {
-		dev_info(sphy->dev, "still being used\n");
-		return;
-	}
-
-	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
-			HSIC_CTRL_REFCLKSEL |
-			HSIC_CTRL_SIDDQ |
-			HSIC_CTRL_FORCESLEEP |
-			HSIC_CTRL_FORCESUSPEND);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
-	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-	phyhost |= (HOST_CTRL0_SIDDQ |
-			HOST_CTRL0_FORCESUSPEND |
-			HOST_CTRL0_FORCESLEEP |
-			HOST_CTRL0_PHYSWRST |
-			HOST_CTRL0_PHYSWRSTALL);
-	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
-	phyotg |= (OTG_SYS_FORCESUSPEND |
-			OTG_SYS_SIDDQ_UOTG |
-			OTG_SYS_FORCESLEEP);
-	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-}
-
-static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phypwr;
-
-	phypwr = readl(regs + SAMSUNG_PHYPWR);
-
-	switch (sphy->drv_data->cpu_type) {
-	case TYPE_S3C64XX:
-		phypwr |= PHYPWR_NORMAL_MASK;
-		break;
-	case TYPE_EXYNOS4210:
-		phypwr |= PHYPWR_NORMAL_MASK_PHY0;
-	default:
-		break;
-	}
-
-	/* Disable analog and otg block power */
-	writel(phypwr, regs + SAMSUNG_PHYPWR);
-}
-
-/*
- * The function passed to the usb driver for phy initialization
- */
-static int samsung_usbphy_init(struct usb_phy *phy)
-{
-	struct samsung_usbphy *sphy;
-	struct usb_bus *host = NULL;
-	unsigned long flags;
-	int ret = 0;
-
-	sphy = phy_to_sphy(phy);
-
-	host = phy->otg->host;
-
-	/* Enable the phy clock */
-	ret = clk_prepare_enable(sphy->clk);
-	if (ret) {
-		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
-		return ret;
-	}
-
-	spin_lock_irqsave(&sphy->lock, flags);
-
-	if (host) {
-		/* setting default phy-type for USB 2.0 */
-		if (!strstr(dev_name(host->controller), "ehci") ||
-				!strstr(dev_name(host->controller), "ohci"))
-			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
-	} else {
-		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
-	}
-
-	/* Disable phy isolation */
-	if (sphy->plat && sphy->plat->pmu_isolation)
-		sphy->plat->pmu_isolation(false);
-	else
-		samsung_usbphy_set_isolation(sphy, false);
-
-	/* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
-	samsung_usbphy_cfg_sel(sphy);
-
-	/* Initialize usb phy registers */
-	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-		samsung_exynos5_usbphy_enable(sphy);
-	else
-		samsung_usbphy_enable(sphy);
-
-	spin_unlock_irqrestore(&sphy->lock, flags);
-
-	/* Disable the phy clock */
-	clk_disable_unprepare(sphy->clk);
-
-	return ret;
-}
-
-/*
- * The function passed to the usb driver for phy shutdown
- */
-static void samsung_usbphy_shutdown(struct usb_phy *phy)
-{
-	struct samsung_usbphy *sphy;
-	struct usb_bus *host = NULL;
-	unsigned long flags;
-
-	sphy = phy_to_sphy(phy);
-
-	host = phy->otg->host;
-
-	if (clk_prepare_enable(sphy->clk)) {
-		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
-		return;
-	}
-
-	spin_lock_irqsave(&sphy->lock, flags);
-
-	if (host) {
-		/* setting default phy-type for USB 2.0 */
-		if (!strstr(dev_name(host->controller), "ehci") ||
-				!strstr(dev_name(host->controller), "ohci"))
-			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
-	} else {
-		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
-	}
-
-	/* De-initialize usb phy registers */
-	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-		samsung_exynos5_usbphy_disable(sphy);
-	else
-		samsung_usbphy_disable(sphy);
-
-	/* Enable phy isolation */
-	if (sphy->plat && sphy->plat->pmu_isolation)
-		sphy->plat->pmu_isolation(true);
-	else
-		samsung_usbphy_set_isolation(sphy, true);
-
-	spin_unlock_irqrestore(&sphy->lock, flags);
-
-	clk_disable_unprepare(sphy->clk);
-}
-
-static const struct of_device_id samsung_usbphy_dt_match[];
-
-static inline const struct samsung_usbphy_drvdata
-*samsung_usbphy_get_driver_data(struct platform_device *pdev)
-{
-	if (pdev->dev.of_node) {
-		const struct of_device_id *match;
-		match = of_match_node(samsung_usbphy_dt_match,
-							pdev->dev.of_node);
-		return match->data;
-	}
-
-	return (struct samsung_usbphy_drvdata *)
-				platform_get_device_id(pdev)->driver_data;
-}
-
-static int __devinit samsung_usbphy_probe(struct platform_device *pdev)
-{
-	struct samsung_usbphy *sphy;
-	struct usb_otg *otg;
-	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
-	const struct samsung_usbphy_drvdata *drv_data;
-	struct device *dev = &pdev->dev;
-	struct resource *phy_mem;
-	void __iomem	*phy_base;
-	struct clk *clk;
-	int ret;
-
-	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!phy_mem) {
-		dev_err(dev, "%s: missing mem resource\n", __func__);
-		return -ENODEV;
-	}
-
-	phy_base = devm_request_and_ioremap(dev, phy_mem);
-	if (!phy_base) {
-		dev_err(dev, "%s: register mapping failed\n", __func__);
-		return -ENXIO;
-	}
-
-	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
-	if (!sphy)
-		return -ENOMEM;
-
-	otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
-	if (!otg)
-		return -ENOMEM;
-
-	drv_data = samsung_usbphy_get_driver_data(pdev);
-
-	if (drv_data->cpu_type == TYPE_EXYNOS5250)
-		clk = devm_clk_get(dev, "usbhost");
-	else
-		clk = devm_clk_get(dev, "otg");
-
-	if (IS_ERR(clk)) {
-		dev_err(dev, "Failed to get otg clock\n");
-		return PTR_ERR(clk);
-	}
-
-	sphy->dev = dev;
-
-	if (dev->of_node) {
-		ret = samsung_usbphy_parse_dt(sphy);
-		if (ret < 0)
-			return ret;
-	} else {
-		if (!pdata) {
-			dev_err(dev, "no platform data specified\n");
-			return -EINVAL;
-		}
-	}
-
-	sphy->plat		= pdata;
-	sphy->regs		= phy_base;
-	sphy->clk		= clk;
-	sphy->drv_data		= drv_data;
-	sphy->phy.dev		= sphy->dev;
-	sphy->phy.label		= "samsung-usbphy";
-	sphy->phy.init		= samsung_usbphy_init;
-	sphy->phy.shutdown	= samsung_usbphy_shutdown;
-	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy);
-
-	sphy->phy.otg		= otg;
-	sphy->phy.otg->phy	= &sphy->phy;
-	sphy->phy.otg->set_host = samsung_usbphy_set_host;
-
-	spin_lock_init(&sphy->lock);
-
-	platform_set_drvdata(pdev, sphy);
-
-	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
-}
-
-static int __exit samsung_usbphy_remove(struct platform_device *pdev)
-{
-	struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
-
-	usb_remove_phy(&sphy->phy);
-
-	if (sphy->pmuregs)
-		iounmap(sphy->pmuregs);
-	if (sphy->sysreg)
-		iounmap(sphy->sysreg);
-
-	return 0;
-}
-
-static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
-	.cpu_type		= TYPE_S3C64XX,
-	.devphy_en_mask		= S3C64XX_USBPHY_ENABLE,
-};
-
-static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
-	.cpu_type		= TYPE_EXYNOS4210,
-	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE,
-	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
-};
-
-static struct samsung_usbphy_drvdata usbphy_exynos5 = {
-	.cpu_type		= TYPE_EXYNOS5250,
-	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
-	.hostphy_reg_offset	= EXYNOS_USBHOST_PHY_CTRL_OFFSET,
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id samsung_usbphy_dt_match[] = {
-	{
-		.compatible = "samsung,s3c64xx-usbphy",
-		.data = &usbphy_s3c64xx,
-	}, {
-		.compatible = "samsung,exynos4210-usbphy",
-		.data = &usbphy_exynos4,
-	}, {
-		.compatible = "samsung,exynos5250-usbphy",
-		.data = &usbphy_exynos5
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
-#endif
-
-static struct platform_device_id samsung_usbphy_driver_ids[] = {
-	{
-		.name		= "s3c64xx-usbphy",
-		.driver_data	= (unsigned long)&usbphy_s3c64xx,
-	}, {
-		.name		= "exynos4210-usbphy",
-		.driver_data	= (unsigned long)&usbphy_exynos4,
-	}, {
-		.name		= "exynos5250-usbphy",
-		.driver_data	= (unsigned long)&usbphy_exynos5,
-	},
-	{},
-};
-
-MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
-
-static struct platform_driver samsung_usbphy_driver = {
-	.probe		= samsung_usbphy_probe,
-	.remove		= __devexit_p(samsung_usbphy_remove),
-	.id_table	= samsung_usbphy_driver_ids,
-	.driver		= {
-		.name	= "samsung-usbphy",
-		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(samsung_usbphy_dt_match),
-	},
-};
-
-module_platform_driver(samsung_usbphy_driver);
-
-MODULE_DESCRIPTION("Samsung USB phy controller");
-MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:samsung-usbphy");
diff --git a/drivers/usb/phy/samsung-usbphy.h b/drivers/usb/phy/samsung-usbphy.h
new file mode 100644
index 0000000..969632b
--- /dev/null
+++ b/drivers/usb/phy/samsung-usbphy.h
@@ -0,0 +1,247 @@
+/* linux/drivers/usb/phy/samsung-usbphy.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/usb/phy.h>
+
+/* Register definitions */
+
+#define SAMSUNG_PHYPWR				(0x00)
+
+#define PHYPWR_NORMAL_MASK			(0x19 << 0)
+#define PHYPWR_OTG_DISABLE			(0x1 << 4)
+#define PHYPWR_ANALOG_POWERDOWN			(0x1 << 3)
+#define PHYPWR_FORCE_SUSPEND			(0x1 << 1)
+/* For Exynos4 */
+#define PHYPWR_NORMAL_MASK_PHY0			(0x39 << 0)
+#define PHYPWR_SLEEP_PHY0			(0x1 << 5)
+
+#define SAMSUNG_PHYCLK				(0x04)
+
+#define PHYCLK_MODE_USB11			(0x1 << 6)
+#define PHYCLK_EXT_OSC				(0x1 << 5)
+#define PHYCLK_COMMON_ON_N			(0x1 << 4)
+#define PHYCLK_ID_PULL				(0x1 << 2)
+#define PHYCLK_CLKSEL_MASK			(0x3 << 0)
+#define PHYCLK_CLKSEL_48M			(0x0 << 0)
+#define PHYCLK_CLKSEL_12M			(0x2 << 0)
+#define PHYCLK_CLKSEL_24M			(0x3 << 0)
+
+#define SAMSUNG_RSTCON				(0x08)
+
+#define RSTCON_PHYLINK_SWRST			(0x1 << 2)
+#define RSTCON_HLINK_SWRST			(0x1 << 1)
+#define RSTCON_SWRST				(0x1 << 0)
+
+/* EXYNOS5 */
+#define EXYNOS5_PHY_HOST_CTRL0			(0x00)
+
+#define HOST_CTRL0_PHYSWRSTALL			(0x1 << 31)
+
+#define HOST_CTRL0_REFCLKSEL_MASK		(0x3 << 19)
+#define HOST_CTRL0_REFCLKSEL_XTAL		(0x0 << 19)
+#define HOST_CTRL0_REFCLKSEL_EXTL		(0x1 << 19)
+#define HOST_CTRL0_REFCLKSEL_CLKCORE		(0x2 << 19)
+
+#define HOST_CTRL0_FSEL_MASK			(0x7 << 16)
+#define HOST_CTRL0_FSEL(_x)			((_x) << 16)
+
+#define FSEL_CLKSEL_50M				(0x7)
+#define FSEL_CLKSEL_24M				(0x5)
+#define FSEL_CLKSEL_20M				(0x4)
+#define FSEL_CLKSEL_19200K			(0x3)
+#define FSEL_CLKSEL_12M				(0x2)
+#define FSEL_CLKSEL_10M				(0x1)
+#define FSEL_CLKSEL_9600K			(0x0)
+
+#define HOST_CTRL0_TESTBURNIN			(0x1 << 11)
+#define HOST_CTRL0_RETENABLE			(0x1 << 10)
+#define HOST_CTRL0_COMMONON_N			(0x1 << 9)
+#define HOST_CTRL0_SIDDQ			(0x1 << 6)
+#define HOST_CTRL0_FORCESLEEP			(0x1 << 5)
+#define HOST_CTRL0_FORCESUSPEND			(0x1 << 4)
+#define HOST_CTRL0_WORDINTERFACE		(0x1 << 3)
+#define HOST_CTRL0_UTMISWRST			(0x1 << 2)
+#define HOST_CTRL0_LINKSWRST			(0x1 << 1)
+#define HOST_CTRL0_PHYSWRST			(0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_TUNE0			(0x04)
+
+#define EXYNOS5_PHY_HSIC_CTRL1			(0x10)
+
+#define EXYNOS5_PHY_HSIC_TUNE1			(0x14)
+
+#define EXYNOS5_PHY_HSIC_CTRL2			(0x20)
+
+#define EXYNOS5_PHY_HSIC_TUNE2			(0x24)
+
+#define HSIC_CTRL_REFCLKSEL_MASK		(0x3 << 23)
+#define HSIC_CTRL_REFCLKSEL			(0x2 << 23)
+
+#define HSIC_CTRL_REFCLKDIV_MASK		(0x7f << 16)
+#define HSIC_CTRL_REFCLKDIV(_x)			((_x) << 16)
+#define HSIC_CTRL_REFCLKDIV_12			(0x24 << 16)
+#define HSIC_CTRL_REFCLKDIV_15			(0x1c << 16)
+#define HSIC_CTRL_REFCLKDIV_16			(0x1a << 16)
+#define HSIC_CTRL_REFCLKDIV_19_2		(0x15 << 16)
+#define HSIC_CTRL_REFCLKDIV_20			(0x14 << 16)
+
+#define HSIC_CTRL_SIDDQ				(0x1 << 6)
+#define HSIC_CTRL_FORCESLEEP			(0x1 << 5)
+#define HSIC_CTRL_FORCESUSPEND			(0x1 << 4)
+#define HSIC_CTRL_WORDINTERFACE			(0x1 << 3)
+#define HSIC_CTRL_UTMISWRST			(0x1 << 2)
+#define HSIC_CTRL_PHYSWRST			(0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_EHCICTRL		(0x30)
+
+#define HOST_EHCICTRL_ENAINCRXALIGN		(0x1 << 29)
+#define HOST_EHCICTRL_ENAINCR4			(0x1 << 28)
+#define HOST_EHCICTRL_ENAINCR8			(0x1 << 27)
+#define HOST_EHCICTRL_ENAINCR16			(0x1 << 26)
+
+#define EXYNOS5_PHY_HOST_OHCICTRL		(0x34)
+
+#define HOST_OHCICTRL_SUSPLGCY			(0x1 << 3)
+#define HOST_OHCICTRL_APPSTARTCLK		(0x1 << 2)
+#define HOST_OHCICTRL_CNTSEL			(0x1 << 1)
+#define HOST_OHCICTRL_CLKCKTRST			(0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_SYS			(0x38)
+
+#define OTG_SYS_PHYLINK_SWRESET			(0x1 << 14)
+#define OTG_SYS_LINKSWRST_UOTG			(0x1 << 13)
+#define OTG_SYS_PHY0_SWRST			(0x1 << 12)
+
+#define OTG_SYS_REFCLKSEL_MASK			(0x3 << 9)
+#define OTG_SYS_REFCLKSEL_XTAL			(0x0 << 9)
+#define OTG_SYS_REFCLKSEL_EXTL			(0x1 << 9)
+#define OTG_SYS_REFCLKSEL_CLKCORE		(0x2 << 9)
+
+#define OTG_SYS_IDPULLUP_UOTG			(0x1 << 8)
+#define OTG_SYS_COMMON_ON			(0x1 << 7)
+
+#define OTG_SYS_FSEL_MASK			(0x7 << 4)
+#define OTG_SYS_FSEL(_x)			((_x) << 4)
+
+#define OTG_SYS_FORCESLEEP			(0x1 << 3)
+#define OTG_SYS_OTGDISABLE			(0x1 << 2)
+#define OTG_SYS_SIDDQ_UOTG			(0x1 << 1)
+#define OTG_SYS_FORCESUSPEND			(0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_TUNE			(0x40)
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#ifndef KHZ
+#define KHZ (1000)
+#endif
+
+#define EXYNOS_USBHOST_PHY_CTRL_OFFSET		(0x4)
+#define S3C64XX_USBPHY_ENABLE			(0x1 << 16)
+#define EXYNOS_USBPHY_ENABLE			(0x1 << 0)
+#define EXYNOS_USB20PHY_CFG_HOST_LINK		(0x1 << 0)
+
+enum samsung_cpu_type {
+	TYPE_S3C64XX,
+	TYPE_EXYNOS4210,
+	TYPE_EXYNOS5250,
+};
+
+/*
+ * struct samsung_usbphy_drvdata - driver data for various SoC variants
+ * @cpu_type: machine identifier
+ * @devphy_en_mask: device phy enable mask for PHY CONTROL register
+ * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
+ * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
+ *		       mapped address of system controller.
+ * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
+ *		       mapped address of system controller.
+ *
+ *	Here we have a separate mask for device type phy.
+ *	Having different masks for host and device type phy helps
+ *	in setting independent masks in case of SoCs like S5PV210,
+ *	in which PHY0 and PHY1 enable bits belong to same register
+ *	placed at position 0 and 1 respectively.
+ *	Although for newer SoCs like exynos these bits belong to
+ *	different registers altogether placed at position 0.
+ */
+struct samsung_usbphy_drvdata {
+	int cpu_type;
+	int devphy_en_mask;
+	int hostphy_en_mask;
+	u32 devphy_reg_offset;
+	u32 hostphy_reg_offset;
+};
+
+/*
+ * struct samsung_usbphy - transceiver driver state
+ * @phy: transceiver structure
+ * @plat: platform data
+ * @dev: The parent device supplied to the probe function
+ * @clk: usb phy clock
+ * @regs: usb phy controller registers memory base
+ * @pmuregs: USB device PHY_CONTROL register memory base
+ * @sysreg: USB2.0 PHY_CFG register memory base
+ * @ref_clk_freq: reference clock frequency selection
+ * @drv_data: driver data available for different SoCs
+ * @phy_type: Samsung SoCs specific phy types:	#HOST
+ *						#DEVICE
+ * @phy_usage: usage count for phy
+ * @lock: lock for phy operations
+ */
+struct samsung_usbphy {
+	struct usb_phy	phy;
+	struct samsung_usbphy_data *plat;
+	struct device	*dev;
+	struct clk	*clk;
+	void __iomem	*regs;
+	void __iomem	*pmuregs;
+	void __iomem	*sysreg;
+	int		ref_clk_freq;
+	const struct samsung_usbphy_drvdata *drv_data;
+	enum samsung_usb_phy_type phy_type;
+	atomic_t	phy_usage;
+	spinlock_t	lock;
+};
+
+#define phy_to_sphy(x)		container_of((x), struct samsung_usbphy, phy)
+
+static const struct of_device_id samsung_usbphy_dt_match[];
+
+static inline const struct samsung_usbphy_drvdata
+*samsung_usbphy_get_driver_data(struct platform_device *pdev)
+{
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+		match = of_match_node(samsung_usbphy_dt_match,
+							pdev->dev.of_node);
+		return match->data;
+	}
+
+	return (struct samsung_usbphy_drvdata *)
+				platform_get_device_id(pdev)->driver_data;
+}
+
+extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy);
+extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on);
+extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy);
+extern int samsung_usbphy_set_type(struct usb_phy *phy,
+				enum samsung_usb_phy_type phy_type);
+extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy);
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v3 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller
  2013-01-14 12:59 [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250 Vivek Gautam
  2013-01-14 12:59 ` [PATCH v3 1/2] usb: phy: samsung: Common out the generic stuff Vivek Gautam
@ 2013-01-14 12:59 ` Vivek Gautam
  2013-01-28 10:26   ` [PATCH v4 " Vivek Gautam
  2013-01-21  6:45 ` [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250 Vivek Gautam
  2 siblings, 1 reply; 14+ messages in thread
From: Vivek Gautam @ 2013-01-14 12:59 UTC (permalink / raw)
  To: linux-usb
  Cc: devicetree-discuss, linux-kernel, linux-samsung-soc, gregkh,
	balbi, kgene.kim, grant.likely, sylvester.nawrocki, dianders,
	av.tikhomirov, p.paneri

Adding PHY driver support for USB 3.0 controller for Samsung's
SoCs.

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---
 drivers/usb/phy/Kconfig          |    8 +
 drivers/usb/phy/Makefile         |    1 +
 drivers/usb/phy/samsung-usb3.c   |  349 ++++++++++++++++++++++++++++++++++++++
 drivers/usb/phy/samsung-usbphy.h |   81 +++++++++
 4 files changed, 439 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/phy/samsung-usb3.c

diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index fae4d08..a7b0536 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -53,3 +53,11 @@ config SAMSUNG_USBPHY
 	help
 	  Enable this to support Samsung USB phy controller for samsung
 	  SoCs.
+
+config SAMSUNG_USB3PHY
+	bool "Samsung USB 3.0 PHY controller Driver"
+	depends on USB_DWC3
+	select USB_OTG_UTILS
+	help
+	  Enable this to support Samsung USB 3.0 phy controller for samsung
+	  SoCs.
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 0f4fd4f..ed28e89 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_MV_U3D_PHY)		+= mv_u3d_phy.o
 obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
 obj-$(CONFIG_USB_RCAR_PHY)		+= rcar-phy.o
 obj-$(CONFIG_SAMSUNG_USBPHY)		+= samsung-usbphy.o samsung-usb2.o
+obj-$(CONFIG_SAMSUNG_USB3PHY)		+= samsung-usb3.o
diff --git a/drivers/usb/phy/samsung-usb3.c b/drivers/usb/phy/samsung-usb3.c
new file mode 100644
index 0000000..8029c1b
--- /dev/null
+++ b/drivers/usb/phy/samsung-usb3.c
@@ -0,0 +1,349 @@
+/* linux/drivers/usb/phy/samsung-usb3.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Vivek Gautam <gautam.vivek@samsung.com>
+ *
+ * Samsung USB 3.0 PHY transceiver; talks to DWC3 controller.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "samsung-usbphy.h"
+
+/*
+ * Sets the phy clk as EXTREFCLK (XXTI) which is internal clock from clock core.
+ */
+static u32 samsung_usb3_phy_set_refclk(struct samsung_usbphy *sphy)
+{
+	u32 reg;
+	u32 refclk;
+
+	refclk = sphy->ref_clk_freq;
+
+	reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK |
+		PHYCLKRST_FSEL(refclk);
+
+	switch (refclk) {
+	case FSEL_CLKSEL_50M:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x00));
+		break;
+	case FSEL_CLKSEL_20M:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x00));
+		break;
+	case FSEL_CLKSEL_19200K:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x88));
+		break;
+	case FSEL_CLKSEL_24M:
+	default:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x88));
+		break;
+	}
+
+	return reg;
+}
+
+static int samsung_exynos5_usb3_phy_enable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phyparam0;
+	u32 phyparam1;
+	u32 linksystem;
+	u32 phybatchg;
+	u32 phytest;
+	u32 phyclkrst;
+
+	/* Reset USB 3.0 PHY */
+	writel(0x0, regs + EXYNOS5_DRD_PHYREG0);
+
+	phyparam0 = readl(regs + EXYNOS5_DRD_PHYPARAM0);
+	/* Select PHY CLK source */
+	phyparam0 &= ~PHYPARAM0_REF_USE_PAD;
+	/* Set Loss-of-Signal Detector sensitivity */
+	phyparam0 &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
+	phyparam0 |= PHYPARAM0_REF_LOSLEVEL;
+	writel(phyparam0, regs + EXYNOS5_DRD_PHYPARAM0);
+
+	writel(0x0, regs + EXYNOS5_DRD_PHYRESUME);
+
+	/*
+	 * Setting the Frame length Adj value[6:1] to default 0x20
+	 * See xHCI 1.0 spec, 5.2.4
+	 */
+	linksystem = LINKSYSTEM_XHCI_VERSION_CONTROL |
+			LINKSYSTEM_FLADJ(0x20);
+	writel(linksystem, regs + EXYNOS5_DRD_LINKSYSTEM);
+
+	phyparam1 = readl(regs + EXYNOS5_DRD_PHYPARAM1);
+	/* Set Tx De-Emphasis level */
+	phyparam1 &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
+	phyparam1 |= PHYPARAM1_PCS_TXDEEMPH;
+	writel(phyparam1, regs + EXYNOS5_DRD_PHYPARAM1);
+
+	phybatchg = readl(regs + EXYNOS5_DRD_PHYBATCHG);
+	phybatchg |= PHYBATCHG_UTMI_CLKSEL;
+	writel(phybatchg, regs + EXYNOS5_DRD_PHYBATCHG);
+
+	/* PHYTEST POWERDOWN Control */
+	phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+	phytest &= ~(PHYTEST_POWERDOWN_SSP |
+			PHYTEST_POWERDOWN_HSP);
+	writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+
+	/* UTMI Power Control */
+	writel(PHYUTMI_OTGDISABLE, regs + EXYNOS5_DRD_PHYUTMI);
+
+	phyclkrst = samsung_usb3_phy_set_refclk(sphy);
+
+	phyclkrst |= PHYCLKRST_PORTRESET |
+			/* Digital power supply in normal operating mode */
+			PHYCLKRST_RETENABLEN |
+			/* Enable ref clock for SS function */
+			PHYCLKRST_REF_SSP_EN |
+			/* Enable spread spectrum */
+			PHYCLKRST_SSC_EN |
+			/* Power down HS Bias and PLL blocks in suspend mode */
+			PHYCLKRST_COMMONONN;
+
+	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+	udelay(10);
+
+	phyclkrst &= ~(PHYCLKRST_PORTRESET);
+	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+	return 0;
+}
+
+static void samsung_exynos5_usb3_phy_disable(struct samsung_usbphy *sphy)
+{
+	u32 phyutmi;
+	u32 phyclkrst;
+	u32 phytest;
+	void __iomem *regs = sphy->regs;
+
+	phyutmi = PHYUTMI_OTGDISABLE |
+			PHYUTMI_FORCESUSPEND |
+			PHYUTMI_FORCESLEEP;
+	writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI);
+
+	/* Resetting the PHYCLKRST enable bits to reduce leakage current */
+	phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST);
+	phyclkrst &= ~(PHYCLKRST_REF_SSP_EN |
+			PHYCLKRST_SSC_EN |
+			PHYCLKRST_COMMONONN);
+	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+	/* Control PHYTEST to remove leakage current */
+	phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+	phytest |= (PHYTEST_POWERDOWN_SSP |
+			PHYTEST_POWERDOWN_HSP);
+	writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+}
+
+static int samsung_usb3_phy_init(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	unsigned long flags;
+	int ret = 0;
+
+	sphy = phy_to_sphy(phy);
+
+	/* Enable the phy clock */
+	ret = clk_prepare_enable(sphy->clk);
+	if (ret) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return ret;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	/* setting default phy-type for USB 3.0 */
+	samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+	/* Disable phy isolation */
+	samsung_usbphy_set_isolation(sphy, false);
+
+	/* Initialize usb phy registers */
+	samsung_exynos5_usb3_phy_enable(sphy);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	/* Disable the phy clock */
+	clk_disable_unprepare(sphy->clk);
+
+	return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usb3_phy_shutdown(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	unsigned long flags;
+
+	sphy = phy_to_sphy(phy);
+
+	if (clk_prepare_enable(sphy->clk)) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	/* setting default phy-type for USB 3.0 */
+	samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+	/* De-initialize usb phy registers */
+	samsung_exynos5_usb3_phy_disable(sphy);
+
+	/* Enable phy isolation */
+	samsung_usbphy_set_isolation(sphy, true);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	clk_disable_unprepare(sphy->clk);
+}
+
+static int __devinit samsung_usb3_phy_probe(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy;
+	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct resource *phy_mem;
+	void __iomem	*phy_base;
+	struct clk *clk;
+	int ret;
+
+	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!phy_mem) {
+		dev_err(dev, "%s: missing mem resource\n", __func__);
+		return -ENODEV;
+	}
+
+	phy_base = devm_request_and_ioremap(dev, phy_mem);
+	if (!phy_base) {
+		dev_err(dev, "%s: register mapping failed\n", __func__);
+		return -ENXIO;
+	}
+
+	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+	if (!sphy)
+		return -ENOMEM;
+
+	clk = devm_clk_get(dev, "usbdrd30");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "Failed to get device clock\n");
+		return PTR_ERR(clk);
+	}
+
+	sphy->dev = dev;
+
+	if (dev->of_node) {
+		ret = samsung_usbphy_parse_dt(sphy);
+		if (ret < 0)
+			return ret;
+	} else {
+		if (!pdata) {
+			dev_err(dev, "no platform data specified\n");
+			return -EINVAL;
+		}
+	}
+
+	sphy->plat		= pdata;
+	sphy->regs		= phy_base;
+	sphy->clk		= clk;
+	sphy->phy.dev		= sphy->dev;
+	sphy->phy.label		= "samsung-usb3-phy";
+	sphy->phy.init		= samsung_usb3_phy_init;
+	sphy->phy.shutdown	= samsung_usb3_phy_shutdown;
+	sphy->drv_data		= samsung_usbphy_get_driver_data(pdev);
+	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy);
+
+	spin_lock_init(&sphy->lock);
+
+	platform_set_drvdata(pdev, sphy);
+
+	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3);
+}
+
+static int __exit samsung_usb3_phy_remove(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&sphy->phy);
+
+	if (sphy->pmuregs)
+		iounmap(sphy->pmuregs);
+	if (sphy->sysreg)
+		iounmap(sphy->sysreg);
+
+	return 0;
+}
+
+static struct samsung_usbphy_drvdata usb3_phy_exynos5 = {
+	.cpu_type		= TYPE_EXYNOS5250,
+	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+	{
+		.compatible = "samsung,exynos5250-usb3-phy",
+		.data = &usb3_phy_exynos5
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+	{
+		.name		= "exynos5250-usb3-phy",
+		.driver_data	= (unsigned long)&usb3_phy_exynos5,
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usbphy_driver = {
+	.probe		= samsung_usb3_phy_probe,
+	.remove		= __devexit_p(samsung_usb3_phy_remove),
+	.id_table	= samsung_usbphy_driver_ids,
+	.driver		= {
+		.name	= "samsung-usb3-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+	},
+};
+
+module_platform_driver(samsung_usbphy_driver);
+
+MODULE_DESCRIPTION("Samsung USB 3.0 phy controller");
+MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usb3-phy");
diff --git a/drivers/usb/phy/samsung-usbphy.h b/drivers/usb/phy/samsung-usbphy.h
index 969632b..f7e657d 100644
--- a/drivers/usb/phy/samsung-usbphy.h
+++ b/drivers/usb/phy/samsung-usbphy.h
@@ -145,6 +145,87 @@
 
 #define EXYNOS5_PHY_OTG_TUNE			(0x40)
 
+/* EXYNOS5: USB 3.0 DRD */
+#define EXYNOS5_DRD_LINKSYSTEM			(0x04)
+
+#define LINKSYSTEM_FLADJ_MASK			(0x3f << 1)
+#define LINKSYSTEM_FLADJ(_x)			((_x) << 1)
+#define LINKSYSTEM_XHCI_VERSION_CONTROL		(0x1 << 27)
+
+#define EXYNOS5_DRD_PHYUTMI			(0x08)
+
+#define PHYUTMI_OTGDISABLE			(0x1 << 6)
+#define PHYUTMI_FORCESUSPEND			(0x1 << 1)
+#define PHYUTMI_FORCESLEEP			(0x1 << 0)
+
+#define EXYNOS5_DRD_PHYPIPE			(0x0c)
+
+#define EXYNOS5_DRD_PHYCLKRST			(0x10)
+
+#define PHYCLKRST_SSC_REFCLKSEL_MASK		(0xff << 23)
+#define PHYCLKRST_SSC_REFCLKSEL(_x)		((_x) << 23)
+
+#define PHYCLKRST_SSC_RANGE_MASK		(0x03 << 21)
+#define PHYCLKRST_SSC_RANGE(_x)			((_x) << 21)
+
+#define PHYCLKRST_SSC_EN			(0x1 << 20)
+#define PHYCLKRST_REF_SSP_EN			(0x1 << 19)
+#define PHYCLKRST_REF_CLKDIV2			(0x1 << 18)
+
+#define PHYCLKRST_MPLL_MULTIPLIER_MASK		(0x7f << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF	(0x19 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF	(0x02 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF	(0x68 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF	(0x7d << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF	(0x02 << 11)
+
+#define PHYCLKRST_FSEL_MASK			(0x3f << 5)
+#define PHYCLKRST_FSEL(_x)			((_x) << 5)
+#define PHYCLKRST_FSEL_PAD_100MHZ		(0x27 << 5)
+#define PHYCLKRST_FSEL_PAD_24MHZ		(0x2a << 5)
+#define PHYCLKRST_FSEL_PAD_20MHZ		(0x31 << 5)
+#define PHYCLKRST_FSEL_PAD_19_2MHZ		(0x38 << 5)
+
+#define PHYCLKRST_RETENABLEN			(0x1 << 4)
+
+#define PHYCLKRST_REFCLKSEL_MASK		(0x03 << 2)
+#define PHYCLKRST_REFCLKSEL_PAD_REFCLK		(0x2 << 2)
+#define PHYCLKRST_REFCLKSEL_EXT_REFCLK		(0x3 << 2)
+
+#define PHYCLKRST_PORTRESET			(0x1 << 1)
+#define PHYCLKRST_COMMONONN			(0x1 << 0)
+
+#define EXYNOS5_DRD_PHYREG0			(0x14)
+#define EXYNOS5_DRD_PHYREG1			(0x18)
+
+#define EXYNOS5_DRD_PHYPARAM0			(0x1c)
+
+#define PHYPARAM0_REF_USE_PAD			(0x1 << 31)
+#define PHYPARAM0_REF_LOSLEVEL_MASK		(0x1f << 26)
+#define PHYPARAM0_REF_LOSLEVEL			(0x9 << 26)
+
+#define EXYNOS5_DRD_PHYPARAM1			(0x20)
+
+#define PHYPARAM1_PCS_TXDEEMPH_MASK		(0x1f << 0)
+#define PHYPARAM1_PCS_TXDEEMPH			(0x1c)
+
+#define EXYNOS5_DRD_PHYTERM			(0x24)
+
+#define EXYNOS5_DRD_PHYTEST			(0x28)
+
+#define PHYTEST_POWERDOWN_SSP			(0x1 << 3)
+#define PHYTEST_POWERDOWN_HSP			(0x1 << 2)
+
+#define EXYNOS5_DRD_PHYADP			(0x2c)
+
+#define EXYNOS5_DRD_PHYBATCHG			(0x30)
+
+#define PHYBATCHG_UTMI_CLKSEL			(0x1 << 2)
+
+#define EXYNOS5_DRD_PHYRESUME			(0x34)
+#define EXYNOS5_DRD_LINKPORT			(0x44)
+
+
 #ifndef MHZ
 #define MHZ (1000*1000)
 #endif
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250
  2013-01-14 12:59 [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250 Vivek Gautam
  2013-01-14 12:59 ` [PATCH v3 1/2] usb: phy: samsung: Common out the generic stuff Vivek Gautam
  2013-01-14 12:59 ` [PATCH v3 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller Vivek Gautam
@ 2013-01-21  6:45 ` Vivek Gautam
  2013-01-21  8:26   ` Felipe Balbi
  2 siblings, 1 reply; 14+ messages in thread
From: Vivek Gautam @ 2013-01-21  6:45 UTC (permalink / raw)
  To: balbi
  Cc: linux-usb, kgene.kim, p.paneri, gregkh, devicetree-discuss,
	linux-kernel, linux-samsung-soc, sylvester.nawrocki,
	av.tikhomirov, Vivek Gautam, Doug Anderson, kishon, Grant Likely

Hi Felipe,


On Mon, Jan 14, 2013 at 6:29 PM, Vivek Gautam <gautam.vivek@samsung.com> wrote:
> Changes from v2:
>  - Renaming 'samsung-usbphy.c' driver to 'samsung-usb2.c' indicating
>    usb 2.0 phy controller's driver for Samsung's SoCs.
>  - Moving the register definitions and strcuture definitions to
>    common header file 'samsung-usbphy.h' to be used across
>    usb 2.0 and usb 3.0 phy.
>  - Keeping common exported function definitions in samsung-usbphy.c
>    which can be used across usb 2.0 and usb 3.0 phy.
>  - Writting separate driver file for Samsung's USB 3.0 phy controller.
>    and making it dependent on USB_DWC3.
>

Is the re-organization being done here fine as per requirements for
separate drivers for usb 2.0 type PHY and usb 3.0 type PHY ?

> Rebased on top of usb-next followed by following patches/patch-threads:
>         -- [PATCH v9 1/2] usb: phy: samsung: Introducing usb phy driver for hsotg
>         -- [PATCH] usb: phy: samsung: Add support to set pmu isolation (version 6)
>         -- [PATCH v6 0/4] Adding usb2.0 host-phy support for exynos5250
>
> Changes form v1:
>  - Moved architecture related patch out of this patch-set.
>  - Replaced unnecessary multi-line macro definitions by
>    single line definitions.
>  - Creating new data structure for USB 3.0 phy type and embedding
>    it in 'samsung_usbphy' structure.
>  - Adding a flag in 'samsung_usbphy' structure to check if device
>    has usb 3.0 type phy or not.
>  - Restructuring probe sequence for USB 3.0 phy, such that we are
>    initializing only when device has usb3.0 type phy.
>
> Vivek Gautam (2):
>   usb: phy: samsung: Common out the generic stuff
>   usb: phy: samsung: Add PHY support for USB 3.0 controller
>
>  drivers/usb/phy/Kconfig          |    8 +
>  drivers/usb/phy/Makefile         |    3 +-
>  drivers/usb/phy/samsung-usb2.c   |  511 +++++++++++++++++++++++++++
>  drivers/usb/phy/samsung-usb3.c   |  349 +++++++++++++++++++
>  drivers/usb/phy/samsung-usbphy.c |  713 +-------------------------------------
>  drivers/usb/phy/samsung-usbphy.h |  328 +++++++++++++++++
>  6 files changed, 1205 insertions(+), 707 deletions(-)
>  create mode 100644 drivers/usb/phy/samsung-usb2.c
>  create mode 100644 drivers/usb/phy/samsung-usb3.c
>  create mode 100644 drivers/usb/phy/samsung-usbphy.h
>



-- 
Thanks & Regards
Vivek

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250
  2013-01-21  6:45 ` [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250 Vivek Gautam
@ 2013-01-21  8:26   ` Felipe Balbi
  0 siblings, 0 replies; 14+ messages in thread
From: Felipe Balbi @ 2013-01-21  8:26 UTC (permalink / raw)
  To: Vivek Gautam
  Cc: balbi, linux-usb, kgene.kim, p.paneri, gregkh,
	devicetree-discuss, linux-kernel, linux-samsung-soc,
	sylvester.nawrocki, av.tikhomirov, Vivek Gautam, Doug Anderson,
	kishon, Grant Likely

[-- Attachment #1: Type: text/plain, Size: 1112 bytes --]

Hi,

On Mon, Jan 21, 2013 at 12:15:10PM +0530, Vivek Gautam wrote:
> Hi Felipe,
> 
> 
> On Mon, Jan 14, 2013 at 6:29 PM, Vivek Gautam <gautam.vivek@samsung.com> wrote:
> > Changes from v2:
> >  - Renaming 'samsung-usbphy.c' driver to 'samsung-usb2.c' indicating
> >    usb 2.0 phy controller's driver for Samsung's SoCs.
> >  - Moving the register definitions and strcuture definitions to
> >    common header file 'samsung-usbphy.h' to be used across
> >    usb 2.0 and usb 3.0 phy.
> >  - Keeping common exported function definitions in samsung-usbphy.c
> >    which can be used across usb 2.0 and usb 3.0 phy.
> >  - Writting separate driver file for Samsung's USB 3.0 phy controller.
> >    and making it dependent on USB_DWC3.
> >
> 
> Is the re-organization being done here fine as per requirements for
> separate drivers for usb 2.0 type PHY and usb 3.0 type PHY ?

should be fine ;-) If there is *truly generic* pieces, it makes sense to
re-use - unless those "generic" parts are common driver churn
(platform_driver definition, module_init(), module_exit(), etc).

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v4 1/2] usb: phy: samsung: Common out the generic stuff
  2013-01-14 12:59 ` [PATCH v3 1/2] usb: phy: samsung: Common out the generic stuff Vivek Gautam
@ 2013-01-28 10:24   ` Vivek Gautam
  2013-01-29  5:34     ` Vivek Gautam
  2013-01-30  5:56     ` Kukjin Kim
  0 siblings, 2 replies; 14+ messages in thread
From: Vivek Gautam @ 2013-01-28 10:24 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-kernel, devicetree-discuss, linux-samsung-soc, gregkh,
	balbi, kgene.kim, grant.likely, sylvester.nawrocki, tomasz.figa,
	av.tikhomirov, dianders, p.paneri

Moving register and structure definitions to header file,
and keeping the generic functions to be used across
multiple PHYs in common file "samsung-usbphy.c".
Also renaming the usb 2.0 phy driver to "samsung-usb2.c"

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---

Changes from v3:
 - Using separate config SAMSUNG_USB2PHY dependent on
   SAMSUNG_USBPHY for samsung-usb2 type PHY controller.

 drivers/usb/phy/Kconfig          |   14 +-
 drivers/usb/phy/Makefile         |    1 +
 drivers/usb/phy/samsung-usb2.c   |  511 +++++++++++++++++++++++++++
 drivers/usb/phy/samsung-usbphy.c |  714 +-------------------------------------
 drivers/usb/phy/samsung-usbphy.h |  247 +++++++++++++
 5 files changed, 778 insertions(+), 709 deletions(-)
 create mode 100644 drivers/usb/phy/samsung-usb2.c
 create mode 100644 drivers/usb/phy/samsung-usbphy.h

diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index fae4d08..cc0d230 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -48,8 +48,18 @@ config USB_RCAR_PHY
 
 config SAMSUNG_USBPHY
 	bool "Samsung USB PHY controller Driver"
-	depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS
 	select USB_OTG_UTILS
 	help
-	  Enable this to support Samsung USB phy controller for samsung
+	  Enable this to support Samsung USB phy controllers for Samsung
 	  SoCs.
+
+if SAMSUNG_USBPHY
+
+config SAMSUNG_USB2PHY
+	bool "Samsung USB 2.0 PHY controller Driver"
+	depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS
+	help
+	  Enable this to support Samsung USB 2.0 (High Speed) phy controller
+	  for Samsung SoCs.
+
+endif
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index ec304f6..7ba9862 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_MV_U3D_PHY)		+= mv_u3d_phy.o
 obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
 obj-$(CONFIG_USB_RCAR_PHY)		+= rcar-phy.o
 obj-$(CONFIG_SAMSUNG_USBPHY)		+= samsung-usbphy.o
+obj-$(CONFIG_SAMSUNG_USB2PHY)		+= samsung-usb2.o
diff --git a/drivers/usb/phy/samsung-usb2.c b/drivers/usb/phy/samsung-usb2.c
new file mode 100644
index 0000000..9a9d1d0
--- /dev/null
+++ b/drivers/usb/phy/samsung-usb2.c
@@ -0,0 +1,511 @@
+/* linux/drivers/usb/phy/samsung-usb2.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Praveen Paneri <p.paneri@samsung.com>
+ *
+ * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "samsung-usbphy.h"
+
+int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
+{
+	if (!otg)
+		return -ENODEV;
+
+	if (!otg->host)
+		otg->host = host;
+
+	return 0;
+}
+
+static bool exynos5_phyhost_is_on(void *regs)
+{
+	u32 reg;
+
+	reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	return !(reg & HOST_CTRL0_SIDDQ);
+}
+
+static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phyclk = sphy->ref_clk_freq;
+	u32 phyhost;
+	u32 phyotg;
+	u32 phyhsic;
+	u32 ehcictrl;
+	u32 ohcictrl;
+
+	/*
+	 * phy_usage helps in keeping usage count for phy
+	 * so that the first consumer enabling the phy is also
+	 * the last consumer to disable it.
+	 */
+
+	atomic_inc(&sphy->phy_usage);
+
+	if (exynos5_phyhost_is_on(regs)) {
+		dev_info(sphy->dev, "Already power on PHY\n");
+		return;
+	}
+
+	/* Host configuration */
+	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	/* phy reference clock configuration */
+	phyhost &= ~HOST_CTRL0_FSEL_MASK;
+	phyhost |= HOST_CTRL0_FSEL(phyclk);
+
+	/* host phy reset */
+	phyhost &= ~(HOST_CTRL0_PHYSWRST |
+			HOST_CTRL0_PHYSWRSTALL |
+			HOST_CTRL0_SIDDQ |
+			/* Enable normal mode of operation */
+			HOST_CTRL0_FORCESUSPEND |
+			HOST_CTRL0_FORCESLEEP);
+
+	/* Link reset */
+	phyhost |= (HOST_CTRL0_LINKSWRST |
+			HOST_CTRL0_UTMISWRST |
+			/* COMMON Block configuration during suspend */
+			HOST_CTRL0_COMMONON_N);
+	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+	udelay(10);
+	phyhost &= ~(HOST_CTRL0_LINKSWRST |
+			HOST_CTRL0_UTMISWRST);
+	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	/* OTG configuration */
+	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+
+	/* phy reference clock configuration */
+	phyotg &= ~OTG_SYS_FSEL_MASK;
+	phyotg |= OTG_SYS_FSEL(phyclk);
+
+	/* Enable normal mode of operation */
+	phyotg &= ~(OTG_SYS_FORCESUSPEND |
+			OTG_SYS_SIDDQ_UOTG |
+			OTG_SYS_FORCESLEEP |
+			OTG_SYS_REFCLKSEL_MASK |
+			/* COMMON Block configuration during suspend */
+			OTG_SYS_COMMON_ON);
+
+	/* OTG phy & link reset */
+	phyotg |= (OTG_SYS_PHY0_SWRST |
+			OTG_SYS_LINKSWRST_UOTG |
+			OTG_SYS_PHYLINK_SWRESET |
+			OTG_SYS_OTGDISABLE |
+			/* Set phy refclk */
+			OTG_SYS_REFCLKSEL_CLKCORE);
+
+	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+	udelay(10);
+	phyotg &= ~(OTG_SYS_PHY0_SWRST |
+			OTG_SYS_LINKSWRST_UOTG |
+			OTG_SYS_PHYLINK_SWRESET);
+	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+
+	/* HSIC phy configuration */
+	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+			HSIC_CTRL_REFCLKSEL |
+			HSIC_CTRL_PHYSWRST);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+	udelay(10);
+	phyhsic &= ~HSIC_CTRL_PHYSWRST;
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+	udelay(80);
+
+	/* enable EHCI DMA burst */
+	ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
+	ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
+				HOST_EHCICTRL_ENAINCR4 |
+				HOST_EHCICTRL_ENAINCR8 |
+				HOST_EHCICTRL_ENAINCR16);
+	writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
+
+	/* set ohci_suspend_on_n */
+	ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
+	ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
+	writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
+}
+
+static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phypwr;
+	u32 phyclk;
+	u32 rstcon;
+
+	/* set clock frequency for PLL */
+	phyclk = sphy->ref_clk_freq;
+	phypwr = readl(regs + SAMSUNG_PHYPWR);
+	rstcon = readl(regs + SAMSUNG_RSTCON);
+
+	switch (sphy->drv_data->cpu_type) {
+	case TYPE_S3C64XX:
+		phyclk &= ~PHYCLK_COMMON_ON_N;
+		phypwr &= ~PHYPWR_NORMAL_MASK;
+		rstcon |= RSTCON_SWRST;
+		break;
+	case TYPE_EXYNOS4210:
+		phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
+		rstcon |= RSTCON_SWRST;
+	default:
+		break;
+	}
+
+	writel(phyclk, regs + SAMSUNG_PHYCLK);
+	/* Configure PHY0 for normal operation*/
+	writel(phypwr, regs + SAMSUNG_PHYPWR);
+	/* reset all ports of PHY and Link */
+	writel(rstcon, regs + SAMSUNG_RSTCON);
+	udelay(10);
+	rstcon &= ~RSTCON_SWRST;
+	writel(rstcon, regs + SAMSUNG_RSTCON);
+}
+
+static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phyhost;
+	u32 phyotg;
+	u32 phyhsic;
+
+	if (atomic_dec_return(&sphy->phy_usage) > 0) {
+		dev_info(sphy->dev, "still being used\n");
+		return;
+	}
+
+	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
+			HSIC_CTRL_REFCLKSEL |
+			HSIC_CTRL_SIDDQ |
+			HSIC_CTRL_FORCESLEEP |
+			HSIC_CTRL_FORCESUSPEND);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
+	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
+
+	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
+	phyhost |= (HOST_CTRL0_SIDDQ |
+			HOST_CTRL0_FORCESUSPEND |
+			HOST_CTRL0_FORCESLEEP |
+			HOST_CTRL0_PHYSWRST |
+			HOST_CTRL0_PHYSWRSTALL);
+	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
+
+	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
+	phyotg |= (OTG_SYS_FORCESUSPEND |
+			OTG_SYS_SIDDQ_UOTG |
+			OTG_SYS_FORCESLEEP);
+	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
+}
+
+static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phypwr;
+
+	phypwr = readl(regs + SAMSUNG_PHYPWR);
+
+	switch (sphy->drv_data->cpu_type) {
+	case TYPE_S3C64XX:
+		phypwr |= PHYPWR_NORMAL_MASK;
+		break;
+	case TYPE_EXYNOS4210:
+		phypwr |= PHYPWR_NORMAL_MASK_PHY0;
+	default:
+		break;
+	}
+
+	/* Disable analog and otg block power */
+	writel(phypwr, regs + SAMSUNG_PHYPWR);
+}
+
+/*
+ * The function passed to the usb driver for phy initialization
+ */
+static int samsung_usbphy_init(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	struct usb_bus *host = NULL;
+	unsigned long flags;
+	int ret = 0;
+
+	sphy = phy_to_sphy(phy);
+
+	host = phy->otg->host;
+
+	/* Enable the phy clock */
+	ret = clk_prepare_enable(sphy->clk);
+	if (ret) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return ret;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	if (host) {
+		/* setting default phy-type for USB 2.0 */
+		if (!strstr(dev_name(host->controller), "ehci") ||
+				!strstr(dev_name(host->controller), "ohci"))
+			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+	} else {
+		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+	}
+
+	/* Disable phy isolation */
+	if (sphy->plat && sphy->plat->pmu_isolation)
+		sphy->plat->pmu_isolation(false);
+	else
+		samsung_usbphy_set_isolation(sphy, false);
+
+	/* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
+	samsung_usbphy_cfg_sel(sphy);
+
+	/* Initialize usb phy registers */
+	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+		samsung_exynos5_usbphy_enable(sphy);
+	else
+		samsung_usbphy_enable(sphy);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	/* Disable the phy clock */
+	clk_disable_unprepare(sphy->clk);
+
+	return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usbphy_shutdown(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	struct usb_bus *host = NULL;
+	unsigned long flags;
+
+	sphy = phy_to_sphy(phy);
+
+	host = phy->otg->host;
+
+	if (clk_prepare_enable(sphy->clk)) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	if (host) {
+		/* setting default phy-type for USB 2.0 */
+		if (!strstr(dev_name(host->controller), "ehci") ||
+				!strstr(dev_name(host->controller), "ohci"))
+			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
+	} else {
+		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+	}
+
+	/* De-initialize usb phy registers */
+	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
+		samsung_exynos5_usbphy_disable(sphy);
+	else
+		samsung_usbphy_disable(sphy);
+
+	/* Enable phy isolation */
+	if (sphy->plat && sphy->plat->pmu_isolation)
+		sphy->plat->pmu_isolation(true);
+	else
+		samsung_usbphy_set_isolation(sphy, true);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	clk_disable_unprepare(sphy->clk);
+}
+
+static int samsung_usbphy_probe(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy;
+	struct usb_otg *otg;
+	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+	const struct samsung_usbphy_drvdata *drv_data;
+	struct device *dev = &pdev->dev;
+	struct resource *phy_mem;
+	void __iomem	*phy_base;
+	struct clk *clk;
+	int ret;
+
+	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!phy_mem) {
+		dev_err(dev, "%s: missing mem resource\n", __func__);
+		return -ENODEV;
+	}
+
+	phy_base = devm_request_and_ioremap(dev, phy_mem);
+	if (!phy_base) {
+		dev_err(dev, "%s: register mapping failed\n", __func__);
+		return -ENXIO;
+	}
+
+	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+	if (!sphy)
+		return -ENOMEM;
+
+	otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
+	if (!otg)
+		return -ENOMEM;
+
+	drv_data = samsung_usbphy_get_driver_data(pdev);
+
+	if (drv_data->cpu_type == TYPE_EXYNOS5250)
+		clk = devm_clk_get(dev, "usbhost");
+	else
+		clk = devm_clk_get(dev, "otg");
+
+	if (IS_ERR(clk)) {
+		dev_err(dev, "Failed to get otg clock\n");
+		return PTR_ERR(clk);
+	}
+
+	sphy->dev = dev;
+
+	if (dev->of_node) {
+		ret = samsung_usbphy_parse_dt(sphy);
+		if (ret < 0)
+			return ret;
+	} else {
+		if (!pdata) {
+			dev_err(dev, "no platform data specified\n");
+			return -EINVAL;
+		}
+	}
+
+	sphy->plat		= pdata;
+	sphy->regs		= phy_base;
+	sphy->clk		= clk;
+	sphy->drv_data		= drv_data;
+	sphy->phy.dev		= sphy->dev;
+	sphy->phy.label		= "samsung-usbphy";
+	sphy->phy.init		= samsung_usbphy_init;
+	sphy->phy.shutdown	= samsung_usbphy_shutdown;
+	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy);
+
+	sphy->phy.otg		= otg;
+	sphy->phy.otg->phy	= &sphy->phy;
+	sphy->phy.otg->set_host = samsung_usbphy_set_host;
+
+	spin_lock_init(&sphy->lock);
+
+	platform_set_drvdata(pdev, sphy);
+
+	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
+}
+
+static int samsung_usbphy_remove(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&sphy->phy);
+
+	if (sphy->pmuregs)
+		iounmap(sphy->pmuregs);
+	if (sphy->sysreg)
+		iounmap(sphy->sysreg);
+
+	return 0;
+}
+
+static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
+	.cpu_type		= TYPE_S3C64XX,
+	.devphy_en_mask		= S3C64XX_USBPHY_ENABLE,
+};
+
+static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
+	.cpu_type		= TYPE_EXYNOS4210,
+	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE,
+	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
+};
+
+static struct samsung_usbphy_drvdata usbphy_exynos5 = {
+	.cpu_type		= TYPE_EXYNOS5250,
+	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
+	.hostphy_reg_offset	= EXYNOS_USBHOST_PHY_CTRL_OFFSET,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+	{
+		.compatible = "samsung,s3c64xx-usbphy",
+		.data = &usbphy_s3c64xx,
+	}, {
+		.compatible = "samsung,exynos4210-usbphy",
+		.data = &usbphy_exynos4,
+	}, {
+		.compatible = "samsung,exynos5250-usbphy",
+		.data = &usbphy_exynos5
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+	{
+		.name		= "s3c64xx-usbphy",
+		.driver_data	= (unsigned long)&usbphy_s3c64xx,
+	}, {
+		.name		= "exynos4210-usbphy",
+		.driver_data	= (unsigned long)&usbphy_exynos4,
+	}, {
+		.name		= "exynos5250-usbphy",
+		.driver_data	= (unsigned long)&usbphy_exynos5,
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usbphy_driver = {
+	.probe		= samsung_usbphy_probe,
+	.remove		= samsung_usbphy_remove,
+	.id_table	= samsung_usbphy_driver_ids,
+	.driver		= {
+		.name	= "samsung-usbphy",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+	},
+};
+
+module_platform_driver(samsung_usbphy_driver);
+
+MODULE_DESCRIPTION("Samsung USB phy controller");
+MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usbphy");
diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
index 6ea5537..7782a43 100644
--- a/drivers/usb/phy/samsung-usbphy.c
+++ b/drivers/usb/phy/samsung-usbphy.c
@@ -5,7 +5,7 @@
  *
  * Author: Praveen Paneri <p.paneri@samsung.com>
  *
- * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
  * OHCI-EXYNOS controllers.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -21,233 +21,16 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/usb/otg.h>
 #include <linux/usb/samsung_usb_phy.h>
-#include <linux/platform_data/samsung-usbphy.h>
 
-/* Register definitions */
+#include "samsung-usbphy.h"
 
-#define SAMSUNG_PHYPWR				(0x00)
-
-#define PHYPWR_NORMAL_MASK			(0x19 << 0)
-#define PHYPWR_OTG_DISABLE			(0x1 << 4)
-#define PHYPWR_ANALOG_POWERDOWN			(0x1 << 3)
-#define PHYPWR_FORCE_SUSPEND			(0x1 << 1)
-/* For Exynos4 */
-#define PHYPWR_NORMAL_MASK_PHY0			(0x39 << 0)
-#define PHYPWR_SLEEP_PHY0			(0x1 << 5)
-
-#define SAMSUNG_PHYCLK				(0x04)
-
-#define PHYCLK_MODE_USB11			(0x1 << 6)
-#define PHYCLK_EXT_OSC				(0x1 << 5)
-#define PHYCLK_COMMON_ON_N			(0x1 << 4)
-#define PHYCLK_ID_PULL				(0x1 << 2)
-#define PHYCLK_CLKSEL_MASK			(0x3 << 0)
-#define PHYCLK_CLKSEL_48M			(0x0 << 0)
-#define PHYCLK_CLKSEL_12M			(0x2 << 0)
-#define PHYCLK_CLKSEL_24M			(0x3 << 0)
-
-#define SAMSUNG_RSTCON				(0x08)
-
-#define RSTCON_PHYLINK_SWRST			(0x1 << 2)
-#define RSTCON_HLINK_SWRST			(0x1 << 1)
-#define RSTCON_SWRST				(0x1 << 0)
-
-/* EXYNOS5 */
-#define EXYNOS5_PHY_HOST_CTRL0			(0x00)
-
-#define HOST_CTRL0_PHYSWRSTALL			(0x1 << 31)
-
-#define HOST_CTRL0_REFCLKSEL_MASK		(0x3 << 19)
-#define HOST_CTRL0_REFCLKSEL_XTAL		(0x0 << 19)
-#define HOST_CTRL0_REFCLKSEL_EXTL		(0x1 << 19)
-#define HOST_CTRL0_REFCLKSEL_CLKCORE		(0x2 << 19)
-
-#define HOST_CTRL0_FSEL_MASK			(0x7 << 16)
-#define HOST_CTRL0_FSEL(_x)			((_x) << 16)
-
-#define FSEL_CLKSEL_50M				(0x7)
-#define FSEL_CLKSEL_24M				(0x5)
-#define FSEL_CLKSEL_20M				(0x4)
-#define FSEL_CLKSEL_19200K			(0x3)
-#define FSEL_CLKSEL_12M				(0x2)
-#define FSEL_CLKSEL_10M				(0x1)
-#define FSEL_CLKSEL_9600K			(0x0)
-
-#define HOST_CTRL0_TESTBURNIN			(0x1 << 11)
-#define HOST_CTRL0_RETENABLE			(0x1 << 10)
-#define HOST_CTRL0_COMMONON_N			(0x1 << 9)
-#define HOST_CTRL0_SIDDQ			(0x1 << 6)
-#define HOST_CTRL0_FORCESLEEP			(0x1 << 5)
-#define HOST_CTRL0_FORCESUSPEND			(0x1 << 4)
-#define HOST_CTRL0_WORDINTERFACE		(0x1 << 3)
-#define HOST_CTRL0_UTMISWRST			(0x1 << 2)
-#define HOST_CTRL0_LINKSWRST			(0x1 << 1)
-#define HOST_CTRL0_PHYSWRST			(0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_TUNE0			(0x04)
-
-#define EXYNOS5_PHY_HSIC_CTRL1			(0x10)
-
-#define EXYNOS5_PHY_HSIC_TUNE1			(0x14)
-
-#define EXYNOS5_PHY_HSIC_CTRL2			(0x20)
-
-#define EXYNOS5_PHY_HSIC_TUNE2			(0x24)
-
-#define HSIC_CTRL_REFCLKSEL_MASK		(0x3 << 23)
-#define HSIC_CTRL_REFCLKSEL			(0x2 << 23)
-
-#define HSIC_CTRL_REFCLKDIV_MASK		(0x7f << 16)
-#define HSIC_CTRL_REFCLKDIV(_x)			((_x) << 16)
-#define HSIC_CTRL_REFCLKDIV_12			(0x24 << 16)
-#define HSIC_CTRL_REFCLKDIV_15			(0x1c << 16)
-#define HSIC_CTRL_REFCLKDIV_16			(0x1a << 16)
-#define HSIC_CTRL_REFCLKDIV_19_2		(0x15 << 16)
-#define HSIC_CTRL_REFCLKDIV_20			(0x14 << 16)
-
-#define HSIC_CTRL_SIDDQ				(0x1 << 6)
-#define HSIC_CTRL_FORCESLEEP			(0x1 << 5)
-#define HSIC_CTRL_FORCESUSPEND			(0x1 << 4)
-#define HSIC_CTRL_WORDINTERFACE			(0x1 << 3)
-#define HSIC_CTRL_UTMISWRST			(0x1 << 2)
-#define HSIC_CTRL_PHYSWRST			(0x1 << 0)
-
-#define EXYNOS5_PHY_HOST_EHCICTRL		(0x30)
-
-#define HOST_EHCICTRL_ENAINCRXALIGN		(0x1 << 29)
-#define HOST_EHCICTRL_ENAINCR4			(0x1 << 28)
-#define HOST_EHCICTRL_ENAINCR8			(0x1 << 27)
-#define HOST_EHCICTRL_ENAINCR16			(0x1 << 26)
-
-#define EXYNOS5_PHY_HOST_OHCICTRL		(0x34)
-
-#define HOST_OHCICTRL_SUSPLGCY			(0x1 << 3)
-#define HOST_OHCICTRL_APPSTARTCLK		(0x1 << 2)
-#define HOST_OHCICTRL_CNTSEL			(0x1 << 1)
-#define HOST_OHCICTRL_CLKCKTRST			(0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_SYS			(0x38)
-
-#define OTG_SYS_PHYLINK_SWRESET			(0x1 << 14)
-#define OTG_SYS_LINKSWRST_UOTG			(0x1 << 13)
-#define OTG_SYS_PHY0_SWRST			(0x1 << 12)
-
-#define OTG_SYS_REFCLKSEL_MASK			(0x3 << 9)
-#define OTG_SYS_REFCLKSEL_XTAL			(0x0 << 9)
-#define OTG_SYS_REFCLKSEL_EXTL			(0x1 << 9)
-#define OTG_SYS_REFCLKSEL_CLKCORE		(0x2 << 9)
-
-#define OTG_SYS_IDPULLUP_UOTG			(0x1 << 8)
-#define OTG_SYS_COMMON_ON			(0x1 << 7)
-
-#define OTG_SYS_FSEL_MASK			(0x7 << 4)
-#define OTG_SYS_FSEL(_x)			((_x) << 4)
-
-#define OTG_SYS_FORCESLEEP			(0x1 << 3)
-#define OTG_SYS_OTGDISABLE			(0x1 << 2)
-#define OTG_SYS_SIDDQ_UOTG			(0x1 << 1)
-#define OTG_SYS_FORCESUSPEND			(0x1 << 0)
-
-#define EXYNOS5_PHY_OTG_TUNE			(0x40)
-
-#ifndef MHZ
-#define MHZ (1000*1000)
-#endif
-
-#ifndef KHZ
-#define KHZ (1000)
-#endif
-
-#define EXYNOS_USBHOST_PHY_CTRL_OFFSET		(0x4)
-#define S3C64XX_USBPHY_ENABLE			(0x1 << 16)
-#define EXYNOS_USBPHY_ENABLE			(0x1 << 0)
-#define EXYNOS_USB20PHY_CFG_HOST_LINK		(0x1 << 0)
-
-enum samsung_cpu_type {
-	TYPE_S3C64XX,
-	TYPE_EXYNOS4210,
-	TYPE_EXYNOS5250,
-};
-
-/*
- * struct samsung_usbphy_drvdata - driver data for various SoC variants
- * @cpu_type: machine identifier
- * @devphy_en_mask: device phy enable mask for PHY CONTROL register
- * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
- * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
- *		       mapped address of system controller.
- * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
- *		       mapped address of system controller.
- *
- *	Here we have a separate mask for device type phy.
- *	Having different masks for host and device type phy helps
- *	in setting independent masks in case of SoCs like S5PV210,
- *	in which PHY0 and PHY1 enable bits belong to same register
- *	placed at position 0 and 1 respectively.
- *	Although for newer SoCs like exynos these bits belong to
- *	different registers altogether placed at position 0.
- */
-struct samsung_usbphy_drvdata {
-	int cpu_type;
-	int devphy_en_mask;
-	int hostphy_en_mask;
-	u32 devphy_reg_offset;
-	u32 hostphy_reg_offset;
-};
-
-/*
- * struct samsung_usbphy - transceiver driver state
- * @phy: transceiver structure
- * @plat: platform data
- * @dev: The parent device supplied to the probe function
- * @clk: usb phy clock
- * @regs: usb phy controller registers memory base
- * @pmuregs: USB device PHY_CONTROL register memory base
- * @sysreg: USB2.0 PHY_CFG register memory base
- * @ref_clk_freq: reference clock frequency selection
- * @drv_data: driver data available for different SoCs
- * @phy_type: Samsung SoCs specific phy types:	#HOST
- *						#DEVICE
- * @phy_usage: usage count for phy
- * @lock: lock for phy operations
- */
-struct samsung_usbphy {
-	struct usb_phy	phy;
-	struct samsung_usbphy_data *plat;
-	struct device	*dev;
-	struct clk	*clk;
-	void __iomem	*regs;
-	void __iomem	*pmuregs;
-	void __iomem	*sysreg;
-	int		ref_clk_freq;
-	const struct samsung_usbphy_drvdata *drv_data;
-	enum samsung_usb_phy_type phy_type;
-	atomic_t	phy_usage;
-	spinlock_t	lock;
-};
-
-#define phy_to_sphy(x)		container_of((x), struct samsung_usbphy, phy)
-
-int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
-{
-	if (!otg)
-		return -ENODEV;
-
-	if (!otg->host)
-		otg->host = host;
-
-	return 0;
-}
-
-static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
+int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
 {
 	struct device_node *usbphy_sys;
 
@@ -288,7 +71,7 @@ err0:
  * Here 'on = true' would mean USB PHY block is isolated, hence
  * de-activated and vice-versa.
  */
-static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
+void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
 {
 	void __iomem *reg = NULL;
 	u32 reg_val;
@@ -340,7 +123,7 @@ static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
 /*
  * Configure the mode of working of usb-phy here: HOST/DEVICE.
  */
-static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
+void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
 {
 	u32 reg;
 
@@ -364,7 +147,7 @@ static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
  * This make sure that correct PHY type is selected before
  * any operation on PHY.
  */
-static int samsung_usbphy_set_type(struct usb_phy *phy,
+int samsung_usbphy_set_type(struct usb_phy *phy,
 				enum samsung_usb_phy_type phy_type)
 {
 	struct samsung_usbphy *sphy = phy_to_sphy(phy);
@@ -377,7 +160,7 @@ static int samsung_usbphy_set_type(struct usb_phy *phy,
 /*
  * Returns reference clock frequency selection value
  */
-static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
+int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
 {
 	struct clk *ref_clk;
 	int refclk_freq = 0;
@@ -445,486 +228,3 @@ static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
 
 	return refclk_freq;
 }
-
-static bool exynos5_phyhost_is_on(void *regs)
-{
-	u32 reg;
-
-	reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	return !(reg & HOST_CTRL0_SIDDQ);
-}
-
-static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phyclk = sphy->ref_clk_freq;
-	u32 phyhost;
-	u32 phyotg;
-	u32 phyhsic;
-	u32 ehcictrl;
-	u32 ohcictrl;
-
-	/*
-	 * phy_usage helps in keeping usage count for phy
-	 * so that the first consumer enabling the phy is also
-	 * the last consumer to disable it.
-	 */
-
-	atomic_inc(&sphy->phy_usage);
-
-	if (exynos5_phyhost_is_on(regs)) {
-		dev_info(sphy->dev, "Already power on PHY\n");
-		return;
-	}
-
-	/* Host configuration */
-	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	/* phy reference clock configuration */
-	phyhost &= ~HOST_CTRL0_FSEL_MASK;
-	phyhost |= HOST_CTRL0_FSEL(phyclk);
-
-	/* host phy reset */
-	phyhost &= ~(HOST_CTRL0_PHYSWRST |
-			HOST_CTRL0_PHYSWRSTALL |
-			HOST_CTRL0_SIDDQ |
-			/* Enable normal mode of operation */
-			HOST_CTRL0_FORCESUSPEND |
-			HOST_CTRL0_FORCESLEEP);
-
-	/* Link reset */
-	phyhost |= (HOST_CTRL0_LINKSWRST |
-			HOST_CTRL0_UTMISWRST |
-			/* COMMON Block configuration during suspend */
-			HOST_CTRL0_COMMONON_N);
-	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-	udelay(10);
-	phyhost &= ~(HOST_CTRL0_LINKSWRST |
-			HOST_CTRL0_UTMISWRST);
-	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	/* OTG configuration */
-	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
-
-	/* phy reference clock configuration */
-	phyotg &= ~OTG_SYS_FSEL_MASK;
-	phyotg |= OTG_SYS_FSEL(phyclk);
-
-	/* Enable normal mode of operation */
-	phyotg &= ~(OTG_SYS_FORCESUSPEND |
-			OTG_SYS_SIDDQ_UOTG |
-			OTG_SYS_FORCESLEEP |
-			OTG_SYS_REFCLKSEL_MASK |
-			/* COMMON Block configuration during suspend */
-			OTG_SYS_COMMON_ON);
-
-	/* OTG phy & link reset */
-	phyotg |= (OTG_SYS_PHY0_SWRST |
-			OTG_SYS_LINKSWRST_UOTG |
-			OTG_SYS_PHYLINK_SWRESET |
-			OTG_SYS_OTGDISABLE |
-			/* Set phy refclk */
-			OTG_SYS_REFCLKSEL_CLKCORE);
-
-	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-	udelay(10);
-	phyotg &= ~(OTG_SYS_PHY0_SWRST |
-			OTG_SYS_LINKSWRST_UOTG |
-			OTG_SYS_PHYLINK_SWRESET);
-	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-
-	/* HSIC phy configuration */
-	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
-			HSIC_CTRL_REFCLKSEL |
-			HSIC_CTRL_PHYSWRST);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-	udelay(10);
-	phyhsic &= ~HSIC_CTRL_PHYSWRST;
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
-	udelay(80);
-
-	/* enable EHCI DMA burst */
-	ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
-	ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
-				HOST_EHCICTRL_ENAINCR4 |
-				HOST_EHCICTRL_ENAINCR8 |
-				HOST_EHCICTRL_ENAINCR16);
-	writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
-
-	/* set ohci_suspend_on_n */
-	ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
-	ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
-	writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
-}
-
-static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phypwr;
-	u32 phyclk;
-	u32 rstcon;
-
-	/* set clock frequency for PLL */
-	phyclk = sphy->ref_clk_freq;
-	phypwr = readl(regs + SAMSUNG_PHYPWR);
-	rstcon = readl(regs + SAMSUNG_RSTCON);
-
-	switch (sphy->drv_data->cpu_type) {
-	case TYPE_S3C64XX:
-		phyclk &= ~PHYCLK_COMMON_ON_N;
-		phypwr &= ~PHYPWR_NORMAL_MASK;
-		rstcon |= RSTCON_SWRST;
-		break;
-	case TYPE_EXYNOS4210:
-		phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
-		rstcon |= RSTCON_SWRST;
-	default:
-		break;
-	}
-
-	writel(phyclk, regs + SAMSUNG_PHYCLK);
-	/* Configure PHY0 for normal operation*/
-	writel(phypwr, regs + SAMSUNG_PHYPWR);
-	/* reset all ports of PHY and Link */
-	writel(rstcon, regs + SAMSUNG_RSTCON);
-	udelay(10);
-	rstcon &= ~RSTCON_SWRST;
-	writel(rstcon, regs + SAMSUNG_RSTCON);
-}
-
-static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phyhost;
-	u32 phyotg;
-	u32 phyhsic;
-
-	if (atomic_dec_return(&sphy->phy_usage) > 0) {
-		dev_info(sphy->dev, "still being used\n");
-		return;
-	}
-
-	phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
-			HSIC_CTRL_REFCLKSEL |
-			HSIC_CTRL_SIDDQ |
-			HSIC_CTRL_FORCESLEEP |
-			HSIC_CTRL_FORCESUSPEND);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
-	writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
-
-	phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
-	phyhost |= (HOST_CTRL0_SIDDQ |
-			HOST_CTRL0_FORCESUSPEND |
-			HOST_CTRL0_FORCESLEEP |
-			HOST_CTRL0_PHYSWRST |
-			HOST_CTRL0_PHYSWRSTALL);
-	writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
-
-	phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
-	phyotg |= (OTG_SYS_FORCESUSPEND |
-			OTG_SYS_SIDDQ_UOTG |
-			OTG_SYS_FORCESLEEP);
-	writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
-}
-
-static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
-{
-	void __iomem *regs = sphy->regs;
-	u32 phypwr;
-
-	phypwr = readl(regs + SAMSUNG_PHYPWR);
-
-	switch (sphy->drv_data->cpu_type) {
-	case TYPE_S3C64XX:
-		phypwr |= PHYPWR_NORMAL_MASK;
-		break;
-	case TYPE_EXYNOS4210:
-		phypwr |= PHYPWR_NORMAL_MASK_PHY0;
-	default:
-		break;
-	}
-
-	/* Disable analog and otg block power */
-	writel(phypwr, regs + SAMSUNG_PHYPWR);
-}
-
-/*
- * The function passed to the usb driver for phy initialization
- */
-static int samsung_usbphy_init(struct usb_phy *phy)
-{
-	struct samsung_usbphy *sphy;
-	struct usb_bus *host = NULL;
-	unsigned long flags;
-	int ret = 0;
-
-	sphy = phy_to_sphy(phy);
-
-	host = phy->otg->host;
-
-	/* Enable the phy clock */
-	ret = clk_prepare_enable(sphy->clk);
-	if (ret) {
-		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
-		return ret;
-	}
-
-	spin_lock_irqsave(&sphy->lock, flags);
-
-	if (host) {
-		/* setting default phy-type for USB 2.0 */
-		if (!strstr(dev_name(host->controller), "ehci") ||
-				!strstr(dev_name(host->controller), "ohci"))
-			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
-	} else {
-		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
-	}
-
-	/* Disable phy isolation */
-	if (sphy->plat && sphy->plat->pmu_isolation)
-		sphy->plat->pmu_isolation(false);
-	else
-		samsung_usbphy_set_isolation(sphy, false);
-
-	/* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
-	samsung_usbphy_cfg_sel(sphy);
-
-	/* Initialize usb phy registers */
-	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-		samsung_exynos5_usbphy_enable(sphy);
-	else
-		samsung_usbphy_enable(sphy);
-
-	spin_unlock_irqrestore(&sphy->lock, flags);
-
-	/* Disable the phy clock */
-	clk_disable_unprepare(sphy->clk);
-
-	return ret;
-}
-
-/*
- * The function passed to the usb driver for phy shutdown
- */
-static void samsung_usbphy_shutdown(struct usb_phy *phy)
-{
-	struct samsung_usbphy *sphy;
-	struct usb_bus *host = NULL;
-	unsigned long flags;
-
-	sphy = phy_to_sphy(phy);
-
-	host = phy->otg->host;
-
-	if (clk_prepare_enable(sphy->clk)) {
-		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
-		return;
-	}
-
-	spin_lock_irqsave(&sphy->lock, flags);
-
-	if (host) {
-		/* setting default phy-type for USB 2.0 */
-		if (!strstr(dev_name(host->controller), "ehci") ||
-				!strstr(dev_name(host->controller), "ohci"))
-			samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
-	} else {
-		samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
-	}
-
-	/* De-initialize usb phy registers */
-	if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
-		samsung_exynos5_usbphy_disable(sphy);
-	else
-		samsung_usbphy_disable(sphy);
-
-	/* Enable phy isolation */
-	if (sphy->plat && sphy->plat->pmu_isolation)
-		sphy->plat->pmu_isolation(true);
-	else
-		samsung_usbphy_set_isolation(sphy, true);
-
-	spin_unlock_irqrestore(&sphy->lock, flags);
-
-	clk_disable_unprepare(sphy->clk);
-}
-
-static const struct of_device_id samsung_usbphy_dt_match[];
-
-static inline const struct samsung_usbphy_drvdata
-*samsung_usbphy_get_driver_data(struct platform_device *pdev)
-{
-	if (pdev->dev.of_node) {
-		const struct of_device_id *match;
-		match = of_match_node(samsung_usbphy_dt_match,
-							pdev->dev.of_node);
-		return match->data;
-	}
-
-	return (struct samsung_usbphy_drvdata *)
-				platform_get_device_id(pdev)->driver_data;
-}
-
-static int samsung_usbphy_probe(struct platform_device *pdev)
-{
-	struct samsung_usbphy *sphy;
-	struct usb_otg *otg;
-	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
-	const struct samsung_usbphy_drvdata *drv_data;
-	struct device *dev = &pdev->dev;
-	struct resource *phy_mem;
-	void __iomem	*phy_base;
-	struct clk *clk;
-	int ret;
-
-	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!phy_mem) {
-		dev_err(dev, "%s: missing mem resource\n", __func__);
-		return -ENODEV;
-	}
-
-	phy_base = devm_request_and_ioremap(dev, phy_mem);
-	if (!phy_base) {
-		dev_err(dev, "%s: register mapping failed\n", __func__);
-		return -ENXIO;
-	}
-
-	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
-	if (!sphy)
-		return -ENOMEM;
-
-	otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
-	if (!otg)
-		return -ENOMEM;
-
-	drv_data = samsung_usbphy_get_driver_data(pdev);
-
-	if (drv_data->cpu_type == TYPE_EXYNOS5250)
-		clk = devm_clk_get(dev, "usbhost");
-	else
-		clk = devm_clk_get(dev, "otg");
-
-	if (IS_ERR(clk)) {
-		dev_err(dev, "Failed to get otg clock\n");
-		return PTR_ERR(clk);
-	}
-
-	sphy->dev = dev;
-
-	if (dev->of_node) {
-		ret = samsung_usbphy_parse_dt(sphy);
-		if (ret < 0)
-			return ret;
-	} else {
-		if (!pdata) {
-			dev_err(dev, "no platform data specified\n");
-			return -EINVAL;
-		}
-	}
-
-	sphy->plat		= pdata;
-	sphy->regs		= phy_base;
-	sphy->clk		= clk;
-	sphy->drv_data		= drv_data;
-	sphy->phy.dev		= sphy->dev;
-	sphy->phy.label		= "samsung-usbphy";
-	sphy->phy.init		= samsung_usbphy_init;
-	sphy->phy.shutdown	= samsung_usbphy_shutdown;
-	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy);
-
-	sphy->phy.otg		= otg;
-	sphy->phy.otg->phy	= &sphy->phy;
-	sphy->phy.otg->set_host = samsung_usbphy_set_host;
-
-	spin_lock_init(&sphy->lock);
-
-	platform_set_drvdata(pdev, sphy);
-
-	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
-}
-
-static int samsung_usbphy_remove(struct platform_device *pdev)
-{
-	struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
-
-	usb_remove_phy(&sphy->phy);
-
-	if (sphy->pmuregs)
-		iounmap(sphy->pmuregs);
-	if (sphy->sysreg)
-		iounmap(sphy->sysreg);
-
-	return 0;
-}
-
-static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
-	.cpu_type		= TYPE_S3C64XX,
-	.devphy_en_mask		= S3C64XX_USBPHY_ENABLE,
-};
-
-static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
-	.cpu_type		= TYPE_EXYNOS4210,
-	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE,
-	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
-};
-
-static struct samsung_usbphy_drvdata usbphy_exynos5 = {
-	.cpu_type		= TYPE_EXYNOS5250,
-	.hostphy_en_mask	= EXYNOS_USBPHY_ENABLE,
-	.hostphy_reg_offset	= EXYNOS_USBHOST_PHY_CTRL_OFFSET,
-};
-
-#ifdef CONFIG_OF
-static const struct of_device_id samsung_usbphy_dt_match[] = {
-	{
-		.compatible = "samsung,s3c64xx-usbphy",
-		.data = &usbphy_s3c64xx,
-	}, {
-		.compatible = "samsung,exynos4210-usbphy",
-		.data = &usbphy_exynos4,
-	}, {
-		.compatible = "samsung,exynos5250-usbphy",
-		.data = &usbphy_exynos5
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
-#endif
-
-static struct platform_device_id samsung_usbphy_driver_ids[] = {
-	{
-		.name		= "s3c64xx-usbphy",
-		.driver_data	= (unsigned long)&usbphy_s3c64xx,
-	}, {
-		.name		= "exynos4210-usbphy",
-		.driver_data	= (unsigned long)&usbphy_exynos4,
-	}, {
-		.name		= "exynos5250-usbphy",
-		.driver_data	= (unsigned long)&usbphy_exynos5,
-	},
-	{},
-};
-
-MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
-
-static struct platform_driver samsung_usbphy_driver = {
-	.probe		= samsung_usbphy_probe,
-	.remove		= samsung_usbphy_remove,
-	.id_table	= samsung_usbphy_driver_ids,
-	.driver		= {
-		.name	= "samsung-usbphy",
-		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(samsung_usbphy_dt_match),
-	},
-};
-
-module_platform_driver(samsung_usbphy_driver);
-
-MODULE_DESCRIPTION("Samsung USB phy controller");
-MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:samsung-usbphy");
diff --git a/drivers/usb/phy/samsung-usbphy.h b/drivers/usb/phy/samsung-usbphy.h
new file mode 100644
index 0000000..969632b
--- /dev/null
+++ b/drivers/usb/phy/samsung-usbphy.h
@@ -0,0 +1,247 @@
+/* linux/drivers/usb/phy/samsung-usbphy.h
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
+ * OHCI-EXYNOS controllers.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/usb/phy.h>
+
+/* Register definitions */
+
+#define SAMSUNG_PHYPWR				(0x00)
+
+#define PHYPWR_NORMAL_MASK			(0x19 << 0)
+#define PHYPWR_OTG_DISABLE			(0x1 << 4)
+#define PHYPWR_ANALOG_POWERDOWN			(0x1 << 3)
+#define PHYPWR_FORCE_SUSPEND			(0x1 << 1)
+/* For Exynos4 */
+#define PHYPWR_NORMAL_MASK_PHY0			(0x39 << 0)
+#define PHYPWR_SLEEP_PHY0			(0x1 << 5)
+
+#define SAMSUNG_PHYCLK				(0x04)
+
+#define PHYCLK_MODE_USB11			(0x1 << 6)
+#define PHYCLK_EXT_OSC				(0x1 << 5)
+#define PHYCLK_COMMON_ON_N			(0x1 << 4)
+#define PHYCLK_ID_PULL				(0x1 << 2)
+#define PHYCLK_CLKSEL_MASK			(0x3 << 0)
+#define PHYCLK_CLKSEL_48M			(0x0 << 0)
+#define PHYCLK_CLKSEL_12M			(0x2 << 0)
+#define PHYCLK_CLKSEL_24M			(0x3 << 0)
+
+#define SAMSUNG_RSTCON				(0x08)
+
+#define RSTCON_PHYLINK_SWRST			(0x1 << 2)
+#define RSTCON_HLINK_SWRST			(0x1 << 1)
+#define RSTCON_SWRST				(0x1 << 0)
+
+/* EXYNOS5 */
+#define EXYNOS5_PHY_HOST_CTRL0			(0x00)
+
+#define HOST_CTRL0_PHYSWRSTALL			(0x1 << 31)
+
+#define HOST_CTRL0_REFCLKSEL_MASK		(0x3 << 19)
+#define HOST_CTRL0_REFCLKSEL_XTAL		(0x0 << 19)
+#define HOST_CTRL0_REFCLKSEL_EXTL		(0x1 << 19)
+#define HOST_CTRL0_REFCLKSEL_CLKCORE		(0x2 << 19)
+
+#define HOST_CTRL0_FSEL_MASK			(0x7 << 16)
+#define HOST_CTRL0_FSEL(_x)			((_x) << 16)
+
+#define FSEL_CLKSEL_50M				(0x7)
+#define FSEL_CLKSEL_24M				(0x5)
+#define FSEL_CLKSEL_20M				(0x4)
+#define FSEL_CLKSEL_19200K			(0x3)
+#define FSEL_CLKSEL_12M				(0x2)
+#define FSEL_CLKSEL_10M				(0x1)
+#define FSEL_CLKSEL_9600K			(0x0)
+
+#define HOST_CTRL0_TESTBURNIN			(0x1 << 11)
+#define HOST_CTRL0_RETENABLE			(0x1 << 10)
+#define HOST_CTRL0_COMMONON_N			(0x1 << 9)
+#define HOST_CTRL0_SIDDQ			(0x1 << 6)
+#define HOST_CTRL0_FORCESLEEP			(0x1 << 5)
+#define HOST_CTRL0_FORCESUSPEND			(0x1 << 4)
+#define HOST_CTRL0_WORDINTERFACE		(0x1 << 3)
+#define HOST_CTRL0_UTMISWRST			(0x1 << 2)
+#define HOST_CTRL0_LINKSWRST			(0x1 << 1)
+#define HOST_CTRL0_PHYSWRST			(0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_TUNE0			(0x04)
+
+#define EXYNOS5_PHY_HSIC_CTRL1			(0x10)
+
+#define EXYNOS5_PHY_HSIC_TUNE1			(0x14)
+
+#define EXYNOS5_PHY_HSIC_CTRL2			(0x20)
+
+#define EXYNOS5_PHY_HSIC_TUNE2			(0x24)
+
+#define HSIC_CTRL_REFCLKSEL_MASK		(0x3 << 23)
+#define HSIC_CTRL_REFCLKSEL			(0x2 << 23)
+
+#define HSIC_CTRL_REFCLKDIV_MASK		(0x7f << 16)
+#define HSIC_CTRL_REFCLKDIV(_x)			((_x) << 16)
+#define HSIC_CTRL_REFCLKDIV_12			(0x24 << 16)
+#define HSIC_CTRL_REFCLKDIV_15			(0x1c << 16)
+#define HSIC_CTRL_REFCLKDIV_16			(0x1a << 16)
+#define HSIC_CTRL_REFCLKDIV_19_2		(0x15 << 16)
+#define HSIC_CTRL_REFCLKDIV_20			(0x14 << 16)
+
+#define HSIC_CTRL_SIDDQ				(0x1 << 6)
+#define HSIC_CTRL_FORCESLEEP			(0x1 << 5)
+#define HSIC_CTRL_FORCESUSPEND			(0x1 << 4)
+#define HSIC_CTRL_WORDINTERFACE			(0x1 << 3)
+#define HSIC_CTRL_UTMISWRST			(0x1 << 2)
+#define HSIC_CTRL_PHYSWRST			(0x1 << 0)
+
+#define EXYNOS5_PHY_HOST_EHCICTRL		(0x30)
+
+#define HOST_EHCICTRL_ENAINCRXALIGN		(0x1 << 29)
+#define HOST_EHCICTRL_ENAINCR4			(0x1 << 28)
+#define HOST_EHCICTRL_ENAINCR8			(0x1 << 27)
+#define HOST_EHCICTRL_ENAINCR16			(0x1 << 26)
+
+#define EXYNOS5_PHY_HOST_OHCICTRL		(0x34)
+
+#define HOST_OHCICTRL_SUSPLGCY			(0x1 << 3)
+#define HOST_OHCICTRL_APPSTARTCLK		(0x1 << 2)
+#define HOST_OHCICTRL_CNTSEL			(0x1 << 1)
+#define HOST_OHCICTRL_CLKCKTRST			(0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_SYS			(0x38)
+
+#define OTG_SYS_PHYLINK_SWRESET			(0x1 << 14)
+#define OTG_SYS_LINKSWRST_UOTG			(0x1 << 13)
+#define OTG_SYS_PHY0_SWRST			(0x1 << 12)
+
+#define OTG_SYS_REFCLKSEL_MASK			(0x3 << 9)
+#define OTG_SYS_REFCLKSEL_XTAL			(0x0 << 9)
+#define OTG_SYS_REFCLKSEL_EXTL			(0x1 << 9)
+#define OTG_SYS_REFCLKSEL_CLKCORE		(0x2 << 9)
+
+#define OTG_SYS_IDPULLUP_UOTG			(0x1 << 8)
+#define OTG_SYS_COMMON_ON			(0x1 << 7)
+
+#define OTG_SYS_FSEL_MASK			(0x7 << 4)
+#define OTG_SYS_FSEL(_x)			((_x) << 4)
+
+#define OTG_SYS_FORCESLEEP			(0x1 << 3)
+#define OTG_SYS_OTGDISABLE			(0x1 << 2)
+#define OTG_SYS_SIDDQ_UOTG			(0x1 << 1)
+#define OTG_SYS_FORCESUSPEND			(0x1 << 0)
+
+#define EXYNOS5_PHY_OTG_TUNE			(0x40)
+
+#ifndef MHZ
+#define MHZ (1000*1000)
+#endif
+
+#ifndef KHZ
+#define KHZ (1000)
+#endif
+
+#define EXYNOS_USBHOST_PHY_CTRL_OFFSET		(0x4)
+#define S3C64XX_USBPHY_ENABLE			(0x1 << 16)
+#define EXYNOS_USBPHY_ENABLE			(0x1 << 0)
+#define EXYNOS_USB20PHY_CFG_HOST_LINK		(0x1 << 0)
+
+enum samsung_cpu_type {
+	TYPE_S3C64XX,
+	TYPE_EXYNOS4210,
+	TYPE_EXYNOS5250,
+};
+
+/*
+ * struct samsung_usbphy_drvdata - driver data for various SoC variants
+ * @cpu_type: machine identifier
+ * @devphy_en_mask: device phy enable mask for PHY CONTROL register
+ * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
+ * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
+ *		       mapped address of system controller.
+ * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
+ *		       mapped address of system controller.
+ *
+ *	Here we have a separate mask for device type phy.
+ *	Having different masks for host and device type phy helps
+ *	in setting independent masks in case of SoCs like S5PV210,
+ *	in which PHY0 and PHY1 enable bits belong to same register
+ *	placed at position 0 and 1 respectively.
+ *	Although for newer SoCs like exynos these bits belong to
+ *	different registers altogether placed at position 0.
+ */
+struct samsung_usbphy_drvdata {
+	int cpu_type;
+	int devphy_en_mask;
+	int hostphy_en_mask;
+	u32 devphy_reg_offset;
+	u32 hostphy_reg_offset;
+};
+
+/*
+ * struct samsung_usbphy - transceiver driver state
+ * @phy: transceiver structure
+ * @plat: platform data
+ * @dev: The parent device supplied to the probe function
+ * @clk: usb phy clock
+ * @regs: usb phy controller registers memory base
+ * @pmuregs: USB device PHY_CONTROL register memory base
+ * @sysreg: USB2.0 PHY_CFG register memory base
+ * @ref_clk_freq: reference clock frequency selection
+ * @drv_data: driver data available for different SoCs
+ * @phy_type: Samsung SoCs specific phy types:	#HOST
+ *						#DEVICE
+ * @phy_usage: usage count for phy
+ * @lock: lock for phy operations
+ */
+struct samsung_usbphy {
+	struct usb_phy	phy;
+	struct samsung_usbphy_data *plat;
+	struct device	*dev;
+	struct clk	*clk;
+	void __iomem	*regs;
+	void __iomem	*pmuregs;
+	void __iomem	*sysreg;
+	int		ref_clk_freq;
+	const struct samsung_usbphy_drvdata *drv_data;
+	enum samsung_usb_phy_type phy_type;
+	atomic_t	phy_usage;
+	spinlock_t	lock;
+};
+
+#define phy_to_sphy(x)		container_of((x), struct samsung_usbphy, phy)
+
+static const struct of_device_id samsung_usbphy_dt_match[];
+
+static inline const struct samsung_usbphy_drvdata
+*samsung_usbphy_get_driver_data(struct platform_device *pdev)
+{
+	if (pdev->dev.of_node) {
+		const struct of_device_id *match;
+		match = of_match_node(samsung_usbphy_dt_match,
+							pdev->dev.of_node);
+		return match->data;
+	}
+
+	return (struct samsung_usbphy_drvdata *)
+				platform_get_device_id(pdev)->driver_data;
+}
+
+extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy);
+extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on);
+extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy);
+extern int samsung_usbphy_set_type(struct usb_phy *phy,
+				enum samsung_usb_phy_type phy_type);
+extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy);
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v4 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller
  2013-01-14 12:59 ` [PATCH v3 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller Vivek Gautam
@ 2013-01-28 10:26   ` Vivek Gautam
  2013-01-29  5:35     ` Vivek Gautam
  2013-01-30  6:01     ` Kukjin Kim
  0 siblings, 2 replies; 14+ messages in thread
From: Vivek Gautam @ 2013-01-28 10:26 UTC (permalink / raw)
  To: linux-usb
  Cc: linux-kernel, devicetree-discuss, linux-samsung-soc, gregkh,
	balbi, kgene.kim, grant.likely, sylvester.nawrocki, tomasz.figa,
	av.tikhomirov, dianders, p.paneri

Adding PHY driver support for USB 3.0 controller for Samsung's
SoCs.

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
---

Changes from v3:
 - Making SAMSUNG_USB3PHY dependent on SAMSUNG_USBPHY.
 - Adding USB_DWC3 to dependencies of SAMSUNG_USB2PHY since
   dwc3 controller also looks for USB2 type PHY.

 drivers/usb/phy/Kconfig          |   11 +-
 drivers/usb/phy/Makefile         |    1 +
 drivers/usb/phy/samsung-usb3.c   |  349 ++++++++++++++++++++++++++++++++++++++
 drivers/usb/phy/samsung-usbphy.h |   81 +++++++++
 4 files changed, 441 insertions(+), 1 deletions(-)
 create mode 100644 drivers/usb/phy/samsung-usb3.c

diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index cc0d230..9325a95 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -52,14 +52,23 @@ config SAMSUNG_USBPHY
 	help
 	  Enable this to support Samsung USB phy controllers for Samsung
 	  SoCs.
+	  Further enable USB 2.0 type PHY or USB 3.0 type PHY as required
+	  for USB controllers in use.
 
 if SAMSUNG_USBPHY
 
 config SAMSUNG_USB2PHY
 	bool "Samsung USB 2.0 PHY controller Driver"
-	depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS
+	depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS || USB_DWC3
 	help
 	  Enable this to support Samsung USB 2.0 (High Speed) phy controller
 	  for Samsung SoCs.
 
+config SAMSUNG_USB3PHY
+	bool "Samsung USB 3.0 PHY controller Driver"
+	depends on USB_DWC3
+	help
+	  Enable this to support Samsung USB 3.0 (Super Speed) phy controller
+	  for samsung SoCs.
+
 endif
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index 7ba9862..b8505ac 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
 obj-$(CONFIG_USB_RCAR_PHY)		+= rcar-phy.o
 obj-$(CONFIG_SAMSUNG_USBPHY)		+= samsung-usbphy.o
 obj-$(CONFIG_SAMSUNG_USB2PHY)		+= samsung-usb2.o
+obj-$(CONFIG_SAMSUNG_USB3PHY)		+= samsung-usb3.o
diff --git a/drivers/usb/phy/samsung-usb3.c b/drivers/usb/phy/samsung-usb3.c
new file mode 100644
index 0000000..29e1321
--- /dev/null
+++ b/drivers/usb/phy/samsung-usb3.c
@@ -0,0 +1,349 @@
+/* linux/drivers/usb/phy/samsung-usb3.c
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *              http://www.samsung.com
+ *
+ * Author: Vivek Gautam <gautam.vivek@samsung.com>
+ *
+ * Samsung USB 3.0 PHY transceiver; talks to DWC3 controller.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/usb/samsung_usb_phy.h>
+#include <linux/platform_data/samsung-usbphy.h>
+
+#include "samsung-usbphy.h"
+
+/*
+ * Sets the phy clk as EXTREFCLK (XXTI) which is internal clock from clock core.
+ */
+static u32 samsung_usb3_phy_set_refclk(struct samsung_usbphy *sphy)
+{
+	u32 reg;
+	u32 refclk;
+
+	refclk = sphy->ref_clk_freq;
+
+	reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK |
+		PHYCLKRST_FSEL(refclk);
+
+	switch (refclk) {
+	case FSEL_CLKSEL_50M:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x00));
+		break;
+	case FSEL_CLKSEL_20M:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x00));
+		break;
+	case FSEL_CLKSEL_19200K:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x88));
+		break;
+	case FSEL_CLKSEL_24M:
+	default:
+		reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
+			PHYCLKRST_SSC_REFCLKSEL(0x88));
+		break;
+	}
+
+	return reg;
+}
+
+static int samsung_exynos5_usb3_phy_enable(struct samsung_usbphy *sphy)
+{
+	void __iomem *regs = sphy->regs;
+	u32 phyparam0;
+	u32 phyparam1;
+	u32 linksystem;
+	u32 phybatchg;
+	u32 phytest;
+	u32 phyclkrst;
+
+	/* Reset USB 3.0 PHY */
+	writel(0x0, regs + EXYNOS5_DRD_PHYREG0);
+
+	phyparam0 = readl(regs + EXYNOS5_DRD_PHYPARAM0);
+	/* Select PHY CLK source */
+	phyparam0 &= ~PHYPARAM0_REF_USE_PAD;
+	/* Set Loss-of-Signal Detector sensitivity */
+	phyparam0 &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
+	phyparam0 |= PHYPARAM0_REF_LOSLEVEL;
+	writel(phyparam0, regs + EXYNOS5_DRD_PHYPARAM0);
+
+	writel(0x0, regs + EXYNOS5_DRD_PHYRESUME);
+
+	/*
+	 * Setting the Frame length Adj value[6:1] to default 0x20
+	 * See xHCI 1.0 spec, 5.2.4
+	 */
+	linksystem = LINKSYSTEM_XHCI_VERSION_CONTROL |
+			LINKSYSTEM_FLADJ(0x20);
+	writel(linksystem, regs + EXYNOS5_DRD_LINKSYSTEM);
+
+	phyparam1 = readl(regs + EXYNOS5_DRD_PHYPARAM1);
+	/* Set Tx De-Emphasis level */
+	phyparam1 &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
+	phyparam1 |= PHYPARAM1_PCS_TXDEEMPH;
+	writel(phyparam1, regs + EXYNOS5_DRD_PHYPARAM1);
+
+	phybatchg = readl(regs + EXYNOS5_DRD_PHYBATCHG);
+	phybatchg |= PHYBATCHG_UTMI_CLKSEL;
+	writel(phybatchg, regs + EXYNOS5_DRD_PHYBATCHG);
+
+	/* PHYTEST POWERDOWN Control */
+	phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+	phytest &= ~(PHYTEST_POWERDOWN_SSP |
+			PHYTEST_POWERDOWN_HSP);
+	writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+
+	/* UTMI Power Control */
+	writel(PHYUTMI_OTGDISABLE, regs + EXYNOS5_DRD_PHYUTMI);
+
+	phyclkrst = samsung_usb3_phy_set_refclk(sphy);
+
+	phyclkrst |= PHYCLKRST_PORTRESET |
+			/* Digital power supply in normal operating mode */
+			PHYCLKRST_RETENABLEN |
+			/* Enable ref clock for SS function */
+			PHYCLKRST_REF_SSP_EN |
+			/* Enable spread spectrum */
+			PHYCLKRST_SSC_EN |
+			/* Power down HS Bias and PLL blocks in suspend mode */
+			PHYCLKRST_COMMONONN;
+
+	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+	udelay(10);
+
+	phyclkrst &= ~(PHYCLKRST_PORTRESET);
+	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+	return 0;
+}
+
+static void samsung_exynos5_usb3_phy_disable(struct samsung_usbphy *sphy)
+{
+	u32 phyutmi;
+	u32 phyclkrst;
+	u32 phytest;
+	void __iomem *regs = sphy->regs;
+
+	phyutmi = PHYUTMI_OTGDISABLE |
+			PHYUTMI_FORCESUSPEND |
+			PHYUTMI_FORCESLEEP;
+	writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI);
+
+	/* Resetting the PHYCLKRST enable bits to reduce leakage current */
+	phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST);
+	phyclkrst &= ~(PHYCLKRST_REF_SSP_EN |
+			PHYCLKRST_SSC_EN |
+			PHYCLKRST_COMMONONN);
+	writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
+
+	/* Control PHYTEST to remove leakage current */
+	phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
+	phytest |= (PHYTEST_POWERDOWN_SSP |
+			PHYTEST_POWERDOWN_HSP);
+	writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
+}
+
+static int samsung_usb3_phy_init(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	unsigned long flags;
+	int ret = 0;
+
+	sphy = phy_to_sphy(phy);
+
+	/* Enable the phy clock */
+	ret = clk_prepare_enable(sphy->clk);
+	if (ret) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return ret;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	/* setting default phy-type for USB 3.0 */
+	samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+	/* Disable phy isolation */
+	samsung_usbphy_set_isolation(sphy, false);
+
+	/* Initialize usb phy registers */
+	samsung_exynos5_usb3_phy_enable(sphy);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	/* Disable the phy clock */
+	clk_disable_unprepare(sphy->clk);
+
+	return ret;
+}
+
+/*
+ * The function passed to the usb driver for phy shutdown
+ */
+static void samsung_usb3_phy_shutdown(struct usb_phy *phy)
+{
+	struct samsung_usbphy *sphy;
+	unsigned long flags;
+
+	sphy = phy_to_sphy(phy);
+
+	if (clk_prepare_enable(sphy->clk)) {
+		dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
+		return;
+	}
+
+	spin_lock_irqsave(&sphy->lock, flags);
+
+	/* setting default phy-type for USB 3.0 */
+	samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
+
+	/* De-initialize usb phy registers */
+	samsung_exynos5_usb3_phy_disable(sphy);
+
+	/* Enable phy isolation */
+	samsung_usbphy_set_isolation(sphy, true);
+
+	spin_unlock_irqrestore(&sphy->lock, flags);
+
+	clk_disable_unprepare(sphy->clk);
+}
+
+static int samsung_usb3_phy_probe(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy;
+	struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct resource *phy_mem;
+	void __iomem	*phy_base;
+	struct clk *clk;
+	int ret;
+
+	phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!phy_mem) {
+		dev_err(dev, "%s: missing mem resource\n", __func__);
+		return -ENODEV;
+	}
+
+	phy_base = devm_request_and_ioremap(dev, phy_mem);
+	if (!phy_base) {
+		dev_err(dev, "%s: register mapping failed\n", __func__);
+		return -ENXIO;
+	}
+
+	sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
+	if (!sphy)
+		return -ENOMEM;
+
+	clk = devm_clk_get(dev, "usbdrd30");
+	if (IS_ERR(clk)) {
+		dev_err(dev, "Failed to get device clock\n");
+		return PTR_ERR(clk);
+	}
+
+	sphy->dev = dev;
+
+	if (dev->of_node) {
+		ret = samsung_usbphy_parse_dt(sphy);
+		if (ret < 0)
+			return ret;
+	} else {
+		if (!pdata) {
+			dev_err(dev, "no platform data specified\n");
+			return -EINVAL;
+		}
+	}
+
+	sphy->plat		= pdata;
+	sphy->regs		= phy_base;
+	sphy->clk		= clk;
+	sphy->phy.dev		= sphy->dev;
+	sphy->phy.label		= "samsung-usb3-phy";
+	sphy->phy.init		= samsung_usb3_phy_init;
+	sphy->phy.shutdown	= samsung_usb3_phy_shutdown;
+	sphy->drv_data		= samsung_usbphy_get_driver_data(pdev);
+	sphy->ref_clk_freq	= samsung_usbphy_get_refclk_freq(sphy);
+
+	spin_lock_init(&sphy->lock);
+
+	platform_set_drvdata(pdev, sphy);
+
+	return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3);
+}
+
+static int samsung_usb3_phy_remove(struct platform_device *pdev)
+{
+	struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
+
+	usb_remove_phy(&sphy->phy);
+
+	if (sphy->pmuregs)
+		iounmap(sphy->pmuregs);
+	if (sphy->sysreg)
+		iounmap(sphy->sysreg);
+
+	return 0;
+}
+
+static struct samsung_usbphy_drvdata usb3_phy_exynos5 = {
+	.cpu_type		= TYPE_EXYNOS5250,
+	.devphy_en_mask		= EXYNOS_USBPHY_ENABLE,
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id samsung_usbphy_dt_match[] = {
+	{
+		.compatible = "samsung,exynos5250-usb3-phy",
+		.data = &usb3_phy_exynos5
+	},
+	{},
+};
+MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
+#endif
+
+static struct platform_device_id samsung_usbphy_driver_ids[] = {
+	{
+		.name		= "exynos5250-usb3-phy",
+		.driver_data	= (unsigned long)&usb3_phy_exynos5,
+	},
+	{},
+};
+
+MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
+
+static struct platform_driver samsung_usb3_phy_driver = {
+	.probe		= samsung_usb3_phy_probe,
+	.remove		= samsung_usb3_phy_remove,
+	.id_table	= samsung_usbphy_driver_ids,
+	.driver		= {
+		.name	= "samsung-usb3-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table = of_match_ptr(samsung_usbphy_dt_match),
+	},
+};
+
+module_platform_driver(samsung_usb3_phy_driver);
+
+MODULE_DESCRIPTION("Samsung USB 3.0 phy controller");
+MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:samsung-usb3-phy");
diff --git a/drivers/usb/phy/samsung-usbphy.h b/drivers/usb/phy/samsung-usbphy.h
index 969632b..f7e657d 100644
--- a/drivers/usb/phy/samsung-usbphy.h
+++ b/drivers/usb/phy/samsung-usbphy.h
@@ -145,6 +145,87 @@
 
 #define EXYNOS5_PHY_OTG_TUNE			(0x40)
 
+/* EXYNOS5: USB 3.0 DRD */
+#define EXYNOS5_DRD_LINKSYSTEM			(0x04)
+
+#define LINKSYSTEM_FLADJ_MASK			(0x3f << 1)
+#define LINKSYSTEM_FLADJ(_x)			((_x) << 1)
+#define LINKSYSTEM_XHCI_VERSION_CONTROL		(0x1 << 27)
+
+#define EXYNOS5_DRD_PHYUTMI			(0x08)
+
+#define PHYUTMI_OTGDISABLE			(0x1 << 6)
+#define PHYUTMI_FORCESUSPEND			(0x1 << 1)
+#define PHYUTMI_FORCESLEEP			(0x1 << 0)
+
+#define EXYNOS5_DRD_PHYPIPE			(0x0c)
+
+#define EXYNOS5_DRD_PHYCLKRST			(0x10)
+
+#define PHYCLKRST_SSC_REFCLKSEL_MASK		(0xff << 23)
+#define PHYCLKRST_SSC_REFCLKSEL(_x)		((_x) << 23)
+
+#define PHYCLKRST_SSC_RANGE_MASK		(0x03 << 21)
+#define PHYCLKRST_SSC_RANGE(_x)			((_x) << 21)
+
+#define PHYCLKRST_SSC_EN			(0x1 << 20)
+#define PHYCLKRST_REF_SSP_EN			(0x1 << 19)
+#define PHYCLKRST_REF_CLKDIV2			(0x1 << 18)
+
+#define PHYCLKRST_MPLL_MULTIPLIER_MASK		(0x7f << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF	(0x19 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF	(0x02 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF	(0x68 << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF	(0x7d << 11)
+#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF	(0x02 << 11)
+
+#define PHYCLKRST_FSEL_MASK			(0x3f << 5)
+#define PHYCLKRST_FSEL(_x)			((_x) << 5)
+#define PHYCLKRST_FSEL_PAD_100MHZ		(0x27 << 5)
+#define PHYCLKRST_FSEL_PAD_24MHZ		(0x2a << 5)
+#define PHYCLKRST_FSEL_PAD_20MHZ		(0x31 << 5)
+#define PHYCLKRST_FSEL_PAD_19_2MHZ		(0x38 << 5)
+
+#define PHYCLKRST_RETENABLEN			(0x1 << 4)
+
+#define PHYCLKRST_REFCLKSEL_MASK		(0x03 << 2)
+#define PHYCLKRST_REFCLKSEL_PAD_REFCLK		(0x2 << 2)
+#define PHYCLKRST_REFCLKSEL_EXT_REFCLK		(0x3 << 2)
+
+#define PHYCLKRST_PORTRESET			(0x1 << 1)
+#define PHYCLKRST_COMMONONN			(0x1 << 0)
+
+#define EXYNOS5_DRD_PHYREG0			(0x14)
+#define EXYNOS5_DRD_PHYREG1			(0x18)
+
+#define EXYNOS5_DRD_PHYPARAM0			(0x1c)
+
+#define PHYPARAM0_REF_USE_PAD			(0x1 << 31)
+#define PHYPARAM0_REF_LOSLEVEL_MASK		(0x1f << 26)
+#define PHYPARAM0_REF_LOSLEVEL			(0x9 << 26)
+
+#define EXYNOS5_DRD_PHYPARAM1			(0x20)
+
+#define PHYPARAM1_PCS_TXDEEMPH_MASK		(0x1f << 0)
+#define PHYPARAM1_PCS_TXDEEMPH			(0x1c)
+
+#define EXYNOS5_DRD_PHYTERM			(0x24)
+
+#define EXYNOS5_DRD_PHYTEST			(0x28)
+
+#define PHYTEST_POWERDOWN_SSP			(0x1 << 3)
+#define PHYTEST_POWERDOWN_HSP			(0x1 << 2)
+
+#define EXYNOS5_DRD_PHYADP			(0x2c)
+
+#define EXYNOS5_DRD_PHYBATCHG			(0x30)
+
+#define PHYBATCHG_UTMI_CLKSEL			(0x1 << 2)
+
+#define EXYNOS5_DRD_PHYRESUME			(0x34)
+#define EXYNOS5_DRD_LINKPORT			(0x44)
+
+
 #ifndef MHZ
 #define MHZ (1000*1000)
 #endif
-- 
1.7.6.5


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 1/2] usb: phy: samsung: Common out the generic stuff
  2013-01-28 10:24   ` [PATCH v4 " Vivek Gautam
@ 2013-01-29  5:34     ` Vivek Gautam
  2013-01-30  5:56     ` Kukjin Kim
  1 sibling, 0 replies; 14+ messages in thread
From: Vivek Gautam @ 2013-01-29  5:34 UTC (permalink / raw)
  To: linux-usb
  Cc: Doug Anderson, kgene.kim, p.paneri, gregkh, devicetree-discuss,
	linux-kernel, balbi, tomasz.figa, linux-samsung-soc,
	sylvester.nawrocki, Vivek Gautam

CC: Doug Anderson


On Mon, Jan 28, 2013 at 3:54 PM, Vivek Gautam <gautam.vivek@samsung.com> wrote:
> Moving register and structure definitions to header file,
> and keeping the generic functions to be used across
> multiple PHYs in common file "samsung-usbphy.c".
> Also renaming the usb 2.0 phy driver to "samsung-usb2.c"
>
> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
> ---
>
> Changes from v3:
>  - Using separate config SAMSUNG_USB2PHY dependent on
>    SAMSUNG_USBPHY for samsung-usb2 type PHY controller.
>
>  drivers/usb/phy/Kconfig          |   14 +-
>  drivers/usb/phy/Makefile         |    1 +
>  drivers/usb/phy/samsung-usb2.c   |  511 +++++++++++++++++++++++++++
>  drivers/usb/phy/samsung-usbphy.c |  714 +-------------------------------------
>  drivers/usb/phy/samsung-usbphy.h |  247 +++++++++++++
>  5 files changed, 778 insertions(+), 709 deletions(-)
>  create mode 100644 drivers/usb/phy/samsung-usb2.c
>  create mode 100644 drivers/usb/phy/samsung-usbphy.h
>
> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
> index fae4d08..cc0d230 100644
> --- a/drivers/usb/phy/Kconfig
> +++ b/drivers/usb/phy/Kconfig
> @@ -48,8 +48,18 @@ config USB_RCAR_PHY
>
>  config SAMSUNG_USBPHY
>         bool "Samsung USB PHY controller Driver"
> -       depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS
>         select USB_OTG_UTILS
>         help
> -         Enable this to support Samsung USB phy controller for samsung
> +         Enable this to support Samsung USB phy controllers for Samsung
>           SoCs.
> +
> +if SAMSUNG_USBPHY
> +
> +config SAMSUNG_USB2PHY
> +       bool "Samsung USB 2.0 PHY controller Driver"
> +       depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS
> +       help
> +         Enable this to support Samsung USB 2.0 (High Speed) phy controller
> +         for Samsung SoCs.
> +
> +endif
> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
> index ec304f6..7ba9862 100644
> --- a/drivers/usb/phy/Makefile
> +++ b/drivers/usb/phy/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_MV_U3D_PHY)              += mv_u3d_phy.o
>  obj-$(CONFIG_USB_EHCI_TEGRA)   += tegra_usb_phy.o
>  obj-$(CONFIG_USB_RCAR_PHY)             += rcar-phy.o
>  obj-$(CONFIG_SAMSUNG_USBPHY)           += samsung-usbphy.o
> +obj-$(CONFIG_SAMSUNG_USB2PHY)          += samsung-usb2.o
> diff --git a/drivers/usb/phy/samsung-usb2.c b/drivers/usb/phy/samsung-usb2.c
> new file mode 100644
> index 0000000..9a9d1d0
> --- /dev/null
> +++ b/drivers/usb/phy/samsung-usb2.c
> @@ -0,0 +1,511 @@
> +/* linux/drivers/usb/phy/samsung-usb2.c
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + *              http://www.samsung.com
> + *
> + * Author: Praveen Paneri <p.paneri@samsung.com>
> + *
> + * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
> + * OHCI-EXYNOS controllers.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/usb/otg.h>
> +#include <linux/usb/samsung_usb_phy.h>
> +#include <linux/platform_data/samsung-usbphy.h>
> +
> +#include "samsung-usbphy.h"
> +
> +int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
> +{
> +       if (!otg)
> +               return -ENODEV;
> +
> +       if (!otg->host)
> +               otg->host = host;
> +
> +       return 0;
> +}
> +
> +static bool exynos5_phyhost_is_on(void *regs)
> +{
> +       u32 reg;
> +
> +       reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
> +
> +       return !(reg & HOST_CTRL0_SIDDQ);
> +}
> +
> +static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
> +{
> +       void __iomem *regs = sphy->regs;
> +       u32 phyclk = sphy->ref_clk_freq;
> +       u32 phyhost;
> +       u32 phyotg;
> +       u32 phyhsic;
> +       u32 ehcictrl;
> +       u32 ohcictrl;
> +
> +       /*
> +        * phy_usage helps in keeping usage count for phy
> +        * so that the first consumer enabling the phy is also
> +        * the last consumer to disable it.
> +        */
> +
> +       atomic_inc(&sphy->phy_usage);
> +
> +       if (exynos5_phyhost_is_on(regs)) {
> +               dev_info(sphy->dev, "Already power on PHY\n");
> +               return;
> +       }
> +
> +       /* Host configuration */
> +       phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
> +
> +       /* phy reference clock configuration */
> +       phyhost &= ~HOST_CTRL0_FSEL_MASK;
> +       phyhost |= HOST_CTRL0_FSEL(phyclk);
> +
> +       /* host phy reset */
> +       phyhost &= ~(HOST_CTRL0_PHYSWRST |
> +                       HOST_CTRL0_PHYSWRSTALL |
> +                       HOST_CTRL0_SIDDQ |
> +                       /* Enable normal mode of operation */
> +                       HOST_CTRL0_FORCESUSPEND |
> +                       HOST_CTRL0_FORCESLEEP);
> +
> +       /* Link reset */
> +       phyhost |= (HOST_CTRL0_LINKSWRST |
> +                       HOST_CTRL0_UTMISWRST |
> +                       /* COMMON Block configuration during suspend */
> +                       HOST_CTRL0_COMMONON_N);
> +       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
> +       udelay(10);
> +       phyhost &= ~(HOST_CTRL0_LINKSWRST |
> +                       HOST_CTRL0_UTMISWRST);
> +       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
> +
> +       /* OTG configuration */
> +       phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
> +
> +       /* phy reference clock configuration */
> +       phyotg &= ~OTG_SYS_FSEL_MASK;
> +       phyotg |= OTG_SYS_FSEL(phyclk);
> +
> +       /* Enable normal mode of operation */
> +       phyotg &= ~(OTG_SYS_FORCESUSPEND |
> +                       OTG_SYS_SIDDQ_UOTG |
> +                       OTG_SYS_FORCESLEEP |
> +                       OTG_SYS_REFCLKSEL_MASK |
> +                       /* COMMON Block configuration during suspend */
> +                       OTG_SYS_COMMON_ON);
> +
> +       /* OTG phy & link reset */
> +       phyotg |= (OTG_SYS_PHY0_SWRST |
> +                       OTG_SYS_LINKSWRST_UOTG |
> +                       OTG_SYS_PHYLINK_SWRESET |
> +                       OTG_SYS_OTGDISABLE |
> +                       /* Set phy refclk */
> +                       OTG_SYS_REFCLKSEL_CLKCORE);
> +
> +       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
> +       udelay(10);
> +       phyotg &= ~(OTG_SYS_PHY0_SWRST |
> +                       OTG_SYS_LINKSWRST_UOTG |
> +                       OTG_SYS_PHYLINK_SWRESET);
> +       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
> +
> +       /* HSIC phy configuration */
> +       phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
> +                       HSIC_CTRL_REFCLKSEL |
> +                       HSIC_CTRL_PHYSWRST);
> +       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
> +       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
> +       udelay(10);
> +       phyhsic &= ~HSIC_CTRL_PHYSWRST;
> +       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
> +       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
> +
> +       udelay(80);
> +
> +       /* enable EHCI DMA burst */
> +       ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
> +       ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
> +                               HOST_EHCICTRL_ENAINCR4 |
> +                               HOST_EHCICTRL_ENAINCR8 |
> +                               HOST_EHCICTRL_ENAINCR16);
> +       writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
> +
> +       /* set ohci_suspend_on_n */
> +       ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
> +       ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
> +       writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
> +}
> +
> +static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
> +{
> +       void __iomem *regs = sphy->regs;
> +       u32 phypwr;
> +       u32 phyclk;
> +       u32 rstcon;
> +
> +       /* set clock frequency for PLL */
> +       phyclk = sphy->ref_clk_freq;
> +       phypwr = readl(regs + SAMSUNG_PHYPWR);
> +       rstcon = readl(regs + SAMSUNG_RSTCON);
> +
> +       switch (sphy->drv_data->cpu_type) {
> +       case TYPE_S3C64XX:
> +               phyclk &= ~PHYCLK_COMMON_ON_N;
> +               phypwr &= ~PHYPWR_NORMAL_MASK;
> +               rstcon |= RSTCON_SWRST;
> +               break;
> +       case TYPE_EXYNOS4210:
> +               phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
> +               rstcon |= RSTCON_SWRST;
> +       default:
> +               break;
> +       }
> +
> +       writel(phyclk, regs + SAMSUNG_PHYCLK);
> +       /* Configure PHY0 for normal operation*/
> +       writel(phypwr, regs + SAMSUNG_PHYPWR);
> +       /* reset all ports of PHY and Link */
> +       writel(rstcon, regs + SAMSUNG_RSTCON);
> +       udelay(10);
> +       rstcon &= ~RSTCON_SWRST;
> +       writel(rstcon, regs + SAMSUNG_RSTCON);
> +}
> +
> +static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
> +{
> +       void __iomem *regs = sphy->regs;
> +       u32 phyhost;
> +       u32 phyotg;
> +       u32 phyhsic;
> +
> +       if (atomic_dec_return(&sphy->phy_usage) > 0) {
> +               dev_info(sphy->dev, "still being used\n");
> +               return;
> +       }
> +
> +       phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
> +                       HSIC_CTRL_REFCLKSEL |
> +                       HSIC_CTRL_SIDDQ |
> +                       HSIC_CTRL_FORCESLEEP |
> +                       HSIC_CTRL_FORCESUSPEND);
> +       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
> +       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
> +
> +       phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
> +       phyhost |= (HOST_CTRL0_SIDDQ |
> +                       HOST_CTRL0_FORCESUSPEND |
> +                       HOST_CTRL0_FORCESLEEP |
> +                       HOST_CTRL0_PHYSWRST |
> +                       HOST_CTRL0_PHYSWRSTALL);
> +       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
> +
> +       phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
> +       phyotg |= (OTG_SYS_FORCESUSPEND |
> +                       OTG_SYS_SIDDQ_UOTG |
> +                       OTG_SYS_FORCESLEEP);
> +       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
> +}
> +
> +static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
> +{
> +       void __iomem *regs = sphy->regs;
> +       u32 phypwr;
> +
> +       phypwr = readl(regs + SAMSUNG_PHYPWR);
> +
> +       switch (sphy->drv_data->cpu_type) {
> +       case TYPE_S3C64XX:
> +               phypwr |= PHYPWR_NORMAL_MASK;
> +               break;
> +       case TYPE_EXYNOS4210:
> +               phypwr |= PHYPWR_NORMAL_MASK_PHY0;
> +       default:
> +               break;
> +       }
> +
> +       /* Disable analog and otg block power */
> +       writel(phypwr, regs + SAMSUNG_PHYPWR);
> +}
> +
> +/*
> + * The function passed to the usb driver for phy initialization
> + */
> +static int samsung_usbphy_init(struct usb_phy *phy)
> +{
> +       struct samsung_usbphy *sphy;
> +       struct usb_bus *host = NULL;
> +       unsigned long flags;
> +       int ret = 0;
> +
> +       sphy = phy_to_sphy(phy);
> +
> +       host = phy->otg->host;
> +
> +       /* Enable the phy clock */
> +       ret = clk_prepare_enable(sphy->clk);
> +       if (ret) {
> +               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
> +               return ret;
> +       }
> +
> +       spin_lock_irqsave(&sphy->lock, flags);
> +
> +       if (host) {
> +               /* setting default phy-type for USB 2.0 */
> +               if (!strstr(dev_name(host->controller), "ehci") ||
> +                               !strstr(dev_name(host->controller), "ohci"))
> +                       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
> +       } else {
> +               samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
> +       }
> +
> +       /* Disable phy isolation */
> +       if (sphy->plat && sphy->plat->pmu_isolation)
> +               sphy->plat->pmu_isolation(false);
> +       else
> +               samsung_usbphy_set_isolation(sphy, false);
> +
> +       /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
> +       samsung_usbphy_cfg_sel(sphy);
> +
> +       /* Initialize usb phy registers */
> +       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> +               samsung_exynos5_usbphy_enable(sphy);
> +       else
> +               samsung_usbphy_enable(sphy);
> +
> +       spin_unlock_irqrestore(&sphy->lock, flags);
> +
> +       /* Disable the phy clock */
> +       clk_disable_unprepare(sphy->clk);
> +
> +       return ret;
> +}
> +
> +/*
> + * The function passed to the usb driver for phy shutdown
> + */
> +static void samsung_usbphy_shutdown(struct usb_phy *phy)
> +{
> +       struct samsung_usbphy *sphy;
> +       struct usb_bus *host = NULL;
> +       unsigned long flags;
> +
> +       sphy = phy_to_sphy(phy);
> +
> +       host = phy->otg->host;
> +
> +       if (clk_prepare_enable(sphy->clk)) {
> +               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
> +               return;
> +       }
> +
> +       spin_lock_irqsave(&sphy->lock, flags);
> +
> +       if (host) {
> +               /* setting default phy-type for USB 2.0 */
> +               if (!strstr(dev_name(host->controller), "ehci") ||
> +                               !strstr(dev_name(host->controller), "ohci"))
> +                       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
> +       } else {
> +               samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
> +       }
> +
> +       /* De-initialize usb phy registers */
> +       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> +               samsung_exynos5_usbphy_disable(sphy);
> +       else
> +               samsung_usbphy_disable(sphy);
> +
> +       /* Enable phy isolation */
> +       if (sphy->plat && sphy->plat->pmu_isolation)
> +               sphy->plat->pmu_isolation(true);
> +       else
> +               samsung_usbphy_set_isolation(sphy, true);
> +
> +       spin_unlock_irqrestore(&sphy->lock, flags);
> +
> +       clk_disable_unprepare(sphy->clk);
> +}
> +
> +static int samsung_usbphy_probe(struct platform_device *pdev)
> +{
> +       struct samsung_usbphy *sphy;
> +       struct usb_otg *otg;
> +       struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
> +       const struct samsung_usbphy_drvdata *drv_data;
> +       struct device *dev = &pdev->dev;
> +       struct resource *phy_mem;
> +       void __iomem    *phy_base;
> +       struct clk *clk;
> +       int ret;
> +
> +       phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!phy_mem) {
> +               dev_err(dev, "%s: missing mem resource\n", __func__);
> +               return -ENODEV;
> +       }
> +
> +       phy_base = devm_request_and_ioremap(dev, phy_mem);
> +       if (!phy_base) {
> +               dev_err(dev, "%s: register mapping failed\n", __func__);
> +               return -ENXIO;
> +       }
> +
> +       sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
> +       if (!sphy)
> +               return -ENOMEM;
> +
> +       otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
> +       if (!otg)
> +               return -ENOMEM;
> +
> +       drv_data = samsung_usbphy_get_driver_data(pdev);
> +
> +       if (drv_data->cpu_type == TYPE_EXYNOS5250)
> +               clk = devm_clk_get(dev, "usbhost");
> +       else
> +               clk = devm_clk_get(dev, "otg");
> +
> +       if (IS_ERR(clk)) {
> +               dev_err(dev, "Failed to get otg clock\n");
> +               return PTR_ERR(clk);
> +       }
> +
> +       sphy->dev = dev;
> +
> +       if (dev->of_node) {
> +               ret = samsung_usbphy_parse_dt(sphy);
> +               if (ret < 0)
> +                       return ret;
> +       } else {
> +               if (!pdata) {
> +                       dev_err(dev, "no platform data specified\n");
> +                       return -EINVAL;
> +               }
> +       }
> +
> +       sphy->plat              = pdata;
> +       sphy->regs              = phy_base;
> +       sphy->clk               = clk;
> +       sphy->drv_data          = drv_data;
> +       sphy->phy.dev           = sphy->dev;
> +       sphy->phy.label         = "samsung-usbphy";
> +       sphy->phy.init          = samsung_usbphy_init;
> +       sphy->phy.shutdown      = samsung_usbphy_shutdown;
> +       sphy->ref_clk_freq      = samsung_usbphy_get_refclk_freq(sphy);
> +
> +       sphy->phy.otg           = otg;
> +       sphy->phy.otg->phy      = &sphy->phy;
> +       sphy->phy.otg->set_host = samsung_usbphy_set_host;
> +
> +       spin_lock_init(&sphy->lock);
> +
> +       platform_set_drvdata(pdev, sphy);
> +
> +       return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
> +}
> +
> +static int samsung_usbphy_remove(struct platform_device *pdev)
> +{
> +       struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
> +
> +       usb_remove_phy(&sphy->phy);
> +
> +       if (sphy->pmuregs)
> +               iounmap(sphy->pmuregs);
> +       if (sphy->sysreg)
> +               iounmap(sphy->sysreg);
> +
> +       return 0;
> +}
> +
> +static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
> +       .cpu_type               = TYPE_S3C64XX,
> +       .devphy_en_mask         = S3C64XX_USBPHY_ENABLE,
> +};
> +
> +static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
> +       .cpu_type               = TYPE_EXYNOS4210,
> +       .devphy_en_mask         = EXYNOS_USBPHY_ENABLE,
> +       .hostphy_en_mask        = EXYNOS_USBPHY_ENABLE,
> +};
> +
> +static struct samsung_usbphy_drvdata usbphy_exynos5 = {
> +       .cpu_type               = TYPE_EXYNOS5250,
> +       .hostphy_en_mask        = EXYNOS_USBPHY_ENABLE,
> +       .hostphy_reg_offset     = EXYNOS_USBHOST_PHY_CTRL_OFFSET,
> +};
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id samsung_usbphy_dt_match[] = {
> +       {
> +               .compatible = "samsung,s3c64xx-usbphy",
> +               .data = &usbphy_s3c64xx,
> +       }, {
> +               .compatible = "samsung,exynos4210-usbphy",
> +               .data = &usbphy_exynos4,
> +       }, {
> +               .compatible = "samsung,exynos5250-usbphy",
> +               .data = &usbphy_exynos5
> +       },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
> +#endif
> +
> +static struct platform_device_id samsung_usbphy_driver_ids[] = {
> +       {
> +               .name           = "s3c64xx-usbphy",
> +               .driver_data    = (unsigned long)&usbphy_s3c64xx,
> +       }, {
> +               .name           = "exynos4210-usbphy",
> +               .driver_data    = (unsigned long)&usbphy_exynos4,
> +       }, {
> +               .name           = "exynos5250-usbphy",
> +               .driver_data    = (unsigned long)&usbphy_exynos5,
> +       },
> +       {},
> +};
> +
> +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
> +
> +static struct platform_driver samsung_usbphy_driver = {
> +       .probe          = samsung_usbphy_probe,
> +       .remove         = samsung_usbphy_remove,
> +       .id_table       = samsung_usbphy_driver_ids,
> +       .driver         = {
> +               .name   = "samsung-usbphy",
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
> +       },
> +};
> +
> +module_platform_driver(samsung_usbphy_driver);
> +
> +MODULE_DESCRIPTION("Samsung USB phy controller");
> +MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:samsung-usbphy");
> diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c
> index 6ea5537..7782a43 100644
> --- a/drivers/usb/phy/samsung-usbphy.c
> +++ b/drivers/usb/phy/samsung-usbphy.c
> @@ -5,7 +5,7 @@
>   *
>   * Author: Praveen Paneri <p.paneri@samsung.com>
>   *
> - * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
> + * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
>   * OHCI-EXYNOS controllers.
>   *
>   * This program is free software; you can redistribute it and/or modify
> @@ -21,233 +21,16 @@
>  #include <linux/module.h>
>  #include <linux/platform_device.h>
>  #include <linux/clk.h>
> -#include <linux/delay.h>
>  #include <linux/device.h>
>  #include <linux/err.h>
>  #include <linux/io.h>
>  #include <linux/of.h>
>  #include <linux/of_address.h>
> -#include <linux/usb/otg.h>
>  #include <linux/usb/samsung_usb_phy.h>
> -#include <linux/platform_data/samsung-usbphy.h>
>
> -/* Register definitions */
> +#include "samsung-usbphy.h"
>
> -#define SAMSUNG_PHYPWR                         (0x00)
> -
> -#define PHYPWR_NORMAL_MASK                     (0x19 << 0)
> -#define PHYPWR_OTG_DISABLE                     (0x1 << 4)
> -#define PHYPWR_ANALOG_POWERDOWN                        (0x1 << 3)
> -#define PHYPWR_FORCE_SUSPEND                   (0x1 << 1)
> -/* For Exynos4 */
> -#define PHYPWR_NORMAL_MASK_PHY0                        (0x39 << 0)
> -#define PHYPWR_SLEEP_PHY0                      (0x1 << 5)
> -
> -#define SAMSUNG_PHYCLK                         (0x04)
> -
> -#define PHYCLK_MODE_USB11                      (0x1 << 6)
> -#define PHYCLK_EXT_OSC                         (0x1 << 5)
> -#define PHYCLK_COMMON_ON_N                     (0x1 << 4)
> -#define PHYCLK_ID_PULL                         (0x1 << 2)
> -#define PHYCLK_CLKSEL_MASK                     (0x3 << 0)
> -#define PHYCLK_CLKSEL_48M                      (0x0 << 0)
> -#define PHYCLK_CLKSEL_12M                      (0x2 << 0)
> -#define PHYCLK_CLKSEL_24M                      (0x3 << 0)
> -
> -#define SAMSUNG_RSTCON                         (0x08)
> -
> -#define RSTCON_PHYLINK_SWRST                   (0x1 << 2)
> -#define RSTCON_HLINK_SWRST                     (0x1 << 1)
> -#define RSTCON_SWRST                           (0x1 << 0)
> -
> -/* EXYNOS5 */
> -#define EXYNOS5_PHY_HOST_CTRL0                 (0x00)
> -
> -#define HOST_CTRL0_PHYSWRSTALL                 (0x1 << 31)
> -
> -#define HOST_CTRL0_REFCLKSEL_MASK              (0x3 << 19)
> -#define HOST_CTRL0_REFCLKSEL_XTAL              (0x0 << 19)
> -#define HOST_CTRL0_REFCLKSEL_EXTL              (0x1 << 19)
> -#define HOST_CTRL0_REFCLKSEL_CLKCORE           (0x2 << 19)
> -
> -#define HOST_CTRL0_FSEL_MASK                   (0x7 << 16)
> -#define HOST_CTRL0_FSEL(_x)                    ((_x) << 16)
> -
> -#define FSEL_CLKSEL_50M                                (0x7)
> -#define FSEL_CLKSEL_24M                                (0x5)
> -#define FSEL_CLKSEL_20M                                (0x4)
> -#define FSEL_CLKSEL_19200K                     (0x3)
> -#define FSEL_CLKSEL_12M                                (0x2)
> -#define FSEL_CLKSEL_10M                                (0x1)
> -#define FSEL_CLKSEL_9600K                      (0x0)
> -
> -#define HOST_CTRL0_TESTBURNIN                  (0x1 << 11)
> -#define HOST_CTRL0_RETENABLE                   (0x1 << 10)
> -#define HOST_CTRL0_COMMONON_N                  (0x1 << 9)
> -#define HOST_CTRL0_SIDDQ                       (0x1 << 6)
> -#define HOST_CTRL0_FORCESLEEP                  (0x1 << 5)
> -#define HOST_CTRL0_FORCESUSPEND                        (0x1 << 4)
> -#define HOST_CTRL0_WORDINTERFACE               (0x1 << 3)
> -#define HOST_CTRL0_UTMISWRST                   (0x1 << 2)
> -#define HOST_CTRL0_LINKSWRST                   (0x1 << 1)
> -#define HOST_CTRL0_PHYSWRST                    (0x1 << 0)
> -
> -#define EXYNOS5_PHY_HOST_TUNE0                 (0x04)
> -
> -#define EXYNOS5_PHY_HSIC_CTRL1                 (0x10)
> -
> -#define EXYNOS5_PHY_HSIC_TUNE1                 (0x14)
> -
> -#define EXYNOS5_PHY_HSIC_CTRL2                 (0x20)
> -
> -#define EXYNOS5_PHY_HSIC_TUNE2                 (0x24)
> -
> -#define HSIC_CTRL_REFCLKSEL_MASK               (0x3 << 23)
> -#define HSIC_CTRL_REFCLKSEL                    (0x2 << 23)
> -
> -#define HSIC_CTRL_REFCLKDIV_MASK               (0x7f << 16)
> -#define HSIC_CTRL_REFCLKDIV(_x)                        ((_x) << 16)
> -#define HSIC_CTRL_REFCLKDIV_12                 (0x24 << 16)
> -#define HSIC_CTRL_REFCLKDIV_15                 (0x1c << 16)
> -#define HSIC_CTRL_REFCLKDIV_16                 (0x1a << 16)
> -#define HSIC_CTRL_REFCLKDIV_19_2               (0x15 << 16)
> -#define HSIC_CTRL_REFCLKDIV_20                 (0x14 << 16)
> -
> -#define HSIC_CTRL_SIDDQ                                (0x1 << 6)
> -#define HSIC_CTRL_FORCESLEEP                   (0x1 << 5)
> -#define HSIC_CTRL_FORCESUSPEND                 (0x1 << 4)
> -#define HSIC_CTRL_WORDINTERFACE                        (0x1 << 3)
> -#define HSIC_CTRL_UTMISWRST                    (0x1 << 2)
> -#define HSIC_CTRL_PHYSWRST                     (0x1 << 0)
> -
> -#define EXYNOS5_PHY_HOST_EHCICTRL              (0x30)
> -
> -#define HOST_EHCICTRL_ENAINCRXALIGN            (0x1 << 29)
> -#define HOST_EHCICTRL_ENAINCR4                 (0x1 << 28)
> -#define HOST_EHCICTRL_ENAINCR8                 (0x1 << 27)
> -#define HOST_EHCICTRL_ENAINCR16                        (0x1 << 26)
> -
> -#define EXYNOS5_PHY_HOST_OHCICTRL              (0x34)
> -
> -#define HOST_OHCICTRL_SUSPLGCY                 (0x1 << 3)
> -#define HOST_OHCICTRL_APPSTARTCLK              (0x1 << 2)
> -#define HOST_OHCICTRL_CNTSEL                   (0x1 << 1)
> -#define HOST_OHCICTRL_CLKCKTRST                        (0x1 << 0)
> -
> -#define EXYNOS5_PHY_OTG_SYS                    (0x38)
> -
> -#define OTG_SYS_PHYLINK_SWRESET                        (0x1 << 14)
> -#define OTG_SYS_LINKSWRST_UOTG                 (0x1 << 13)
> -#define OTG_SYS_PHY0_SWRST                     (0x1 << 12)
> -
> -#define OTG_SYS_REFCLKSEL_MASK                 (0x3 << 9)
> -#define OTG_SYS_REFCLKSEL_XTAL                 (0x0 << 9)
> -#define OTG_SYS_REFCLKSEL_EXTL                 (0x1 << 9)
> -#define OTG_SYS_REFCLKSEL_CLKCORE              (0x2 << 9)
> -
> -#define OTG_SYS_IDPULLUP_UOTG                  (0x1 << 8)
> -#define OTG_SYS_COMMON_ON                      (0x1 << 7)
> -
> -#define OTG_SYS_FSEL_MASK                      (0x7 << 4)
> -#define OTG_SYS_FSEL(_x)                       ((_x) << 4)
> -
> -#define OTG_SYS_FORCESLEEP                     (0x1 << 3)
> -#define OTG_SYS_OTGDISABLE                     (0x1 << 2)
> -#define OTG_SYS_SIDDQ_UOTG                     (0x1 << 1)
> -#define OTG_SYS_FORCESUSPEND                   (0x1 << 0)
> -
> -#define EXYNOS5_PHY_OTG_TUNE                   (0x40)
> -
> -#ifndef MHZ
> -#define MHZ (1000*1000)
> -#endif
> -
> -#ifndef KHZ
> -#define KHZ (1000)
> -#endif
> -
> -#define EXYNOS_USBHOST_PHY_CTRL_OFFSET         (0x4)
> -#define S3C64XX_USBPHY_ENABLE                  (0x1 << 16)
> -#define EXYNOS_USBPHY_ENABLE                   (0x1 << 0)
> -#define EXYNOS_USB20PHY_CFG_HOST_LINK          (0x1 << 0)
> -
> -enum samsung_cpu_type {
> -       TYPE_S3C64XX,
> -       TYPE_EXYNOS4210,
> -       TYPE_EXYNOS5250,
> -};
> -
> -/*
> - * struct samsung_usbphy_drvdata - driver data for various SoC variants
> - * @cpu_type: machine identifier
> - * @devphy_en_mask: device phy enable mask for PHY CONTROL register
> - * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
> - * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
> - *                    mapped address of system controller.
> - * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
> - *                    mapped address of system controller.
> - *
> - *     Here we have a separate mask for device type phy.
> - *     Having different masks for host and device type phy helps
> - *     in setting independent masks in case of SoCs like S5PV210,
> - *     in which PHY0 and PHY1 enable bits belong to same register
> - *     placed at position 0 and 1 respectively.
> - *     Although for newer SoCs like exynos these bits belong to
> - *     different registers altogether placed at position 0.
> - */
> -struct samsung_usbphy_drvdata {
> -       int cpu_type;
> -       int devphy_en_mask;
> -       int hostphy_en_mask;
> -       u32 devphy_reg_offset;
> -       u32 hostphy_reg_offset;
> -};
> -
> -/*
> - * struct samsung_usbphy - transceiver driver state
> - * @phy: transceiver structure
> - * @plat: platform data
> - * @dev: The parent device supplied to the probe function
> - * @clk: usb phy clock
> - * @regs: usb phy controller registers memory base
> - * @pmuregs: USB device PHY_CONTROL register memory base
> - * @sysreg: USB2.0 PHY_CFG register memory base
> - * @ref_clk_freq: reference clock frequency selection
> - * @drv_data: driver data available for different SoCs
> - * @phy_type: Samsung SoCs specific phy types: #HOST
> - *                                             #DEVICE
> - * @phy_usage: usage count for phy
> - * @lock: lock for phy operations
> - */
> -struct samsung_usbphy {
> -       struct usb_phy  phy;
> -       struct samsung_usbphy_data *plat;
> -       struct device   *dev;
> -       struct clk      *clk;
> -       void __iomem    *regs;
> -       void __iomem    *pmuregs;
> -       void __iomem    *sysreg;
> -       int             ref_clk_freq;
> -       const struct samsung_usbphy_drvdata *drv_data;
> -       enum samsung_usb_phy_type phy_type;
> -       atomic_t        phy_usage;
> -       spinlock_t      lock;
> -};
> -
> -#define phy_to_sphy(x)         container_of((x), struct samsung_usbphy, phy)
> -
> -int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
> -{
> -       if (!otg)
> -               return -ENODEV;
> -
> -       if (!otg->host)
> -               otg->host = host;
> -
> -       return 0;
> -}
> -
> -static int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
> +int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy)
>  {
>         struct device_node *usbphy_sys;
>
> @@ -288,7 +71,7 @@ err0:
>   * Here 'on = true' would mean USB PHY block is isolated, hence
>   * de-activated and vice-versa.
>   */
> -static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
> +void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
>  {
>         void __iomem *reg = NULL;
>         u32 reg_val;
> @@ -340,7 +123,7 @@ static void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on)
>  /*
>   * Configure the mode of working of usb-phy here: HOST/DEVICE.
>   */
> -static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
> +void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
>  {
>         u32 reg;
>
> @@ -364,7 +147,7 @@ static void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy)
>   * This make sure that correct PHY type is selected before
>   * any operation on PHY.
>   */
> -static int samsung_usbphy_set_type(struct usb_phy *phy,
> +int samsung_usbphy_set_type(struct usb_phy *phy,
>                                 enum samsung_usb_phy_type phy_type)
>  {
>         struct samsung_usbphy *sphy = phy_to_sphy(phy);
> @@ -377,7 +160,7 @@ static int samsung_usbphy_set_type(struct usb_phy *phy,
>  /*
>   * Returns reference clock frequency selection value
>   */
> -static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
> +int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
>  {
>         struct clk *ref_clk;
>         int refclk_freq = 0;
> @@ -445,486 +228,3 @@ static int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy)
>
>         return refclk_freq;
>  }
> -
> -static bool exynos5_phyhost_is_on(void *regs)
> -{
> -       u32 reg;
> -
> -       reg = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
> -
> -       return !(reg & HOST_CTRL0_SIDDQ);
> -}
> -
> -static void samsung_exynos5_usbphy_enable(struct samsung_usbphy *sphy)
> -{
> -       void __iomem *regs = sphy->regs;
> -       u32 phyclk = sphy->ref_clk_freq;
> -       u32 phyhost;
> -       u32 phyotg;
> -       u32 phyhsic;
> -       u32 ehcictrl;
> -       u32 ohcictrl;
> -
> -       /*
> -        * phy_usage helps in keeping usage count for phy
> -        * so that the first consumer enabling the phy is also
> -        * the last consumer to disable it.
> -        */
> -
> -       atomic_inc(&sphy->phy_usage);
> -
> -       if (exynos5_phyhost_is_on(regs)) {
> -               dev_info(sphy->dev, "Already power on PHY\n");
> -               return;
> -       }
> -
> -       /* Host configuration */
> -       phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
> -
> -       /* phy reference clock configuration */
> -       phyhost &= ~HOST_CTRL0_FSEL_MASK;
> -       phyhost |= HOST_CTRL0_FSEL(phyclk);
> -
> -       /* host phy reset */
> -       phyhost &= ~(HOST_CTRL0_PHYSWRST |
> -                       HOST_CTRL0_PHYSWRSTALL |
> -                       HOST_CTRL0_SIDDQ |
> -                       /* Enable normal mode of operation */
> -                       HOST_CTRL0_FORCESUSPEND |
> -                       HOST_CTRL0_FORCESLEEP);
> -
> -       /* Link reset */
> -       phyhost |= (HOST_CTRL0_LINKSWRST |
> -                       HOST_CTRL0_UTMISWRST |
> -                       /* COMMON Block configuration during suspend */
> -                       HOST_CTRL0_COMMONON_N);
> -       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
> -       udelay(10);
> -       phyhost &= ~(HOST_CTRL0_LINKSWRST |
> -                       HOST_CTRL0_UTMISWRST);
> -       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
> -
> -       /* OTG configuration */
> -       phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
> -
> -       /* phy reference clock configuration */
> -       phyotg &= ~OTG_SYS_FSEL_MASK;
> -       phyotg |= OTG_SYS_FSEL(phyclk);
> -
> -       /* Enable normal mode of operation */
> -       phyotg &= ~(OTG_SYS_FORCESUSPEND |
> -                       OTG_SYS_SIDDQ_UOTG |
> -                       OTG_SYS_FORCESLEEP |
> -                       OTG_SYS_REFCLKSEL_MASK |
> -                       /* COMMON Block configuration during suspend */
> -                       OTG_SYS_COMMON_ON);
> -
> -       /* OTG phy & link reset */
> -       phyotg |= (OTG_SYS_PHY0_SWRST |
> -                       OTG_SYS_LINKSWRST_UOTG |
> -                       OTG_SYS_PHYLINK_SWRESET |
> -                       OTG_SYS_OTGDISABLE |
> -                       /* Set phy refclk */
> -                       OTG_SYS_REFCLKSEL_CLKCORE);
> -
> -       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
> -       udelay(10);
> -       phyotg &= ~(OTG_SYS_PHY0_SWRST |
> -                       OTG_SYS_LINKSWRST_UOTG |
> -                       OTG_SYS_PHYLINK_SWRESET);
> -       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
> -
> -       /* HSIC phy configuration */
> -       phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
> -                       HSIC_CTRL_REFCLKSEL |
> -                       HSIC_CTRL_PHYSWRST);
> -       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
> -       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
> -       udelay(10);
> -       phyhsic &= ~HSIC_CTRL_PHYSWRST;
> -       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
> -       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
> -
> -       udelay(80);
> -
> -       /* enable EHCI DMA burst */
> -       ehcictrl = readl(regs + EXYNOS5_PHY_HOST_EHCICTRL);
> -       ehcictrl |= (HOST_EHCICTRL_ENAINCRXALIGN |
> -                               HOST_EHCICTRL_ENAINCR4 |
> -                               HOST_EHCICTRL_ENAINCR8 |
> -                               HOST_EHCICTRL_ENAINCR16);
> -       writel(ehcictrl, regs + EXYNOS5_PHY_HOST_EHCICTRL);
> -
> -       /* set ohci_suspend_on_n */
> -       ohcictrl = readl(regs + EXYNOS5_PHY_HOST_OHCICTRL);
> -       ohcictrl |= HOST_OHCICTRL_SUSPLGCY;
> -       writel(ohcictrl, regs + EXYNOS5_PHY_HOST_OHCICTRL);
> -}
> -
> -static void samsung_usbphy_enable(struct samsung_usbphy *sphy)
> -{
> -       void __iomem *regs = sphy->regs;
> -       u32 phypwr;
> -       u32 phyclk;
> -       u32 rstcon;
> -
> -       /* set clock frequency for PLL */
> -       phyclk = sphy->ref_clk_freq;
> -       phypwr = readl(regs + SAMSUNG_PHYPWR);
> -       rstcon = readl(regs + SAMSUNG_RSTCON);
> -
> -       switch (sphy->drv_data->cpu_type) {
> -       case TYPE_S3C64XX:
> -               phyclk &= ~PHYCLK_COMMON_ON_N;
> -               phypwr &= ~PHYPWR_NORMAL_MASK;
> -               rstcon |= RSTCON_SWRST;
> -               break;
> -       case TYPE_EXYNOS4210:
> -               phypwr &= ~PHYPWR_NORMAL_MASK_PHY0;
> -               rstcon |= RSTCON_SWRST;
> -       default:
> -               break;
> -       }
> -
> -       writel(phyclk, regs + SAMSUNG_PHYCLK);
> -       /* Configure PHY0 for normal operation*/
> -       writel(phypwr, regs + SAMSUNG_PHYPWR);
> -       /* reset all ports of PHY and Link */
> -       writel(rstcon, regs + SAMSUNG_RSTCON);
> -       udelay(10);
> -       rstcon &= ~RSTCON_SWRST;
> -       writel(rstcon, regs + SAMSUNG_RSTCON);
> -}
> -
> -static void samsung_exynos5_usbphy_disable(struct samsung_usbphy *sphy)
> -{
> -       void __iomem *regs = sphy->regs;
> -       u32 phyhost;
> -       u32 phyotg;
> -       u32 phyhsic;
> -
> -       if (atomic_dec_return(&sphy->phy_usage) > 0) {
> -               dev_info(sphy->dev, "still being used\n");
> -               return;
> -       }
> -
> -       phyhsic = (HSIC_CTRL_REFCLKDIV_12 |
> -                       HSIC_CTRL_REFCLKSEL |
> -                       HSIC_CTRL_SIDDQ |
> -                       HSIC_CTRL_FORCESLEEP |
> -                       HSIC_CTRL_FORCESUSPEND);
> -       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL1);
> -       writel(phyhsic, regs + EXYNOS5_PHY_HSIC_CTRL2);
> -
> -       phyhost = readl(regs + EXYNOS5_PHY_HOST_CTRL0);
> -       phyhost |= (HOST_CTRL0_SIDDQ |
> -                       HOST_CTRL0_FORCESUSPEND |
> -                       HOST_CTRL0_FORCESLEEP |
> -                       HOST_CTRL0_PHYSWRST |
> -                       HOST_CTRL0_PHYSWRSTALL);
> -       writel(phyhost, regs + EXYNOS5_PHY_HOST_CTRL0);
> -
> -       phyotg = readl(regs + EXYNOS5_PHY_OTG_SYS);
> -       phyotg |= (OTG_SYS_FORCESUSPEND |
> -                       OTG_SYS_SIDDQ_UOTG |
> -                       OTG_SYS_FORCESLEEP);
> -       writel(phyotg, regs + EXYNOS5_PHY_OTG_SYS);
> -}
> -
> -static void samsung_usbphy_disable(struct samsung_usbphy *sphy)
> -{
> -       void __iomem *regs = sphy->regs;
> -       u32 phypwr;
> -
> -       phypwr = readl(regs + SAMSUNG_PHYPWR);
> -
> -       switch (sphy->drv_data->cpu_type) {
> -       case TYPE_S3C64XX:
> -               phypwr |= PHYPWR_NORMAL_MASK;
> -               break;
> -       case TYPE_EXYNOS4210:
> -               phypwr |= PHYPWR_NORMAL_MASK_PHY0;
> -       default:
> -               break;
> -       }
> -
> -       /* Disable analog and otg block power */
> -       writel(phypwr, regs + SAMSUNG_PHYPWR);
> -}
> -
> -/*
> - * The function passed to the usb driver for phy initialization
> - */
> -static int samsung_usbphy_init(struct usb_phy *phy)
> -{
> -       struct samsung_usbphy *sphy;
> -       struct usb_bus *host = NULL;
> -       unsigned long flags;
> -       int ret = 0;
> -
> -       sphy = phy_to_sphy(phy);
> -
> -       host = phy->otg->host;
> -
> -       /* Enable the phy clock */
> -       ret = clk_prepare_enable(sphy->clk);
> -       if (ret) {
> -               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
> -               return ret;
> -       }
> -
> -       spin_lock_irqsave(&sphy->lock, flags);
> -
> -       if (host) {
> -               /* setting default phy-type for USB 2.0 */
> -               if (!strstr(dev_name(host->controller), "ehci") ||
> -                               !strstr(dev_name(host->controller), "ohci"))
> -                       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
> -       } else {
> -               samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
> -       }
> -
> -       /* Disable phy isolation */
> -       if (sphy->plat && sphy->plat->pmu_isolation)
> -               sphy->plat->pmu_isolation(false);
> -       else
> -               samsung_usbphy_set_isolation(sphy, false);
> -
> -       /* Selecting Host/OTG mode; After reset USB2.0PHY_CFG: HOST */
> -       samsung_usbphy_cfg_sel(sphy);
> -
> -       /* Initialize usb phy registers */
> -       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> -               samsung_exynos5_usbphy_enable(sphy);
> -       else
> -               samsung_usbphy_enable(sphy);
> -
> -       spin_unlock_irqrestore(&sphy->lock, flags);
> -
> -       /* Disable the phy clock */
> -       clk_disable_unprepare(sphy->clk);
> -
> -       return ret;
> -}
> -
> -/*
> - * The function passed to the usb driver for phy shutdown
> - */
> -static void samsung_usbphy_shutdown(struct usb_phy *phy)
> -{
> -       struct samsung_usbphy *sphy;
> -       struct usb_bus *host = NULL;
> -       unsigned long flags;
> -
> -       sphy = phy_to_sphy(phy);
> -
> -       host = phy->otg->host;
> -
> -       if (clk_prepare_enable(sphy->clk)) {
> -               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
> -               return;
> -       }
> -
> -       spin_lock_irqsave(&sphy->lock, flags);
> -
> -       if (host) {
> -               /* setting default phy-type for USB 2.0 */
> -               if (!strstr(dev_name(host->controller), "ehci") ||
> -                               !strstr(dev_name(host->controller), "ohci"))
> -                       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_HOST);
> -       } else {
> -               samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
> -       }
> -
> -       /* De-initialize usb phy registers */
> -       if (sphy->drv_data->cpu_type == TYPE_EXYNOS5250)
> -               samsung_exynos5_usbphy_disable(sphy);
> -       else
> -               samsung_usbphy_disable(sphy);
> -
> -       /* Enable phy isolation */
> -       if (sphy->plat && sphy->plat->pmu_isolation)
> -               sphy->plat->pmu_isolation(true);
> -       else
> -               samsung_usbphy_set_isolation(sphy, true);
> -
> -       spin_unlock_irqrestore(&sphy->lock, flags);
> -
> -       clk_disable_unprepare(sphy->clk);
> -}
> -
> -static const struct of_device_id samsung_usbphy_dt_match[];
> -
> -static inline const struct samsung_usbphy_drvdata
> -*samsung_usbphy_get_driver_data(struct platform_device *pdev)
> -{
> -       if (pdev->dev.of_node) {
> -               const struct of_device_id *match;
> -               match = of_match_node(samsung_usbphy_dt_match,
> -                                                       pdev->dev.of_node);
> -               return match->data;
> -       }
> -
> -       return (struct samsung_usbphy_drvdata *)
> -                               platform_get_device_id(pdev)->driver_data;
> -}
> -
> -static int samsung_usbphy_probe(struct platform_device *pdev)
> -{
> -       struct samsung_usbphy *sphy;
> -       struct usb_otg *otg;
> -       struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
> -       const struct samsung_usbphy_drvdata *drv_data;
> -       struct device *dev = &pdev->dev;
> -       struct resource *phy_mem;
> -       void __iomem    *phy_base;
> -       struct clk *clk;
> -       int ret;
> -
> -       phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> -       if (!phy_mem) {
> -               dev_err(dev, "%s: missing mem resource\n", __func__);
> -               return -ENODEV;
> -       }
> -
> -       phy_base = devm_request_and_ioremap(dev, phy_mem);
> -       if (!phy_base) {
> -               dev_err(dev, "%s: register mapping failed\n", __func__);
> -               return -ENXIO;
> -       }
> -
> -       sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
> -       if (!sphy)
> -               return -ENOMEM;
> -
> -       otg = devm_kzalloc(dev, sizeof(*otg), GFP_KERNEL);
> -       if (!otg)
> -               return -ENOMEM;
> -
> -       drv_data = samsung_usbphy_get_driver_data(pdev);
> -
> -       if (drv_data->cpu_type == TYPE_EXYNOS5250)
> -               clk = devm_clk_get(dev, "usbhost");
> -       else
> -               clk = devm_clk_get(dev, "otg");
> -
> -       if (IS_ERR(clk)) {
> -               dev_err(dev, "Failed to get otg clock\n");
> -               return PTR_ERR(clk);
> -       }
> -
> -       sphy->dev = dev;
> -
> -       if (dev->of_node) {
> -               ret = samsung_usbphy_parse_dt(sphy);
> -               if (ret < 0)
> -                       return ret;
> -       } else {
> -               if (!pdata) {
> -                       dev_err(dev, "no platform data specified\n");
> -                       return -EINVAL;
> -               }
> -       }
> -
> -       sphy->plat              = pdata;
> -       sphy->regs              = phy_base;
> -       sphy->clk               = clk;
> -       sphy->drv_data          = drv_data;
> -       sphy->phy.dev           = sphy->dev;
> -       sphy->phy.label         = "samsung-usbphy";
> -       sphy->phy.init          = samsung_usbphy_init;
> -       sphy->phy.shutdown      = samsung_usbphy_shutdown;
> -       sphy->ref_clk_freq      = samsung_usbphy_get_refclk_freq(sphy);
> -
> -       sphy->phy.otg           = otg;
> -       sphy->phy.otg->phy      = &sphy->phy;
> -       sphy->phy.otg->set_host = samsung_usbphy_set_host;
> -
> -       spin_lock_init(&sphy->lock);
> -
> -       platform_set_drvdata(pdev, sphy);
> -
> -       return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB2);
> -}
> -
> -static int samsung_usbphy_remove(struct platform_device *pdev)
> -{
> -       struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
> -
> -       usb_remove_phy(&sphy->phy);
> -
> -       if (sphy->pmuregs)
> -               iounmap(sphy->pmuregs);
> -       if (sphy->sysreg)
> -               iounmap(sphy->sysreg);
> -
> -       return 0;
> -}
> -
> -static const struct samsung_usbphy_drvdata usbphy_s3c64xx = {
> -       .cpu_type               = TYPE_S3C64XX,
> -       .devphy_en_mask         = S3C64XX_USBPHY_ENABLE,
> -};
> -
> -static const struct samsung_usbphy_drvdata usbphy_exynos4 = {
> -       .cpu_type               = TYPE_EXYNOS4210,
> -       .devphy_en_mask         = EXYNOS_USBPHY_ENABLE,
> -       .hostphy_en_mask        = EXYNOS_USBPHY_ENABLE,
> -};
> -
> -static struct samsung_usbphy_drvdata usbphy_exynos5 = {
> -       .cpu_type               = TYPE_EXYNOS5250,
> -       .hostphy_en_mask        = EXYNOS_USBPHY_ENABLE,
> -       .hostphy_reg_offset     = EXYNOS_USBHOST_PHY_CTRL_OFFSET,
> -};
> -
> -#ifdef CONFIG_OF
> -static const struct of_device_id samsung_usbphy_dt_match[] = {
> -       {
> -               .compatible = "samsung,s3c64xx-usbphy",
> -               .data = &usbphy_s3c64xx,
> -       }, {
> -               .compatible = "samsung,exynos4210-usbphy",
> -               .data = &usbphy_exynos4,
> -       }, {
> -               .compatible = "samsung,exynos5250-usbphy",
> -               .data = &usbphy_exynos5
> -       },
> -       {},
> -};
> -MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
> -#endif
> -
> -static struct platform_device_id samsung_usbphy_driver_ids[] = {
> -       {
> -               .name           = "s3c64xx-usbphy",
> -               .driver_data    = (unsigned long)&usbphy_s3c64xx,
> -       }, {
> -               .name           = "exynos4210-usbphy",
> -               .driver_data    = (unsigned long)&usbphy_exynos4,
> -       }, {
> -               .name           = "exynos5250-usbphy",
> -               .driver_data    = (unsigned long)&usbphy_exynos5,
> -       },
> -       {},
> -};
> -
> -MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
> -
> -static struct platform_driver samsung_usbphy_driver = {
> -       .probe          = samsung_usbphy_probe,
> -       .remove         = samsung_usbphy_remove,
> -       .id_table       = samsung_usbphy_driver_ids,
> -       .driver         = {
> -               .name   = "samsung-usbphy",
> -               .owner  = THIS_MODULE,
> -               .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
> -       },
> -};
> -
> -module_platform_driver(samsung_usbphy_driver);
> -
> -MODULE_DESCRIPTION("Samsung USB phy controller");
> -MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
> -MODULE_LICENSE("GPL");
> -MODULE_ALIAS("platform:samsung-usbphy");
> diff --git a/drivers/usb/phy/samsung-usbphy.h b/drivers/usb/phy/samsung-usbphy.h
> new file mode 100644
> index 0000000..969632b
> --- /dev/null
> +++ b/drivers/usb/phy/samsung-usbphy.h
> @@ -0,0 +1,247 @@
> +/* linux/drivers/usb/phy/samsung-usbphy.h
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + *              http://www.samsung.com
> + *
> + * Samsung USB-PHY transceiver; talks to S3C HS OTG controller, EHCI-S5P and
> + * OHCI-EXYNOS controllers.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/usb/phy.h>
> +
> +/* Register definitions */
> +
> +#define SAMSUNG_PHYPWR                         (0x00)
> +
> +#define PHYPWR_NORMAL_MASK                     (0x19 << 0)
> +#define PHYPWR_OTG_DISABLE                     (0x1 << 4)
> +#define PHYPWR_ANALOG_POWERDOWN                        (0x1 << 3)
> +#define PHYPWR_FORCE_SUSPEND                   (0x1 << 1)
> +/* For Exynos4 */
> +#define PHYPWR_NORMAL_MASK_PHY0                        (0x39 << 0)
> +#define PHYPWR_SLEEP_PHY0                      (0x1 << 5)
> +
> +#define SAMSUNG_PHYCLK                         (0x04)
> +
> +#define PHYCLK_MODE_USB11                      (0x1 << 6)
> +#define PHYCLK_EXT_OSC                         (0x1 << 5)
> +#define PHYCLK_COMMON_ON_N                     (0x1 << 4)
> +#define PHYCLK_ID_PULL                         (0x1 << 2)
> +#define PHYCLK_CLKSEL_MASK                     (0x3 << 0)
> +#define PHYCLK_CLKSEL_48M                      (0x0 << 0)
> +#define PHYCLK_CLKSEL_12M                      (0x2 << 0)
> +#define PHYCLK_CLKSEL_24M                      (0x3 << 0)
> +
> +#define SAMSUNG_RSTCON                         (0x08)
> +
> +#define RSTCON_PHYLINK_SWRST                   (0x1 << 2)
> +#define RSTCON_HLINK_SWRST                     (0x1 << 1)
> +#define RSTCON_SWRST                           (0x1 << 0)
> +
> +/* EXYNOS5 */
> +#define EXYNOS5_PHY_HOST_CTRL0                 (0x00)
> +
> +#define HOST_CTRL0_PHYSWRSTALL                 (0x1 << 31)
> +
> +#define HOST_CTRL0_REFCLKSEL_MASK              (0x3 << 19)
> +#define HOST_CTRL0_REFCLKSEL_XTAL              (0x0 << 19)
> +#define HOST_CTRL0_REFCLKSEL_EXTL              (0x1 << 19)
> +#define HOST_CTRL0_REFCLKSEL_CLKCORE           (0x2 << 19)
> +
> +#define HOST_CTRL0_FSEL_MASK                   (0x7 << 16)
> +#define HOST_CTRL0_FSEL(_x)                    ((_x) << 16)
> +
> +#define FSEL_CLKSEL_50M                                (0x7)
> +#define FSEL_CLKSEL_24M                                (0x5)
> +#define FSEL_CLKSEL_20M                                (0x4)
> +#define FSEL_CLKSEL_19200K                     (0x3)
> +#define FSEL_CLKSEL_12M                                (0x2)
> +#define FSEL_CLKSEL_10M                                (0x1)
> +#define FSEL_CLKSEL_9600K                      (0x0)
> +
> +#define HOST_CTRL0_TESTBURNIN                  (0x1 << 11)
> +#define HOST_CTRL0_RETENABLE                   (0x1 << 10)
> +#define HOST_CTRL0_COMMONON_N                  (0x1 << 9)
> +#define HOST_CTRL0_SIDDQ                       (0x1 << 6)
> +#define HOST_CTRL0_FORCESLEEP                  (0x1 << 5)
> +#define HOST_CTRL0_FORCESUSPEND                        (0x1 << 4)
> +#define HOST_CTRL0_WORDINTERFACE               (0x1 << 3)
> +#define HOST_CTRL0_UTMISWRST                   (0x1 << 2)
> +#define HOST_CTRL0_LINKSWRST                   (0x1 << 1)
> +#define HOST_CTRL0_PHYSWRST                    (0x1 << 0)
> +
> +#define EXYNOS5_PHY_HOST_TUNE0                 (0x04)
> +
> +#define EXYNOS5_PHY_HSIC_CTRL1                 (0x10)
> +
> +#define EXYNOS5_PHY_HSIC_TUNE1                 (0x14)
> +
> +#define EXYNOS5_PHY_HSIC_CTRL2                 (0x20)
> +
> +#define EXYNOS5_PHY_HSIC_TUNE2                 (0x24)
> +
> +#define HSIC_CTRL_REFCLKSEL_MASK               (0x3 << 23)
> +#define HSIC_CTRL_REFCLKSEL                    (0x2 << 23)
> +
> +#define HSIC_CTRL_REFCLKDIV_MASK               (0x7f << 16)
> +#define HSIC_CTRL_REFCLKDIV(_x)                        ((_x) << 16)
> +#define HSIC_CTRL_REFCLKDIV_12                 (0x24 << 16)
> +#define HSIC_CTRL_REFCLKDIV_15                 (0x1c << 16)
> +#define HSIC_CTRL_REFCLKDIV_16                 (0x1a << 16)
> +#define HSIC_CTRL_REFCLKDIV_19_2               (0x15 << 16)
> +#define HSIC_CTRL_REFCLKDIV_20                 (0x14 << 16)
> +
> +#define HSIC_CTRL_SIDDQ                                (0x1 << 6)
> +#define HSIC_CTRL_FORCESLEEP                   (0x1 << 5)
> +#define HSIC_CTRL_FORCESUSPEND                 (0x1 << 4)
> +#define HSIC_CTRL_WORDINTERFACE                        (0x1 << 3)
> +#define HSIC_CTRL_UTMISWRST                    (0x1 << 2)
> +#define HSIC_CTRL_PHYSWRST                     (0x1 << 0)
> +
> +#define EXYNOS5_PHY_HOST_EHCICTRL              (0x30)
> +
> +#define HOST_EHCICTRL_ENAINCRXALIGN            (0x1 << 29)
> +#define HOST_EHCICTRL_ENAINCR4                 (0x1 << 28)
> +#define HOST_EHCICTRL_ENAINCR8                 (0x1 << 27)
> +#define HOST_EHCICTRL_ENAINCR16                        (0x1 << 26)
> +
> +#define EXYNOS5_PHY_HOST_OHCICTRL              (0x34)
> +
> +#define HOST_OHCICTRL_SUSPLGCY                 (0x1 << 3)
> +#define HOST_OHCICTRL_APPSTARTCLK              (0x1 << 2)
> +#define HOST_OHCICTRL_CNTSEL                   (0x1 << 1)
> +#define HOST_OHCICTRL_CLKCKTRST                        (0x1 << 0)
> +
> +#define EXYNOS5_PHY_OTG_SYS                    (0x38)
> +
> +#define OTG_SYS_PHYLINK_SWRESET                        (0x1 << 14)
> +#define OTG_SYS_LINKSWRST_UOTG                 (0x1 << 13)
> +#define OTG_SYS_PHY0_SWRST                     (0x1 << 12)
> +
> +#define OTG_SYS_REFCLKSEL_MASK                 (0x3 << 9)
> +#define OTG_SYS_REFCLKSEL_XTAL                 (0x0 << 9)
> +#define OTG_SYS_REFCLKSEL_EXTL                 (0x1 << 9)
> +#define OTG_SYS_REFCLKSEL_CLKCORE              (0x2 << 9)
> +
> +#define OTG_SYS_IDPULLUP_UOTG                  (0x1 << 8)
> +#define OTG_SYS_COMMON_ON                      (0x1 << 7)
> +
> +#define OTG_SYS_FSEL_MASK                      (0x7 << 4)
> +#define OTG_SYS_FSEL(_x)                       ((_x) << 4)
> +
> +#define OTG_SYS_FORCESLEEP                     (0x1 << 3)
> +#define OTG_SYS_OTGDISABLE                     (0x1 << 2)
> +#define OTG_SYS_SIDDQ_UOTG                     (0x1 << 1)
> +#define OTG_SYS_FORCESUSPEND                   (0x1 << 0)
> +
> +#define EXYNOS5_PHY_OTG_TUNE                   (0x40)
> +
> +#ifndef MHZ
> +#define MHZ (1000*1000)
> +#endif
> +
> +#ifndef KHZ
> +#define KHZ (1000)
> +#endif
> +
> +#define EXYNOS_USBHOST_PHY_CTRL_OFFSET         (0x4)
> +#define S3C64XX_USBPHY_ENABLE                  (0x1 << 16)
> +#define EXYNOS_USBPHY_ENABLE                   (0x1 << 0)
> +#define EXYNOS_USB20PHY_CFG_HOST_LINK          (0x1 << 0)
> +
> +enum samsung_cpu_type {
> +       TYPE_S3C64XX,
> +       TYPE_EXYNOS4210,
> +       TYPE_EXYNOS5250,
> +};
> +
> +/*
> + * struct samsung_usbphy_drvdata - driver data for various SoC variants
> + * @cpu_type: machine identifier
> + * @devphy_en_mask: device phy enable mask for PHY CONTROL register
> + * @hostphy_en_mask: host phy enable mask for PHY CONTROL register
> + * @devphy_reg_offset: offset to DEVICE PHY CONTROL register from
> + *                    mapped address of system controller.
> + * @hostphy_reg_offset: offset to HOST PHY CONTROL register from
> + *                    mapped address of system controller.
> + *
> + *     Here we have a separate mask for device type phy.
> + *     Having different masks for host and device type phy helps
> + *     in setting independent masks in case of SoCs like S5PV210,
> + *     in which PHY0 and PHY1 enable bits belong to same register
> + *     placed at position 0 and 1 respectively.
> + *     Although for newer SoCs like exynos these bits belong to
> + *     different registers altogether placed at position 0.
> + */
> +struct samsung_usbphy_drvdata {
> +       int cpu_type;
> +       int devphy_en_mask;
> +       int hostphy_en_mask;
> +       u32 devphy_reg_offset;
> +       u32 hostphy_reg_offset;
> +};
> +
> +/*
> + * struct samsung_usbphy - transceiver driver state
> + * @phy: transceiver structure
> + * @plat: platform data
> + * @dev: The parent device supplied to the probe function
> + * @clk: usb phy clock
> + * @regs: usb phy controller registers memory base
> + * @pmuregs: USB device PHY_CONTROL register memory base
> + * @sysreg: USB2.0 PHY_CFG register memory base
> + * @ref_clk_freq: reference clock frequency selection
> + * @drv_data: driver data available for different SoCs
> + * @phy_type: Samsung SoCs specific phy types: #HOST
> + *                                             #DEVICE
> + * @phy_usage: usage count for phy
> + * @lock: lock for phy operations
> + */
> +struct samsung_usbphy {
> +       struct usb_phy  phy;
> +       struct samsung_usbphy_data *plat;
> +       struct device   *dev;
> +       struct clk      *clk;
> +       void __iomem    *regs;
> +       void __iomem    *pmuregs;
> +       void __iomem    *sysreg;
> +       int             ref_clk_freq;
> +       const struct samsung_usbphy_drvdata *drv_data;
> +       enum samsung_usb_phy_type phy_type;
> +       atomic_t        phy_usage;
> +       spinlock_t      lock;
> +};
> +
> +#define phy_to_sphy(x)         container_of((x), struct samsung_usbphy, phy)
> +
> +static const struct of_device_id samsung_usbphy_dt_match[];
> +
> +static inline const struct samsung_usbphy_drvdata
> +*samsung_usbphy_get_driver_data(struct platform_device *pdev)
> +{
> +       if (pdev->dev.of_node) {
> +               const struct of_device_id *match;
> +               match = of_match_node(samsung_usbphy_dt_match,
> +                                                       pdev->dev.of_node);
> +               return match->data;
> +       }
> +
> +       return (struct samsung_usbphy_drvdata *)
> +                               platform_get_device_id(pdev)->driver_data;
> +}
> +
> +extern int samsung_usbphy_parse_dt(struct samsung_usbphy *sphy);
> +extern void samsung_usbphy_set_isolation(struct samsung_usbphy *sphy, bool on);
> +extern void samsung_usbphy_cfg_sel(struct samsung_usbphy *sphy);
> +extern int samsung_usbphy_set_type(struct usb_phy *phy,
> +                               enum samsung_usb_phy_type phy_type);
> +extern int samsung_usbphy_get_refclk_freq(struct samsung_usbphy *sphy);
> --
> 1.7.6.5
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss



-- 
Thanks & Regards
Vivek

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller
  2013-01-28 10:26   ` [PATCH v4 " Vivek Gautam
@ 2013-01-29  5:35     ` Vivek Gautam
  2013-01-30  6:01     ` Kukjin Kim
  1 sibling, 0 replies; 14+ messages in thread
From: Vivek Gautam @ 2013-01-29  5:35 UTC (permalink / raw)
  To: linux-usb
  Cc: Doug Anderson, linux-kernel, devicetree-discuss,
	linux-samsung-soc, gregkh, balbi, kgene.kim, grant.likely,
	sylvester.nawrocki, tomasz.figa, av.tikhomirov, p.paneri,
	Vivek Gautam

CC: Doug Anderson


On Mon, Jan 28, 2013 at 3:56 PM, Vivek Gautam <gautam.vivek@samsung.com> wrote:
> Adding PHY driver support for USB 3.0 controller for Samsung's
> SoCs.
>
> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
> ---
>
> Changes from v3:
>  - Making SAMSUNG_USB3PHY dependent on SAMSUNG_USBPHY.
>  - Adding USB_DWC3 to dependencies of SAMSUNG_USB2PHY since
>    dwc3 controller also looks for USB2 type PHY.
>
>  drivers/usb/phy/Kconfig          |   11 +-
>  drivers/usb/phy/Makefile         |    1 +
>  drivers/usb/phy/samsung-usb3.c   |  349 ++++++++++++++++++++++++++++++++++++++
>  drivers/usb/phy/samsung-usbphy.h |   81 +++++++++
>  4 files changed, 441 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/usb/phy/samsung-usb3.c
>
> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
> index cc0d230..9325a95 100644
> --- a/drivers/usb/phy/Kconfig
> +++ b/drivers/usb/phy/Kconfig
> @@ -52,14 +52,23 @@ config SAMSUNG_USBPHY
>         help
>           Enable this to support Samsung USB phy controllers for Samsung
>           SoCs.
> +         Further enable USB 2.0 type PHY or USB 3.0 type PHY as required
> +         for USB controllers in use.
>
>  if SAMSUNG_USBPHY
>
>  config SAMSUNG_USB2PHY
>         bool "Samsung USB 2.0 PHY controller Driver"
> -       depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS
> +       depends on USB_S3C_HSOTG || USB_EHCI_S5P || USB_OHCI_EXYNOS || USB_DWC3
>         help
>           Enable this to support Samsung USB 2.0 (High Speed) phy controller
>           for Samsung SoCs.
>
> +config SAMSUNG_USB3PHY
> +       bool "Samsung USB 3.0 PHY controller Driver"
> +       depends on USB_DWC3
> +       help
> +         Enable this to support Samsung USB 3.0 (Super Speed) phy controller
> +         for samsung SoCs.
> +
>  endif
> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
> index 7ba9862..b8505ac 100644
> --- a/drivers/usb/phy/Makefile
> +++ b/drivers/usb/phy/Makefile
> @@ -11,3 +11,4 @@ obj-$(CONFIG_USB_EHCI_TEGRA)  += tegra_usb_phy.o
>  obj-$(CONFIG_USB_RCAR_PHY)             += rcar-phy.o
>  obj-$(CONFIG_SAMSUNG_USBPHY)           += samsung-usbphy.o
>  obj-$(CONFIG_SAMSUNG_USB2PHY)          += samsung-usb2.o
> +obj-$(CONFIG_SAMSUNG_USB3PHY)          += samsung-usb3.o
> diff --git a/drivers/usb/phy/samsung-usb3.c b/drivers/usb/phy/samsung-usb3.c
> new file mode 100644
> index 0000000..29e1321
> --- /dev/null
> +++ b/drivers/usb/phy/samsung-usb3.c
> @@ -0,0 +1,349 @@
> +/* linux/drivers/usb/phy/samsung-usb3.c
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + *              http://www.samsung.com
> + *
> + * Author: Vivek Gautam <gautam.vivek@samsung.com>
> + *
> + * Samsung USB 3.0 PHY transceiver; talks to DWC3 controller.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/usb/samsung_usb_phy.h>
> +#include <linux/platform_data/samsung-usbphy.h>
> +
> +#include "samsung-usbphy.h"
> +
> +/*
> + * Sets the phy clk as EXTREFCLK (XXTI) which is internal clock from clock core.
> + */
> +static u32 samsung_usb3_phy_set_refclk(struct samsung_usbphy *sphy)
> +{
> +       u32 reg;
> +       u32 refclk;
> +
> +       refclk = sphy->ref_clk_freq;
> +
> +       reg = PHYCLKRST_REFCLKSEL_EXT_REFCLK |
> +               PHYCLKRST_FSEL(refclk);
> +
> +       switch (refclk) {
> +       case FSEL_CLKSEL_50M:
> +               reg |= (PHYCLKRST_MPLL_MULTIPLIER_50M_REF |
> +                       PHYCLKRST_SSC_REFCLKSEL(0x00));
> +               break;
> +       case FSEL_CLKSEL_20M:
> +               reg |= (PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF |
> +                       PHYCLKRST_SSC_REFCLKSEL(0x00));
> +               break;
> +       case FSEL_CLKSEL_19200K:
> +               reg |= (PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF |
> +                       PHYCLKRST_SSC_REFCLKSEL(0x88));
> +               break;
> +       case FSEL_CLKSEL_24M:
> +       default:
> +               reg |= (PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF |
> +                       PHYCLKRST_SSC_REFCLKSEL(0x88));
> +               break;
> +       }
> +
> +       return reg;
> +}
> +
> +static int samsung_exynos5_usb3_phy_enable(struct samsung_usbphy *sphy)
> +{
> +       void __iomem *regs = sphy->regs;
> +       u32 phyparam0;
> +       u32 phyparam1;
> +       u32 linksystem;
> +       u32 phybatchg;
> +       u32 phytest;
> +       u32 phyclkrst;
> +
> +       /* Reset USB 3.0 PHY */
> +       writel(0x0, regs + EXYNOS5_DRD_PHYREG0);
> +
> +       phyparam0 = readl(regs + EXYNOS5_DRD_PHYPARAM0);
> +       /* Select PHY CLK source */
> +       phyparam0 &= ~PHYPARAM0_REF_USE_PAD;
> +       /* Set Loss-of-Signal Detector sensitivity */
> +       phyparam0 &= ~PHYPARAM0_REF_LOSLEVEL_MASK;
> +       phyparam0 |= PHYPARAM0_REF_LOSLEVEL;
> +       writel(phyparam0, regs + EXYNOS5_DRD_PHYPARAM0);
> +
> +       writel(0x0, regs + EXYNOS5_DRD_PHYRESUME);
> +
> +       /*
> +        * Setting the Frame length Adj value[6:1] to default 0x20
> +        * See xHCI 1.0 spec, 5.2.4
> +        */
> +       linksystem = LINKSYSTEM_XHCI_VERSION_CONTROL |
> +                       LINKSYSTEM_FLADJ(0x20);
> +       writel(linksystem, regs + EXYNOS5_DRD_LINKSYSTEM);
> +
> +       phyparam1 = readl(regs + EXYNOS5_DRD_PHYPARAM1);
> +       /* Set Tx De-Emphasis level */
> +       phyparam1 &= ~PHYPARAM1_PCS_TXDEEMPH_MASK;
> +       phyparam1 |= PHYPARAM1_PCS_TXDEEMPH;
> +       writel(phyparam1, regs + EXYNOS5_DRD_PHYPARAM1);
> +
> +       phybatchg = readl(regs + EXYNOS5_DRD_PHYBATCHG);
> +       phybatchg |= PHYBATCHG_UTMI_CLKSEL;
> +       writel(phybatchg, regs + EXYNOS5_DRD_PHYBATCHG);
> +
> +       /* PHYTEST POWERDOWN Control */
> +       phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
> +       phytest &= ~(PHYTEST_POWERDOWN_SSP |
> +                       PHYTEST_POWERDOWN_HSP);
> +       writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
> +
> +       /* UTMI Power Control */
> +       writel(PHYUTMI_OTGDISABLE, regs + EXYNOS5_DRD_PHYUTMI);
> +
> +       phyclkrst = samsung_usb3_phy_set_refclk(sphy);
> +
> +       phyclkrst |= PHYCLKRST_PORTRESET |
> +                       /* Digital power supply in normal operating mode */
> +                       PHYCLKRST_RETENABLEN |
> +                       /* Enable ref clock for SS function */
> +                       PHYCLKRST_REF_SSP_EN |
> +                       /* Enable spread spectrum */
> +                       PHYCLKRST_SSC_EN |
> +                       /* Power down HS Bias and PLL blocks in suspend mode */
> +                       PHYCLKRST_COMMONONN;
> +
> +       writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
> +
> +       udelay(10);
> +
> +       phyclkrst &= ~(PHYCLKRST_PORTRESET);
> +       writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
> +
> +       return 0;
> +}
> +
> +static void samsung_exynos5_usb3_phy_disable(struct samsung_usbphy *sphy)
> +{
> +       u32 phyutmi;
> +       u32 phyclkrst;
> +       u32 phytest;
> +       void __iomem *regs = sphy->regs;
> +
> +       phyutmi = PHYUTMI_OTGDISABLE |
> +                       PHYUTMI_FORCESUSPEND |
> +                       PHYUTMI_FORCESLEEP;
> +       writel(phyutmi, regs + EXYNOS5_DRD_PHYUTMI);
> +
> +       /* Resetting the PHYCLKRST enable bits to reduce leakage current */
> +       phyclkrst = readl(regs + EXYNOS5_DRD_PHYCLKRST);
> +       phyclkrst &= ~(PHYCLKRST_REF_SSP_EN |
> +                       PHYCLKRST_SSC_EN |
> +                       PHYCLKRST_COMMONONN);
> +       writel(phyclkrst, regs + EXYNOS5_DRD_PHYCLKRST);
> +
> +       /* Control PHYTEST to remove leakage current */
> +       phytest = readl(regs + EXYNOS5_DRD_PHYTEST);
> +       phytest |= (PHYTEST_POWERDOWN_SSP |
> +                       PHYTEST_POWERDOWN_HSP);
> +       writel(phytest, regs + EXYNOS5_DRD_PHYTEST);
> +}
> +
> +static int samsung_usb3_phy_init(struct usb_phy *phy)
> +{
> +       struct samsung_usbphy *sphy;
> +       unsigned long flags;
> +       int ret = 0;
> +
> +       sphy = phy_to_sphy(phy);
> +
> +       /* Enable the phy clock */
> +       ret = clk_prepare_enable(sphy->clk);
> +       if (ret) {
> +               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
> +               return ret;
> +       }
> +
> +       spin_lock_irqsave(&sphy->lock, flags);
> +
> +       /* setting default phy-type for USB 3.0 */
> +       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
> +
> +       /* Disable phy isolation */
> +       samsung_usbphy_set_isolation(sphy, false);
> +
> +       /* Initialize usb phy registers */
> +       samsung_exynos5_usb3_phy_enable(sphy);
> +
> +       spin_unlock_irqrestore(&sphy->lock, flags);
> +
> +       /* Disable the phy clock */
> +       clk_disable_unprepare(sphy->clk);
> +
> +       return ret;
> +}
> +
> +/*
> + * The function passed to the usb driver for phy shutdown
> + */
> +static void samsung_usb3_phy_shutdown(struct usb_phy *phy)
> +{
> +       struct samsung_usbphy *sphy;
> +       unsigned long flags;
> +
> +       sphy = phy_to_sphy(phy);
> +
> +       if (clk_prepare_enable(sphy->clk)) {
> +               dev_err(sphy->dev, "%s: clk_prepare_enable failed\n", __func__);
> +               return;
> +       }
> +
> +       spin_lock_irqsave(&sphy->lock, flags);
> +
> +       /* setting default phy-type for USB 3.0 */
> +       samsung_usbphy_set_type(&sphy->phy, USB_PHY_TYPE_DEVICE);
> +
> +       /* De-initialize usb phy registers */
> +       samsung_exynos5_usb3_phy_disable(sphy);
> +
> +       /* Enable phy isolation */
> +       samsung_usbphy_set_isolation(sphy, true);
> +
> +       spin_unlock_irqrestore(&sphy->lock, flags);
> +
> +       clk_disable_unprepare(sphy->clk);
> +}
> +
> +static int samsung_usb3_phy_probe(struct platform_device *pdev)
> +{
> +       struct samsung_usbphy *sphy;
> +       struct samsung_usbphy_data *pdata = pdev->dev.platform_data;
> +       struct device *dev = &pdev->dev;
> +       struct resource *phy_mem;
> +       void __iomem    *phy_base;
> +       struct clk *clk;
> +       int ret;
> +
> +       phy_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +       if (!phy_mem) {
> +               dev_err(dev, "%s: missing mem resource\n", __func__);
> +               return -ENODEV;
> +       }
> +
> +       phy_base = devm_request_and_ioremap(dev, phy_mem);
> +       if (!phy_base) {
> +               dev_err(dev, "%s: register mapping failed\n", __func__);
> +               return -ENXIO;
> +       }
> +
> +       sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
> +       if (!sphy)
> +               return -ENOMEM;
> +
> +       clk = devm_clk_get(dev, "usbdrd30");
> +       if (IS_ERR(clk)) {
> +               dev_err(dev, "Failed to get device clock\n");
> +               return PTR_ERR(clk);
> +       }
> +
> +       sphy->dev = dev;
> +
> +       if (dev->of_node) {
> +               ret = samsung_usbphy_parse_dt(sphy);
> +               if (ret < 0)
> +                       return ret;
> +       } else {
> +               if (!pdata) {
> +                       dev_err(dev, "no platform data specified\n");
> +                       return -EINVAL;
> +               }
> +       }
> +
> +       sphy->plat              = pdata;
> +       sphy->regs              = phy_base;
> +       sphy->clk               = clk;
> +       sphy->phy.dev           = sphy->dev;
> +       sphy->phy.label         = "samsung-usb3-phy";
> +       sphy->phy.init          = samsung_usb3_phy_init;
> +       sphy->phy.shutdown      = samsung_usb3_phy_shutdown;
> +       sphy->drv_data          = samsung_usbphy_get_driver_data(pdev);
> +       sphy->ref_clk_freq      = samsung_usbphy_get_refclk_freq(sphy);
> +
> +       spin_lock_init(&sphy->lock);
> +
> +       platform_set_drvdata(pdev, sphy);
> +
> +       return usb_add_phy(&sphy->phy, USB_PHY_TYPE_USB3);
> +}
> +
> +static int samsung_usb3_phy_remove(struct platform_device *pdev)
> +{
> +       struct samsung_usbphy *sphy = platform_get_drvdata(pdev);
> +
> +       usb_remove_phy(&sphy->phy);
> +
> +       if (sphy->pmuregs)
> +               iounmap(sphy->pmuregs);
> +       if (sphy->sysreg)
> +               iounmap(sphy->sysreg);
> +
> +       return 0;
> +}
> +
> +static struct samsung_usbphy_drvdata usb3_phy_exynos5 = {
> +       .cpu_type               = TYPE_EXYNOS5250,
> +       .devphy_en_mask         = EXYNOS_USBPHY_ENABLE,
> +};
> +
> +#ifdef CONFIG_OF
> +static const struct of_device_id samsung_usbphy_dt_match[] = {
> +       {
> +               .compatible = "samsung,exynos5250-usb3-phy",
> +               .data = &usb3_phy_exynos5
> +       },
> +       {},
> +};
> +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
> +#endif
> +
> +static struct platform_device_id samsung_usbphy_driver_ids[] = {
> +       {
> +               .name           = "exynos5250-usb3-phy",
> +               .driver_data    = (unsigned long)&usb3_phy_exynos5,
> +       },
> +       {},
> +};
> +
> +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
> +
> +static struct platform_driver samsung_usb3_phy_driver = {
> +       .probe          = samsung_usb3_phy_probe,
> +       .remove         = samsung_usb3_phy_remove,
> +       .id_table       = samsung_usbphy_driver_ids,
> +       .driver         = {
> +               .name   = "samsung-usb3-phy",
> +               .owner  = THIS_MODULE,
> +               .of_match_table = of_match_ptr(samsung_usbphy_dt_match),
> +       },
> +};
> +
> +module_platform_driver(samsung_usb3_phy_driver);
> +
> +MODULE_DESCRIPTION("Samsung USB 3.0 phy controller");
> +MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:samsung-usb3-phy");
> diff --git a/drivers/usb/phy/samsung-usbphy.h b/drivers/usb/phy/samsung-usbphy.h
> index 969632b..f7e657d 100644
> --- a/drivers/usb/phy/samsung-usbphy.h
> +++ b/drivers/usb/phy/samsung-usbphy.h
> @@ -145,6 +145,87 @@
>
>  #define EXYNOS5_PHY_OTG_TUNE                   (0x40)
>
> +/* EXYNOS5: USB 3.0 DRD */
> +#define EXYNOS5_DRD_LINKSYSTEM                 (0x04)
> +
> +#define LINKSYSTEM_FLADJ_MASK                  (0x3f << 1)
> +#define LINKSYSTEM_FLADJ(_x)                   ((_x) << 1)
> +#define LINKSYSTEM_XHCI_VERSION_CONTROL                (0x1 << 27)
> +
> +#define EXYNOS5_DRD_PHYUTMI                    (0x08)
> +
> +#define PHYUTMI_OTGDISABLE                     (0x1 << 6)
> +#define PHYUTMI_FORCESUSPEND                   (0x1 << 1)
> +#define PHYUTMI_FORCESLEEP                     (0x1 << 0)
> +
> +#define EXYNOS5_DRD_PHYPIPE                    (0x0c)
> +
> +#define EXYNOS5_DRD_PHYCLKRST                  (0x10)
> +
> +#define PHYCLKRST_SSC_REFCLKSEL_MASK           (0xff << 23)
> +#define PHYCLKRST_SSC_REFCLKSEL(_x)            ((_x) << 23)
> +
> +#define PHYCLKRST_SSC_RANGE_MASK               (0x03 << 21)
> +#define PHYCLKRST_SSC_RANGE(_x)                        ((_x) << 21)
> +
> +#define PHYCLKRST_SSC_EN                       (0x1 << 20)
> +#define PHYCLKRST_REF_SSP_EN                   (0x1 << 19)
> +#define PHYCLKRST_REF_CLKDIV2                  (0x1 << 18)
> +
> +#define PHYCLKRST_MPLL_MULTIPLIER_MASK         (0x7f << 11)
> +#define PHYCLKRST_MPLL_MULTIPLIER_100MHZ_REF   (0x19 << 11)
> +#define PHYCLKRST_MPLL_MULTIPLIER_50M_REF      (0x02 << 11)
> +#define PHYCLKRST_MPLL_MULTIPLIER_24MHZ_REF    (0x68 << 11)
> +#define PHYCLKRST_MPLL_MULTIPLIER_20MHZ_REF    (0x7d << 11)
> +#define PHYCLKRST_MPLL_MULTIPLIER_19200KHZ_REF (0x02 << 11)
> +
> +#define PHYCLKRST_FSEL_MASK                    (0x3f << 5)
> +#define PHYCLKRST_FSEL(_x)                     ((_x) << 5)
> +#define PHYCLKRST_FSEL_PAD_100MHZ              (0x27 << 5)
> +#define PHYCLKRST_FSEL_PAD_24MHZ               (0x2a << 5)
> +#define PHYCLKRST_FSEL_PAD_20MHZ               (0x31 << 5)
> +#define PHYCLKRST_FSEL_PAD_19_2MHZ             (0x38 << 5)
> +
> +#define PHYCLKRST_RETENABLEN                   (0x1 << 4)
> +
> +#define PHYCLKRST_REFCLKSEL_MASK               (0x03 << 2)
> +#define PHYCLKRST_REFCLKSEL_PAD_REFCLK         (0x2 << 2)
> +#define PHYCLKRST_REFCLKSEL_EXT_REFCLK         (0x3 << 2)
> +
> +#define PHYCLKRST_PORTRESET                    (0x1 << 1)
> +#define PHYCLKRST_COMMONONN                    (0x1 << 0)
> +
> +#define EXYNOS5_DRD_PHYREG0                    (0x14)
> +#define EXYNOS5_DRD_PHYREG1                    (0x18)
> +
> +#define EXYNOS5_DRD_PHYPARAM0                  (0x1c)
> +
> +#define PHYPARAM0_REF_USE_PAD                  (0x1 << 31)
> +#define PHYPARAM0_REF_LOSLEVEL_MASK            (0x1f << 26)
> +#define PHYPARAM0_REF_LOSLEVEL                 (0x9 << 26)
> +
> +#define EXYNOS5_DRD_PHYPARAM1                  (0x20)
> +
> +#define PHYPARAM1_PCS_TXDEEMPH_MASK            (0x1f << 0)
> +#define PHYPARAM1_PCS_TXDEEMPH                 (0x1c)
> +
> +#define EXYNOS5_DRD_PHYTERM                    (0x24)
> +
> +#define EXYNOS5_DRD_PHYTEST                    (0x28)
> +
> +#define PHYTEST_POWERDOWN_SSP                  (0x1 << 3)
> +#define PHYTEST_POWERDOWN_HSP                  (0x1 << 2)
> +
> +#define EXYNOS5_DRD_PHYADP                     (0x2c)
> +
> +#define EXYNOS5_DRD_PHYBATCHG                  (0x30)
> +
> +#define PHYBATCHG_UTMI_CLKSEL                  (0x1 << 2)
> +
> +#define EXYNOS5_DRD_PHYRESUME                  (0x34)
> +#define EXYNOS5_DRD_LINKPORT                   (0x44)
> +
> +
>  #ifndef MHZ
>  #define MHZ (1000*1000)
>  #endif
> --
> 1.7.6.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Thanks & Regards
Vivek

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH v4 1/2] usb: phy: samsung: Common out the generic stuff
  2013-01-28 10:24   ` [PATCH v4 " Vivek Gautam
  2013-01-29  5:34     ` Vivek Gautam
@ 2013-01-30  5:56     ` Kukjin Kim
  2013-02-05  6:32       ` Vivek Gautam
  1 sibling, 1 reply; 14+ messages in thread
From: Kukjin Kim @ 2013-01-30  5:56 UTC (permalink / raw)
  To: 'Vivek Gautam', linux-usb
  Cc: linux-kernel, devicetree-discuss, linux-samsung-soc, gregkh,
	balbi, grant.likely, sylvester.nawrocki, tomasz.figa,
	av.tikhomirov, dianders, p.paneri

Vivek Gautam wrote:
> 
> Moving register and structure definitions to header file,
> and keeping the generic functions to be used across
> multiple PHYs in common file "samsung-usbphy.c".
> Also renaming the usb 2.0 phy driver to "samsung-usb2.c"

Just in my opinion, Samsung-usb2phy is more clear?...In addition, I looked
at using SAMSUNG_USB2PHY as a statement.

> 
> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
> ---
> 
> Changes from v3:
>  - Using separate config SAMSUNG_USB2PHY dependent on
>    SAMSUNG_USBPHY for samsung-usb2 type PHY controller.
> 
>  drivers/usb/phy/Kconfig          |   14 +-
>  drivers/usb/phy/Makefile         |    1 +
>  drivers/usb/phy/samsung-usb2.c   |  511 +++++++++++++++++++++++++++
>  drivers/usb/phy/samsung-usbphy.c |  714
+-------------------------------------
>  drivers/usb/phy/samsung-usbphy.h |  247 +++++++++++++
>  5 files changed, 778 insertions(+), 709 deletions(-)
>  create mode 100644 drivers/usb/phy/samsung-usb2.c
>  create mode 100644 drivers/usb/phy/samsung-usbphy.h
> 
> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
> index fae4d08..cc0d230 100644
> --- a/drivers/usb/phy/Kconfig
> +++ b/drivers/usb/phy/Kconfig
> @@ -48,8 +48,18 @@ config USB_RCAR_PHY
> 
>  config SAMSUNG_USBPHY
>  	bool "Samsung USB PHY controller Driver"
> -	depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
> USB_OHCI_EXYNOS

So this can be selected without any dependency?

>  	select USB_OTG_UTILS
>  	help
> -	  Enable this to support Samsung USB phy controller for samsung
> +	  Enable this to support Samsung USB phy controllers for Samsung
>  	  SoCs.

Hmm, according to above comments, this should be enabled under Samsung SoC?

> +
> +if SAMSUNG_USBPHY

Why is this needed here?

> +
> +config SAMSUNG_USB2PHY
> +	bool "Samsung USB 2.0 PHY controller Driver"
> +	depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
> USB_OHCI_EXYNOS
> +	help
> +	  Enable this to support Samsung USB 2.0 (High Speed) phy controller
> +	  for Samsung SoCs.
> +
> +endif
> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
> index ec304f6..7ba9862 100644
> --- a/drivers/usb/phy/Makefile
> +++ b/drivers/usb/phy/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_MV_U3D_PHY)		+=
> mv_u3d_phy.o
>  obj-$(CONFIG_USB_EHCI_TEGRA)	+= tegra_usb_phy.o
>  obj-$(CONFIG_USB_RCAR_PHY)		+= rcar-phy.o
>  obj-$(CONFIG_SAMSUNG_USBPHY)		+= samsung-usbphy.o
> +obj-$(CONFIG_SAMSUNG_USB2PHY)		+= samsung-usb2.o
> diff --git a/drivers/usb/phy/samsung-usb2.c b/drivers/usb/phy/samsung-
> usb2.c
> new file mode 100644
> index 0000000..9a9d1d0
> --- /dev/null
> +++ b/drivers/usb/phy/samsung-usb2.c
> @@ -0,0 +1,511 @@
> +/* linux/drivers/usb/phy/samsung-usb2.c
> + *
> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
> + *              http://www.samsung.com
> + *
> + * Author: Praveen Paneri <p.paneri@samsung.com>
> + *
> + * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller,
EHCI-S5P
> and
> + * OHCI-EXYNOS controllers.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/device.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/of.h>
> +#include <linux/usb/otg.h>
> +#include <linux/usb/samsung_usb_phy.h>
> +#include <linux/platform_data/samsung-usbphy.h>
> +
> +#include "samsung-usbphy.h"
> +
> +int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)

For naming, if you want to support usb 2.0 phy here, the name of fuction
should be changed to more clear name such as usb2phy or whatever.

As I'm understanding, the samsung-usbphy.c can be used for common stuff and
this is for only usb 2.0 phy.

[...]

> +#ifdef CONFIG_OF
> +static const struct of_device_id samsung_usbphy_dt_match[] = {
> +	{
> +		.compatible = "samsung,s3c64xx-usbphy",
> +		.data = &usbphy_s3c64xx,
> +	}, {
> +		.compatible = "samsung,exynos4210-usbphy",
> +		.data = &usbphy_exynos4,
> +	}, {
> +		.compatible = "samsung,exynos5250-usbphy",
> +		.data = &usbphy_exynos5
> +	},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
> +#endif
> +
> +static struct platform_device_id samsung_usbphy_driver_ids[] = {
> +	{
> +		.name		= "s3c64xx-usbphy",
> +		.driver_data	= (unsigned long)&usbphy_s3c64xx,
> +	}, {
> +		.name		= "exynos4210-usbphy",
> +		.driver_data	= (unsigned long)&usbphy_exynos4,
> +	}, {
> +		.name		= "exynos5250-usbphy",
> +		.driver_data	= (unsigned long)&usbphy_exynos5,
> +	},
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
> +
> +static struct platform_driver samsung_usbphy_driver = {
> +	.probe		= samsung_usbphy_probe,
> +	.remove		= samsung_usbphy_remove,
> +	.id_table	= samsung_usbphy_driver_ids,
> +	.driver		= {
> +		.name	= "samsung-usbphy",
> +		.owner	= THIS_MODULE,
> +		.of_match_table =
> of_match_ptr(samsung_usbphy_dt_match),
> +	},
> +};
> +
> +module_platform_driver(samsung_usbphy_driver);
> +
> +MODULE_DESCRIPTION("Samsung USB phy controller");

USB 2.0 Phy?

> +MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:samsung-usbphy");

Is this for samsung-usbphy or samsung-usb2/samsung-usb2phy?

[...]

I know why you create separated phy file samsung-usbphy.c and samsung-usb2.c
here, but I think for that, would be better if you could consider the name
and so on.

Thanks.

- Kukjin


^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [PATCH v4 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller
  2013-01-28 10:26   ` [PATCH v4 " Vivek Gautam
  2013-01-29  5:35     ` Vivek Gautam
@ 2013-01-30  6:01     ` Kukjin Kim
  2013-01-30  8:20       ` Felipe Balbi
  2013-02-05  6:36       ` Vivek Gautam
  1 sibling, 2 replies; 14+ messages in thread
From: Kukjin Kim @ 2013-01-30  6:01 UTC (permalink / raw)
  To: 'Vivek Gautam', linux-usb
  Cc: linux-kernel, devicetree-discuss, linux-samsung-soc, gregkh,
	balbi, grant.likely, sylvester.nawrocki, tomasz.figa,
	av.tikhomirov, dianders, p.paneri

Vivek Gautam wrote:
> 
> Adding PHY driver support for USB 3.0 controller for Samsung's
> SoCs.
> 
> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
> ---
> 
> Changes from v3:
>  - Making SAMSUNG_USB3PHY dependent on SAMSUNG_USBPHY.
>  - Adding USB_DWC3 to dependencies of SAMSUNG_USB2PHY since
>    dwc3 controller also looks for USB2 type PHY.
> 
>  drivers/usb/phy/Kconfig          |   11 +-
>  drivers/usb/phy/Makefile         |    1 +
>  drivers/usb/phy/samsung-usb3.c   |  349
> ++++++++++++++++++++++++++++++++++++++
>  drivers/usb/phy/samsung-usbphy.h |   81 +++++++++
>  4 files changed, 441 insertions(+), 1 deletions(-)
>  create mode 100644 drivers/usb/phy/samsung-usb3.c
> 
> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
> index cc0d230..9325a95 100644
> --- a/drivers/usb/phy/Kconfig
> +++ b/drivers/usb/phy/Kconfig
> @@ -52,14 +52,23 @@ config SAMSUNG_USBPHY
>  	help
>  	  Enable this to support Samsung USB phy controllers for Samsung
>  	  SoCs.
> +	  Further enable USB 2.0 type PHY or USB 3.0 type PHY as required
> +	  for USB controllers in use.
> 
>  if SAMSUNG_USBPHY
> 
>  config SAMSUNG_USB2PHY
>  	bool "Samsung USB 2.0 PHY controller Driver"
> -	depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
> USB_OHCI_EXYNOS
> +	depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
> USB_OHCI_EXYNOS || USB_DWC3
>  	help
>  	  Enable this to support Samsung USB 2.0 (High Speed) phy controller
>  	  for Samsung SoCs.
> 
> +config SAMSUNG_USB3PHY
> +	bool "Samsung USB 3.0 PHY controller Driver"
> +	depends on USB_DWC3
> +	help
> +	  Enable this to support Samsung USB 3.0 (Super Speed) phy
> controller
> +	  for samsung SoCs.
> +
>  endif

It mean, when USB_DWC3 is selected, we can select only one USB2PHY or
USB3PHY?

[...]

> +#ifdef CONFIG_OF
> +static const struct of_device_id samsung_usbphy_dt_match[] = {
> +	{
> +		.compatible = "samsung,exynos5250-usb3-phy",
> +		.data = &usb3_phy_exynos5
> +	},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
> +#endif
> +
> +static struct platform_device_id samsung_usbphy_driver_ids[] = {
> +	{
> +		.name		= "exynos5250-usb3-phy",

According to the name of file, exynos5250-usb3phy? Just it is imho...

> +		.driver_data	= (unsigned long)&usb3_phy_exynos5,
> +	},
> +	{},
> +};
> +
> +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
> +
> +static struct platform_driver samsung_usb3_phy_driver = {
> +	.probe		= samsung_usb3_phy_probe,
> +	.remove		= samsung_usb3_phy_remove,
> +	.id_table	= samsung_usbphy_driver_ids,
> +	.driver		= {
> +		.name	= "samsung-usb3-phy",
> +		.owner	= THIS_MODULE,
> +		.of_match_table =
> of_match_ptr(samsung_usbphy_dt_match),
> +	},
> +};
> +
> +module_platform_driver(samsung_usb3_phy_driver);
> +
> +MODULE_DESCRIPTION("Samsung USB 3.0 phy controller");
> +MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
> +MODULE_LICENSE("GPL");
> +MODULE_ALIAS("platform:samsung-usb3-phy");

I want you to use same naming rule.

Thanks.

- Kukjin


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller
  2013-01-30  6:01     ` Kukjin Kim
@ 2013-01-30  8:20       ` Felipe Balbi
  2013-02-05  6:36       ` Vivek Gautam
  1 sibling, 0 replies; 14+ messages in thread
From: Felipe Balbi @ 2013-01-30  8:20 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: 'Vivek Gautam',
	linux-usb, linux-kernel, devicetree-discuss, linux-samsung-soc,
	gregkh, balbi, grant.likely, sylvester.nawrocki, tomasz.figa,
	av.tikhomirov, dianders, p.paneri

[-- Attachment #1: Type: text/plain, Size: 2174 bytes --]

On Tue, Jan 29, 2013 at 10:01:52PM -0800, Kukjin Kim wrote:
> Vivek Gautam wrote:
> > 
> > Adding PHY driver support for USB 3.0 controller for Samsung's
> > SoCs.
> > 
> > Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
> > ---
> > 
> > Changes from v3:
> >  - Making SAMSUNG_USB3PHY dependent on SAMSUNG_USBPHY.
> >  - Adding USB_DWC3 to dependencies of SAMSUNG_USB2PHY since
> >    dwc3 controller also looks for USB2 type PHY.
> > 
> >  drivers/usb/phy/Kconfig          |   11 +-
> >  drivers/usb/phy/Makefile         |    1 +
> >  drivers/usb/phy/samsung-usb3.c   |  349
> > ++++++++++++++++++++++++++++++++++++++
> >  drivers/usb/phy/samsung-usbphy.h |   81 +++++++++
> >  4 files changed, 441 insertions(+), 1 deletions(-)
> >  create mode 100644 drivers/usb/phy/samsung-usb3.c
> > 
> > diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
> > index cc0d230..9325a95 100644
> > --- a/drivers/usb/phy/Kconfig
> > +++ b/drivers/usb/phy/Kconfig
> > @@ -52,14 +52,23 @@ config SAMSUNG_USBPHY
> >  	help
> >  	  Enable this to support Samsung USB phy controllers for Samsung
> >  	  SoCs.
> > +	  Further enable USB 2.0 type PHY or USB 3.0 type PHY as required
> > +	  for USB controllers in use.
> > 
> >  if SAMSUNG_USBPHY
> > 
> >  config SAMSUNG_USB2PHY
> >  	bool "Samsung USB 2.0 PHY controller Driver"
> > -	depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
> > USB_OHCI_EXYNOS
> > +	depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
> > USB_OHCI_EXYNOS || USB_DWC3
> >  	help
> >  	  Enable this to support Samsung USB 2.0 (High Speed) phy controller
> >  	  for Samsung SoCs.
> > 
> > +config SAMSUNG_USB3PHY
> > +	bool "Samsung USB 3.0 PHY controller Driver"
> > +	depends on USB_DWC3
> > +	help
> > +	  Enable this to support Samsung USB 3.0 (Super Speed) phy
> > controller
> > +	  for samsung SoCs.
> > +
> >  endif
> 
> It mean, when USB_DWC3 is selected, we can select only one USB2PHY or
> USB3PHY?

right, not sure that's a wise idea. It makes enabling USB support
trickier than it needs to be. How about just dropping all dependencies
if it compiles cleanly on all arches ?

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 1/2] usb: phy: samsung: Common out the generic stuff
  2013-01-30  5:56     ` Kukjin Kim
@ 2013-02-05  6:32       ` Vivek Gautam
  0 siblings, 0 replies; 14+ messages in thread
From: Vivek Gautam @ 2013-02-05  6:32 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: Vivek Gautam, linux-usb, linux-kernel, devicetree-discuss,
	linux-samsung-soc, gregkh, balbi, grant.likely,
	sylvester.nawrocki, tomasz.figa, av.tikhomirov, dianders,
	p.paneri

Hi Kukjin,


On Wed, Jan 30, 2013 at 11:26 AM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> Vivek Gautam wrote:
>>
>> Moving register and structure definitions to header file,
>> and keeping the generic functions to be used across
>> multiple PHYs in common file "samsung-usbphy.c".
>> Also renaming the usb 2.0 phy driver to "samsung-usb2.c"
>
> Just in my opinion, Samsung-usb2phy is more clear?...In addition, I looked
> at using SAMSUNG_USB2PHY as a statement.
>

Sure will change the file names as suggested
samsung-usbphy.c : common PHY controller driver
samsung-usb2phy.c : USB 2.0 PHY controller driver

Will change the names for CONFIG_XX also accordingly.

>>
>> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
>> ---
>>
>> Changes from v3:
>>  - Using separate config SAMSUNG_USB2PHY dependent on
>>    SAMSUNG_USBPHY for samsung-usb2 type PHY controller.
>>
>>  drivers/usb/phy/Kconfig          |   14 +-
>>  drivers/usb/phy/Makefile         |    1 +
>>  drivers/usb/phy/samsung-usb2.c   |  511 +++++++++++++++++++++++++++
>>  drivers/usb/phy/samsung-usbphy.c |  714
> +-------------------------------------
>>  drivers/usb/phy/samsung-usbphy.h |  247 +++++++++++++
>>  5 files changed, 778 insertions(+), 709 deletions(-)
>>  create mode 100644 drivers/usb/phy/samsung-usb2.c
>>  create mode 100644 drivers/usb/phy/samsung-usbphy.h
>>
>> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
>> index fae4d08..cc0d230 100644
>> --- a/drivers/usb/phy/Kconfig
>> +++ b/drivers/usb/phy/Kconfig
>> @@ -48,8 +48,18 @@ config USB_RCAR_PHY
>>
>>  config SAMSUNG_USBPHY
>>       bool "Samsung USB PHY controller Driver"
>> -     depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
>> USB_OHCI_EXYNOS
>
> So this can be selected without any dependency?
>

The idea was SAMSUNG_USBPHY is selected for usb2 type PHY as well as
usb 3 type PHY.
But this seems to be bad :-(
Better we do something like this ?

config SAMSUNG_USB2
        bool "Samsung USB 2.0 PHY controller Driver"
        select SAMSUNG_USBPHY
        select USB_OTG_UTILS
        help
          Enable this to support Samsung USB 2.0 (High Speed) PHY controller
          driver for Samsung SoCs.

config SAMSUNG_USBPHY
        bool "Samsung USB PHY controller Driver"
        help
          Enable this to support Samsung USB phy helper driver for Samsung SoCs.
          This driver provides common interface for Samsung USB 2.0 PHY driver
          and later for Samsung USB 3.0 PHY driver.

>>       select USB_OTG_UTILS
>>       help
>> -       Enable this to support Samsung USB phy controller for samsung
>> +       Enable this to support Samsung USB phy controllers for Samsung
>>         SoCs.
>
> Hmm, according to above comments, this should be enabled under Samsung SoC?
>

May we just add these configs under USB as mentioned above ?

>> +
>> +if SAMSUNG_USBPHY
>
> Why is this needed here?
>

We will not need this if we change to something like mentioned above.

>> +
>> +config SAMSUNG_USB2PHY
>> +     bool "Samsung USB 2.0 PHY controller Driver"
>> +     depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
>> USB_OHCI_EXYNOS
>> +     help
>> +       Enable this to support Samsung USB 2.0 (High Speed) phy controller
>> +       for Samsung SoCs.
>> +
>> +endif
>> diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
>> index ec304f6..7ba9862 100644
>> --- a/drivers/usb/phy/Makefile
>> +++ b/drivers/usb/phy/Makefile
>> @@ -10,3 +10,4 @@ obj-$(CONFIG_MV_U3D_PHY)            +=
>> mv_u3d_phy.o
>>  obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o
>>  obj-$(CONFIG_USB_RCAR_PHY)           += rcar-phy.o
>>  obj-$(CONFIG_SAMSUNG_USBPHY)         += samsung-usbphy.o
>> +obj-$(CONFIG_SAMSUNG_USB2PHY)                += samsung-usb2.o
>> diff --git a/drivers/usb/phy/samsung-usb2.c b/drivers/usb/phy/samsung-
>> usb2.c
>> new file mode 100644
>> index 0000000..9a9d1d0
>> --- /dev/null
>> +++ b/drivers/usb/phy/samsung-usb2.c
>> @@ -0,0 +1,511 @@
>> +/* linux/drivers/usb/phy/samsung-usb2.c
>> + *
>> + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
>> + *              http://www.samsung.com
>> + *
>> + * Author: Praveen Paneri <p.paneri@samsung.com>
>> + *
>> + * Samsung USB2.0 PHY transceiver; talks to S3C HS OTG controller,
> EHCI-S5P
>> and
>> + * OHCI-EXYNOS controllers.
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + */
>> +
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/clk.h>
>> +#include <linux/delay.h>
>> +#include <linux/device.h>
>> +#include <linux/err.h>
>> +#include <linux/io.h>
>> +#include <linux/of.h>
>> +#include <linux/usb/otg.h>
>> +#include <linux/usb/samsung_usb_phy.h>
>> +#include <linux/platform_data/samsung-usbphy.h>
>> +
>> +#include "samsung-usbphy.h"
>> +
>> +int samsung_usbphy_set_host(struct usb_otg *otg, struct usb_bus *host)
>
> For naming, if you want to support usb 2.0 phy here, the name of fuction
> should be changed to more clear name such as usb2phy or whatever.
>
> As I'm understanding, the samsung-usbphy.c can be used for common stuff and
> this is for only usb 2.0 phy.
>

True.
Will keep the naming as suggested. usb2phy naming for functions
specific to SAMSUNG_USB2PHY

> [...]
>
>> +#ifdef CONFIG_OF
>> +static const struct of_device_id samsung_usbphy_dt_match[] = {
>> +     {
>> +             .compatible = "samsung,s3c64xx-usbphy",
>> +             .data = &usbphy_s3c64xx,
>> +     }, {
>> +             .compatible = "samsung,exynos4210-usbphy",
>> +             .data = &usbphy_exynos4,
>> +     }, {
>> +             .compatible = "samsung,exynos5250-usbphy",
>> +             .data = &usbphy_exynos5
>> +     },
>> +     {},
>> +};
>> +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
>> +#endif
>> +
>> +static struct platform_device_id samsung_usbphy_driver_ids[] = {
>> +     {
>> +             .name           = "s3c64xx-usbphy",
>> +             .driver_data    = (unsigned long)&usbphy_s3c64xx,
>> +     }, {
>> +             .name           = "exynos4210-usbphy",
>> +             .driver_data    = (unsigned long)&usbphy_exynos4,
>> +     }, {
>> +             .name           = "exynos5250-usbphy",
>> +             .driver_data    = (unsigned long)&usbphy_exynos5,
>> +     },
>> +     {},
>> +};
>> +
>> +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
>> +
>> +static struct platform_driver samsung_usbphy_driver = {
>> +     .probe          = samsung_usbphy_probe,
>> +     .remove         = samsung_usbphy_remove,
>> +     .id_table       = samsung_usbphy_driver_ids,
>> +     .driver         = {
>> +             .name   = "samsung-usbphy",
>> +             .owner  = THIS_MODULE,
>> +             .of_match_table =
>> of_match_ptr(samsung_usbphy_dt_match),
>> +     },
>> +};
>> +
>> +module_platform_driver(samsung_usbphy_driver);
>> +
>> +MODULE_DESCRIPTION("Samsung USB phy controller");
>
> USB 2.0 Phy?
>

Yes, will amend this.

>> +MODULE_AUTHOR("Praveen Paneri <p.paneri@samsung.com>");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("platform:samsung-usbphy");
>
> Is this for samsung-usbphy or samsung-usb2/samsung-usb2phy?
>

Must be changed to samsung-usb2phy.

> [...]
>
> I know why you create separated phy file samsung-usbphy.c and samsung-usb2.c
> here, but I think for that, would be better if you could consider the name
> and so on.
>

Yes, sure will keep the naming convention as suggested.


-- 
Thanks & Regards
Vivek

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH v4 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller
  2013-01-30  6:01     ` Kukjin Kim
  2013-01-30  8:20       ` Felipe Balbi
@ 2013-02-05  6:36       ` Vivek Gautam
  1 sibling, 0 replies; 14+ messages in thread
From: Vivek Gautam @ 2013-02-05  6:36 UTC (permalink / raw)
  To: Kukjin Kim
  Cc: Vivek Gautam, linux-usb, linux-kernel, devicetree-discuss,
	linux-samsung-soc, gregkh, balbi, grant.likely,
	sylvester.nawrocki, tomasz.figa, av.tikhomirov, dianders,
	p.paneri

Hi Kukjin,


On Wed, Jan 30, 2013 at 11:31 AM, Kukjin Kim <kgene.kim@samsung.com> wrote:
> Vivek Gautam wrote:
>>
>> Adding PHY driver support for USB 3.0 controller for Samsung's
>> SoCs.
>>
>> Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
>> ---
>>
>> Changes from v3:
>>  - Making SAMSUNG_USB3PHY dependent on SAMSUNG_USBPHY.
>>  - Adding USB_DWC3 to dependencies of SAMSUNG_USB2PHY since
>>    dwc3 controller also looks for USB2 type PHY.
>>
>>  drivers/usb/phy/Kconfig          |   11 +-
>>  drivers/usb/phy/Makefile         |    1 +
>>  drivers/usb/phy/samsung-usb3.c   |  349
>> ++++++++++++++++++++++++++++++++++++++
>>  drivers/usb/phy/samsung-usbphy.h |   81 +++++++++
>>  4 files changed, 441 insertions(+), 1 deletions(-)
>>  create mode 100644 drivers/usb/phy/samsung-usb3.c
>>
>> diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
>> index cc0d230..9325a95 100644
>> --- a/drivers/usb/phy/Kconfig
>> +++ b/drivers/usb/phy/Kconfig
>> @@ -52,14 +52,23 @@ config SAMSUNG_USBPHY
>>       help
>>         Enable this to support Samsung USB phy controllers for Samsung
>>         SoCs.
>> +       Further enable USB 2.0 type PHY or USB 3.0 type PHY as required
>> +       for USB controllers in use.
>>
>>  if SAMSUNG_USBPHY
>>
>>  config SAMSUNG_USB2PHY
>>       bool "Samsung USB 2.0 PHY controller Driver"
>> -     depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
>> USB_OHCI_EXYNOS
>> +     depends on USB_S3C_HSOTG || USB_EHCI_S5P ||
>> USB_OHCI_EXYNOS || USB_DWC3
>>       help
>>         Enable this to support Samsung USB 2.0 (High Speed) phy controller
>>         for Samsung SoCs.
>>
>> +config SAMSUNG_USB3PHY
>> +     bool "Samsung USB 3.0 PHY controller Driver"
>> +     depends on USB_DWC3
>> +     help
>> +       Enable this to support Samsung USB 3.0 (Super Speed) phy
>> controller
>> +       for samsung SoCs.
>> +
>>  endif
>
> It mean, when USB_DWC3 is selected, we can select only one USB2PHY or
> USB3PHY?
>

Actually, DWC3 expects both USB2PHY and USB3PHY, so went this way.
But this seems bad :-(
Will remove these dependencies as suggested by Felipe also.

> [...]
>
>> +#ifdef CONFIG_OF
>> +static const struct of_device_id samsung_usbphy_dt_match[] = {
>> +     {
>> +             .compatible = "samsung,exynos5250-usb3-phy",
>> +             .data = &usb3_phy_exynos5
>> +     },
>> +     {},
>> +};
>> +MODULE_DEVICE_TABLE(of, samsung_usbphy_dt_match);
>> +#endif
>> +
>> +static struct platform_device_id samsung_usbphy_driver_ids[] = {
>> +     {
>> +             .name           = "exynos5250-usb3-phy",
>
> According to the name of file, exynos5250-usb3phy? Just it is imho...
>

Ok, sure will amend this.

>> +             .driver_data    = (unsigned long)&usb3_phy_exynos5,
>> +     },
>> +     {},
>> +};
>> +
>> +MODULE_DEVICE_TABLE(platform, samsung_usbphy_driver_ids);
>> +
>> +static struct platform_driver samsung_usb3_phy_driver = {
>> +     .probe          = samsung_usb3_phy_probe,
>> +     .remove         = samsung_usb3_phy_remove,
>> +     .id_table       = samsung_usbphy_driver_ids,
>> +     .driver         = {
>> +             .name   = "samsung-usb3-phy",
>> +             .owner  = THIS_MODULE,
>> +             .of_match_table =
>> of_match_ptr(samsung_usbphy_dt_match),
>> +     },
>> +};
>> +
>> +module_platform_driver(samsung_usb3_phy_driver);
>> +
>> +MODULE_DESCRIPTION("Samsung USB 3.0 phy controller");
>> +MODULE_AUTHOR("Vivek Gautam <gautam.vivek@samsung.com>");
>> +MODULE_LICENSE("GPL");
>> +MODULE_ALIAS("platform:samsung-usb3-phy");
>
> I want you to use same naming rule.
>

Sure.


-- 
Thanks & Regards
Vivek

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2013-02-05  6:37 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-14 12:59 [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250 Vivek Gautam
2013-01-14 12:59 ` [PATCH v3 1/2] usb: phy: samsung: Common out the generic stuff Vivek Gautam
2013-01-28 10:24   ` [PATCH v4 " Vivek Gautam
2013-01-29  5:34     ` Vivek Gautam
2013-01-30  5:56     ` Kukjin Kim
2013-02-05  6:32       ` Vivek Gautam
2013-01-14 12:59 ` [PATCH v3 2/2] usb: phy: samsung: Add PHY support for USB 3.0 controller Vivek Gautam
2013-01-28 10:26   ` [PATCH v4 " Vivek Gautam
2013-01-29  5:35     ` Vivek Gautam
2013-01-30  6:01     ` Kukjin Kim
2013-01-30  8:20       ` Felipe Balbi
2013-02-05  6:36       ` Vivek Gautam
2013-01-21  6:45 ` [PATCH v3 0/2] Adding USB 3.0 DRD-phy support for exynos5250 Vivek Gautam
2013-01-21  8:26   ` Felipe Balbi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).