aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-01-31 11:56:27 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-01-31 11:56:27 -0500
commit6b629f2826419ab0fde54d04d97531fe4ce972bf (patch)
treef350600aa48940b0e3fd1f6aa8f2091fdf9dbe16
parentdd3217408168a96de0546aeb53cfd79a9f68dc95 (diff)
parentbbd3ce86c768928d5db334881e20116c6da4d0c7 (diff)
Merge tag 'for-3.20' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-testing
Kishon writes: Adds a new Rockchip PHY driver and contains miscellaneous fixes.
-rw-r--r--Documentation/devicetree/bindings/phy/phy-miphy28lp.txt43
-rw-r--r--Documentation/devicetree/bindings/phy/phy-miphy365x.txt15
-rw-r--r--Documentation/devicetree/bindings/phy/phy-stih407-usb.txt10
-rw-r--r--Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt37
-rw-r--r--Documentation/devicetree/bindings/phy/samsung-phy.txt2
-rw-r--r--arch/arm/boot/dts/stih416.dtsi10
-rw-r--r--drivers/phy/Kconfig7
-rw-r--r--drivers/phy/Makefile1
-rw-r--r--drivers/phy/phy-armada375-usb2.c4
-rw-r--r--drivers/phy/phy-exynos-mipi-video.c89
-rw-r--r--drivers/phy/phy-miphy28lp.c61
-rw-r--r--drivers/phy/phy-miphy365x.c29
-rw-r--r--drivers/phy/phy-rockchip-usb.c158
-rw-r--r--drivers/phy/phy-stih407-usb.c25
-rw-r--r--drivers/phy/phy-ti-pipe3.c143
-rw-r--r--include/linux/mfd/syscon/exynos4-pmu.h21
16 files changed, 483 insertions, 172 deletions
diff --git a/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt b/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
index 46a135dae6b3..89caa885d08c 100644
--- a/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
+++ b/Documentation/devicetree/bindings/phy/phy-miphy28lp.txt
@@ -26,6 +26,7 @@ Required properties (port (child) node):
26 filled in "reg". It can also contain the offset of the system configuration 26 filled in "reg". It can also contain the offset of the system configuration
27 registers used as glue-logic to setup the device for SATA/PCIe or USB3 27 registers used as glue-logic to setup the device for SATA/PCIe or USB3
28 devices. 28 devices.
29- st,syscfg : Offset of the parent configuration register.
29- resets : phandle to the parent reset controller. 30- resets : phandle to the parent reset controller.
30- reset-names : Associated name must be "miphy-sw-rst". 31- reset-names : Associated name must be "miphy-sw-rst".
31 32
@@ -54,18 +55,12 @@ example:
54 phy_port0: port@9b22000 { 55 phy_port0: port@9b22000 {
55 reg = <0x9b22000 0xff>, 56 reg = <0x9b22000 0xff>,
56 <0x9b09000 0xff>, 57 <0x9b09000 0xff>,
57 <0x9b04000 0xff>, 58 <0x9b04000 0xff>;
58 <0x114 0x4>, /* sysctrl MiPHY cntrl */
59 <0x818 0x4>, /* sysctrl MiPHY status*/
60 <0xe0 0x4>, /* sysctrl PCIe */
61 <0xec 0x4>; /* sysctrl SATA */
62 reg-names = "sata-up", 59 reg-names = "sata-up",
63 "pcie-up", 60 "pcie-up",
64 "pipew", 61 "pipew";
65 "miphy-ctrl-glue", 62
66 "miphy-status-glue", 63 st,syscfg = <0x114 0x818 0xe0 0xec>;
67 "pcie-glue",
68 "sata-glue";
69 #phy-cells = <1>; 64 #phy-cells = <1>;
70 st,osc-rdy; 65 st,osc-rdy;
71 reset-names = "miphy-sw-rst"; 66 reset-names = "miphy-sw-rst";
@@ -75,18 +70,13 @@ example:
75 phy_port1: port@9b2a000 { 70 phy_port1: port@9b2a000 {
76 reg = <0x9b2a000 0xff>, 71 reg = <0x9b2a000 0xff>,
77 <0x9b19000 0xff>, 72 <0x9b19000 0xff>,
78 <0x9b14000 0xff>, 73 <0x9b14000 0xff>;
79 <0x118 0x4>,
80 <0x81c 0x4>,
81 <0xe4 0x4>,
82 <0xf0 0x4>;
83 reg-names = "sata-up", 74 reg-names = "sata-up",
84 "pcie-up", 75 "pcie-up",
85 "pipew", 76 "pipew";
86 "miphy-ctrl-glue", 77
87 "miphy-status-glue", 78 st,syscfg = <0x118 0x81c 0xe4 0xf0>;
88 "pcie-glue", 79
89 "sata-glue";
90 #phy-cells = <1>; 80 #phy-cells = <1>;
91 st,osc-force-ext; 81 st,osc-force-ext;
92 reset-names = "miphy-sw-rst"; 82 reset-names = "miphy-sw-rst";
@@ -95,13 +85,12 @@ example:
95 85
96 phy_port2: port@8f95000 { 86 phy_port2: port@8f95000 {
97 reg = <0x8f95000 0xff>, 87 reg = <0x8f95000 0xff>,
98 <0x8f90000 0xff>, 88 <0x8f90000 0xff>;
99 <0x11c 0x4>,
100 <0x820 0x4>;
101 reg-names = "pipew", 89 reg-names = "pipew",
102 "usb3-up", 90 "usb3-up";
103 "miphy-ctrl-glue", 91
104 "miphy-status-glue"; 92 st,syscfg = <0x11c 0x820>;
93
105 #phy-cells = <1>; 94 #phy-cells = <1>;
106 reset-names = "miphy-sw-rst"; 95 reset-names = "miphy-sw-rst";
107 resets = <&softreset STIH407_MIPHY2_SOFTRESET>; 96 resets = <&softreset STIH407_MIPHY2_SOFTRESET>;
@@ -125,4 +114,4 @@ example:
125 114
126Macro definitions for the supported miphy configuration can be found in: 115Macro definitions for the supported miphy configuration can be found in:
127 116
128include/dt-bindings/phy/phy-miphy28lp.h 117include/dt-bindings/phy/phy.h
diff --git a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
index 42c880886cf7..9802d5d911aa 100644
--- a/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
+++ b/Documentation/devicetree/bindings/phy/phy-miphy365x.txt
@@ -6,8 +6,10 @@ for SATA and PCIe.
6 6
7Required properties (controller (parent) node): 7Required properties (controller (parent) node):
8- compatible : Should be "st,miphy365x-phy" 8- compatible : Should be "st,miphy365x-phy"
9- st,syscfg : Should be a phandle of the system configuration register group 9- st,syscfg : Phandle / integer array property. Phandle of sysconfig group
10 which contain the SATA, PCIe mode setting bits 10 containing the miphy registers and integer array should contain
11 an entry for each port sub-node, specifying the control
12 register offset inside the sysconfig group.
11 13
12Required nodes : A sub-node is required for each channel the controller 14Required nodes : A sub-node is required for each channel the controller
13 provides. Address range information including the usual 15 provides. Address range information including the usual
@@ -26,7 +28,6 @@ Required properties (port (child) node):
26 registers filled in "reg": 28 registers filled in "reg":
27 - sata: For SATA devices 29 - sata: For SATA devices
28 - pcie: For PCIe devices 30 - pcie: For PCIe devices
29 - syscfg: To specify the syscfg based config register
30 31
31Optional properties (port (child) node): 32Optional properties (port (child) node):
32- st,sata-gen : Generation of locally attached SATA IP. Expected values 33- st,sata-gen : Generation of locally attached SATA IP. Expected values
@@ -39,20 +40,20 @@ Example:
39 40
40 miphy365x_phy: miphy365x@fe382000 { 41 miphy365x_phy: miphy365x@fe382000 {
41 compatible = "st,miphy365x-phy"; 42 compatible = "st,miphy365x-phy";
42 st,syscfg = <&syscfg_rear>; 43 st,syscfg = <&syscfg_rear 0x824 0x828>;
43 #address-cells = <1>; 44 #address-cells = <1>;
44 #size-cells = <1>; 45 #size-cells = <1>;
45 ranges; 46 ranges;
46 47
47 phy_port0: port@fe382000 { 48 phy_port0: port@fe382000 {
48 reg = <0xfe382000 0x100>, <0xfe394000 0x100>, <0x824 0x4>; 49 reg = <0xfe382000 0x100>, <0xfe394000 0x100>;
49 reg-names = "sata", "pcie", "syscfg"; 50 reg-names = "sata", "pcie";
50 #phy-cells = <1>; 51 #phy-cells = <1>;
51 st,sata-gen = <3>; 52 st,sata-gen = <3>;
52 }; 53 };
53 54
54 phy_port1: port@fe38a000 { 55 phy_port1: port@fe38a000 {
55 reg = <0xfe38a000 0x100>, <0xfe804000 0x100>, <0x828 0x4>;; 56 reg = <0xfe38a000 0x100>, <0xfe804000 0x100>;;
56 reg-names = "sata", "pcie", "syscfg"; 57 reg-names = "sata", "pcie", "syscfg";
57 #phy-cells = <1>; 58 #phy-cells = <1>;
58 st,pcie-tx-pol-inv; 59 st,pcie-tx-pol-inv;
diff --git a/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt b/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt
index 1ef8228db73b..de6a706abcdb 100644
--- a/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt
+++ b/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt
@@ -5,10 +5,7 @@ host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC fa
5 5
6Required properties: 6Required properties:
7- compatible : should be "st,stih407-usb2-phy" 7- compatible : should be "st,stih407-usb2-phy"
8- reg : contain the offset and length of the system configuration registers 8- st,syscfg : phandle of sysconfig bank plus integer array containing phyparam and phyctrl register offsets
9 used as glue logic to control & parameter phy
10- reg-names : the names of the system configuration registers in "reg", should be "param" and "reg"
11- st,syscfg : sysconfig register to manage phy parameter at driver level
12- resets : list of phandle and reset specifier pairs. There should be two entries, one 9- resets : list of phandle and reset specifier pairs. There should be two entries, one
13 for the whole phy and one for the port 10 for the whole phy and one for the port
14- reset-names : list of reset signal names. Should be "global" and "port" 11- reset-names : list of reset signal names. Should be "global" and "port"
@@ -19,11 +16,8 @@ Example:
19 16
20usb2_picophy0: usbpicophy@f8 { 17usb2_picophy0: usbpicophy@f8 {
21 compatible = "st,stih407-usb2-phy"; 18 compatible = "st,stih407-usb2-phy";
22 reg = <0xf8 0x04>, /* syscfg 5062 */
23 <0xf4 0x04>; /* syscfg 5061 */
24 reg-names = "param", "ctrl";
25 #phy-cells = <0>; 19 #phy-cells = <0>;
26 st,syscfg = <&syscfg_core>; 20 st,syscfg = <&syscfg_core 0x100 0xf4>;
27 resets = <&softreset STIH407_PICOPHY_SOFTRESET>, 21 resets = <&softreset STIH407_PICOPHY_SOFTRESET>,
28 <&picophyreset STIH407_PICOPHY0_RESET>; 22 <&picophyreset STIH407_PICOPHY0_RESET>;
29 reset-names = "global", "port"; 23 reset-names = "global", "port";
diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
new file mode 100644
index 000000000000..826454ac43bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt
@@ -0,0 +1,37 @@
1ROCKCHIP USB2 PHY
2
3Required properties:
4 - compatible: rockchip,rk3288-usb-phy
5 - rockchip,grf : phandle to the syscon managing the "general
6 register files"
7 - #address-cells: should be 1
8 - #size-cells: should be 0
9
10Sub-nodes:
11Each PHY should be represented as a sub-node.
12
13Sub-nodes
14required properties:
15- #phy-cells: should be 0
16- reg: PHY configure reg address offset in GRF
17 "0x320" - for PHY attach to OTG controller
18 "0x334" - for PHY attach to HOST0 controller
19 "0x348" - for PHY attach to HOST1 controller
20
21Optional Properties:
22- clocks : phandle + clock specifier for the phy clocks
23- clock-names: string, clock name, must be "phyclk"
24
25Example:
26
27usbphy: phy {
28 compatible = "rockchip,rk3288-usb-phy";
29 rockchip,grf = <&grf>;
30 #address-cells = <1>;
31 #size-cells = <0>;
32
33 usbphy0: usb-phy0 {
34 #phy-cells = <0>;
35 reg = <0x320>;
36 };
37};
diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt
index d5bad920827f..91e38cfe1f8f 100644
--- a/Documentation/devicetree/bindings/phy/samsung-phy.txt
+++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt
@@ -3,8 +3,8 @@ Samsung S5P/EXYNOS SoC series MIPI CSIS/DSIM DPHY
3 3
4Required properties: 4Required properties:
5- compatible : should be "samsung,s5pv210-mipi-video-phy"; 5- compatible : should be "samsung,s5pv210-mipi-video-phy";
6- reg : offset and length of the MIPI DPHY register set;
7- #phy-cells : from the generic phy bindings, must be 1; 6- #phy-cells : from the generic phy bindings, must be 1;
7- syscon - phandle to the PMU system controller;
8 8
9For "samsung,s5pv210-mipi-video-phy" compatible PHYs the second cell in 9For "samsung,s5pv210-mipi-video-phy" compatible PHYs the second cell in
10the PHY specifier identifies the PHY and its meaning is as follows: 10the PHY specifier identifies the PHY and its meaning is as follows:
diff --git a/arch/arm/boot/dts/stih416.dtsi b/arch/arm/boot/dts/stih416.dtsi
index fad9073ddeed..85afe01c34fa 100644
--- a/arch/arm/boot/dts/stih416.dtsi
+++ b/arch/arm/boot/dts/stih416.dtsi
@@ -283,21 +283,21 @@
283 283
284 miphy365x_phy: phy@fe382000 { 284 miphy365x_phy: phy@fe382000 {
285 compatible = "st,miphy365x-phy"; 285 compatible = "st,miphy365x-phy";
286 st,syscfg = <&syscfg_rear>; 286 st,syscfg = <&syscfg_rear 0x824 0x828>;
287 #address-cells = <1>; 287 #address-cells = <1>;
288 #size-cells = <1>; 288 #size-cells = <1>;
289 ranges; 289 ranges;
290 290
291 phy_port0: port@fe382000 { 291 phy_port0: port@fe382000 {
292 #phy-cells = <1>; 292 #phy-cells = <1>;
293 reg = <0xfe382000 0x100>, <0xfe394000 0x100>, <0x824 0x4>; 293 reg = <0xfe382000 0x100>, <0xfe394000 0x100>;
294 reg-names = "sata", "pcie", "syscfg"; 294 reg-names = "sata", "pcie";
295 }; 295 };
296 296
297 phy_port1: port@fe38a000 { 297 phy_port1: port@fe38a000 {
298 #phy-cells = <1>; 298 #phy-cells = <1>;
299 reg = <0xfe38a000 0x100>, <0xfe804000 0x100>, <0x828 0x4>; 299 reg = <0xfe38a000 0x100>, <0xfe804000 0x100>;
300 reg-names = "sata", "pcie", "syscfg"; 300 reg-names = "sata", "pcie";
301 }; 301 };
302 }; 302 };
303 303
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index ccad8809ecb1..b24500afba25 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -239,6 +239,13 @@ config PHY_QCOM_IPQ806X_SATA
239 depends on OF 239 depends on OF
240 select GENERIC_PHY 240 select GENERIC_PHY
241 241
242config PHY_ROCKCHIP_USB
243 tristate "Rockchip USB2 PHY Driver"
244 depends on ARCH_ROCKCHIP && OF
245 select GENERIC_PHY
246 help
247 Enable this to support the Rockchip USB 2.0 PHY.
248
242config PHY_ST_SPEAR1310_MIPHY 249config PHY_ST_SPEAR1310_MIPHY
243 tristate "ST SPEAR1310-MIPHY driver" 250 tristate "ST SPEAR1310-MIPHY driver"
244 select GENERIC_PHY 251 select GENERIC_PHY
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index aa74f961e44e..48bf5a15f161 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -28,6 +28,7 @@ phy-exynos-usb2-$(CONFIG_PHY_EXYNOS5250_USB2) += phy-exynos5250-usb2.o
28phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o 28phy-exynos-usb2-$(CONFIG_PHY_S5PV210_USB2) += phy-s5pv210-usb2.o
29obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o 29obj-$(CONFIG_PHY_EXYNOS5_USBDRD) += phy-exynos5-usbdrd.o
30obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o 30obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o
31obj-$(CONFIG_PHY_ROCKCHIP_USB) += phy-rockchip-usb.o
31obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o 32obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o
32obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o 33obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o
33obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o 34obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o
diff --git a/drivers/phy/phy-armada375-usb2.c b/drivers/phy/phy-armada375-usb2.c
index ac7d99d01cb3..7c99ca256f05 100644
--- a/drivers/phy/phy-armada375-usb2.c
+++ b/drivers/phy/phy-armada375-usb2.c
@@ -118,8 +118,8 @@ static int armada375_usb_phy_probe(struct platform_device *pdev)
118 118
119 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 119 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
120 usb_cluster_base = devm_ioremap_resource(&pdev->dev, res); 120 usb_cluster_base = devm_ioremap_resource(&pdev->dev, res);
121 if (!usb_cluster_base) 121 if (IS_ERR(usb_cluster_base))
122 return -ENOMEM; 122 return PTR_ERR(usb_cluster_base);
123 123
124 phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops); 124 phy = devm_phy_create(dev, NULL, &armada375_usb_phy_ops);
125 if (IS_ERR(phy)) { 125 if (IS_ERR(phy)) {
diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c
index 943e0f88a120..f017b2f2a54e 100644
--- a/drivers/phy/phy-exynos-mipi-video.c
+++ b/drivers/phy/phy-exynos-mipi-video.c
@@ -12,19 +12,18 @@
12#include <linux/err.h> 12#include <linux/err.h>
13#include <linux/io.h> 13#include <linux/io.h>
14#include <linux/kernel.h> 14#include <linux/kernel.h>
15#include <linux/mfd/syscon/exynos4-pmu.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/of.h> 17#include <linux/of.h>
17#include <linux/of_address.h> 18#include <linux/of_address.h>
18#include <linux/phy/phy.h> 19#include <linux/phy/phy.h>
19#include <linux/platform_device.h> 20#include <linux/platform_device.h>
21#include <linux/regmap.h>
20#include <linux/spinlock.h> 22#include <linux/spinlock.h>
23#include <linux/mfd/syscon.h>
21 24
22/* MIPI_PHYn_CONTROL register offset: n = 0..1 */ 25/* MIPI_PHYn_CONTROL reg. offset (for base address from ioremap): n = 0..1 */
23#define EXYNOS_MIPI_PHY_CONTROL(n) ((n) * 4) 26#define EXYNOS_MIPI_PHY_CONTROL(n) ((n) * 4)
24#define EXYNOS_MIPI_PHY_ENABLE (1 << 0)
25#define EXYNOS_MIPI_PHY_SRESETN (1 << 1)
26#define EXYNOS_MIPI_PHY_MRESETN (1 << 2)
27#define EXYNOS_MIPI_PHY_RESET_MASK (3 << 1)
28 27
29enum exynos_mipi_phy_id { 28enum exynos_mipi_phy_id {
30 EXYNOS_MIPI_PHY_ID_CSIS0, 29 EXYNOS_MIPI_PHY_ID_CSIS0,
@@ -38,43 +37,62 @@ enum exynos_mipi_phy_id {
38 ((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM1) 37 ((id) == EXYNOS_MIPI_PHY_ID_DSIM0 || (id) == EXYNOS_MIPI_PHY_ID_DSIM1)
39 38
40struct exynos_mipi_video_phy { 39struct exynos_mipi_video_phy {
41 spinlock_t slock;
42 struct video_phy_desc { 40 struct video_phy_desc {
43 struct phy *phy; 41 struct phy *phy;
44 unsigned int index; 42 unsigned int index;
45 } phys[EXYNOS_MIPI_PHYS_NUM]; 43 } phys[EXYNOS_MIPI_PHYS_NUM];
44 spinlock_t slock;
46 void __iomem *regs; 45 void __iomem *regs;
46 struct mutex mutex;
47 struct regmap *regmap;
47}; 48};
48 49
49static int __set_phy_state(struct exynos_mipi_video_phy *state, 50static int __set_phy_state(struct exynos_mipi_video_phy *state,
50 enum exynos_mipi_phy_id id, unsigned int on) 51 enum exynos_mipi_phy_id id, unsigned int on)
51{ 52{
53 const unsigned int offset = EXYNOS4_MIPI_PHY_CONTROL(id / 2);
52 void __iomem *addr; 54 void __iomem *addr;
53 u32 reg, reset; 55 u32 val, reset;
54
55 addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2);
56 56
57 if (is_mipi_dsim_phy_id(id)) 57 if (is_mipi_dsim_phy_id(id))
58 reset = EXYNOS_MIPI_PHY_MRESETN; 58 reset = EXYNOS4_MIPI_PHY_MRESETN;
59 else
60 reset = EXYNOS_MIPI_PHY_SRESETN;
61
62 spin_lock(&state->slock);
63 reg = readl(addr);
64 if (on)
65 reg |= reset;
66 else 59 else
67 reg &= ~reset; 60 reset = EXYNOS4_MIPI_PHY_SRESETN;
68 writel(reg, addr); 61
69 62 if (state->regmap) {
70 /* Clear ENABLE bit only if MRESETN, SRESETN bits are not set. */ 63 mutex_lock(&state->mutex);
71 if (on) 64 regmap_read(state->regmap, offset, &val);
72 reg |= EXYNOS_MIPI_PHY_ENABLE; 65 if (on)
73 else if (!(reg & EXYNOS_MIPI_PHY_RESET_MASK)) 66 val |= reset;
74 reg &= ~EXYNOS_MIPI_PHY_ENABLE; 67 else
68 val &= ~reset;
69 regmap_write(state->regmap, offset, val);
70 if (on)
71 val |= EXYNOS4_MIPI_PHY_ENABLE;
72 else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK))
73 val &= ~EXYNOS4_MIPI_PHY_ENABLE;
74 regmap_write(state->regmap, offset, val);
75 mutex_unlock(&state->mutex);
76 } else {
77 addr = state->regs + EXYNOS_MIPI_PHY_CONTROL(id / 2);
78
79 spin_lock(&state->slock);
80 val = readl(addr);
81 if (on)
82 val |= reset;
83 else
84 val &= ~reset;
85 writel(val, addr);
86 /* Clear ENABLE bit only if MRESETN, SRESETN bits are not set */
87 if (on)
88 val |= EXYNOS4_MIPI_PHY_ENABLE;
89 else if (!(val & EXYNOS4_MIPI_PHY_RESET_MASK))
90 val &= ~EXYNOS4_MIPI_PHY_ENABLE;
91
92 writel(val, addr);
93 spin_unlock(&state->slock);
94 }
75 95
76 writel(reg, addr);
77 spin_unlock(&state->slock);
78 return 0; 96 return 0;
79} 97}
80 98
@@ -118,7 +136,6 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
118{ 136{
119 struct exynos_mipi_video_phy *state; 137 struct exynos_mipi_video_phy *state;
120 struct device *dev = &pdev->dev; 138 struct device *dev = &pdev->dev;
121 struct resource *res;
122 struct phy_provider *phy_provider; 139 struct phy_provider *phy_provider;
123 unsigned int i; 140 unsigned int i;
124 141
@@ -126,14 +143,22 @@ static int exynos_mipi_video_phy_probe(struct platform_device *pdev)
126 if (!state) 143 if (!state)
127 return -ENOMEM; 144 return -ENOMEM;
128 145
129 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 146 state->regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "syscon");
147 if (IS_ERR(state->regmap)) {
148 struct resource *res;
130 149
131 state->regs = devm_ioremap_resource(dev, res); 150 dev_info(dev, "regmap lookup failed: %ld\n",
132 if (IS_ERR(state->regs)) 151 PTR_ERR(state->regmap));
133 return PTR_ERR(state->regs); 152
153 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
154 state->regs = devm_ioremap_resource(dev, res);
155 if (IS_ERR(state->regs))
156 return PTR_ERR(state->regs);
157 }
134 158
135 dev_set_drvdata(dev, state); 159 dev_set_drvdata(dev, state);
136 spin_lock_init(&state->slock); 160 spin_lock_init(&state->slock);
161 mutex_init(&state->mutex);
137 162
138 for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) { 163 for (i = 0; i < EXYNOS_MIPI_PHYS_NUM; i++) {
139 struct phy *phy = devm_phy_create(dev, NULL, 164 struct phy *phy = devm_phy_create(dev, NULL,
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
index 27fa62ce6136..9b2848e6115d 100644
--- a/drivers/phy/phy-miphy28lp.c
+++ b/drivers/phy/phy-miphy28lp.c
@@ -194,6 +194,14 @@
194#define MIPHY_SATA_BANK_NB 3 194#define MIPHY_SATA_BANK_NB 3
195#define MIPHY_PCIE_BANK_NB 2 195#define MIPHY_PCIE_BANK_NB 2
196 196
197enum {
198 SYSCFG_CTRL,
199 SYSCFG_STATUS,
200 SYSCFG_PCI,
201 SYSCFG_SATA,
202 SYSCFG_REG_MAX,
203};
204
197struct miphy28lp_phy { 205struct miphy28lp_phy {
198 struct phy *phy; 206 struct phy *phy;
199 struct miphy28lp_dev *phydev; 207 struct miphy28lp_dev *phydev;
@@ -211,10 +219,7 @@ struct miphy28lp_phy {
211 u32 sata_gen; 219 u32 sata_gen;
212 220
213 /* Sysconfig registers offsets needed to configure the device */ 221 /* Sysconfig registers offsets needed to configure the device */
214 u32 syscfg_miphy_ctrl; 222 u32 syscfg_reg[SYSCFG_REG_MAX];
215 u32 syscfg_miphy_status;
216 u32 syscfg_pci;
217 u32 syscfg_sata;
218 u8 type; 223 u8 type;
219}; 224};
220 225
@@ -834,12 +839,12 @@ static int miphy_osc_is_ready(struct miphy28lp_phy *miphy_phy)
834 if (!miphy_phy->osc_rdy) 839 if (!miphy_phy->osc_rdy)
835 return 0; 840 return 0;
836 841
837 if (!miphy_phy->syscfg_miphy_status) 842 if (!miphy_phy->syscfg_reg[SYSCFG_STATUS])
838 return -EINVAL; 843 return -EINVAL;
839 844
840 do { 845 do {
841 regmap_read(miphy_dev->regmap, miphy_phy->syscfg_miphy_status, 846 regmap_read(miphy_dev->regmap,
842 &val); 847 miphy_phy->syscfg_reg[SYSCFG_STATUS], &val);
843 848
844 if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY) 849 if ((val & MIPHY_OSC_RDY) != MIPHY_OSC_RDY)
845 cpu_relax(); 850 cpu_relax();
@@ -888,7 +893,7 @@ static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)
888 int err; 893 int err;
889 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 894 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
890 895
891 if (!miphy_phy->syscfg_miphy_ctrl) 896 if (!miphy_phy->syscfg_reg[SYSCFG_CTRL])
892 return -EINVAL; 897 return -EINVAL;
893 898
894 err = reset_control_assert(miphy_phy->miphy_rst); 899 err = reset_control_assert(miphy_phy->miphy_rst);
@@ -900,7 +905,8 @@ static int miphy28lp_setup(struct miphy28lp_phy *miphy_phy, u32 miphy_val)
900 if (miphy_phy->osc_force_ext) 905 if (miphy_phy->osc_force_ext)
901 miphy_val |= MIPHY_OSC_FORCE_EXT; 906 miphy_val |= MIPHY_OSC_FORCE_EXT;
902 907
903 regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_miphy_ctrl, 908 regmap_update_bits(miphy_dev->regmap,
909 miphy_phy->syscfg_reg[SYSCFG_CTRL],
904 MIPHY_CTRL_MASK, miphy_val); 910 MIPHY_CTRL_MASK, miphy_val);
905 911
906 err = reset_control_deassert(miphy_phy->miphy_rst); 912 err = reset_control_deassert(miphy_phy->miphy_rst);
@@ -917,8 +923,9 @@ static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)
917 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 923 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
918 int err, sata_conf = SATA_CTRL_SELECT_SATA; 924 int err, sata_conf = SATA_CTRL_SELECT_SATA;
919 925
920 if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci) 926 if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||
921 || (!miphy_phy->base)) 927 (!miphy_phy->syscfg_reg[SYSCFG_PCI]) ||
928 (!miphy_phy->base))
922 return -EINVAL; 929 return -EINVAL;
923 930
924 dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base); 931 dev_info(miphy_dev->dev, "sata-up mode, addr 0x%p\n", miphy_phy->base);
@@ -926,10 +933,11 @@ static int miphy28lp_init_sata(struct miphy28lp_phy *miphy_phy)
926 /* Configure the glue-logic */ 933 /* Configure the glue-logic */
927 sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE); 934 sata_conf |= ((miphy_phy->sata_gen - SATA_GEN1) << SATA_SPDMODE);
928 935
929 regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata, 936 regmap_update_bits(miphy_dev->regmap,
937 miphy_phy->syscfg_reg[SYSCFG_SATA],
930 SATA_CTRL_MASK, sata_conf); 938 SATA_CTRL_MASK, sata_conf);
931 939
932 regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci, 940 regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],
933 PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE); 941 PCIE_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
934 942
935 /* MiPHY path and clocking init */ 943 /* MiPHY path and clocking init */
@@ -951,17 +959,19 @@ static int miphy28lp_init_pcie(struct miphy28lp_phy *miphy_phy)
951 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev; 959 struct miphy28lp_dev *miphy_dev = miphy_phy->phydev;
952 int err; 960 int err;
953 961
954 if ((!miphy_phy->syscfg_sata) || (!miphy_phy->syscfg_pci) 962 if ((!miphy_phy->syscfg_reg[SYSCFG_SATA]) ||
963 (!miphy_phy->syscfg_reg[SYSCFG_PCI])
955 || (!miphy_phy->base) || (!miphy_phy->pipebase)) 964 || (!miphy_phy->base) || (!miphy_phy->pipebase))
956 return -EINVAL; 965 return -EINVAL;
957 966
958 dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base); 967 dev_info(miphy_dev->dev, "pcie-up mode, addr 0x%p\n", miphy_phy->base);
959 968
960 /* Configure the glue-logic */ 969 /* Configure the glue-logic */
961 regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_sata, 970 regmap_update_bits(miphy_dev->regmap,
971 miphy_phy->syscfg_reg[SYSCFG_SATA],
962 SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE); 972 SATA_CTRL_MASK, SATA_CTRL_SELECT_PCIE);
963 973
964 regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_pci, 974 regmap_update_bits(miphy_dev->regmap, miphy_phy->syscfg_reg[SYSCFG_PCI],
965 PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL); 975 PCIE_CTRL_MASK, SYSCFG_PCIE_PCIE_VAL);
966 976
967 /* MiPHY path and clocking init */ 977 /* MiPHY path and clocking init */
@@ -1156,7 +1166,8 @@ static int miphy28lp_probe_resets(struct device_node *node,
1156static int miphy28lp_of_probe(struct device_node *np, 1166static int miphy28lp_of_probe(struct device_node *np,
1157 struct miphy28lp_phy *miphy_phy) 1167 struct miphy28lp_phy *miphy_phy)
1158{ 1168{
1159 struct resource res; 1169 int i;
1170 u32 ctrlreg;
1160 1171
1161 miphy_phy->osc_force_ext = 1172 miphy_phy->osc_force_ext =
1162 of_property_read_bool(np, "st,osc-force-ext"); 1173 of_property_read_bool(np, "st,osc-force-ext");
@@ -1175,18 +1186,10 @@ static int miphy28lp_of_probe(struct device_node *np,
1175 if (!miphy_phy->sata_gen) 1186 if (!miphy_phy->sata_gen)
1176 miphy_phy->sata_gen = SATA_GEN1; 1187 miphy_phy->sata_gen = SATA_GEN1;
1177 1188
1178 if (!miphy28lp_get_resource_byname(np, "miphy-ctrl-glue", &res)) 1189 for (i = 0; i < SYSCFG_REG_MAX; i++) {
1179 miphy_phy->syscfg_miphy_ctrl = res.start; 1190 if (!of_property_read_u32_index(np, "st,syscfg", i, &ctrlreg))
1180 1191 miphy_phy->syscfg_reg[i] = ctrlreg;
1181 if (!miphy28lp_get_resource_byname(np, "miphy-status-glue", &res)) 1192 }
1182 miphy_phy->syscfg_miphy_status = res.start;
1183
1184 if (!miphy28lp_get_resource_byname(np, "pcie-glue", &res))
1185 miphy_phy->syscfg_pci = res.start;
1186
1187 if (!miphy28lp_get_resource_byname(np, "sata-glue", &res))
1188 miphy_phy->syscfg_sata = res.start;
1189
1190 1193
1191 return 0; 1194 return 0;
1192} 1195}
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
index 6ab43a814ad2..6c80154e8bff 100644
--- a/drivers/phy/phy-miphy365x.c
+++ b/drivers/phy/phy-miphy365x.c
@@ -141,7 +141,7 @@ struct miphy365x_phy {
141 bool pcie_tx_pol_inv; 141 bool pcie_tx_pol_inv;
142 bool sata_tx_pol_inv; 142 bool sata_tx_pol_inv;
143 u32 sata_gen; 143 u32 sata_gen;
144 u64 ctrlreg; 144 u32 ctrlreg;
145 u8 type; 145 u8 type;
146}; 146};
147 147
@@ -179,7 +179,7 @@ static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
179 bool sata = (miphy_phy->type == MIPHY_TYPE_SATA); 179 bool sata = (miphy_phy->type == MIPHY_TYPE_SATA);
180 180
181 return regmap_update_bits(miphy_dev->regmap, 181 return regmap_update_bits(miphy_dev->regmap,
182 (unsigned int)miphy_phy->ctrlreg, 182 miphy_phy->ctrlreg,
183 SYSCFG_SELECT_SATA_MASK, 183 SYSCFG_SELECT_SATA_MASK,
184 sata << SYSCFG_SELECT_SATA_POS); 184 sata << SYSCFG_SELECT_SATA_POS);
185} 185}
@@ -445,7 +445,6 @@ int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
445{ 445{
446 struct device_node *phynode = miphy_phy->phy->dev.of_node; 446 struct device_node *phynode = miphy_phy->phy->dev.of_node;
447 const char *name; 447 const char *name;
448 const __be32 *taddr;
449 int type = miphy_phy->type; 448 int type = miphy_phy->type;
450 int ret; 449 int ret;
451 450
@@ -455,22 +454,6 @@ int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
455 return ret; 454 return ret;
456 } 455 }
457 456
458 if (!strncmp(name, "syscfg", 6)) {
459 taddr = of_get_address(phynode, index, NULL, NULL);
460 if (!taddr) {
461 dev_err(dev, "failed to fetch syscfg address\n");
462 return -EINVAL;
463 }
464
465 miphy_phy->ctrlreg = of_translate_address(phynode, taddr);
466 if (miphy_phy->ctrlreg == OF_BAD_ADDR) {
467 dev_err(dev, "failed to translate syscfg address\n");
468 return -EINVAL;
469 }
470
471 return 0;
472 }
473
474 if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) || 457 if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) ||
475 (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE))) 458 (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE)))
476 return 0; 459 return 0;
@@ -606,7 +589,15 @@ static int miphy365x_probe(struct platform_device *pdev)
606 return ret; 589 return ret;
607 590
608 phy_set_drvdata(phy, miphy_dev->phys[port]); 591 phy_set_drvdata(phy, miphy_dev->phys[port]);
592
609 port++; 593 port++;
594 /* sysconfig offsets are indexed from 1 */
595 ret = of_property_read_u32_index(np, "st,syscfg", port,
596 &miphy_phy->ctrlreg);
597 if (ret) {
598 dev_err(&pdev->dev, "No sysconfig offset found\n");
599 return ret;
600 }
610 } 601 }
611 602
612 provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate); 603 provider = devm_of_phy_provider_register(&pdev->dev, miphy365x_xlate);
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c
new file mode 100644
index 000000000000..22011c3b6a4b
--- /dev/null
+++ b/drivers/phy/phy-rockchip-usb.c
@@ -0,0 +1,158 @@
1/*
2 * Rockchip usb PHY driver
3 *
4 * Copyright (C) 2014 Yunzhi Li <lyz@rock-chips.com>
5 * Copyright (C) 2014 ROCKCHIP, Inc.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk.h>
18#include <linux/io.h>
19#include <linux/kernel.h>
20#include <linux/module.h>
21#include <linux/mutex.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/phy/phy.h>
25#include <linux/platform_device.h>
26#include <linux/regulator/consumer.h>
27#include <linux/reset.h>
28#include <linux/regmap.h>
29#include <linux/mfd/syscon.h>
30
31/*
32 * The higher 16-bit of this register is used for write protection
33 * only if BIT(13 + 16) set to 1 the BIT(13) can be written.
34 */
35#define SIDDQ_WRITE_ENA BIT(29)
36#define SIDDQ_ON BIT(13)
37#define SIDDQ_OFF (0 << 13)
38
39struct rockchip_usb_phy {
40 unsigned int reg_offset;
41 struct regmap *reg_base;
42 struct clk *clk;
43 struct phy *phy;
44};
45
46static int rockchip_usb_phy_power(struct rockchip_usb_phy *phy,
47 bool siddq)
48{
49 return regmap_write(phy->reg_base, phy->reg_offset,
50 SIDDQ_WRITE_ENA | (siddq ? SIDDQ_ON : SIDDQ_OFF));
51}
52
53static int rockchip_usb_phy_power_off(struct phy *_phy)
54{
55 struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
56 int ret = 0;
57
58 /* Power down usb phy analog blocks by set siddq 1 */
59 ret = rockchip_usb_phy_power(phy, 1);
60 if (ret)
61 return ret;
62
63 clk_disable_unprepare(phy->clk);
64 if (ret)
65 return ret;
66
67 return 0;
68}
69
70static int rockchip_usb_phy_power_on(struct phy *_phy)
71{
72 struct rockchip_usb_phy *phy = phy_get_drvdata(_phy);
73 int ret = 0;
74
75 ret = clk_prepare_enable(phy->clk);
76 if (ret)
77 return ret;
78
79 /* Power up usb phy analog blocks by set siddq 0 */
80 ret = rockchip_usb_phy_power(phy, 0);
81 if (ret)
82 return ret;
83
84 return 0;
85}
86
87static struct phy_ops ops = {
88 .power_on = rockchip_usb_phy_power_on,
89 .power_off = rockchip_usb_phy_power_off,
90 .owner = THIS_MODULE,
91};
92
93static int rockchip_usb_phy_probe(struct platform_device *pdev)
94{
95 struct device *dev = &pdev->dev;
96 struct rockchip_usb_phy *rk_phy;
97 struct phy_provider *phy_provider;
98 struct device_node *child;
99 struct regmap *grf;
100 unsigned int reg_offset;
101
102 grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
103 if (IS_ERR(grf)) {
104 dev_err(&pdev->dev, "Missing rockchip,grf property\n");
105 return PTR_ERR(grf);
106 }
107
108 for_each_available_child_of_node(dev->of_node, child) {
109 rk_phy = devm_kzalloc(dev, sizeof(*rk_phy), GFP_KERNEL);
110 if (!rk_phy)
111 return -ENOMEM;
112
113 if (of_property_read_u32(child, "reg", &reg_offset)) {
114 dev_err(dev, "missing reg property in node %s\n",
115 child->name);
116 return -EINVAL;
117 }
118
119 rk_phy->reg_offset = reg_offset;
120 rk_phy->reg_base = grf;
121
122 rk_phy->clk = of_clk_get_by_name(child, "phyclk");
123 if (IS_ERR(rk_phy->clk))
124 rk_phy->clk = NULL;
125
126 rk_phy->phy = devm_phy_create(dev, child, &ops);
127 if (IS_ERR(rk_phy->phy)) {
128 dev_err(dev, "failed to create PHY\n");
129 return PTR_ERR(rk_phy->phy);
130 }
131 phy_set_drvdata(rk_phy->phy, rk_phy);
132 }
133
134 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
135 return PTR_ERR_OR_ZERO(phy_provider);
136}
137
138static const struct of_device_id rockchip_usb_phy_dt_ids[] = {
139 { .compatible = "rockchip,rk3288-usb-phy" },
140 {}
141};
142
143MODULE_DEVICE_TABLE(of, rockchip_usb_phy_dt_ids);
144
145static struct platform_driver rockchip_usb_driver = {
146 .probe = rockchip_usb_phy_probe,
147 .driver = {
148 .name = "rockchip-usb-phy",
149 .owner = THIS_MODULE,
150 .of_match_table = rockchip_usb_phy_dt_ids,
151 },
152};
153
154module_platform_driver(rockchip_usb_driver);
155
156MODULE_AUTHOR("Yunzhi Li <lyz@rock-chips.com>");
157MODULE_DESCRIPTION("Rockchip USB 2.0 PHY driver");
158MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-stih407-usb.c b/drivers/phy/phy-stih407-usb.c
index 74f0fab3cd8a..1d5ae5f8ef69 100644
--- a/drivers/phy/phy-stih407-usb.c
+++ b/drivers/phy/phy-stih407-usb.c
@@ -22,6 +22,9 @@
22#include <linux/mfd/syscon.h> 22#include <linux/mfd/syscon.h>
23#include <linux/phy/phy.h> 23#include <linux/phy/phy.h>
24 24
25#define PHYPARAM_REG 1
26#define PHYCTRL_REG 2
27
25/* Default PHY_SEL and REFCLKSEL configuration */ 28/* Default PHY_SEL and REFCLKSEL configuration */
26#define STIH407_USB_PICOPHY_CTRL_PORT_CONF 0x6 29#define STIH407_USB_PICOPHY_CTRL_PORT_CONF 0x6
27#define STIH407_USB_PICOPHY_CTRL_PORT_MASK 0x1f 30#define STIH407_USB_PICOPHY_CTRL_PORT_MASK 0x1f
@@ -93,7 +96,7 @@ static int stih407_usb2_picophy_probe(struct platform_device *pdev)
93 struct device_node *np = dev->of_node; 96 struct device_node *np = dev->of_node;
94 struct phy_provider *phy_provider; 97 struct phy_provider *phy_provider;
95 struct phy *phy; 98 struct phy *phy;
96 struct resource *res; 99 int ret;
97 100
98 phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); 101 phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL);
99 if (!phy_dev) 102 if (!phy_dev)
@@ -123,19 +126,19 @@ static int stih407_usb2_picophy_probe(struct platform_device *pdev)
123 return PTR_ERR(phy_dev->regmap); 126 return PTR_ERR(phy_dev->regmap);
124 } 127 }
125 128
126 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl"); 129 ret = of_property_read_u32_index(np, "st,syscfg", PHYPARAM_REG,
127 if (!res) { 130 &phy_dev->param);
128 dev_err(dev, "No ctrl reg found\n"); 131 if (ret) {
129 return -ENXIO; 132 dev_err(dev, "can't get phyparam offset (%d)\n", ret);
133 return ret;
130 } 134 }
131 phy_dev->ctrl = res->start;
132 135
133 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "param"); 136 ret = of_property_read_u32_index(np, "st,syscfg", PHYCTRL_REG,
134 if (!res) { 137 &phy_dev->ctrl);
135 dev_err(dev, "No param reg found\n"); 138 if (ret) {
136 return -ENXIO; 139 dev_err(dev, "can't get phyctrl offset (%d)\n", ret);
140 return ret;
137 } 141 }
138 phy_dev->param = res->start;
139 142
140 phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data); 143 phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data);
141 if (IS_ERR(phy)) { 144 if (IS_ERR(phy)) {
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 465de2c800f2..95c88f929f27 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -28,6 +28,7 @@
28#include <linux/delay.h> 28#include <linux/delay.h>
29#include <linux/phy/omap_control_phy.h> 29#include <linux/phy/omap_control_phy.h>
30#include <linux/of_platform.h> 30#include <linux/of_platform.h>
31#include <linux/spinlock.h>
31 32
32#define PLL_STATUS 0x00000004 33#define PLL_STATUS 0x00000004
33#define PLL_GO 0x00000008 34#define PLL_GO 0x00000008
@@ -82,6 +83,10 @@ struct ti_pipe3 {
82 struct clk *refclk; 83 struct clk *refclk;
83 struct clk *div_clk; 84 struct clk *div_clk;
84 struct pipe3_dpll_map *dpll_map; 85 struct pipe3_dpll_map *dpll_map;
86 bool enabled;
87 spinlock_t lock; /* serialize clock enable/disable */
88 /* the below flag is needed specifically for SATA */
89 bool refclk_enabled;
85}; 90};
86 91
87static struct pipe3_dpll_map dpll_map_usb[] = { 92static struct pipe3_dpll_map dpll_map_usb[] = {
@@ -307,6 +312,7 @@ static int ti_pipe3_probe(struct platform_device *pdev)
307 return -ENOMEM; 312 return -ENOMEM;
308 313
309 phy->dev = &pdev->dev; 314 phy->dev = &pdev->dev;
315 spin_lock_init(&phy->lock);
310 316
311 if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { 317 if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
312 match = of_match_device(of_match_ptr(ti_pipe3_id_table), 318 match = of_match_device(of_match_ptr(ti_pipe3_id_table),
@@ -333,21 +339,24 @@ static int ti_pipe3_probe(struct platform_device *pdev)
333 } 339 }
334 } 340 }
335 341
342 phy->refclk = devm_clk_get(phy->dev, "refclk");
343 if (IS_ERR(phy->refclk)) {
344 dev_err(&pdev->dev, "unable to get refclk\n");
345 /* older DTBs have missing refclk in SATA PHY
346 * so don't bail out in case of SATA PHY.
347 */
348 if (!of_device_is_compatible(node, "ti,phy-pipe3-sata"))
349 return PTR_ERR(phy->refclk);
350 }
351
336 if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) { 352 if (!of_device_is_compatible(node, "ti,phy-pipe3-sata")) {
337 phy->wkupclk = devm_clk_get(phy->dev, "wkupclk"); 353 phy->wkupclk = devm_clk_get(phy->dev, "wkupclk");
338 if (IS_ERR(phy->wkupclk)) { 354 if (IS_ERR(phy->wkupclk)) {
339 dev_err(&pdev->dev, "unable to get wkupclk\n"); 355 dev_err(&pdev->dev, "unable to get wkupclk\n");
340 return PTR_ERR(phy->wkupclk); 356 return PTR_ERR(phy->wkupclk);
341 } 357 }
342
343 phy->refclk = devm_clk_get(phy->dev, "refclk");
344 if (IS_ERR(phy->refclk)) {
345 dev_err(&pdev->dev, "unable to get refclk\n");
346 return PTR_ERR(phy->refclk);
347 }
348 } else { 358 } else {
349 phy->wkupclk = ERR_PTR(-ENODEV); 359 phy->wkupclk = ERR_PTR(-ENODEV);
350 phy->refclk = ERR_PTR(-ENODEV);
351 } 360 }
352 361
353 if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { 362 if (of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
@@ -426,33 +435,42 @@ static int ti_pipe3_remove(struct platform_device *pdev)
426} 435}
427 436
428#ifdef CONFIG_PM 437#ifdef CONFIG_PM
429 438static int ti_pipe3_enable_refclk(struct ti_pipe3 *phy)
430static int ti_pipe3_runtime_suspend(struct device *dev)
431{ 439{
432 struct ti_pipe3 *phy = dev_get_drvdata(dev); 440 if (!IS_ERR(phy->refclk) && !phy->refclk_enabled) {
441 int ret;
433 442
434 if (!IS_ERR(phy->wkupclk)) 443 ret = clk_prepare_enable(phy->refclk);
435 clk_disable_unprepare(phy->wkupclk); 444 if (ret) {
445 dev_err(phy->dev, "Failed to enable refclk %d\n", ret);
446 return ret;
447 }
448 phy->refclk_enabled = true;
449 }
450
451 return 0;
452}
453
454static void ti_pipe3_disable_refclk(struct ti_pipe3 *phy)
455{
436 if (!IS_ERR(phy->refclk)) 456 if (!IS_ERR(phy->refclk))
437 clk_disable_unprepare(phy->refclk); 457 clk_disable_unprepare(phy->refclk);
438 if (!IS_ERR(phy->div_clk))
439 clk_disable_unprepare(phy->div_clk);
440 458
441 return 0; 459 phy->refclk_enabled = false;
442} 460}
443 461
444static int ti_pipe3_runtime_resume(struct device *dev) 462static int ti_pipe3_enable_clocks(struct ti_pipe3 *phy)
445{ 463{
446 u32 ret = 0; 464 int ret = 0;
447 struct ti_pipe3 *phy = dev_get_drvdata(dev); 465 unsigned long flags;
448 466
449 if (!IS_ERR(phy->refclk)) { 467 spin_lock_irqsave(&phy->lock, flags);
450 ret = clk_prepare_enable(phy->refclk); 468 if (phy->enabled)
451 if (ret) { 469 goto err1;
452 dev_err(phy->dev, "Failed to enable refclk %d\n", ret); 470
453 goto err1; 471 ret = ti_pipe3_enable_refclk(phy);
454 } 472 if (ret)
455 } 473 goto err1;
456 474
457 if (!IS_ERR(phy->wkupclk)) { 475 if (!IS_ERR(phy->wkupclk)) {
458 ret = clk_prepare_enable(phy->wkupclk); 476 ret = clk_prepare_enable(phy->wkupclk);
@@ -469,6 +487,9 @@ static int ti_pipe3_runtime_resume(struct device *dev)
469 goto err3; 487 goto err3;
470 } 488 }
471 } 489 }
490
491 phy->enabled = true;
492 spin_unlock_irqrestore(&phy->lock, flags);
472 return 0; 493 return 0;
473 494
474err3: 495err3:
@@ -479,20 +500,80 @@ err2:
479 if (!IS_ERR(phy->refclk)) 500 if (!IS_ERR(phy->refclk))
480 clk_disable_unprepare(phy->refclk); 501 clk_disable_unprepare(phy->refclk);
481 502
503 ti_pipe3_disable_refclk(phy);
482err1: 504err1:
505 spin_unlock_irqrestore(&phy->lock, flags);
483 return ret; 506 return ret;
484} 507}
485 508
509static void ti_pipe3_disable_clocks(struct ti_pipe3 *phy)
510{
511 unsigned long flags;
512
513 spin_lock_irqsave(&phy->lock, flags);
514 if (!phy->enabled) {
515 spin_unlock_irqrestore(&phy->lock, flags);
516 return;
517 }
518
519 if (!IS_ERR(phy->wkupclk))
520 clk_disable_unprepare(phy->wkupclk);
521 /* Don't disable refclk for SATA PHY due to Errata i783 */
522 if (!of_device_is_compatible(phy->dev->of_node, "ti,phy-pipe3-sata"))
523 ti_pipe3_disable_refclk(phy);
524 if (!IS_ERR(phy->div_clk))
525 clk_disable_unprepare(phy->div_clk);
526 phy->enabled = false;
527 spin_unlock_irqrestore(&phy->lock, flags);
528}
529
530static int ti_pipe3_runtime_suspend(struct device *dev)
531{
532 struct ti_pipe3 *phy = dev_get_drvdata(dev);
533
534 ti_pipe3_disable_clocks(phy);
535 return 0;
536}
537
538static int ti_pipe3_runtime_resume(struct device *dev)
539{
540 struct ti_pipe3 *phy = dev_get_drvdata(dev);
541 int ret = 0;
542
543 ret = ti_pipe3_enable_clocks(phy);
544 return ret;
545}
546
547static int ti_pipe3_suspend(struct device *dev)
548{
549 struct ti_pipe3 *phy = dev_get_drvdata(dev);
550
551 ti_pipe3_disable_clocks(phy);
552 return 0;
553}
554
555static int ti_pipe3_resume(struct device *dev)
556{
557 struct ti_pipe3 *phy = dev_get_drvdata(dev);
558 int ret;
559
560 ret = ti_pipe3_enable_clocks(phy);
561 if (ret)
562 return ret;
563
564 pm_runtime_disable(dev);
565 pm_runtime_set_active(dev);
566 pm_runtime_enable(dev);
567 return 0;
568}
569#endif
570
486static const struct dev_pm_ops ti_pipe3_pm_ops = { 571static const struct dev_pm_ops ti_pipe3_pm_ops = {
487 SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend, 572 SET_RUNTIME_PM_OPS(ti_pipe3_runtime_suspend,
488 ti_pipe3_runtime_resume, NULL) 573 ti_pipe3_runtime_resume, NULL)
574 SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume)
489}; 575};
490 576
491#define DEV_PM_OPS (&ti_pipe3_pm_ops)
492#else
493#define DEV_PM_OPS NULL
494#endif
495
496#ifdef CONFIG_OF 577#ifdef CONFIG_OF
497static const struct of_device_id ti_pipe3_id_table[] = { 578static const struct of_device_id ti_pipe3_id_table[] = {
498 { 579 {
@@ -520,7 +601,7 @@ static struct platform_driver ti_pipe3_driver = {
520 .remove = ti_pipe3_remove, 601 .remove = ti_pipe3_remove,
521 .driver = { 602 .driver = {
522 .name = "ti-pipe3", 603 .name = "ti-pipe3",
523 .pm = DEV_PM_OPS, 604 .pm = &ti_pipe3_pm_ops,
524 .of_match_table = of_match_ptr(ti_pipe3_id_table), 605 .of_match_table = of_match_ptr(ti_pipe3_id_table),
525 }, 606 },
526}; 607};
diff --git a/include/linux/mfd/syscon/exynos4-pmu.h b/include/linux/mfd/syscon/exynos4-pmu.h
new file mode 100644
index 000000000000..278b1b1549e9
--- /dev/null
+++ b/include/linux/mfd/syscon/exynos4-pmu.h
@@ -0,0 +1,21 @@
1/*
2 * Copyright (C) 2015 Samsung Electronics Co., Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _LINUX_MFD_SYSCON_PMU_EXYNOS4_H_
10#define _LINUX_MFD_SYSCON_PMU_EXYNOS4_H_
11
12/* Exynos4 PMU register definitions */
13
14/* MIPI_PHYn_CONTROL register offset: n = 0..1 */
15#define EXYNOS4_MIPI_PHY_CONTROL(n) (0x710 + (n) * 4)
16#define EXYNOS4_MIPI_PHY_ENABLE (1 << 0)
17#define EXYNOS4_MIPI_PHY_SRESETN (1 << 1)
18#define EXYNOS4_MIPI_PHY_MRESETN (1 << 2)
19#define EXYNOS4_MIPI_PHY_RESET_MASK (3 << 1)
20
21#endif /* _LINUX_MFD_SYSCON_PMU_EXYNOS4_H_ */