All of lore.kernel.org
 help / color / mirror / Atom feed
* [GIT PULL 00/28] PHY: for 3.17
@ 2014-07-22 10:56 Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 01/28] phy: miphy365x: Add MiPHY365x header file for DT x Driver defines Kishon Vijay Abraham I
                   ` (28 more replies)
  0 siblings, 29 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

Hi Greg,

Here's the PULL Request for 3.17 merge window. It adds regulator
support in PHY core and adds better support for multi-phy PHY providers.
It includes a bunch of new PHY drivers and some misc cleanups and fixes.

Let me know if I have to change something.

Cheers
Kishon

The following changes since commit 1795cd9b3a91d4b5473c97f491d63892442212ab:

  Linux 3.16-rc5 (2014-07-13 14:04:33 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git tags/for_3.17

for you to fetch changes up to 7ebdb52e192c4d496a9b3a87d47eba3eba3e1fd4:

  phy: miphy365x: Represent each PHY channel as a DT subnode (2014-07-22 12:46:43 +0530)

----------------------------------------------------------------
for_3.17

Adds regulator support in PHY core. PHY core is modified to support
representation of multi-phy PHY providers with each individual PHY
as sub-node OF PHY provider node. New PHY drivers adapted to PHY
framework (hix5hd2 SATA PHY, QCOM APQ8064 SATA PHY,
QCOM IPQ806x SATA PHY, Berlin SATA PHY and MiPHY356x). Existing
TI PIPE3 PHY can now be used for PCIe too. Includes misc fixes and
cleanups.

----------------------------------------------------------------
Andrew Lunn (1):
      phy: Remove ARCH_KIRKWOOD dependency

Antoine Ténart (2):
      phy: add a driver for the Berlin SATA PHY
      Documentation: bindings: add the Berlin SATA PHY

Jiancheng Xue (2):
      Documentation: Document Hisilicon hix5hd2 sata PHY
      phy: add hix5hd2-sata-phy driver

Jingoo Han (1):
      phy: exynos5-usbdrd: Make local functions static

Kamil Debski (1):
      phy: phy-samsung-usb2: Change phy power on/power off sequence

Kishon Vijay Abraham I (4):
      phy: phy-omap-pipe3: Add support for PCIe PHY
      phy: pipe3: insert delay to enumerate in GEN2 mode
      phy: core: Fix of_phy_provider_lookup to return PHY provider for sub node
      phy: core: Let node ptr of PHY point to PHY and not of PHY provider

Kumar Gala (2):
      phy: qcom: Add driver for QCOM IPQ806x SATA PHY
      phy: qcom: Add device tree bindings for IPQ806x SATA PHY

Lee Jones (4):
      phy: miphy365x: Add MiPHY365x header file for DT x Driver defines
      phy: miphy365x: Add Device Tree bindings for the MiPHY365x
      phy: miphy365x: Provide support for the MiPHY356x Generic PHY
      phy: miphy365x: Represent each PHY channel as a DT subnode

Marek Szyprowski (1):
      drivers: phy: exynos-usb2: add support for Exynos 3250

Roger Quadros (2):
      phy: core: Support regulator supply for PHY power
      phy: core: Add phy-supply to DT binding documentation

Sachin Kamat (5):
      phy: exynos-dp-video: Use PTR_ERR_OR_ZERO
      phy: exynos-mipi-video: Use PTR_ERR_OR_ZERO
      phy: sun4i-usb: Use PTR_ERR_OR_ZERO
      phy: Kconfig: Re-organize Exynos USB 2.0 PHY configs
      phy: Kconfig: Update config for Exynos USB DRD

Srinivas Kandagatla (3):
      phy: qcom: Add driver for QCOM APQ8064 SATA PHY
      phy: qcom: Add APQ8064 SATA PHY device tree bindings
      phy: qcom-apq8064: fix possible timeout without check

 .../devicetree/bindings/phy/berlin-sata-phy.txt    |   34 ++
 .../devicetree/bindings/phy/hix5hd2-phy.txt        |   22 +
 .../devicetree/bindings/phy/phy-bindings.txt       |    4 +
 .../devicetree/bindings/phy/phy-miphy365x.txt      |   76 +++
 .../bindings/phy/qcom-apq8064-sata-phy.txt         |   24 +
 .../bindings/phy/qcom-ipq806x-sata-phy.txt         |   23 +
 .../devicetree/bindings/phy/samsung-phy.txt        |    2 +
 Documentation/devicetree/bindings/phy/ti-phy.txt   |   23 +-
 Documentation/phy.txt                              |   10 +-
 drivers/phy/Kconfig                                |   78 ++-
 drivers/phy/Makefile                               |    5 +
 drivers/phy/phy-bcm-kona-usb2.c                    |    2 +-
 drivers/phy/phy-berlin-sata.c                      |  284 +++++++++
 drivers/phy/phy-core.c                             |   56 +-
 drivers/phy/phy-exynos-dp-video.c                  |    7 +-
 drivers/phy/phy-exynos-mipi-video.c                |    7 +-
 drivers/phy/phy-exynos4x12-usb2.c                  |  125 ++--
 drivers/phy/phy-exynos5-usbdrd.c                   |    9 +-
 drivers/phy/phy-exynos5250-sata.c                  |    2 +-
 drivers/phy/phy-exynos5250-usb2.c                  |    2 -
 drivers/phy/phy-hix5hd2-sata.c                     |  192 ++++++
 drivers/phy/phy-miphy365x.c                        |  636 ++++++++++++++++++++
 drivers/phy/phy-mvebu-sata.c                       |    2 +-
 drivers/phy/phy-omap-control.c                     |   52 +-
 drivers/phy/phy-omap-usb2.c                        |    2 +-
 drivers/phy/phy-qcom-apq8064-sata.c                |  289 +++++++++
 drivers/phy/phy-qcom-ipq806x-sata.c                |  211 +++++++
 drivers/phy/phy-samsung-usb2.c                     |    9 +-
 drivers/phy/phy-samsung-usb2.h                     |    5 +-
 drivers/phy/phy-sun4i-usb.c                        |    7 +-
 drivers/phy/phy-ti-pipe3.c                         |  107 +++-
 drivers/phy/phy-twl4030-usb.c                      |    2 +-
 drivers/phy/phy-xgene.c                            |    2 +-
 include/dt-bindings/phy/phy-miphy365x.h            |   14 +
 include/linux/phy/omap_control_phy.h               |   10 +
 include/linux/phy/phy.h                            |   17 +-
 36 files changed, 2218 insertions(+), 134 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
 create mode 100644 Documentation/devicetree/bindings/phy/hix5hd2-phy.txt
 create mode 100644 Documentation/devicetree/bindings/phy/phy-miphy365x.txt
 create mode 100644 Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt
 create mode 100644 Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt
 create mode 100644 drivers/phy/phy-berlin-sata.c
 create mode 100644 drivers/phy/phy-hix5hd2-sata.c
 create mode 100644 drivers/phy/phy-miphy365x.c
 create mode 100644 drivers/phy/phy-qcom-apq8064-sata.c
 create mode 100644 drivers/phy/phy-qcom-ipq806x-sata.c
 create mode 100644 include/dt-bindings/phy/phy-miphy365x.h

-- 
1.7.9.5


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

* [PATCH 01/28] phy: miphy365x: Add MiPHY365x header file for DT x Driver defines
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 02/28] phy: exynos-dp-video: Use PTR_ERR_OR_ZERO Kishon Vijay Abraham I
                   ` (27 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Lee Jones <lee.jones@linaro.org>

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

Cc: Kishon Vijay Abraham I <kishon@ti.com>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Alexandre Torgue <alexandre.torgue@st.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 include/dt-bindings/phy/phy-miphy365x.h |   14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 include/dt-bindings/phy/phy-miphy365x.h

diff --git a/include/dt-bindings/phy/phy-miphy365x.h b/include/dt-bindings/phy/phy-miphy365x.h
new file mode 100644
index 0000000..8ef8aba
--- /dev/null
+++ b/include/dt-bindings/phy/phy-miphy365x.h
@@ -0,0 +1,14 @@
+/*
+ * This header provides constants for the phy framework
+ * based on the STMicroelectronics MiPHY365x.
+ *
+ * Author: Lee Jones <lee.jones@linaro.org>
+ */
+#ifndef _DT_BINDINGS_PHY_MIPHY
+#define _DT_BINDINGS_PHY_MIPHY
+
+#define MIPHY_TYPE_SATA		1
+#define MIPHY_TYPE_PCIE		2
+#define MIPHY_TYPE_USB		3
+
+#endif /* _DT_BINDINGS_PHY_MIPHY */
-- 
1.7.9.5


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

* [PATCH 02/28] phy: exynos-dp-video: Use PTR_ERR_OR_ZERO
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 01/28] phy: miphy365x: Add MiPHY365x header file for DT x Driver defines Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 03/28] phy: exynos-mipi-video: " Kishon Vijay Abraham I
                   ` (26 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Sachin Kamat <sachin.kamat@linaro.org>

PTR_ERR_OR_ZERO simplifies the code.

Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Cc: Jingoo Han <jg1.han@samsung.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-exynos-dp-video.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c
index 0786fef..098f822 100644
--- a/drivers/phy/phy-exynos-dp-video.c
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -84,10 +85,8 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
 	phy_set_drvdata(phy, state);
 
 	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 exynos_dp_video_phy_of_match[] = {
-- 
1.7.9.5


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

* [PATCH 03/28] phy: exynos-mipi-video: Use PTR_ERR_OR_ZERO
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 01/28] phy: miphy365x: Add MiPHY365x header file for DT x Driver defines Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 02/28] phy: exynos-dp-video: Use PTR_ERR_OR_ZERO Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 04/28] phy: sun4i-usb: " Kishon Vijay Abraham I
                   ` (25 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Sachin Kamat <sachin.kamat@linaro.org>

PTR_ERR_OR_ZERO simplifies the code.

Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-exynos-mipi-video.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index ff02668..6d6bcf5 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -9,6 +9,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -149,10 +150,8 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
 
 	phy_provider = devm_of_phy_provider_register(dev,
 					exynos_mipi_video_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 exynos_mipi_video_phy_of_match[] = {
-- 
1.7.9.5


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

* [PATCH 04/28] phy: sun4i-usb: Use PTR_ERR_OR_ZERO
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (2 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 03/28] phy: exynos-mipi-video: " Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 05/28] phy: exynos5-usbdrd: Make local functions static Kishon Vijay Abraham I
                   ` (24 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Sachin Kamat <sachin.kamat@linaro.org>

PTR_ERR_OR_ZERO simplifies the code.

Signed-off-by: Sachin Kamat <sachin.kamat@linaro.org>
Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-sun4i-usb.c |    5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 115d8d5..7a4ea55 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -22,6 +22,7 @@
  */
 
 #include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -306,10 +307,8 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 
 	dev_set_drvdata(dev, data);
 	phy_provider = devm_of_phy_provider_register(dev, sun4i_usb_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 sun4i_usb_phy_of_match[] = {
-- 
1.7.9.5


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

* [PATCH 05/28] phy: exynos5-usbdrd: Make local functions static
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (3 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 04/28] phy: sun4i-usb: " Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 06/28] phy: phy-samsung-usb2: Change phy power on/power off sequence Kishon Vijay Abraham I
                   ` (23 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Jingoo Han <jg1.han@samsung.com>

Make local functions static, because these are used only in this
file.

Signed-off-by: Jingoo Han <jg1.han@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-exynos5-usbdrd.c |    6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index 76d862b..205159d 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -506,7 +506,7 @@ static struct phy_ops exynos5_usbdrd_phy_ops = {
 	.owner		= THIS_MODULE,
 };
 
-const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
+static const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
 	{
 		.id		= EXYNOS5_DRDPHY_UTMI,
 		.phy_isol	= exynos5_usbdrd_phy_isol,
@@ -521,13 +521,13 @@ const struct exynos5_usbdrd_phy_config phy_cfg_exynos5[] = {
 	},
 };
 
-const struct exynos5_usbdrd_phy_drvdata exynos5420_usbdrd_phy = {
+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,
 };
 
-const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
+static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
 	.phy_cfg		= phy_cfg_exynos5,
 	.pmu_offset_usbdrd0_phy	= EXYNOS5_USBDRD_PHY_CONTROL,
 };
-- 
1.7.9.5


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

* [PATCH 06/28] phy: phy-samsung-usb2: Change phy power on/power off sequence
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (4 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 05/28] phy: exynos5-usbdrd: Make local functions static Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 07/28] phy: phy-omap-pipe3: Add support for PCIe PHY Kishon Vijay Abraham I
                   ` (22 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Kamil Debski <k.debski@samsung.com>

The Exynos4412 USB 2.0 PHY hardware differs from the description provided
in the documentation. Some register bits have different function. This
patch fixes the defines of register bits and changes the way how phys are
powered on and off.

Signed-off-by: Kamil Debski <k.debski@samsung.com>
Tested-by: Daniel Drake <drake@endlessm.com>
Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-exynos4x12-usb2.c |  112 +++++++++++++++++++++++++------------
 drivers/phy/phy-exynos5250-usb2.c |    2 -
 drivers/phy/phy-samsung-usb2.h    |    3 +-
 3 files changed, 77 insertions(+), 40 deletions(-)

diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c
index d92a7cc..63134d8 100644
--- a/drivers/phy/phy-exynos4x12-usb2.c
+++ b/drivers/phy/phy-exynos4x12-usb2.c
@@ -86,13 +86,23 @@
 #define EXYNOS_4x12_URSTCON_OTG_HLINK		BIT(1)
 #define EXYNOS_4x12_URSTCON_OTG_PHYLINK		BIT(2)
 #define EXYNOS_4x12_URSTCON_HOST_PHY		BIT(3)
+/* The following bit defines are presented in the
+ * order taken from the Exynos4412 reference manual.
+ *
+ * During experiments with the hardware and debugging
+ * it was determined that the hardware behaves contrary
+ * to the manual.
+ *
+ * The following bit values were chaned accordingly to the
+ * results of real hardware experiments.
+ */
 #define EXYNOS_4x12_URSTCON_PHY1		BIT(4)
-#define EXYNOS_4x12_URSTCON_HSIC0		BIT(5)
-#define EXYNOS_4x12_URSTCON_HSIC1		BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC0		BIT(6)
+#define EXYNOS_4x12_URSTCON_HSIC1		BIT(5)
 #define EXYNOS_4x12_URSTCON_HOST_LINK_ALL	BIT(7)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P0	BIT(8)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P0	BIT(10)
 #define EXYNOS_4x12_URSTCON_HOST_LINK_P1	BIT(9)
-#define EXYNOS_4x12_URSTCON_HOST_LINK_P2	BIT(10)
+#define EXYNOS_4x12_URSTCON_HOST_LINK_P2	BIT(8)
 
 /* Isolation, configured in the power management unit */
 #define EXYNOS_4x12_USB_ISOL_OFFSET		0x704
@@ -188,6 +198,7 @@ static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
 	clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
 	clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
 	clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
+	clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
 	writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
 }
 
@@ -198,27 +209,22 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
 	u32 phypwr = 0;
 	u32 rst;
 	u32 pwr;
-	u32 mode = 0;
-	u32 switch_mode = 0;
 
 	switch (inst->cfg->id) {
 	case EXYNOS4x12_DEVICE:
 		phypwr =	EXYNOS_4x12_UPHYPWR_PHY0;
 		rstbits =	EXYNOS_4x12_URSTCON_PHY0;
-		mode =		EXYNOS_4x12_MODE_SWITCH_DEVICE;
-		switch_mode =	1;
 		break;
 	case EXYNOS4x12_HOST:
 		phypwr =	EXYNOS_4x12_UPHYPWR_PHY1;
-		rstbits =	EXYNOS_4x12_URSTCON_HOST_PHY;
-		mode =		EXYNOS_4x12_MODE_SWITCH_HOST;
-		switch_mode =	1;
+		rstbits =	EXYNOS_4x12_URSTCON_HOST_PHY |
+				EXYNOS_4x12_URSTCON_PHY1 |
+				EXYNOS_4x12_URSTCON_HOST_LINK_P0;
 		break;
 	case EXYNOS4x12_HSIC0:
 		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC0;
-		rstbits =	EXYNOS_4x12_URSTCON_HSIC1 |
-				EXYNOS_4x12_URSTCON_HOST_LINK_P0 |
-				EXYNOS_4x12_URSTCON_HOST_PHY;
+		rstbits =	EXYNOS_4x12_URSTCON_HSIC0 |
+				EXYNOS_4x12_URSTCON_HOST_LINK_P1;
 		break;
 	case EXYNOS4x12_HSIC1:
 		phypwr =	EXYNOS_4x12_UPHYPWR_HSIC1;
@@ -228,11 +234,6 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
 	};
 
 	if (on) {
-		if (switch_mode)
-			regmap_update_bits(drv->reg_sys,
-					   EXYNOS_4x12_MODE_SWITCH_OFFSET,
-					   EXYNOS_4x12_MODE_SWITCH_MASK, mode);
-
 		pwr = readl(drv->reg_phy + EXYNOS_4x12_UPHYPWR);
 		pwr &= ~phypwr;
 		writel(pwr, drv->reg_phy + EXYNOS_4x12_UPHYPWR);
@@ -253,41 +254,78 @@ static void exynos4x12_phy_pwr(struct samsung_usb2_phy_instance *inst, bool on)
 	}
 }
 
-static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+static void exynos4x12_power_on_int(struct samsung_usb2_phy_instance *inst)
 {
-	struct samsung_usb2_phy_driver *drv = inst->drv;
+	if (inst->int_cnt++ > 0)
+		return;
 
-	inst->enabled = 1;
 	exynos4x12_setup_clk(inst);
-	exynos4x12_phy_pwr(inst, 1);
 	exynos4x12_isol(inst, 0);
+	exynos4x12_phy_pwr(inst, 1);
+}
+
+static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
+{
+	struct samsung_usb2_phy_driver *drv = inst->drv;
+
+	if (inst->ext_cnt++ > 0)
+		return 0;
 
-	/* Power on the device, as it is necessary for HSIC to work */
-	if (inst->cfg->id == EXYNOS4x12_HSIC0) {
-		struct samsung_usb2_phy_instance *device =
-					&drv->instances[EXYNOS4x12_DEVICE];
-		exynos4x12_phy_pwr(device, 1);
-		exynos4x12_isol(device, 0);
+	if (inst->cfg->id == EXYNOS4x12_HOST) {
+		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+						EXYNOS_4x12_MODE_SWITCH_MASK,
+						EXYNOS_4x12_MODE_SWITCH_HOST);
+		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
 	}
 
+	if (inst->cfg->id == EXYNOS4x12_DEVICE)
+		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+						EXYNOS_4x12_MODE_SWITCH_MASK,
+						EXYNOS_4x12_MODE_SWITCH_DEVICE);
+
+	if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+		inst->cfg->id == EXYNOS4x12_HSIC1) {
+		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
+		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_HOST]);
+	}
+
+	exynos4x12_power_on_int(inst);
+
 	return 0;
 }
 
-static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+static void exynos4x12_power_off_int(struct samsung_usb2_phy_instance *inst)
 {
-	struct samsung_usb2_phy_driver *drv = inst->drv;
-	struct samsung_usb2_phy_instance *device =
-					&drv->instances[EXYNOS4x12_DEVICE];
+	if (inst->int_cnt-- > 1)
+		return;
 
-	inst->enabled = 0;
 	exynos4x12_isol(inst, 1);
 	exynos4x12_phy_pwr(inst, 0);
+}
 
-	if (inst->cfg->id == EXYNOS4x12_HSIC0 && !device->enabled) {
-		exynos4x12_isol(device, 1);
-		exynos4x12_phy_pwr(device, 0);
+static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
+{
+	struct samsung_usb2_phy_driver *drv = inst->drv;
+
+	if (inst->ext_cnt-- > 1)
+		return 0;
+
+	if (inst->cfg->id == EXYNOS4x12_DEVICE)
+		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
+						EXYNOS_4x12_MODE_SWITCH_MASK,
+						EXYNOS_4x12_MODE_SWITCH_HOST);
+
+	if (inst->cfg->id == EXYNOS4x12_HOST)
+		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
+
+	if (inst->cfg->id == EXYNOS4x12_HSIC0 ||
+		inst->cfg->id == EXYNOS4x12_HSIC1) {
+		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_DEVICE]);
+		exynos4x12_power_off_int(&drv->instances[EXYNOS4x12_HOST]);
 	}
 
+	exynos4x12_power_off_int(inst);
+
 	return 0;
 }
 
diff --git a/drivers/phy/phy-exynos5250-usb2.c b/drivers/phy/phy-exynos5250-usb2.c
index 94179af..1c139aa 100644
--- a/drivers/phy/phy-exynos5250-usb2.c
+++ b/drivers/phy/phy-exynos5250-usb2.c
@@ -318,7 +318,6 @@ static int exynos5250_power_on(struct samsung_usb2_phy_instance *inst)
 
 		break;
 	}
-	inst->enabled = 1;
 	exynos5250_isol(inst, 0);
 
 	return 0;
@@ -331,7 +330,6 @@ static int exynos5250_power_off(struct samsung_usb2_phy_instance *inst)
 	u32 otg;
 	u32 hsic;
 
-	inst->enabled = 0;
 	exynos5250_isol(inst, 1);
 
 	switch (inst->cfg->id) {
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 45b3170..9188478 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -29,7 +29,8 @@ struct samsung_usb2_phy_instance {
 	const struct samsung_usb2_common_phy *cfg;
 	struct phy *phy;
 	struct samsung_usb2_phy_driver *drv;
-	bool enabled;
+	int int_cnt;
+	int ext_cnt;
 };
 
 struct samsung_usb2_phy_driver {
-- 
1.7.9.5


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

* [PATCH 07/28] phy: phy-omap-pipe3: Add support for PCIe PHY
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (5 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 06/28] phy: phy-samsung-usb2: Change phy power on/power off sequence Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 08/28] phy: pipe3: insert delay to enumerate in GEN2 mode Kishon Vijay Abraham I
                   ` (21 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

PCIe PHY uses an external pll instead of the internal pll used by SATA
and USB3. So added support in pipe3 PHY to use external pll.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Reviewed-by: Roger Quadros <rogerq@ti.com>
---
 Documentation/devicetree/bindings/phy/ti-phy.txt |   11 ++-
 drivers/phy/phy-ti-pipe3.c                       |  103 +++++++++++++++++-----
 2 files changed, 91 insertions(+), 23 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
index 9ce458f..b50e1c1 100644
--- a/Documentation/devicetree/bindings/phy/ti-phy.txt
+++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
@@ -56,8 +56,8 @@ usb2phy@4a0ad080 {
 TI PIPE3 PHY
 
 Required properties:
- - compatible: Should be "ti,phy-usb3" or "ti,phy-pipe3-sata".
-   "ti,omap-usb3" is deprecated.
+ - compatible: Should be "ti,phy-usb3", "ti,phy-pipe3-sata" or
+   "ti,phy-pipe3-pcie. "ti,omap-usb3" is deprecated.
  - 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".
@@ -69,10 +69,17 @@ Required properties:
    * "wkupclk" - wakeup clock.
    * "sysclk" - system clock.
    * "refclk" - reference clock.
+   * "dpll_ref" - external dpll ref clk
+   * "dpll_ref_m2" - external dpll ref clk
+   * "phy-div" - divider for apll
+   * "div-clk" - apll clock
 
 Optional properties:
  - ctrl-module : phandle of the control module used by PHY driver to power on
    the PHY.
+ - id: If there are multiple instance of the same type, in order to
+   differentiate between each instance "id" can be used (e.g., multi-lane PCIe
+   PHY). If "id" is not provided, it is set to default value of '1'.
 
 This is usually a subnode of ocp2scp to which it is connected.
 
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 5913676..6174f4b 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -80,7 +80,9 @@ struct ti_pipe3 {
 	struct clk		*wkupclk;
 	struct clk		*sys_clk;
 	struct clk		*refclk;
+	struct clk		*div_clk;
 	struct pipe3_dpll_map	*dpll_map;
+	u8			id;
 };
 
 static struct pipe3_dpll_map dpll_map_usb[] = {
@@ -215,6 +217,9 @@ static int ti_pipe3_init(struct phy *x)
 	u32 val;
 	int ret = 0;
 
+	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
+		return 0;
+
 	/* Bring it out of IDLE if it is IDLE */
 	val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
 	if (val & PLL_IDLE) {
@@ -238,8 +243,11 @@ static int ti_pipe3_exit(struct phy *x)
 	u32 val;
 	unsigned long timeout;
 
-	/* SATA DPLL can't be powered down due to Errata i783 */
-	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
+	/* SATA DPLL can't be powered down due to Errata i783 and PCIe
+	 * does not have internal DPLL
+	 */
+	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata") ||
+	    of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
 		return 0;
 
 	/* Put DPLL in IDLE mode */
@@ -286,32 +294,41 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 	struct device_node *control_node;
 	struct platform_device *control_pdev;
 	const struct of_device_id *match;
-
-	match = of_match_device(of_match_ptr(ti_pipe3_id_table), &pdev->dev);
-	if (!match)
-		return -EINVAL;
+	struct clk *clk;
 
 	phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
 	if (!phy) {
 		dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n");
 		return -ENOMEM;
 	}
+	phy->dev		= &pdev->dev;
 
-	phy->dpll_map = (struct pipe3_dpll_map *)match->data;
-	if (!phy->dpll_map) {
-		dev_err(&pdev->dev, "no DPLL data\n");
-		return -EINVAL;
-	}
+	if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+		match = of_match_device(of_match_ptr(ti_pipe3_id_table),
+					&pdev->dev);
+		if (!match)
+			return -EINVAL;
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
-	phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
-	if (IS_ERR(phy->pll_ctrl_base))
-		return PTR_ERR(phy->pll_ctrl_base);
+		phy->dpll_map = (struct pipe3_dpll_map *)match->data;
+		if (!phy->dpll_map) {
+			dev_err(&pdev->dev, "no DPLL data\n");
+			return -EINVAL;
+		}
 
-	phy->dev		= &pdev->dev;
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   "pll_ctrl");
+		phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(phy->pll_ctrl_base))
+			return PTR_ERR(phy->pll_ctrl_base);
 
-	if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
+		phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
+		if (IS_ERR(phy->sys_clk)) {
+			dev_err(&pdev->dev, "unable to get sysclk\n");
+			return -EINVAL;
+		}
+	}
 
+	if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
 		phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
 		if (IS_ERR(phy->wkupclk)) {
 			dev_err(&pdev->dev, "unable to get wkupclk\n");
@@ -328,10 +345,38 @@ static int ti_pipe3_probe(struct platform_device *pdev)
 		phy->refclk = ERR_PTR(-ENODEV);
 	}
 
-	phy->sys_clk = devm_clk_get(phy->dev, "sysclk");
-	if (IS_ERR(phy->sys_clk)) {
-		dev_err(&pdev->dev, "unable to get sysclk\n");
-		return -EINVAL;
+	if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
+		if (of_property_read_u8(node, "id", &phy->id) < 0)
+			phy->id = 1;
+
+		clk = devm_clk_get(phy->dev, "dpll_ref");
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "unable to get dpll ref clk\n");
+			return PTR_ERR(clk);
+		}
+		clk_set_rate(clk, 1500000000);
+
+		clk = devm_clk_get(phy->dev, "dpll_ref_m2");
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "unable to get dpll ref m2 clk\n");
+			return PTR_ERR(clk);
+		}
+		clk_set_rate(clk, 100000000);
+
+		clk = devm_clk_get(phy->dev, "phy-div");
+		if (IS_ERR(clk)) {
+			dev_err(&pdev->dev, "unable to get phy-div clk\n");
+			return PTR_ERR(clk);
+		}
+		clk_set_rate(clk, 100000000);
+
+		phy->div_clk = devm_clk_get(phy->dev, "div-clk");
+		if (IS_ERR(phy->div_clk)) {
+			dev_err(&pdev->dev, "unable to get div-clk\n");
+			return PTR_ERR(phy->div_clk);
+		}
+	} else {
+		phy->div_clk = ERR_PTR(-ENODEV);
 	}
 
 	control_node = of_parse_phandle(node, "ctrl-module", 0);
