mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [GIT PULL 00/25] phy: for 3.19
@ 2014-11-27  6:25 Kishon Vijay Abraham I
  2014-11-27  6:25 ` [PATCH 01/25] phy: Add PHY header file for DT x Driver defines Kishon Vijay Abraham I
                   ` (25 more replies)
  0 siblings, 26 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:25 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

Hi Greg,

Please find the pull request for 3.19 merge window.

This contains improvements in phy core dealing with non-dt boot.
It also adds 3 new phy drivers armada375-usb2, berlin-usb and miphy28lp.

There is a patch that touches drivers/pinctrl since one of the PHY drivers
is present there and it has to be modified to use the modified
devm_phy_create API.

Let me know If I have to change something.

Thanks
Kishon

The following changes since commit 206c5f60a3d902bc4b56dab2de3e88de5eb06108:

  Linux 3.18-rc4 (2014-11-09 14:55:29 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git tags/for-3.19

for you to fetch changes up to eee47538ec1f26198cf5da675975b61d7f16135b:

  phy: add support for USB cluster on the Armada 375 SoC (2014-11-26 11:07:14 +0530)

----------------------------------------------------------------
Improvements in phy-core specifically on PHY core finds the PHY in the case
of non-dt boot. Adds three new PHY drivers using the PHY framework and some
miscellaneous fixes and cleanups.

----------------------------------------------------------------
Andrew Lunn (1):
  Phy: DT binding documentation for Marvell MVEBU SATA phy.

Antoine Tenart (2):
  phy: add the Berlin USB PHY driver
  Documentation: bindings: add doc for the Berlin USB PHY

Gabriel FERNANDEZ (6):
  phy: Add PHY header file for DT x Driver defines
  phy: miphy28lp: Add Device Tree bindings for the MiPHY28lp
  phy: miphy28lp: Provide support for the MiPHY28lp Generic PHY
  phy: miphy28lp: Add SSC support for SATA
  phy: miphy28lp: Add SSC support for PCIE
  phy: miphy28lp: Tune tx impedance across Soc cuts

Gregory CLEMENT (3):
  phy: Use PTR_ERR_OR_ZERO to fix warning raised by coccinelle
  Phy: DT binding documentation for the Armada 375 USB cluster binding
  phy: add support for USB cluster on the Armada 375 SoC

Heikki Krogerus (5):
  phy: safer to_phy() macro
  phy: improved lookup method
  phy: twl4030: use the new lookup method
  phy: remove the old lookup method
  usb: dwc3: host: convey the PHYs to xhci

Kishon Vijay Abraham I (1):
  phy: phy-core: use the np present in of_phandle_args to get the PHY

Roman Byshko (1):
  phy: sun4i: add support for USB phy0

Sebastian Hesselbarth (3):
  phy: berlin-sata: Move PHY_BASE into private data struct
  phy: berlin-sata: Add support for BG2 SATA PHY
  phy: berlin-sata: Document BG2 compatible

Vivek Gautam (3):
  phy: exynos5-usbdrd: Add pipe-clk, utmi-clk and itp-clk support
  phy: exynos5-usbdrd: Add facility for VBUS-BOOST-5V supply
  phy: exynos7-usbdrd: Update dependency for ARCH_EXYNOS

 Documentation/devicetree/bindings/ata/marvell.txt  |    6 +
 .../devicetree/bindings/phy/berlin-sata-phy.txt    |    4 +-
 .../devicetree/bindings/phy/berlin-usb-phy.txt     |   16 +
 .../devicetree/bindings/phy/phy-miphy28lp.txt      |  128 ++
 .../devicetree/bindings/phy/phy-mvebu.txt          |   43 +
 .../devicetree/bindings/phy/samsung-phy.txt        |    6 +
 Documentation/phy.txt                              |   60 +-
 drivers/phy/Kconfig                                |   23 +-
 drivers/phy/Makefile                               |    3 +
 drivers/phy/phy-armada375-usb2.c                   |  158 +++
 drivers/phy/phy-bcm-kona-usb2.c                    |    2 +-
 drivers/phy/phy-berlin-sata.c                      |   36 +-
 drivers/phy/phy-berlin-usb.c                       |  223 ++++
 drivers/phy/phy-core.c                             |  115 +-
 drivers/phy/phy-exynos-dp-video.c                  |    2 +-
 drivers/phy/phy-exynos-mipi-video.c                |    2 +-
 drivers/phy/phy-exynos5-usbdrd.c                   |  139 ++-
 drivers/phy/phy-exynos5250-sata.c                  |    2 +-
 drivers/phy/phy-hix5hd2-sata.c                     |    7 +-
 drivers/phy/phy-miphy28lp.c                        | 1283 ++++++++++++++++++++
 drivers/phy/phy-miphy365x.c                        |    7 +-
 drivers/phy/phy-mvebu-sata.c                       |    2 +-
 drivers/phy/phy-omap-usb2.c                        |    2 +-
 drivers/phy/phy-qcom-apq8064-sata.c                |    3 +-
 drivers/phy/phy-qcom-ipq806x-sata.c                |    3 +-
 drivers/phy/phy-rcar-gen2.c                        |    2 +-
 drivers/phy/phy-samsung-usb2.c                     |    3 +-
 drivers/phy/phy-spear1310-miphy.c                  |    2 +-
 drivers/phy/phy-spear1340-miphy.c                  |    2 +-
 drivers/phy/phy-stih407-usb.c                      |    2 +-
 drivers/phy/phy-stih41x-usb.c                      |    7 +-
 drivers/phy/phy-sun4i-usb.c                        |   11 +-
 drivers/phy/phy-ti-pipe3.c                         |    2 +-
 drivers/phy/phy-twl4030-usb.c                      |    9 +-
 drivers/phy/phy-xgene.c                            |    2 +-
 drivers/pinctrl/pinctrl-tegra-xusb.c               |    4 +-
 drivers/usb/dwc3/host.c                            |   22 +-
 include/dt-bindings/phy/phy.h                      |   19 +
 include/linux/phy/phy.h                            |   52 +-
 39 files changed, 2210 insertions(+), 204 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/phy/berlin-usb-phy.txt
 create mode 100644 Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
 create mode 100644 Documentation/devicetree/bindings/phy/phy-mvebu.txt
 create mode 100644 drivers/phy/phy-armada375-usb2.c
 create mode 100644 drivers/phy/phy-berlin-usb.c
 create mode 100644 drivers/phy/phy-miphy28lp.c
 create mode 100644 include/dt-bindings/phy/phy.h

-- 
1.7.9.5


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

* [PATCH 01/25] phy: Add PHY header file for DT x Driver defines
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
@ 2014-11-27  6:25 ` Kishon Vijay Abraham I
  2014-11-27  6:25 ` [PATCH 02/25] phy: miphy28lp: Add Device Tree bindings for the MiPHY28lp Kishon Vijay Abraham I
                   ` (24 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:25 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Gabriel FERNANDEZ <gabriel.fernandez@st.com>

This provides the shared header file which will be reference from both
PHY driver and its associated Device Tree node(s).

Signed-off-by: Gabriel Fernandez <gabriel.fernandez@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 include/dt-bindings/phy/phy.h |   18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
 create mode 100644 include/dt-bindings/phy/phy.h

diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
new file mode 100644
index 0000000..e8c6a3f
--- /dev/null
+++ b/include/dt-bindings/phy/phy.h
@@ -0,0 +1,18 @@
+/*
+ *
+ * This header provides constants for the phy framework
+ *
+ * Copyright (C) 2014 STMicroelectronics
+ * Author: Gabriel Fernandez <gabriel.fernandez@st.com>
+ * License terms:  GNU General Public License (GPL), version 2
+ */
+
+#ifndef _DT_BINDINGS_PHY
+#define _DT_BINDINGS_PHY
+
+#define PHY_TYPE_SATA		1
+#define PHY_TYPE_PCIE		2
+#define PHY_TYPE_USB2		3
+#define PHY_TYPE_USB3		4
+
+#endif /* _DT_BINDINGS_PHY */
-- 
1.7.9.5


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

* [PATCH 02/25] phy: miphy28lp: Add Device Tree bindings for the MiPHY28lp
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
  2014-11-27  6:25 ` [PATCH 01/25] phy: Add PHY header file for DT x Driver defines Kishon Vijay Abraham I
@ 2014-11-27  6:25 ` Kishon Vijay Abraham I
  2014-11-27  6:25 ` [PATCH 03/25] phy: miphy28lp: Provide support for the MiPHY28lp Generic PHY Kishon Vijay Abraham I
                   ` (23 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:25 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Gabriel FERNANDEZ <gabriel.fernandez@st.com>

The MiPHY28lp is a Generic PHY which can serve various SATA or PCIe
or USB3 devices.

Signed-off-by: alexandre torgue <alexandre.torgue@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/phy-miphy28lp.txt      |  126 ++++++++++++++++++++
 1 file changed, 126 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-miphy28lp.txt

diff --git a/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt b/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
new file mode 100644
index 0000000..b7c13ad
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
@@ -0,0 +1,126 @@
+STMicroelectronics STi MIPHY28LP PHY binding
+============================================
+
+This binding describes a miphy device that is used to control PHY hardware
+for SATA, PCIe or USB3.
+
+Required properties (controller (parent) node):
+- compatible	: Should be "st,miphy28lp-phy".
+- st,syscfg	: Should be a phandle of the system configuration register group
+		  which contain the SATA, PCIe or USB3 mode setting bits.
+
+Required nodes	:  A sub-node is required for each channel the controller
+		   provides. Address range information including the usual
+		   'reg' and 'reg-names' properties are used inside these
+		   nodes to describe the controller's topology. These nodes
+		   are translated by the driver's .xlate() function.
+
+Required properties (port (child) node):
+- #phy-cells	: Should be 1 (See second example)
+		  Cell after port phandle is device type from:
+			- PHY_TYPE_SATA
+			- PHY_TYPE_PCI
+			- PHY_TYPE_USB3
+- reg		: Address and length of the register set for the device.
+- reg-names	: The names of the register addresses corresponding to the registers
+		  filled in "reg". It can also contain the offset of the system configuration
+		  registers used as glue-logic to setup the device for SATA/PCIe or USB3
+		  devices.
+- resets	: phandle to the parent reset controller.
+- reset-names	: Associated name must be "miphy-sw-rst".
+
+Optional properties (port (child) node):
+- st,osc-rdy		: to check the MIPHY0_OSC_RDY status in the glue-logic. This
+			  is not available in all the MiPHY. For example, for STiH407, only the
+			  MiPHY0 has this bit.
+- st,osc-force-ext	: to select the external oscillator. This can change from
+			  different MiPHY inside the same SoC.
+- st,sata_gen		: to select which SATA_SPDMODE has to be set in the SATA system config
+			  register.
+- st,px_rx_pol_inv	: to invert polarity of RXn/RXp (respectively negative line and positive
+			  line).
+
+example:
+
+		miphy28lp_phy: miphy28lp@9b22000 {
+			compatible = "st,miphy28lp-phy";
+			st,syscfg = <&syscfg_core>;
+			#address-cells	= <1>;
+			#size-cells	= <1>;
+			ranges;
+
+			phy_port0: port@9b22000 {
+				reg = <0x9b22000 0xff>,
+				      <0x9b09000 0xff>,
+				      <0x9b04000 0xff>,
+				      <0x114 0x4>, /* sysctrl MiPHY cntrl */
+				      <0x818 0x4>, /* sysctrl MiPHY status*/
+				      <0xe0  0x4>, /* sysctrl PCIe */
+				      <0xec  0x4>; /* sysctrl SATA */
+				reg-names = "sata-up",
+					    "pcie-up",
+					    "pipew",
+					    "miphy-ctrl-glue",
+					    "miphy-status-glue",
+					    "pcie-glue",
+					    "sata-glue";
+				#phy-cells = <1>;
+				st,osc-rdy;
+				reset-names = "miphy-sw-rst";
+				resets = <&softreset STIH407_MIPHY0_SOFTRESET>;
+			};
+
+			phy_port1: port@9b2a000 {
+				reg = <0x9b2a000 0xff>,
+				      <0x9b19000 0xff>,
+				      <0x9b14000 0xff>,
+				      <0x118 0x4>,
+				      <0x81c 0x4>,
+				      <0xe4  0x4>,
+				      <0xf0  0x4>;
+				reg-names = "sata-up",
+					    "pcie-up",
+					    "pipew",
+					    "miphy-ctrl-glue",
+					    "miphy-status-glue",
+					    "pcie-glue",
+					    "sata-glue";
+				#phy-cells = <1>;
+				st,osc-force-ext;
+				reset-names = "miphy-sw-rst";
+				resets = <&softreset STIH407_MIPHY1_SOFTRESET>;
+			};
+
+			phy_port2: port@8f95000 {
+				reg = <0x8f95000 0xff>,
+				      <0x8f90000 0xff>,
+				      <0x11c 0x4>,
+				      <0x820 0x4>;
+				reg-names = "pipew",
+				    "usb3-up",
+				    "miphy-ctrl-glue",
+				    "miphy-status-glue";
+				#phy-cells = <1>;
+				reset-names = "miphy-sw-rst";
+				resets = <&softreset STIH407_MIPHY2_SOFTRESET>;
+			};
+		};
+
+
+Specifying phy control of devices
+=================================
+
+Device nodes should specify the configuration required in their "phys"
+property, containing a phandle to the miphy device node and an index
+specifying which configuration to use, as described in phy-bindings.txt.
+
+example:
+		sata0: sata@9b20000  {
+			...
+			phys		= <&phy_port0 PHY_TYPE_SATA>;
+			...
+		};
+
+Macro definitions for the supported miphy configuration can be found in:
+
+include/dt-bindings/phy/phy-miphy28lp.h
-- 
1.7.9.5


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

* [PATCH 03/25] phy: miphy28lp: Provide support for the MiPHY28lp Generic PHY
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
  2014-11-27  6:25 ` [PATCH 01/25] phy: Add PHY header file for DT x Driver defines Kishon Vijay Abraham I
  2014-11-27  6:25 ` [PATCH 02/25] phy: miphy28lp: Add Device Tree bindings for the MiPHY28lp Kishon Vijay Abraham I
@ 2014-11-27  6:25 ` Kishon Vijay Abraham I
  2014-11-27  7:00   ` sanjeev sharma
  2014-11-27  6:25 ` [PATCH 04/25] phy: miphy28lp: Add SSC support for SATA Kishon Vijay Abraham I
                   ` (22 subsequent siblings)
  25 siblings, 1 reply; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:25 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Gabriel FERNANDEZ <gabriel.fernandez@st.com>

The MiPHY28lp is a Generic PHY which can serve various SATA or PCIe
or USB3 devices.

Signed-off-by: alexandre torgue <alexandre.torgue@st.com>
Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig         |    8 +
 drivers/phy/Makefile        |    1 +
 drivers/phy/phy-miphy28lp.c | 1177 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1186 insertions(+)
 create mode 100644 drivers/phy/phy-miphy28lp.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 2a436e6..cfaced9 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -38,6 +38,14 @@ config PHY_MVEBU_SATA
 	depends on OF
 	select GENERIC_PHY
 
+config PHY_MIPHY28LP
+	tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407"
+	depends on ARCH_STI
+	select GENERIC_PHY
+	help
+	  Enable this to support the miphy transceiver (for SATA/PCIE/USB3)
+	  that is part of STMicroelectronics STiH407 SoC.
+
 config PHY_MIPHY365X
 	tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
 	depends on ARCH_STI
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index c4590fc..30d90a8 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
 obj-$(CONFIG_PHY_MVEBU_SATA)		+= phy-mvebu-sata.o
+obj-$(CONFIG_PHY_MIPHY28LP) 		+= phy-miphy28lp.o
 obj-$(CONFIG_PHY_MIPHY365X)		+= phy-miphy365x.o
 obj-$(CONFIG_PHY_RCAR_GEN2)		+= phy-rcar-gen2.o
 obj-$(CONFIG_OMAP_CONTROL_PHY)		+= phy-omap-control.o
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
new file mode 100644
index 0000000..7d592e6
--- /dev/null
+++ b/drivers/phy/phy-miphy28lp.c
@@ -0,0 +1,1177 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics
+ *
+ * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407).
+ *
+ * Author: Alexandre Torgue <alexandre.torgue@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/platform_device.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/clk.h>
+#include <linux/phy/phy.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include <dt-bindings/phy/phy.h>
+
+/* MiPHY registers */
+#define MIPHY_CONF_RESET		0x00
+#define RST_APPLI_SW		BIT(0)
+#define RST_CONF_SW		BIT(1)
+#define RST_MACRO_SW		BIT(2)
+
+#define MIPHY_RESET			0x01
+#define RST_PLL_SW		BIT(0)
+#define RST_COMP_SW		BIT(2)
+
+#define MIPHY_STATUS_1			0x02
+#define PHY_RDY			BIT(0)
+#define HFC_RDY			BIT(1)
+#define HFC_PLL			BIT(2)
+
+#define MIPHY_CONTROL			0x04
+#define TERM_EN_SW		BIT(2)
+#define DIS_LINK_RST		BIT(3)
+#define AUTO_RST_RX		BIT(4)
+#define PX_RX_POL		BIT(5)
+
+#define MIPHY_BOUNDARY_SEL		0x0a
+#define TX_SEL			BIT(6)
+#define SSC_SEL			BIT(4)
+#define GENSEL_SEL		BIT(0)
+
+#define MIPHY_BOUNDARY_1		0x0b
+#define MIPHY_BOUNDARY_2		0x0c
+#define SSC_EN_SW		BIT(2)
+
+#define MIPHY_PLL_CLKREF_FREQ		0x0d
+#define MIPHY_SPEED			0x0e
+#define TX_SPDSEL_80DEC		0
+#define TX_SPDSEL_40DEC		1
+#define TX_SPDSEL_20DEC		2
+#define RX_SPDSEL_80DEC		0
+#define RX_SPDSEL_40DEC		(1 << 2)
+#define RX_SPDSEL_20DEC		(2 << 2)
+
+#define MIPHY_CONF			0x0f
+#define MIPHY_CTRL_TEST_SEL		0x20
+#define MIPHY_CTRL_TEST_1		0x21
+#define MIPHY_CTRL_TEST_2		0x22
+#define MIPHY_CTRL_TEST_3		0x23
+#define MIPHY_CTRL_TEST_4		0x24
+#define MIPHY_FEEDBACK_TEST		0x25
+#define MIPHY_DEBUG_BUS			0x26
+#define MIPHY_DEBUG_STATUS_MSB		0x27
+#define MIPHY_DEBUG_STATUS_LSB		0x28
+#define MIPHY_PWR_RAIL_1		0x29
+#define MIPHY_PWR_RAIL_2		0x2a
+#define MIPHY_SYNCHAR_CONTROL		0x30
+
+#define MIPHY_COMP_FSM_1		0x3a
+#define COMP_START		BIT(6)
+
+#define MIPHY_COMP_FSM_6		0x3f
+#define COMP_DONE		BIT(7)
+
+#define MIPHY_COMP_POSTP		0x42
+#define MIPHY_TX_CTRL_1			0x49
+#define TX_REG_STEP_0V		0
+#define TX_REG_STEP_P_25MV	1
+#define TX_REG_STEP_P_50MV	2
+#define TX_REG_STEP_N_25MV	7
+#define TX_REG_STEP_N_50MV	6
+#define TX_REG_STEP_N_75MV	5
+
+#define MIPHY_TX_CTRL_2			0x4a
+#define TX_SLEW_SW_40_PS	0
+#define TX_SLEW_SW_80_PS	1
+#define TX_SLEW_SW_120_PS	2
+
+#define MIPHY_TX_CTRL_3			0x4b
+#define MIPHY_TX_CAL_MAN		0x4e
+#define TX_SLEW_CAL_MAN_EN	BIT(0)
+
+#define MIPHY_TST_BIAS_BOOST_2		0x62
+#define MIPHY_BIAS_BOOST_1		0x63
+#define MIPHY_BIAS_BOOST_2		0x64
+#define MIPHY_RX_DESBUFF_FDB_2		0x67
+#define MIPHY_RX_DESBUFF_FDB_3		0x68
+#define MIPHY_SIGDET_COMPENS1		0x69
+#define MIPHY_SIGDET_COMPENS2		0x6a
+#define MIPHY_JITTER_PERIOD		0x6b
+#define MIPHY_JITTER_AMPLITUDE_1	0x6c
+#define MIPHY_JITTER_AMPLITUDE_2	0x6d
+#define MIPHY_JITTER_AMPLITUDE_3	0x6e
+#define MIPHY_RX_K_GAIN			0x78
+#define MIPHY_RX_BUFFER_CTRL		0x7a
+#define VGA_GAIN		BIT(0)
+#define EQ_DC_GAIN		BIT(2)
+#define EQ_BOOST_GAIN		BIT(3)
+
+#define MIPHY_RX_VGA_GAIN		0x7b
+#define MIPHY_RX_EQU_GAIN_1		0x7f
+#define MIPHY_RX_EQU_GAIN_2		0x80
+#define MIPHY_RX_EQU_GAIN_3		0x81
+#define MIPHY_RX_CAL_CTRL_1		0x97
+#define MIPHY_RX_CAL_CTRL_2		0x98
+
+#define MIPHY_RX_CAL_OFFSET_CTRL	0x99
+#define CAL_OFFSET_VGA_64	(0x03 << 0)
+#define CAL_OFFSET_THRESHOLD_64	(0x03 << 2)
+#define VGA_OFFSET_POLARITY	BIT(4)
+#define OFFSET_COMPENSATION_EN	BIT(6)
+
+#define MIPHY_RX_CAL_VGA_STEP		0x9a
+#define MIPHY_RX_CAL_EYE_MIN		0x9d
+#define MIPHY_RX_CAL_OPT_LENGTH		0x9f
+#define MIPHY_RX_LOCK_CTRL_1		0xc1
+#define MIPHY_RX_LOCK_SETTINGS_OPT	0xc2
+#define MIPHY_RX_LOCK_STEP		0xc4
+
+#define MIPHY_RX_SIGDET_SLEEP_OA	0xc9
+#define MIPHY_RX_SIGDET_SLEEP_SEL	0xca
+#define MIPHY_RX_SIGDET_WAIT_SEL	0xcb
+#define MIPHY_RX_SIGDET_DATA_SEL	0xcc
+#define EN_ULTRA_LOW_POWER	BIT(0)
+#define EN_FIRST_HALF		BIT(1)
+#define EN_SECOND_HALF		BIT(2)
+#define EN_DIGIT_SIGNAL_CHECK	BIT(3)
+
+#define MIPHY_RX_POWER_CTRL_1		0xcd
+#define MIPHY_RX_POWER_CTRL_2		0xce
+#define MIPHY_PLL_CALSET_CTRL		0xd3
+#define MIPHY_PLL_CALSET_1		0xd4
+#define MIPHY_PLL_CALSET_2		0xd5
+#define MIPHY_PLL_CALSET_3		0xd6
+#define MIPHY_PLL_CALSET_4		0xd7
+#define MIPHY_PLL_SBR_1			0xe3
+#define SET_NEW_CHANGE		BIT(1)
+
+#define MIPHY_PLL_SBR_2			0xe4
+#define MIPHY_PLL_SBR_3			0xe5
+#define MIPHY_PLL_SBR_4			0xe6
+#define MIPHY_PLL_COMMON_MISC_2		0xe9
+#define START_ACT_FILT		BIT(6)
+
+#define MIPHY_PLL_SPAREIN		0xeb
+
+/*
+ * On STiH407 the glue logic can be different among MiPHY devices; for example:
+ * MiPHY0: OSC_FORCE_EXT means:
+ *  0: 30MHz crystal clk - 1: 100MHz ext clk routed through MiPHY1
+ * MiPHY1: OSC_FORCE_EXT means:
+ *  1: 30MHz crystal clk - 0: 100MHz ext clk routed through MiPHY1
+ * Some devices have not the possibility to check if the osc is ready.
+ */
+#define MIPHY_OSC_FORCE_EXT	BIT(3)
+#define MIPHY_OSC_RDY		BIT(5)
+
+#define MIPHY_CTRL_MASK		0x0f
+#define MIPHY_CTRL_DEFAULT	0
+#define MIPHY_CTRL_SYNC_D_EN	BIT(2)
+
+/* SATA / PCIe defines */
+#define SATA_CTRL_MASK		0x07
+#define PCIE_CTRL_MASK		0xff
+#define SATA_CTRL_SELECT_SATA	1
+#define SATA_CTRL_SELECT_PCIE	0
+#define SYSCFG_PCIE_PCIE_VAL	0x80
+#define SATA_SPDMODE		1
+
+struct miphy28lp_phy {
+	struct phy *phy;
+	struct miphy28lp_dev *phydev;
+	void __iomem *base;
+	void __iomem *pipebase;
+
+	bool osc_force_ext;
+	bool osc_rdy;
+	bool px_rx_pol_inv;
+
+	struct reset_control *miphy_rst;
+
+	u32 sata_gen;
+
+	/* Sysconfig registers offsets needed to configure the device */
+	u32 syscfg_miphy_ctrl;
+	u32 syscfg_miphy_status;
+	u32 syscfg_pci;
+	u32 syscfg_sata;
+	u8 type;
+};
+
+struct miphy28lp_dev {
+	struct device *dev;
+	struct regmap *regmap;
+	struct mutex miphy_mutex;
+	struct miphy28lp_phy **phys;
+};
+
+struct miphy_initval {
+	u16 reg;
+	u16 val;
+};
+
+enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 };
+
+static char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" };
+
+struct pll_ratio {
+	int clk_ref;
+	int calset_1;
+	int calset_2;
+	int calset_3;
+	int calset_4;
+	int cal_ctrl;
+};
+
+static struct pll_ratio sata_pll_ratio = {
+	.clk_ref = 0x1e,
+	.calset_1 = 0xc8,
+	.calset_2 = 0x00,
+	.calset_3 = 0x00,
+	.calset_4 = 0x00,
+	.cal_ctrl = 0x00,
+};
+
+static struct pll_ratio pcie_pll_ratio = {
+	.clk_ref = 0x1e,
+	.calset_1 = 0xa6,
+	.calset_2 = 0xaa,
+	.calset_3 = 0xaa,
+	.calset_4 = 0x00,
+	.cal_ctrl = 0x00,
+};
+
+static struct pll_ratio usb3_pll_ratio = {
+	.clk_ref = 0x1e,
+	.calset_1 = 0xa6,
+	.calset_2 = 0xaa,
+	.calset_3 = 0xaa,
+	.calset_4 = 0x04,
+	.cal_ctrl = 0x00,
+};
+
+struct miphy28lp_pll_gen {
+	int bank;
+	int speed;
+	int bias_boost_1;
+	int bias_boost_2;
+	int tx_ctrl_1;
+	int tx_ctrl_2;
+	int tx_ctrl_3;
+	int rx_k_gain;
+	int rx_vga_gain;
+	int rx_equ_gain_1;
+	int rx_equ_gain_2;
+	int rx_equ_gain_3;
+	int rx_buff_ctrl;
+};
+
+static struct miphy28lp_pll_gen sata_pll_gen[] = {
+	{
+		.bank		= 0x00,
+		.speed		= TX_SPDSEL_80DEC | RX_SPDSEL_80DEC,
+		.bias_boost_1	= 0x00,
+		.bias_boost_2	= 0xae,
+		.tx_ctrl_2	= 0x53,
+		.tx_ctrl_3	= 0x00,
+		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+		.rx_vga_gain	= 0x00,
+		.rx_equ_gain_1	= 0x7d,
+		.rx_equ_gain_2	= 0x56,
+		.rx_equ_gain_3	= 0x00,
+	},
+	{
+		.bank		= 0x01,
+		.speed		= TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,
+		.bias_boost_1	= 0x00,
+		.bias_boost_2	= 0xae,
+		.tx_ctrl_2	= 0x72,
+		.tx_ctrl_3	= 0x20,
+		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+		.rx_vga_gain	= 0x00,
+		.rx_equ_gain_1	= 0x7d,
+		.rx_equ_gain_2	= 0x56,
+		.rx_equ_gain_3	= 0x00,
+	},
+	{
+		.bank		= 0x02,
+		.speed		= TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,
+		.bias_boost_1	= 0x00,
+		.bias_boost_2	= 0xae,
+		.tx_ctrl_2	= 0xc0,
+		.tx_ctrl_3	= 0x20,
+		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+		.rx_vga_gain	= 0x00,
+		.rx_equ_gain_1	= 0x7d,
+		.rx_equ_gain_2	= 0x56,
+		.rx_equ_gain_3	= 0x00,
+	},
+};
+
+static struct miphy28lp_pll_gen pcie_pll_gen[] = {
+	{
+		.bank		= 0x00,
+		.speed		= TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,
+		.bias_boost_1	= 0x00,
+		.bias_boost_2	= 0xa5,
+		.tx_ctrl_1	= TX_REG_STEP_N_25MV,
+		.tx_ctrl_2	= 0x71,
+		.tx_ctrl_3	= 0x60,
+		.rx_k_gain	= 0x98,
+		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+		.rx_vga_gain	= 0x00,
+		.rx_equ_gain_1	= 0x79,
+		.rx_equ_gain_2	= 0x56,
+	},
+	{
+		.bank		= 0x01,
+		.speed		= TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,
+		.bias_boost_1	= 0x00,
+		.bias_boost_2	= 0xa5,
+		.tx_ctrl_1	= TX_REG_STEP_N_25MV,
+		.tx_ctrl_2	= 0x70,
+		.tx_ctrl_3	= 0x60,
+		.rx_k_gain	= 0xcc,
+		.rx_buff_ctrl	= EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
+		.rx_vga_gain	= 0x00,
+		.rx_equ_gain_1	= 0x78,
+		.rx_equ_gain_2	= 0x07,
+	},
+};
+
+static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy)
+{
+	void *base = miphy_phy->base;
+	u8 val;
+
+	/* Putting Macro in reset */
+	writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
+
+	val = RST_APPLI_SW | RST_CONF_SW;
+	writeb_relaxed(val, base + MIPHY_CONF_RESET);
+
+	writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
+
+	/* Bringing the MIPHY-CPU registers out of reset */
+	if (miphy_phy->type == PHY_TYPE_PCIE) {
+		val = AUTO_RST_RX | TERM_EN_SW;
+		writeb_relaxed(val, base + MIPHY_CONTROL);
+	} else {
+		val = AUTO_RST_RX | TERM_EN_SW | DIS_LINK_RST;
+		writeb_relaxed(val, base + MIPHY_CONTROL);
+	}
+}
+
+static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy,
+		struct pll_ratio *pll_ratio)
+{
+	void *base = miphy_phy->base;
+	u8 val;
+
+	/* Applying PLL Settings */
+	writeb_relaxed(0x1d, base + MIPHY_PLL_SPAREIN);
+	writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);
+
+	/* PLL Ratio */
+	writeb_relaxed(pll_ratio->calset_1, base + MIPHY_PLL_CALSET_1);
+	writeb_relaxed(pll_ratio->calset_2, base + MIPHY_PLL_CALSET_2);
+	writeb_relaxed(pll_ratio->calset_3, base + MIPHY_PLL_CALSET_3);
+	writeb_relaxed(pll_ratio->calset_4, base + MIPHY_PLL_CALSET_4);
+	writeb_relaxed(pll_ratio->cal_ctrl, base + MIPHY_PLL_CALSET_CTRL);
+
+	writeb_relaxed(TX_SEL, base + MIPHY_BOUNDARY_SEL);
+
+	val = (0x68 << 1) | TX_SLEW_CAL_MAN_EN;
+	writeb_relaxed(val, base + MIPHY_TX_CAL_MAN);
+
+	val = VGA_OFFSET_POLARITY | CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;
+
+	if (miphy_phy->type != PHY_TYPE_SATA)
+		val |= OFFSET_COMPENSATION_EN;
+
+	writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);
+
+	if (miphy_phy->type == PHY_TYPE_USB3) {
+		writeb_relaxed(0x00, base + MIPHY_CONF);
+		writeb_relaxed(0x70, base + MIPHY_RX_LOCK_STEP);
+		writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_OA);
+		writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_SEL);
+		writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_WAIT_SEL);
+
+		val = EN_DIGIT_SIGNAL_CHECK | EN_FIRST_HALF;
+		writeb_relaxed(val, base + MIPHY_RX_SIGDET_DATA_SEL);
+	}
+
+}
+
+static inline void miphy28lp_sata_config_gen(struct miphy28lp_phy *miphy_phy)
+{
+	void __iomem *base = miphy_phy->base;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(sata_pll_gen); i++) {
+		struct miphy28lp_pll_gen *gen = &sata_pll_gen[i];
+
+		/* Banked settings */
+		writeb_relaxed(gen->bank, base + MIPHY_CONF);
+		writeb_relaxed(gen->speed, base + MIPHY_SPEED);
+		writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);
+		writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);
+
+		/* TX buffer Settings */
+		writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);
+		writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);
+
+		/* RX Buffer Settings */
+		writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);
+		writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);
+		writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);
+		writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);
+		writeb_relaxed(gen->rx_equ_gain_3, base + MIPHY_RX_EQU_GAIN_3);
+	}
+}
+
+static inline void miphy28lp_pcie_config_gen(struct miphy28lp_phy *miphy_phy)
+{
+	void __iomem *base = miphy_phy->base;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(pcie_pll_gen); i++) {
+		struct miphy28lp_pll_gen *gen = &pcie_pll_gen[i];
+
+		/* Banked settings */
+		writeb_relaxed(gen->bank, base + MIPHY_CONF);
+		writeb_relaxed(gen->speed, base + MIPHY_SPEED);
+		writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);
+		writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);
+
+		/* TX buffer Settings */
+		writeb_relaxed(gen->tx_ctrl_1, base + MIPHY_TX_CTRL_1);
+		writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);
+		writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);
+
+		writeb_relaxed(gen->rx_k_gain, base + MIPHY_RX_K_GAIN);
+
+		/* RX Buffer Settings */
+		writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);
+		writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);
+		writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);
+		writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);
+	}
+}
+
+static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy)
+{
+	unsigned long finish = jiffies + 5 * HZ;
+	u8 val;
+
+	/* Waiting for Compensation to complete */
+	do {
+		val = readb_relaxed(miphy_phy->base + MIPHY_COMP_FSM_6);
+
+		if (time_after_eq(jiffies, finish))
+			return -EBUSY;
+		cpu_relax();
+	} while (!(val & COMP_DONE));
+
+	return 0;
+}
+
+
+static inline int miphy28lp_compensation(struct miphy28lp_phy *miphy_phy,
+		struct pll_ratio *pll_ratio)
+{
+	void __iomem *base = miphy_phy->base;
+
+	/* Poll for HFC ready after reset release */
+	/* Compensation measurement */
+	writeb_relaxed(RST_PLL_SW | RST_COMP_SW, base + MIPHY_RESET);
+
+	writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);
+	writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);
+	writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);
+
+	if (miphy_phy->type == PHY_TYPE_PCIE)
+		writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);
+
+	writeb_relaxed(0x00, base + MIPHY_RESET);
+	writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);
+	writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
+
+	/* TX compensation offset to re-center TX impedance */
+	writeb_relaxed(0x00, base + MIPHY_COMP_POSTP);
+
+	if (miphy_phy->type == PHY_TYPE_PCIE)
+		return miphy28lp_wait_compensation(miphy_phy);
+
+	return 0;
+}
+
+static inline void miphy28_usb3_miphy_reset(struct miphy28lp_phy *miphy_phy)
+{
+	void __iomem *base = miphy_phy->base;
+	u8 val;
+
+	/* MIPHY Reset */
+	writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
+	writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
+	writeb_relaxed(RST_COMP_SW, base + MIPHY_RESET);
+
+	val = RST_COMP_SW | RST_PLL_SW;
+	writeb_relaxed(val, base + MIPHY_RESET);
+
+	writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);
+	writeb_relaxed(0x1e, base + MIPHY_PLL_CLKREF_FREQ);
+	writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);
+	writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);
+	writeb_relaxed(0x00, base + MIPHY_RESET);
+	writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);
+	writeb_relaxed(0x00, base + MIPHY_CONF);
+	writeb_relaxed(0x00, base + MIPHY_BOUNDARY_1);
+	writeb_relaxed(0x00, base + MIPHY_TST_BIAS_BOOST_2);
+	writeb_relaxed(0x00, base + MIPHY_CONF);
+	writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
+	writeb_relaxed(0xa5, base + MIPHY_DEBUG_BUS);
+	writeb_relaxed(0x00, base + MIPHY_CONF);
+}
+
+static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)
+{
+	void __iomem *base = miphy_phy->base;
+	int err;
+	u8 val;
+
+	/* Putting Macro in reset */
+	miphy28lp_set_reset(miphy_phy);
+
+	/* PLL calibration */
+	miphy28lp_pll_calibration(miphy_phy, &sata_pll_ratio);
+
+	/* Banked settings Gen1/Gen2/Gen3 */
+	miphy28lp_sata_config_gen(miphy_phy);
+
+	/* Power control */
+	/* Input bridge enable, manual input bridge control */
+	writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
+
+	/* Macro out of reset */
+	writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
+
+	/* Poll for HFC ready after reset release */
+	/* Compensation measurement */
+	err = miphy28lp_compensation(miphy_phy, &sata_pll_ratio);
+	if (err)
+		return err;
+
+	if (miphy_phy->px_rx_pol_inv) {
+		/* Invert Rx polarity */
+		val = readb_relaxed(miphy_phy->base + MIPHY_CONTROL);
+		val |= PX_RX_POL;
+		writeb_relaxed(val, miphy_phy->base + MIPHY_CONTROL);
+	}
+
+	return 0;
+}
+
+static inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy)
+{
+	void __iomem *base = miphy_phy->base;
+	int err;
+
+	/* Putting Macro in reset */
+	miphy28lp_set_reset(miphy_phy);
+
+	/* PLL calibration */
+	miphy28lp_pll_calibration(miphy_phy, &pcie_pll_ratio);
+
+	/* Banked settings Gen1/Gen2 */
+	miphy28lp_pcie_config_gen(miphy_phy);
+
+	/* Power control */
+	/* Input bridge enable, manual input bridge control */
+	writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
+
+	/* Macro out of reset */
+	writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
+
+	/* Poll for HFC ready after reset release */
+	/* Compensation measurement */
+	err = miphy28lp_compensation(miphy_phy, &pcie_pll_ratio);
+	if (err)
+		return err;
+
+	return 0;
+}
+
+
+static inline void miphy28lp_configure_usb3(struct miphy28lp_phy *miphy_phy)
+{
+	void __iomem *base = miphy_phy->base;
+	u8 val;
+
+	/* Putting Macro in reset */
+	miphy28lp_set_reset(miphy_phy);
+
+	/* PLL calibration */
+	miphy28lp_pll_calibration(miphy_phy, &usb3_pll_ratio);
+
+	/* Writing The Speed Rate */
+	writeb_relaxed(0x00, base + MIPHY_CONF);
+
+	val = RX_SPDSEL_20DEC | TX_SPDSEL_20DEC;
+	writeb_relaxed(val, base + MIPHY_SPEED);
+
+	/* RX Channel compensation and calibration */
+	writeb_relaxed(0x1c, base + MIPHY_RX_LOCK_SETTINGS_OPT);
+	writeb_relaxed(0x51, base + MIPHY_RX_CAL_CTRL_1);
+	writeb_relaxed(0x70, base + MIPHY_RX_CAL_CTRL_2);
+
+	val = OFFSET_COMPENSATION_EN | VGA_OFFSET_POLARITY |
+	      CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;
+	writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);
+	writeb_relaxed(0x22, base + MIPHY_RX_CAL_VGA_STEP);
+	writeb_relaxed(0x0e, base + MIPHY_RX_CAL_OPT_LENGTH);
+
+	val = EQ_DC_GAIN | VGA_GAIN;
+	writeb_relaxed(val, base + MIPHY_RX_BUFFER_CTRL);
+	writeb_relaxed(0x78, base + MIPHY_RX_EQU_GAIN_1);
+	writeb_relaxed(0x1b, base + MIPHY_SYNCHAR_CONTROL);
+
+	/* TX compensation offset to re-center TX impedance */
+	writeb_relaxed(0x02, base + MIPHY_COMP_POSTP);
+
+	/* Enable GENSEL_SEL and SSC */
+	/* TX_SEL=0 swing preemp forced by pipe registres */
+	val = SSC_SEL | GENSEL_SEL;
+	writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
+
+	/* MIPHY Bias boost */
+	writeb_relaxed(0x00, base + MIPHY_BIAS_BOOST_1);
+	writeb_relaxed(0xa7, base + MIPHY_BIAS_BOOST_2);
+
+	/* SSC modulation */
+	writeb_relaxed(SSC_EN_SW, base + MIPHY_BOUNDARY_2);
+
+	/* MIPHY TX control */
+	writeb_relaxed(0x00, base + MIPHY_CONF);
+
+	/* Validate Step component */
+	writeb_relaxed(0x5a, base + MIPHY_PLL_SBR_3);
+	writeb_relaxed(0xa0, base + MIPHY_PLL_SBR_4);
+
+	/* Validate Period component */
+	writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
+	writeb_relaxed(0xa1, base + MIPHY_PLL_SBR_4);
+
+	/* Clear any previous request */
+	writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+
+	/* requests the PLL to take in account new parameters */
+	writeb_relaxed(0x02, base + MIPHY_PLL_SBR_1);
+
+	/* To be sure there is no other pending requests */
+	writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+
+	/* Rx PI controller settings */
+	writeb_relaxed(0xca, base + MIPHY_RX_K_GAIN);
+
+	/* MIPHY RX input bridge control */
+	/* INPUT_BRIDGE_EN_SW=1, manual input bridge control[0]=1 */
+	writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
+	writeb_relaxed(0x29, base + MIPHY_RX_POWER_CTRL_1);
+	writeb_relaxed(0x1a, base + MIPHY_RX_POWER_CTRL_2);
+
+	/* MIPHY Reset for usb3 */
+	miphy28_usb3_miphy_reset(miphy_phy);
+}
+
+static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)
+{
+	unsigned long finish = jiffies + 5 * HZ;
+	u8 mask = HFC_PLL | HFC_RDY;
+	u8 val;
+
+	/*
+	 * For PCIe and USB3 check only that PLL and HFC are ready
+	 * For SATA check also that phy is ready!
+	 */
+	if (miphy_phy->type == PHY_TYPE_SATA)
+		mask |= PHY_RDY;
+
+	do {
+		val = readb_relaxed(miphy_phy->base + MIPHY_STATUS_1);
+		if ((val & mask) != mask)
+			cpu_relax();
+		else
+			return 0;
+	} while (!time_after_eq(jiffies, finish));
+
+	return -EBUSY;
+}
+
+static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
+{
+	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+	unsigned long finish = jiffies + 5 * HZ;
+	u32 val;
+
+	if (!miphy_phy->osc_rdy)
+		return 0;
+
+	if (!miphy_phy->syscfg_miphy_status)
+		return -EINVAL;
+
+	do {
+		regmap_read(miphy_dev->regmap, miphy_phy->syscfg_miphy_status,
+			    &val);
+
+		if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY)
+			cpu_relax();
+		else
+			return 0;
+	} while (!time_after_eq(jiffies, finish));
+
+	return -EBUSY;
+}
+
+static int miphy28lp_get_resource_byname(struct device_node *child,
+					  char *rname, struct resource *res)
+{
+	int index;
+
+	index = of_property_match_string(child, "reg-names", rname);
+	if (index < 0)
+		return -ENODEV;
+
+	return of_address_to_resource(child, index, res);
+}
+
+static int miphy28lp_get_one_addr(struct device *dev,
+				  struct device_node *child, char *rname,
+				  void __iomem **base)
+{
+	struct resource res;
+	int ret;
+
+	ret = miphy28lp_get_resource_byname(child, rname, &res);
+	if (!ret) {
+		*base = devm_ioremap(dev, res.start, resource_size(&res));
+		if (!*base) {
+			dev_err(dev, "failed to ioremap %s address region\n"
+					, rname);
+			return -ENOENT;
+		}
+	}
+
+	return 0;
+}
+
+/* MiPHY reset and sysconf setup */
+static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)
+{
+	int err;
+	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+
+	if (!miphy_phy->syscfg_miphy_ctrl)
+		return -EINVAL;
+
+	err = reset_control_assert(miphy_phy->miphy_rst);
+	if (err) {
+		dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
+		return err;
+	}
+
+	if (miphy_phy->osc_force_ext)
+		miphy_val |= MIPHY_OSC_FORCE_EXT;
+
+	regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_miphy_ctrl,
+			   MIPHY_CTRL_MASK, miphy_val);
+
+	err = reset_control_deassert(miphy_phy->miphy_rst);
+	if (err) {
+		dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
+		return err;
+	}
+
+	return miphy_osc_is_ready(miphy_phy);
+}
+
+static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)
+{
+	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+	int err, sata_conf = SATA_CTRL_SELECT_SATA;
+
+	if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci)
+		|| (!miphy_phy->base))
+		return -EINVAL;
+
+	dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base);
+
+	/* Configure the glue-logic */
+	sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE);
+
+	regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata,
+			   SATA_CTRL_MASK, sata_conf);
+
+	regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci,
+			   PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
+
+	/* MiPHY path and clocking init */
+	err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);
+
+	if (err) {
+		dev_err(miphy_dev->dev, "SATA phy setup failed\n");
+		return err;
+	}
+
+	/* initialize miphy */
+	miphy28lp_configure_sata(miphy_phy);
+
+	return miphy_is_ready(miphy_phy);
+}
+
+static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy)
+{
+	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+	int err;
+
+	if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci)
+		|| (!miphy_phy->base) || (!miphy_phy->pipebase))
+		return -EINVAL;
+
+	dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base);
+
+	/* Configure the glue-logic */
+	regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata,
+			   SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
+
+	regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci,
+			   PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL);
+
+	/* MiPHY path and clocking init */
+	err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);
+
+	if (err) {
+		dev_err(miphy_dev->dev, "PCIe phy setup failed\n");
+		return err;
+	}
+
+	/* initialize miphy */
+	err = miphy28lp_configure_pcie(miphy_phy);
+	if (err)
+		return err;
+
+	/* PIPE Wrapper Configuration */
+	writeb_relaxed(0x68, miphy_phy->pipebase + 0x104); /* Rise_0 */
+	writeb_relaxed(0x61, miphy_phy->pipebase + 0x105); /* Rise_1 */
+	writeb_relaxed(0x68, miphy_phy->pipebase + 0x108); /* Fall_0 */
+	writeb_relaxed(0x61, miphy_phy->pipebase + 0x109); /* Fall-1 */
+	writeb_relaxed(0x68, miphy_phy->pipebase + 0x10c); /* Threshold_0 */
+	writeb_relaxed(0x60, miphy_phy->pipebase + 0x10d); /* Threshold_1 */
+
+	/* Wait for phy_ready */
+	return miphy_is_ready(miphy_phy);
+}
+
+static int miphy28lp_init_usb3(struct miphy28lp_phy *miphy_phy)
+{
+	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+	int err;
+
+	if ((!miphy_phy->base) || (!miphy_phy->pipebase))
+		return -EINVAL;
+
+	dev_info(miphy_dev->dev, "usb3-up mode, addr 0x%p\n", miphy_phy->base);
+
+	/* MiPHY path and clocking init */
+	err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_SYNC_D_EN);
+	if (err) {
+		dev_err(miphy_dev->dev, "USB3 phy setup failed\n");
+		return err;
+	}
+
+	/* initialize miphy */
+	miphy28lp_configure_usb3(miphy_phy);
+
+	/* PIPE Wrapper Configuration */
+	writeb_relaxed(0x68, miphy_phy->pipebase + 0x23);
+	writeb_relaxed(0x61, miphy_phy->pipebase + 0x24);
+	writeb_relaxed(0x68, miphy_phy->pipebase + 0x26);
+	writeb_relaxed(0x61, miphy_phy->pipebase + 0x27);
+	writeb_relaxed(0x18, miphy_phy->pipebase + 0x29);
+	writeb_relaxed(0x61, miphy_phy->pipebase + 0x2a);
+
+	/* pipe Wrapper usb3 TX swing de-emph margin PREEMPH[7:4], SWING[3:0] */
+	writeb_relaxed(0X67, miphy_phy->pipebase + 0x68);
+	writeb_relaxed(0x0d, miphy_phy->pipebase + 0x69);
+	writeb_relaxed(0X67, miphy_phy->pipebase + 0x6a);
+	writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6b);
+	writeb_relaxed(0X67, miphy_phy->pipebase + 0x6c);
+	writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6d);
+	writeb_relaxed(0X67, miphy_phy->pipebase + 0x6e);
+	writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6f);
+
+	return miphy_is_ready(miphy_phy);
+}
+
+static int miphy28lp_init(struct phy *phy)
+{
+	struct miphy28lp_phy *miphy_phy = phy_get_drvdata(phy);
+	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+	int ret;
+
+	mutex_lock(&miphy_dev->miphy_mutex);
+
+	switch (miphy_phy->type) {
+
+	case PHY_TYPE_SATA:
+		ret = miphy28lp_init_sata(miphy_phy);
+		break;
+	case PHY_TYPE_PCIE:
+		ret = miphy28lp_init_pcie(miphy_phy);
+		break;
+	case PHY_TYPE_USB3:
+		ret = miphy28lp_init_usb3(miphy_phy);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	mutex_unlock(&miphy_dev->miphy_mutex);
+
+	return ret;
+}
+
+static int miphy28lp_get_addr(struct miphy28lp_phy *miphy_phy)
+{
+	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+	struct device_node *phynode = miphy_phy->phy->dev.of_node;
+	int err;
+
+	if ((miphy_phy->type != PHY_TYPE_SATA) &&
+	    (miphy_phy->type != PHY_TYPE_PCIE) &&
+	    (miphy_phy->type != PHY_TYPE_USB3)) {
+		return -EINVAL;
+	}
+
+	err = miphy28lp_get_one_addr(miphy_dev->dev, phynode,
+			PHY_TYPE_name[miphy_phy->type - PHY_TYPE_SATA],
+			&miphy_phy->base);
+	if (err)
+		return err;
+
+	if ((miphy_phy->type == PHY_TYPE_PCIE) ||
+	    (miphy_phy->type == PHY_TYPE_USB3)) {
+		err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, "pipew",
+					     &miphy_phy->pipebase);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static struct phy *miphy28lp_xlate(struct device *dev,
+				   struct of_phandle_args *args)
+{
+	struct miphy28lp_dev *miphy_dev = dev_get_drvdata(dev);
+	struct miphy28lp_phy *miphy_phy = NULL;
+	struct device_node *phynode = args->np;
+	int ret, index = 0;
+
+	if (!of_device_is_available(phynode)) {
+		dev_warn(dev, "Requested PHY is disabled\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	if (args->args_count != 1) {
+		dev_err(dev, "Invalid number of cells in 'phy' property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	for (index = 0; index < of_get_child_count(dev->of_node); index++)
+		if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
+			miphy_phy = miphy_dev->phys[index];
+			break;
+		}
+
+	if (!miphy_phy) {
+		dev_err(dev, "Failed to find appropriate phy\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	miphy_phy->type = args->args[0];
+
+	ret = miphy28lp_get_addr(miphy_phy);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	return miphy_phy->phy;
+}
+
+static struct phy_ops miphy28lp_ops = {
+	.init = miphy28lp_init,
+};
+
+static int miphy28lp_probe_resets(struct device_node *node,
+				  struct miphy28lp_phy *miphy_phy)
+{
+	struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
+	int err;
+
+	miphy_phy->miphy_rst = of_reset_control_get(node, "miphy-sw-rst");
+
+	if (IS_ERR(miphy_phy->miphy_rst)) {
+		dev_err(miphy_dev->dev,
+				"miphy soft reset control not defined\n");
+		return PTR_ERR(miphy_phy->miphy_rst);
+	}
+
+	err = reset_control_deassert(miphy_phy->miphy_rst);
+	if (err) {
+		dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int miphy28lp_of_probe(struct device_node *np,
+			      struct miphy28lp_phy *miphy_phy)
+{
+	struct resource res;
+
+	miphy_phy->osc_force_ext =
+		of_property_read_bool(np, "st,osc-force-ext");
+
+	miphy_phy->osc_rdy = of_property_read_bool(np, "st,osc-rdy");
+
+	miphy_phy->px_rx_pol_inv =
+		of_property_read_bool(np, "st,px_rx_pol_inv");
+
+	of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen);
+	if (!miphy_phy->sata_gen)
+		miphy_phy->sata_gen = SATA_GEN1;
+
+	if (!miphy28lp_get_resource_byname(np, "miphy-ctrl-glue", &res))
+		miphy_phy->syscfg_miphy_ctrl = res.start;
+
+	if (!miphy28lp_get_resource_byname(np, "miphy-status-glue", &res))
+		miphy_phy->syscfg_miphy_status = res.start;
+
+	if (!miphy28lp_get_resource_byname(np, "pcie-glue", &res))
+		miphy_phy->syscfg_pci = res.start;
+
+	if (!miphy28lp_get_resource_byname(np, "sata-glue", &res))
+		miphy_phy->syscfg_sata = res.start;
+
+
+	return 0;
+}
+
+static int miphy28lp_probe(struct platform_device *pdev)
+{
+	struct device_node *child, *np = pdev->dev.of_node;
+	struct miphy28lp_dev *miphy_dev;
+	struct phy_provider *provider;
+	struct phy *phy;
+	int chancount, port = 0;
+	int ret;
+
+	miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
+	if (!miphy_dev)
+		return -ENOMEM;
+
+	chancount = of_get_child_count(np);
+	miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount,
+				       GFP_KERNEL);
+	if (!miphy_dev->phys)
+		return -ENOMEM;
+
+	miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+	if (IS_ERR(miphy_dev->regmap)) {
+		dev_err(miphy_dev->dev, "No syscfg phandle specified\n");
+		return PTR_ERR(miphy_dev->regmap);
+	}
+
+	miphy_dev->dev = &pdev->dev;
+
+	dev_set_drvdata(&pdev->dev, miphy_dev);
+
+	mutex_init(&miphy_dev->miphy_mutex);
+
+	for_each_child_of_node(np, child) {
+		struct miphy28lp_phy *miphy_phy;
+
+		miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
+					 GFP_KERNEL);
+		if (!miphy_phy)
+			return -ENOMEM;
+
+		miphy_dev->phys[port] = miphy_phy;
+
+		phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops, NULL);
+		if (IS_ERR(phy)) {
+			dev_err(&pdev->dev, "failed to create PHY\n");
+			return PTR_ERR(phy);
+		}
+
+		miphy_dev->phys[port]->phy = phy;
+		miphy_dev->phys[port]->phydev = miphy_dev;
+
+		ret = miphy28lp_of_probe(child, miphy_phy);
+		if (ret)
+			return ret;
+
+		ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]);
+		if (ret)
+			return ret;
+
+		phy_set_drvdata(phy, miphy_dev->phys[port]);
+		port++;
+
+	}
+
+	provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);
+	if (IS_ERR(provider))
+		return PTR_ERR(provider);
+
+	return 0;
+}
+
+static const struct of_device_id miphy28lp_of_match[] = {
+	{.compatible = "st,miphy28lp-phy", },
+	{},
+};
+
+MODULE_DEVICE_TABLE(of, miphy28lp_of_match);
+
+static struct platform_driver miphy28lp_driver = {
+	.probe = miphy28lp_probe,
+	.driver = {
+		.name = "miphy28lp-phy",
+		.owner = THIS_MODULE,
+		.of_match_table = miphy28lp_of_match,
+	}
+};
+
+module_platform_driver(miphy28lp_driver);
+
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics miphy28lp driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5


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

* [PATCH 04/25] phy: miphy28lp: Add SSC support for SATA
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (2 preceding siblings ...)
  2014-11-27  6:25 ` [PATCH 03/25] phy: miphy28lp: Provide support for the MiPHY28lp Generic PHY Kishon Vijay Abraham I
@ 2014-11-27  6:25 ` Kishon Vijay Abraham I
  2014-11-27  6:25 ` [PATCH 05/25] phy: miphy28lp: Add SSC support for PCIE Kishon Vijay Abraham I
                   ` (21 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:25 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Gabriel FERNANDEZ <gabriel.fernandez@st.com>

This patch to tune on/off the ssc on miphy sata setup.
User can now enable ssc via dt blob, it is useful to reduce
effects of EMI.

Signed-off-by: Giuseppe Condorelli <giuseppe.condorelli@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/phy-miphy28lp.txt      |    1 +
 drivers/phy/phy-miphy28lp.c                        |   46 ++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt b/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
index b7c13ad..4a3b4af 100644
--- a/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
+++ b/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
@@ -39,6 +39,7 @@ Optional properties (port (child) node):
 			  register.
 - st,px_rx_pol_inv	: to invert polarity of RXn/RXp (respectively negative line and positive
 			  line).
+- st,scc-on		: enable ssc to reduce effects of EMI (only for sata or PCIe).
 
 example:
 
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
index 7d592e6..d2f797c 100644
--- a/drivers/phy/phy-miphy28lp.c
+++ b/drivers/phy/phy-miphy28lp.c
@@ -191,6 +191,8 @@
 #define SYSCFG_PCIE_PCIE_VAL	0x80
 #define SATA_SPDMODE		1
 
+#define MIPHY_SATA_BANK_NB	3
+
 struct miphy28lp_phy {
 	struct phy *phy;
 	struct miphy28lp_dev *phydev;
@@ -200,6 +202,7 @@ struct miphy28lp_phy {
 	bool osc_force_ext;
 	bool osc_rdy;
 	bool px_rx_pol_inv;
+	bool ssc;
 
 	struct reset_control *miphy_rst;
 
@@ -550,6 +553,44 @@ static inline void miphy28_usb3_miphy_reset(struct miphy28lp_phy *miphy_phy)
 	writeb_relaxed(0x00, base + MIPHY_CONF);
 }
 
+static void miphy_sata_tune_ssc(struct miphy28lp_phy *miphy_phy)
+{
+	void __iomem *base = miphy_phy->base;
+	u8 val;
+
+	/* Compensate Tx impedance to avoid out of range values */
+	/*
+	 * Enable the SSC on PLL for all banks
+	 * SSC Modulation @ 31 KHz and 4000 ppm modulation amp
+	 */
+	val = readb_relaxed(base + MIPHY_BOUNDARY_2);
+	val |= SSC_EN_SW;
+	writeb_relaxed(val, base + MIPHY_BOUNDARY_2);
+
+	val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);
+	val |= SSC_SEL;
+	writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
+
+	for (val = 0; val < MIPHY_SATA_BANK_NB; val++) {
+		writeb_relaxed(val, base + MIPHY_CONF);
+
+		/* Add value to each reference clock cycle  */
+		/* and define the period length of the SSC */
+		writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
+		writeb_relaxed(0x6c, base + MIPHY_PLL_SBR_3);
+		writeb_relaxed(0x81, base + MIPHY_PLL_SBR_4);
+
+		/* Clear any previous request */
+		writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+
+		/* requests the PLL to take in account new parameters */
+		writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
+
+		/* To be sure there is no other pending requests */
+		writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+	}
+}
+
 static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)
 {
 	void __iomem *base = miphy_phy->base;
@@ -585,6 +626,9 @@ static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)
 		writeb_relaxed(val, miphy_phy->base + MIPHY_CONTROL);
 	}
 
+	if (miphy_phy->ssc)
+		miphy_sata_tune_ssc(miphy_phy);
+
 	return 0;
 }
 
@@ -1064,6 +1108,8 @@ static int miphy28lp_of_probe(struct device_node *np,
 	miphy_phy->px_rx_pol_inv =
 		of_property_read_bool(np, "st,px_rx_pol_inv");
 
+	miphy_phy->ssc = of_property_read_bool(np, "st,ssc-on");
+
 	of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen);
 	if (!miphy_phy->sata_gen)
 		miphy_phy->sata_gen = SATA_GEN1;
-- 
1.7.9.5


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

* [PATCH 05/25] phy: miphy28lp: Add SSC support for PCIE
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (3 preceding siblings ...)
  2014-11-27  6:25 ` [PATCH 04/25] phy: miphy28lp: Add SSC support for SATA Kishon Vijay Abraham I
@ 2014-11-27  6:25 ` Kishon Vijay Abraham I
  2014-11-27  6:25 ` [PATCH 06/25] phy: miphy28lp: Tune tx impedance across Soc cuts Kishon Vijay Abraham I
                   ` (20 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:25 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Gabriel FERNANDEZ <gabriel.fernandez@st.com>

SSC is the technique of modulating the operating frequency of a signal
slightly to spread its radiated emissions over a range of frequencies.
This reduction in the maximum emission for a given frequency helps meet
radiated emission requirements.
These settings are applicable for PCIE with Internal clock.

Signed-off-by: Harsh Gupta <harsh.gupta@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-miphy28lp.c |   44 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
index d2f797c..d8ff895 100644
--- a/drivers/phy/phy-miphy28lp.c
+++ b/drivers/phy/phy-miphy28lp.c
@@ -192,6 +192,7 @@
 #define SATA_SPDMODE		1
 
 #define MIPHY_SATA_BANK_NB	3
+#define MIPHY_PCIE_BANK_NB	2
 
 struct miphy28lp_phy {
 	struct phy *phy;
@@ -591,6 +592,46 @@ static void miphy_sata_tune_ssc(struct miphy28lp_phy *miphy_phy)
 	}
 }
 
+static void miphy_pcie_tune_ssc(struct miphy28lp_phy *miphy_phy)
+{
+	void __iomem *base = miphy_phy->base;
+	u8 val;
+
+	/* Compensate Tx impedance to avoid out of range values */
+	/*
+	 * Enable the SSC on PLL for all banks
+	 * SSC Modulation @ 31 KHz and 4000 ppm modulation amp
+	 */
+	val = readb_relaxed(base + MIPHY_BOUNDARY_2);
+	val |= SSC_EN_SW;
+	writeb_relaxed(val, base + MIPHY_BOUNDARY_2);
+
+	val = readb_relaxed(base + MIPHY_BOUNDARY_SEL);
+	val |= SSC_SEL;
+	writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
+
+	for (val = 0; val < MIPHY_PCIE_BANK_NB; val++) {
+		writeb_relaxed(val, base + MIPHY_CONF);
+
+		/* Validate Step component */
+		writeb_relaxed(0x69, base + MIPHY_PLL_SBR_3);
+		writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);
+
+		/* Validate Period component */
+		writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
+		writeb_relaxed(0x21, base + MIPHY_PLL_SBR_4);
+
+		/* Clear any previous request */
+		writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+
+		/* requests the PLL to take in account new parameters */
+		writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
+
+		/* To be sure there is no other pending requests */
+		writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
+	}
+}
+
 static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)
 {
 	void __iomem *base = miphy_phy->base;
@@ -659,6 +700,9 @@ static inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy)
 	if (err)
 		return err;
 
+	if (miphy_phy->ssc)
+		miphy_pcie_tune_ssc(miphy_phy);
+
 	return 0;
 }
 
-- 
1.7.9.5


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

* [PATCH 06/25] phy: miphy28lp: Tune tx impedance across Soc cuts
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (4 preceding siblings ...)
  2014-11-27  6:25 ` [PATCH 05/25] phy: miphy28lp: Add SSC support for PCIE Kishon Vijay Abraham I
@ 2014-11-27  6:25 ` Kishon Vijay Abraham I
  2014-11-27  6:25 ` [PATCH 07/25] phy: phy-core: use the np present in of_phandle_args to get the PHY Kishon Vijay Abraham I
                   ` (19 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:25 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Gabriel FERNANDEZ <gabriel.fernandez@st.com>

This patch to compensate tx impedance (Sata, PCIe)
depending on Soc cuts the kernel is built for.

Signed-off-by: Giuseppe Condorelli <giuseppe.condorelli@st.com>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/phy-miphy28lp.txt      |    1 +
 drivers/phy/phy-miphy28lp.c                        |   16 ++++++++++++++++
 2 files changed, 17 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt b/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
index 4a3b4af..46a135d 100644
--- a/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
+++ b/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
@@ -40,6 +40,7 @@ Optional properties (port (child) node):
 - st,px_rx_pol_inv	: to invert polarity of RXn/RXp (respectively negative line and positive
 			  line).
 - st,scc-on		: enable ssc to reduce effects of EMI (only for sata or PCIe).
+- st,tx-impedance-comp	: to compensate tx impedance avoiding out of range values.
 
 example:
 
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
index d8ff895..87dcc9a 100644
--- a/drivers/phy/phy-miphy28lp.c
+++ b/drivers/phy/phy-miphy28lp.c
@@ -204,6 +204,7 @@ struct miphy28lp_phy {
 	bool osc_rdy;
 	bool px_rx_pol_inv;
 	bool ssc;
+	bool tx_impedance;
 
 	struct reset_control *miphy_rst;
 
@@ -632,6 +633,12 @@ static void miphy_pcie_tune_ssc(struct miphy28lp_phy *miphy_phy)
 	}
 }
 
+static inline void miphy_tune_tx_impedance(struct miphy28lp_phy *miphy_phy)
+{
+	/* Compensate Tx impedance to avoid out of range values */
+	writeb_relaxed(0x02, miphy_phy->base + MIPHY_COMP_POSTP);
+}
+
 static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)
 {
 	void __iomem *base = miphy_phy->base;
@@ -670,6 +677,9 @@ static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)
 	if (miphy_phy->ssc)
 		miphy_sata_tune_ssc(miphy_phy);
 
+	if (miphy_phy->tx_impedance)
+		miphy_tune_tx_impedance(miphy_phy);
+
 	return 0;
 }
 
@@ -703,6 +713,9 @@ static inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy)
 	if (miphy_phy->ssc)
 		miphy_pcie_tune_ssc(miphy_phy);
 
+	if (miphy_phy->tx_impedance)
+		miphy_tune_tx_impedance(miphy_phy);
+
 	return 0;
 }
 
@@ -1154,6 +1167,9 @@ static int miphy28lp_of_probe(struct device_node *np,
 
 	miphy_phy->ssc = of_property_read_bool(np, "st,ssc-on");
 
+	miphy_phy->tx_impedance =
+		of_property_read_bool(np, "st,tx-impedance-comp");
+
 	of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen);
 	if (!miphy_phy->sata_gen)
 		miphy_phy->sata_gen = SATA_GEN1;
-- 
1.7.9.5


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

* [PATCH 07/25] phy: phy-core: use the np present in of_phandle_args to get the PHY
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (5 preceding siblings ...)
  2014-11-27  6:25 ` [PATCH 06/25] phy: miphy28lp: Tune tx impedance across Soc cuts Kishon Vijay Abraham I
@ 2014-11-27  6:25 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 08/25] phy: sun4i: add support for USB phy0 Kishon Vijay Abraham I
                   ` (18 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:25 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

Instead of using the node pointer of the PHY provider and then scanning its
child nodes to get a reference to the PHY, directly use the node pointer
present in of_phandle_args to get a reference to the PHY.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-core.c |   10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index ff5eec5..1606ce9 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -414,21 +414,13 @@ struct phy *of_phy_simple_xlate(struct device *dev, struct of_phandle_args
 {
 	struct phy *phy;
 	struct class_dev_iter iter;
-	struct device_node *node = dev->of_node;
-	struct device_node *child;
 
 	class_dev_iter_init(&iter, phy_class, NULL, NULL);
 	while ((dev = class_dev_iter_next(&iter))) {
 		phy = to_phy(dev);
-		if (node != phy->dev.of_node) {
-			for_each_child_of_node(node, child) {
-				if (child == phy->dev.of_node)
-					goto phy_found;
-			}
+		if (args->np != phy->dev.of_node)
 			continue;
-		}
 
-phy_found:
 		class_dev_iter_exit(&iter);
 		return phy;
 	}
-- 
1.7.9.5


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

* [PATCH 08/25] phy: sun4i: add support for USB phy0
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (6 preceding siblings ...)
  2014-11-27  6:25 ` [PATCH 07/25] phy: phy-core: use the np present in of_phandle_args to get the PHY Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 09/25] phy: berlin-sata: Move PHY_BASE into private data struct Kishon Vijay Abraham I
                   ` (17 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Roman Byshko <rbyshko@gmail.com>

The driver for sun4i USB phys currently supports
only phy1 and phy2 which are used for USB host
controllers. This patch adds support for USB phy0,
which is used by the musb hdrc USB controller.

Signed-off-by: Roman Byshko <rbyshko@gmail.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-sun4i-usb.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 0baf5ef..6bd2b0c 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -157,6 +157,10 @@ static int sun4i_usb_phy_init(struct phy *_phy)
 		return ret;
 	}
 
+	/* Enable USB 45 Ohm resistor calibration */
+	if (phy->index == 0)
+		sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1);
+
 	/* Adjust PHY's magnitude and rate */
 	sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE, 0x14, 5);
 
@@ -213,7 +217,7 @@ static struct phy *sun4i_usb_phy_xlate(struct device *dev,
 {
 	struct sun4i_usb_phy_data *data = dev_get_drvdata(dev);
 
-	if (WARN_ON(args->args[0] == 0 || args->args[0] >= data->num_phys))
+	if (args->args[0] >= data->num_phys)
 		return ERR_PTR(-ENODEV);
 
 	return data->phys[args->args[0]].phy;
@@ -255,8 +259,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 	if (IS_ERR(data->base))
 		return PTR_ERR(data->base);
 
-	/* Skip 0, 0 is the phy for otg which is not yet supported. */
-	for (i = 1; i < data->num_phys; i++) {
+	for (i = 0; i < data->num_phys; i++) {
 		struct sun4i_usb_phy *phy = data->phys + i;
 		char name[16];
 
-- 
1.7.9.5


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

* [PATCH 09/25] phy: berlin-sata: Move PHY_BASE into private data struct
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (7 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 08/25] phy: sun4i: add support for USB phy0 Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 10/25] phy: berlin-sata: Add support for BG2 SATA PHY Kishon Vijay Abraham I
                   ` (16 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

Currently, Berlin SATA PHY driver assumes PHY_BASE address being
constant. While this PHY_BASE is correct for BG2Q, older BG2 PHY_BASE
is different. Prepare the driver for BG2 support by moving the phy_base
into private driver data.

Acked-by: Antoine Ténart <antoine.tenart@free-electrons.com>
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-berlin-sata.c |   24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
index 69ced52..cdb46d1 100644
--- a/drivers/phy/phy-berlin-sata.c
+++ b/drivers/phy/phy-berlin-sata.c
@@ -30,7 +30,7 @@
 #define MBUS_WRITE_REQUEST_SIZE_128	(BIT(2) << 16)
 #define MBUS_READ_REQUEST_SIZE_128	(BIT(2) << 19)
 
-#define PHY_BASE		0x200
+#define BG2Q_PHY_BASE		0x200
 
 /* register 0x01 */
 #define REF_FREF_SEL_25		BIT(0)
@@ -61,15 +61,16 @@ struct phy_berlin_priv {
 	struct clk		*clk;
 	struct phy_berlin_desc	**phys;
 	unsigned		nphys;
+	u32			phy_base;
 };
 
-static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, u32 reg,
-					       u32 mask, u32 val)
+static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg,
+			       u32 phy_base, u32 reg, u32 mask, u32 val)
 {
 	u32 regval;
 
 	/* select register */
-	writel(PHY_BASE + reg, ctrl_reg + PORT_VSR_ADDR);
+	writel(phy_base + reg, ctrl_reg + PORT_VSR_ADDR);
 
 	/* set bits */
 	regval = readl(ctrl_reg + PORT_VSR_DATA);
@@ -103,17 +104,20 @@ static int phy_berlin_sata_power_on(struct phy *phy)
 	writel(regval, priv->base + HOST_VSA_DATA);
 
 	/* set PHY mode and ref freq to 25 MHz */
-	phy_berlin_sata_reg_setbits(ctrl_reg, 0x1, 0xff,
-				    REF_FREF_SEL_25 | PHY_MODE_SATA);
+	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
+				    0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA);
 
 	/* set PHY up to 6 Gbps */
