From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Fri, 8 Aug 2014 18:34:32 +0000 (-0700)
Subject: Merge tag 'drivers-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/arm... 
X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=10c8e0562057b5d64ea170feab148e1550420030;p=linux.git

Merge tag 'drivers-for-3.17' of git://git./linux/kernel/git/arm/arm-soc

Pull ARM SoC driver changes from Olof Johansson:
 "A handful of driver-related changes.  We've had a bunch of them going
  in through other branches as well, so it's only a part of what we
  really have this release.

  Larger pieces are:

   - Removal of a now unused PWM driver for atmel
     [ This includes AVR32 changes that have been appropriately acked ]
   - Performance counter support for the arm CCN interconnect
   - OMAP mailbox driver cleanups and consolidation
   - PCI and SATA PHY drivers for SPEAr 13xx platforms
   - Redefinition (with backwards compatibility!) of PCI DT bindings for
     Tegra to better model regulators/power"

Note: this merge also fixes up the semantic conflict with the new
calling convention for devm_phy_create(), see commit f0ed817638b5 ("phy:
core: Let node ptr of PHY point to PHY and not of PHY provider") that
came in through Greg's USB tree.

Semantic merge patch by Stephen Rothwell <sfr@canb.auug.org.au> through
the next tree.

* tag 'drivers-for-3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (38 commits)
  bus: arm-ccn: Fix error handling at event allocation
  mailbox/omap: add a parent structure for every IP instance
  mailbox/omap: remove the private mailbox structure
  mailbox/omap: consolidate OMAP mailbox driver
  mailbox/omap: simplify the fifo assignment by using macros
  mailbox/omap: remove omap_mbox_type_t from mailbox ops
  mailbox/omap: remove OMAP1 mailbox driver
  mailbox/omap: use devm_* interfaces
  bus: ARM CCN: add PERF_EVENTS dependency
  bus: ARM CCN PMU driver
  PCI: spear: Remove spear13xx_pcie_remove()
  PCI: spear: Fix Section mismatch compilation warning for probe()
  ARM: tegra: Remove legacy PCIe power supply properties
  PCI: tegra: Remove deprecated power supply properties
  PCI: tegra: Implement accurate power supply scheme
  ARM: SPEAr13xx: Update defconfigs
  ARM: SPEAr13xx: Add pcie and miphy DT nodes
  ARM: SPEAr13xx: Add bindings and dt node for misc block
  ARM: SPEAr13xx: Fix static mapping table
  phy: Add drivers for PCIe and SATA phy on SPEAr13xx
  ...
---

10c8e0562057b5d64ea170feab148e1550420030
diff --cc drivers/phy/Kconfig
index d1f5fc924c936,e8f8a2d165d19..0dd742719154a
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@@ -197,25 -171,23 +197,37 @@@ config PHY_EXYNOS5_USBDR
  	  This driver provides PHY interface for USB 3.0 DRD controller
  	  present on Exynos5 SoC series.
  
--config PHY_XGENE
--	tristate "APM X-Gene 15Gbps PHY support"
--	depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
- 	select GENERIC_PHY
- 	help
- 	  This option enables support for APM X-Gene SoC multi-purpose PHY.
- 
 +config PHY_QCOM_APQ8064_SATA
 +	tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
 +	depends on ARCH_QCOM
 +	depends on HAS_IOMEM
 +	depends on OF
 +	select GENERIC_PHY
 +
 +config PHY_QCOM_IPQ806X_SATA
 +	tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
 +	depends on ARCH_QCOM
 +	depends on HAS_IOMEM
 +	depends on OF
  	select GENERIC_PHY
 -	help
 -	  This option enables support for APM X-Gene SoC multi-purpose PHY.
  
+ config PHY_ST_SPEAR1310_MIPHY
+ 	tristate "ST SPEAR1310-MIPHY driver"
+ 	select GENERIC_PHY
+ 	help
+ 	  Support for ST SPEAr1310 MIPHY which can be used for PCIe and SATA.
+ 
+ config PHY_ST_SPEAR1340_MIPHY
+ 	tristate "ST SPEAR1340-MIPHY driver"
+ 	select GENERIC_PHY
+ 	help
+ 	  Support for ST SPEAr1340 MIPHY which can be used for PCIe and SATA.
+ 
++config PHY_XGENE
++	tristate "APM X-Gene 15Gbps PHY support"
++	depends on HAS_IOMEM && OF && (ARM64 || COMPILE_TEST)
++	select GENERIC_PHY
++	help
++	  This option enables support for APM X-Gene SoC multi-purpose PHY.
++
  endmenu
diff --cc drivers/phy/Makefile
index ec24e915349b7,d39609bb38dec..95c69ed5ed451
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@@ -21,8 -18,7 +21,10 @@@ phy-exynos-usb2-y			+= phy-samsung-usb2
  phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2)	+= phy-exynos4210-usb2.o
  phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2)	+= phy-exynos4x12-usb2.o
  phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2)	+= phy-exynos5250-usb2.o
 +phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2)	+= phy-s5pv210-usb2.o
  obj-$(CONFIG_PHY_EXYNOS5_USBDRD)	+= phy-exynos5-usbdrd.o
--obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
 +obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
 +obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
+ obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY)	+= phy-spear1310-miphy.o
+ obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY)	+= phy-spear1340-miphy.o
++obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
diff --cc drivers/phy/phy-spear1310-miphy.c
index 0000000000000,c58c869d57e05..6dcbfcddb3723
mode 000000,100644..100644
--- a/drivers/phy/phy-spear1310-miphy.c
+++ b/drivers/phy/phy-spear1310-miphy.c
@@@ -1,0 -1,274 +1,274 @@@
+ /*
+  * ST SPEAr1310-miphy driver
+  *
+  * Copyright (C) 2014 ST Microelectronics
+  * Pratyush Anand <pratyush.anand@st.com>
+  * Mohit Kumar <mohit.kumar@st.com>
+  *
+  * 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.
+  *
+  */
+ 
+ #include <linux/bitops.h>
+ #include <linux/delay.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/kernel.h>
+ #include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+ #include <linux/of_device.h>
+ #include <linux/phy/phy.h>
+ #include <linux/regmap.h>
+ 
+ /* SPEAr1310 Registers */
+ #define SPEAR1310_PCIE_SATA_CFG			0x3A4
+ 	#define SPEAR1310_PCIE_SATA2_SEL_PCIE		(0 << 31)
+ 	#define SPEAR1310_PCIE_SATA1_SEL_PCIE		(0 << 30)
+ 	#define SPEAR1310_PCIE_SATA0_SEL_PCIE		(0 << 29)
+ 	#define SPEAR1310_PCIE_SATA2_SEL_SATA		BIT(31)
+ 	#define SPEAR1310_PCIE_SATA1_SEL_SATA		BIT(30)
+ 	#define SPEAR1310_PCIE_SATA0_SEL_SATA		BIT(29)
+ 	#define SPEAR1310_SATA2_CFG_TX_CLK_EN		BIT(27)
+ 	#define SPEAR1310_SATA2_CFG_RX_CLK_EN		BIT(26)
+ 	#define SPEAR1310_SATA2_CFG_POWERUP_RESET	BIT(25)
+ 	#define SPEAR1310_SATA2_CFG_PM_CLK_EN		BIT(24)
+ 	#define SPEAR1310_SATA1_CFG_TX_CLK_EN		BIT(23)
+ 	#define SPEAR1310_SATA1_CFG_RX_CLK_EN		BIT(22)
+ 	#define SPEAR1310_SATA1_CFG_POWERUP_RESET	BIT(21)
+ 	#define SPEAR1310_SATA1_CFG_PM_CLK_EN		BIT(20)
+ 	#define SPEAR1310_SATA0_CFG_TX_CLK_EN		BIT(19)
+ 	#define SPEAR1310_SATA0_CFG_RX_CLK_EN		BIT(18)
+ 	#define SPEAR1310_SATA0_CFG_POWERUP_RESET	BIT(17)
+ 	#define SPEAR1310_SATA0_CFG_PM_CLK_EN		BIT(16)
+ 	#define SPEAR1310_PCIE2_CFG_DEVICE_PRESENT	BIT(11)
+ 	#define SPEAR1310_PCIE2_CFG_POWERUP_RESET	BIT(10)
+ 	#define SPEAR1310_PCIE2_CFG_CORE_CLK_EN		BIT(9)
+ 	#define SPEAR1310_PCIE2_CFG_AUX_CLK_EN		BIT(8)
+ 	#define SPEAR1310_PCIE1_CFG_DEVICE_PRESENT	BIT(7)
+ 	#define SPEAR1310_PCIE1_CFG_POWERUP_RESET	BIT(6)
+ 	#define SPEAR1310_PCIE1_CFG_CORE_CLK_EN		BIT(5)
+ 	#define SPEAR1310_PCIE1_CFG_AUX_CLK_EN		BIT(4)
+ 	#define SPEAR1310_PCIE0_CFG_DEVICE_PRESENT	BIT(3)
+ 	#define SPEAR1310_PCIE0_CFG_POWERUP_RESET	BIT(2)
+ 	#define SPEAR1310_PCIE0_CFG_CORE_CLK_EN		BIT(1)
+ 	#define SPEAR1310_PCIE0_CFG_AUX_CLK_EN		BIT(0)
+ 
+ 	#define SPEAR1310_PCIE_CFG_MASK(x) ((0xF << (x * 4)) | BIT((x + 29)))
+ 	#define SPEAR1310_SATA_CFG_MASK(x) ((0xF << (x * 4 + 16)) | \
+ 			BIT((x + 29)))
+ 	#define SPEAR1310_PCIE_CFG_VAL(x) \
+ 			(SPEAR1310_PCIE_SATA##x##_SEL_PCIE | \
+ 			SPEAR1310_PCIE##x##_CFG_AUX_CLK_EN | \
+ 			SPEAR1310_PCIE##x##_CFG_CORE_CLK_EN | \
+ 			SPEAR1310_PCIE##x##_CFG_POWERUP_RESET | \
+ 			SPEAR1310_PCIE##x##_CFG_DEVICE_PRESENT)
+ 	#define SPEAR1310_SATA_CFG_VAL(x) \
+ 			(SPEAR1310_PCIE_SATA##x##_SEL_SATA | \
+ 			SPEAR1310_SATA##x##_CFG_PM_CLK_EN | \
+ 			SPEAR1310_SATA##x##_CFG_POWERUP_RESET | \
+ 			SPEAR1310_SATA##x##_CFG_RX_CLK_EN | \
+ 			SPEAR1310_SATA##x##_CFG_TX_CLK_EN)
+ 
+ #define SPEAR1310_PCIE_MIPHY_CFG_1		0x3A8
+ 	#define SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT	BIT(31)
+ 	#define SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2	BIT(28)
+ 	#define SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(x)	(x << 16)
+ 	#define SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT	BIT(15)
+ 	#define SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2	BIT(12)
+ 	#define SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(x)	(x << 0)
+ 	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_MASK (0xFFFF)
+ 	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK (0xFFFF << 16)
+ 	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA \
+ 			(SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+ 			SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 | \
+ 			SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(60) | \
+ 			SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+ 			SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 | \
+ 			SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(60))
+ 	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+ 			(SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(120))
+ 	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE \
+ 			(SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+ 			SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(25) | \
+ 			SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+ 			SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(25))
+ 
+ #define SPEAR1310_PCIE_MIPHY_CFG_2		0x3AC
+ 
+ enum spear1310_miphy_mode {
+ 	SATA,
+ 	PCIE,
+ };
+ 
+ struct spear1310_miphy_priv {
+ 	/* instance id of this phy */
+ 	u32				id;
+ 	/* phy mode: 0 for SATA 1 for PCIe */
+ 	enum spear1310_miphy_mode	mode;
+ 	/* regmap for any soc specific misc registers */
+ 	struct regmap			*misc;
+ 	/* phy struct pointer */
+ 	struct phy			*phy;
+ };
+ 
+ static int spear1310_miphy_pcie_init(struct spear1310_miphy_priv *priv)
+ {
+ 	u32 val;
+ 
+ 	regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+ 			   SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK,
+ 			   SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE);
+ 
+ 	switch (priv->id) {
+ 	case 0:
+ 		val = SPEAR1310_PCIE_CFG_VAL(0);
+ 		break;
+ 	case 1:
+ 		val = SPEAR1310_PCIE_CFG_VAL(1);
+ 		break;
+ 	case 2:
+ 		val = SPEAR1310_PCIE_CFG_VAL(2);
+ 		break;
+ 	default:
+ 		return -EINVAL;
+ 	}
+ 
+ 	regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
+ 			   SPEAR1310_PCIE_CFG_MASK(priv->id), val);
+ 
+ 	return 0;
+ }
+ 
+ static int spear1310_miphy_pcie_exit(struct spear1310_miphy_priv *priv)
+ {
+ 	regmap_update_bits(priv->misc, SPEAR1310_PCIE_SATA_CFG,
+ 			   SPEAR1310_PCIE_CFG_MASK(priv->id), 0);
+ 
+ 	regmap_update_bits(priv->misc, SPEAR1310_PCIE_MIPHY_CFG_1,
+ 			   SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK, 0);
+ 
+ 	return 0;
+ }
+ 
+ static int spear1310_miphy_init(struct phy *phy)
+ {
+ 	struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
+ 	int ret = 0;
+ 
+ 	if (priv->mode == PCIE)
+ 		ret = spear1310_miphy_pcie_init(priv);
+ 
+ 	return ret;
+ }
+ 
+ static int spear1310_miphy_exit(struct phy *phy)
+ {
+ 	struct spear1310_miphy_priv *priv = phy_get_drvdata(phy);
+ 	int ret = 0;
+ 
+ 	if (priv->mode == PCIE)
+ 		ret = spear1310_miphy_pcie_exit(priv);
+ 
+ 	return ret;
+ }
+ 
+ static const struct of_device_id spear1310_miphy_of_match[] = {
+ 	{ .compatible = "st,spear1310-miphy" },
+ 	{ },
+ };
+ MODULE_DEVICE_TABLE(of, spear1310_miphy_of_match);
+ 
+ static struct phy_ops spear1310_miphy_ops = {
+ 	.init = spear1310_miphy_init,
+ 	.exit = spear1310_miphy_exit,
+ 	.owner = THIS_MODULE,
+ };
+ 
+ static struct phy *spear1310_miphy_xlate(struct device *dev,
+ 					 struct of_phandle_args *args)
+ {
+ 	struct spear1310_miphy_priv *priv = dev_get_drvdata(dev);
+ 
+ 	if (args->args_count < 1) {
+ 		dev_err(dev, "DT did not pass correct no of args\n");
+ 		return NULL;
+ 	}
+ 
+ 	priv->mode = args->args[0];
+ 
+ 	if (priv->mode != SATA && priv->mode != PCIE) {
+ 		dev_err(dev, "DT did not pass correct phy mode\n");
+ 		return NULL;
+ 	}
+ 
+ 	return priv->phy;
+ }
+ 
+ static int spear1310_miphy_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct spear1310_miphy_priv *priv;
+ 	struct phy_provider *phy_provider;
+ 
+ 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ 	if (!priv) {
+ 		dev_err(dev, "can't alloc spear1310_miphy private date memory\n");
+ 		return -ENOMEM;
+ 	}
+ 
+ 	priv->misc =
+ 		syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
+ 	if (IS_ERR(priv->misc)) {
+ 		dev_err(dev, "failed to find misc regmap\n");
+ 		return PTR_ERR(priv->misc);
+ 	}
+ 
+ 	if (of_property_read_u32(dev->of_node, "phy-id", &priv->id)) {
+ 		dev_err(dev, "failed to find phy id\n");
+ 		return -EINVAL;
+ 	}
+ 
 -	priv->phy = devm_phy_create(dev, &spear1310_miphy_ops, NULL);