@@ -387,6 +432,8 @@ static int ti_pipe3_runtime_suspend(struct device *dev)
 		clk_disable_unprepare(phy->wkupclk);
 	if (!IS_ERR(phy->refclk))
 		clk_disable_unprepare(phy->refclk);
+	if (!IS_ERR(phy->div_clk))
+		clk_disable_unprepare(phy->div_clk);
 
 	return 0;
 }
@@ -412,8 +459,19 @@ static int ti_pipe3_runtime_resume(struct device *dev)
 		}
 	}
 
+	if (!IS_ERR(phy->div_clk)) {
+		ret = clk_prepare_enable(phy->div_clk);
+		if (ret) {
+			dev_err(phy->dev, "Failed to enable div_clk %d\n", ret);
+			goto err3;
+		}
+	}
 	return 0;
 
+err3:
+	if (!IS_ERR(phy->wkupclk))
+		clk_disable_unprepare(phy->wkupclk);
+
 err2:
 	if (!IS_ERR(phy->refclk))
 		clk_disable_unprepare(phy->refclk);
@@ -446,6 +504,9 @@ static const struct of_device_id ti_pipe3_id_table[] = {
 		.compatible = "ti,phy-pipe3-sata",
 		.data = dpll_map_sata,
 	},
+	{
+		.compatible = "ti,phy-pipe3-pcie",
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
-- 
1.7.9.5


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

* [PATCH 08/28] phy: pipe3: insert delay to enumerate in GEN2 mode
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (6 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 07/28] phy: phy-omap-pipe3: Add support for PCIe PHY Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 09/28] Documentation: Document Hisilicon hix5hd2 sata PHY Kishon Vijay Abraham I
                   ` (20 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

8-bit delay value (0xF1) is required for GEN2 devices to be enumerated
consistently. Added an API to be called from PHY drivers to set this delay
value and called it from PIPE3 driver to set the delay value.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Reviewed-by: Roger Quadros <rogerq@ti.com>
---
 Documentation/devicetree/bindings/phy/ti-phy.txt |   12 ++---
 drivers/phy/phy-omap-control.c                   |   52 +++++++++++++++++++++-
 drivers/phy/phy-ti-pipe3.c                       |    4 +-
 include/linux/phy/omap_control_phy.h             |   10 +++++
 4 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/ti-phy.txt b/Documentation/devicetree/bindings/phy/ti-phy.txt
index b50e1c1..305e3df 100644
--- a/Documentation/devicetree/bindings/phy/ti-phy.txt
+++ b/Documentation/devicetree/bindings/phy/ti-phy.txt
@@ -9,15 +9,17 @@ Required properties:
                         e.g. USB2_PHY on OMAP5.
  "ti,control-phy-pipe3" - if it has DPLL and individual Rx & Tx power control
                         e.g. USB3 PHY and SATA PHY on OMAP5.
+ "ti,control-phy-pcie" - for pcie to support external clock for pcie and to
+			set PCS delay value.
+			e.g. PCIE PHY in DRA7x
  "ti,control-phy-usb2-dra7" - if it has power down register like USB2 PHY on
                         DRA7 platform.
  "ti,control-phy-usb2-am437" - if it has power down register like USB2 PHY on
                         AM437 platform.
- - reg : Address and length of the register set for the device. It contains
-   the address of "otghs_control" for control-phy-otghs or "power" register
-   for other types.
- - reg-names: should be "otghs_control" control-phy-otghs and "power" for
-   other types.
+ - reg : register ranges as listed in the reg-names property
+ - reg-names: "otghs_control" for control-phy-otghs
+	      "power", "pcie_pcs" and "control_sma" for control-phy-pcie
+	      "power" for all other types
 
 omap_control_usb: omap-control-usb@4a002300 {
         compatible = "ti,control-phy-otghs";
diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
index 311b4f9..9487bf1 100644
--- a/drivers/phy/phy-omap-control.c
+++ b/drivers/phy/phy-omap-control.c
@@ -27,6 +27,41 @@
 #include <linux/phy/omap_control_phy.h>
 
 /**
+ * omap_control_pcie_pcs - set the PCS delay count
+ * @dev: the control module device
+ * @id: index of the pcie PHY (should be 1 or 2)
+ * @delay: 8 bit delay value
+ */
+void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay)
+{
+	u32 val;
+	struct omap_control_phy	*control_phy;
+
+	if (IS_ERR(dev) || !dev) {
+		pr_err("%s: invalid device\n", __func__);
+		return;
+	}
+
+	control_phy = dev_get_drvdata(dev);
+	if (!control_phy) {
+		dev_err(dev, "%s: invalid control phy device\n", __func__);
+		return;
+	}
+
+	if (control_phy->type != OMAP_CTRL_TYPE_PCIE) {
+		dev_err(dev, "%s: unsupported operation\n", __func__);
+		return;
+	}
+
+	val = readl(control_phy->pcie_pcs);
+	val &= ~(OMAP_CTRL_PCIE_PCS_MASK <<
+		(id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT));
+	val |= delay << (id * OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT);
+	writel(val, control_phy->pcie_pcs);
+}
+EXPORT_SYMBOL_GPL(omap_control_pcie_pcs);
+
+/**
  * omap_control_phy_power - power on/off the phy using control module reg
  * @dev: the control module device
  * @on: 0 or 1, based on powering on or off the PHY
@@ -61,6 +96,7 @@ void omap_control_phy_power(struct device *dev, int on)
 			val |= OMAP_CTRL_DEV_PHY_PD;
 		break;
 
+	case OMAP_CTRL_TYPE_PCIE:
 	case OMAP_CTRL_TYPE_PIPE3:
 		rate = clk_get_rate(control_phy->sys_clk);
 		rate = rate/1000000;
@@ -211,6 +247,7 @@ EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
 static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
 static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
 static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
+static const enum omap_control_phy_type pcie_data = OMAP_CTRL_TYPE_PCIE;
 static const enum omap_control_phy_type dra7usb2_data = OMAP_CTRL_TYPE_DRA7USB2;
 static const enum omap_control_phy_type am437usb2_data = OMAP_CTRL_TYPE_AM437USB2;
 
@@ -228,6 +265,10 @@ static const struct of_device_id omap_control_phy_id_table[] = {
 		.data = &pipe3_data,
 	},
 	{
+		.compatible = "ti,control-phy-pcie",
+		.data = &pcie_data,
+	},
+	{
 		.compatible = "ti,control-phy-usb2-dra7",
 		.data = &dra7usb2_data,
 	},
@@ -279,7 +320,8 @@ static int omap_control_phy_probe(struct platform_device *pdev)
 		}
 	}
 
-	if (control_phy->type == OMAP_CTRL_TYPE_PIPE3) {
+	if (control_phy->type == OMAP_CTRL_TYPE_PIPE3 ||
+	    control_phy->type == OMAP_CTRL_TYPE_PCIE) {
 		control_phy->sys_clk = devm_clk_get(control_phy->dev,
 			"sys_clkin");
 		if (IS_ERR(control_phy->sys_clk)) {
@@ -288,6 +330,14 @@ static int omap_control_phy_probe(struct platform_device *pdev)
 		}
 	}
 
+	if (control_phy->type == OMAP_CTRL_TYPE_PCIE) {
+		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+						   "pcie_pcs");
+		control_phy->pcie_pcs = devm_ioremap_resource(&pdev->dev, res);
+		if (IS_ERR(control_phy->pcie_pcs))
+			return PTR_ERR(control_phy->pcie_pcs);
+	}
+
 	dev_set_drvdata(control_phy->dev, control_phy);
 
 	return 0;
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 6174f4b..93bcd67 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -217,8 +217,10 @@ static int ti_pipe3_init(struct phy *x)
 	u32 val;
 	int ret = 0;
 
-	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie"))
+	if (of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-pcie")) {
+		omap_control_pcie_pcs(phy->control_dev, phy->id, 0xF1);
 		return 0;
+	}
 
 	/* Bring it out of IDLE if it is IDLE */
 	val = ti_pipe3_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
diff --git a/include/linux/phy/omap_control_phy.h b/include/linux/phy/omap_control_phy.h
index 5450403..e9e6cfb 100644
--- a/include/linux/phy/omap_control_phy.h
+++ b/include/linux/phy/omap_control_phy.h
@@ -23,6 +23,7 @@ enum omap_control_phy_type {
 	OMAP_CTRL_TYPE_OTGHS = 1,	/* Mailbox OTGHS_CONTROL */
 	OMAP_CTRL_TYPE_USB2,	/* USB2_PHY, power down in CONTROL_DEV_CONF */
 	OMAP_CTRL_TYPE_PIPE3,	/* PIPE3 PHY, DPLL & seperate Rx/Tx power */
+	OMAP_CTRL_TYPE_PCIE,	/* RX TX control of ACSPCIE */
 	OMAP_CTRL_TYPE_DRA7USB2, /* USB2 PHY, power and power_aux e.g. DRA7 */
 	OMAP_CTRL_TYPE_AM437USB2, /* USB2 PHY, power e.g. AM437x */
 };
@@ -33,6 +34,7 @@ struct omap_control_phy {
 	u32 __iomem *otghs_control;
 	u32 __iomem *power;
 	u32 __iomem *power_aux;
+	u32 __iomem *pcie_pcs;
 
 	struct clk *sys_clk;
 
@@ -63,6 +65,9 @@ enum omap_control_usb_mode {
 #define	OMAP_CTRL_PIPE3_PHY_TX_RX_POWERON	0x3
 #define	OMAP_CTRL_PIPE3_PHY_TX_RX_POWEROFF	0x0
 
+#define	OMAP_CTRL_PCIE_PCS_MASK			0xff
+#define	OMAP_CTRL_PCIE_PCS_DELAY_COUNT_SHIFT	0x8
+
 #define OMAP_CTRL_USB2_PHY_PD		BIT(28)
 
 #define AM437X_CTRL_USB2_PHY_PD		BIT(0)
@@ -74,6 +79,7 @@ enum omap_control_usb_mode {
 void omap_control_phy_power(struct device *dev, int on);
 void omap_control_usb_set_mode(struct device *dev,
 			       enum omap_control_usb_mode mode);
+void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay);
 #else
 
 static inline void omap_control_phy_power(struct device *dev, int on)
@@ -84,6 +90,10 @@ static inline void omap_control_usb_set_mode(struct device *dev,
 	enum omap_control_usb_mode mode)
 {
 }
+
+static inline void omap_control_pcie_pcs(struct device *dev, u8 id, u8 delay)
+{
+}
 #endif
 
 #endif	/* __OMAP_CONTROL_PHY_H__ */
-- 
1.7.9.5


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

* [PATCH 09/28] Documentation: Document Hisilicon hix5hd2 sata PHY
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (7 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 08/28] phy: pipe3: insert delay to enumerate in GEN2 mode Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 10/28] phy: add hix5hd2-sata-phy driver Kishon Vijay Abraham I
                   ` (19 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Jiancheng Xue <xuejiancheng@huawei.com>

Add necessary binding documentation SATA PHY on Hisilicon hix5hd2 soc.

Signed-off-by: Jiancheng Xue <xuejiancheng@huawei.com>
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/hix5hd2-phy.txt        |   22 ++++++++++++++++++++
 1 file changed, 22 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/hix5hd2-phy.txt

diff --git a/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt b/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt
new file mode 100644
index 0000000..296168b
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/hix5hd2-phy.txt
@@ -0,0 +1,22 @@
+Hisilicon hix5hd2 SATA PHY
+-----------------------
+
+Required properties:
+- compatible: should be "hisilicon,hix5hd2-sata-phy"
+- reg: offset and length of the PHY registers
+- #phy-cells: must be 0
+Refer to phy/phy-bindings.txt for the generic PHY binding properties
+
+Optional Properties:
+- hisilicon,peripheral-syscon: phandle of syscon used to control peripheral.
+- hisilicon,power-reg: offset and bit number within peripheral-syscon,
+	register of controlling sata power supply.
+
+Example:
+	sata_phy: phy@f9900000 {
+		compatible = "hisilicon,hix5hd2-sata-phy";
+		reg = <0xf9900000 0x10000>;
+		#phy-cells = <0>;
+		hisilicon,peripheral-syscon = <&peripheral_ctrl>;
+		hisilicon,power-reg = <0x8 10>;
+	};
-- 
1.7.9.5


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

* [PATCH 10/28] phy: add hix5hd2-sata-phy driver
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (8 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 09/28] Documentation: Document Hisilicon hix5hd2 sata PHY Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-24 11:27   ` Paul Bolle
  2014-07-22 10:56 ` [PATCH 11/28] drivers: phy: exynos-usb2: add support for Exynos 3250 Kishon Vijay Abraham I
                   ` (18 subsequent siblings)
  28 siblings, 1 reply; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Jiancheng Xue <xuejiancheng@huawei.com>

Add hix5hd2-sata-phy driver on Hisilicon hix5hd2 soc.

Signed-off-by: Jiancheng Xue <xuejiancheng@huawei.com>
Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig            |    8 ++
 drivers/phy/Makefile           |    1 +
 drivers/phy/phy-hix5hd2-sata.c |  192 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 201 insertions(+)
 create mode 100644 drivers/phy/phy-hix5hd2-sata.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 64b98d2..30c82fc 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -109,6 +109,14 @@ config PHY_EXYNOS5250_SATA
 	  SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
 	  port to accept one SATA device.
 
+config PHY_HIX5HD2_SATA
+	tristate "HIX5HD2 SATA PHY Driver"
+	depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
+	select GENERIC_PHY
+	select MFD_SYSCON
+	help
+	  Support for SATA PHY on Hisilicon hix5hd2 Soc.
+
 config PHY_SUN4I_USB
 	tristate "Allwinner sunxi SoC USB PHY driver"
 	depends on ARCH_SUNXI && HAS_IOMEM && OF
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index b4f1d57..54f04d0 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
 obj-$(CONFIG_TI_PIPE3)			+= phy-ti-pipe3.o
 obj-$(CONFIG_TWL4030_USB)		+= phy-twl4030-usb.o
 obj-$(CONFIG_PHY_EXYNOS5250_SATA)	+= phy-exynos5250-sata.o
+obj-$(CONFIG_PHY_HIX5HD2_SATA)		+= phy-hix5hd2-sata.o
 obj-$(CONFIG_PHY_SUN4I_USB)		+= phy-sun4i-usb.o
 obj-$(CONFIG_PHY_SAMSUNG_USB2)		+= phy-exynos-usb2.o
 phy-exynos-usb2-y			+= phy-samsung-usb2.o
diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c
new file mode 100644
index 0000000..d442834
--- /dev/null
+++ b/drivers/phy/phy-hix5hd2-sata.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2014 Linaro Ltd.
+ * Copyright (c) 2014 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#define SATA_PHY0_CTLL		0xa0
+#define MPLL_MULTIPLIER_SHIFT	1
+#define MPLL_MULTIPLIER_MASK	0xfe
+#define MPLL_MULTIPLIER_50M	0x3c
+#define MPLL_MULTIPLIER_100M	0x1e
+#define PHY_RESET		BIT(0)
+#define REF_SSP_EN		BIT(9)
+#define SSC_EN			BIT(10)
+#define REF_USE_PAD		BIT(23)
+
+#define SATA_PORT_PHYCTL	0x174
+#define SPEED_MODE_MASK		0x6f0000
+#define HALF_RATE_SHIFT		16
+#define PHY_CONFIG_SHIFT	18
+#define GEN2_EN_SHIFT		21
+#define SPEED_CTRL		BIT(20)
+
+#define SATA_PORT_PHYCTL1	0x148
+#define AMPLITUDE_MASK		0x3ffffe
+#define AMPLITUDE_GEN3		0x68
+#define AMPLITUDE_GEN3_SHIFT	15
+#define AMPLITUDE_GEN2		0x56
+#define AMPLITUDE_GEN2_SHIFT	8
+#define AMPLITUDE_GEN1		0x56
+#define AMPLITUDE_GEN1_SHIFT	1
+
+#define SATA_PORT_PHYCTL2	0x14c
+#define PREEMPH_MASK		0x3ffff
+#define PREEMPH_GEN3		0x20
+#define PREEMPH_GEN3_SHIFT	12
+#define PREEMPH_GEN2		0x15
+#define PREEMPH_GEN2_SHIFT	6
+#define PREEMPH_GEN1		0x5
+#define PREEMPH_GEN1_SHIFT	0
+
+struct hix5hd2_priv {
+	void __iomem	*base;
+	struct regmap	*peri_ctrl;
+};
+
+enum phy_speed_mode {
+	SPEED_MODE_GEN1 = 0,
+	SPEED_MODE_GEN2 = 1,
+	SPEED_MODE_GEN3 = 2,
+};
+
+static int hix5hd2_sata_phy_init(struct phy *phy)
+{
+	struct hix5hd2_priv *priv = phy_get_drvdata(phy);
+	u32 val, data[2];
+	int ret;
+
+	if (priv->peri_ctrl) {
+		ret = of_property_read_u32_array(phy->dev.of_node,
+						 "hisilicon,power-reg",
+						 &data[0], 2);
+		if (ret) {
+			dev_err(&phy->dev, "Fail read hisilicon,power-reg\n");
+			return ret;
+		}
+
+		regmap_update_bits(priv->peri_ctrl, data[0],
+				   BIT(data[1]), BIT(data[1]));
+	}
+
+	/* reset phy */
+	val = readl_relaxed(priv->base + SATA_PHY0_CTLL);
+	val &= ~(MPLL_MULTIPLIER_MASK | REF_USE_PAD);
+	val |= MPLL_MULTIPLIER_50M << MPLL_MULTIPLIER_SHIFT |
+	       REF_SSP_EN | PHY_RESET;
+	writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+	msleep(20);
+	val &= ~PHY_RESET;
+	writel_relaxed(val, priv->base + SATA_PHY0_CTLL);
+
+	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL1);
+	val &= ~AMPLITUDE_MASK;
+	val |= AMPLITUDE_GEN3 << AMPLITUDE_GEN3_SHIFT |
+	       AMPLITUDE_GEN2 << AMPLITUDE_GEN2_SHIFT |
+	       AMPLITUDE_GEN1 << AMPLITUDE_GEN1_SHIFT;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL1);
+
+	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL2);
+	val &= ~PREEMPH_MASK;
+	val |= PREEMPH_GEN3 << PREEMPH_GEN3_SHIFT |
+	       PREEMPH_GEN2 << PREEMPH_GEN2_SHIFT |
+	       PREEMPH_GEN1 << PREEMPH_GEN1_SHIFT;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL2);
+
+	/* ensure PHYCTRL setting takes effect */
+	val = readl_relaxed(priv->base + SATA_PORT_PHYCTL);
+	val &= ~SPEED_MODE_MASK;
+	val |= SPEED_MODE_GEN1 << HALF_RATE_SHIFT |
+	       SPEED_MODE_GEN1 << PHY_CONFIG_SHIFT |
+	       SPEED_MODE_GEN1 << GEN2_EN_SHIFT | SPEED_CTRL;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+	msleep(20);
+	val &= ~SPEED_MODE_MASK;
+	val |= SPEED_MODE_GEN3 << HALF_RATE_SHIFT |
+	       SPEED_MODE_GEN3 << PHY_CONFIG_SHIFT |
+	       SPEED_MODE_GEN3 << GEN2_EN_SHIFT | SPEED_CTRL;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+	val &= ~(SPEED_MODE_MASK | SPEED_CTRL);
+	val |= SPEED_MODE_GEN2 << HALF_RATE_SHIFT |
+	       SPEED_MODE_GEN2 << PHY_CONFIG_SHIFT |
+	       SPEED_MODE_GEN2 << GEN2_EN_SHIFT;
+	writel_relaxed(val, priv->base + SATA_PORT_PHYCTL);
+
+	return 0;
+}
+
+static struct phy_ops hix5hd2_sata_phy_ops = {
+	.init		= hix5hd2_sata_phy_init,
+	.owner		= THIS_MODULE,
+};
+
+static int hix5hd2_sata_phy_probe(struct platform_device *pdev)
+{
+	struct phy_provider *phy_provider;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy *phy;
+	struct hix5hd2_priv *priv;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->peri_ctrl = syscon_regmap_lookup_by_phandle(dev->of_node,
+					"hisilicon,peripheral-syscon");
+	if (IS_ERR(priv->peri_ctrl))
+		priv->peri_ctrl = NULL;
+
+	phy = devm_phy_create(dev, &hix5hd2_sata_phy_ops, NULL);
+	if (IS_ERR(phy)) {
+		dev_err(dev, "failed to create PHY\n");
+		return PTR_ERR(phy);
+	}
+
+	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;
+}
+
+static const struct of_device_id hix5hd2_sata_phy_of_match[] = {
+	{.compatible = "hisilicon,hix5hd2-sata-phy",},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, hix5hd2_sata_phy_of_match);
+
+static struct platform_driver hix5hd2_sata_phy_driver = {
+	.probe	= hix5hd2_sata_phy_probe,
+	.driver = {
+		.name	= "hix5hd2-sata-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= hix5hd2_sata_phy_of_match,
+	}
+};
+module_platform_driver(hix5hd2_sata_phy_driver);
+
+MODULE_AUTHOR("Jiancheng Xue <xuejiancheng@huawei.com>");
+MODULE_DESCRIPTION("HISILICON HIX5HD2 SATA PHY driver");
+MODULE_ALIAS("platform:hix5hd2-sata-phy");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5


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

* [PATCH 11/28] drivers: phy: exynos-usb2: add support for Exynos 3250
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (9 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 10/28] phy: add hix5hd2-sata-phy driver Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 12/28] phy: core: Support regulator supply for PHY power Kishon Vijay Abraham I
                   ` (17 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Marek Szyprowski <m.szyprowski@samsung.com>

This patch adds support for Exynos3250 SoC to Exynos2USB PHY driver.
Although Exynos3250 has only one device phy interface, the register
layout and all operations that are required to get it enabled are almost
same as on Exynos4x12. The only different is one more register
(REFCLKSEL) which need to be set and lack of MODE SWITCH register.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Reviewed-by: Tomasz Figa <t.figa@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/samsung-phy.txt        |    2 ++
 drivers/phy/Kconfig                                |   12 ++++++------
 drivers/phy/phy-exynos4x12-usb2.c                  |   17 +++++++++++++++--
 drivers/phy/phy-samsung-usb2.c                     |    6 ++++++
 drivers/phy/phy-samsung-usb2.h                     |    2 ++
 5 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index 2049261..6099a5c 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -26,6 +26,7 @@ Samsung S5P/EXYNOS SoC series USB PHY
 
 Required properties:
 - compatible : should be one of the listed compatibles:
+	- "samsung,exynos3250-usb2-phy"
 	- "samsung,exynos4210-usb2-phy"
 	- "samsung,exynos4x12-usb2-phy"
 	- "samsung,exynos5250-usb2-phy"
@@ -46,6 +47,7 @@ and Exynos 4212) it is as follows:
   1 - USB host ("host"),
   2 - HSIC0 ("hsic0"),
   3 - HSIC1 ("hsic1"),
+Exynos3250 has only USB device phy available as phy 0.
 
 Exynos 4210 and Exynos 4212 use mode switching and require that mode switch
 register is supplied.
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 30c82fc..7c49c4c 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -151,14 +151,14 @@ config PHY_EXYNOS4210_USB2
 	  phys are available - device, host, HSIC0 and HSIC1.
 
 config PHY_EXYNOS4X12_USB2
-	bool "Support for Exynos 4x12"
+	bool "Support for Exynos 3250/4x12"
 	depends on PHY_SAMSUNG_USB2
-	depends on (SOC_EXYNOS4212 || SOC_EXYNOS4412)
+	depends on (SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412)
 	help
-	  Enable USB PHY support for Exynos 4x12. This option requires that
-	  Samsung USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of Exynos 4x12 four
-	  phys are available - device, host, HSIC0 and HSIC1.
+	  Enable USB PHY support for Exynos 3250/4x12. This option requires
+	  that Samsung USB 2.0 PHY driver is enabled and means that support for
+	  this particular SoC is compiled in the driver. In case of Exynos 4x12
+	  four phys are available - device, host, HSIC0 and HSIC1.
 
 config PHY_EXYNOS5250_USB2
 	bool "Support for Exynos 5250"
diff --git a/drivers/phy/phy-exynos4x12-usb2.c b/drivers/phy/phy-exynos4x12-usb2.c
index 63134d8..0b9de88 100644
--- a/drivers/phy/phy-exynos4x12-usb2.c
+++ b/drivers/phy/phy-exynos4x12-usb2.c
@@ -67,6 +67,8 @@
 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_24MHZ	(0x5 << 0)
 #define EXYNOS_4x12_UPHYCLK_PHYFSEL_50MHZ	(0x7 << 0)
 
+#define EXYNOS_3250_UPHYCLK_REFCLKSEL		(0x2 << 8)
+
 #define EXYNOS_4x12_UPHYCLK_PHY0_ID_PULLUP	BIT(3)
 #define EXYNOS_4x12_UPHYCLK_PHY0_COMMON_ON	BIT(4)
 #define EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON	BIT(7)
@@ -197,6 +199,10 @@ static void exynos4x12_setup_clk(struct samsung_usb2_phy_instance *inst)
 
 	clk = readl(drv->reg_phy + EXYNOS_4x12_UPHYCLK);
 	clk &= ~EXYNOS_4x12_UPHYCLK_PHYFSEL_MASK;
+
+	if (drv->cfg->has_refclk_sel)
+		clk = EXYNOS_3250_UPHYCLK_REFCLKSEL;
+
 	clk |= drv->ref_reg_val << EXYNOS_4x12_UPHYCLK_PHYFSEL_OFFSET;
 	clk |= EXYNOS_4x12_UPHYCLK_PHY1_COMMON_ON;
 	writel(clk, drv->reg_phy + EXYNOS_4x12_UPHYCLK);
@@ -278,7 +284,7 @@ static int exynos4x12_power_on(struct samsung_usb2_phy_instance *inst)
 		exynos4x12_power_on_int(&drv->instances[EXYNOS4x12_DEVICE]);
 	}
 