-	phy_berlin_sata_reg_setbits(ctrl_reg, 0x25, 0xc00, PHY_GEN_MAX_6_0);
+	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
+				    0x0c00, PHY_GEN_MAX_6_0);
 
 	/* set 40 bits width */
-	phy_berlin_sata_reg_setbits(ctrl_reg, 0x23,  0xc00, DATA_BIT_WIDTH_40);
+	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x23,
+				    0x0c00, DATA_BIT_WIDTH_40);
 
 	/* use max pll rate */
-	phy_berlin_sata_reg_setbits(ctrl_reg, 0x2, 0x0, USE_MAX_PLL_RATE);
+	phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x02,
+				    0x0000, USE_MAX_PLL_RATE);
 
 	/* set Gen3 controller speed */
 	regval = readl(ctrl_reg + PORT_SCR_CTL);
@@ -218,6 +222,8 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
 	if (!priv->phys)
 		return -ENOMEM;
 
+	priv->phy_base = BG2Q_PHY_BASE;
+
 	dev_set_drvdata(dev, priv);
 	spin_lock_init(&priv->lock);
 
-- 
1.7.9.5


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

* [PATCH 10/25] phy: berlin-sata: Add support for BG2 SATA PHY
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (8 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 09/25] phy: berlin-sata: Move PHY_BASE into private data struct Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 11/25] phy: berlin-sata: Document BG2 compatible Kishon Vijay Abraham I
                   ` (15 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

Berlin BG2 also has a SATA PHY compatible with the current driver
except different PHY_BASE. Add a new compatible to the driver
reflecting the different PHY_BASE.

Acked-by: Antoine Ténart <antoine.tenart@free-electrons.com>
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-berlin-sata.c |    7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
index cdb46d1..873e7a8 100644
--- a/drivers/phy/phy-berlin-sata.c
+++ b/drivers/phy/phy-berlin-sata.c
@@ -30,6 +30,7 @@
 #define MBUS_WRITE_REQUEST_SIZE_128	(BIT(2) << 16)
 #define MBUS_READ_REQUEST_SIZE_128	(BIT(2) << 19)
 
+#define BG2_PHY_BASE		0x080
 #define BG2Q_PHY_BASE		0x200
 
 /* register 0x01 */
@@ -222,7 +223,10 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
 	if (!priv->phys)
 		return -ENOMEM;
 
-	priv->phy_base = BG2Q_PHY_BASE;
+	if (of_device_is_compatible(dev->of_node, "marvell,berlin2-sata-phy"))
+		priv->phy_base = BG2_PHY_BASE;
+	else
+		priv->phy_base = BG2Q_PHY_BASE;
 
 	dev_set_drvdata(dev, priv);
 	spin_lock_init(&priv->lock);
@@ -271,6 +275,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id phy_berlin_sata_of_match[] = {
+	{ .compatible = "marvell,berlin2-sata-phy" },
 	{ .compatible = "marvell,berlin2q-sata-phy" },
 	{ },
 };
-- 
1.7.9.5


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

* [PATCH 11/25] phy: berlin-sata: Document BG2 compatible
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (9 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 10/25] phy: berlin-sata: Add support for BG2 SATA PHY Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 12/25] phy: add the Berlin USB PHY driver Kishon Vijay Abraham I
                   ` (14 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>

Berlin BG2 SATA PHY is slightly different from currently supported
BG2Q SATA PHY. Document the new compatible for BG2's PHY.

Acked-by: Antoine Ténart <antoine.tenart@free-electrons.com>
Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/berlin-sata-phy.txt    |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt b/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
index 88f8c23..c0155f8 100644
--- a/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
+++ b/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
@@ -2,7 +2,9 @@ Berlin SATA PHY
 ---------------
 
 Required properties:
-- compatible: should be "marvell,berlin2q-sata-phy"
+- compatible: should be one of
+    "marvell,berlin2-sata-phy"
+    "marvell,berlin2q-sata-phy"
 - address-cells: should be 1
 - size-cells: should be 0
 - phy-cells: from the generic PHY bindings, must be 1
-- 
1.7.9.5


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

* [PATCH 12/25] phy: add the Berlin USB PHY driver
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (10 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 11/25] phy: berlin-sata: Document BG2 compatible Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 13/25] Documentation: bindings: add doc for the Berlin USB PHY Kishon Vijay Abraham I
                   ` (13 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Antoine Tenart <antoine.tenart@free-electrons.com>

Add the driver driving the Marvell Berlin USB PHY. This allows to
initialize the PHY and to use it from the USB driver later.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig          |    7 ++
 drivers/phy/Makefile         |    1 +
 drivers/phy/phy-berlin-usb.c |  224 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 232 insertions(+)
 create mode 100644 drivers/phy/phy-berlin-usb.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index cfaced9..4144d25 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -15,6 +15,13 @@ config GENERIC_PHY
 	  phy users can obtain reference to the PHY. All the users of this
 	  framework should select this config.
 
+config PHY_BERLIN_USB
+	tristate "Marvell Berlin USB PHY Driver"
+	depends on ARCH_BERLIN && RESET_CONTROLLER && HAS_IOMEM && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the USB PHY on Marvell Berlin SoCs.
+
 config PHY_BERLIN_SATA
 	tristate "Marvell Berlin SATA PHY driver"
 	depends on ARCH_BERLIN && HAS_IOMEM && OF
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 30d90a8..68022f6 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
+obj-$(CONFIG_PHY_BERLIN_USB)		+= phy-berlin-usb.o
 obj-$(CONFIG_PHY_BERLIN_SATA)		+= phy-berlin-sata.o
 obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c
new file mode 100644
index 0000000..f9f1306
--- /dev/null
+++ b/drivers/phy/phy-berlin-usb.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Tenart <antoine.tenart@free-electrons.com>
+ * Jisheng Zhang <jszhang@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/gpio.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define USB_PHY_PLL		0x04
+#define USB_PHY_PLL_CONTROL	0x08
+#define USB_PHY_TX_CTRL0	0x10
+#define USB_PHY_TX_CTRL1	0x14
+#define USB_PHY_TX_CTRL2	0x18
+#define USB_PHY_RX_CTRL		0x20
+#define USB_PHY_ANALOG		0x34
+
+/* USB_PHY_PLL */
+#define CLK_REF_DIV(x)		((x) << 4)
+#define FEEDBACK_CLK_DIV(x)	((x) << 8)
+
+/* USB_PHY_PLL_CONTROL */
+#define CLK_STABLE		BIT(0)
+#define PLL_CTRL_PIN		BIT(1)
+#define PLL_CTRL_REG		BIT(2)
+#define PLL_ON			BIT(3)
+#define PHASE_OFF_TOL_125	(0x0 << 5)
+#define PHASE_OFF_TOL_250	BIT(5)
+#define KVC0_CALIB		(0x0 << 9)
+#define KVC0_REG_CTRL		BIT(9)
+#define KVC0_HIGH		(0x0 << 10)
+#define KVC0_LOW		(0x3 << 10)
+#define CLK_BLK_EN		BIT(13)
+
+/* USB_PHY_TX_CTRL0 */
+#define EXT_HS_RCAL_EN		BIT(3)
+#define EXT_FS_RCAL_EN		BIT(4)
+#define IMPCAL_VTH_DIV(x)	((x) << 5)
+#define EXT_RS_RCAL_DIV(x)	((x) << 8)
+#define EXT_FS_RCAL_DIV(x)	((x) << 12)
+
+/* USB_PHY_TX_CTRL1 */
+#define TX_VDD15_14		(0x0 << 4)
+#define TX_VDD15_15		BIT(4)
+#define TX_VDD15_16		(0x2 << 4)
+#define TX_VDD15_17		(0x3 << 4)
+#define TX_VDD12_VDD		(0x0 << 6)
+#define TX_VDD12_11		BIT(6)
+#define TX_VDD12_12		(0x2 << 6)
+#define TX_VDD12_13		(0x3 << 6)
+#define LOW_VDD_EN		BIT(8)
+#define TX_OUT_AMP(x)		((x) << 9)
+
+/* USB_PHY_TX_CTRL2 */
+#define TX_CHAN_CTRL_REG(x)	((x) << 0)
+#define DRV_SLEWRATE(x)		((x) << 4)
+#define IMP_CAL_FS_HS_DLY_0	(0x0 << 6)
+#define IMP_CAL_FS_HS_DLY_1	BIT(6)
+#define IMP_CAL_FS_HS_DLY_2	(0x2 << 6)
+#define IMP_CAL_FS_HS_DLY_3	(0x3 << 6)
+#define FS_DRV_EN_MASK(x)	((x) << 8)
+#define HS_DRV_EN_MASK(x)	((x) << 12)
+
+/* USB_PHY_RX_CTRL */
+#define PHASE_FREEZE_DLY_2_CL	(0x0 << 0)
+#define PHASE_FREEZE_DLY_4_CL	BIT(0)
+#define ACK_LENGTH_8_CL		(0x0 << 2)
+#define ACK_LENGTH_12_CL	BIT(2)
+#define ACK_LENGTH_16_CL	(0x2 << 2)
+#define ACK_LENGTH_20_CL	(0x3 << 2)
+#define SQ_LENGTH_3		(0x0 << 4)
+#define SQ_LENGTH_6		BIT(4)
+#define SQ_LENGTH_9		(0x2 << 4)
+#define SQ_LENGTH_12		(0x3 << 4)
+#define DISCON_THRESHOLD_260	(0x0 << 6)
+#define DISCON_THRESHOLD_270	BIT(6)
+#define DISCON_THRESHOLD_280	(0x2 << 6)
+#define DISCON_THRESHOLD_290	(0x3 << 6)
+#define SQ_THRESHOLD(x)		((x) << 8)
+#define LPF_COEF(x)		((x) << 12)
+#define INTPL_CUR_10		(0x0 << 14)
+#define INTPL_CUR_20		BIT(14)
+#define INTPL_CUR_30		(0x2 << 14)
+#define INTPL_CUR_40		(0x3 << 14)
+
+/* USB_PHY_ANALOG */
+#define ANA_PWR_UP		BIT(1)
+#define ANA_PWR_DOWN		BIT(2)
+#define V2I_VCO_RATIO(x)	((x) << 7)
+#define R_ROTATE_90		(0x0 << 10)
+#define R_ROTATE_0		BIT(10)
+#define MODE_TEST_EN		BIT(11)
+#define ANA_TEST_DC_CTRL(x)	((x) << 12)
+
+#define to_phy_berlin_usb_priv(p)	\
+	container_of((p), struct phy_berlin_usb_priv, phy)
+
+static const u32 phy_berlin_pll_dividers[] = {
+	/* Berlin 2 */
+	CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
+	/* Berlin 2CD */
+	CLK_REF_DIV(0x6) | FEEDBACK_CLK_DIV(0x55),
+};
+
+struct phy_berlin_usb_priv {
+	void __iomem		*base;
+	struct phy		*phy;
+	struct reset_control	*rst_ctrl;
+	u32			pll_divider;
+};
+
+static int phy_berlin_usb_power_on(struct phy *phy)
+{
+	struct phy_berlin_usb_priv *priv = dev_get_drvdata(phy->dev.parent);
+
+	reset_control_reset(priv->rst_ctrl);
+
+	writel(priv->pll_divider,
+	       priv->base + USB_PHY_PLL);
+	writel(CLK_STABLE | PLL_CTRL_REG | PHASE_OFF_TOL_250 | KVC0_REG_CTRL |
+	       CLK_BLK_EN, priv->base + USB_PHY_PLL_CONTROL);
+	writel(V2I_VCO_RATIO(0x5) | R_ROTATE_0 | ANA_TEST_DC_CTRL(0x5),
+	       priv->base + USB_PHY_ANALOG);
+	writel(PHASE_FREEZE_DLY_4_CL | ACK_LENGTH_16_CL | SQ_LENGTH_12 |
+	       DISCON_THRESHOLD_260 | SQ_THRESHOLD(0xa) | LPF_COEF(0x2) |
+	       INTPL_CUR_30, priv->base + USB_PHY_RX_CTRL);
+
+	writel(TX_VDD12_13 | TX_OUT_AMP(0x3), priv->base + USB_PHY_TX_CTRL1);
+	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
+	       priv->base + USB_PHY_TX_CTRL0);
+
+	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4) |
+	       EXT_FS_RCAL_DIV(0x2), priv->base + USB_PHY_TX_CTRL0);
+
+	writel(EXT_HS_RCAL_EN | IMPCAL_VTH_DIV(0x3) | EXT_RS_RCAL_DIV(0x4),
+	       priv->base + USB_PHY_TX_CTRL0);
+	writel(TX_CHAN_CTRL_REG(0xf) | DRV_SLEWRATE(0x3) | IMP_CAL_FS_HS_DLY_3 |
+	       FS_DRV_EN_MASK(0xd), priv->base + USB_PHY_TX_CTRL2);
+
+	return 0;
+}
+
+static struct phy_ops phy_berlin_usb_ops = {
+	.power_on	= phy_berlin_usb_power_on,
+	.owner		= THIS_MODULE,
+};
+
+static const struct of_device_id phy_berlin_sata_of_match[] = {
+	{
+		.compatible = "marvell,berlin2-usb-phy",
+		.data = &phy_berlin_pll_dividers[0],
+	},
+	{
+		.compatible = "marvell,berlin2cd-usb-phy",
+		.data = &phy_berlin_pll_dividers[1],
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, phy_berlin_sata_of_match);
+
+static int phy_berlin_usb_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match =
+		of_match_device(phy_berlin_sata_of_match, &pdev->dev);
+	struct phy_berlin_usb_priv *priv;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+
+	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(priv->base))
+		return PTR_ERR(priv->base);
+
+	priv->rst_ctrl = devm_reset_control_get(&pdev->dev, NULL);
+	if (IS_ERR(priv->rst_ctrl))
+		return PTR_ERR(priv->rst_ctrl);
+
+	priv->pll_divider = *((u32 *)match->data);
+
+	priv->phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops,
+				    NULL);
+	if (IS_ERR(priv->phy)) {
+		dev_err(&pdev->dev, "failed to create PHY\n");
+		return PTR_ERR(priv->phy);
+	}
+
+	platform_set_drvdata(pdev, priv);
+
+	phy_provider =
+		devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider))
+		return PTR_ERR(phy_provider);
+
+	return 0;
+}
+
+static struct platform_driver phy_berlin_usb_driver = {
+	.probe	= phy_berlin_usb_probe,
+	.driver	= {
+		.name		= "phy-berlin-usb",
+		.owner		= THIS_MODULE,
+		.of_match_table	= phy_berlin_sata_of_match,
+	 },
+};
+module_platform_driver(phy_berlin_usb_driver);
+
+MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>");
+MODULE_DESCRIPTION("Marvell Berlin PHY driver for USB");
+MODULE_LICENSE("GPL");
-- 
1.7.9.5


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

* [PATCH 13/25] Documentation: bindings: add doc for the Berlin USB PHY
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (11 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 12/25] phy: add the Berlin USB PHY driver Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 14/25] phy: safer to_phy() macro Kishon Vijay Abraham I
                   ` (12 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Antoine Tenart <antoine.tenart@free-electrons.com>

Document the bindings of the Marvell Berlin USB PHY driver.

Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/berlin-usb-phy.txt     |   16 ++++++++++++++++
 1 file changed, 16 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/berlin-usb-phy.txt

diff --git a/Documentation/devicetree/bindings/phy/berlin-usb-phy.txt b/Documentation/devicetree/bindings/phy/berlin-usb-phy.txt
new file mode 100644
index 0000000..be33780
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/berlin-usb-phy.txt
@@ -0,0 +1,16 @@
+* Marvell Berlin USB PHY
+
+Required properties:
+- compatible: "marvell,berlin2-usb-phy" or "marvell,berlin2cd-usb-phy"
+- reg: base address and length of the registers
+- #phys-cells: should be 0
+- resets: reference to the reset controller
+
+Example:
+
+	usb-phy@f774000 {
+		compatible = "marvell,berlin2-usb-phy";
+		reg = <0xf774000 0x128>;
+		#phy-cells = <0>;
+		resets = <&chip 0x104 14>;
+	};
-- 
1.7.9.5


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

* [PATCH 14/25] phy: safer to_phy() macro
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (12 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 13/25] Documentation: bindings: add doc for the Berlin USB PHY Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 15/25] phy: improved lookup method Kishon Vijay Abraham I
                   ` (11 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

This makes to_phy() macro work with other variable names
besides "dev".

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Vivek Gautam <gautam.vivek@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 include/linux/phy/phy.h |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 8cb6f81..9fda683 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -110,7 +110,7 @@ struct phy_init_data {
 	.port		= _port,				\
 }
 
-#define	to_phy(dev)	(container_of((dev), struct phy, dev))
+#define	to_phy(a)	(container_of((a), struct phy, dev))
 
 #define	of_phy_provider_register(dev, xlate)	\
 	__of_phy_provider_register((dev), THIS_MODULE, (xlate))
-- 
1.7.9.5


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

* [PATCH 15/25] phy: improved lookup method
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (13 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 14/25] phy: safer to_phy() macro Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 16/25] phy: twl4030: use the new " Kishon Vijay Abraham I
                   ` (10 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

Separates registration of the phy and the lookup. The method
is copied from clkdev.c,

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 Documentation/phy.txt   |   60 +++++++++------------------------
 drivers/phy/phy-core.c  |   84 ++++++++++++++++++++++++++++++++++++++++++++++-
 include/linux/phy/phy.h |   16 +++++++++
 3 files changed, 115 insertions(+), 45 deletions(-)

diff --git a/Documentation/phy.txt b/Documentation/phy.txt
index c6594af..371361c 100644
--- a/Documentation/phy.txt
+++ b/Documentation/phy.txt
@@ -54,18 +54,14 @@ The PHY driver should create the PHY in order for other peripheral controllers
 to make use of it. The PHY framework provides 2 APIs to create the PHY.
 
 struct phy *phy_create(struct device *dev, struct device_node *node,
-		       const struct phy_ops *ops,
-		       struct phy_init_data *init_data);
+		       const struct phy_ops *ops);
 struct phy *devm_phy_create(struct device *dev, struct device_node *node,
-			    const struct phy_ops *ops,
-			    struct phy_init_data *init_data);
+			    const struct phy_ops *ops);
 
 The PHY drivers can use one of the above 2 APIs to create the PHY by passing