++	priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops, NULL);
+ 	if (IS_ERR(priv->phy)) {
+ 		dev_err(dev, "failed to create SATA PCIe PHY\n");
+ 		return PTR_ERR(priv->phy);
+ 	}
+ 
+ 	dev_set_drvdata(dev, priv);
+ 	phy_set_drvdata(priv->phy, priv);
+ 
+ 	phy_provider =
+ 		devm_of_phy_provider_register(dev, spear1310_miphy_xlate);
+ 	if (IS_ERR(phy_provider)) {
+ 		dev_err(dev, "failed to register phy provider\n");
+ 		return PTR_ERR(phy_provider);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ static struct platform_driver spear1310_miphy_driver = {
+ 	.probe		= spear1310_miphy_probe,
+ 	.driver = {
+ 		.name = "spear1310-miphy",
+ 		.owner = THIS_MODULE,
+ 		.of_match_table = of_match_ptr(spear1310_miphy_of_match),
+ 	},
+ };
+ 
+ static int __init spear1310_miphy_phy_init(void)
+ {
+ 	return platform_driver_register(&spear1310_miphy_driver);
+ }
+ module_init(spear1310_miphy_phy_init);
+ 
+ static void __exit spear1310_miphy_phy_exit(void)
+ {
+ 	platform_driver_unregister(&spear1310_miphy_driver);
+ }
+ module_exit(spear1310_miphy_phy_exit);
+ 
+ MODULE_DESCRIPTION("ST SPEAR1310-MIPHY driver");
+ MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
+ MODULE_LICENSE("GPL v2");
diff --cc drivers/phy/phy-spear1340-miphy.c
index 0000000000000,8de98adf21c36..7135ba2603b6e
mode 000000,100644..100644
--- a/drivers/phy/phy-spear1340-miphy.c
+++ b/drivers/phy/phy-spear1340-miphy.c
@@@ -1,0 -1,307 +1,307 @@@
+ /*
+  * ST spear1340-miphy driver
+  *
+  * Copyright (C) 2014 ST Microelectronics
+  * Pratyush Anand <pratyush.anand@st.com>
+  * Mohit Kumar <mohit.kumar@st.com>
+  *
+  * 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.
+  *
+  */
+ 
+ #include <linux/bitops.h>
+ #include <linux/delay.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/kernel.h>
+ #include <linux/mfd/syscon.h>
+ #include <linux/module.h>
+ #include <linux/of_device.h>
+ #include <linux/phy/phy.h>
+ #include <linux/regmap.h>
+ 
+ /* SPEAr1340 Registers */
+ /* Power Management Registers */
+ #define SPEAR1340_PCM_CFG			0x100
+ 	#define SPEAR1340_PCM_CFG_SATA_POWER_EN		BIT(11)
+ #define SPEAR1340_PCM_WKUP_CFG			0x104
+ #define SPEAR1340_SWITCH_CTR			0x108
+ 
+ #define SPEAR1340_PERIP1_SW_RST			0x318
+ 	#define SPEAR1340_PERIP1_SW_RSATA		BIT(12)
+ #define SPEAR1340_PERIP2_SW_RST			0x31C
+ #define SPEAR1340_PERIP3_SW_RST			0x320
+ 
+ /* PCIE - SATA configuration registers */
+ #define SPEAR1340_PCIE_SATA_CFG			0x424
+ 	/* PCIE CFG MASks */
+ 	#define SPEAR1340_PCIE_CFG_DEVICE_PRESENT	BIT(11)
+ 	#define SPEAR1340_PCIE_CFG_POWERUP_RESET	BIT(10)
+ 	#define SPEAR1340_PCIE_CFG_CORE_CLK_EN		BIT(9)
+ 	#define SPEAR1340_PCIE_CFG_AUX_CLK_EN		BIT(8)
+ 	#define SPEAR1340_SATA_CFG_TX_CLK_EN		BIT(4)
+ 	#define SPEAR1340_SATA_CFG_RX_CLK_EN		BIT(3)
+ 	#define SPEAR1340_SATA_CFG_POWERUP_RESET	BIT(2)
+ 	#define SPEAR1340_SATA_CFG_PM_CLK_EN		BIT(1)
+ 	#define SPEAR1340_PCIE_SATA_SEL_PCIE		(0)
+ 	#define SPEAR1340_PCIE_SATA_SEL_SATA		(1)
+ 	#define SPEAR1340_PCIE_SATA_CFG_MASK		0xF1F
+ 	#define SPEAR1340_PCIE_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_PCIE | \
+ 			SPEAR1340_PCIE_CFG_AUX_CLK_EN | \
+ 			SPEAR1340_PCIE_CFG_CORE_CLK_EN | \
+ 			SPEAR1340_PCIE_CFG_POWERUP_RESET | \
+ 			SPEAR1340_PCIE_CFG_DEVICE_PRESENT)
+ 	#define SPEAR1340_SATA_CFG_VAL	(SPEAR1340_PCIE_SATA_SEL_SATA | \
+ 			SPEAR1340_SATA_CFG_PM_CLK_EN | \
+ 			SPEAR1340_SATA_CFG_POWERUP_RESET | \
+ 			SPEAR1340_SATA_CFG_RX_CLK_EN | \
+ 			SPEAR1340_SATA_CFG_TX_CLK_EN)
+ 
+ #define SPEAR1340_PCIE_MIPHY_CFG		0x428
+ 	#define SPEAR1340_MIPHY_OSC_BYPASS_EXT		BIT(31)
+ 	#define SPEAR1340_MIPHY_CLK_REF_DIV2		BIT(27)
+ 	#define SPEAR1340_MIPHY_CLK_REF_DIV4		(2 << 27)
+ 	#define SPEAR1340_MIPHY_CLK_REF_DIV8		(3 << 27)
+ 	#define SPEAR1340_MIPHY_PLL_RATIO_TOP(x)	(x << 0)
+ 	#define SPEAR1340_PCIE_MIPHY_CFG_MASK		0xF80000FF
+ 	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA \
+ 			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+ 			SPEAR1340_MIPHY_CLK_REF_DIV2 | \
+ 			SPEAR1340_MIPHY_PLL_RATIO_TOP(60))
+ 	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+ 			(SPEAR1340_MIPHY_PLL_RATIO_TOP(120))
+ 	#define SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE \
+ 			(SPEAR1340_MIPHY_OSC_BYPASS_EXT | \
+ 			SPEAR1340_MIPHY_PLL_RATIO_TOP(25))
+ 
+ enum spear1340_miphy_mode {
+ 	SATA,
+ 	PCIE,
+ };
+ 
+ struct spear1340_miphy_priv {
+ 	/* phy mode: 0 for SATA 1 for PCIe */
+ 	enum spear1340_miphy_mode	mode;
+ 	/* regmap for any soc specific misc registers */
+ 	struct regmap			*misc;
+ 	/* phy struct pointer */
+ 	struct phy			*phy;
+ };
+ 
+ static int spear1340_miphy_sata_init(struct spear1340_miphy_priv *priv)
+ {
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+ 			   SPEAR1340_PCIE_SATA_CFG_MASK,
+ 			   SPEAR1340_SATA_CFG_VAL);
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+ 			   SPEAR1340_PCIE_MIPHY_CFG_MASK,
+ 			   SPEAR1340_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK);
+ 	/* Switch on sata power domain */
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
+ 			   SPEAR1340_PCM_CFG_SATA_POWER_EN,
+ 			   SPEAR1340_PCM_CFG_SATA_POWER_EN);
+ 	/* Wait for SATA power domain on */
+ 	msleep(20);
+ 
+ 	/* Disable PCIE SATA Controller reset */
+ 	regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
+ 			   SPEAR1340_PERIP1_SW_RSATA, 0);
+ 	/* Wait for SATA reset de-assert completion */
+ 	msleep(20);
+ 
+ 	return 0;
+ }
+ 
+ static int spear1340_miphy_sata_exit(struct spear1340_miphy_priv *priv)
+ {
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+ 			   SPEAR1340_PCIE_SATA_CFG_MASK, 0);
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+ 			   SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
+ 
+ 	/* Enable PCIE SATA Controller reset */
+ 	regmap_update_bits(priv->misc, SPEAR1340_PERIP1_SW_RST,
+ 			   SPEAR1340_PERIP1_SW_RSATA,
+ 			   SPEAR1340_PERIP1_SW_RSATA);
+ 	/* Wait for SATA power domain off */
+ 	msleep(20);
+ 	/* Switch off sata power domain */
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCM_CFG,
+ 			   SPEAR1340_PCM_CFG_SATA_POWER_EN, 0);
+ 	/* Wait for SATA reset assert completion */
+ 	msleep(20);
+ 
+ 	return 0;
+ }
+ 
+ static int spear1340_miphy_pcie_init(struct spear1340_miphy_priv *priv)
+ {
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+ 			   SPEAR1340_PCIE_MIPHY_CFG_MASK,
+ 			   SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE);
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+ 			   SPEAR1340_PCIE_SATA_CFG_MASK,
+ 			   SPEAR1340_PCIE_CFG_VAL);
+ 
+ 	return 0;
+ }
+ 
+ static int spear1340_miphy_pcie_exit(struct spear1340_miphy_priv *priv)
+ {
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCIE_MIPHY_CFG,
+ 			   SPEAR1340_PCIE_MIPHY_CFG_MASK, 0);
+ 	regmap_update_bits(priv->misc, SPEAR1340_PCIE_SATA_CFG,
+ 			   SPEAR1340_PCIE_SATA_CFG_MASK, 0);
+ 
+ 	return 0;
+ }
+ 
+ static int spear1340_miphy_init(struct phy *phy)
+ {
+ 	struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
+ 	int ret = 0;
+ 
+ 	if (priv->mode == SATA)
+ 		ret = spear1340_miphy_sata_init(priv);
+ 	else if (priv->mode == PCIE)
+ 		ret = spear1340_miphy_pcie_init(priv);
+ 
+ 	return ret;
+ }
+ 
+ static int spear1340_miphy_exit(struct phy *phy)
+ {
+ 	struct spear1340_miphy_priv *priv = phy_get_drvdata(phy);
+ 	int ret = 0;
+ 
+ 	if (priv->mode == SATA)
+ 		ret = spear1340_miphy_sata_exit(priv);
+ 	else if (priv->mode == PCIE)
+ 		ret = spear1340_miphy_pcie_exit(priv);
+ 
+ 	return ret;
+ }
+ 
+ static const struct of_device_id spear1340_miphy_of_match[] = {
+ 	{ .compatible = "st,spear1340-miphy" },
+ 	{ },
+ };
+ MODULE_DEVICE_TABLE(of, spear1340_miphy_of_match);
+ 
+ static struct phy_ops spear1340_miphy_ops = {
+ 	.init = spear1340_miphy_init,
+ 	.exit = spear1340_miphy_exit,
+ 	.owner = THIS_MODULE,
+ };
+ 
+ #ifdef CONFIG_PM_SLEEP
+ static int spear1340_miphy_suspend(struct device *dev)
+ {
+ 	struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+ 	int ret = 0;
+ 
+ 	if (priv->mode == SATA)
+ 		ret = spear1340_miphy_sata_exit(priv);
+ 
+ 	return ret;
+ }
+ 
+ static int spear1340_miphy_resume(struct device *dev)
+ {
+ 	struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+ 	int ret = 0;
+ 
+ 	if (priv->mode == SATA)
+ 		ret = spear1340_miphy_sata_init(priv);
+ 
+ 	return ret;
+ }
+ #endif
+ 
+ static SIMPLE_DEV_PM_OPS(spear1340_miphy_pm_ops, spear1340_miphy_suspend,
+ 			 spear1340_miphy_resume);
+ 
+ static struct phy *spear1340_miphy_xlate(struct device *dev,
+ 					 struct of_phandle_args *args)
+ {
+ 	struct spear1340_miphy_priv *priv = dev_get_drvdata(dev);
+ 
+ 	if (args->args_count < 1) {
+ 		dev_err(dev, "DT did not pass correct no of args\n");
+ 		return NULL;
+ 	}
+ 
+ 	priv->mode = args->args[0];
+ 
+ 	if (priv->mode != SATA && priv->mode != PCIE) {
+ 		dev_err(dev, "DT did not pass correct phy mode\n");
+ 		return NULL;
+ 	}
+ 
+ 	return priv->phy;
+ }
+ 
+ static int spear1340_miphy_probe(struct platform_device *pdev)
+ {
+ 	struct device *dev = &pdev->dev;
+ 	struct spear1340_miphy_priv *priv;
+ 	struct phy_provider *phy_provider;
+ 
+ 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ 	if (!priv) {
+ 		dev_err(dev, "can't alloc spear1340_miphy private date memory\n");
+ 		return -ENOMEM;
+ 	}
+ 
+ 	priv->misc =
+ 		syscon_regmap_lookup_by_phandle(dev->of_node, "misc");
+ 	if (IS_ERR(priv->misc)) {
+ 		dev_err(dev, "failed to find misc regmap\n");
+ 		return PTR_ERR(priv->misc);
+ 	}
+ 
 -	priv->phy = devm_phy_create(dev, &spear1340_miphy_ops, NULL);
++	priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops, NULL);
+ 	if (IS_ERR(priv->phy)) {
+ 		dev_err(dev, "failed to create SATA PCIe PHY\n");
+ 		return PTR_ERR(priv->phy);
+ 	}
+ 
+ 	dev_set_drvdata(dev, priv);
+ 	phy_set_drvdata(priv->phy, priv);
+ 
+ 	phy_provider =
+ 		devm_of_phy_provider_register(dev, spear1340_miphy_xlate);
+ 	if (IS_ERR(phy_provider)) {
+ 		dev_err(dev, "failed to register phy provider\n");
+ 		return PTR_ERR(phy_provider);
+ 	}
+ 
+ 	return 0;
+ }
+ 
+ static struct platform_driver spear1340_miphy_driver = {
+ 	.probe		= spear1340_miphy_probe,
+ 	.driver = {
+ 		.name = "spear1340-miphy",
+ 		.owner = THIS_MODULE,
+ 		.pm = &spear1340_miphy_pm_ops,
+ 		.of_match_table = of_match_ptr(spear1340_miphy_of_match),
+ 	},
+ };
+ 
+ static int __init spear1340_miphy_phy_init(void)
+ {
+ 	return platform_driver_register(&spear1340_miphy_driver);
+ }
+ module_init(spear1340_miphy_phy_init);
+ 
+ static void __exit spear1340_miphy_phy_exit(void)
+ {
+ 	platform_driver_unregister(&spear1340_miphy_driver);
+ }
+ module_exit(spear1340_miphy_phy_exit);
+ 
+ MODULE_DESCRIPTION("ST SPEAR1340-MIPHY driver");
+ MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>");
+ MODULE_LICENSE("GPL v2");
diff --cc drivers/pinctrl/pinctrl-tegra-xusb.c
index 4a7daf577b49a,0000000000000..a066204748459
mode 100644,000000..100644
--- a/drivers/pinctrl/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@@ -1,973 -1,0 +1,973 @@@
 +/*
 + * Copyright (c) 2014, NVIDIA CORPORATION.  All rights reserved.
 + *
 + * This program is free software; you can redistribute it and/or modify it
 + * under the terms and conditions of the GNU General Public License,
 + * version 2, as published by the Free Software Foundation.
 + *
 + * This program is distributed in the hope 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/delay.h>
 +#include <linux/io.h>
 +#include <linux/module.h>
 +#include <linux/of.h>
 +#include <linux/phy/phy.h>
 +#include <linux/pinctrl/pinctrl.h>
 +#include <linux/pinctrl/pinmux.h>
 +#include <linux/platform_device.h>
 +#include <linux/reset.h>
 +
 +#include <dt-bindings/pinctrl/pinctrl-tegra-xusb.h>
 +
 +#include "core.h"
 +#include "pinctrl-utils.h"
 +
 +#define XUSB_PADCTL_ELPG_PROGRAM 0x01c
 +#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN (1 << 26)
 +#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY (1 << 25)
 +#define XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN (1 << 24)
 +
 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1 0x040
 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET (1 << 19)
 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK (0xf << 12)
 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST (1 << 1)
 +
 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2 0x044
 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN (1 << 6)
 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN (1 << 5)
 +#define XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL (1 << 4)
 +
 +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1 0x138
 +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET (1 << 27)
 +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE (1 << 24)
 +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD (1 << 3)
 +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST (1 << 1)
 +#define XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ (1 << 0)
 +
 +#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1 0x148
 +#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD (1 << 1)
 +#define XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ (1 << 0)
 +
 +struct tegra_xusb_padctl_function {
 +	const char *name;
 +	const char * const *groups;
 +	unsigned int num_groups;
 +};
 +
 +struct tegra_xusb_padctl_group {
 +	const unsigned int *funcs;
 +	unsigned int num_funcs;
 +};
 +
 +struct tegra_xusb_padctl_soc {
 +	const struct pinctrl_pin_desc *pins;
 +	unsigned int num_pins;
 +
 +	const struct tegra_xusb_padctl_function *functions;
 +	unsigned int num_functions;
 +
 +	const struct tegra_xusb_padctl_lane *lanes;
 +	unsigned int num_lanes;
 +};
 +
 +struct tegra_xusb_padctl_lane {
 +	const char *name;
 +
 +	unsigned int offset;
 +	unsigned int shift;
 +	unsigned int mask;
 +	unsigned int iddq;
 +
 +	const unsigned int *funcs;
 +	unsigned int num_funcs;
 +};
 +
 +struct tegra_xusb_padctl {
 +	struct device *dev;
 +	void __iomem *regs;
 +	struct mutex lock;
 +	struct reset_control *rst;
 +
 +	const struct tegra_xusb_padctl_soc *soc;
 +	struct pinctrl_dev *pinctrl;
 +	struct pinctrl_desc desc;
 +
 +	struct phy_provider *provider;
 +	struct phy *phys[2];
 +
 +	unsigned int enable;
 +};
 +
 +static inline void padctl_writel(struct tegra_xusb_padctl *padctl, u32 value,
 +				 unsigned long offset)
 +{
 +	writel(value, padctl->regs + offset);
 +}
 +
 +static inline u32 padctl_readl(struct tegra_xusb_padctl *padctl,
 +			       unsigned long offset)
 +{
 +	return readl(padctl->regs + offset);
 +}
 +
 +static int tegra_xusb_padctl_get_groups_count(struct pinctrl_dev *pinctrl)
 +{
 +	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 +
 +	return padctl->soc->num_pins;
 +}
 +
 +static const char *tegra_xusb_padctl_get_group_name(struct pinctrl_dev *pinctrl,
 +						    unsigned int group)
 +{
 +	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 +
 +	return padctl->soc->pins[group].name;
 +}
 +
 +enum tegra_xusb_padctl_param {
 +	TEGRA_XUSB_PADCTL_IDDQ,
 +};
 +
 +static const struct tegra_xusb_padctl_property {
 +	const char *name;
 +	enum tegra_xusb_padctl_param param;
 +} properties[] = {
 +	{ "nvidia,iddq", TEGRA_XUSB_PADCTL_IDDQ },
 +};
 +
 +#define TEGRA_XUSB_PADCTL_PACK(param, value) ((param) << 16 | (value))
 +#define TEGRA_XUSB_PADCTL_UNPACK_PARAM(config) ((config) >> 16)
 +#define TEGRA_XUSB_PADCTL_UNPACK_VALUE(config) ((config) & 0xffff)
 +
 +static int tegra_xusb_padctl_parse_subnode(struct tegra_xusb_padctl *padctl,
 +					   struct device_node *np,
 +					   struct pinctrl_map **maps,
 +					   unsigned int *reserved_maps,
 +					   unsigned int *num_maps)
 +{
 +	unsigned int i, reserve = 0, num_configs = 0;
 +	unsigned long config, *configs = NULL;
 +	const char *function, *group;
 +	struct property *prop;
 +	int err = 0;
 +	u32 value;
 +
 +	err = of_property_read_string(np, "nvidia,function", &function);
 +	if (err < 0) {
 +		if (err != -EINVAL)
 +			return err;
 +
 +		function = NULL;
 +	}
 +
 +	for (i = 0; i < ARRAY_SIZE(properties); i++) {
 +		err = of_property_read_u32(np, properties[i].name, &value);
 +		if (err < 0) {
 +			if (err == -EINVAL)
 +				continue;
 +
 +			return err;
 +		}
 +
 +		config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, value);
 +
 +		err = pinctrl_utils_add_config(padctl->pinctrl, &configs,
 +					       &num_configs, config);
 +		if (err < 0)
 +			return err;
 +	}
 +
 +	if (function)
 +		reserve++;
 +
 +	if (num_configs)
 +		reserve++;
 +
 +	err = of_property_count_strings(np, "nvidia,lanes");
 +	if (err < 0)
 +		return err;
 +
 +	reserve *= err;
 +
 +	err = pinctrl_utils_reserve_map(padctl->pinctrl, maps, reserved_maps,
 +					num_maps, reserve);
 +	if (err < 0)
 +		return err;
 +
 +	of_property_for_each_string(np, "nvidia,lanes", prop, group) {
 +		if (function) {
 +			err = pinctrl_utils_add_map_mux(padctl->pinctrl, maps,
 +					reserved_maps, num_maps, group,
 +					function);
 +			if (err < 0)
 +				return err;
 +		}
 +
 +		if (num_configs) {
 +			err = pinctrl_utils_add_map_configs(padctl->pinctrl,
 +					maps, reserved_maps, num_maps, group,
 +					configs, num_configs,
 +					PIN_MAP_TYPE_CONFIGS_GROUP);
 +			if (err < 0)
 +				return err;
 +		}
 +	}
 +
 +	return 0;
 +}
 +
 +static int tegra_xusb_padctl_dt_node_to_map(struct pinctrl_dev *pinctrl,
 +					    struct device_node *parent,
 +					    struct pinctrl_map **maps,
 +					    unsigned int *num_maps)
 +{
 +	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 +	unsigned int reserved_maps = 0;
 +	struct device_node *np;
 +	int err;
 +
 +	*num_maps = 0;
 +	*maps = NULL;
 +
 +	for_each_child_of_node(parent, np) {
 +		err = tegra_xusb_padctl_parse_subnode(padctl, np, maps,
 +						      &reserved_maps,
 +						      num_maps);
 +		if (err < 0)
 +			return err;
 +	}
 +
 +	return 0;
 +}
 +
 +static const struct pinctrl_ops tegra_xusb_padctl_pinctrl_ops = {
 +	.get_groups_count = tegra_xusb_padctl_get_groups_count,
 +	.get_group_name = tegra_xusb_padctl_get_group_name,
 +	.dt_node_to_map = tegra_xusb_padctl_dt_node_to_map,
 +	.dt_free_map = pinctrl_utils_dt_free_map,
 +};
 +
 +static int tegra_xusb_padctl_get_functions_count(struct pinctrl_dev *pinctrl)
 +{
 +	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 +
 +	return padctl->soc->num_functions;
 +}
 +
 +static const char *
 +tegra_xusb_padctl_get_function_name(struct pinctrl_dev *pinctrl,
 +				    unsigned int function)
 +{
 +	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 +
 +	return padctl->soc->functions[function].name;
 +}
 +
 +static int tegra_xusb_padctl_get_function_groups(struct pinctrl_dev *pinctrl,
 +						 unsigned int function,
 +						 const char * const **groups,
 +						 unsigned * const num_groups)
 +{
 +	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 +
 +	*num_groups = padctl->soc->functions[function].num_groups;
 +	*groups = padctl->soc->functions[function].groups;
 +
 +	return 0;
 +}
 +
 +static int tegra_xusb_padctl_pinmux_enable(struct pinctrl_dev *pinctrl,
 +					   unsigned int function,
 +					   unsigned int group)
 +{
 +	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 +	const struct tegra_xusb_padctl_lane *lane;
 +	unsigned int i;
 +	u32 value;
 +
 +	lane = &padctl->soc->lanes[group];
 +
 +	for (i = 0; i < lane->num_funcs; i++)
 +		if (lane->funcs[i] == function)
 +			break;
 +
 +	if (i >= lane->num_funcs)
 +		return -EINVAL;
 +
 +	value = padctl_readl(padctl, lane->offset);
 +	value &= ~(lane->mask << lane->shift);
 +	value |= i << lane->shift;
 +	padctl_writel(padctl, value, lane->offset);
 +
 +	return 0;
 +}
 +
 +static const struct pinmux_ops tegra_xusb_padctl_pinmux_ops = {
 +	.get_functions_count = tegra_xusb_padctl_get_functions_count,
 +	.get_function_name = tegra_xusb_padctl_get_function_name,
 +	.get_function_groups = tegra_xusb_padctl_get_function_groups,
 +	.enable = tegra_xusb_padctl_pinmux_enable,
 +};
 +
 +static int tegra_xusb_padctl_pinconf_group_get(struct pinctrl_dev *pinctrl,
 +					       unsigned int group,
 +					       unsigned long *config)
 +{
 +	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 +	const struct tegra_xusb_padctl_lane *lane;
 +	enum tegra_xusb_padctl_param param;
 +	u32 value;
 +
 +	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(*config);
 +	lane = &padctl->soc->lanes[group];
 +
 +	switch (param) {
 +	case TEGRA_XUSB_PADCTL_IDDQ:
 +		/* lanes with iddq == 0 don't support this parameter */
 +		if (lane->iddq == 0)
 +			return -EINVAL;
 +
 +		value = padctl_readl(padctl, lane->offset);
 +
 +		if (value & BIT(lane->iddq))
 +			value = 0;
 +		else
 +			value = 1;
 +
 +		*config = TEGRA_XUSB_PADCTL_PACK(param, value);
 +		break;
 +
 +	default:
 +		dev_err(padctl->dev, "invalid configuration parameter: %04x\n",
 +			param);
 +		return -ENOTSUPP;
 +	}
 +
 +	return 0;
 +}
 +
 +static int tegra_xusb_padctl_pinconf_group_set(struct pinctrl_dev *pinctrl,
 +					       unsigned int group,
 +					       unsigned long *configs,
 +					       unsigned int num_configs)
 +{
 +	struct tegra_xusb_padctl *padctl = pinctrl_dev_get_drvdata(pinctrl);
 +	const struct tegra_xusb_padctl_lane *lane;
 +	enum tegra_xusb_padctl_param param;
 +	unsigned long value;
 +	unsigned int i;
 +	u32 regval;
 +
 +	lane = &padctl->soc->lanes[group];
 +
 +	for (i = 0; i < num_configs; i++) {
 +		param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(configs[i]);
 +		value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(configs[i]);
 +
 +		switch (param) {
 +		case TEGRA_XUSB_PADCTL_IDDQ:
 +			/* lanes with iddq == 0 don't support this parameter */
 +			if (lane->iddq == 0)
 +				return -EINVAL;
 +
 +			regval = padctl_readl(padctl, lane->offset);
 +
 +			if (value)
 +				regval &= ~BIT(lane->iddq);
 +			else
 +				regval |= BIT(lane->iddq);
 +
 +			padctl_writel(padctl, regval, lane->offset);
 +			break;
 +
 +		default:
 +			dev_err(padctl->dev,
 +				"invalid configuration parameter: %04x\n",
 +				param);
 +			return -ENOTSUPP;
 +		}
 +	}
 +
 +	return 0;
 +}
 +
 +#ifdef CONFIG_DEBUG_FS
 +static const char *strip_prefix(const char *s)
 +{
 +	const char *comma = strchr(s, ',');
 +	if (!comma)
 +		return s;
 +
 +	return comma + 1;
 +}
 +
 +static void
 +tegra_xusb_padctl_pinconf_group_dbg_show(struct pinctrl_dev *pinctrl,
 +					 struct seq_file *s,
 +					 unsigned int group)
 +{
 +	unsigned int i;
 +
 +	for (i = 0; i < ARRAY_SIZE(properties); i++) {
 +		unsigned long config, value;
 +		int err;
 +
 +		config = TEGRA_XUSB_PADCTL_PACK(properties[i].param, 0);
 +
 +		err = tegra_xusb_padctl_pinconf_group_get(pinctrl, group,
 +							  &config);
 +		if (err < 0)
 +			continue;
 +
 +		value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
 +
 +		seq_printf(s, "\n\t%s=%lu\n", strip_prefix(properties[i].name),
 +			   value);
 +	}
 +}
 +
 +static void
 +tegra_xusb_padctl_pinconf_config_dbg_show(struct pinctrl_dev *pinctrl,
 +					  struct seq_file *s,
 +					  unsigned long config)
 +{
 +	enum tegra_xusb_padctl_param param;
 +	const char *name = "unknown";
 +	unsigned long value;
 +	unsigned int i;
 +
 +	param = TEGRA_XUSB_PADCTL_UNPACK_PARAM(config);
 +	value = TEGRA_XUSB_PADCTL_UNPACK_VALUE(config);
 +
 +	for (i = 0; i < ARRAY_SIZE(properties); i++) {
 +		if (properties[i].param == param) {
 +			name = properties[i].name;
 +			break;
 +		}
 +	}
 +
 +	seq_printf(s, "%s=%lu", strip_prefix(name), value);
 +}
 +#endif
 +
 +static const struct pinconf_ops tegra_xusb_padctl_pinconf_ops = {
 +	.pin_config_group_get = tegra_xusb_padctl_pinconf_group_get,
 +	.pin_config_group_set = tegra_xusb_padctl_pinconf_group_set,
 +#ifdef CONFIG_DEBUG_FS
 +	.pin_config_group_dbg_show = tegra_xusb_padctl_pinconf_group_dbg_show,
 +	.pin_config_config_dbg_show = tegra_xusb_padctl_pinconf_config_dbg_show,
 +#endif
 +};
 +
 +static int tegra_xusb_padctl_enable(struct tegra_xusb_padctl *padctl)
 +{
 +	u32 value;
 +
 +	mutex_lock(&padctl->lock);
 +
 +	if (padctl->enable++ > 0)
 +		goto out;
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
 +	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
 +	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
 +
 +	usleep_range(100, 200);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
 +	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
 +	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
 +
 +	usleep_range(100, 200);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
 +	value &= ~XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
 +	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
 +
 +out:
 +	mutex_unlock(&padctl->lock);
 +	return 0;
 +}
 +
 +static int tegra_xusb_padctl_disable(struct tegra_xusb_padctl *padctl)
 +{
 +	u32 value;
 +
 +	mutex_lock(&padctl->lock);
 +
 +	if (WARN_ON(padctl->enable == 0))
 +		goto out;
 +
 +	if (--padctl->enable > 0)
 +		goto out;
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
 +	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_VCORE_DOWN;
 +	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
 +
 +	usleep_range(100, 200);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
 +	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN_EARLY;
 +	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
 +
 +	usleep_range(100, 200);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_ELPG_PROGRAM);
 +	value |= XUSB_PADCTL_ELPG_PROGRAM_AUX_MUX_LP0_CLAMP_EN;
 +	padctl_writel(padctl, value, XUSB_PADCTL_ELPG_PROGRAM);
 +
 +out:
 +	mutex_unlock(&padctl->lock);
 +	return 0;
 +}
 +
 +static int tegra_xusb_phy_init(struct phy *phy)
 +{
 +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
 +
 +	return tegra_xusb_padctl_enable(padctl);
 +}
 +
 +static int tegra_xusb_phy_exit(struct phy *phy)
 +{
 +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
 +
 +	return tegra_xusb_padctl_disable(padctl);
 +}
 +
 +static int pcie_phy_power_on(struct phy *phy)
 +{
 +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
 +	unsigned long timeout;
 +	int err = -ETIMEDOUT;
 +	u32 value;
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 +	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_REFCLK_SEL_MASK;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
 +	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL2_REFCLKBUF_EN |
 +		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_EN |
 +		 XUSB_PADCTL_IOPHY_PLL_P0_CTL2_TXCLKREF_SEL;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL2);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 +	value |= XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 +
 +	timeout = jiffies + msecs_to_jiffies(50);
 +
 +	while (time_before(jiffies, timeout)) {
 +		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 +		if (value & XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL0_LOCKDET) {
 +			err = 0;
 +			break;
 +		}
 +
 +		usleep_range(100, 200);
 +	}
 +
 +	return err;
 +}
 +
 +static int pcie_phy_power_off(struct phy *phy)
 +{
 +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
 +	u32 value;
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 +	value &= ~XUSB_PADCTL_IOPHY_PLL_P0_CTL1_PLL_RST;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_P0_CTL1);
 +
 +	return 0;
 +}
 +
 +static const struct phy_ops pcie_phy_ops = {
 +	.init = tegra_xusb_phy_init,
 +	.exit = tegra_xusb_phy_exit,
 +	.power_on = pcie_phy_power_on,
 +	.power_off = pcie_phy_power_off,
 +	.owner = THIS_MODULE,
 +};
 +
 +static int sata_phy_power_on(struct phy *phy)
 +{
 +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
 +	unsigned long timeout;
 +	int err = -ETIMEDOUT;
 +	u32 value;
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
 +	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
 +	value &= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
 +	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +
 +	timeout = jiffies + msecs_to_jiffies(50);
 +
 +	while (time_before(jiffies, timeout)) {
 +		value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +		if (value & XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_LOCKDET) {
 +			err = 0;
 +			break;
 +		}
 +
 +		usleep_range(100, 200);
 +	}
 +
 +	return err;
 +}
 +
 +static int sata_phy_power_off(struct phy *phy)
 +{
 +	struct tegra_xusb_padctl *padctl = phy_get_drvdata(phy);
 +	u32 value;
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_RST;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +	value &= ~XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL1_MODE;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_PWR_OVRD;
 +	value |= XUSB_PADCTL_IOPHY_PLL_S0_CTL1_PLL_IDDQ;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_PLL_S0_CTL1);
 +
 +	value = padctl_readl(padctl, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
 +	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ_OVRD;
 +	value |= ~XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1_IDDQ;
 +	padctl_writel(padctl, value, XUSB_PADCTL_IOPHY_MISC_PAD_S0_CTL1);
 +
 +	return 0;
 +}
 +
 +static const struct phy_ops sata_phy_ops = {
 +	.init = tegra_xusb_phy_init,
 +	.exit = tegra_xusb_phy_exit,
 +	.power_on = sata_phy_power_on,
 +	.power_off = sata_phy_power_off,
 +	.owner = THIS_MODULE,
 +};
 +
 +static struct phy *tegra_xusb_padctl_xlate(struct device *dev,
 +					   struct of_phandle_args *args)
 +{
 +	struct tegra_xusb_padctl *padctl = dev_get_drvdata(dev);
 +	unsigned int index = args->args[0];
 +
 +	if (args->args_count <= 0)
 +		return ERR_PTR(-EINVAL);
 +
 +	if (index > ARRAY_SIZE(padctl->phys))
 +		return ERR_PTR(-EINVAL);
 +
 +	return padctl->phys[index];
 +}
 +
 +#define PIN_OTG_0   0
 +#define PIN_OTG_1   1
 +#define PIN_OTG_2   2
 +#define PIN_ULPI_0  3
 +#define PIN_HSIC_0  4
 +#define PIN_HSIC_1  5
 +#define PIN_PCIE_0  6
 +#define PIN_PCIE_1  7
 +#define PIN_PCIE_2  8
 +#define PIN_PCIE_3  9
 +#define PIN_PCIE_4 10
 +#define PIN_SATA_0 11
 +
 +static const struct pinctrl_pin_desc tegra124_pins[] = {
 +	PINCTRL_PIN(PIN_OTG_0,  "otg-0"),
 +	PINCTRL_PIN(PIN_OTG_1,  "otg-1"),
 +	PINCTRL_PIN(PIN_OTG_2,  "otg-2"),
 +	PINCTRL_PIN(PIN_ULPI_0, "ulpi-0"),
 +	PINCTRL_PIN(PIN_HSIC_0, "hsic-0"),
 +	PINCTRL_PIN(PIN_HSIC_1, "hsic-1"),
 +	PINCTRL_PIN(PIN_PCIE_0, "pcie-0"),
 +	PINCTRL_PIN(PIN_PCIE_1, "pcie-1"),
 +	PINCTRL_PIN(PIN_PCIE_2, "pcie-2"),
 +	PINCTRL_PIN(PIN_PCIE_3, "pcie-3"),
 +	PINCTRL_PIN(PIN_PCIE_4, "pcie-4"),
 +	PINCTRL_PIN(PIN_SATA_0, "sata-0"),
 +};
 +
 +static const char * const tegra124_snps_groups[] = {
 +	"otg-0",
 +	"otg-1",
 +	"otg-2",
 +	"ulpi-0",
 +	"hsic-0",
 +	"hsic-1",
 +};
 +
 +static const char * const tegra124_xusb_groups[] = {
 +	"otg-0",
 +	"otg-1",
 +	"otg-2",
 +	"ulpi-0",
 +	"hsic-0",
 +	"hsic-1",
 +};
 +
 +static const char * const tegra124_uart_groups[] = {
 +	"otg-0",
 +	"otg-1",
 +	"otg-2",
 +};
 +
 +static const char * const tegra124_pcie_groups[] = {
 +	"pcie-0",
 +	"pcie-1",
 +	"pcie-2",
 +	"pcie-3",
 +	"pcie-4",
 +	"sata-0",
 +};
 +
 +static const char * const tegra124_usb3_groups[] = {
 +	"pcie-0",
 +	"pcie-1",
 +	"pcie-2",
 +	"pcie-3",
 +	"pcie-4",
 +	"sata-0",
 +};
 +
 +static const char * const tegra124_sata_groups[] = {
 +	"pcie-0",
 +	"pcie-1",
 +	"pcie-2",
 +	"pcie-3",
 +	"pcie-4",
 +	"sata-0",
 +};
 +
 +static const char * const tegra124_rsvd_groups[] = {
 +	"otg-0",
 +	"otg-1",
 +	"otg-2",
 +	"pcie-0",
 +	"pcie-1",
 +	"pcie-2",
 +	"pcie-3",
 +	"pcie-4",
 +	"sata-0",
 +};
 +
 +#define TEGRA124_FUNCTION(_name)					\
 +	{								\
 +		.name = #_name,						\
 +		.num_groups = ARRAY_SIZE(tegra124_##_name##_groups),	\
 +		.groups = tegra124_##_name##_groups,			\
 +	}
 +
 +static struct tegra_xusb_padctl_function tegra124_functions[] = {
 +	TEGRA124_FUNCTION(snps),
 +	TEGRA124_FUNCTION(xusb),
 +	TEGRA124_FUNCTION(uart),
 +	TEGRA124_FUNCTION(pcie),
 +	TEGRA124_FUNCTION(usb3),
 +	TEGRA124_FUNCTION(sata),
 +	TEGRA124_FUNCTION(rsvd),
 +};
 +
 +enum tegra124_function {
 +	TEGRA124_FUNC_SNPS,
 +	TEGRA124_FUNC_XUSB,
 +	TEGRA124_FUNC_UART,
 +	TEGRA124_FUNC_PCIE,
 +	TEGRA124_FUNC_USB3,
 +	TEGRA124_FUNC_SATA,
 +	TEGRA124_FUNC_RSVD,
 +};
 +
 +static const unsigned int tegra124_otg_functions[] = {
 +	TEGRA124_FUNC_SNPS,
 +	TEGRA124_FUNC_XUSB,
 +	TEGRA124_FUNC_UART,
 +	TEGRA124_FUNC_RSVD,
 +};
 +
 +static const unsigned int tegra124_usb_functions[] = {
 +	TEGRA124_FUNC_SNPS,
 +	TEGRA124_FUNC_XUSB,
 +};
 +
 +static const unsigned int tegra124_pci_functions[] = {
 +	TEGRA124_FUNC_PCIE,
 +	TEGRA124_FUNC_USB3,
 +	TEGRA124_FUNC_SATA,
 +	TEGRA124_FUNC_RSVD,
 +};
 +
 +#define TEGRA124_LANE(_name, _offset, _shift, _mask, _iddq, _funcs)	\
 +	{								\
 +		.name = _name,						\
 +		.offset = _offset,					\
 +		.shift = _shift,					\
 +		.mask = _mask,						\
 +		.iddq = _iddq,						\
 +		.num_funcs = ARRAY_SIZE(tegra124_##_funcs##_functions),	\
 +		.funcs = tegra124_##_funcs##_functions,			\
 +	}
 +
 +static const struct tegra_xusb_padctl_lane tegra124_lanes[] = {
 +	TEGRA124_LANE("otg-0",  0x004,  0, 0x3, 0, otg),
 +	TEGRA124_LANE("otg-1",  0x004,  2, 0x3, 0, otg),
 +	TEGRA124_LANE("otg-2",  0x004,  4, 0x3, 0, otg),
 +	TEGRA124_LANE("ulpi-0", 0x004, 12, 0x1, 0, usb),
 +	TEGRA124_LANE("hsic-0", 0x004, 14, 0x1, 0, usb),
 +	TEGRA124_LANE("hsic-1", 0x004, 15, 0x1, 0, usb),
 +	TEGRA124_LANE("pcie-0", 0x134, 16, 0x3, 1, pci),
 +	TEGRA124_LANE("pcie-1", 0x134, 18, 0x3, 2, pci),
 +	TEGRA124_LANE("pcie-2", 0x134, 20, 0x3, 3, pci),
 +	TEGRA124_LANE("pcie-3", 0x134, 22, 0x3, 4, pci),
 +	TEGRA124_LANE("pcie-4", 0x134, 24, 0x3, 5, pci),
 +	TEGRA124_LANE("sata-0", 0x134, 26, 0x3, 6, pci),
 +};
 +
 +static const struct tegra_xusb_padctl_soc tegra124_soc = {
 +	.num_pins = ARRAY_SIZE(tegra124_pins),
 +	.pins = tegra124_pins,
 +	.num_functions = ARRAY_SIZE(tegra124_functions),
 +	.functions = tegra124_functions,
 +	.num_lanes = ARRAY_SIZE(tegra124_lanes),
 +	.lanes = tegra124_lanes,
 +};
 +
 +static const struct of_device_id tegra_xusb_padctl_of_match[] = {
 +	{ .compatible = "nvidia,tegra124-xusb-padctl", .data = &tegra124_soc },
 +	{ }
 +};
 +MODULE_DEVICE_TABLE(of, tegra_xusb_padctl_of_match);
 +
 +static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 +{
 +	struct tegra_xusb_padctl *padctl;
 +	const struct of_device_id *match;
 +	struct resource *res;
 +	struct phy *phy;
 +	int err;
 +
 +	padctl = devm_kzalloc(&pdev->dev, sizeof(*padctl), GFP_KERNEL);
 +	if (!padctl)
 +		return -ENOMEM;
 +
 +	platform_set_drvdata(pdev, padctl);
 +	mutex_init(&padctl->lock);
 +	padctl->dev = &pdev->dev;
 +
 +	match = of_match_node(tegra_xusb_padctl_of_match, pdev->dev.of_node);
 +	padctl->soc = match->data;
 +
 +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 +	padctl->regs = devm_ioremap_resource(&pdev->dev, res);
 +	if (IS_ERR(padctl->regs))
 +		return PTR_ERR(padctl->regs);
 +
 +	padctl->rst = devm_reset_control_get(&pdev->dev, NULL);
 +	if (IS_ERR(padctl->rst))
 +		return PTR_ERR(padctl->rst);
 +
 +	err = reset_control_deassert(padctl->rst);
 +	if (err < 0)
 +		return err;
 +
 +	memset(&padctl->desc, 0, sizeof(padctl->desc));
 +	padctl->desc.name = dev_name(padctl->dev);
 +	padctl->desc.pctlops = &tegra_xusb_padctl_pinctrl_ops;
 +	padctl->desc.pmxops = &tegra_xusb_padctl_pinmux_ops;
 +	padctl->desc.confops = &tegra_xusb_padctl_pinconf_ops;
 +	padctl->desc.owner = THIS_MODULE;
 +
 +	padctl->pinctrl = pinctrl_register(&padctl->desc, &pdev->dev, padctl);
 +	if (!padctl->pinctrl) {
 +		dev_err(&pdev->dev, "failed to register pincontrol\n");
 +		err = -ENODEV;
 +		goto reset;
 +	}
 +
- 	phy = devm_phy_create(&pdev->dev, &pcie_phy_ops, NULL);
++	phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops, NULL);
 +	if (IS_ERR(phy)) {
 +		err = PTR_ERR(phy);
 +		goto unregister;
 +	}
 +
 +	padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
 +	phy_set_drvdata(phy, padctl);
 +
- 	phy = devm_phy_create(&pdev->dev, &sata_phy_ops, NULL);
++	phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops, NULL);
 +	if (IS_ERR(phy)) {
 +		err = PTR_ERR(phy);
 +		goto unregister;
 +	}
 +
 +	padctl->phys[TEGRA_XUSB_PADCTL_SATA] = phy;
 +	phy_set_drvdata(phy, padctl);
 +
 +	padctl->provider = devm_of_phy_provider_register(&pdev->dev,
 +							 tegra_xusb_padctl_xlate);
 +	if (err < 0) {
 +		dev_err(&pdev->dev, "failed to register PHYs: %d\n", err);
 +		goto unregister;
 +	}
 +
 +	return 0;
 +
 +unregister:
 +	pinctrl_unregister(padctl->pinctrl);
 +reset:
 +	reset_control_assert(padctl->rst);
 +	return err;
 +}
 +
 +static int tegra_xusb_padctl_remove(struct platform_device *pdev)
 +{
 +	struct tegra_xusb_padctl *padctl = platform_get_drvdata(pdev);
 +	int err;
 +
 +	pinctrl_unregister(padctl->pinctrl);
 +
 +	err = reset_control_assert(padctl->rst);
 +	if (err < 0)
 +		dev_err(&pdev->dev, "failed to assert reset: %d\n", err);
 +
 +	return err;
 +}
 +
 +static struct platform_driver tegra_xusb_padctl_driver = {
 +	.driver = {
 +		.name = "tegra-xusb-padctl",
 +		.of_match_table = tegra_xusb_padctl_of_match,
 +	},
 +	.probe = tegra_xusb_padctl_probe,
 +	.remove = tegra_xusb_padctl_remove,
 +};
 +module_platform_driver(tegra_xusb_padctl_driver);
 +
 +MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
 +MODULE_DESCRIPTION("Tegra 124 XUSB Pad Control driver");
 +MODULE_LICENSE("GPL v2");