-	if (inst->cfg->id == EXYNOS4x12_DEVICE)
+	if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
 		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
 						EXYNOS_4x12_MODE_SWITCH_MASK,
 						EXYNOS_4x12_MODE_SWITCH_DEVICE);
@@ -310,7 +316,7 @@ static int exynos4x12_power_off(struct samsung_usb2_phy_instance *inst)
 	if (inst->ext_cnt-- > 1)
 		return 0;
 
-	if (inst->cfg->id == EXYNOS4x12_DEVICE)
+	if (inst->cfg->id == EXYNOS4x12_DEVICE && drv->cfg->has_mode_switch)
 		regmap_update_bits(drv->reg_sys, EXYNOS_4x12_MODE_SWITCH_OFFSET,
 						EXYNOS_4x12_MODE_SWITCH_MASK,
 						EXYNOS_4x12_MODE_SWITCH_HOST);
@@ -358,6 +364,13 @@ static const struct samsung_usb2_common_phy exynos4x12_phys[] = {
 	{},
 };
 
+const struct samsung_usb2_phy_config exynos3250_usb2_phy_config = {
+	.has_refclk_sel		= 1,
+	.num_phys		= 1,
+	.phys			= exynos4x12_phys,
+	.rate_to_clk		= exynos4x12_rate_to_clk,
+};
+
 const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config = {
 	.has_mode_switch	= 1,
 	.num_phys		= EXYNOS4x12_NUM_PHYS,
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index 1e69a32..16aae7a 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -87,6 +87,12 @@ static struct phy *samsung_usb2_phy_xlate(struct device *dev,
 }
 
 static const struct of_device_id samsung_usb2_phy_of_match[] = {
+#ifdef CONFIG_PHY_EXYNOS4X12_USB2
+	{
+		.compatible = "samsung,exynos3250-usb2-phy",
+		.data = &exynos3250_usb2_phy_config,
+	},
+#endif
 #ifdef CONFIG_PHY_EXYNOS4210_USB2
 	{
 		.compatible = "samsung,exynos4210-usb2-phy",
diff --git a/drivers/phy/phy-samsung-usb2.h b/drivers/phy/phy-samsung-usb2.h
index 9188478..b03da0e 100644
--- a/drivers/phy/phy-samsung-usb2.h
+++ b/drivers/phy/phy-samsung-usb2.h
@@ -60,8 +60,10 @@ struct samsung_usb2_phy_config {
 	int (*rate_to_clk)(unsigned long, u32 *);
 	unsigned int num_phys;
 	bool has_mode_switch;
+	bool has_refclk_sel;
 };
 
+extern const struct samsung_usb2_phy_config exynos3250_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos4210_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos4x12_usb2_phy_config;
 extern const struct samsung_usb2_phy_config exynos5250_usb2_phy_config;
-- 
1.7.9.5


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

* [PATCH 12/28] phy: core: Support regulator supply for PHY power
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (10 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 11/28] drivers: phy: exynos-usb2: add support for Exynos 3250 Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 13/28] phy: core: Add phy-supply to DT binding documentation Kishon Vijay Abraham I
                   ` (16 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Roger Quadros <rogerq@ti.com>

Some PHYs can be powered by an external power regulator.
e.g. USB_HS PHY on DRA7 SoC. Make the PHY core support a
power regulator.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-core.c  |   26 ++++++++++++++++++++++++++
 include/linux/phy/phy.h |    2 ++
 2 files changed, 28 insertions(+)

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 49c4465..75c9739 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -21,6 +21,7 @@
 #include <linux/phy/phy.h>
 #include <linux/idr.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 
 static struct class *phy_class;
 static DEFINE_MUTEX(phy_provider_mutex);
@@ -226,6 +227,12 @@ int phy_power_on(struct phy *phy)
 	if (!phy)
 		return 0;
 
+	if (phy->pwr) {
+		ret = regulator_enable(phy->pwr);
+		if (ret)
+			return ret;
+	}
+
 	ret = phy_pm_runtime_get_sync(phy);
 	if (ret < 0 && ret != -ENOTSUPP)
 		return ret;
@@ -247,6 +254,8 @@ int phy_power_on(struct phy *phy)
 out:
 	mutex_unlock(&phy->mutex);
 	phy_pm_runtime_put_sync(phy);
+	if (phy->pwr)
+		regulator_disable(phy->pwr);
 
 	return ret;
 }
@@ -272,6 +281,9 @@ int phy_power_off(struct phy *phy)
 	mutex_unlock(&phy->mutex);
 	phy_pm_runtime_put(phy);
 
+	if (phy->pwr)
+		regulator_disable(phy->pwr);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(phy_power_off);
@@ -588,6 +600,16 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 		goto free_phy;
 	}
 
+	/* phy-supply */
+	phy->pwr = regulator_get_optional(dev, "phy");
+	if (IS_ERR(phy->pwr)) {
+		if (PTR_ERR(phy->pwr) == -EPROBE_DEFER) {
+			ret = -EPROBE_DEFER;
+			goto free_ida;
+		}
+		phy->pwr = NULL;
+	}
+
 	device_initialize(&phy->dev);
 	mutex_init(&phy->mutex);
 
@@ -617,6 +639,9 @@ put_dev:
 	put_device(&phy->dev);  /* calls phy_release() which frees resources */
 	return ERR_PTR(ret);
 
+free_ida:
+	ida_simple_remove(&phy_ida, phy->id);
+
 free_phy:
 	kfree(phy);
 	return ERR_PTR(ret);
@@ -800,6 +825,7 @@ static void phy_release(struct device *dev)
 
 	phy = to_phy(dev);
 	dev_vdbg(dev, "releasing '%s'\n", dev_name(dev));
+	regulator_put(phy->pwr);
 	ida_simple_remove(&phy_ida, phy->id);
 	kfree(phy);
 }
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 2760744..9a86945 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -18,6 +18,7 @@
 #include <linux/of.h>
 #include <linux/device.h>
 #include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
 
 struct phy;
 
@@ -65,6 +66,7 @@ struct phy {
 	int			init_count;
 	int			power_count;
 	struct phy_attrs	attrs;
+	struct regulator	*pwr;
 };
 
 /**
-- 
1.7.9.5


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

* [PATCH 13/28] phy: core: Add phy-supply to DT binding documentation
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (11 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 12/28] phy: core: Support regulator supply for PHY power Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 14/28] phy: Kconfig: Re-organize Exynos USB 2.0 PHY configs Kishon Vijay Abraham I
                   ` (15 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Roger Quadros <rogerq@ti.com>

phy-supply is a phandle to the regulator that provides power to the
PHY. This regulator is managed during the PHY power on/off sequence
by the phy core driver.

Signed-off-by: Roger Quadros <rogerq@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/phy-bindings.txt       |    4 ++++
 1 file changed, 4 insertions(+)

diff --git a/Documentation/devicetree/bindings/phy/phy-bindings.txt b/Documentation/devicetree/bindings/phy/phy-bindings.txt
index 8ae844f..2aa1840 100644
--- a/Documentation/devicetree/bindings/phy/phy-bindings.txt
+++ b/Documentation/devicetree/bindings/phy/phy-bindings.txt
@@ -10,6 +10,10 @@ Required Properties:
 		provider can use the values in cells to find the appropriate
 		PHY.
 
+Optional Properties:
+phy-supply:	Phandle to a regulator that provides power to the PHY. This
+		regulator will be managed during the PHY power on/off sequence.
+
 For example:
 
 phys: phy {
-- 
1.7.9.5


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

* [PATCH 14/28] phy: Kconfig: Re-organize Exynos USB 2.0 PHY configs
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (12 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 13/28] phy: core: Add phy-supply to DT binding documentation Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 15/28] phy: Kconfig: Update config for Exynos USB DRD Kishon Vijay Abraham I
                   ` (14 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Sachin Kamat <sachin.kamat@samsung.com>

Since the USB 2.0 PHYs are required with EHCI/OHCI USB drivers and
USB gadget controller supported by the DWC2 gadget driver, make it
depend on them and default to ARCH_EXYNOS as they are meant for
Exynos platforms. Also, make the sub-drivers silent options enabling
them based on the SoC platforms that they are meant to work with. This
will make life easier for end users who do not have any way knowing the
dependencies.

Signed-off-by: Sachin Kamat <sachin.kamat@samsung.com>
Reviewed-by: Jingoo Han <jg1.han@samsung.com>
Tested-by: Vivek Gautam <gautam.vivek@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig |   35 +++++++++++------------------------
 1 file changed, 11 insertions(+), 24 deletions(-)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 7c49c4c..f28b87f 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -132,43 +132,30 @@ config PHY_SUN4I_USB
 config PHY_SAMSUNG_USB2
 	tristate "Samsung USB 2.0 PHY driver"
 	depends on HAS_IOMEM
+	depends on USB_EHCI_EXYNOS || USB_OHCI_EXYNOS || USB_DWC2
 	select GENERIC_PHY
 	select MFD_SYSCON
+	default ARCH_EXYNOS
 	help
 	  Enable this to support the Samsung USB 2.0 PHY driver for Samsung
-	  SoCs. This driver provides the interface for USB 2.0 PHY. Support for
-	  particular SoCs has to be enabled in addition to this driver. Number
-	  and type of supported phys depends on the SoC.
+	  SoCs. This driver provides the interface for USB 2.0 PHY. Support
+	  for particular PHYs will be enabled based on the SoC type in addition
+	  to this driver.
 
 config PHY_EXYNOS4210_USB2
-	bool "Support for Exynos 4210"
+	bool
 	depends on PHY_SAMSUNG_USB2
-	depends on CPU_EXYNOS4210
-	help
-	  Enable USB PHY support for Exynos 4210. This option requires that
-	  Samsung USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of Exynos 4210 four
-	  phys are available - device, host, HSIC0 and HSIC1.
+	default CPU_EXYNOS4210
 
 config PHY_EXYNOS4X12_USB2
-	bool "Support for Exynos 3250/4x12"
+	bool
 	depends on PHY_SAMSUNG_USB2
-	depends on (SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412)
-	help
-	  Enable USB PHY support for Exynos 3250/4x12. This option requires
-	  that Samsung USB 2.0 PHY driver is enabled and means that support for
-	  this particular SoC is compiled in the driver. In case of Exynos 4x12
-	  four phys are available - device, host, HSIC0 and HSIC1.
+	default SOC_EXYNOS3250 || SOC_EXYNOS4212 || SOC_EXYNOS4412
 
 config PHY_EXYNOS5250_USB2
-	bool "Support for Exynos 5250"
+	bool
 	depends on PHY_SAMSUNG_USB2
-	depends on SOC_EXYNOS5250
-	help
-	  Enable USB PHY support for Exynos 5250. This option requires that
-	  Samsung USB 2.0 PHY driver is enabled and means that support for this
-	  particular SoC is compiled in the driver. In case of Exynos 5250 four
-	  phys are available - device, host, HSIC0 and HSIC.
+	default SOC_EXYNOS5250 || SOC_EXYNOS5420
 
 config PHY_EXYNOS5_USBDRD
 	tristate "Exynos5 SoC series USB DRD PHY driver"
-- 
1.7.9.5


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

* [PATCH 15/28] phy: Kconfig: Update config for Exynos USB DRD
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (13 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 14/28] phy: Kconfig: Re-organize Exynos USB 2.0 PHY configs Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 16/28] phy: qcom: Add driver for QCOM APQ8064 SATA PHY Kishon Vijay Abraham I
                   ` (13 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Sachin Kamat <sachin.kamat@samsung.com>

USB DWC3 driver on Exynos platform does not work without its
corresponding phy driver. Hence make the PHY driver depend on
Exynos DWC3 driver and default it to yes to make things easier
for the end user.

Signed-off-by: Sachin Kamat <sachin.kamat@samsung.com>
Reviewed-by: Jingoo Han <jg1.han@samsung.com>
Tested-by: Vivek Gautam <gautam.vivek@samsung.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig |    2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index f28b87f..778e126 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -161,8 +161,10 @@ config PHY_EXYNOS5_USBDRD
 	tristate "Exynos5 SoC series USB DRD PHY driver"
 	depends on ARCH_EXYNOS5 && OF
 	depends on HAS_IOMEM
+	depends on USB_DWC3_EXYNOS
 	select GENERIC_PHY
 	select MFD_SYSCON
+	default y
 	help
 	  Enable USB DRD PHY support for Exynos 5 SoC series.
 	  This driver provides PHY interface for USB 3.0 DRD controller
-- 
1.7.9.5


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

* [PATCH 16/28] phy: qcom: Add driver for QCOM APQ8064 SATA PHY
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (14 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 15/28] phy: Kconfig: Update config for Exynos USB DRD Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 17/28] phy: qcom: Add APQ8064 SATA PHY device tree bindings Kishon Vijay Abraham I
                   ` (12 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>

Add a PHY driver for uses with AHCI based SATA controller driver on the
APQ8064 family of SoCs.

This patch is a forward port from Qualcomm's v3.4 andriod kernel.

Tested on IFC6410 board.

CC: Sujit Reddy Thumma <sthumma@codeaurora.org>
Tested-by: Kiran Padwal <kiran.padwal@smartplayin.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig                 |    7 +
 drivers/phy/Makefile                |    1 +
 drivers/phy/phy-qcom-apq8064-sata.c |  288 +++++++++++++++++++++++++++++++++++
 3 files changed, 296 insertions(+)
 create mode 100644 drivers/phy/phy-qcom-apq8064-sata.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 778e126..6911152 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -177,4 +177,11 @@ config PHY_XGENE
 	help
 	  This option enables support for APM X-Gene SoC multi-purpose PHY.
 
+config PHY_QCOM_APQ8064_SATA
+	tristate "Qualcomm APQ8064 SATA SerDes/PHY driver"
+	depends on ARCH_QCOM
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 54f04d0..a4819d3 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -21,3 +21,4 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4X12_USB2)	+= phy-exynos4x12-usb2.o
 phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2)	+= phy-exynos5250-usb2.o
 obj-$(CONFIG_PHY_EXYNOS5_USBDRD)	+= phy-exynos5-usbdrd.o
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
+obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c
new file mode 100644
index 0000000..c9b4dd6
--- /dev/null
+++ b/drivers/phy/phy-qcom-apq8064-sata.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+/* PHY registers */
+#define UNIPHY_PLL_REFCLK_CFG		0x000
+#define UNIPHY_PLL_PWRGEN_CFG		0x014
+#define UNIPHY_PLL_GLB_CFG		0x020
+#define UNIPHY_PLL_SDM_CFG0		0x038
+#define UNIPHY_PLL_SDM_CFG1		0x03C
+#define UNIPHY_PLL_SDM_CFG2		0x040
+#define UNIPHY_PLL_SDM_CFG3		0x044
+#define UNIPHY_PLL_SDM_CFG4		0x048
+#define UNIPHY_PLL_SSC_CFG0		0x04C
+#define UNIPHY_PLL_SSC_CFG1		0x050
+#define UNIPHY_PLL_SSC_CFG2		0x054
+#define UNIPHY_PLL_SSC_CFG3		0x058
+#define UNIPHY_PLL_LKDET_CFG0		0x05C
+#define UNIPHY_PLL_LKDET_CFG1		0x060
+#define UNIPHY_PLL_LKDET_CFG2		0x064
+#define UNIPHY_PLL_CAL_CFG0		0x06C
+#define UNIPHY_PLL_CAL_CFG8		0x08C
+#define UNIPHY_PLL_CAL_CFG9		0x090
+#define UNIPHY_PLL_CAL_CFG10		0x094
+#define UNIPHY_PLL_CAL_CFG11		0x098
+#define UNIPHY_PLL_STATUS		0x0C0
+
+#define SATA_PHY_SER_CTRL		0x100
+#define SATA_PHY_TX_DRIV_CTRL0		0x104
+#define SATA_PHY_TX_DRIV_CTRL1		0x108
+#define SATA_PHY_TX_IMCAL0		0x11C
+#define SATA_PHY_TX_IMCAL2		0x124
+#define SATA_PHY_RX_IMCAL0		0x128
+#define SATA_PHY_EQUAL			0x13C
+#define SATA_PHY_OOB_TERM		0x144
+#define SATA_PHY_CDR_CTRL0		0x148
+#define SATA_PHY_CDR_CTRL1		0x14C
+#define SATA_PHY_CDR_CTRL2		0x150
+#define SATA_PHY_CDR_CTRL3		0x154
+#define SATA_PHY_PI_CTRL0		0x168
+#define SATA_PHY_POW_DWN_CTRL0		0x180
+#define SATA_PHY_POW_DWN_CTRL1		0x184
+#define SATA_PHY_TX_DATA_CTRL		0x188
+#define SATA_PHY_ALIGNP			0x1A4
+#define SATA_PHY_TX_IMCAL_STAT		0x1E4
+#define SATA_PHY_RX_IMCAL_STAT		0x1E8
+
+#define UNIPHY_PLL_LOCK		BIT(0)
+#define SATA_PHY_TX_CAL		BIT(0)
+#define SATA_PHY_RX_CAL		BIT(0)
+
+/* default timeout set to 1 sec */
+#define TIMEOUT_MS		10000
+#define DELAY_INTERVAL_US	100
+
+struct qcom_apq8064_sata_phy {
+	void __iomem *mmio;
+	struct clk *cfg_clk;
+	struct device *dev;
+};
+
+/* Helper function to do poll and timeout */
+static int read_poll_timeout(void __iomem *addr, u32 mask)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS);
+
+	do {
+		if (readl_relaxed(addr) & mask)
+			return 0;
+
+		 usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
+	} while (!time_after(jiffies, timeout));
+
+	return -ETIMEDOUT;
+}
+
+static int qcom_apq8064_sata_phy_init(struct phy *generic_phy)
+{
+	struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+	void __iomem *base = phy->mmio;
+	int ret = 0;
+
+	/* SATA phy initialization */
+	writel_relaxed(0x01, base + SATA_PHY_SER_CTRL);
+	writel_relaxed(0xB1, base + SATA_PHY_POW_DWN_CTRL0);
+	/* Make sure the power down happens before power up */
+	mb();
+	usleep_range(10, 60);
+
+	writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+	writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+	writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+	writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+	writel_relaxed(0x02, base + SATA_PHY_TX_IMCAL2);
+
+	/* Write UNIPHYPLL registers to configure PLL */
+	writel_relaxed(0x04, base + UNIPHY_PLL_REFCLK_CFG);
+	writel_relaxed(0x00, base + UNIPHY_PLL_PWRGEN_CFG);
+
+	writel_relaxed(0x0A, base + UNIPHY_PLL_CAL_CFG0);
+	writel_relaxed(0xF3, base + UNIPHY_PLL_CAL_CFG8);
+	writel_relaxed(0x01, base + UNIPHY_PLL_CAL_CFG9);
+	writel_relaxed(0xED, base + UNIPHY_PLL_CAL_CFG10);
+	writel_relaxed(0x02, base + UNIPHY_PLL_CAL_CFG11);
+
+	writel_relaxed(0x36, base + UNIPHY_PLL_SDM_CFG0);
+	writel_relaxed(0x0D, base + UNIPHY_PLL_SDM_CFG1);
+	writel_relaxed(0xA3, base + UNIPHY_PLL_SDM_CFG2);
+	writel_relaxed(0xF0, base + UNIPHY_PLL_SDM_CFG3);
+	writel_relaxed(0x00, base + UNIPHY_PLL_SDM_CFG4);
+
+	writel_relaxed(0x19, base + UNIPHY_PLL_SSC_CFG0);
+	writel_relaxed(0xE1, base + UNIPHY_PLL_SSC_CFG1);
+	writel_relaxed(0x00, base + UNIPHY_PLL_SSC_CFG2);
+	writel_relaxed(0x11, base + UNIPHY_PLL_SSC_CFG3);
+
+	writel_relaxed(0x04, base + UNIPHY_PLL_LKDET_CFG0);
+	writel_relaxed(0xFF, base + UNIPHY_PLL_LKDET_CFG1);
+
+	writel_relaxed(0x02, base + UNIPHY_PLL_GLB_CFG);
+	/* make sure global config LDO power down happens before power up */
+	mb();
+
+	writel_relaxed(0x03, base + UNIPHY_PLL_GLB_CFG);
+	writel_relaxed(0x05, base + UNIPHY_PLL_LKDET_CFG2);
+
+	/* PLL Lock wait */
+	ret = read_poll_timeout(base + UNIPHY_PLL_STATUS, UNIPHY_PLL_LOCK);
+	if (ret) {
+		dev_err(phy->dev, "poll timeout UNIPHY_PLL_STATUS\n");
+		return ret;
+	}
+
+	/* TX Calibration */
+	ret = read_poll_timeout(base + SATA_PHY_TX_IMCAL_STAT, SATA_PHY_TX_CAL);
+	if (ret) {
+		dev_err(phy->dev, "poll timeout SATA_PHY_TX_IMCAL_STAT\n");
+		return ret;
+	}
+
+	/* RX Calibration */
+	ret = read_poll_timeout(base + SATA_PHY_RX_IMCAL_STAT, SATA_PHY_RX_CAL);
+	if (ret) {
+		dev_err(phy->dev, "poll timeout SATA_PHY_RX_IMCAL_STAT\n");
+		return ret;
+	}
+
+	/* SATA phy calibrated succesfully, power up to functional mode */
+	writel_relaxed(0x3E, base + SATA_PHY_POW_DWN_CTRL1);
+	writel_relaxed(0x01, base + SATA_PHY_RX_IMCAL0);
+	writel_relaxed(0x01, base + SATA_PHY_TX_IMCAL0);
+
+	writel_relaxed(0x00, base + SATA_PHY_POW_DWN_CTRL1);
+	writel_relaxed(0x59, base + SATA_PHY_CDR_CTRL0);
+	writel_relaxed(0x04, base + SATA_PHY_CDR_CTRL1);
+	writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL2);
+	writel_relaxed(0x00, base + SATA_PHY_PI_CTRL0);
+	writel_relaxed(0x00, base + SATA_PHY_CDR_CTRL3);
+	writel_relaxed(0x01, base + SATA_PHY_POW_DWN_CTRL0);
+
+	writel_relaxed(0x11, base + SATA_PHY_TX_DATA_CTRL);
+	writel_relaxed(0x43, base + SATA_PHY_ALIGNP);
+	writel_relaxed(0x04, base + SATA_PHY_OOB_TERM);
+
+	writel_relaxed(0x01, base + SATA_PHY_EQUAL);
+	writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL0);
+	writel_relaxed(0x09, base + SATA_PHY_TX_DRIV_CTRL1);
+
+	return 0;
+}
+
+static int qcom_apq8064_sata_phy_exit(struct phy *generic_phy)
+{
+	struct qcom_apq8064_sata_phy *phy = phy_get_drvdata(generic_phy);
+	void __iomem *base = phy->mmio;
+
+	/* Power down PHY */
+	writel_relaxed(0xF8, base + SATA_PHY_POW_DWN_CTRL0);
+	writel_relaxed(0xFE, base + SATA_PHY_POW_DWN_CTRL1);
+
+	/* Power down PLL block */
+	writel_relaxed(0x00, base + UNIPHY_PLL_GLB_CFG);
+
+	return 0;
+}
+
+static struct phy_ops qcom_apq8064_sata_phy_ops = {
+	.init		= qcom_apq8064_sata_phy_init,
+	.exit		= qcom_apq8064_sata_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static int qcom_apq8064_sata_phy_probe(struct platform_device *pdev)
+{
+	struct qcom_apq8064_sata_phy *phy;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+	struct phy *generic_phy;
+	int ret;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	phy->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(phy->mmio))
+		return PTR_ERR(phy->mmio);
+
+	generic_phy = devm_phy_create(dev, &qcom_apq8064_sata_phy_ops, NULL);
+	if (IS_ERR(generic_phy)) {
+		dev_err(dev, "%s: failed to create phy\n", __func__);
+		return PTR_ERR(generic_phy);
+	}
+
+	phy->dev = dev;
+	phy_set_drvdata(generic_phy, phy);
+	platform_set_drvdata(pdev, phy);
+
+	phy->cfg_clk = devm_clk_get(dev, "cfg");
+	if (IS_ERR(phy->cfg_clk)) {
+		dev_err(dev, "Failed to get sata cfg clock\n");
+		return PTR_ERR(phy->cfg_clk);
+	}
+
+	ret = clk_prepare_enable(phy->cfg_clk);
+	if (ret)
+		return ret;
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		clk_disable_unprepare(phy->cfg_clk);
+		dev_err(dev, "%s: failed to register phy\n", __func__);
+		return PTR_ERR(phy_provider);
+	}
+
+	return 0;
+}
+
+static int qcom_apq8064_sata_phy_remove(struct platform_device *pdev)
+{
+	struct qcom_apq8064_sata_phy *phy = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(phy->cfg_clk);
+
+	return 0;
+}
+
+static const struct of_device_id qcom_apq8064_sata_phy_of_match[] = {
+	{ .compatible = "qcom,apq8064-sata-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, qcom_apq8064_sata_phy_of_match);
+
+static struct platform_driver qcom_apq8064_sata_phy_driver = {
+	.probe	= qcom_apq8064_sata_phy_probe,
+	.remove	= qcom_apq8064_sata_phy_remove,
+	.driver = {
+		.name	= "qcom-apq8064-sata-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= qcom_apq8064_sata_phy_of_match,
+	}
+};
+module_platform_driver(qcom_apq8064_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM apq8064 SATA PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5


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

* [PATCH 17/28] phy: qcom: Add APQ8064 SATA PHY device tree bindings
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (15 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 16/28] phy: qcom: Add driver for QCOM APQ8064 SATA PHY Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 18/28] phy: Remove ARCH_KIRKWOOD dependency Kishon Vijay Abraham I
                   ` (11 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>

This patch adds binding spec for Qualcomm AP8064 SATA PHY.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Tested-by: Kiran Padwal <kiran.padwal@smartplayin.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../bindings/phy/qcom-apq8064-sata-phy.txt         |   24 ++++++++++++++++++++
 1 file changed, 24 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt

diff --git a/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt b/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt
new file mode 100644
index 0000000..952f6c9
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/qcom-apq8064-sata-phy.txt
@@ -0,0 +1,24 @@
+Qualcomm APQ8064 SATA PHY Controller
+------------------------------------
+
+SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
+Each SATA PHY controller should have its own node.
+
+Required properties:
+- compatible: compatible list, contains "qcom,apq8064-sata-phy".
+- reg: offset and length of the SATA PHY register set;
+- #phy-cells: must be zero
+- clocks: a list of phandles and clock-specifier pairs, one for each entry in
+  clock-names.
+- clock-names: must be "cfg" for phy config clock.
+
+Example:
+	sata_phy: sata-phy@1b400000 {
+		compatible = "qcom,apq8064-sata-phy";
+		reg = <0x1b400000 0x200>;
+
+		clocks = <&gcc SATA_PHY_CFG_CLK>;
+		clock-names = "cfg";
+
+		#phy-cells = <0>;
+	};
-- 
1.7.9.5


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

* [PATCH 18/28] phy: Remove ARCH_KIRKWOOD dependency
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (16 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 17/28] phy: qcom: Add APQ8064 SATA PHY device tree bindings Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 19/28] phy: add a driver for the Berlin SATA PHY Kishon Vijay Abraham I
                   ` (10 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Andrew Lunn <andrew@lunn.ch>

mach-kirkwood has been removed, now that kirkwood lives in mach-mvebu.
Depend on MACH_KIRKWOOD, which will be set when these SoCs are built
as part of mach-mvebv.

Signed-off-by: Andrew Lunn <andrew@lunn.ch>
Cc: Kishon Vijay Abraham I <kishon@ti.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 6911152..261ad18 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -27,7 +27,7 @@ config PHY_EXYNOS_MIPI_VIDEO
 
 config PHY_MVEBU_SATA
 	def_bool y
-	depends on ARCH_KIRKWOOD || ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
+	depends on ARCH_DOVE || MACH_DOVE || MACH_KIRKWOOD
 	depends on OF
 	select GENERIC_PHY
 
-- 
1.7.9.5


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

* [PATCH 19/28] phy: add a driver for the Berlin SATA PHY
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (17 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 18/28] phy: Remove ARCH_KIRKWOOD dependency Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 20/28] Documentation: bindings: add " Kishon Vijay Abraham I
                   ` (9 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Antoine Ténart <antoine.tenart@free-electrons.com>

The Berlin SoC has a two SATA ports. Add a PHY driver to handle them.

The mode selection can let us think this PHY can be configured to fit
other purposes. But there are reasons to think the SATA mode will be
the only one usable: the PHY registers are only accessible indirectly
through two registers in the SATA range, the PHY seems to be integrated
and no information tells us the contrary. For these reasons, make the
driver a SATA PHY driver.

Signed-off-by: Antoine Ténart <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-sata.c |  284 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 292 insertions(+)
 create mode 100644 drivers/phy/phy-berlin-sata.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 261ad18..1704fd4 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_SATA
+	tristate "Marvell Berlin SATA PHY driver"
+	depends on ARCH_BERLIN && HAS_IOMEM && OF
+	select GENERIC_PHY
+	help
+	  Enable this to support the SATA PHY on Marvell Berlin SoCs.
+
 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 a4819d3..3c2ad59 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -3,6 +3,7 @@
 #
 
 obj-$(CONFIG_GENERIC_PHY)		+= phy-core.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
 obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)	+= phy-exynos-mipi-video.o
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
new file mode 100644
index 0000000..c5e688b
--- /dev/null
+++ b/drivers/phy/phy-berlin-sata.c
@@ -0,0 +1,284 @@
+/*
+ * Marvell Berlin SATA PHY driver
+ *
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Ténart <antoine.tenart@free-electrons.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/clk.h>
+#include <linux/module.h>
+#include <linux/phy/phy.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+
+#define HOST_VSA_ADDR		0x0
+#define HOST_VSA_DATA		0x4
+#define PORT_SCR_CTL		0x2c
+#define PORT_VSR_ADDR		0x78
+#define PORT_VSR_DATA		0x7c
+
+#define CONTROL_REGISTER	0x0
+#define MBUS_SIZE_CONTROL	0x4
+
+#define POWER_DOWN_PHY0			BIT(6)
+#define POWER_DOWN_PHY1			BIT(14)
+#define MBUS_WRITE_REQUEST_SIZE_128	(BIT(2) << 16)
+#define MBUS_READ_REQUEST_SIZE_128	(BIT(2) << 19)
+
+#define PHY_BASE		0x200
+
+/* register 0x01 */
+#define REF_FREF_SEL_25		BIT(0)
+#define PHY_MODE_SATA		(0x0 << 5)
+
+/* register 0x02 */
+#define USE_MAX_PLL_RATE	BIT(12)
+
+/* register 0x23 */
+#define DATA_BIT_WIDTH_10	(0x0 << 10)
+#define DATA_BIT_WIDTH_20	(0x1 << 10)
+#define DATA_BIT_WIDTH_40	(0x2 << 10)
+
+/* register 0x25 */
+#define PHY_GEN_MAX_1_5		(0x0 << 10)
+#define PHY_GEN_MAX_3_0		(0x1 << 10)
+#define PHY_GEN_MAX_6_0		(0x2 << 10)
+
+struct phy_berlin_desc {
+	struct phy	*phy;
+	u32		power_bit;
+	unsigned	index;
+};
+
+struct phy_berlin_priv {
+	void __iomem		*base;
+	spinlock_t		lock;
+	struct clk		*clk;
+	struct phy_berlin_desc	**phys;
+	unsigned		nphys;
+};
+
+static inline void phy_berlin_sata_reg_setbits(void __iomem *ctrl_reg, u32 reg,
+					       u32 mask, u32 val)
+{
+	u32 regval;
+
+	/* select register */
+	writel(PHY_BASE + reg, ctrl_reg + PORT_VSR_ADDR);
+
+	/* set bits */
+	regval = readl(ctrl_reg + PORT_VSR_DATA);
+	regval &= ~mask;
+	regval |= val;
+	writel(regval, ctrl_reg + PORT_VSR_DATA);
+}
+
+static int phy_berlin_sata_power_on(struct phy *phy)
+{
+	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+	void __iomem *ctrl_reg = priv->base + 0x60 + (desc->index * 0x80);
+	int ret = 0;
+	u32 regval;
+
+	clk_prepare_enable(priv->clk);
+
+	spin_lock(&priv->lock);
+
+	/* Power on PHY */
+	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval &= ~desc->power_bit;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	/* Configure MBus */
+	writel(MBUS_SIZE_CONTROL, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval |= MBUS_WRITE_REQUEST_SIZE_128 | MBUS_READ_REQUEST_SIZE_128;
+	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);
+
+	/* set PHY up to 6 Gbps */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x25, 0xc00, PHY_GEN_MAX_6_0);
+
+	/* set 40 bits width */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x23,  0xc00, DATA_BIT_WIDTH_40);
+
+	/* use max pll rate */
+	phy_berlin_sata_reg_setbits(ctrl_reg, 0x2, 0x0, USE_MAX_PLL_RATE);
+
+	/* set Gen3 controller speed */
+	regval = readl(ctrl_reg + PORT_SCR_CTL);
+	regval &= ~GENMASK(7, 4);
+	regval |= 0x30;
+	writel(regval, ctrl_reg + PORT_SCR_CTL);
+
+	spin_unlock(&priv->lock);
+
+	clk_disable_unprepare(priv->clk);
+
+	return ret;
+}
+
+static int phy_berlin_sata_power_off(struct phy *phy)
+{
+	struct phy_berlin_desc *desc = phy_get_drvdata(phy);
+	struct phy_berlin_priv *priv = dev_get_drvdata(phy->dev.parent);
+	u32 regval;
+
+	clk_prepare_enable(priv->clk);
+
+	spin_lock(&priv->lock);
+
+	/* Power down PHY */
+	writel(CONTROL_REGISTER, priv->base + HOST_VSA_ADDR);
+	regval = readl(priv->base + HOST_VSA_DATA);
+	regval |= desc->power_bit;
+	writel(regval, priv->base + HOST_VSA_DATA);
+
+	spin_unlock(&priv->lock);
+
+	clk_disable_unprepare(priv->clk);
+
+	return 0;
+}
+
+static struct phy *phy_berlin_sata_phy_xlate(struct device *dev,
+					     struct of_phandle_args *args)
+{
+	struct phy_berlin_priv *priv = dev_get_drvdata(dev);
+	int i;
+
+	if (WARN_ON(args->args[0] >= priv->nphys))
+		return ERR_PTR(-ENODEV);
+
+	for (i = 0; i < priv->nphys; i++) {
+		if (priv->phys[i]->index == args->args[0])
+			break;
+	}
+
+	if (i == priv->nphys)
+		return ERR_PTR(-ENODEV);
+
+	return priv->phys[i]->phy;
+}
+
+static struct phy_ops phy_berlin_sata_ops = {
+	.power_on	= phy_berlin_sata_power_on,
+	.power_off	= phy_berlin_sata_power_off,
+	.owner		= THIS_MODULE,
+};
+
+static u32 phy_berlin_power_down_bits[] = {
+	POWER_DOWN_PHY0,
+	POWER_DOWN_PHY1,
+};
+
+static int phy_berlin_sata_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct device_node *child;
+	struct phy *phy;
+	struct phy_provider *phy_provider;
+	struct phy_berlin_priv *priv;
+	struct resource *res;
+	int i = 0;
+	u32 phy_id;
+
+	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	priv->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!priv->base)
+		return -ENOMEM;
+
+	priv->clk = devm_clk_get(dev, NULL);
+	if (IS_ERR(priv->clk))
+		return PTR_ERR(priv->clk);
+
+	priv->nphys = of_get_child_count(dev->of_node);
+	if (priv->nphys == 0)
+		return -ENODEV;
+
+	priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys),
+				  GFP_KERNEL);
+	if (!priv->phys)
+		return -ENOMEM;
+
+	dev_set_drvdata(dev, priv);
+	spin_lock_init(&priv->lock);
+
+	for_each_available_child_of_node(dev->of_node, child) {
+		struct phy_berlin_desc *phy_desc;
+
+		if (of_property_read_u32(child, "reg", &phy_id)) {
+			dev_err(dev, "missing reg property in node %s\n",
+				child->name);
+			return -EINVAL;
+		}
+
+		if (phy_id >= ARRAY_SIZE(phy_berlin_power_down_bits)) {
+			dev_err(dev, "invalid reg in node %s\n", child->name);
+			return -EINVAL;
+		}
+
+		phy_desc = devm_kzalloc(dev, sizeof(*phy_desc), GFP_KERNEL);
+		if (!phy_desc)
+			return -ENOMEM;
+
+		phy = devm_phy_create(dev, &phy_berlin_sata_ops, NULL);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "failed to create PHY %d\n", phy_id);
+			return PTR_ERR(phy);
+		}
+
+		phy_desc->phy = phy;
+		phy_desc->power_bit = phy_berlin_power_down_bits[phy_id];
+		phy_desc->index = phy_id;
+		phy_set_drvdata(phy, phy_desc);
+
+		priv->phys[i++] = phy_desc;
+
+		/* Make sure the PHY is off */
+		phy_berlin_sata_power_off(phy);
+	}
+
+	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;
+}
+
+static const struct of_device_id phy_berlin_sata_of_match[] = {
+	{ .compatible = "marvell,berlin2q-sata-phy" },
+	{ },
+};
+
+static struct platform_driver phy_berlin_sata_driver = {
+	.probe	= phy_berlin_sata_probe,
+	.driver	= {
+		.name		= "phy-berlin-sata",
+		.owner		= THIS_MODULE,
+		.of_match_table	= phy_berlin_sata_of_match,
+	},
+};
+module_platform_driver(phy_berlin_sata_driver);
+
+MODULE_DESCRIPTION("Marvell Berlin SATA PHY driver");
+MODULE_AUTHOR("Antoine Ténart <antoine.tenart@free-electrons.com>");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5


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