-the device pointer, phy ops and init_data.
+the device pointer and phy ops.
 phy_ops is a set of function pointers for performing PHY operations such as
-init, exit, power_on and power_off. *init_data* is mandatory to get a reference
-to the PHY in the case of non-dt boot. See section *Board File Initialization*
-on how init_data should be used.
+init, exit, power_on and power_off.
 
 Inorder to dereference the private data (in phy_ops), the phy provider driver
 can use phy_set_drvdata() after creating the PHY and use phy_get_drvdata() in
@@ -137,42 +133,18 @@ There are exported APIs like phy_pm_runtime_get, phy_pm_runtime_get_sync,
 phy_pm_runtime_put, phy_pm_runtime_put_sync, phy_pm_runtime_allow and
 phy_pm_runtime_forbid for performing PM operations.
 
-8. Board File Initialization
-
-Certain board file initialization is necessary in order to get a reference
-to the PHY in the case of non-dt boot.
-Say we have a single device that implements 3 PHYs that of USB, SATA and PCIe,
-then in the board file the following initialization should be done.
-
-struct phy_consumer consumers[] = {
-	PHY_CONSUMER("dwc3.0", "usb"),
-	PHY_CONSUMER("pcie.0", "pcie"),
-	PHY_CONSUMER("sata.0", "sata"),
-};
-PHY_CONSUMER takes 2 parameters, first is the device name of the controller
-(PHY consumer) and second is the port name.
-
-struct phy_init_data init_data = {
-	.consumers = consumers,
-	.num_consumers = ARRAY_SIZE(consumers),
-};
-
-static const struct platform_device pipe3_phy_dev = {
-	.name = "pipe3-phy",
-	.id = -1,
-	.dev = {
-		.platform_data = {
-			.init_data = &init_data,
-		},
-	},
-};
-
-then, while doing phy_create, the PHY driver should pass this init_data
-	phy_create(dev, ops, pdata->init_data);
-
-and the controller driver (phy consumer) should pass the port name along with
-the device to get a reference to the PHY
-	phy_get(dev, "pcie");
+8. PHY Mappings
+
+In order to get reference to a PHY without help from DeviceTree, the framework
+offers lookups which can be compared to clkdev that allow clk structures to be
+bound to devices. A lookup can be made be made during runtime when a handle to
+the struct phy already exists.
+
+The framework offers the following API for registering and unregistering the
+lookups.
+
+int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id);
+void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id);
 
 9. DeviceTree Binding
 
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 1606ce9..bc83077 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -26,6 +26,7 @@
 static struct class *phy_class;
 static DEFINE_MUTEX(phy_provider_mutex);
 static LIST_HEAD(phy_provider_list);
+static LIST_HEAD(phys);
 static DEFINE_IDA(phy_ida);
 
 static void devm_phy_release(struct device *dev, void *res)
@@ -84,6 +85,87 @@ static struct phy *phy_lookup(struct device *device, const char *port)
 	return ERR_PTR(-ENODEV);
 }
 
+/**
+ * phy_create_lookup() - allocate and register PHY/device association
+ * @phy: the phy of the association
+ * @con_id: connection ID string on device
+ * @dev_id: the device of the association
+ *
+ * Creates and registers phy_lookup entry.
+ */
+int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id)
+{
+	struct phy_lookup *pl;
+
+	if (!phy || !dev_id || !con_id)
+		return -EINVAL;
+
+	pl = kzalloc(sizeof(*pl), GFP_KERNEL);
+	if (!pl)
+		return -ENOMEM;
+
+	pl->dev_id = dev_id;
+	pl->con_id = con_id;
+	pl->phy = phy;
+
+	mutex_lock(&phy_provider_mutex);
+	list_add_tail(&pl->node, &phys);
+	mutex_unlock(&phy_provider_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(phy_create_lookup);
+
+/**
+ * phy_remove_lookup() - find and remove PHY/device association
+ * @phy: the phy of the association
+ * @con_id: connection ID string on device
+ * @dev_id: the device of the association
+ *
+ * Finds and unregisters phy_lookup entry that was created with
+ * phy_create_lookup().
+ */
+void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id)
+{
+	struct phy_lookup *pl;
+
+	if (!phy || !dev_id || !con_id)
+		return;
+
+	mutex_lock(&phy_provider_mutex);
+	list_for_each_entry(pl, &phys, node)
+		if (pl->phy == phy && !strcmp(pl->dev_id, dev_id) &&
+		    !strcmp(pl->con_id, con_id)) {
+			list_del(&pl->node);
+			kfree(pl);
+			break;
+		}
+	mutex_unlock(&phy_provider_mutex);
+}
+EXPORT_SYMBOL_GPL(phy_remove_lookup);
+
+static struct phy *phy_find(struct device *dev, const char *con_id)
+{
+	const char *dev_id = dev_name(dev);
+	struct phy_lookup *p, *pl = NULL;
+	struct phy *phy;
+
+	mutex_lock(&phy_provider_mutex);
+	list_for_each_entry(p, &phys, node)
+		if (!strcmp(p->dev_id, dev_id) && !strcmp(p->con_id, con_id)) {
+			pl = p;
+			break;
+		}
+	mutex_unlock(&phy_provider_mutex);
+
+	phy = pl ? pl->phy : ERR_PTR(-ENODEV);
+
+	/* fall-back to the old lookup method for now */
+	if (IS_ERR(phy))
+		phy = phy_lookup(dev, con_id);
+	return phy;
+}
+
 static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
 {
 	struct phy_provider *phy_provider;
@@ -455,7 +537,7 @@ struct phy *phy_get(struct device *dev, const char *string)
 			string);
 		phy = _of_phy_get(dev->of_node, index);
 	} else {
-		phy = phy_lookup(dev, string);
+		phy = phy_find(dev, string);
 	}
 	if (IS_ERR(phy))
 		return phy;
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 9fda683..849284e 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -110,6 +110,13 @@ struct phy_init_data {
 	.port		= _port,				\
 }
 
+struct phy_lookup {
+	struct list_head node;
+	const char *dev_id;
+	const char *con_id;
+	struct phy *phy;
+};
+
 #define	to_phy(a)	(container_of((a), struct phy, dev))
 
 #define	of_phy_provider_register(dev, xlate)	\
@@ -174,6 +181,8 @@ struct phy_provider *__devm_of_phy_provider_register(struct device *dev,
 void of_phy_provider_unregister(struct phy_provider *phy_provider);
 void devm_of_phy_provider_unregister(struct device *dev,
 	struct phy_provider *phy_provider);
+int phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id);
+void phy_remove_lookup(struct phy *phy, const char *con_id, const char *dev_id);
 #else
 static inline int phy_pm_runtime_get(struct phy *phy)
 {
@@ -345,6 +354,13 @@ static inline void devm_of_phy_provider_unregister(struct device *dev,
 	struct phy_provider *phy_provider)
 {
 }
+static inline int
+phy_create_lookup(struct phy *phy, const char *con_id, const char *dev_id)
+{
+	return 0;
+}
+static inline void phy_remove_lookup(struct phy *phy, const char *con_id,
+				     const char *dev_id) { }
 #endif
 
 #endif /* __DRIVERS_PHY_H */
-- 
1.7.9.5


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

* [PATCH 16/25] phy: twl4030: use the new lookup method
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (14 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 15/25] phy: improved lookup method Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 17/25] phy: remove the old " Kishon Vijay Abraham I
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

Creates the lookup separately. Hard coding the consumer as
it can't be anything else except musb.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-twl4030-usb.c |    9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
index 7b04bef..c45a3aa 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -644,7 +644,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 	struct usb_otg		*otg;
 	struct device_node	*np = pdev->dev.of_node;
 	struct phy_provider	*phy_provider;
-	struct phy_init_data	*init_data = NULL;
 
 	twl = devm_kzalloc(&pdev->dev, sizeof(*twl), GFP_KERNEL);
 	if (!twl)