* [PATCH 20/28] Documentation: bindings: add the Berlin SATA PHY
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (18 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 19/28] phy: add a driver for the Berlin SATA PHY Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 21/28] phy: core: Fix of_phy_provider_lookup to return PHY provider for sub node Kishon Vijay Abraham I
                   ` (8 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Antoine Ténart <antoine.tenart@free-electrons.com>

The Berlin SATA PHY drives the PHY related to the SATA interface. Add
the corresponding documentation.

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

diff --git a/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt b/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
new file mode 100644
index 0000000..88f8c23
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/berlin-sata-phy.txt
@@ -0,0 +1,34 @@
+Berlin SATA PHY
+---------------
+
+Required properties:
+- compatible: should be "marvell,berlin2q-sata-phy"
+- address-cells: should be 1
+- size-cells: should be 0
+- phy-cells: from the generic PHY bindings, must be 1
+- reg: address and length of the register
+- clocks: reference to the clock entry
+
+Sub-nodes:
+Each PHY should be represented as a sub-node.
+
+Sub-nodes required properties:
+- reg: the PHY number
+
+Example:
+	sata_phy: phy@f7e900a0 {
+		compatible = "marvell,berlin2q-sata-phy";
+		reg = <0xf7e900a0 0x200>;
+		clocks = <&chip CLKID_SATA>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#phy-cells = <1>;
+
+		sata-phy@0 {
+			reg = <0>;
+		};
+
+		sata-phy@1 {
+			reg = <1>;
+		};
+	};
-- 
1.7.9.5


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

* [PATCH 21/28] phy: core: Fix of_phy_provider_lookup to return PHY provider for sub node
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (19 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 20/28] Documentation: bindings: add " Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 22/28] phy: core: Let node ptr of PHY point to PHY and not of PHY provider Kishon Vijay Abraham I
                   ` (7 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

Fixed of_phy_provider_lookup to return 'phy_provider' if _of_phy_get
passes the node pointer of the sub-node of phy provider node. This is
needed when phy provider implements multiple PHYs and each PHY is
modelled as the sub-node of PHY provider device node.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
 drivers/phy/phy-core.c |    5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index 75c9739..527e744 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -87,10 +87,15 @@ static struct phy *phy_lookup(struct device *device, const char *port)
 static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
 {
 	struct phy_provider *phy_provider;
+	struct device_node *child;
 
 	list_for_each_entry(phy_provider, &phy_provider_list, list) {
 		if (phy_provider->dev->of_node == node)
 			return phy_provider;
+
+		for_each_child_of_node(phy_provider->dev->of_node, child)
+			if (child == node)
+				return phy_provider;
 	}
 
 	return ERR_PTR(-EPROBE_DEFER);
-- 
1.7.9.5


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

* [PATCH 22/28] phy: core: Let node ptr of PHY point to PHY and not of PHY provider
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (20 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 21/28] phy: core: Fix of_phy_provider_lookup to return PHY provider for sub node Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 23/28] phy: qcom-apq8064: fix possible timeout without check Kishon Vijay Abraham I
                   ` (6 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

In case of multi-phy PHY providers, each PHY should be modeled as a sub
node of the PHY provider. Then each PHY will have a different node pointer
(node pointer of sub node) than that of PHY provider. Added this provision
in the PHY core.
Also fixed all drivers to use the updated API.

Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Acked-by: Lee Jones <lee.jones@linaro.org>
---
 Documentation/phy.txt               |   10 ++++++----
 drivers/phy/phy-bcm-kona-usb2.c     |    2 +-
 drivers/phy/phy-berlin-sata.c       |    2 +-
 drivers/phy/phy-core.c              |   25 ++++++++++++++++++-------
 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-mvebu-sata.c        |    2 +-
 drivers/phy/phy-omap-usb2.c         |    2 +-
 drivers/phy/phy-qcom-apq8064-sata.c |    3 ++-
 drivers/phy/phy-samsung-usb2.c      |    3 ++-
 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 +-
 include/linux/phy/phy.h             |   15 ++++++++++-----
 18 files changed, 52 insertions(+), 31 deletions(-)

diff --git a/Documentation/phy.txt b/Documentation/phy.txt
index ebff6ee..c6594af 100644
--- a/Documentation/phy.txt
+++ b/Documentation/phy.txt
@@ -53,10 +53,12 @@ unregister the PHY.
 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, const struct phy_ops *ops,
-        struct phy_init_data *init_data);
-struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
-	struct phy_init_data *init_data);
+struct phy *phy_create(struct device *dev, struct device_node *node,
+		       const struct phy_ops *ops,
+		       struct phy_init_data *init_data);
+struct phy *devm_phy_create(struct device *dev, struct device_node *node,
+			    const struct phy_ops *ops,
+			    struct phy_init_data *init_data);
 
 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.
diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c
index e94f5a6..894fe74 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, &ops, NULL);
+	gphy = devm_phy_create(dev, NULL, &ops, NULL);
 	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 c5e688b..5c3a042 100644
--- a/drivers/phy/phy-berlin-sata.c
+++ b/drivers/phy/phy-berlin-sata.c
@@ -239,7 +239,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
 		if (!phy_desc)
 			return -ENOMEM;
 
-		phy = devm_phy_create(dev, &phy_berlin_sata_ops, NULL);
+		phy = devm_phy_create(dev, NULL, &phy_berlin_sata_ops, NULL);
 		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-core.c b/drivers/phy/phy-core.c
index 527e744..ff5eec5 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -415,13 +415,20 @@ 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)
+		if (node != phy->dev.of_node) {
+			for_each_child_of_node(node, child) {
+				if (child == phy->dev.of_node)
+					goto phy_found;
+			}
 			continue;
+		}
 
+phy_found:
 		class_dev_iter_exit(&iter);
 		return phy;
 	}
@@ -579,13 +586,15 @@ EXPORT_SYMBOL_GPL(devm_of_phy_get);
 /**
  * phy_create() - create a new phy
  * @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, const struct phy_ops *ops,
-	struct phy_init_data *init_data)
+struct phy *phy_create(struct device *dev, struct device_node *node,
+		       const struct phy_ops *ops,
+		       struct phy_init_data *init_data)
 {
 	int ret;
 	int id;
@@ -620,7 +629,7 @@ struct phy *phy_create(struct device *dev, const struct phy_ops *ops,
 
 	phy->dev.class = phy_class;
 	phy->dev.parent = dev;
-	phy->dev.of_node = dev->of_node;
+	phy->dev.of_node = node ?: dev->of_node;
 	phy->id = id;
 	phy->ops = ops;
 	phy->init_data = init_data;
@@ -656,6 +665,7 @@ EXPORT_SYMBOL_GPL(phy_create);
 /**
  * devm_phy_create() - create a new phy
  * @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
  *
@@ -664,8 +674,9 @@ EXPORT_SYMBOL_GPL(phy_create);
  * On driver detach, release function is invoked on the devres data,
  * then, devres data is freed.
  */
-struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
-	struct phy_init_data *init_data)
+struct phy *devm_phy_create(struct device *dev, struct device_node *node,
+			    const struct phy_ops *ops,
+			    struct phy_init_data *init_data)
 {
 	struct phy **ptr, *phy;
 
@@ -673,7 +684,7 @@ struct phy *devm_phy_create(struct device *dev, const struct phy_ops *ops,
 	if (!ptr)
 		return ERR_PTR(-ENOMEM);
 
-	phy = phy_create(dev, ops, init_data);
+	phy = phy_create(dev, node, ops, init_data);
 	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 098f822..8b3026e 100644
--- a/drivers/phy/phy-exynos-dp-video.c
+++ b/drivers/phy/phy-exynos-dp-video.c
@@ -77,7 +77,7 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev)
 	if (IS_ERR(state->regs))
 		return PTR_ERR(state->regs);
 
-	phy = devm_phy_create(dev, &exynos_dp_video_phy_ops, NULL);
+	phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops, NULL);
 	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 6d6bcf5..b55a92e 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -136,7 +136,7 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
 	spin_lock_init(&state->slock);
 
 	for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
-		struct phy *phy = devm_phy_create(dev,
+		struct phy *phy = devm_phy_create(dev, NULL,
 					&exynos_mipi_video_phy_ops, NULL);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "failed to create PHY %d\n", i);
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index 205159d..b05302b 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -635,7 +635,8 @@ static int exynos5_usbdrd_phy_probe(struct platform_device *pdev)
 	dev_vdbg(dev, "Creating usbdrd_phy phy\n");
 
 	for (i = 0; i < EXYNOS5_DRDPHYS_NUM; i++) {
-		struct phy *phy = devm_phy_create(dev, &exynos5_usbdrd_phy_ops,
+		struct phy *phy = devm_phy_create(dev, NULL,
+						  &exynos5_usbdrd_phy_ops,
 						  NULL);
 		if (IS_ERR(phy)) {
 			dev_err(dev, "Failed to create usbdrd_phy phy\n");
diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c
index 0568945..19a679a 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, &exynos_sata_phy_ops, NULL);
+	sata_phy->phy = devm_phy_create(dev, NULL, &exynos_sata_phy_ops, NULL);
 	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 d442834..6a08fa5 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, &hix5hd2_sata_phy_ops, NULL);
+	phy = devm_phy_create(dev, NULL, &hix5hd2_sata_phy_ops, NULL);
 	if (IS_ERR(phy)) {
 		dev_err(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 d70ecd6..cc3c0e1 100644
--- a/drivers/phy/phy-mvebu-sata.c
+++ b/drivers/phy/phy-mvebu-sata.c
@@ -99,7 +99,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, &phy_mvebu_sata_ops, NULL);
+	phy = devm_phy_create(&pdev->dev, NULL, &phy_mvebu_sata_ops, NULL);
 	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 34b3961..93d7835 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -263,7 +263,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
 
 	platform_set_drvdata(pdev, phy);
 
-	generic_phy = devm_phy_create(phy->dev, &ops, NULL);
+	generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
 	if (IS_ERR(generic_phy))
 		return PTR_ERR(generic_phy);
 
diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c
index c9b4dd6..d7c01aa 100644
--- a/drivers/phy/phy-qcom-apq8064-sata.c
+++ b/drivers/phy/phy-qcom-apq8064-sata.c
@@ -228,7 +228,8 @@ 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, &qcom_apq8064_sata_phy_ops, NULL);
+	generic_phy = devm_phy_create(dev, NULL, &qcom_apq8064_sata_phy_ops,
+				      NULL);
 	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-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index 16aae7a..ae30640 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -196,7 +196,8 @@ 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, &samsung_usb2_phy_ops, NULL);
+		p->phy = devm_phy_create(dev, NULL, &samsung_usb2_phy_ops,
+					 NULL);
 		if (IS_ERR(p->phy)) {
 			dev_err(drv->dev, "Failed to create usb2_phy \"%s\"\n",
 				label);
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c
index 7a4ea55..61ebea4 100644
--- a/drivers/phy/phy-sun4i-usb.c
+++ b/drivers/phy/phy-sun4i-usb.c
@@ -295,7 +295,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev)
 				return PTR_ERR(phy->pmu);
 		}
 
-		phy->phy = devm_phy_create(dev, &sun4i_usb_phy_ops, NULL);
+		phy->phy = devm_phy_create(dev, NULL, &sun4i_usb_phy_ops, NULL);
 		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 93bcd67..b964aa9 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -400,7 +400,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, &ops, NULL);
+	generic_phy = devm_phy_create(phy->dev, NULL, &ops, NULL);
 	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 2e0e9b3..e1a6623 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -695,7 +695,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, &ops, init_data);
+	phy = devm_phy_create(twl->dev, NULL, &ops, init_data);
 	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 4aa1ccd..db809b9 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, &xgene_phy_ops, NULL);
+	ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops, NULL);
 	if (IS_ERR(ctx->phy)) {
 		dev_dbg(&pdev->dev, "Failed to create PHY\n");
 		rc = PTR_ERR(ctx->phy);
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 9a86945..8cb6f81 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -158,9 +158,10 @@ void devm_phy_put(struct device *dev, struct phy *phy);
 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, const struct phy_ops *ops,
-	struct phy_init_data *init_data);
-struct phy *devm_phy_create(struct device *dev,
+struct phy *phy_create(struct device *dev, struct device_node *node,
+		       const struct phy_ops *ops,
+		       struct phy_init_data *init_data);
+struct phy *devm_phy_create(struct device *dev, struct device_node *node,
 	const struct phy_ops *ops, struct phy_init_data *init_data);
 void phy_destroy(struct phy *phy);
 void devm_phy_destroy(struct device *dev, struct phy *phy);
@@ -299,13 +300,17 @@ static inline struct phy *of_phy_simple_xlate(struct device *dev,
 }
 
 static inline struct phy *phy_create(struct device *dev,
-	const struct phy_ops *ops, struct phy_init_data *init_data)
+				     struct device_node *node,
+				     const struct phy_ops *ops,
+				     struct phy_init_data *init_data)
 {
 	return ERR_PTR(-ENOSYS);
 }
 
 static inline struct phy *devm_phy_create(struct device *dev,
-	const struct phy_ops *ops, struct phy_init_data *init_data)
+					  struct device_node *node,
+					  const struct phy_ops *ops,
+					  struct phy_init_data *init_data)
 {
 	return ERR_PTR(-ENOSYS);
 }
-- 
1.7.9.5


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

* [PATCH 23/28] phy: qcom-apq8064: fix possible timeout without check
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (21 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 22/28] phy: core: Let node ptr of PHY point to PHY and not of PHY provider Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 24/28] phy: qcom: Add driver for QCOM IPQ806x SATA PHY Kishon Vijay Abraham I
                   ` (5 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>

This patch fixes a possible timeout in poll loop without actually
checking the register before return. In theory the there is a possibility
of loop being scheduled after a long lock/delay, which would then force
the loop to exit without actually checking the register.

Reported-by: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-qcom-apq8064-sata.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c
index d7c01aa..b3ef7d8 100644
--- a/drivers/phy/phy-qcom-apq8064-sata.c
+++ b/drivers/phy/phy-qcom-apq8064-sata.c
@@ -91,7 +91,7 @@ static int read_poll_timeout(void __iomem *addr, u32 mask)
 		 usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50);
 	} while (!time_after(jiffies, timeout));
 
-	return -ETIMEDOUT;
+	return (readl_relaxed(addr) & mask) ? 0 : -ETIMEDOUT;
 }
 
 static int qcom_apq8064_sata_phy_init(struct phy *generic_phy)
-- 
1.7.9.5


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

* [PATCH 24/28] phy: qcom: Add driver for QCOM IPQ806x SATA PHY
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (22 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 23/28] phy: qcom-apq8064: fix possible timeout without check Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 25/28] phy: qcom: Add device tree bindings for " Kishon Vijay Abraham I
                   ` (4 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Kumar Gala <galak@codeaurora.org>

Add a PHY driver for uses with AHCI based SATA controller driver on the
IPQ806x family of SoCs.

Signed-off-by: Kumar Gala <galak@codeaurora.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig                 |    7 ++
 drivers/phy/Makefile                |    1 +
 drivers/phy/phy-qcom-ipq806x-sata.c |  211 +++++++++++++++++++++++++++++++++++
 3 files changed, 219 insertions(+)
 create mode 100644 drivers/phy/phy-qcom-ipq806x-sata.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 1704fd4..3e251aa 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -191,4 +191,11 @@ config PHY_QCOM_APQ8064_SATA
 	depends on OF
 	select GENERIC_PHY
 
+config PHY_QCOM_IPQ806X_SATA
+	tristate "Qualcomm IPQ806x SATA SerDes/PHY driver"
+	depends on ARCH_QCOM
+	depends on HAS_IOMEM
+	depends on OF
+	select GENERIC_PHY
+
 endmenu
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 3c2ad59..54ab978 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -23,3 +23,4 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2)	+= phy-exynos5250-usb2.o
 obj-$(CONFIG_PHY_EXYNOS5_USBDRD)	+= phy-exynos5-usbdrd.o
 obj-$(CONFIG_PHY_XGENE)			+= phy-xgene.o
 obj-$(CONFIG_PHY_QCOM_APQ8064_SATA)	+= phy-qcom-apq8064-sata.o
+obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA)	+= phy-qcom-ipq806x-sata.o
diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c
new file mode 100644
index 0000000..909b5a8
--- /dev/null
+++ b/drivers/phy/phy-qcom-ipq806x-sata.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/phy/phy.h>
+
+struct qcom_ipq806x_sata_phy {
+	void __iomem *mmio;
+	struct clk *cfg_clk;
+	struct device *dev;
+};
+
+#define __set(v, a, b)	(((v) << (b)) & GENMASK(a, b))
+
+#define SATA_PHY_P0_PARAM0		0x200
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(x)	__set(x, 17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK	GENMASK(17, 12)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2(x)	__set(x, 11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK	GENMASK(11, 6)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1(x)	__set(x, 5, 0)
+#define SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK	GENMASK(5, 0)
+
+#define SATA_PHY_P0_PARAM1		0x204
+#define SATA_PHY_P0_PARAM1_RESERVED_BITS31_21(x)	__set(x, 31, 21)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(x)	__set(x, 20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK	GENMASK(20, 14)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(x)	__set(x, 13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK	GENMASK(13, 7)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(x)	__set(x, 6, 0)
+#define SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK	GENMASK(6, 0)
+
+#define SATA_PHY_P0_PARAM2		0x208
+#define SATA_PHY_P0_PARAM2_RX_EQ(x)	__set(x, 20, 18)
+#define SATA_PHY_P0_PARAM2_RX_EQ_MASK	GENMASK(20, 18)
+
+#define SATA_PHY_P0_PARAM3		0x20C
+#define SATA_PHY_SSC_EN			0x8
+#define SATA_PHY_P0_PARAM4		0x210
+#define SATA_PHY_REF_SSP_EN		0x2
+#define SATA_PHY_RESET			0x1
+
+static int qcom_ipq806x_sata_phy_init(struct phy *generic_phy)
+{
+	struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+	u32 reg;
+
+	/* Setting SSC_EN to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM3);
+	reg = reg | SATA_PHY_SSC_EN;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM3);
+
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM0) &
+			~(SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3_MASK |
+			  SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN2_MASK |
+			  SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN1_MASK);
+	reg |= SATA_PHY_P0_PARAM0_P0_TX_PREEMPH_GEN3(0xf);
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM0);
+
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM1) &
+			~(SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3_MASK |
+			  SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2_MASK |
+			  SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1_MASK);
+	reg |= SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN3(0x55) |
+		SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN2(0x55) |
+		SATA_PHY_P0_PARAM1_P0_TX_AMPLITUDE_GEN1(0x55);
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM1);
+
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM2) &
+		~SATA_PHY_P0_PARAM2_RX_EQ_MASK;
+	reg |= SATA_PHY_P0_PARAM2_RX_EQ(0x3);
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM2);
+
+	/* Setting PHY_RESET to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg | SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	/* Setting REF_SSP_EN to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg | SATA_PHY_REF_SSP_EN | SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	/* make sure all changes complete before we let the PHY out of reset */
+	mb();
+
+	/* sleep for max. 50us more to combine processor wakeups */
+	usleep_range(20, 20 + 50);
+
+	/* Clearing PHY_RESET to 0 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg & ~SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	return 0;
+}
+
+static int qcom_ipq806x_sata_phy_exit(struct phy *generic_phy)
+{
+	struct qcom_ipq806x_sata_phy *phy = phy_get_drvdata(generic_phy);
+	u32 reg;
+
+	/* Setting PHY_RESET to 1 */
+	reg = readl_relaxed(phy->mmio + SATA_PHY_P0_PARAM4);
+	reg = reg | SATA_PHY_RESET;
+	writel_relaxed(reg, phy->mmio + SATA_PHY_P0_PARAM4);
+
+	return 0;
+}
+
+static struct phy_ops qcom_ipq806x_sata_phy_ops = {
+	.init		= qcom_ipq806x_sata_phy_init,
+	.exit		= qcom_ipq806x_sata_phy_exit,
+	.owner		= THIS_MODULE,
+};
+
+static int qcom_ipq806x_sata_phy_probe(struct platform_device *pdev)
+{
+	struct qcom_ipq806x_sata_phy *phy;
+	struct device *dev = &pdev->dev;
+	struct resource *res;
+	struct phy_provider *phy_provider;
+	struct phy *generic_phy;
+	int ret;
+
+	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
+	if (!phy)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	phy->mmio = devm_ioremap_resource(dev, res);
+	if (IS_ERR(phy->mmio))
+		return PTR_ERR(phy->mmio);
+
+	generic_phy = devm_phy_create(dev, NULL, &qcom_ipq806x_sata_phy_ops,
+				      NULL);
+	if (IS_ERR(generic_phy)) {
+		dev_err(dev, "%s: failed to create phy\n", __func__);
+		return PTR_ERR(generic_phy);
+	}
+
+	phy->dev = dev;
+	phy_set_drvdata(generic_phy, phy);
+	platform_set_drvdata(pdev, phy);
+
+	phy->cfg_clk = devm_clk_get(dev, "cfg");
+	if (IS_ERR(phy->cfg_clk)) {
+		dev_err(dev, "Failed to get sata cfg clock\n");
+		return PTR_ERR(phy->cfg_clk);
+	}
+
+	ret = clk_prepare_enable(phy->cfg_clk);
+	if (ret)
+		return ret;
+
+	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
+	if (IS_ERR(phy_provider)) {
+		clk_disable_unprepare(phy->cfg_clk);
+		dev_err(dev, "%s: failed to register phy\n", __func__);
+		return PTR_ERR(phy_provider);
+	}
+
+	return 0;
+}
+
+static int qcom_ipq806x_sata_phy_remove(struct platform_device *pdev)
+{
+	struct qcom_ipq806x_sata_phy *phy = platform_get_drvdata(pdev);
+
+	clk_disable_unprepare(phy->cfg_clk);
+
+	return 0;
+}
+
+static const struct of_device_id qcom_ipq806x_sata_phy_of_match[] = {
+	{ .compatible = "qcom,ipq806x-sata-phy" },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, qcom_ipq806x_sata_phy_of_match);
+
+static struct platform_driver qcom_ipq806x_sata_phy_driver = {
+	.probe	= qcom_ipq806x_sata_phy_probe,
+	.remove	= qcom_ipq806x_sata_phy_remove,
+	.driver = {
+		.name	= "qcom-ipq806x-sata-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= qcom_ipq806x_sata_phy_of_match,
+	}
+};
+module_platform_driver(qcom_ipq806x_sata_phy_driver);
+
+MODULE_DESCRIPTION("QCOM IPQ806x SATA PHY driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5


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

* [PATCH 25/28] phy: qcom: Add device tree bindings for IPQ806x SATA PHY
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (23 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 24/28] phy: qcom: Add driver for QCOM IPQ806x SATA PHY Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 26/28] phy: miphy365x: Add Device Tree bindings for the MiPHY365x Kishon Vijay Abraham I
                   ` (3 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Kumar Gala <galak@codeaurora.org>

Add binding spec for Qualcomm SoC PHYs, starting with the SATA PHY on
the IPQ806x family of SoCs.

Signed-off-by: Kumar Gala <galak@codeaurora.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../bindings/phy/qcom-ipq806x-sata-phy.txt         |   23 ++++++++++++++++++++
 1 file changed, 23 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt

diff --git a/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt b/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt
new file mode 100644
index 0000000..76bfbd0
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/qcom-ipq806x-sata-phy.txt
@@ -0,0 +1,23 @@
+Qualcomm IPQ806x SATA PHY Controller
+------------------------------------
+
+SATA PHY nodes are defined to describe on-chip SATA Physical layer controllers.
+Each SATA PHY controller should have its own node.
+
+Required properties:
+- compatible: compatible list, contains "qcom,ipq806x-sata-phy"
+- reg: offset and length of the SATA PHY register set;
+- #phy-cells: must be zero
+- clocks: must be exactly one entry
+- clock-names: must be "cfg"
+
+Example:
+	sata_phy: sata-phy@1b400000 {
+		compatible = "qcom,ipq806x-sata-phy";
+		reg = <0x1b400000 0x200>;
+
+		clocks = <&gcc SATA_PHY_CFG_CLK>;
+		clock-names = "cfg";
+
+		#phy-cells = <0>;
+	};
-- 
1.7.9.5


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

* [PATCH 26/28] phy: miphy365x: Add Device Tree bindings for the MiPHY365x
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (24 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 25/28] phy: qcom: Add device tree bindings for " Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 10:56 ` [PATCH 27/28] phy: miphy365x: Provide support for the MiPHY356x Generic PHY Kishon Vijay Abraham I
                   ` (2 subsequent siblings)
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Lee Jones <lee.jones@linaro.org>

The MiPHY365x is a Generic PHY which can serve various SATA or PCIe
devices. It has 2 ports which it can use for either; both SATA, both
PCIe or one of each in any configuration.

Acked-by: Mark Rutland <mark.rutland@arm.com>
Acked-by: Alexandre Torgue <alexandre.torgue@st.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 .../devicetree/bindings/phy/phy-miphy365x.txt      |   76 ++++++++++++++++++++
 1 file changed, 76 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/phy/phy-miphy365x.txt

diff --git a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
new file mode 100644
index 0000000..42c8808
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
@@ -0,0 +1,76 @@
+STMicroelectronics STi MIPHY365x PHY binding
+============================================
+
+This binding describes a miphy device that is used to control PHY hardware
+for SATA and PCIe.
+
+Required properties (controller (parent) node):
+- compatible    : Should be "st,miphy365x-phy"
+- st,syscfg     : Should be a phandle of the system configuration register group
+		  which contain the SATA, PCIe 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:
+			- MIPHY_TYPE_SATA
+			- MIPHY_TYPE_PCI
+- reg        	: Address and length of register sets for each device in
+		  "reg-names"
+- reg-names     : The names of the register addresses corresponding to the
+		  registers filled in "reg":
+			- sata:   For SATA devices
+			- pcie:   For PCIe devices
+			- syscfg: To specify the syscfg based config register
+
+Optional properties (port (child) node):
+- st,sata-gen	     :	Generation of locally attached SATA IP. Expected values
+			are {1,2,3). If not supplied generation 1 hardware will
+			be expected
+- st,pcie-tx-pol-inv :	Bool property to invert the polarity PCIe Tx (Txn/Txp)
+- st,sata-tx-pol-inv :	Bool property to invert the polarity SATA Tx (Txn/Txp)
+
+Example:
+
+	miphy365x_phy: miphy365x@fe382000 {
+		compatible      = "st,miphy365x-phy";
+		st,syscfg  	= <&syscfg_rear>;
+		#address-cells	= <1>;
+		#size-cells	= <1>;
+		ranges;
+
+		phy_port0: port@fe382000 {
+			reg = <0xfe382000 0x100>, <0xfe394000 0x100>, <0x824 0x4>;
+			reg-names = "sata", "pcie", "syscfg";
+			#phy-cells = <1>;
+			st,sata-gen = <3>;
+		};
+
+		phy_port1: port@fe38a000 {
+			reg = <0xfe38a000 0x100>, <0xfe804000 0x100>, <0x828 0x4>;;
+			reg-names = "sata", "pcie", "syscfg";
+			#phy-cells = <1>;
+			st,pcie-tx-pol-inv;
+		};
+	};
+
+Specifying phy control of devices
+=================================
+
+Device nodes should specify the configuration required in their "phys"
+property, containing a phandle to the phy port node and a device type.
+
+Example:
+
+#include <dt-bindings/phy/phy-miphy365x.h>
+
+	sata0: sata@fe380000 {
+		...
+		phys	  = <&phy_port0 MIPHY_TYPE_SATA>;
+		...
+	};
-- 
1.7.9.5


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

* [PATCH 27/28] phy: miphy365x: Provide support for the MiPHY356x Generic PHY
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (25 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 26/28] phy: miphy365x: Add Device Tree bindings for the MiPHY365x Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-24 10:36   ` Paul Bolle
  2014-07-22 10:56 ` [PATCH 28/28] phy: miphy365x: Represent each PHY channel as a DT subnode Kishon Vijay Abraham I
  2014-07-22 23:33 ` [GIT PULL 00/28] PHY: for 3.17 Greg KH
  28 siblings, 1 reply; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Lee Jones <lee.jones@linaro.org>

The MiPHY365x is a Generic PHY which can serve various SATA or PCIe
devices. It has 2 ports which it can use for either; both SATA, both
PCIe or one of each in any configuration.

Acked-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Alexandre Torgue <alexandre.torgue@st.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/Kconfig         |   10 +
 drivers/phy/Makefile        |    1 +
 drivers/phy/phy-miphy365x.c |  616 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 627 insertions(+)
 create mode 100644 drivers/phy/phy-miphy365x.c

diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 3e251aa..cc97c89 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -38,6 +38,16 @@ config PHY_MVEBU_SATA
 	depends on OF
 	select GENERIC_PHY
 
+config PHY_MIPHY365X
+	tristate "STMicroelectronics MIPHY365X PHY driver for STiH41x series"
+	depends on ARCH_STI
+	depends on GENERIC_PHY
+	depends on HAS_IOMEM
+	depends on OF
+	help
+	  Enable this to support the miphy transceiver (for SATA/PCIE)
+	  that is part of STMicroelectronics STiH41x SoC series.
+
 config OMAP_CONTROL_PHY
 	tristate "OMAP CONTROL PHY Driver"
 	depends on ARCH_OMAP2PLUS || COMPILE_TEST
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index 54ab978..971ad0a 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_MIPHY365X)		+= phy-miphy365x.o
 obj-$(CONFIG_OMAP_CONTROL_PHY)		+= phy-omap-control.o
 obj-$(CONFIG_OMAP_USB2)			+= phy-omap-usb2.o
 obj-$(CONFIG_TI_PIPE3)			+= phy-ti-pipe3.o
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
new file mode 100644
index 0000000..65ecd04
--- /dev/null
+++ b/drivers/phy/phy-miphy365x.c
@@ -0,0 +1,616 @@
+/*
+ * Copyright (C) 2014 STMicroelectronics – All Rights Reserved
+ *
+ * STMicroelectronics PHY driver MiPHY365 (for SoC STiH416).
+ *
+ * Authors: Alexandre Torgue <alexandre.torgue@st.com>
+ *          Lee Jones <lee.jones@linaro.org>
+ *
+ * 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/clk.h>
+#include <linux/phy/phy.h>
+#include <linux/delay.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/phy/phy-miphy365x.h>
+
+#define HFC_TIMEOUT		100
+
+#define SYSCFG_2521		0x824
+#define SYSCFG_2522		0x828
+#define SYSCFG_PCIE_SATA_MASK	BIT(1)
+#define SYSCFG_PCIE_SATA_POS	1
+
+/* MiPHY365x register definitions */
+#define RESET_REG		0x00
+#define RST_PLL			BIT(1)
+#define RST_PLL_CAL		BIT(2)
+#define RST_RX			BIT(4)
+#define RST_MACRO		BIT(7)
+
+#define STATUS_REG		0x01
+#define IDLL_RDY		BIT(0)
+#define PLL_RDY			BIT(1)
+#define DES_BIT_LOCK		BIT(2)
+#define DES_SYMBOL_LOCK		BIT(3)
+
+#define CTRL_REG		0x02
+#define TERM_EN			BIT(0)
+#define PCI_EN			BIT(2)
+#define DES_BIT_LOCK_EN		BIT(3)
+#define TX_POL			BIT(5)
+
+#define INT_CTRL_REG		0x03
+
+#define BOUNDARY1_REG		0x10
+#define SPDSEL_SEL		BIT(0)
+
+#define BOUNDARY3_REG		0x12
+#define TX_SPDSEL_GEN1_VAL	0
+#define TX_SPDSEL_GEN2_VAL	0x01
+#define TX_SPDSEL_GEN3_VAL	0x02
+#define RX_SPDSEL_GEN1_VAL	0
+#define RX_SPDSEL_GEN2_VAL	(0x01 << 3)
+#define RX_SPDSEL_GEN3_VAL	(0x02 << 3)
+
+#define PCIE_REG		0x16
+
+#define BUF_SEL_REG		0x20
+#define CONF_GEN_SEL_GEN3	0x02
+#define CONF_GEN_SEL_GEN2	0x01
+#define PD_VDDTFILTER		BIT(4)
+
+#define TXBUF1_REG		0x21
+#define SWING_VAL		0x04
+#define SWING_VAL_GEN1		0x03
+#define PREEMPH_VAL		(0x3 << 5)
+
+#define TXBUF2_REG		0x22
+#define TXSLEW_VAL		0x2
+#define TXSLEW_VAL_GEN1		0x4
+
+#define RXBUF_OFFSET_CTRL_REG	0x23
+
+#define RXBUF_REG		0x25
+#define SDTHRES_VAL		0x01
+#define EQ_ON3			(0x03 << 4)
+#define EQ_ON1			(0x01 << 4)
+
+#define COMP_CTRL1_REG		0x40
+#define START_COMSR		BIT(0)
+#define START_COMZC		BIT(1)
+#define COMSR_DONE		BIT(2)
+#define COMZC_DONE		BIT(3)
+#define COMP_AUTO_LOAD		BIT(4)
+
+#define COMP_CTRL2_REG		0x41
+#define COMP_2MHZ_RAT_GEN1	0x1e
+#define COMP_2MHZ_RAT		0xf
+
+#define COMP_CTRL3_REG		0x42
+#define COMSR_COMP_REF		0x33
+
+#define COMP_IDLL_REG		0x47
+#define COMZC_IDLL		0x2a
+
+#define PLL_CTRL1_REG		0x50
+#define PLL_START_CAL		BIT(0)
+#define BUF_EN			BIT(2)
+#define SYNCHRO_TX		BIT(3)
+#define SSC_EN			BIT(6)
+#define CONFIG_PLL		BIT(7)
+
+#define PLL_CTRL2_REG		0x51
+#define BYPASS_PLL_CAL		BIT(1)
+
+#define PLL_RAT_REG		0x52
+
+#define PLL_SSC_STEP_MSB_REG	0x56
+#define PLL_SSC_STEP_MSB_VAL	0x03
+
+#define PLL_SSC_STEP_LSB_REG	0x57
+#define PLL_SSC_STEP_LSB_VAL	0x63
+
+#define PLL_SSC_PER_MSB_REG	0x58
+#define PLL_SSC_PER_MSB_VAL	0
+
+#define PLL_SSC_PER_LSB_REG	0x59
+#define PLL_SSC_PER_LSB_VAL	0xf1
+
+#define IDLL_TEST_REG		0x72
+#define START_CLK_HF		BIT(6)
+
+#define DES_BITLOCK_REG		0x86
+#define BIT_LOCK_LEVEL		0x01
+#define BIT_LOCK_CNT_512	(0x03 << 5)
+
+static u8 ports[] = { MIPHY_PORT_0, MIPHY_PORT_1 };
+
+struct miphy365x_phy {
+	struct phy *phy;
+	void __iomem *base;
+	void __iomem *sata;
+	void __iomem *pcie;
+	u8 type;
+	u8 port;
+};
+
+struct miphy365x_dev {
+	struct device *dev;
+	struct regmap *regmap;
+	struct mutex miphy_mutex;
+	struct miphy365x phys[ARRAY_SIZE(ports)];
+	bool pcie_tx_pol_inv;
+	bool sata_tx_pol_inv;
+	u32 sata_gen;
+};
+
+/*
+ * These values are represented in Device tree. They are considered to be ABI
+ * and although they can be extended any existing values must not change.
+ */
+enum miphy_sata_gen {
+	SATA_GEN1 = 1,
+	SATA_GEN2,
+	SATA_GEN3
+};
+
+static u8 rx_tx_spd[] = {
+	TX_SPDSEL_GEN1_VAL | RX_SPDSEL_GEN1_VAL,
+	TX_SPDSEL_GEN2_VAL | RX_SPDSEL_GEN2_VAL,
+	TX_SPDSEL_GEN3_VAL | RX_SPDSEL_GEN3_VAL
+};
+
+/*
+ * This function selects the system configuration,
+ * either two SATA, one SATA and one PCIe, or two PCIe lanes.
+ */
+static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
+			      struct miphy365x_dev *miphy_dev)
+{
+	u8 config = miphy_phy->type | miphy_phy->port;
+	u32 mask  = SYSCFG_PCIE_SATA_MASK;
+	u32 reg;
+	bool sata;
+
+	switch (config) {
+	case MIPHY_SATA_PORT0:
+		reg = SYSCFG_2521;
+		sata = true;
+		break;
+	case MIPHY_PCIE_PORT1:
+		reg = SYSCFG_2522;
+		sata = false;
+		break;
+	default:
+		dev_err(miphy_dev->dev, "Configuration not supported\n");
+		return -EINVAL;
+	}
+
+	return regmap_update_bits(miphy_dev->regmap, reg, mask,
+				  sata << SYSCFG_PCIE_SATA_POS);
+}
+
+static int miphy365x_init_pcie_port(struct miphy365x_phy *miphy_phy,
+				    struct miphy365x_dev *miphy_dev)
+{
+	u8 val;
+
+	if (miphy_phy->pcie_tx_pol_inv) {
+		/* Invert Tx polarity and clear pci_txdetect_pol bit */
+		val = TERM_EN | PCI_EN | DES_BIT_LOCK_EN | TX_POL;
+		writeb_relaxed(val, miphy_phy->base + CTRL_REG);
+		writeb_relaxed(0x00, miphy_phy->base + PCIE_REG);
+	}
+
+	return 0;
+}
+
+static inline int miphy365x_hfc_not_rdy(struct miphy365x_phy *miphy_phy,
+					struct miphy365x_dev *miphy_dev)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
+	u8 mask = IDLL_RDY | PLL_RDY;
+	u8 regval;
+
+	do {
+		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
+		if (!(regval & mask))
+			return 0;
+
+		usleep_range(2000, 2500);
+	} while (time_before(jiffies, timeout));
+
+	dev_err(miphy_dev->dev, "HFC ready timeout!\n");
+	return -EBUSY;
+}
+
+static inline int miphy365x_rdy(struct miphy365x_phy *miphy_phy,
+				struct miphy365x_dev *miphy_dev)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(HFC_TIMEOUT);
+	u8 mask = IDLL_RDY | PLL_RDY;
+	u8 regval;
+
+	do {
+		regval = readb_relaxed(miphy_phy->base + STATUS_REG);
+		if ((regval & mask) == mask)
+			return 0;
+
+		usleep_range(2000, 2500);
+	} while (time_before(jiffies, timeout));
+
+	dev_err(miphy_dev->dev, "PHY not ready timeout!\n");
+	return -EBUSY;
+}
+
+static inline void miphy365x_set_comp(struct miphy365x_phy *miphy_phy,
+				      struct miphy365x_dev *miphy_dev)
+{
+	u8 val, mask;
+
+	if (miphy_dev->sata_gen == SATA_GEN1)
+		writeb_relaxed(COMP_2MHZ_RAT_GEN1,
+			       miphy_phy->base + COMP_CTRL2_REG);
+	else
+		writeb_relaxed(COMP_2MHZ_RAT,
+			       miphy_phy->base + COMP_CTRL2_REG);
+
+	if (miphy_dev->sata_gen != SATA_GEN3) {
+		writeb_relaxed(COMSR_COMP_REF,
+			       miphy_phy->base + COMP_CTRL3_REG);
+		/*
+		 * Force VCO current to value defined by address 0x5A
+		 * and disable PCIe100Mref bit
+		 * Enable auto load compensation for pll_i_bias
+		 */
+		writeb_relaxed(BYPASS_PLL_CAL, miphy_phy->base + PLL_CTRL2_REG);
+		writeb_relaxed(COMZC_IDLL, miphy_phy->base + COMP_IDLL_REG);
+	}
+
+	/*
+	 * Force restart compensation and enable auto load
+	 * for Comzc_Tx, Comzc_Rx and Comsr on macro
+	 */
+	val = START_COMSR | START_COMZC | COMP_AUTO_LOAD;
+	writeb_relaxed(val, miphy_phy->base + COMP_CTRL1_REG);
+
+	mask = COMSR_DONE | COMZC_DONE;
+	while ((readb_relaxed(miphy_phy->base + COMP_CTRL1_REG) & mask)	!= mask)
+		cpu_relax();
+}
+
+static inline void miphy365x_set_ssc(struct miphy365x_phy *miphy_phy,
+				     struct miphy365x_dev *miphy_dev)
+{
+	u8 val;
+
+	/*
+	 * SSC Settings. SSC will be enabled through Link
+	 * SSC Ampl. = 0.4%
+	 * SSC Freq = 31KHz
+	 */
+	writeb_relaxed(PLL_SSC_STEP_MSB_VAL,
+		       miphy_phy->base + PLL_SSC_STEP_MSB_REG);
+	writeb_relaxed(PLL_SSC_STEP_LSB_VAL,
+		       miphy_phy->base + PLL_SSC_STEP_LSB_REG);
+	writeb_relaxed(PLL_SSC_PER_MSB_VAL,
+		       miphy_phy->base + PLL_SSC_PER_MSB_REG);
+	writeb_relaxed(PLL_SSC_PER_LSB_VAL,
+		       miphy_phy->base + PLL_SSC_PER_LSB_REG);
+
+	/* SSC Settings complete */
+	if (miphy_dev->sata_gen == SATA_GEN1) {
+		val = PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
+		writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
+	} else {
+		val = SSC_EN | PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
+		writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
+	}
+}
+
+static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
+				    struct miphy365x_dev *miphy_dev)
+{
+	int ret;
+	u8 val;
+
+	/*
+	 * Force PHY macro reset, PLL calibration reset, PLL reset
+	 * and assert Deserializer Reset
+	 */
+	val = RST_PLL | RST_PLL_CAL | RST_RX | RST_MACRO;
+	writeb_relaxed(val, miphy_phy->base + RESET_REG);
+
+	if (miphy_dev->sata_tx_pol_inv)
+		writeb_relaxed(TX_POL, miphy_phy->base + CTRL_REG);
+
+	/*
+	 * Force macro1 to use rx_lspd, tx_lspd
+	 * Force Rx_Clock on first I-DLL phase
+	 * Force Des in HP mode on macro, rx_lspd, tx_lspd for Gen2/3
+	 */
+	writeb_relaxed(SPDSEL_SEL, miphy_phy->base + BOUNDARY1_REG);
+	writeb_relaxed(START_CLK_HF, miphy_phy->base + IDLL_TEST_REG);
+	val = rx_tx_spd[miphy_dev->sata_gen];
+	writeb_relaxed(val, miphy_phy->base + BOUNDARY3_REG);
+
+	/* Wait for HFC_READY = 0 */
+	ret = miphy365x_hfc_not_rdy(miphy_phy, miphy_dev);
+	if (ret)
+		return ret;
+
+	/* Compensation Recalibration */
+	miphy365x_set_comp(miphy_phy, miphy_dev);
+
+	switch (miphy_dev->sata_gen) {
+	case SATA_GEN3:
+		/*
+		 * TX Swing target 550-600mv peak to peak diff
+		 * Tx Slew target 90-110ps rising/falling time
+		 * Rx Eq ON3, Sigdet threshold SDTH1
+		 */
+		val = PD_VDDTFILTER | CONF_GEN_SEL_GEN3;
+		writeb_relaxed(val, miphy_phy->base + BUF_SEL_REG);
+		val = SWING_VAL | PREEMPH_VAL;
+		writeb_relaxed(val, miphy_phy->base + TXBUF1_REG);
+		writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
+		writeb_relaxed(0x00, miphy_phy->base + RXBUF_OFFSET_CTRL_REG);
+		val = SDTHRES_VAL | EQ_ON3;
+		writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
+		break;
+	case SATA_GEN2:
+		/*
+		 * conf gen sel=0x1 to program Gen2 banked registers
+		 * VDDT filter ON
+		 * Tx Swing target 550-600mV peak-to-peak diff
+		 * Tx Slew target 90-110 ps rising/falling time
+		 * RX Equalization ON1, Sigdet threshold SDTH1
+		 */
+		writeb_relaxed(CONF_GEN_SEL_GEN2,
+			       miphy_phy->base + BUF_SEL_REG);
+		writeb_relaxed(SWING_VAL, miphy_phy->base + TXBUF1_REG);
+		writeb_relaxed(TXSLEW_VAL, miphy_phy->base + TXBUF2_REG);
+		val = SDTHRES_VAL | EQ_ON1;
+		writeb_relaxed(val, miphy_phy->base + RXBUF_REG);
+		break;
+	case SATA_GEN1:
+		/*
+		 * conf gen sel = 00b to program Gen1 banked registers
+		 * VDDT filter ON
+		 * Tx Swing target 500-550mV peak-to-peak diff
+		 * Tx Slew target120-140 ps rising/falling time
+		 */
+		writeb_relaxed(PD_VDDTFILTER, miphy_phy->base + BUF_SEL_REG);
+		writeb_relaxed(SWING_VAL_GEN1, miphy_phy->base + TXBUF1_REG);
+		writeb_relaxed(TXSLEW_VAL_GEN1,	miphy_phy->base + TXBUF2_REG);
+		break;
+	default:
+		break;
+	}
+
+	/* Force Macro1 in partial mode & release pll cal reset */
+	writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
+	usleep_range(100, 150);
+
+	miphy365x_set_ssc(miphy_phy, miphy_dev);
+
+	/* Wait for phy_ready */
+	ret = miphy365x_rdy(miphy_phy, miphy_dev);
+	if (ret)
+		return ret;
+
+	/*
+	 * Enable macro1 to use rx_lspd & tx_lspd
+	 * Release Rx_Clock on first I-DLL phase on macro1
+	 * Assert deserializer reset
+	 * des_bit_lock_en is set
+	 * bit lock detection strength
+	 * Deassert deserializer reset
+	 */
+	writeb_relaxed(0x00, miphy_phy->base + BOUNDARY1_REG);
+	writeb_relaxed(0x00, miphy_phy->base + IDLL_TEST_REG);
+	writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
+	val = miphy_dev->sata_tx_pol_inv ?
+		(TX_POL | DES_BIT_LOCK_EN) : DES_BIT_LOCK_EN;
+	writeb_relaxed(val, miphy_phy->base + CTRL_REG);
+
+	val = BIT_LOCK_CNT_512 | BIT_LOCK_LEVEL;
+	writeb_relaxed(val, miphy_phy->base + DES_BITLOCK_REG);
+	writeb_relaxed(0x00, miphy_phy->base + RESET_REG);
+
+	return 0;
+}
+
+static int miphy365x_init(struct phy *phy)
+{
+	struct miphy365x_phy *miphy_phy = phy_get_drvdata(phy);
+	struct miphy365x_dev *miphy_dev = dev_get_drvdata(phy->dev.parent);
+	int ret = 0;
+
+	mutex_lock(&miphy_dev->miphy_mutex);
+
+	ret = miphy365x_set_path(miphy_phy, miphy_dev);
+	if (ret) {
+		mutex_unlock(&miphy_dev->miphy_mutex);
+		return ret;
+	}
+
+	/* Initialise Miphy for PCIe or SATA */
+	if (miphy_phy->type == MIPHY_TYPE_PCIE)
+		ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev);
+	else
+		ret = miphy365x_init_sata_port(miphy_phy, miphy_dev);
+
+	mutex_unlock(&miphy_dev->miphy_mutex);
+
+	return ret;
+}
+
+static struct phy *miphy365x_xlate(struct device *dev,
+				   struct of_phandle_args *args)
+{
+	struct miphy365x_dev *state = dev_get_drvdata(dev);
+	u8 port, type;
+
+	if (args->count != 2) {
+		dev_err(dev, "Invalid number of cells in 'phy' property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	if (args->args[0] & 0xFFFFFF00 || args->args[1] & 0xFFFFFF00) {
+		dev_err(dev, "Unsupported flags set in 'phy' property\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	port = args->args[0];
+	type = args->args[1];
+
+	if (WARN_ON(port >= ARRAY_SIZE(ports)))
+		return ERR_PTR(-EINVAL);
+
+	if (type == MIPHY_TYPE_SATA)
+		state->phys[port].base = state->phys[port].sata;
+	else if (type == MIPHY_TYPE_PCIE)
+		state->phys[port].base = state->phys[port].pcie;
+	else {
+		WARN(1, "Invalid type specified in DT");
+		return ERR_PTR(-EINVAL);
+	}
+
+	state->phys[port].type = type;
+
+	return state->phys[port].phy;
+}
+
+static struct phy_ops miphy365x_ops = {
+	.init		= miphy365x_init,
+	.owner		= THIS_MODULE,
+};
+
+static int miphy365x_get_base_addr(struct platform_device *pdev,
+				   struct miphy365x_phy *phy, u8 port)
+{
+	struct resource *res;
+	char type[6];
+
+	sprintf(type, "sata%d", port);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, type);
+	phy->sata = devm_ioremap_resource(&pdev->dev, res));
+	if (!phy->sata)
+		return -ENOMEM;
+
+	sprintf(type, "pcie%d", port);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, type);
+	phy->pcie = devm_ioremap_resource(&pdev->dev, res));
+	if (!phy->pcie)
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int miphy365x_of_probe(struct device_node *np,
+			      struct miphy365x_dev *phy_dev)
+{
+	phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+	if (IS_ERR(phy_dev->regmap)) {
+		dev_err(phy_dev->dev, "No syscfg phandle specified\n");
+		return PTR_ERR(phy_dev->regmap);
+	}
+
+	of_property_read_u32(np, "st,sata-gen", &phy_dev->sata_gen);
+	if (!phy_dev->sata_gen)
+		phy_dev->sata_gen = SATA_GEN1;
+
+	phy_dev->pcie_tx_pol_inv =
+		of_property_read_bool(np, "st,pcie-tx-pol-inv");
+
+	phy_dev->sata_tx_pol_inv =
+		of_property_read_bool(np, "st,sata-tx-pol-inv");
+
+	return 0;
+}
+
+static int miphy365x_probe(struct platform_device *pdev)
+{
+	struct device_node *np = pdev->dev.of_node;
+	struct miphy365x_dev *phy_dev;
+	struct device *dev = &pdev->dev;
+	struct phy_provider *provider;
+	u8 port;
+	int ret;
+
+	phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL);
+	if (!phy_dev)
+		return -ENOMEM;
+
+	ret = miphy365x_of_probe(np, phy_dev);
+	if (ret)
+		return ret;
+
+	phy_dev->dev = dev;
+
+	dev_set_drvdata(dev, phy_dev);
+
+	mutex_init(&phy_dev->miphy_mutex);
+
+	for (port = 0; port < ARRAY_SIZE(ports); port++) {
+		struct phy *phy;
+
+		phy = devm_phy_create(dev, &miphy365x_ops, NULL);
+		if (IS_ERR(phy)) {
+			dev_err(dev, "failed to create PHY on port %d\n", port);
+			return PTR_ERR(phy);
+		}
+
+		phy_dev->phys[port].phy  = phy;
+		phy_dev->phys[port].port = port;
+
+		ret = miphy365x_get_base_addr(pdev,
+					&phy_dev->phys[port], port);
+		if (ret)
+			return ret;
+
+		phy_set_drvdata(phy, &phy_dev->phys[port]);
+	}
+
+	provider = devm_of_phy_provider_register(dev, miphy365x_xlate);
+	if (IS_ERR(provider))
+		return PTR_ERR(provider);
+
+	return 0;
+}
+
+static const struct of_device_id miphy365x_of_match[] = {
+	{ .compatible = "st,miphy365x-phy", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, miphy365x_of_match);
+
+static struct platform_driver miphy365x_driver = {
+	.probe	= miphy365x_probe,
+	.driver = {
+		.name	= "miphy365x-phy",
+		.owner	= THIS_MODULE,
+		.of_match_table	= miphy365x_of_match,
+	}
+};
+module_platform_driver(miphy365x_driver);
+
+MODULE_AUTHOR("Alexandre Torgue <alexandre.torgue@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics miphy365x driver");
+MODULE_LICENSE("GPL v2");
-- 
1.7.9.5


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

* [PATCH 28/28] phy: miphy365x: Represent each PHY channel as a DT subnode
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (26 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 27/28] phy: miphy365x: Provide support for the MiPHY356x Generic PHY Kishon Vijay Abraham I
@ 2014-07-22 10:56 ` Kishon Vijay Abraham I
  2014-07-22 23:33 ` [GIT PULL 00/28] PHY: for 3.17 Greg KH
  28 siblings, 0 replies; 32+ messages in thread
From: Kishon Vijay Abraham I @ 2014-07-22 10:56 UTC (permalink / raw)
  To: gregkh; +Cc: kishon, linux-kernel

From: Lee Jones <lee.jones@linaro.org>

This has the added advantages of being able to enable/disable each
of the channels as simply as enabling/disabling the DT node.

Suggested-by: Kishon Vijay Abraham I <kishon@ti.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
---
 drivers/phy/phy-miphy365x.c |  256 +++++++++++++++++++++++--------------------
 1 file changed, 138 insertions(+), 118 deletions(-)

diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
index 65ecd04..e111baf 100644
--- a/drivers/phy/phy-miphy365x.c
+++ b/drivers/phy/phy-miphy365x.c
@@ -18,6 +18,7 @@
 #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>
@@ -28,10 +29,8 @@
 
 #define HFC_TIMEOUT		100
 
-#define SYSCFG_2521		0x824
-#define SYSCFG_2522		0x828
-#define SYSCFG_PCIE_SATA_MASK	BIT(1)
-#define SYSCFG_PCIE_SATA_POS	1
+#define SYSCFG_SELECT_SATA_MASK	BIT(1)
+#define SYSCFG_SELECT_SATA_POS	1
 
 /* MiPHY365x register definitions */
 #define RESET_REG		0x00
@@ -136,25 +135,21 @@
 #define BIT_LOCK_LEVEL		0x01
 #define BIT_LOCK_CNT_512	(0x03 << 5)
 
-static u8 ports[] = { MIPHY_PORT_0, MIPHY_PORT_1 };
-
 struct miphy365x_phy {
 	struct phy *phy;
 	void __iomem *base;
-	void __iomem *sata;
-	void __iomem *pcie;
+	bool pcie_tx_pol_inv;
+	bool sata_tx_pol_inv;
+	u32 sata_gen;
+	u64 ctrlreg;
 	u8 type;
-	u8 port;
 };
 
 struct miphy365x_dev {
 	struct device *dev;
 	struct regmap *regmap;
 	struct mutex miphy_mutex;
-	struct miphy365x phys[ARRAY_SIZE(ports)];
-	bool pcie_tx_pol_inv;
-	bool sata_tx_pol_inv;
-	u32 sata_gen;
+	struct miphy365x_phy **phys;
 };
 
 /*
@@ -180,27 +175,12 @@ static u8 rx_tx_spd[] = {
 static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
 			      struct miphy365x_dev *miphy_dev)
 {
-	u8 config = miphy_phy->type | miphy_phy->port;
-	u32 mask  = SYSCFG_PCIE_SATA_MASK;
-	u32 reg;
-	bool sata;
-
-	switch (config) {
-	case MIPHY_SATA_PORT0:
-		reg = SYSCFG_2521;
-		sata = true;
-		break;
-	case MIPHY_PCIE_PORT1:
-		reg = SYSCFG_2522;
-		sata = false;
-		break;
-	default:
-		dev_err(miphy_dev->dev, "Configuration not supported\n");
-		return -EINVAL;
-	}
+	bool sata = (miphy_phy->type == MIPHY_TYPE_SATA);
 
-	return regmap_update_bits(miphy_dev->regmap, reg, mask,
-				  sata << SYSCFG_PCIE_SATA_POS);
+	return regmap_update_bits(miphy_dev->regmap,
+				  (unsigned int)miphy_phy->ctrlreg,
+				  SYSCFG_SELECT_SATA_MASK,
+				  sata << SYSCFG_SELECT_SATA_POS);
 }
 
 static int miphy365x_init_pcie_port(struct miphy365x_phy *miphy_phy,
@@ -261,14 +241,14 @@ static inline void miphy365x_set_comp(struct miphy365x_phy *miphy_phy,
 {
 	u8 val, mask;
 
-	if (miphy_dev->sata_gen == SATA_GEN1)
+	if (miphy_phy->sata_gen == SATA_GEN1)
 		writeb_relaxed(COMP_2MHZ_RAT_GEN1,
 			       miphy_phy->base + COMP_CTRL2_REG);
 	else
 		writeb_relaxed(COMP_2MHZ_RAT,
 			       miphy_phy->base + COMP_CTRL2_REG);
 
-	if (miphy_dev->sata_gen != SATA_GEN3) {
+	if (miphy_phy->sata_gen != SATA_GEN3) {
 		writeb_relaxed(COMSR_COMP_REF,
 			       miphy_phy->base + COMP_CTRL3_REG);
 		/*
@@ -312,7 +292,7 @@ static inline void miphy365x_set_ssc(struct miphy365x_phy *miphy_phy,
 		       miphy_phy->base + PLL_SSC_PER_LSB_REG);
 
 	/* SSC Settings complete */
-	if (miphy_dev->sata_gen == SATA_GEN1) {
+	if (miphy_phy->sata_gen == SATA_GEN1) {
 		val = PLL_START_CAL | BUF_EN | SYNCHRO_TX | CONFIG_PLL;
 		writeb_relaxed(val, miphy_phy->base + PLL_CTRL1_REG);
 	} else {
@@ -334,7 +314,7 @@ static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
 	val = RST_PLL | RST_PLL_CAL | RST_RX | RST_MACRO;
 	writeb_relaxed(val, miphy_phy->base + RESET_REG);
 
-	if (miphy_dev->sata_tx_pol_inv)
+	if (miphy_phy->sata_tx_pol_inv)
 		writeb_relaxed(TX_POL, miphy_phy->base + CTRL_REG);
 
 	/*
@@ -344,7 +324,7 @@ static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
 	 */
 	writeb_relaxed(SPDSEL_SEL, miphy_phy->base + BOUNDARY1_REG);
 	writeb_relaxed(START_CLK_HF, miphy_phy->base + IDLL_TEST_REG);
-	val = rx_tx_spd[miphy_dev->sata_gen];
+	val = rx_tx_spd[miphy_phy->sata_gen];
 	writeb_relaxed(val, miphy_phy->base + BOUNDARY3_REG);
 
 	/* Wait for HFC_READY = 0 */
@@ -355,7 +335,7 @@ static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
 	/* Compensation Recalibration */
 	miphy365x_set_comp(miphy_phy, miphy_dev);
 
-	switch (miphy_dev->sata_gen) {
+	switch (miphy_phy->sata_gen) {
 	case SATA_GEN3:
 		/*
 		 * TX Swing target 550-600mv peak to peak diff
@@ -423,7 +403,7 @@ static int miphy365x_init_sata_port(struct miphy365x_phy *miphy_phy,
 	writeb_relaxed(0x00, miphy_phy->base + BOUNDARY1_REG);
 	writeb_relaxed(0x00, miphy_phy->base + IDLL_TEST_REG);
 	writeb_relaxed(RST_RX, miphy_phy->base + RESET_REG);
-	val = miphy_dev->sata_tx_pol_inv ?
+	val = miphy_phy->sata_tx_pol_inv ?
 		(TX_POL | DES_BIT_LOCK_EN) : DES_BIT_LOCK_EN;
 	writeb_relaxed(val, miphy_phy->base + CTRL_REG);
 
@@ -459,40 +439,95 @@ static int miphy365x_init(struct phy *phy)
 	return ret;
 }
 
+int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
+		       int index)
+{
+	struct device_node *phynode = miphy_phy->phy->dev.of_node;
+	const char *name;
+	const __be32 *taddr;
+	int type = miphy_phy->type;
+	int ret;
+
+	ret = of_property_read_string_index(phynode, "reg-names", index, &name);
+	if (ret) {
+		dev_err(dev, "no reg-names property not found\n");
+		return ret;
+	}
+
+	if (!strncmp(name, "syscfg", 6)) {
+		taddr = of_get_address(phynode, index, NULL, NULL);
+		if (!taddr) {
+			dev_err(dev, "failed to fetch syscfg address\n");
+			return -EINVAL;
+		}
+
+		miphy_phy->ctrlreg = of_translate_address(phynode, taddr);
+		if (miphy_phy->ctrlreg == OF_BAD_ADDR) {
+			dev_err(dev, "failed to translate syscfg address\n");
+			return -EINVAL;
+		}
+
+		return 0;
+	}
+
+	if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) ||
+	      (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE)))
+		return 0;
+
+	miphy_phy->base = of_iomap(phynode, index);
+	if (!miphy_phy->base) {
+		dev_err(dev, "Failed to map %s\n", phynode->full_name);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static struct phy *miphy365x_xlate(struct device *dev,
 				   struct of_phandle_args *args)
 {
-	struct miphy365x_dev *state = dev_get_drvdata(dev);
-	u8 port, type;
+	struct miphy365x_dev *miphy_dev = dev_get_drvdata(dev);
+	struct miphy365x_phy *miphy_phy = NULL;
+	struct device_node *phynode = args->np;
+	int ret, index;
+
+	if (!of_device_is_available(phynode)) {
+		dev_warn(dev, "Requested PHY is disabled\n");
+		return ERR_PTR(-ENODEV);
+	}
 
-	if (args->count != 2) {
+	if (args->args_count != 1) {
 		dev_err(dev, "Invalid number of cells in 'phy' property\n");
 		return ERR_PTR(-EINVAL);
 	}
 
-	if (args->args[0] & 0xFFFFFF00 || args->args[1] & 0xFFFFFF00) {
-		dev_err(dev, "Unsupported flags set in 'phy' property\n");
+	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);
 	}
 
-	port = args->args[0];
-	type = args->args[1];
-
-	if (WARN_ON(port >= ARRAY_SIZE(ports)))
-		return ERR_PTR(-EINVAL);
+	miphy_phy->type = args->args[0];
 
-	if (type == MIPHY_TYPE_SATA)
-		state->phys[port].base = state->phys[port].sata;
-	else if (type == MIPHY_TYPE_PCIE)
-		state->phys[port].base = state->phys[port].pcie;
-	else {
-		WARN(1, "Invalid type specified in DT");
+	if (!(miphy_phy->type == MIPHY_TYPE_SATA ||
+	      miphy_phy->type == MIPHY_TYPE_PCIE)) {
+		dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type);
 		return ERR_PTR(-EINVAL);
 	}
 
-	state->phys[port].type = type;
+	/* Each port handles SATA and PCIE - third entry is always sysconf. */
+	for (index = 0; index < 3; index++) {
+		ret = miphy365x_get_addr(dev, miphy_phy, index);
+		if (ret < 0)
+			return ERR_PTR(ret);
+	}
 
-	return state->phys[port].phy;
+	return miphy_phy->phy;
 }
 
 static struct phy_ops miphy365x_ops = {
@@ -500,95 +535,80 @@ static struct phy_ops miphy365x_ops = {
 	.owner		= THIS_MODULE,
 };
 
-static int miphy365x_get_base_addr(struct platform_device *pdev,
-				   struct miphy365x_phy *phy, u8 port)
+static int miphy365x_of_probe(struct device_node *phynode,
+			      struct miphy365x_phy *miphy_phy)
 {
-	struct resource *res;
-	char type[6];
+	of_property_read_u32(phynode, "st,sata-gen", &miphy_phy->sata_gen);
+	if (!miphy_phy->sata_gen)
+		miphy_phy->sata_gen = SATA_GEN1;
 
-	sprintf(type, "sata%d", port);
+	miphy_phy->pcie_tx_pol_inv =
+		of_property_read_bool(phynode, "st,pcie-tx-pol-inv");
 
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, type);
-	phy->sata = devm_ioremap_resource(&pdev->dev, res));
-	if (!phy->sata)
-		return -ENOMEM;
-
-	sprintf(type, "pcie%d", port);
-
-	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, type);
-	phy->pcie = devm_ioremap_resource(&pdev->dev, res));
-	if (!phy->pcie)
-		return -ENOMEM;
-
-	return 0;
-}
-
-static int miphy365x_of_probe(struct device_node *np,
-			      struct miphy365x_dev *phy_dev)
-{
-	phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
-	if (IS_ERR(phy_dev->regmap)) {
-		dev_err(phy_dev->dev, "No syscfg phandle specified\n");
-		return PTR_ERR(phy_dev->regmap);
-	}
-
-	of_property_read_u32(np, "st,sata-gen", &phy_dev->sata_gen);
-	if (!phy_dev->sata_gen)
-		phy_dev->sata_gen = SATA_GEN1;
-
-	phy_dev->pcie_tx_pol_inv =
-		of_property_read_bool(np, "st,pcie-tx-pol-inv");
-
-	phy_dev->sata_tx_pol_inv =
-		of_property_read_bool(np, "st,sata-tx-pol-inv");
+	miphy_phy->sata_tx_pol_inv =
+		of_property_read_bool(phynode, "st,sata-tx-pol-inv");
 
 	return 0;
 }
 
 static int miphy365x_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
-	struct miphy365x_dev *phy_dev;
-	struct device *dev = &pdev->dev;
+	struct device_node *child, *np = pdev->dev.of_node;
+	struct miphy365x_dev *miphy_dev;
 	struct phy_provider *provider;
-	u8 port;
+	struct phy *phy;
+	int chancount, port = 0;
 	int ret;
 
-	phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL);
-	if (!phy_dev)
+	miphy_dev = devm_kzalloc(&pdev->dev, sizeof(*miphy_dev), GFP_KERNEL);
+	if (!miphy_dev)
 		return -ENOMEM;
 
-	ret = miphy365x_of_probe(np, phy_dev);
-	if (ret)
-		return ret;
+	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);
 
-	phy_dev->dev = dev;
+	mutex_init(&miphy_dev->miphy_mutex);
 
-	dev_set_drvdata(dev, phy_dev);
+	for_each_child_of_node(np, child) {
+		struct miphy365x_phy *miphy_phy;
 
-	mutex_init(&phy_dev->miphy_mutex);
+		miphy_phy = devm_kzalloc(&pdev->dev, sizeof(*miphy_phy),
+					 GFP_KERNEL);
+		if (!miphy_phy)
+			return -ENOMEM;
 
-	for (port = 0; port < ARRAY_SIZE(ports); port++) {
-		struct phy *phy;
+		miphy_dev->phys[port] = miphy_phy;
 
-		phy = devm_phy_create(dev, &miphy365x_ops, NULL);
+		phy = devm_phy_create(&pdev->dev, child, &miphy365x_ops, NULL);
 		if (IS_ERR(phy)) {
-			dev_err(dev, "failed to create PHY on port %d\n", port);
+			dev_err(&pdev->dev, "failed to create PHY\n");
 			return PTR_ERR(phy);
 		}
 
-		phy_dev->phys[port].phy  = phy;
-		phy_dev->phys[port].port = port;
+		miphy_dev->phys[port]->phy = phy;
 
-		ret = miphy365x_get_base_addr(pdev,
-					&phy_dev->phys[port], port);
+		ret = miphy365x_of_probe(child, miphy_phy);
 		if (ret)
 			return ret;
 
-		phy_set_drvdata(phy, &phy_dev->phys[port]);
+		phy_set_drvdata(phy, miphy_dev->phys[port]);
+		port++;
 	}
 
-	provider = devm_of_phy_provider_register(dev, miphy365x_xlate);
+	provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
 	if (IS_ERR(provider))
 		return PTR_ERR(provider);
 
-- 
1.7.9.5


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

* Re: [GIT PULL 00/28] PHY: for 3.17
  2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
                   ` (27 preceding siblings ...)
  2014-07-22 10:56 ` [PATCH 28/28] phy: miphy365x: Represent each PHY channel as a DT subnode Kishon Vijay Abraham I
@ 2014-07-22 23:33 ` Greg KH
  28 siblings, 0 replies; 32+ messages in thread
From: Greg KH @ 2014-07-22 23:33 UTC (permalink / raw)
  To: Kishon Vijay Abraham I; +Cc: linux-kernel

On Tue, Jul 22, 2014 at 04:26:23PM +0530, Kishon Vijay Abraham I wrote:
> Hi Greg,
> 
> Here's the PULL Request for 3.17 merge window. It adds regulator
> support in PHY core and adds better support for multi-phy PHY providers.
> It includes a bunch of new PHY drivers and some misc cleanups and fixes.
> 
> Let me know if I have to change something.
> 
> Cheers
> Kishon
> 
> The following changes since commit 1795cd9b3a91d4b5473c97f491d63892442212ab:
> 
>   Linux 3.16-rc5 (2014-07-13 14:04:33 -0700)
> 
> are available in the git repository at:
> 
>   git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy.git tags/for_3.17

Pulled and pushed out, thanks.

greg k-h

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

* Re: [PATCH 27/28] phy: miphy365x: Provide support for the MiPHY356x Generic PHY
  2014-07-22 10:56 ` [PATCH 27/28] phy: miphy365x: Provide support for the MiPHY356x Generic PHY Kishon Vijay Abraham I
@ 2014-07-24 10:36   ` Paul Bolle
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Bolle @ 2014-07-24 10:36 UTC (permalink / raw)
  To: Lee Jones
  Cc: Mark Rutland, Alexandre Torgue, Kishon Vijay Abraham I, gregkh,
	linux-kernel

On Tue, 2014-07-22 at 16:26 +0530, Kishon Vijay Abraham I wrote:
> From: Lee Jones <lee.jones@linaro.org>
> 
> The MiPHY365x is a Generic PHY which can serve various SATA or PCIe
> devices. It has 2 ports which it can use for either; both SATA, both
> PCIe or one of each in any configuration.
> 
> Acked-by: Mark Rutland <mark.rutland@arm.com>
> Signed-off-by: Alexandre Torgue <alexandre.torgue@st.com>
> Signed-off-by: Lee Jones <lee.jones@linaro.org>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---

This patch landed in today's linux-next (ie, next-20140724).

>[...]
> --- /dev/null
> +++ b/drivers/phy/phy-miphy365x.c
> @@ -0,0 +1,616 @@
>[...]
> +
> +#define PLL_CTRL1_REG		0x50
> +#define PLL_START_CAL		BIT(0)
> +#define BUF_EN			BIT(2)
> +#define SYNCHRO_TX		BIT(3)
> +#define SSC_EN			BIT(6)
> +#define CONFIG_PLL		BIT(7)

This is probably a pet peeve very few people share, but anyway: would it
be possible to not use the CONFIG_ prefix here? Ie, to use, say, CONF_
or CFG_ instead.

I know there are quite a few preprocessor defines for macros starting
with CONFIG_ already. And I realize CONFIG_ is rather generic. But that
is what the build system uses so I do think it would preferable to try
to use it only for actual Kconfig macros.


Paul Bolle


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

* Re: [PATCH 10/28] phy: add hix5hd2-sata-phy driver
  2014-07-22 10:56 ` [PATCH 10/28] phy: add hix5hd2-sata-phy driver Kishon Vijay Abraham I
@ 2014-07-24 11:27   ` Paul Bolle
  0 siblings, 0 replies; 32+ messages in thread
From: Paul Bolle @ 2014-07-24 11:27 UTC (permalink / raw)
  To: Kishon Vijay Abraham I; +Cc: gregkh, linux-kernel

On Tue, 2014-07-22 at 16:26 +0530, Kishon Vijay Abraham I wrote:
> From: Jiancheng Xue <xuejiancheng@huawei.com>
> 
> Add hix5hd2-sata-phy driver on Hisilicon hix5hd2 soc.
> 
> Signed-off-by: Jiancheng Xue <xuejiancheng@huawei.com>
> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org>
> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
> ---

This landed as commit e379413a346c in today's linux-next (ie,
next-20140724). 

>  drivers/phy/Kconfig            |    8 ++
>  drivers/phy/Makefile           |    1 +
>  drivers/phy/phy-hix5hd2-sata.c |  192 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 201 insertions(+)
>  create mode 100644 drivers/phy/phy-hix5hd2-sata.c
> 
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 64b98d2..30c82fc 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -109,6 +109,14 @@ config PHY_EXYNOS5250_SATA
>  	  SATA 3.0 Gb/s, SATA 6.0 Gb/s speeds. It supports one SATA host
>  	  port to accept one SATA device.
>  
> +config PHY_HIX5HD2_SATA
> +	tristate "HIX5HD2 SATA PHY Driver"
> +	depends on ARCH_HIX5HD2 && OF && HAS_IOMEM
> +	select GENERIC_PHY
> +	select MFD_SYSCON
> +	help
> +	  Support for SATA PHY on Hisilicon hix5hd2 Soc.
> +
>  config PHY_SUN4I_USB
>  	tristate "Allwinner sunxi SoC USB PHY driver"
>  	depends on ARCH_SUNXI && HAS_IOMEM && OF

Apparently the code to add ARCH_HIX5HD2 is still pending. (I already
asked about that symbol in https://lkml.org/lkml/2014/6/19/99 .)

So currently this driver won't get build testing through linux-next.
Perhaps this entry could optionally depend on COMPILE_TEST, if build
testing is wanted, that is. (I assume there are ate least build robots
using COMPILE_TEST. Is that correct?)


Paul Bolle


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

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

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-22 10:56 [GIT PULL 00/28] PHY: for 3.17 Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 01/28] phy: miphy365x: Add MiPHY365x header file for DT x Driver defines Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 02/28] phy: exynos-dp-video: Use PTR_ERR_OR_ZERO Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 03/28] phy: exynos-mipi-video: " Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 04/28] phy: sun4i-usb: " Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 05/28] phy: exynos5-usbdrd: Make local functions static Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 06/28] phy: phy-samsung-usb2: Change phy power on/power off sequence Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 07/28] phy: phy-omap-pipe3: Add support for PCIe PHY Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 08/28] phy: pipe3: insert delay to enumerate in GEN2 mode Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 09/28] Documentation: Document Hisilicon hix5hd2 sata PHY Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 10/28] phy: add hix5hd2-sata-phy driver Kishon Vijay Abraham I
2014-07-24 11:27   ` Paul Bolle
2014-07-22 10:56 ` [PATCH 11/28] drivers: phy: exynos-usb2: add support for Exynos 3250 Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 12/28] phy: core: Support regulator supply for PHY power Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 13/28] phy: core: Add phy-supply to DT binding documentation Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 14/28] phy: Kconfig: Re-organize Exynos USB 2.0 PHY configs Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 15/28] phy: Kconfig: Update config for Exynos USB DRD Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 16/28] phy: qcom: Add driver for QCOM APQ8064 SATA PHY Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 17/28] phy: qcom: Add APQ8064 SATA PHY device tree bindings Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 18/28] phy: Remove ARCH_KIRKWOOD dependency Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 19/28] phy: add a driver for the Berlin SATA PHY Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 20/28] Documentation: bindings: add " Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 21/28] phy: core: Fix of_phy_provider_lookup to return PHY provider for sub node Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 22/28] phy: core: Let node ptr of PHY point to PHY and not of PHY provider Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 23/28] phy: qcom-apq8064: fix possible timeout without check Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 24/28] phy: qcom: Add driver for QCOM IPQ806x SATA PHY Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 25/28] phy: qcom: Add device tree bindings for " Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 26/28] phy: miphy365x: Add Device Tree bindings for the MiPHY365x Kishon Vijay Abraham I
2014-07-22 10:56 ` [PATCH 27/28] phy: miphy365x: Provide support for the MiPHY356x Generic PHY Kishon Vijay Abraham I
2014-07-24 10:36   ` Paul Bolle
2014-07-22 10:56 ` [PATCH 28/28] phy: miphy365x: Represent each PHY channel as a DT subnode Kishon Vijay Abraham I
2014-07-22 23:33 ` [GIT PULL 00/28] PHY: for 3.17 Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.