@@ -655,7 +654,6 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 				(enum twl4030_usb_mode *)&twl->usb_mode);
 	else if (pdata) {
 		twl->usb_mode = pdata->usb_mode;
-		init_data = pdata->init_data;
 	} else {
 		dev_err(&pdev->dev, "twl4030 initialized without pdata\n");
 		return -EINVAL;
@@ -680,7 +678,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 	otg->set_host		= twl4030_set_host;
 	otg->set_peripheral	= twl4030_set_peripheral;
 
-	phy = devm_phy_create(twl->dev, NULL, &ops, init_data);
+	phy = devm_phy_create(twl->dev, NULL, &ops, NULL);
 	if (IS_ERR(phy)) {
 		dev_dbg(&pdev->dev, "Failed to create PHY\n");
 		return PTR_ERR(phy);
@@ -733,6 +731,11 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 		return status;
 	}
 
+	if (pdata)
+		err = phy_create_lookup(phy, "usb", "musb-hdrc.0");
+	if (err)
+		return err;
+
 	pm_runtime_mark_last_busy(&pdev->dev);
 	pm_runtime_put_autosuspend(twl->dev);
 
-- 
1.7.9.5


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

* [PATCH 17/25] phy: remove the old lookup method
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (15 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 16/25] phy: twl4030: use the new " Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 18/25] usb: dwc3: host: convey the PHYs to xhci Kishon Vijay Abraham I
                   ` (8 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

The users of the old method are now converted to the new one.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
[ kishon@ti.com : made phy-berlin-usb.c and phy-miphy28lp.c to use the updated
		  devm_phy_create API.]
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-bcm-kona-usb2.c      |    2 +-
 drivers/phy/phy-berlin-sata.c        |    2 +-
 drivers/phy/phy-berlin-usb.c         |    3 +--
 drivers/phy/phy-core.c               |   49 +++-------------------------------
 drivers/phy/phy-exynos-dp-video.c    |    2 +-
 drivers/phy/phy-exynos-mipi-video.c  |    2 +-
 drivers/phy/phy-exynos5-usbdrd.c     |    3 +--
 drivers/phy/phy-exynos5250-sata.c    |    2 +-
 drivers/phy/phy-hix5hd2-sata.c       |    2 +-
 drivers/phy/phy-miphy28lp.c          |    2 +-
 drivers/phy/phy-miphy365x.c          |    2 +-
 drivers/phy/phy-mvebu-sata.c         |    2 +-
 drivers/phy/phy-omap-usb2.c          |    2 +-
 drivers/phy/phy-qcom-apq8064-sata.c  |    3 +--
 drivers/phy/phy-qcom-ipq806x-sata.c  |    3 +--
 drivers/phy/phy-rcar-gen2.c          |    2 +-
 drivers/phy/phy-samsung-usb2.c       |    3 +--
 drivers/phy/phy-spear1310-miphy.c    |    2 +-
 drivers/phy/phy-spear1340-miphy.c    |    2 +-
 drivers/phy/phy-stih407-usb.c        |    2 +-
 drivers/phy/phy-stih41x-usb.c        |    2 +-
 drivers/phy/phy-sun4i-usb.c          |    2 +-
 drivers/phy/phy-ti-pipe3.c           |    2 +-
 drivers/phy/phy-twl4030-usb.c        |    2 +-
 drivers/phy/phy-xgene.c              |    2 +-
 drivers/pinctrl/pinctrl-tegra-xusb.c |    4 +--
 include/linux/phy/phy.h              |   38 +++-----------------------
 27 files changed, 34 insertions(+), 110 deletions(-)

diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c
index c1e0ca3..ef2dc1a 100644
--- a/drivers/phy/phy-bcm-kona-usb2.c
+++ b/drivers/phy/phy-bcm-kona-usb2.c
@@ -117,7 +117,7 @@ static int bcm_kona_usb2_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, phy);
 
-	gphy = devm_phy_create(dev, NULL, &ops, NULL);
+	gphy = devm_phy_create(dev, NULL, &ops);
 	if (IS_ERR(gphy))
 		return PTR_ERR(gphy);
 
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
index 873e7a8..3e599dc 100644
--- a/drivers/phy/phy-berlin-sata.c
+++ b/drivers/phy/phy-berlin-sata.c
@@ -249,7 +249,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
 		if (!phy_desc)
 			return -ENOMEM;
 
-		phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops, NULL);
+		phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "failed to create PHY %d\n", phy_id);
 			return PTR_ERR(phy);
diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c
index f9f1306..c8a8d53 100644
--- a/drivers/phy/phy-berlin-usb.c
+++ b/drivers/phy/phy-berlin-usb.c
@@ -192,8 +192,7 @@ static int phy_berlin_usb_probe(struct platform_device *pdev)
 
 	priv->pll_divider = *((u32 *)match->data);
 
-	priv->phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops,
-				    NULL);
+	priv->phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
 	if (IS_ERR(priv->phy)) {
 		dev_err(&pdev->dev, "failed to create PHY\n");
 		return PTR_ERR(priv->phy);
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index bc83077..a12d353 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -55,36 +55,6 @@ static int devm_phy_match(struct device *dev, void *res, void *match_data)
 	return res == match_data;
 }
 
-static struct phy *phy_lookup(struct device *device, const char *port)
-{
-	unsigned int count;
-	struct phy *phy;
-	struct device *dev;
-	struct phy_consumer *consumers;
-	struct class_dev_iter iter;
-
-	class_dev_iter_init(&iter, phy_class, NULL, NULL);
-	while ((dev = class_dev_iter_next(&iter))) {
-		phy = to_phy(dev);
-
-		if (!phy->init_data)
-			continue;
-		count = phy->init_data->num_consumers;
-		consumers = phy->init_data->consumers;
-		while (count--) {
-			if (!strcmp(consumers->dev_name, dev_name(device)) &&
-					!strcmp(consumers->port, port)) {
-				class_dev_iter_exit(&iter);
-				return phy;
-			}
-			consumers++;
-		}
-	}
-
-	class_dev_iter_exit(&iter);
-	return ERR_PTR(-ENODEV);
-}
-
 /**
  * phy_create_lookup() - allocate and register PHY/device association
  * @phy: the phy of the association
@@ -148,7 +118,6 @@ static struct phy *phy_find(struct device *dev, const char *con_id)
 {
 	const char *dev_id = dev_name(dev);
 	struct phy_lookup *p, *pl = NULL;
-	struct phy *phy;
 
 	mutex_lock(&phy_provider_mutex);
 	list_for_each_entry(p, &phys, node)
@@ -158,12 +127,7 @@ static struct phy *phy_find(struct device *dev, const char *con_id)
 		}
 	mutex_unlock(&phy_provider_mutex);
 
-	phy = pl ? pl->phy : ERR_PTR(-ENODEV);
-
-	/* fall-back to the old lookup method for now */
-	if (IS_ERR(phy))
-		phy = phy_lookup(dev, con_id);
-	return phy;
+	return pl ? pl->phy : ERR_PTR(-ENODEV);
 }
 
 static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
@@ -662,13 +626,11 @@ EXPORT_SYMBOL_GPL(devm_of_phy_get);
  * @dev: device that is creating the new phy
  * @node: device node of the phy
  * @ops: function pointers for performing phy operations
- * @init_data: contains the list of PHY consumers or NULL
  *
  * Called to create a phy using phy framework.
  */
 struct phy *phy_create(struct device *dev, struct device_node *node,
-		       const struct phy_ops *ops,
-		       struct phy_init_data *init_data)
+		       const struct phy_ops *ops)
 {
 	int ret;
 	int id;
@@ -706,7 +668,6 @@ struct phy *phy_create(struct device *dev, struct device_node *node,
 	phy->dev.of_node = node ?: dev->of_node;
 	phy->id = id;
 	phy->ops = ops;
-	phy->init_data = init_data;
 
 	ret = dev_set_name(&phy->dev, "phy-%s.%d", dev_name(dev), id);
 	if (ret)
@@ -741,7 +702,6 @@ EXPORT_SYMBOL_GPL(phy_create);
  * @dev: device that is creating the new phy
  * @node: device node of the phy
  * @ops: function pointers for performing phy operations
- * @init_data: contains the list of PHY consumers or NULL
  *
  * Creates a new PHY device adding it to the PHY class.
  * While at that, it also associates the device with the phy using devres.
@@ -749,8 +709,7 @@ EXPORT_SYMBOL_GPL(phy_create);
  * then, devres data is freed.
  */
 struct phy *devm_phy_create(struct device *dev, struct device_node *node,
-			    const struct phy_ops *ops,
-			    struct phy_init_data *init_data)
+			    const struct phy_ops *ops)
 {
 	struct phy **ptr, *phy;
 
@@ -758,7 +717,7 @@ struct phy *devm_phy_create(struct device *dev, struct device_node *node,
 	if (!ptr)
 		return ERR_PTR(-ENOMEM);
 
-	phy = phy_create(dev, node, ops, init_data);
+	phy = phy_create(dev, node, ops);
 	if (!IS_ERR(phy)) {
 		*ptr = phy;
 		devres_add(dev, ptr);
diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
index 84f49e5..f86cbe6 100644
--- a/drivers/phy/phy-exynos-dp-video.c
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -112,7 +112,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
 	match = of_match_node(exynos_dp_video_phy_of_match, dev->of_node);
 	state->drvdata = match->data;
 
-	phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops, NULL);
+	phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops);
 	if (IS_ERR(phy)) {
 		dev_err(dev, "failed to create Display Port PHY\n");
 		return PTR_ERR(phy);
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index 6a9bef1..943e0f8 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -137,7 +137,7 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
 
 	for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
 		struct phy *phy = devm_phy_create(dev, NULL,
-					&exynos_mipi_video_phy_ops, NULL);
+						  &exynos_mipi_video_phy_ops);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "failed to create PHY %d\n", i);
 			return PTR_ERR(phy);
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index f756aca..b3ca3bc 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -637,8 +637,7 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 
 	for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
 		struct phy *phy = devm_phy_create(dev, NULL,
-						  &exynos5_usbdrd_phy_ops,
-						  NULL);
+						  &exynos5_usbdrd_phy_ops);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "Failed to create usbdrd_phy phy\n");
 			return PTR_ERR(phy);
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c
index 54cf4ae..bc858cc 100644
--- a/drivers/phy/phy-exynos5250-sata.c
+++ b/drivers/phy/phy-exynos5250-sata.c
@@ -210,7 +210,7 @@ static int exynos_sata_phy_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops, NULL);
+	sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops);
 	if (IS_ERR(sata_phy->phy)) {
 		clk_disable_unprepare(sata_phy->phyclk);
 		dev_err(dev, "failed to create PHY\n");
diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c
index d5d9780..a80ff9d 100644
--- a/drivers/phy/phy-hix5hd2-sata.c
+++ b/drivers/phy/phy-hix5hd2-sata.c
@@ -156,7 +156,7 @@ static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
 	if (IS_ERR(priv->peri_ctrl))
 		priv->peri_ctrl = NULL;
 
-	phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops, NULL);
+	phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops);
 	if (IS_ERR(phy)) {
 		dev_err(dev, "failed to create PHY\n");
 		return PTR_ERR(phy);
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
index 87dcc9a..e34da13 100644
--- a/drivers/phy/phy-miphy28lp.c
+++ b/drivers/phy/phy-miphy28lp.c
@@ -1231,7 +1231,7 @@ static int miphy28lp_probe(struct platform_device *pdev)
 
 		miphy_dev->phys[port] = miphy_phy;
 
-		phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops, NULL);
+		phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops);
 		if (IS_ERR(phy)) {
 			dev_err(&pdev->dev, "failed to create PHY\n");
 			return PTR_ERR(phy);
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
index 801afaf..239930e 100644
--- a/drivers/phy/phy-miphy365x.c
+++ b/drivers/phy/phy-miphy365x.c
@@ -593,7 +593,7 @@ static int miphy365x_probe(struct platform_device *pdev)
 
 		miphy_dev->phys[port] = miphy_phy;
 
-		phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops, NULL);
+		phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops);
 		if (IS_ERR(phy)) {
 			dev_err(&pdev->dev, "failed to create PHY\n");
 			return PTR_ERR(phy);
diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c
index d395558..03b94f9 100644
--- a/drivers/phy/phy-mvebu-sata.c
+++ b/drivers/phy/phy-mvebu-sata.c
@@ -101,7 +101,7 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev)
 	if (IS_ERR(priv->clk))
 		return PTR_ERR(priv->clk);
 
-	phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops, NULL);
+	phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops);
 	if (IS_ERR(phy))
 		return PTR_ERR(phy);
 
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index f091576..5dab3ec 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -260,7 +260,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, phy);
 	pm_runtime_enable(phy->dev);
 
-	generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
+	generic_phy = devm_phy_create(phy->dev, NULL, &ops);
 	if (IS_ERR(generic_phy)) {
 		pm_runtime_disable(phy->dev);
 		return PTR_ERR(generic_phy);
diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c
index 7b3ddfb..4b243f7 100644
--- a/drivers/phy/phy-qcom-apq8064-sata.c
+++ b/drivers/phy/phy-qcom-apq8064-sata.c
@@ -228,8 +228,7 @@ static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
 	if (IS_ERR(phy->mmio))
 		return PTR_ERR(phy->mmio);
 
-	generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops,
-				      NULL);
+	generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops);
 	if (IS_ERR(generic_phy)) {
 		dev_err(dev, "%s: failed to create phy\n", __func__);
 		return PTR_ERR(generic_phy);
diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c
index 759b0bf..6f2fe26 100644
--- a/drivers/phy/phy-qcom-ipq806x-sata.c
+++ b/drivers/phy/phy-qcom-ipq806x-sata.c
@@ -150,8 +150,7 @@ static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
 	if (IS_ERR(phy->mmio))
 		return PTR_ERR(phy->mmio);
 
-	generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops,
-				      NULL);
+	generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops);
 	if (IS_ERR(generic_phy)) {
 		dev_err(dev, "%s: failed to create phy\n", __func__);
 		return PTR_ERR(generic_phy);
diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c
index 2793af1..778276a 100644
--- a/drivers/phy/phy-rcar-gen2.c
+++ b/drivers/phy/phy-rcar-gen2.c
@@ -304,7 +304,7 @@ static int rcar_gen2_phy_probe(struct platform_device *pdev)
 			phy->select_value = select_value[channel_num][n];
 
 			phy->phy = devm_phy_create(dev, NULL,
-						   &rcar_gen2_phy_ops, NULL);
+						   &rcar_gen2_phy_ops);
 			if (IS_ERR(phy->phy)) {
 				dev_err(dev, "Failed to create PHY\n");
 				return PTR_ERR(phy->phy);
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index 908949d..4a12f66 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -202,8 +202,7 @@ static int samsung_usb2_phy_probe(struct platform_device *pdev)
 		struct samsung_usb2_phy_instance *p = &drv->instances[i];
 
 		dev_dbg(dev, "Creating phy \"%s\"\n", label);
-		p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops,
-					 NULL);
+		p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops);
 		if (IS_ERR(p->phy)) {
 			dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
 				label);
diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/phy-spear1310-miphy.c
index 5f4c586..9f47fae 100644
--- a/drivers/phy/phy-spear1310-miphy.c
+++ b/drivers/phy/phy-spear1310-miphy.c
@@ -227,7 +227,7 @@ static int spear1310_miphy_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops, NULL);
+	priv->phy = devm_phy_create(dev, NULL, &spear1310_miphy_ops);
 	if (IS_ERR(priv->phy)) {
 		dev_err(dev, "failed to create SATA PCIe PHY\n");
 		return PTR_ERR(priv->phy);
diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/phy-spear1340-miphy.c
index 1ecd094..e42bc20 100644
--- a/drivers/phy/phy-spear1340-miphy.c
+++ b/drivers/phy/phy-spear1340-miphy.c
@@ -259,7 +259,7 @@ static int spear1340_miphy_probe(struct platform_device *pdev)
 		return PTR_ERR(priv->misc);
 	}
 
-	priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops, NULL);
+	priv->phy = devm_phy_create(dev, NULL, &spear1340_miphy_ops);
 	if (IS_ERR(priv->phy)) {
 		dev_err(dev, "failed to create SATA PCIe PHY\n");
 		return PTR_ERR(priv->phy);
diff --git a/drivers/phy/phy-stih407-usb.c b/drivers/phy/phy-stih407-usb.c
index 42428d4..74f0fab 100644
--- a/drivers/phy/phy-stih407-usb.c
+++ b/drivers/phy/phy-stih407-usb.c
@@ -137,7 +137,7 @@ static int stih407_usb2_picophy_probe(struct platform_device *pdev)
 	}
 	phy_dev->param = res->start;
 
-	phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data, NULL);
+	phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data);
 	if (IS_ERR(phy)) {
 		dev_err(dev, "failed to create Display Port PHY\n");
 		return PTR_ERR(phy);
diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c
index 9f16cb8..4ab581e 100644
--- a/drivers/phy/phy-stih41x-usb.c
+++ b/drivers/phy/phy-stih41x-usb.c
@@ -148,7 +148,7 @@ static int stih41x_usb_phy_probe(struct platform_device *pdev)
 		return PTR_ERR(phy_dev->clk);
 	}
 
-	phy = devm_phy_create(dev, NULL, &stih41x_usb_phy_ops, NULL);
+	phy = devm_phy_create(dev, NULL, &stih41x_usb_phy_ops);
 
 	if (IS_ERR(phy)) {
 		dev_err(dev, "failed to create phy\n");
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 6bd2b0c..fb02a67 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -298,7 +298,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 				return PTR_ERR(phy->pmu);
 		}
 
-		phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops, NULL);
+		phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops);
 		if (IS_ERR(phy->phy)) {
 			dev_err(dev, "failed to create PHY %d\n", i);
 			return PTR_ERR(phy->phy);
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index ab1e22d..c297b7a 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -399,7 +399,7 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 	platform_set_drvdata(pdev, phy);
 	pm_runtime_enable(phy->dev);
 
-	generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
+	generic_phy = devm_phy_create(phy->dev, NULL, &ops);
 	if (IS_ERR(generic_phy))
 		return PTR_ERR(generic_phy);
 
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
index c45a3aa..d19e4a0 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -678,7 +678,7 @@ static int twl4030_usb_probe(struct platform_device *pdev)
 	otg->set_host		= twl4030_set_host;
 	otg->set_peripheral	= twl4030_set_peripheral;
 
-	phy = devm_phy_create(twl->dev, NULL, &ops, NULL);
+	phy = devm_phy_create(twl->dev, NULL, &ops);
 	if (IS_ERR(phy)) {
 		dev_dbg(&pdev->dev, "Failed to create PHY\n");
 		return PTR_ERR(phy);
diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c
index f8a51b1..29214a3 100644
--- a/drivers/phy/phy-xgene.c
+++ b/drivers/phy/phy-xgene.c
@@ -1707,7 +1707,7 @@ static int xgene_phy_probe(struct platform_device *pdev)
 	ctx->dev = &pdev->dev;
 	platform_set_drvdata(pdev, ctx);
 
-	ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops, NULL);
+	ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops);
 	if (IS_ERR(ctx->phy)) {
 		dev_dbg(&pdev->dev, "Failed to create PHY\n");
 		rc = PTR_ERR(ctx->phy);
diff --git a/drivers/pinctrl/pinctrl-tegra-xusb.c b/drivers/pinctrl/pinctrl-tegra-xusb.c
index 1631ec9..a84299b 100644
--- a/drivers/pinctrl/pinctrl-tegra-xusb.c
+++ b/drivers/pinctrl/pinctrl-tegra-xusb.c
@@ -910,7 +910,7 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 		goto reset;
 	}
 
-	phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops, NULL);
+	phy = devm_phy_create(&pdev->dev, NULL, &pcie_phy_ops);
 	if (IS_ERR(phy)) {
 		err = PTR_ERR(phy);
 		goto unregister;
@@ -919,7 +919,7 @@ static int tegra_xusb_padctl_probe(struct platform_device *pdev)
 	padctl->phys[TEGRA_XUSB_PADCTL_PCIE] = phy;
 	phy_set_drvdata(phy, padctl);
 
-	phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops, NULL);
+	phy = devm_phy_create(&pdev->dev, NULL, &sata_phy_ops);
 	if (IS_ERR(phy)) {
 		err = PTR_ERR(phy);
 		goto unregister;
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 849284e..a0197fa 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -61,7 +61,6 @@ struct phy {
 	struct device		dev;
 	int			id;
 	const struct phy_ops	*ops;
-	struct phy_init_data	*init_data;
 	struct mutex		mutex;
 	int			init_count;
 	int			power_count;
@@ -84,32 +83,6 @@ struct phy_provider {
 		struct of_phandle_args *args);
 };
 
-/**
- * struct phy_consumer - represents the phy consumer
- * @dev_name: the device name of the controller that will use this PHY device
- * @port: name given to the consumer port
- */
-struct phy_consumer {
-	const char *dev_name;
-	const char *port;
-};
-
-/**
- * struct phy_init_data - contains the list of PHY consumers
- * @num_consumers: number of consumers for this PHY device
- * @consumers: list of PHY consumers
- */
-struct phy_init_data {
-	unsigned int num_consumers;
-	struct phy_consumer *consumers;
-};
-
-#define PHY_CONSUMER(_dev_name, _port)				\
-{								\
-	.dev_name	= _dev_name,				\
-	.port		= _port,				\
-}
-
 struct phy_lookup {
 	struct list_head node;
 	const char *dev_id;
@@ -166,10 +139,9 @@ struct phy *of_phy_get(struct device_node *np, const char *con_id);
 struct phy *of_phy_simple_xlate(struct device *dev,
 	struct of_phandle_args *args);
 struct phy *phy_create(struct device *dev, struct device_node *node,
-		       const struct phy_ops *ops,
-		       struct phy_init_data *init_data);
+		       const struct phy_ops *ops);
 struct phy *devm_phy_create(struct device *dev, struct device_node *node,
-	const struct phy_ops *ops, struct phy_init_data *init_data);
+			    const struct phy_ops *ops);
 void phy_destroy(struct phy *phy);
 void devm_phy_destroy(struct device *dev, struct phy *phy);
 struct phy_provider *__of_phy_provider_register(struct device *dev,
@@ -310,16 +282,14 @@ static inline struct phy *of_phy_simple_xlate(struct device *dev,
 
 static inline struct phy *phy_create(struct device *dev,
 				     struct device_node *node,
-				     const struct phy_ops *ops,
-				     struct phy_init_data *init_data)
+				     const struct phy_ops *ops)
 {
 	return ERR_PTR(-ENOSYS);
 }
 
 static inline struct phy *devm_phy_create(struct device *dev,
 					  struct device_node *node,
-					  const struct phy_ops *ops,
-					  struct phy_init_data *init_data)
+					  const struct phy_ops *ops)
 {
 	return ERR_PTR(-ENOSYS);
 }
-- 
1.7.9.5


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

* [PATCH 18/25] usb: dwc3: host: convey the PHYs to xhci
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (16 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 17/25] phy: remove the old " Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 19/25] phy: exynos5-usbdrd: Add pipe-clk, utmi-clk and itp-clk support Kishon Vijay Abraham I
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Heikki Krogerus <heikki.krogerus@linux.intel.com>

On some platforms a PHY may need to be handled also in the
host controller driver. Exynos5420 SoC requires some "PHY
tuning" based on the USB speed. This patch delivers dwc3's
PHYs to the xhci platform device when it's created.

Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Vivek Gautam <gautam.vivek@samsung.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/usb/dwc3/host.c |   22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index dcb8ca0..12bfd3c 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -29,8 +29,7 @@ int dwc3_host_init(struct dwc3 *dwc)
 	xhci = platform_device_alloc("xhci-hcd", PLATFORM_DEVID_AUTO);
 	if (!xhci) {
 		dev_err(dwc->dev, "couldn't allocate xHCI device\n");
-		ret = -ENOMEM;
-		goto err0;
+		return -ENOMEM;
 	}
 
 	dma_set_coherent_mask(&xhci->dev, dwc->dev->coherent_dma_mask);
@@ -60,22 +59,33 @@ int dwc3_host_init(struct dwc3 *dwc)
 		goto err1;
 	}
 
+	phy_create_lookup(dwc->usb2_generic_phy, "usb2-phy",
+			  dev_name(&xhci->dev));
+	phy_create_lookup(dwc->usb3_generic_phy, "usb3-phy",
+			  dev_name(&xhci->dev));
+
 	ret = platform_device_add(xhci);
 	if (ret) {
 		dev_err(dwc->dev, "failed to register xHCI device\n");
-		goto err1;
+		goto err2;
 	}
 
 	return 0;
-
+err2:
+	phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy",
+			  dev_name(&xhci->dev));
+	phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy",
+			  dev_name(&xhci->dev));
 err1:
 	platform_device_put(xhci);
-
-err0:
 	return ret;
 }
 
 void dwc3_host_exit(struct dwc3 *dwc)
 {
+	phy_remove_lookup(dwc->usb2_generic_phy, "usb2-phy",
+			  dev_name(&dwc->xhci->dev));
+	phy_remove_lookup(dwc->usb3_generic_phy, "usb3-phy",
+			  dev_name(&dwc->xhci->dev));
 	platform_device_unregister(dwc->xhci);
 }
-- 
1.7.9.5


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

* [PATCH 19/25] phy: exynos5-usbdrd: Add pipe-clk, utmi-clk and itp-clk support
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (17 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 18/25] usb: dwc3: host: convey the PHYs to xhci Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 20/25] phy: exynos5-usbdrd: Add facility for VBUS-BOOST-5V supply Kishon Vijay Abraham I
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Vivek Gautam <gautam.vivek@samsung.com>

Exynos7 SoC has now separate gate control for 125MHz pipe3 phy
clock, as well as 60MHz utmi phy clock.
Additionally, separate gate control is available for the clock
used for ITP (Isochronous Transfer Packet) generation.

So get the same and control in the phy-exynos5-usbdrd driver.

Suggested-by: Anton Tikhomirov <av.tikhomirov@samsung.com>
Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/samsung-phy.txt        |    6 ++
 drivers/phy/phy-exynos5-usbdrd.c                   |  104 ++++++++++++++++----
 2 files changed, 92 insertions(+), 18 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index 15e0f2c..d5bad92 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -128,6 +128,7 @@ Required properties:
 - compatible : Should be set to one of the following supported values:
 	- "samsung,exynos5250-usbdrd-phy" - for exynos5250 SoC,
 	- "samsung,exynos5420-usbdrd-phy" - for exynos5420 SoC.
+	- "samsung,exynos7-usbdrd-phy" - for exynos7 SoC.
 - reg : Register offset and length of USB DRD PHY register set;
 - clocks: Clock IDs array as required by the controller
 - clock-names: names of clocks correseponding to IDs in the clock property;
@@ -138,6 +139,11 @@ Required properties:
 	       PHY operations, associated by phy name. It is used to
 	       determine bit values for clock settings register.
 	       For Exynos5420 this is given as 'sclk_usbphy30' in CMU.
+	- optional clocks: Exynos7 SoC has now following additional
+			   gate clocks available:
+			   - phy_pipe: for PIPE3 phy
+			   - phy_utmi: for UTMI+ phy
+			   - itp: for ITP generation
 - samsung,pmu-syscon: phandle for PMU system controller interface, used to
 		      control pmu registers for power isolation.
 - #phy-cells : from the generic PHY bindings, must be 1;
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index b3ca3bc..99ba56d 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -141,6 +141,7 @@ struct exynos5_usbdrd_phy_drvdata {
 	const struct exynos5_usbdrd_phy_config *phy_cfg;
 	u32 pmu_offset_usbdrd0_phy;
 	u32 pmu_offset_usbdrd1_phy;
+	bool has_common_clk_gate;
 };
 
 /**
@@ -148,6 +149,9 @@ struct exynos5_usbdrd_phy_drvdata {
  * @dev: pointer to device instance of this platform device
  * @reg_phy: usb phy controller register memory base
  * @clk: phy clock for register access
+ * @pipeclk: clock for pipe3 phy
+ * @utmiclk: clock for utmi+ phy
+ * @itpclk: clock for ITP generation
  * @drv_data: pointer to SoC level driver data structure
  * @phys[]: array for 'EXYNOS5_DRDPHYS_NUM' number of PHY
  *	    instances each with its 'phy' and 'phy_cfg'.
@@ -155,12 +159,14 @@ struct exynos5_usbdrd_phy_drvdata {
  *	       reference clocks' for SS and HS operations
  * @ref_clk: reference clock to PHY block from which PHY's
  *	     operational clocks are derived
- * @ref_rate: rate of above reference clock
  */
 struct exynos5_usbdrd_phy {
 	struct device *dev;
 	void __iomem *reg_phy;
 	struct clk *clk;
+	struct clk *pipeclk;
+	struct clk *utmiclk;
+	struct clk *itpclk;
 	const struct exynos5_usbdrd_phy_drvdata *drv_data;
 	struct phy_usb_instance {
 		struct phy *phy;
@@ -447,6 +453,11 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy)
 	dev_dbg(phy_drd->dev, "Request to power_on usbdrd_phy phy\n");
 
 	clk_prepare_enable(phy_drd->ref_clk);
+	if (!phy_drd->drv_data->has_common_clk_gate) {
+		clk_prepare_enable(phy_drd->pipeclk);
+		clk_prepare_enable(phy_drd->utmiclk);
+		clk_prepare_enable(phy_drd->itpclk);
+	}
 
 	/* Enable VBUS supply */
 	if (phy_drd->vbus) {
@@ -464,6 +475,11 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy)
 
 fail_vbus:
 	clk_disable_unprepare(phy_drd->ref_clk);
+	if (!phy_drd->drv_data->has_common_clk_gate) {
+		clk_disable_unprepare(phy_drd->itpclk);
+		clk_disable_unprepare(phy_drd->utmiclk);
+		clk_disable_unprepare(phy_drd->pipeclk);
+	}
 
 	return ret;
 }
@@ -483,6 +499,11 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
 		regulator_disable(phy_drd->vbus);
 
 	clk_disable_unprepare(phy_drd->ref_clk);
+	if (!phy_drd->drv_data->has_common_clk_gate) {
+		clk_disable_unprepare(phy_drd->itpclk);
+		clk_disable_unprepare(phy_drd->pipeclk);
+		clk_disable_unprepare(phy_drd->utmiclk);
+	}
 
 	return 0;
 }
@@ -506,6 +527,57 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
 	.owner		= THIS_MODULE,
 };
 
+static int exynos5_usbdrd_phy_clk_handle(struct exynos5_usbdrd_phy *phy_drd)
+{
+	unsigned long ref_rate;
+	int ret;
+
+	phy_drd->clk = devm_clk_get(phy_drd->dev, "phy");
+	if (IS_ERR(phy_drd->clk)) {
+		dev_err(phy_drd->dev, "Failed to get phy clock\n");
+		return PTR_ERR(phy_drd->clk);
+	}
+
+	phy_drd->ref_clk = devm_clk_get(phy_drd->dev, "ref");
+	if (IS_ERR(phy_drd->ref_clk)) {
+		dev_err(phy_drd->dev, "Failed to get phy reference clock\n");
+		return PTR_ERR(phy_drd->ref_clk);
+	}
+	ref_rate = clk_get_rate(phy_drd->ref_clk);
+
+	ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
+	if (ret) {
+		dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
+			ref_rate);
+		return ret;
+	}
+
+	if (!phy_drd->drv_data->has_common_clk_gate) {
+		phy_drd->pipeclk = devm_clk_get(phy_drd->dev, "phy_pipe");
+		if (IS_ERR(phy_drd->pipeclk)) {
+			dev_info(phy_drd->dev,
+				 "PIPE3 phy operational clock not specified\n");
+			phy_drd->pipeclk = NULL;
+		}
+
+		phy_drd->utmiclk = devm_clk_get(phy_drd->dev, "phy_utmi");
+		if (IS_ERR(phy_drd->utmiclk)) {
+			dev_info(phy_drd->dev,
+				 "UTMI phy operational clock not specified\n");
+			phy_drd->utmiclk = NULL;
+		}
+
+		phy_drd->itpclk = devm_clk_get(phy_drd->dev, "itp");
+		if (IS_ERR(phy_drd->itpclk)) {
+			dev_info(phy_drd->dev,
+				 "ITP clock from main OSC not specified\n");
+			phy_drd->itpclk = NULL;
+		}
+	}
+
+	return 0;
+}
+
 static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
 	{
 		.id		= EXYNOS5_DRDPHY_UTMI,
@@ -525,11 +597,19 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos5,
 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
 	.pmu_offset_usbdrd1_phy	= EXYNOS5420_USBDRD1_PHY_CONTROL,
+	.has_common_clk_gate	= true,
 };
 
 static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos5,
 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
+	.has_common_clk_gate	= true,
+};
+
+static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
+	.phy_cfg		= phy_cfg_exynos5,
+	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
+	.has_common_clk_gate	= false,
 };
 
 static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
@@ -539,6 +619,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
 	}, {
 		.compatible = "samsung,exynos5420-usbdrd-phy",
 		.data = &exynos5420_usbdrd_phy
+	}, {
+		.compatible = "samsung,exynos7-usbdrd-phy",
+		.data = &exynos7_usbdrd_phy
 	},
 	{ },
 };
@@ -555,7 +638,6 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 	const struct exynos5_usbdrd_phy_drvdata *drv_data;
 	struct regmap *reg_pmu;
 	u32 pmu_offset;
-	unsigned long ref_rate;
 	int i, ret;
 	int channel;
 
@@ -576,23 +658,9 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 	drv_data = match->data;
 	phy_drd->drv_data = drv_data;
 
-	phy_drd->clk = devm_clk_get(dev, "phy");
-	if (IS_ERR(phy_drd->clk)) {
-		dev_err(dev, "Failed to get clock of phy controller\n");
-		return PTR_ERR(phy_drd->clk);
-	}
-
-	phy_drd->ref_clk = devm_clk_get(dev, "ref");
-	if (IS_ERR(phy_drd->ref_clk)) {
-		dev_err(dev, "Failed to get reference clock of usbdrd phy\n");
-		return PTR_ERR(phy_drd->ref_clk);
-	}
-	ref_rate = clk_get_rate(phy_drd->ref_clk);
-
-	ret = exynos5_rate_to_clk(ref_rate, &phy_drd->extrefclk);
+	ret = exynos5_usbdrd_phy_clk_handle(phy_drd);
 	if (ret) {
-		dev_err(phy_drd->dev, "Clock rate (%ld) not supported\n",
-			ref_rate);
+		dev_err(dev, "Failed to initialize clocks\n");
 		return ret;
 	}
 
-- 
1.7.9.5


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

* [PATCH 20/25] phy: exynos5-usbdrd: Add facility for VBUS-BOOST-5V supply
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (18 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 19/25] phy: exynos5-usbdrd: Add pipe-clk, utmi-clk and itp-clk support Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 21/25] phy: exynos7-usbdrd: Update dependency for ARCH_EXYNOS Kishon Vijay Abraham I
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Vivek Gautam <gautam.vivek@samsung.com>

Some Exynos boards have a separate regulator controlling a
Boost 5V supply which goes as input for VBUS regulator.
So adding a control for the same in driver, to enable
vbus supply on the port.

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-exynos5-usbdrd.c |   32 ++++++++++++++++++++++++++++++--
 1 file changed, 30 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index 99ba56d..0437401 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -159,6 +159,8 @@ struct exynos5_usbdrd_phy_drvdata {
  *	       reference clocks' for SS and HS operations
  * @ref_clk: reference clock to PHY block from which PHY's
  *	     operational clocks are derived
+ * vbus: VBUS regulator for phy
+ * vbus_boost: Boost regulator for VBUS present on few Exynos boards
  */
 struct exynos5_usbdrd_phy {
 	struct device *dev;
@@ -178,6 +180,7 @@ struct exynos5_usbdrd_phy {
 	u32 extrefclk;
 	struct clk *ref_clk;
 	struct regulator *vbus;
+	struct regulator *vbus_boost;
 };
 
 static inline
@@ -460,11 +463,20 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy)
 	}
 
 	/* Enable VBUS supply */
+	if (phy_drd->vbus_boost) {
+		ret = regulator_enable(phy_drd->vbus_boost);
+		if (ret) {
+			dev_err(phy_drd->dev,
+				"Failed to enable VBUS boost supply\n");
+			goto fail_vbus;
+		}
+	}
+
 	if (phy_drd->vbus) {
 		ret = regulator_enable(phy_drd->vbus);
 		if (ret) {
 			dev_err(phy_drd->dev, "Failed to enable VBUS supply\n");
-			goto fail_vbus;
+			goto fail_vbus_boost;
 		}
 	}
 
@@ -473,6 +485,10 @@ static int exynos5_usbdrd_phy_power_on(struct phy *phy)
 
 	return 0;
 
+fail_vbus_boost:
+	if (phy_drd->vbus_boost)
+		regulator_disable(phy_drd->vbus_boost);
+
 fail_vbus:
 	clk_disable_unprepare(phy_drd->ref_clk);
 	if (!phy_drd->drv_data->has_common_clk_gate) {
@@ -497,6 +513,8 @@ static int exynos5_usbdrd_phy_power_off(struct phy *phy)
 	/* Disable VBUS supply */
 	if (phy_drd->vbus)
 		regulator_disable(phy_drd->vbus);
+	if (phy_drd->vbus_boost)
+		regulator_disable(phy_drd->vbus_boost);
 
 	clk_disable_unprepare(phy_drd->ref_clk);
 	if (!phy_drd->drv_data->has_common_clk_gate) {
@@ -690,7 +708,7 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 		break;
 	}
 
-	/* Get Vbus regulator */
+	/* Get Vbus regulators */
 	phy_drd->vbus = devm_regulator_get(dev, "vbus");
 	if (IS_ERR(phy_drd->vbus)) {
 		ret = PTR_ERR(phy_drd->vbus);
@@ -701,6 +719,16 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 		phy_drd->vbus = NULL;
 	}
 
+	phy_drd->vbus_boost = devm_regulator_get(dev, "vbus-boost");
+	if (IS_ERR(phy_drd->vbus_boost)) {
+		ret = PTR_ERR(phy_drd->vbus_boost);
+		if (ret == -EPROBE_DEFER)
+			return ret;
+
+		dev_warn(dev, "Failed to get VBUS boost supply regulator\n");
+		phy_drd->vbus_boost = NULL;
+	}
+
 	dev_vdbg(dev, "Creating usbdrd_phy phy\n");
 
 	for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
-- 
1.7.9.5


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

* [PATCH 21/25] phy: exynos7-usbdrd: Update dependency for ARCH_EXYNOS
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (19 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 20/25] phy: exynos5-usbdrd: Add facility for VBUS-BOOST-5V supply Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 22/25] phy: Use PTR_ERR_OR_ZERO to fix warning raised by coccinelle Kishon Vijay Abraham I
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Vivek Gautam <gautam.vivek@samsung.com>

This PHY controller is also present on Exynos7 platform
in arch-exynos family.
So PHY_EXYNOS5_USBDRD should now depend on ARCH_EXYNOS.

Signed-off-by: Vivek Gautam <gautam.vivek@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 4144d25..96d43d5 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -208,7 +208,7 @@ config PHY_EXYNOS5250_USB2
 
 config PHY_EXYNOS5_USBDRD
 	tristate "Exynos5 SoC series USB DRD PHY driver"
-	depends on ARCH_EXYNOS5 && OF
+	depends on ARCH_EXYNOS && OF
 	depends on HAS_IOMEM
 	depends on USB_DWC3_EXYNOS
 	select GENERIC_PHY
-- 
1.7.9.5


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

* [PATCH 22/25] phy: Use PTR_ERR_OR_ZERO to fix warning raised by coccinelle
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (20 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 21/25] phy: exynos7-usbdrd: Update dependency for ARCH_EXYNOS Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 23/25] Phy: DT binding documentation for Marvell MVEBU SATA phy Kishon Vijay Abraham I
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Gregory CLEMENT <gregory.clement@free-electrons.com>

Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR

Generated by: coccinelle/api/ptr_ret.cocci

Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-berlin-sata.c  |    5 +----
 drivers/phy/phy-hix5hd2-sata.c |    5 +----
 drivers/phy/phy-miphy365x.c    |    5 +----
 drivers/phy/phy-stih41x-usb.c  |    5 +----
 4 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
index 3e599dc..099eee8 100644
--- a/drivers/phy/phy-berlin-sata.c
+++ b/drivers/phy/phy-berlin-sata.c
@@ -268,10 +268,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
 
 	phy_provider =
 		devm_of_phy_provider_register(dev, phy_berlin_sata_phy_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
-
-	return 0;
+	return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id phy_berlin_sata_of_match[] = {
diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c
index a80ff9d..34915b4 100644
--- a/drivers/phy/phy-hix5hd2-sata.c
+++ b/drivers/phy/phy-hix5hd2-sata.c
@@ -164,10 +164,7 @@ static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
 
 	phy_set_drvdata(phy, priv);
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
-
-	return 0;
+	return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id hix5hd2_sata_phy_of_match[] = {
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
index 239930e..6ab43a8 100644
--- a/drivers/phy/phy-miphy365x.c
+++ b/drivers/phy/phy-miphy365x.c
@@ -610,10 +610,7 @@ static int miphy365x_probe(struct platform_device *pdev)
 	}
 
 	provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
-	if (IS_ERR(provider))
-		return PTR_ERR(provider);
-
-	return 0;
+	return PTR_ERR_OR_ZERO(provider);
 }
 
 static const struct of_device_id miphy365x_of_match[] = {
diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c
index 4ab581e..a603801 100644
--- a/drivers/phy/phy-stih41x-usb.c
+++ b/drivers/phy/phy-stih41x-usb.c
@@ -160,10 +160,7 @@ static int stih41x_usb_phy_probe(struct platform_device *pdev)
 	phy_set_drvdata(phy, phy_dev);
 
 	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
-	if (IS_ERR(phy_provider))
-		return PTR_ERR(phy_provider);
-
-	return 0;
+	return PTR_ERR_OR_ZERO(phy_provider);
 }
 
 static const struct of_device_id stih41x_usb_phy_of_match[] = {
-- 
1.7.9.5


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

* [PATCH 23/25] Phy: DT binding documentation for Marvell MVEBU SATA phy.
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (21 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 22/25] phy: Use PTR_ERR_OR_ZERO to fix warning raised by coccinelle Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 24/25] Phy: DT binding documentation for the Armada 375 USB cluster binding Kishon Vijay Abraham I
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Andrew Lunn <andrew@lunn.ch>

Describe the binding for the Marvell MVEBU SATA phy. This driver
can be used at least with Kirkwood, Dove and maybe others.
Additionally, update the SATA binding with the properties to link
to the phy nodes.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 Documentation/devicetree/bindings/ata/marvell.txt  |    6 ++++++
 .../devicetree/bindings/phy/phy-mvebu.txt          |   22 ++++++++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-mvebu.txt

diff --git a/Documentation/devicetree/bindings/ata/marvell.txt b/Documentation/devicetree/bindings/ata/marvell.txt
index 1c83516..b460edd 100644
--- a/Documentation/devicetree/bindings/ata/marvell.txt
+++ b/Documentation/devicetree/bindings/ata/marvell.txt
@@ -6,11 +6,17 @@ Required Properties:
 - interrupts    : Interrupt controller is using
 - nr-ports      : Number of SATA ports in use.
 
+Optional Properties:
+- phys		: List of phandles to sata phys
+- phy-names	: Should be "0", "1", etc, one number per phandle
+
 Example:
 
 	sata@80000 {
 		compatible = "marvell,orion-sata";
 		reg = <0x80000 0x5000>;
 		interrupts = <21>;
+		phys = <&sata_phy0>, <&sata_phy1>;
+		phy-names = "0", "1";
 		nr-ports = <2>;
 	}
diff --git a/Documentation/devicetree/bindings/phy/phy-mvebu.txt b/Documentation/devicetree/bindings/phy/phy-mvebu.txt
new file mode 100644
index 0000000..6cb3364
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-mvebu.txt
@@ -0,0 +1,22 @@
+* Marvell MVEBU SATA PHY
+
+Power control for the SATA phy found on Marvell MVEBU SoCs.
+
+This document extends the binding described in phy-bindings.txt
+
+Required properties :
+
+ - reg		   : Offset and length of the register set for the SATA device
+ - compatible	   : Should be "marvell,mvebu-sata-phy"
+ - clocks	   : phandle of clock and specifier that supplies the device
+ - clock-names	   : Should be "sata"
+
+Example:
+		sata-phy@84000 {
+			compatible = "marvell,mvebu-sata-phy";
+			reg = <0x84000 0x0334>;
+			clocks = <&gate_clk 15>;
+			clock-names = "sata";
+			#phy-cells = <0>;
+			status = "ok";
+		};
-- 
1.7.9.5


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

* [PATCH 24/25] Phy: DT binding documentation for the Armada 375 USB cluster binding
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (22 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 23/25] Phy: DT binding documentation for Marvell MVEBU SATA phy Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27  6:26 ` [PATCH 25/25] phy: add support for USB cluster on the Armada 375 SoC Kishon Vijay Abraham I
  2014-11-27 16:49 ` [GIT PULL 00/25] phy: for 3.19 Greg KH
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Gregory CLEMENT <gregory.clement@free-electrons.com>

Armada 375 comes with an USB2 host and device controller and an USB3
controller. The USB cluster control register allows to manage common
features of both USB controllers. This commit adds the Device Tree
binding documentation for this piece of hardware.

Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Acked-by: Jason Cooper <jason@lakedaemon.net>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/phy-mvebu.txt          |   21 ++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/phy-mvebu.txt b/Documentation/devicetree/bindings/phy/phy-mvebu.txt
index 6cb3364..f95b626 100644
--- a/Documentation/devicetree/bindings/phy/phy-mvebu.txt
+++ b/Documentation/devicetree/bindings/phy/phy-mvebu.txt
@@ -20,3 +20,24 @@ Example:
 			#phy-cells = <0>;
 			status = "ok";
 		};
+
+Armada 375 USB cluster
+----------------------
+
+Armada 375 comes with an USB2 host and device controller and an USB3
+controller. The USB cluster control register allows to manage common
+features of both USB controllers.
+
+Required properties:
+
+- compatible: "marvell,armada-375-usb-cluster"
+- reg: Should contain usb cluster register location and length.
+- #phy-cells : from the generic phy bindings, must be 1. Possible
+values are 1 (USB2), 2 (USB3).
+
+Example:
+		usbcluster: usb-cluster@18400 {
+			compatible = "marvell,armada-375-usb-cluster";
+			reg = <0x18400 0x4>;
+			#phy-cells = <1>
+		};
-- 
1.7.9.5


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

* [PATCH 25/25] phy: add support for USB cluster on the Armada 375 SoC
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (23 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 24/25] Phy: DT binding documentation for the Armada 375 USB cluster binding Kishon Vijay Abraham I
@ 2014-11-27  6:26 ` Kishon Vijay Abraham I
  2014-11-27 16:49 ` [GIT PULL 00/25] phy: for 3.19 Greg KH
  25 siblings, 0 replies; 28+ messages in thread
From: Kishon Vijay Abraham I @ 2014-11-27  6:26 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Gregory CLEMENT <gregory.clement@free-electrons.com>

The Armada 375 SoC comes with an USB2 host and device controller and
an USB3 controller. The USB cluster control register allows to manage
common features of both USB controllers.

This commit adds a driver integrated in the generic PHY framework to
control this USB cluster feature.

Signed-off-by: Gregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
[ kishon@ti.com : Made it to use the updated devm_phy_create API and
		  soem cosmentic changes in Kconfig file.]
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Acked-by: Jason Cooper <jason@lakedaemon.net>
---
 drivers/phy/Kconfig              |    6 ++
 drivers/phy/Makefile             |    1 +
 drivers/phy/phy-armada375-usb2.c |  158 ++++++++++++++++++++++++++++++++++++++
 include/dt-bindings/phy/phy.h    |    1 +
 4 files changed, 166 insertions(+)
 create mode 100644 drivers/phy/phy-armada375-usb2.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 96d43d5..ccad880 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -29,6 +29,12 @@ config PHY_BERLIN_SATA
 	help
 	  Enable this to support the SATA PHY on Marvell Berlin SoCs.
 
+config ARMADA375_USBCLUSTER_PHY
+	def_bool y
+	depends on MACH_ARMADA_375 || COMPILE_TEST
+	depends on OF
+	select GENERIC_PHY
+
 config PHY_EXYNOS_MIPI_VIDEO
 	tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
 	depends on HAS_IOMEM
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 68022f6..aa74f96 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -5,6 +5,7 @@
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.o
 obj-$(CONFIG_PHY_BERLIN_USB)		+= phy-berlin-usb.o
 obj-$(CONFIG_PHY_BERLIN_SATA)		+= phy-berlin-sata.o
+obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY)	+= phy-armada375-usb2.o
 obj-$(CONFIG_BCM_KONA_USB2_PHY)		+= phy-bcm-kona-usb2.o
 obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)	+= phy-exynos-dp-video.o
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/phy-armada375-usb2.c
new file mode 100644
index 0000000..ac7d99d
--- /dev/null
+++ b/drivers/phy/phy-armada375-usb2.c
@@ -0,0 +1,158 @@
+/*
+ * USB cluster support for Armada 375 platform.
+ *
+ * Copyright (C) 2014 Marvell
+ *
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2 or later. This program is licensed "as is"
+ * without any warranty of any kind, whether express or implied.
+ *
+ * Armada 375 comes with an USB2 host and device controller and an
+ * USB3 controller. The USB cluster control register allows to manage
+ * common features of both USB controllers.
+ */
+
+#include <dt-bindings/phy/phy.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+
+#define USB2_PHY_CONFIG_DISABLE BIT(0)
+
+struct armada375_cluster_phy {
+	struct phy *phy;
+	void __iomem *reg;
+	bool use_usb3;
+	int phy_provided;
+};
+
+static int armada375_usb_phy_init(struct phy *phy)
+{
+	struct armada375_cluster_phy *cluster_phy;
+	u32 reg;
+
+	cluster_phy = dev_get_drvdata(phy->dev.parent);
+	if (!cluster_phy)
+		return -ENODEV;
+
+	reg = readl(cluster_phy->reg);
+	if (cluster_phy->use_usb3)
+		reg |= USB2_PHY_CONFIG_DISABLE;
+	else
+		reg &= ~USB2_PHY_CONFIG_DISABLE;
+	writel(reg, cluster_phy->reg);
+
+	return 0;
+}
+
+static struct phy_ops armada375_usb_phy_ops = {
+	.init = armada375_usb_phy_init,
+	.owner = THIS_MODULE,
+};
+
+/*
+ * Only one controller can use this PHY. We shouldn't have the case
+ * when two controllers want to use this PHY. But if this case occurs
+ * then we provide a phy to the first one and return an error for the
+ * next one. This error has also to be an error returned by
+ * devm_phy_optional_get() so different from ENODEV for USB2. In the
+ * USB3 case it still optional and we use ENODEV.
+ */
+static struct phy *armada375_usb_phy_xlate(struct device *dev,
+					struct of_phandle_args *args)
+{
+	struct armada375_cluster_phy *cluster_phy = dev_get_drvdata(dev);
+
+	if (!cluster_phy)
+		return  ERR_PTR(-ENODEV);
+
+	/*
+	 * Either the phy had never been requested and then the first
+	 * usb claiming it can get it, or it had already been
+	 * requested in this case, we only allow to use it with the
+	 * same configuration.
+	 */
+	if (WARN_ON((cluster_phy->phy_provided != PHY_NONE) &&
+			(cluster_phy->phy_provided != args->args[0]))) {
+		dev_err(dev, "This PHY has already been provided!\n");
+		dev_err(dev, "Check your device tree, only one controller can use it\n.");
+		if (args->args[0] == PHY_TYPE_USB2)
+			return ERR_PTR(-EBUSY);
+		else
+			return ERR_PTR(-ENODEV);
+	}
+
+	if (args->args[0] == PHY_TYPE_USB2)
+		cluster_phy->use_usb3 = false;
+	else if (args->args[0] == PHY_TYPE_USB3)
+		cluster_phy->use_usb3 = true;
+	else {
+		dev_err(dev, "Invalid PHY mode\n");
+		return ERR_PTR(-ENODEV);
+	}
+
+	/* Store which phy mode is used for next test */
+	cluster_phy->phy_provided = args->args[0];
+
+	return cluster_phy->phy;
+}
+
+static int armada375_usb_phy_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct phy *phy;
+	struct phy_provider *phy_provider;
+	void __iomem *usb_cluster_base;
+	struct resource *res;
+	struct armada375_cluster_phy *cluster_phy;
+
+	cluster_phy = devm_kzalloc(dev, sizeof(*cluster_phy), GFP_KERNEL);
+	if (!cluster_phy)
+		return  -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	usb_cluster_base = devm_ioremap_resource(&pdev->dev, res);
+	if (!usb_cluster_base)
+		return -ENOMEM;
+
+	phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops);
+	if (IS_ERR(phy)) {
+		dev_err(dev, "failed to create PHY\n");
+		return PTR_ERR(phy);
+	}
+
+	cluster_phy->phy = phy;
+	cluster_phy->reg = usb_cluster_base;
+
+	dev_set_drvdata(dev, cluster_phy);
+
+	phy_provider = devm_of_phy_provider_register(&pdev->dev,
+						     armada375_usb_phy_xlate);
+	return PTR_ERR_OR_ZERO(phy_provider);
+}
+
+static const struct of_device_id of_usb_cluster_table[] = {
+	{ .compatible = "marvell,armada-375-usb-cluster", },
+	{ /* end of list */ },
+};
+MODULE_DEVICE_TABLE(of, of_usb_cluster_table);
+
+static struct platform_driver armada375_usb_phy_driver = {
+	.probe	= armada375_usb_phy_probe,
+	.driver = {
+		.of_match_table	= of_usb_cluster_table,
+		.name  = "armada-375-usb-cluster",
+		.owner = THIS_MODULE,
+	}
+};
+module_platform_driver(armada375_usb_phy_driver);
+
+MODULE_DESCRIPTION("Armada 375 USB cluster driver");
+MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
+MODULE_LICENSE("GPL");
diff --git a/include/dt-bindings/phy/phy.h b/include/dt-bindings/phy/phy.h
index e8c6a3f..6c90193 100644
--- a/include/dt-bindings/phy/phy.h
+++ b/include/dt-bindings/phy/phy.h
@@ -10,6 +10,7 @@
 #ifndef _DT_BINDINGS_PHY
 #define _DT_BINDINGS_PHY
 
+#define PHY_NONE		0
 #define PHY_TYPE_SATA		1
 #define PHY_TYPE_PCIE		2
 #define PHY_TYPE_USB2		3
-- 
1.7.9.5


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

* Re: [PATCH 03/25] phy: miphy28lp: Provide support for the MiPHY28lp Generic PHY
  2014-11-27  6:25 ` [PATCH 03/25] phy: miphy28lp: Provide support for the MiPHY28lp Generic PHY Kishon Vijay Abraham I
@ 2014-11-27  7:00   ` sanjeev sharma
  0 siblings, 0 replies; 28+ messages in thread
From: sanjeev sharma @ 2014-11-27  7:00 UTC (permalink / raw)
  To: Kishon Vijay Abraham I; +Cc: gregkh, linux-kernel

On Thu, Nov 27, 2014 at 11:55 AM, Kishon Vijay Abraham I <kishon@ti.com> wrote:
> From: Gabriel FERNANDEZ <gabriel.fernandez@st.com>
>
> The MiPHY28lp is a Generic PHY which can serve various SATA or PCIe
> or USB3 devices.
>
> Signed-off-by: alexandre torgue <alexandre.torgue@st.com>
> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
> Signed-off-by: Gabriel Fernandez <gabriel.fernandez@linaro.org>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---
>  drivers/phy/Kconfig         |    8 +
>  drivers/phy/Makefile        |    1 +
>  drivers/phy/phy-miphy28lp.c | 1177 +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 1186 insertions(+)
>  create mode 100644 drivers/phy/phy-miphy28lp.c
>
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 2a436e6..cfaced9 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -38,6 +38,14 @@ config PHY_MVEBU_SATA
>         depends on OF
>         select GENERIC_PHY
>
> +config PHY_MIPHY28LP
> +       tristate "STMicroelectronics MIPHY28LP PHY driver for STiH407"
> +       depends on ARCH_STI
> +       select GENERIC_PHY
> +       help
> +         Enable this to support the miphy transceiver (for SATA/PCIE/USB3)
> +         that is part of STMicroelectronics STiH407 SoC.
> +
>  config PHY_MIPHY365X
>         tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
>         depends on ARCH_STI
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index c4590fc..30d90a8 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_BCM_KONA_USB2_PHY)         += phy-bcm-kona-usb2.o
>  obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)      += phy-exynos-dp-video.o
>  obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)    += phy-exynos-mipi-video.o
>  obj-$(CONFIG_PHY_MVEBU_SATA)           += phy-mvebu-sata.o
> +obj-$(CONFIG_PHY_MIPHY28LP)            += phy-miphy28lp.o
>  obj-$(CONFIG_PHY_MIPHY365X)            += phy-miphy365x.o
>  obj-$(CONFIG_PHY_RCAR_GEN2)            += phy-rcar-gen2.o
>  obj-$(CONFIG_OMAP_CONTROL_PHY)         += phy-omap-control.o
> diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
> new file mode 100644
> index 0000000..7d592e6
> --- /dev/null
> +++ b/drivers/phy/phy-miphy28lp.c
> @@ -0,0 +1,1177 @@
> +/*
> + * Copyright (C) 2014 STMicroelectronics
> + *
> + * STMicroelectronics PHY driver MiPHY28lp (for SoC STiH407).
> + *
> + * Author: Alexandre Torgue <alexandre.torgue@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/platform_device.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_platform.h>
> +#include <linux/of_address.h>
> +#include <linux/clk.h>
> +#include <linux/phy/phy.h>
> +#include <linux/delay.h>
> +#include <linux/mfd/syscon.h>
> +#include <linux/regmap.h>
> +#include <linux/reset.h>
> +
> +#include <dt-bindings/phy/phy.h>
> +
> +/* MiPHY registers */
> +#define MIPHY_CONF_RESET               0x00
> +#define RST_APPLI_SW           BIT(0)
> +#define RST_CONF_SW            BIT(1)
> +#define RST_MACRO_SW           BIT(2)
> +
> +#define MIPHY_RESET                    0x01
> +#define RST_PLL_SW             BIT(0)
> +#define RST_COMP_SW            BIT(2)
> +
> +#define MIPHY_STATUS_1                 0x02
> +#define PHY_RDY                        BIT(0)
> +#define HFC_RDY                        BIT(1)
> +#define HFC_PLL                        BIT(2)
> +
> +#define MIPHY_CONTROL                  0x04
> +#define TERM_EN_SW             BIT(2)
> +#define DIS_LINK_RST           BIT(3)
> +#define AUTO_RST_RX            BIT(4)
> +#define PX_RX_POL              BIT(5)
> +
> +#define MIPHY_BOUNDARY_SEL             0x0a
> +#define TX_SEL                 BIT(6)
> +#define SSC_SEL                        BIT(4)
> +#define GENSEL_SEL             BIT(0)
> +
> +#define MIPHY_BOUNDARY_1               0x0b
> +#define MIPHY_BOUNDARY_2               0x0c
> +#define SSC_EN_SW              BIT(2)
> +
> +#define MIPHY_PLL_CLKREF_FREQ          0x0d
> +#define MIPHY_SPEED                    0x0e
> +#define TX_SPDSEL_80DEC                0
> +#define TX_SPDSEL_40DEC                1
> +#define TX_SPDSEL_20DEC                2
> +#define RX_SPDSEL_80DEC                0
> +#define RX_SPDSEL_40DEC                (1 << 2)
> +#define RX_SPDSEL_20DEC                (2 << 2)
> +
> +#define MIPHY_CONF                     0x0f
> +#define MIPHY_CTRL_TEST_SEL            0x20
> +#define MIPHY_CTRL_TEST_1              0x21
> +#define MIPHY_CTRL_TEST_2              0x22
> +#define MIPHY_CTRL_TEST_3              0x23
> +#define MIPHY_CTRL_TEST_4              0x24
> +#define MIPHY_FEEDBACK_TEST            0x25
> +#define MIPHY_DEBUG_BUS                        0x26
> +#define MIPHY_DEBUG_STATUS_MSB         0x27
> +#define MIPHY_DEBUG_STATUS_LSB         0x28
> +#define MIPHY_PWR_RAIL_1               0x29
> +#define MIPHY_PWR_RAIL_2               0x2a
> +#define MIPHY_SYNCHAR_CONTROL          0x30
> +
> +#define MIPHY_COMP_FSM_1               0x3a
> +#define COMP_START             BIT(6)
> +
> +#define MIPHY_COMP_FSM_6               0x3f
> +#define COMP_DONE              BIT(7)
> +
> +#define MIPHY_COMP_POSTP               0x42
> +#define MIPHY_TX_CTRL_1                        0x49
> +#define TX_REG_STEP_0V         0
> +#define TX_REG_STEP_P_25MV     1
> +#define TX_REG_STEP_P_50MV     2
> +#define TX_REG_STEP_N_25MV     7
> +#define TX_REG_STEP_N_50MV     6
> +#define TX_REG_STEP_N_75MV     5
> +
> +#define MIPHY_TX_CTRL_2                        0x4a
> +#define TX_SLEW_SW_40_PS       0
> +#define TX_SLEW_SW_80_PS       1
> +#define TX_SLEW_SW_120_PS      2
> +
> +#define MIPHY_TX_CTRL_3                        0x4b
> +#define MIPHY_TX_CAL_MAN               0x4e
> +#define TX_SLEW_CAL_MAN_EN     BIT(0)
> +
> +#define MIPHY_TST_BIAS_BOOST_2         0x62
> +#define MIPHY_BIAS_BOOST_1             0x63
> +#define MIPHY_BIAS_BOOST_2             0x64
> +#define MIPHY_RX_DESBUFF_FDB_2         0x67
> +#define MIPHY_RX_DESBUFF_FDB_3         0x68
> +#define MIPHY_SIGDET_COMPENS1          0x69
> +#define MIPHY_SIGDET_COMPENS2          0x6a
> +#define MIPHY_JITTER_PERIOD            0x6b
> +#define MIPHY_JITTER_AMPLITUDE_1       0x6c
> +#define MIPHY_JITTER_AMPLITUDE_2       0x6d
> +#define MIPHY_JITTER_AMPLITUDE_3       0x6e
> +#define MIPHY_RX_K_GAIN                        0x78
> +#define MIPHY_RX_BUFFER_CTRL           0x7a
> +#define VGA_GAIN               BIT(0)
> +#define EQ_DC_GAIN             BIT(2)
> +#define EQ_BOOST_GAIN          BIT(3)
> +
> +#define MIPHY_RX_VGA_GAIN              0x7b
> +#define MIPHY_RX_EQU_GAIN_1            0x7f
> +#define MIPHY_RX_EQU_GAIN_2            0x80
> +#define MIPHY_RX_EQU_GAIN_3            0x81
> +#define MIPHY_RX_CAL_CTRL_1            0x97
> +#define MIPHY_RX_CAL_CTRL_2            0x98
> +
> +#define MIPHY_RX_CAL_OFFSET_CTRL       0x99
> +#define CAL_OFFSET_VGA_64      (0x03 << 0)
> +#define CAL_OFFSET_THRESHOLD_64        (0x03 << 2)
> +#define VGA_OFFSET_POLARITY    BIT(4)
> +#define OFFSET_COMPENSATION_EN BIT(6)
> +
> +#define MIPHY_RX_CAL_VGA_STEP          0x9a
> +#define MIPHY_RX_CAL_EYE_MIN           0x9d
> +#define MIPHY_RX_CAL_OPT_LENGTH                0x9f
> +#define MIPHY_RX_LOCK_CTRL_1           0xc1
> +#define MIPHY_RX_LOCK_SETTINGS_OPT     0xc2
> +#define MIPHY_RX_LOCK_STEP             0xc4
> +
> +#define MIPHY_RX_SIGDET_SLEEP_OA       0xc9
> +#define MIPHY_RX_SIGDET_SLEEP_SEL      0xca
> +#define MIPHY_RX_SIGDET_WAIT_SEL       0xcb
> +#define MIPHY_RX_SIGDET_DATA_SEL       0xcc
> +#define EN_ULTRA_LOW_POWER     BIT(0)
> +#define EN_FIRST_HALF          BIT(1)
> +#define EN_SECOND_HALF         BIT(2)
> +#define EN_DIGIT_SIGNAL_CHECK  BIT(3)
> +
> +#define MIPHY_RX_POWER_CTRL_1          0xcd
> +#define MIPHY_RX_POWER_CTRL_2          0xce
> +#define MIPHY_PLL_CALSET_CTRL          0xd3
> +#define MIPHY_PLL_CALSET_1             0xd4
> +#define MIPHY_PLL_CALSET_2             0xd5
> +#define MIPHY_PLL_CALSET_3             0xd6
> +#define MIPHY_PLL_CALSET_4             0xd7
> +#define MIPHY_PLL_SBR_1                        0xe3
> +#define SET_NEW_CHANGE         BIT(1)
> +
> +#define MIPHY_PLL_SBR_2                        0xe4
> +#define MIPHY_PLL_SBR_3                        0xe5
> +#define MIPHY_PLL_SBR_4                        0xe6
> +#define MIPHY_PLL_COMMON_MISC_2                0xe9
> +#define START_ACT_FILT         BIT(6)
> +
> +#define MIPHY_PLL_SPAREIN              0xeb
> +
> +/*
> + * On STiH407 the glue logic can be different among MiPHY devices; for example:
> + * MiPHY0: OSC_FORCE_EXT means:
> + *  0: 30MHz crystal clk - 1: 100MHz ext clk routed through MiPHY1
> + * MiPHY1: OSC_FORCE_EXT means:
> + *  1: 30MHz crystal clk - 0: 100MHz ext clk routed through MiPHY1
> + * Some devices have not the possibility to check if the osc is ready.
> + */
> +#define MIPHY_OSC_FORCE_EXT    BIT(3)
> +#define MIPHY_OSC_RDY          BIT(5)
> +
> +#define MIPHY_CTRL_MASK                0x0f
> +#define MIPHY_CTRL_DEFAULT     0
> +#define MIPHY_CTRL_SYNC_D_EN   BIT(2)
> +
> +/* SATA / PCIe defines */
> +#define SATA_CTRL_MASK         0x07
> +#define PCIE_CTRL_MASK         0xff
> +#define SATA_CTRL_SELECT_SATA  1
> +#define SATA_CTRL_SELECT_PCIE  0
> +#define SYSCFG_PCIE_PCIE_VAL   0x80
> +#define SATA_SPDMODE           1
> +
> +struct miphy28lp_phy {
> +       struct phy *phy;
> +       struct miphy28lp_dev *phydev;
> +       void __iomem *base;
> +       void __iomem *pipebase;
> +
> +       bool osc_force_ext;
> +       bool osc_rdy;
> +       bool px_rx_pol_inv;
> +
> +       struct reset_control *miphy_rst;
> +
> +       u32 sata_gen;
> +
> +       /* Sysconfig registers offsets needed to configure the device */
> +       u32 syscfg_miphy_ctrl;
> +       u32 syscfg_miphy_status;
> +       u32 syscfg_pci;
> +       u32 syscfg_sata;
> +       u8 type;
> +};
> +
> +struct miphy28lp_dev {
> +       struct device *dev;
> +       struct regmap *regmap;
> +       struct mutex miphy_mutex;
> +       struct miphy28lp_phy **phys;
> +};
> +
> +struct miphy_initval {
> +       u16 reg;
> +       u16 val;
> +};
> +
> +enum miphy_sata_gen { SATA_GEN1, SATA_GEN2, SATA_GEN3 };
> +
> +static char *PHY_TYPE_name[] = { "sata-up", "pcie-up", "", "usb3-up" };
> +
> +struct pll_ratio {
> +       int clk_ref;
> +       int calset_1;
> +       int calset_2;
> +       int calset_3;
> +       int calset_4;
> +       int cal_ctrl;
> +};
> +
> +static struct pll_ratio sata_pll_ratio = {
> +       .clk_ref = 0x1e,
> +       .calset_1 = 0xc8,
> +       .calset_2 = 0x00,
> +       .calset_3 = 0x00,
> +       .calset_4 = 0x00,
> +       .cal_ctrl = 0x00,
> +};
> +
> +static struct pll_ratio pcie_pll_ratio = {
> +       .clk_ref = 0x1e,
> +       .calset_1 = 0xa6,
> +       .calset_2 = 0xaa,
> +       .calset_3 = 0xaa,
> +       .calset_4 = 0x00,
> +       .cal_ctrl = 0x00,
> +};
> +
> +static struct pll_ratio usb3_pll_ratio = {
> +       .clk_ref = 0x1e,
> +       .calset_1 = 0xa6,
> +       .calset_2 = 0xaa,
> +       .calset_3 = 0xaa,
> +       .calset_4 = 0x04,
> +       .cal_ctrl = 0x00,
> +};
> +
> +struct miphy28lp_pll_gen {
> +       int bank;
> +       int speed;
> +       int bias_boost_1;
> +       int bias_boost_2;
> +       int tx_ctrl_1;
> +       int tx_ctrl_2;
> +       int tx_ctrl_3;
> +       int rx_k_gain;
> +       int rx_vga_gain;
> +       int rx_equ_gain_1;
> +       int rx_equ_gain_2;
> +       int rx_equ_gain_3;
> +       int rx_buff_ctrl;
> +};
> +
> +static struct miphy28lp_pll_gen sata_pll_gen[] = {
> +       {
> +               .bank           = 0x00,
> +               .speed          = TX_SPDSEL_80DEC | RX_SPDSEL_80DEC,
> +               .bias_boost_1   = 0x00,
> +               .bias_boost_2   = 0xae,
> +               .tx_ctrl_2      = 0x53,
> +               .tx_ctrl_3      = 0x00,
> +               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
> +               .rx_vga_gain    = 0x00,
> +               .rx_equ_gain_1  = 0x7d,
> +               .rx_equ_gain_2  = 0x56,
> +               .rx_equ_gain_3  = 0x00,
> +       },
> +       {
> +               .bank           = 0x01,
> +               .speed          = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,
> +               .bias_boost_1   = 0x00,
> +               .bias_boost_2   = 0xae,
> +               .tx_ctrl_2      = 0x72,
> +               .tx_ctrl_3      = 0x20,
> +               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
> +               .rx_vga_gain    = 0x00,
> +               .rx_equ_gain_1  = 0x7d,
> +               .rx_equ_gain_2  = 0x56,
> +               .rx_equ_gain_3  = 0x00,
> +       },
> +       {
> +               .bank           = 0x02,
> +               .speed          = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,
> +               .bias_boost_1   = 0x00,
> +               .bias_boost_2   = 0xae,
> +               .tx_ctrl_2      = 0xc0,
> +               .tx_ctrl_3      = 0x20,
> +               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
> +               .rx_vga_gain    = 0x00,
> +               .rx_equ_gain_1  = 0x7d,
> +               .rx_equ_gain_2  = 0x56,
> +               .rx_equ_gain_3  = 0x00,
> +       },
> +};
> +
> +static struct miphy28lp_pll_gen pcie_pll_gen[] = {
> +       {
> +               .bank           = 0x00,
> +               .speed          = TX_SPDSEL_40DEC | RX_SPDSEL_40DEC,
> +               .bias_boost_1   = 0x00,
> +               .bias_boost_2   = 0xa5,
> +               .tx_ctrl_1      = TX_REG_STEP_N_25MV,
> +               .tx_ctrl_2      = 0x71,
> +               .tx_ctrl_3      = 0x60,
> +               .rx_k_gain      = 0x98,
> +               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
> +               .rx_vga_gain    = 0x00,
> +               .rx_equ_gain_1  = 0x79,
> +               .rx_equ_gain_2  = 0x56,
> +       },
> +       {
> +               .bank           = 0x01,
> +               .speed          = TX_SPDSEL_20DEC | RX_SPDSEL_20DEC,
> +               .bias_boost_1   = 0x00,
> +               .bias_boost_2   = 0xa5,
> +               .tx_ctrl_1      = TX_REG_STEP_N_25MV,
> +               .tx_ctrl_2      = 0x70,
> +               .tx_ctrl_3      = 0x60,
> +               .rx_k_gain      = 0xcc,
> +               .rx_buff_ctrl   = EQ_BOOST_GAIN | EQ_DC_GAIN | VGA_GAIN,
> +               .rx_vga_gain    = 0x00,
> +               .rx_equ_gain_1  = 0x78,
> +               .rx_equ_gain_2  = 0x07,
> +       },
> +};
> +
> +static inline void miphy28lp_set_reset(struct miphy28lp_phy *miphy_phy)
> +{
> +       void *base = miphy_phy->base;
> +       u8 val;
> +
> +       /* Putting Macro in reset */
> +       writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
> +
> +       val = RST_APPLI_SW | RST_CONF_SW;
> +       writeb_relaxed(val, base + MIPHY_CONF_RESET);
> +
> +       writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
> +
> +       /* Bringing the MIPHY-CPU registers out of reset */
> +       if (miphy_phy->type == PHY_TYPE_PCIE) {
> +               val = AUTO_RST_RX | TERM_EN_SW;
> +               writeb_relaxed(val, base + MIPHY_CONTROL);
> +       } else {
> +               val = AUTO_RST_RX | TERM_EN_SW | DIS_LINK_RST;
> +               writeb_relaxed(val, base + MIPHY_CONTROL);
> +       }
> +}
> +
> +static inline void miphy28lp_pll_calibration(struct miphy28lp_phy *miphy_phy,
> +               struct pll_ratio *pll_ratio)
> +{
> +       void *base = miphy_phy->base;
> +       u8 val;
> +
> +       /* Applying PLL Settings */
> +       writeb_relaxed(0x1d, base + MIPHY_PLL_SPAREIN);
> +       writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);
> +
> +       /* PLL Ratio */
> +       writeb_relaxed(pll_ratio->calset_1, base + MIPHY_PLL_CALSET_1);
> +       writeb_relaxed(pll_ratio->calset_2, base + MIPHY_PLL_CALSET_2);
> +       writeb_relaxed(pll_ratio->calset_3, base + MIPHY_PLL_CALSET_3);
> +       writeb_relaxed(pll_ratio->calset_4, base + MIPHY_PLL_CALSET_4);
> +       writeb_relaxed(pll_ratio->cal_ctrl, base + MIPHY_PLL_CALSET_CTRL);
> +
> +       writeb_relaxed(TX_SEL, base + MIPHY_BOUNDARY_SEL);
> +
> +       val = (0x68 << 1) | TX_SLEW_CAL_MAN_EN;
> +       writeb_relaxed(val, base + MIPHY_TX_CAL_MAN);
> +
> +       val = VGA_OFFSET_POLARITY | CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;
> +
> +       if (miphy_phy->type != PHY_TYPE_SATA)
> +               val |= OFFSET_COMPENSATION_EN;
> +
> +       writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);
> +
> +       if (miphy_phy->type == PHY_TYPE_USB3) {
> +               writeb_relaxed(0x00, base + MIPHY_CONF);
> +               writeb_relaxed(0x70, base + MIPHY_RX_LOCK_STEP);
> +               writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_OA);
> +               writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_SLEEP_SEL);
> +               writeb_relaxed(EN_FIRST_HALF, base + MIPHY_RX_SIGDET_WAIT_SEL);
> +
> +               val = EN_DIGIT_SIGNAL_CHECK | EN_FIRST_HALF;
> +               writeb_relaxed(val, base + MIPHY_RX_SIGDET_DATA_SEL);
> +       }
> +
> +}
> +
> +static inline void miphy28lp_sata_config_gen(struct miphy28lp_phy *miphy_phy)
> +{
> +       void __iomem *base = miphy_phy->base;
> +       int i;
> +
> +       for (i = 0; i < ARRAY_SIZE(sata_pll_gen); i++) {
> +               struct miphy28lp_pll_gen *gen = &sata_pll_gen[i];
> +
> +               /* Banked settings */
> +               writeb_relaxed(gen->bank, base + MIPHY_CONF);
> +               writeb_relaxed(gen->speed, base + MIPHY_SPEED);
> +               writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);
> +               writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);
> +
> +               /* TX buffer Settings */
> +               writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);
> +               writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);
> +
> +               /* RX Buffer Settings */
> +               writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);
> +               writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);
> +               writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);
> +               writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);
> +               writeb_relaxed(gen->rx_equ_gain_3, base + MIPHY_RX_EQU_GAIN_3);
> +       }
> +}
> +
> +static inline void miphy28lp_pcie_config_gen(struct miphy28lp_phy *miphy_phy)
> +{
> +       void __iomem *base = miphy_phy->base;
> +       int i;
> +
> +       for (i = 0; i < ARRAY_SIZE(pcie_pll_gen); i++) {
> +               struct miphy28lp_pll_gen *gen = &pcie_pll_gen[i];
> +
> +               /* Banked settings */
> +               writeb_relaxed(gen->bank, base + MIPHY_CONF);
> +               writeb_relaxed(gen->speed, base + MIPHY_SPEED);
> +               writeb_relaxed(gen->bias_boost_1, base + MIPHY_BIAS_BOOST_1);
> +               writeb_relaxed(gen->bias_boost_2, base + MIPHY_BIAS_BOOST_2);
> +
> +               /* TX buffer Settings */
> +               writeb_relaxed(gen->tx_ctrl_1, base + MIPHY_TX_CTRL_1);
> +               writeb_relaxed(gen->tx_ctrl_2, base + MIPHY_TX_CTRL_2);
> +               writeb_relaxed(gen->tx_ctrl_3, base + MIPHY_TX_CTRL_3);
> +
> +               writeb_relaxed(gen->rx_k_gain, base + MIPHY_RX_K_GAIN);
> +
> +               /* RX Buffer Settings */
> +               writeb_relaxed(gen->rx_buff_ctrl, base + MIPHY_RX_BUFFER_CTRL);
> +               writeb_relaxed(gen->rx_vga_gain, base + MIPHY_RX_VGA_GAIN);
> +               writeb_relaxed(gen->rx_equ_gain_1, base + MIPHY_RX_EQU_GAIN_1);
> +               writeb_relaxed(gen->rx_equ_gain_2, base + MIPHY_RX_EQU_GAIN_2);
> +       }
> +}
> +
> +static inline int miphy28lp_wait_compensation(struct miphy28lp_phy *miphy_phy)
> +{
> +       unsigned long finish = jiffies + 5 * HZ;
> +       u8 val;
> +
> +       /* Waiting for Compensation to complete */
> +       do {
> +               val = readb_relaxed(miphy_phy->base + MIPHY_COMP_FSM_6);
> +
> +               if (time_after_eq(jiffies, finish))
> +                       return -EBUSY;
> +               cpu_relax();
> +       } while (!(val & COMP_DONE));
> +
> +       return 0;
> +}
> +
> +
> +static inline int miphy28lp_compensation(struct miphy28lp_phy *miphy_phy,
> +               struct pll_ratio *pll_ratio)
> +{
> +       void __iomem *base = miphy_phy->base;
> +
> +       /* Poll for HFC ready after reset release */
> +       /* Compensation measurement */
> +       writeb_relaxed(RST_PLL_SW | RST_COMP_SW, base + MIPHY_RESET);
> +
> +       writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);
> +       writeb_relaxed(pll_ratio->clk_ref, base + MIPHY_PLL_CLKREF_FREQ);
> +       writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);
> +
> +       if (miphy_phy->type == PHY_TYPE_PCIE)
> +               writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);
> +
> +       writeb_relaxed(0x00, base + MIPHY_RESET);
> +       writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);
> +       writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
> +
> +       /* TX compensation offset to re-center TX impedance */
> +       writeb_relaxed(0x00, base + MIPHY_COMP_POSTP);
> +
> +       if (miphy_phy->type == PHY_TYPE_PCIE)
> +               return miphy28lp_wait_compensation(miphy_phy);
> +
> +       return 0;
> +}
> +
> +static inline void miphy28_usb3_miphy_reset(struct miphy28lp_phy *miphy_phy)
> +{
> +       void __iomem *base = miphy_phy->base;
> +       u8 val;
> +
> +       /* MIPHY Reset */
> +       writeb_relaxed(RST_APPLI_SW, base + MIPHY_CONF_RESET);
> +       writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
> +       writeb_relaxed(RST_COMP_SW, base + MIPHY_RESET);
> +
> +       val = RST_COMP_SW | RST_PLL_SW;
> +       writeb_relaxed(val, base + MIPHY_RESET);
> +
> +       writeb_relaxed(0x00, base + MIPHY_PLL_COMMON_MISC_2);
> +       writeb_relaxed(0x1e, base + MIPHY_PLL_CLKREF_FREQ);
> +       writeb_relaxed(COMP_START, base + MIPHY_COMP_FSM_1);
> +       writeb_relaxed(RST_PLL_SW, base + MIPHY_RESET);
> +       writeb_relaxed(0x00, base + MIPHY_RESET);
> +       writeb_relaxed(START_ACT_FILT, base + MIPHY_PLL_COMMON_MISC_2);
> +       writeb_relaxed(0x00, base + MIPHY_CONF);
> +       writeb_relaxed(0x00, base + MIPHY_BOUNDARY_1);
> +       writeb_relaxed(0x00, base + MIPHY_TST_BIAS_BOOST_2);
> +       writeb_relaxed(0x00, base + MIPHY_CONF);
> +       writeb_relaxed(SET_NEW_CHANGE, base + MIPHY_PLL_SBR_1);
> +       writeb_relaxed(0xa5, base + MIPHY_DEBUG_BUS);
> +       writeb_relaxed(0x00, base + MIPHY_CONF);
> +}
> +
> +static inline int miphy28lp_configure_sata(struct miphy28lp_phy *miphy_phy)
> +{
> +       void __iomem *base = miphy_phy->base;
> +       int err;
> +       u8 val;
> +
> +       /* Putting Macro in reset */
> +       miphy28lp_set_reset(miphy_phy);
> +
> +       /* PLL calibration */
> +       miphy28lp_pll_calibration(miphy_phy, &sata_pll_ratio);
> +
> +       /* Banked settings Gen1/Gen2/Gen3 */
> +       miphy28lp_sata_config_gen(miphy_phy);
> +
> +       /* Power control */
> +       /* Input bridge enable, manual input bridge control */
> +       writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
> +
> +       /* Macro out of reset */
> +       writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
> +
> +       /* Poll for HFC ready after reset release */
> +       /* Compensation measurement */
> +       err = miphy28lp_compensation(miphy_phy, &sata_pll_ratio);
> +       if (err)
> +               return err;
> +
> +       if (miphy_phy->px_rx_pol_inv) {
> +               /* Invert Rx polarity */
> +               val = readb_relaxed(miphy_phy->base + MIPHY_CONTROL);
> +               val |= PX_RX_POL;
> +               writeb_relaxed(val, miphy_phy->base + MIPHY_CONTROL);
> +       }
> +
> +       return 0;
> +}
> +
> +static inline int miphy28lp_configure_pcie(struct miphy28lp_phy *miphy_phy)
> +{
> +       void __iomem *base = miphy_phy->base;
> +       int err;
> +
> +       /* Putting Macro in reset */
> +       miphy28lp_set_reset(miphy_phy);
> +
> +       /* PLL calibration */
> +       miphy28lp_pll_calibration(miphy_phy, &pcie_pll_ratio);
> +
> +       /* Banked settings Gen1/Gen2 */
> +       miphy28lp_pcie_config_gen(miphy_phy);
> +
> +       /* Power control */
> +       /* Input bridge enable, manual input bridge control */
> +       writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
> +
> +       /* Macro out of reset */
> +       writeb_relaxed(0x00, base + MIPHY_CONF_RESET);
> +
> +       /* Poll for HFC ready after reset release */
> +       /* Compensation measurement */
> +       err = miphy28lp_compensation(miphy_phy, &pcie_pll_ratio);
> +       if (err)
> +               return err;
> +
> +       return 0;
> +}
> +
> +
> +static inline void miphy28lp_configure_usb3(struct miphy28lp_phy *miphy_phy)
> +{
> +       void __iomem *base = miphy_phy->base;
> +       u8 val;
> +
> +       /* Putting Macro in reset */
> +       miphy28lp_set_reset(miphy_phy);
> +
> +       /* PLL calibration */
> +       miphy28lp_pll_calibration(miphy_phy, &usb3_pll_ratio);
> +
> +       /* Writing The Speed Rate */
> +       writeb_relaxed(0x00, base + MIPHY_CONF);
> +
> +       val = RX_SPDSEL_20DEC | TX_SPDSEL_20DEC;
> +       writeb_relaxed(val, base + MIPHY_SPEED);
> +
> +       /* RX Channel compensation and calibration */
> +       writeb_relaxed(0x1c, base + MIPHY_RX_LOCK_SETTINGS_OPT);
> +       writeb_relaxed(0x51, base + MIPHY_RX_CAL_CTRL_1);
> +       writeb_relaxed(0x70, base + MIPHY_RX_CAL_CTRL_2);
> +
> +       val = OFFSET_COMPENSATION_EN | VGA_OFFSET_POLARITY |
> +             CAL_OFFSET_THRESHOLD_64 | CAL_OFFSET_VGA_64;
> +       writeb_relaxed(val, base + MIPHY_RX_CAL_OFFSET_CTRL);
> +       writeb_relaxed(0x22, base + MIPHY_RX_CAL_VGA_STEP);
> +       writeb_relaxed(0x0e, base + MIPHY_RX_CAL_OPT_LENGTH);
> +
> +       val = EQ_DC_GAIN | VGA_GAIN;
> +       writeb_relaxed(val, base + MIPHY_RX_BUFFER_CTRL);
> +       writeb_relaxed(0x78, base + MIPHY_RX_EQU_GAIN_1);
> +       writeb_relaxed(0x1b, base + MIPHY_SYNCHAR_CONTROL);
> +
> +       /* TX compensation offset to re-center TX impedance */
> +       writeb_relaxed(0x02, base + MIPHY_COMP_POSTP);
> +
> +       /* Enable GENSEL_SEL and SSC */
> +       /* TX_SEL=0 swing preemp forced by pipe registres */
> +       val = SSC_SEL | GENSEL_SEL;
> +       writeb_relaxed(val, base + MIPHY_BOUNDARY_SEL);
> +
> +       /* MIPHY Bias boost */
> +       writeb_relaxed(0x00, base + MIPHY_BIAS_BOOST_1);
> +       writeb_relaxed(0xa7, base + MIPHY_BIAS_BOOST_2);
> +
> +       /* SSC modulation */
> +       writeb_relaxed(SSC_EN_SW, base + MIPHY_BOUNDARY_2);
> +
> +       /* MIPHY TX control */
> +       writeb_relaxed(0x00, base + MIPHY_CONF);
> +
> +       /* Validate Step component */
> +       writeb_relaxed(0x5a, base + MIPHY_PLL_SBR_3);
> +       writeb_relaxed(0xa0, base + MIPHY_PLL_SBR_4);
> +
> +       /* Validate Period component */
> +       writeb_relaxed(0x3c, base + MIPHY_PLL_SBR_2);
> +       writeb_relaxed(0xa1, base + MIPHY_PLL_SBR_4);
> +
> +       /* Clear any previous request */
> +       writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
> +
> +       /* requests the PLL to take in account new parameters */
> +       writeb_relaxed(0x02, base + MIPHY_PLL_SBR_1);
> +
> +       /* To be sure there is no other pending requests */
> +       writeb_relaxed(0x00, base + MIPHY_PLL_SBR_1);
> +
> +       /* Rx PI controller settings */
> +       writeb_relaxed(0xca, base + MIPHY_RX_K_GAIN);
> +
> +       /* MIPHY RX input bridge control */
> +       /* INPUT_BRIDGE_EN_SW=1, manual input bridge control[0]=1 */
> +       writeb_relaxed(0x21, base + MIPHY_RX_POWER_CTRL_1);
> +       writeb_relaxed(0x29, base + MIPHY_RX_POWER_CTRL_1);
> +       writeb_relaxed(0x1a, base + MIPHY_RX_POWER_CTRL_2);
> +
> +       /* MIPHY Reset for usb3 */
> +       miphy28_usb3_miphy_reset(miphy_phy);
> +}
> +
> +static inline int miphy_is_ready(struct miphy28lp_phy *miphy_phy)
> +{
> +       unsigned long finish = jiffies + 5 * HZ;
> +       u8 mask = HFC_PLL | HFC_RDY;
> +       u8 val;
> +
> +       /*
> +        * For PCIe and USB3 check only that PLL and HFC are ready
> +        * For SATA check also that phy is ready!
> +        */
> +       if (miphy_phy->type == PHY_TYPE_SATA)
> +               mask |= PHY_RDY;
> +
> +       do {
> +               val = readb_relaxed(miphy_phy->base + MIPHY_STATUS_1);
> +               if ((val & mask) != mask)
> +                       cpu_relax();
> +               else
> +                       return 0;
> +       } while (!time_after_eq(jiffies, finish));
> +
> +       return -EBUSY;
> +}
> +
> +static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
> +{
> +       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
> +       unsigned long finish = jiffies + 5 * HZ;
> +       u32 val;
> +
> +       if (!miphy_phy->osc_rdy)
> +               return 0;
> +
> +       if (!miphy_phy->syscfg_miphy_status)
> +               return -EINVAL;
> +
> +       do {
> +               regmap_read(miphy_dev->regmap, miphy_phy->syscfg_miphy_status,
> +                           &val);
> +
> +               if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY)
> +                       cpu_relax();
> +               else
> +                       return 0;
> +       } while (!time_after_eq(jiffies, finish));
> +
> +       return -EBUSY;
> +}
> +
> +static int miphy28lp_get_resource_byname(struct device_node *child,
> +                                         char *rname, struct resource *res)
> +{
> +       int index;
> +
> +       index = of_property_match_string(child, "reg-names", rname);
> +       if (index < 0)
> +               return -ENODEV;
> +
> +       return of_address_to_resource(child, index, res);
> +}
> +
> +static int miphy28lp_get_one_addr(struct device *dev,
> +                                 struct device_node *child, char *rname,
> +                                 void __iomem **base)
> +{
> +       struct resource res;
> +       int ret;
> +
> +       ret = miphy28lp_get_resource_byname(child, rname, &res);
> +       if (!ret) {
> +               *base = devm_ioremap(dev, res.start, resource_size(&res));
> +               if (!*base) {
> +                       dev_err(dev, "failed to ioremap %s address region\n"
> +                                       , rname);
> +                       return -ENOENT;
> +               }
> +       }
> +
> +       return 0;
> +}
> +
> +/* MiPHY reset and sysconf setup */
> +static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)
> +{
> +       int err;
> +       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
> +
> +       if (!miphy_phy->syscfg_miphy_ctrl)
> +               return -EINVAL;
> +
> +       err = reset_control_assert(miphy_phy->miphy_rst);
> +       if (err) {
> +               dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
> +               return err;
> +       }
> +
> +       if (miphy_phy->osc_force_ext)
> +               miphy_val |= MIPHY_OSC_FORCE_EXT;
> +
> +       regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_miphy_ctrl,
> +                          MIPHY_CTRL_MASK, miphy_val);
> +
> +       err = reset_control_deassert(miphy_phy->miphy_rst);
> +       if (err) {
> +               dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
> +               return err;
> +       }
> +
> +       return miphy_osc_is_ready(miphy_phy);
> +}
> +
> +static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)
> +{
> +       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
> +       int err, sata_conf = SATA_CTRL_SELECT_SATA;
> +
> +       if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci)
> +               || (!miphy_phy->base))
> +               return -EINVAL;
> +
> +       dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base);
> +
> +       /* Configure the glue-logic */
> +       sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE);
> +
> +       regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata,
> +                          SATA_CTRL_MASK, sata_conf);
> +
> +       regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci,
> +                          PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
> +
> +       /* MiPHY path and clocking init */
> +       err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);
> +
> +       if (err) {
> +               dev_err(miphy_dev->dev, "SATA phy setup failed\n");
> +               return err;
> +       }
> +
> +       /* initialize miphy */
> +       miphy28lp_configure_sata(miphy_phy);
> +
> +       return miphy_is_ready(miphy_phy);
> +}
> +
> +static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy)
> +{
> +       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
> +       int err;
> +
> +       if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci)
> +               || (!miphy_phy->base) || (!miphy_phy->pipebase))
> +               return -EINVAL;
> +
> +       dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base);
> +
> +       /* Configure the glue-logic */
> +       regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata,
> +                          SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
> +
> +       regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci,
> +                          PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL);
> +
> +       /* MiPHY path and clocking init */
> +       err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_DEFAULT);
> +
> +       if (err) {
> +               dev_err(miphy_dev->dev, "PCIe phy setup failed\n");
> +               return err;
> +       }
> +
> +       /* initialize miphy */
> +       err = miphy28lp_configure_pcie(miphy_phy);
> +       if (err)
> +               return err;
> +
> +       /* PIPE Wrapper Configuration */
> +       writeb_relaxed(0x68, miphy_phy->pipebase + 0x104); /* Rise_0 */
> +       writeb_relaxed(0x61, miphy_phy->pipebase + 0x105); /* Rise_1 */
> +       writeb_relaxed(0x68, miphy_phy->pipebase + 0x108); /* Fall_0 */
> +       writeb_relaxed(0x61, miphy_phy->pipebase + 0x109); /* Fall-1 */
> +       writeb_relaxed(0x68, miphy_phy->pipebase + 0x10c); /* Threshold_0 */
> +       writeb_relaxed(0x60, miphy_phy->pipebase + 0x10d); /* Threshold_1 */
> +
> +       /* Wait for phy_ready */
> +       return miphy_is_ready(miphy_phy);
> +}
> +
> +static int miphy28lp_init_usb3(struct miphy28lp_phy *miphy_phy)
> +{
> +       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
> +       int err;
> +
> +       if ((!miphy_phy->base) || (!miphy_phy->pipebase))
> +               return -EINVAL;
> +
> +       dev_info(miphy_dev->dev, "usb3-up mode, addr 0x%p\n", miphy_phy->base);
> +
> +       /* MiPHY path and clocking init */
> +       err = miphy28lp_setup(miphy_phy, MIPHY_CTRL_SYNC_D_EN);
> +       if (err) {
> +               dev_err(miphy_dev->dev, "USB3 phy setup failed\n");
> +               return err;
> +       }
> +
> +       /* initialize miphy */
> +       miphy28lp_configure_usb3(miphy_phy);
> +
> +       /* PIPE Wrapper Configuration */
> +       writeb_relaxed(0x68, miphy_phy->pipebase + 0x23);
> +       writeb_relaxed(0x61, miphy_phy->pipebase + 0x24);
> +       writeb_relaxed(0x68, miphy_phy->pipebase + 0x26);
> +       writeb_relaxed(0x61, miphy_phy->pipebase + 0x27);
> +       writeb_relaxed(0x18, miphy_phy->pipebase + 0x29);
> +       writeb_relaxed(0x61, miphy_phy->pipebase + 0x2a);
> +
> +       /* pipe Wrapper usb3 TX swing de-emph margin PREEMPH[7:4], SWING[3:0] */
> +       writeb_relaxed(0X67, miphy_phy->pipebase + 0x68);
> +       writeb_relaxed(0x0d, miphy_phy->pipebase + 0x69);
> +       writeb_relaxed(0X67, miphy_phy->pipebase + 0x6a);
> +       writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6b);
> +       writeb_relaxed(0X67, miphy_phy->pipebase + 0x6c);
> +       writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6d);
> +       writeb_relaxed(0X67, miphy_phy->pipebase + 0x6e);
> +       writeb_relaxed(0X0d, miphy_phy->pipebase + 0x6f);
> +
> +       return miphy_is_ready(miphy_phy);
> +}
> +
> +static int miphy28lp_init(struct phy *phy)
> +{
> +       struct miphy28lp_phy *miphy_phy = phy_get_drvdata(phy);
> +       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
> +       int ret;
> +
> +       mutex_lock(&miphy_dev->miphy_mutex);
> +
> +       switch (miphy_phy->type) {
> +
> +       case PHY_TYPE_SATA:
> +               ret = miphy28lp_init_sata(miphy_phy);
> +               break;
> +       case PHY_TYPE_PCIE:
> +               ret = miphy28lp_init_pcie(miphy_phy);
> +               break;
> +       case PHY_TYPE_USB3:
> +               ret = miphy28lp_init_usb3(miphy_phy);
> +               break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       mutex_unlock(&miphy_dev->miphy_mutex);
> +
> +       return ret;
> +}
> +
> +static int miphy28lp_get_addr(struct miphy28lp_phy *miphy_phy)
> +{
> +       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
> +       struct device_node *phynode = miphy_phy->phy->dev.of_node;
> +       int err;
> +
> +       if ((miphy_phy->type != PHY_TYPE_SATA) &&
> +           (miphy_phy->type != PHY_TYPE_PCIE) &&
> +           (miphy_phy->type != PHY_TYPE_USB3)) {
> +               return -EINVAL;
> +       }
> +
> +       err = miphy28lp_get_one_addr(miphy_dev->dev, phynode,
> +                       PHY_TYPE_name[miphy_phy->type - PHY_TYPE_SATA],
> +                       &miphy_phy->base);
> +       if (err)
> +               return err;
> +
> +       if ((miphy_phy->type == PHY_TYPE_PCIE) ||
> +           (miphy_phy->type == PHY_TYPE_USB3)) {
> +               err = miphy28lp_get_one_addr(miphy_dev->dev, phynode, "pipew",
> +                                            &miphy_phy->pipebase);
> +               if (err)
> +                       return err;
> +       }
> +
> +       return 0;
> +}
> +
> +static struct phy *miphy28lp_xlate(struct device *dev,
> +                                  struct of_phandle_args *args)
> +{
> +       struct miphy28lp_dev *miphy_dev = dev_get_drvdata(dev);
> +       struct miphy28lp_phy *miphy_phy = NULL;
> +       struct device_node *phynode = args->np;
> +       int ret, index = 0;
> +
> +       if (!of_device_is_available(phynode)) {
> +               dev_warn(dev, "Requested PHY is disabled\n");
> +               return ERR_PTR(-ENODEV);
> +       }
> +
> +       if (args->args_count != 1) {
> +               dev_err(dev, "Invalid number of cells in 'phy' property\n");
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       for (index = 0; index < of_get_child_count(dev->of_node); index++)
> +               if (phynode == miphy_dev->phys[index]->phy->dev.of_node) {
> +                       miphy_phy = miphy_dev->phys[index];
> +                       break;
> +               }
> +
> +       if (!miphy_phy) {
> +               dev_err(dev, "Failed to find appropriate phy\n");
> +               return ERR_PTR(-EINVAL);
> +       }
> +
> +       miphy_phy->type = args->args[0];
> +
> +       ret = miphy28lp_get_addr(miphy_phy);
> +       if (ret < 0)
> +               return ERR_PTR(ret);
> +
> +       return miphy_phy->phy;
> +}
> +
> +static struct phy_ops miphy28lp_ops = {
> +       .init = miphy28lp_init,
> +};
> +
> +static int miphy28lp_probe_resets(struct device_node *node,
> +                                 struct miphy28lp_phy *miphy_phy)
> +{
> +       struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
> +       int err;
> +
> +       miphy_phy->miphy_rst = of_reset_control_get(node, "miphy-sw-rst");
> +
> +       if (IS_ERR(miphy_phy->miphy_rst)) {
> +               dev_err(miphy_dev->dev,
> +                               "miphy soft reset control not defined\n");
> +               return PTR_ERR(miphy_phy->miphy_rst);
> +       }
> +
> +       err = reset_control_deassert(miphy_phy->miphy_rst);
> +       if (err) {
> +               dev_err(miphy_dev->dev, "unable to bring out of miphy reset\n");
> +               return err;
> +       }
> +
> +       return 0;
> +}
> +
> +static int miphy28lp_of_probe(struct device_node *np,
> +                             struct miphy28lp_phy *miphy_phy)
> +{
> +       struct resource res;
> +
> +       miphy_phy->osc_force_ext =
> +               of_property_read_bool(np, "st,osc-force-ext");
> +
> +       miphy_phy->osc_rdy = of_property_read_bool(np, "st,osc-rdy");
> +
> +       miphy_phy->px_rx_pol_inv =
> +               of_property_read_bool(np, "st,px_rx_pol_inv");
> +
> +       of_property_read_u32(np, "st,sata-gen", &miphy_phy->sata_gen);
> +       if (!miphy_phy->sata_gen)
> +               miphy_phy->sata_gen = SATA_GEN1;
> +
> +       if (!miphy28lp_get_resource_byname(np, "miphy-ctrl-glue", &res))
> +               miphy_phy->syscfg_miphy_ctrl = res.start;
> +
> +       if (!miphy28lp_get_resource_byname(np, "miphy-status-glue", &res))
> +               miphy_phy->syscfg_miphy_status = res.start;
> +
> +       if (!miphy28lp_get_resource_byname(np, "pcie-glue", &res))
> +               miphy_phy->syscfg_pci = res.start;
> +
> +       if (!miphy28lp_get_resource_byname(np, "sata-glue", &res))
> +               miphy_phy->syscfg_sata = res.start;
> +
> +
> +       return 0;
> +}
> +
> +static int miphy28lp_probe(struct platform_device *pdev)
> +{
> +       struct device_node *child, *np = pdev->dev.of_node;
> +       struct miphy28lp_dev *miphy_dev;
> +       struct phy_provider *provider;
> +       struct phy *phy;
> +       int chancount, port = 0;
> +       int ret;
> +
> +       miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
> +       if (!miphy_dev)
> +               return -ENOMEM;
> +
> +       chancount = of_get_child_count(np);
> +       miphy_dev->phys = devm_kzalloc(&pdev->dev, sizeof(phy) * chancount,
> +                                      GFP_KERNEL);
> +       if (!miphy_dev->phys)
> +               return -ENOMEM;
> +
> +       miphy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
> +       if (IS_ERR(miphy_dev->regmap)) {
> +               dev_err(miphy_dev->dev, "No syscfg phandle specified\n");
> +               return PTR_ERR(miphy_dev->regmap);
> +       }
> +
> +       miphy_dev->dev = &pdev->dev;
> +
> +       dev_set_drvdata(&pdev->dev, miphy_dev);
> +
> +       mutex_init(&miphy_dev->miphy_mutex);
> +
> +       for_each_child_of_node(np, child) {
> +               struct miphy28lp_phy *miphy_phy;
> +
> +               miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
> +                                        GFP_KERNEL);
> +               if (!miphy_phy)
> +                       return -ENOMEM;
> +
> +               miphy_dev->phys[port] = miphy_phy;
> +
> +               phy = devm_phy_create(&pdev->dev, child, &miphy28lp_ops, NULL);
> +               if (IS_ERR(phy)) {
> +                       dev_err(&pdev->dev, "failed to create PHY\n");
> +                       return PTR_ERR(phy);
> +               }
> +
> +               miphy_dev->phys[port]->phy = phy;
> +               miphy_dev->phys[port]->phydev = miphy_dev;
> +
> +               ret = miphy28lp_of_probe(child, miphy_phy);
> +               if (ret)
> +                       return ret;
> +
> +               ret = miphy28lp_probe_resets(child, miphy_dev->phys[port]);
> +               if (ret)
> +                       return ret;
> +
> +               phy_set_drvdata(phy, miphy_dev->phys[port]);
> +               port++;
> +
> +       }
> +
> +       provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);
> +       if (IS_ERR(provider))
> +               return PTR_ERR(provider);
> +
> +       return 0;
> +}
> +
> +static const struct of_device_id miphy28lp_of_match[] = {
> +       {.compatible = "st,miphy28lp-phy", },
> +       {},
> +};
> +
> +MODULE_DEVICE_TABLE(of, miphy28lp_of_match);
> +
> +static struct platform_driver miphy28lp_driver = {
> +       .probe = miphy28lp_probe,
> +       .driver = {
> +               .name = "miphy28lp-phy",
> +               .owner = THIS_MODULE,

can we remove .owner field for drivers because this is overriden in
_platform_driver_register.

Sanjeev

> +               .of_match_table = miphy28lp_of_match,
> +       }
> +};
> +
> +module_platform_driver(miphy28lp_driver);
> +
> +MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
> +MODULE_DESCRIPTION("STMicroelectronics miphy28lp driver");
> +MODULE_LICENSE("GPL v2");
> --
> 1.7.9.5
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [GIT PULL 00/25] phy: for 3.19
  2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
                   ` (24 preceding siblings ...)
  2014-11-27  6:26 ` [PATCH 25/25] phy: add support for USB cluster on the Armada 375 SoC Kishon Vijay Abraham I
@ 2014-11-27 16:49 ` Greg KH
  25 siblings, 0 replies; 28+ messages in thread
From: Greg KH @ 2014-11-27 16:49 UTC (permalink / raw)
  To: Kishon Vijay Abraham I; +Cc: linux-kernel

On Thu, Nov 27, 2014 at 11:55:52AM +0530, Kishon Vijay Abraham I wrote:
> Hi Greg,
> 
> Please find the pull request for 3.19 merge window.
> 
> This contains improvements in phy core dealing with non-dt boot.
> It also adds 3 new phy drivers armada375-usb2, berlin-usb and miphy28lp.
> 
> There is a patch that touches drivers/pinctrl since one of the PHY drivers
> is present there and it has to be modified to use the modified
> devm_phy_create API.
> 
> Let me know If I have to change something.
> 
> Thanks
> Kishon
> 
> The following changes since commit 206c5f60a3d902bc4b56dab2de3e88de5eb06108:
> 
>   Linux 3.18-rc4 (2014-11-09 14:55:29 -0800)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git tags/for-3.19

Pulled and pushed out, thanks.

greg k-h

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

end of thread, other threads:[~2014-11-27 16:51 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-27  6:25 [GIT PULL 00/25] phy: for 3.19 Kishon Vijay Abraham I
2014-11-27  6:25 ` [PATCH 01/25] phy: Add PHY header file for DT x Driver defines Kishon Vijay Abraham I
2014-11-27  6:25 ` [PATCH 02/25] phy: miphy28lp: Add Device Tree bindings for the MiPHY28lp Kishon Vijay Abraham I
2014-11-27  6:25 ` [PATCH 03/25] phy: miphy28lp: Provide support for the MiPHY28lp Generic PHY Kishon Vijay Abraham I
2014-11-27  7:00   ` sanjeev sharma
2014-11-27  6:25 ` [PATCH 04/25] phy: miphy28lp: Add SSC support for SATA Kishon Vijay Abraham I
2014-11-27  6:25 ` [PATCH 05/25] phy: miphy28lp: Add SSC support for PCIE Kishon Vijay Abraham I
2014-11-27  6:25 ` [PATCH 06/25] phy: miphy28lp: Tune tx impedance across Soc cuts Kishon Vijay Abraham I
2014-11-27  6:25 ` [PATCH 07/25] phy: phy-core: use the np present in of_phandle_args to get the PHY Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 08/25] phy: sun4i: add support for USB phy0 Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 09/25] phy: berlin-sata: Move PHY_BASE into private data struct Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 10/25] phy: berlin-sata: Add support for BG2 SATA PHY Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 11/25] phy: berlin-sata: Document BG2 compatible Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 12/25] phy: add the Berlin USB PHY driver Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 13/25] Documentation: bindings: add doc for the Berlin USB PHY Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 14/25] phy: safer to_phy() macro Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 15/25] phy: improved lookup method Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 16/25] phy: twl4030: use the new " Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 17/25] phy: remove the old " Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 18/25] usb: dwc3: host: convey the PHYs to xhci Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 19/25] phy: exynos5-usbdrd: Add pipe-clk, utmi-clk and itp-clk support Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 20/25] phy: exynos5-usbdrd: Add facility for VBUS-BOOST-5V supply Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 21/25] phy: exynos7-usbdrd: Update dependency for ARCH_EXYNOS Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 22/25] phy: Use PTR_ERR_OR_ZERO to fix warning raised by coccinelle Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 23/25] Phy: DT binding documentation for Marvell MVEBU SATA phy Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 24/25] Phy: DT binding documentation for the Armada 375 USB cluster binding Kishon Vijay Abraham I
2014-11-27  6:26 ` [PATCH 25/25] phy: add support for USB cluster on the Armada 375 SoC Kishon Vijay Abraham I
2014-11-27 16:49 ` [GIT PULL 00/25] phy: for 3.19 Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome