diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-07-13 23:03:50 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2016-07-13 23:03:50 -0400 |
commit | ca2b6faeb96d6d71ebc0627d6679f7b6667cfb00 (patch) | |
tree | f05df9d14c6cf7669caf2c368c597e4f82f290fb | |
parent | 25b1f9acc452209ae0fcc8c1332be852b5c52f53 (diff) | |
parent | c14f8a4032efa73d9c4e155add47c19252b3bdf4 (diff) |
Merge tag 'phy-for-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-testing
Kishon writes:
phy: for 4.8 -rc1
*) Add a new phy_ops for setting the phy mode
*) Add a new phy driver for DA8xx SoC USB PHY
*) Minor fixes and cleanups
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
-rw-r--r-- | Documentation/devicetree/bindings/phy/phy-da8xx-usb.txt | 40 | ||||
-rw-r--r-- | Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | 27 | ||||
-rw-r--r-- | drivers/phy/Kconfig | 10 | ||||
-rw-r--r-- | drivers/phy/Makefile | 1 | ||||
-rw-r--r-- | drivers/phy/phy-core.c | 15 | ||||
-rw-r--r-- | drivers/phy/phy-da8xx-usb.c | 245 | ||||
-rw-r--r-- | drivers/phy/phy-qcom-ufs-qmp-14nm.c | 1 | ||||
-rw-r--r-- | drivers/phy/phy-qcom-ufs-qmp-20nm.c | 1 | ||||
-rw-r--r-- | drivers/phy/phy-rcar-gen3-usb2.c | 26 | ||||
-rw-r--r-- | drivers/phy/phy-rockchip-usb.c | 23 | ||||
-rw-r--r-- | drivers/phy/phy-sun4i-usb.c | 34 | ||||
-rw-r--r-- | drivers/phy/phy-xgene.c | 4 | ||||
-rw-r--r-- | include/linux/phy/phy.h | 17 |
13 files changed, 408 insertions, 36 deletions
diff --git a/Documentation/devicetree/bindings/phy/phy-da8xx-usb.txt b/Documentation/devicetree/bindings/phy/phy-da8xx-usb.txt new file mode 100644 index 000000000000..c26478be391b --- /dev/null +++ b/Documentation/devicetree/bindings/phy/phy-da8xx-usb.txt | |||
@@ -0,0 +1,40 @@ | |||
1 | TI DA8xx/OMAP-L1xx/AM18xx USB PHY | ||
2 | |||
3 | Required properties: | ||
4 | - compatible: must be "ti,da830-usb-phy". | ||
5 | - #phy-cells: must be 1. | ||
6 | |||
7 | This device controls the PHY for both the USB 1.1 OHCI and USB 2.0 OTG | ||
8 | controllers on DA8xx SoCs. Consumers of this device should use index 0 for | ||
9 | the USB 2.0 phy device and index 1 for the USB 1.1 phy device. | ||
10 | |||
11 | It also requires a "syscon" node with compatible = "ti,da830-cfgchip", "syscon" | ||
12 | to access the CFGCHIP2 register. | ||
13 | |||
14 | Example: | ||
15 | |||
16 | cfgchip: cfgchip@1417c { | ||
17 | compatible = "ti,da830-cfgchip", "syscon"; | ||
18 | reg = <0x1417c 0x14>; | ||
19 | }; | ||
20 | |||
21 | usb_phy: usb-phy { | ||
22 | compatible = "ti,da830-usb-phy"; | ||
23 | #phy-cells = <1>; | ||
24 | }; | ||
25 | |||
26 | usb20: usb@200000 { | ||
27 | compatible = "ti,da830-musb"; | ||
28 | reg = <0x200000 0x1000>; | ||
29 | interrupts = <58>; | ||
30 | phys = <&usb_phy 0>; | ||
31 | phy-names = "usb-phy"; | ||
32 | }; | ||
33 | |||
34 | usb11: usb@225000 { | ||
35 | compatible = "ti,da830-ohci"; | ||
36 | reg = <0x225000 0x1000>; | ||
37 | interrupts = <59>; | ||
38 | phys = <&usb_phy 1>; | ||
39 | phy-names = "usb-phy"; | ||
40 | }; | ||
diff --git a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt index 68498d560354..cc6be9680a6d 100644 --- a/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt +++ b/Documentation/devicetree/bindings/phy/rockchip-usb-phy.txt | |||
@@ -5,11 +5,13 @@ Required properties: | |||
5 | "rockchip,rk3066a-usb-phy" | 5 | "rockchip,rk3066a-usb-phy" |
6 | "rockchip,rk3188-usb-phy" | 6 | "rockchip,rk3188-usb-phy" |
7 | "rockchip,rk3288-usb-phy" | 7 | "rockchip,rk3288-usb-phy" |
8 | - rockchip,grf : phandle to the syscon managing the "general | ||
9 | register files" | ||
10 | - #address-cells: should be 1 | 8 | - #address-cells: should be 1 |
11 | - #size-cells: should be 0 | 9 | - #size-cells: should be 0 |
12 | 10 | ||
11 | Deprecated properties: | ||
12 | - rockchip,grf : phandle to the syscon managing the "general | ||
13 | register files" - phy should be a child of the GRF instead | ||
14 | |||
13 | Sub-nodes: | 15 | Sub-nodes: |
14 | Each PHY should be represented as a sub-node. | 16 | Each PHY should be represented as a sub-node. |
15 | 17 | ||
@@ -28,14 +30,19 @@ Optional Properties: | |||
28 | 30 | ||
29 | Example: | 31 | Example: |
30 | 32 | ||
31 | usbphy: phy { | 33 | grf: syscon@ff770000 { |
32 | compatible = "rockchip,rk3288-usb-phy"; | 34 | compatible = "rockchip,rk3288-grf", "syscon", "simple-mfd"; |
33 | rockchip,grf = <&grf>; | 35 | |
34 | #address-cells = <1>; | 36 | ... |
35 | #size-cells = <0>; | 37 | |
38 | usbphy: phy { | ||
39 | compatible = "rockchip,rk3288-usb-phy"; | ||
40 | #address-cells = <1>; | ||
41 | #size-cells = <0>; | ||
36 | 42 | ||
37 | usbphy0: usb-phy0 { | 43 | usbphy0: usb-phy0 { |
38 | #phy-cells = <0>; | 44 | #phy-cells = <0>; |
39 | reg = <0x320>; | 45 | reg = <0x320>; |
46 | }; | ||
40 | }; | 47 | }; |
41 | }; | 48 | }; |
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 8d1cfb7f3ea2..cc0b69545385 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig | |||
@@ -44,6 +44,16 @@ config ARMADA375_USBCLUSTER_PHY | |||
44 | depends on OF && HAS_IOMEM | 44 | depends on OF && HAS_IOMEM |
45 | select GENERIC_PHY | 45 | select GENERIC_PHY |
46 | 46 | ||
47 | config PHY_DA8XX_USB | ||
48 | tristate "TI DA8xx USB PHY Driver" | ||
49 | depends on ARCH_DAVINCI_DA8XX | ||
50 | select GENERIC_PHY | ||
51 | select MFD_SYSCON | ||
52 | help | ||
53 | Enable this to support the USB PHY on DA8xx SoCs. | ||
54 | |||
55 | This driver controls both the USB 1.1 PHY and the USB 2.0 PHY. | ||
56 | |||
47 | config PHY_DM816X_USB | 57 | config PHY_DM816X_USB |
48 | tristate "TI dm816x USB PHY driver" | 58 | tristate "TI dm816x USB PHY driver" |
49 | depends on ARCH_OMAP2PLUS | 59 | depends on ARCH_OMAP2PLUS |
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 9c3e73ccabc4..fa8480e89724 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile | |||
@@ -6,6 +6,7 @@ obj-$(CONFIG_GENERIC_PHY) += phy-core.o | |||
6 | obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o | 6 | obj-$(CONFIG_PHY_BCM_NS_USB2) += phy-bcm-ns-usb2.o |
7 | obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o | 7 | obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o |
8 | obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o | 8 | obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o |
9 | obj-$(CONFIG_PHY_DA8XX_USB) += phy-da8xx-usb.o | ||
9 | obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o | 10 | obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o |
10 | obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o | 11 | obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o |
11 | obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o | 12 | obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o |
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index b72e9a3b6429..8eca906b6e70 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c | |||
@@ -342,6 +342,21 @@ int phy_power_off(struct phy *phy) | |||
342 | } | 342 | } |
343 | EXPORT_SYMBOL_GPL(phy_power_off); | 343 | EXPORT_SYMBOL_GPL(phy_power_off); |
344 | 344 | ||
345 | int phy_set_mode(struct phy *phy, enum phy_mode mode) | ||
346 | { | ||
347 | int ret; | ||
348 | |||
349 | if (!phy || !phy->ops->set_mode) | ||
350 | return 0; | ||
351 | |||
352 | mutex_lock(&phy->mutex); | ||
353 | ret = phy->ops->set_mode(phy, mode); | ||
354 | mutex_unlock(&phy->mutex); | ||
355 | |||
356 | return ret; | ||
357 | } | ||
358 | EXPORT_SYMBOL_GPL(phy_set_mode); | ||
359 | |||
345 | /** | 360 | /** |
346 | * _of_phy_get() - lookup and obtain a reference to a phy by phandle | 361 | * _of_phy_get() - lookup and obtain a reference to a phy by phandle |
347 | * @np: device_node for which to get the phy | 362 | * @np: device_node for which to get the phy |
diff --git a/drivers/phy/phy-da8xx-usb.c b/drivers/phy/phy-da8xx-usb.c new file mode 100644 index 000000000000..b2e59b6170ac --- /dev/null +++ b/drivers/phy/phy-da8xx-usb.c | |||
@@ -0,0 +1,245 @@ | |||
1 | /* | ||
2 | * phy-da8xx-usb - TI DaVinci DA8xx USB PHY driver | ||
3 | * | ||
4 | * Copyright (C) 2016 David Lechner <david@lechnology.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; version 2 of the License. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/clk.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/of.h> | ||
19 | #include <linux/mfd/da8xx-cfgchip.h> | ||
20 | #include <linux/mfd/syscon.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/phy/phy.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/regmap.h> | ||
25 | |||
26 | struct da8xx_usb_phy { | ||
27 | struct phy_provider *phy_provider; | ||
28 | struct phy *usb11_phy; | ||
29 | struct phy *usb20_phy; | ||
30 | struct clk *usb11_clk; | ||
31 | struct clk *usb20_clk; | ||
32 | struct regmap *regmap; | ||
33 | }; | ||
34 | |||
35 | static int da8xx_usb11_phy_power_on(struct phy *phy) | ||
36 | { | ||
37 | struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy); | ||
38 | int ret; | ||
39 | |||
40 | ret = clk_prepare_enable(d_phy->usb11_clk); | ||
41 | if (ret) | ||
42 | return ret; | ||
43 | |||
44 | regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM, | ||
45 | CFGCHIP2_USB1SUSPENDM); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static int da8xx_usb11_phy_power_off(struct phy *phy) | ||
51 | { | ||
52 | struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy); | ||
53 | |||
54 | regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_USB1SUSPENDM, 0); | ||
55 | |||
56 | clk_disable_unprepare(d_phy->usb11_clk); | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | static const struct phy_ops da8xx_usb11_phy_ops = { | ||
62 | .power_on = da8xx_usb11_phy_power_on, | ||
63 | .power_off = da8xx_usb11_phy_power_off, | ||
64 | .owner = THIS_MODULE, | ||
65 | }; | ||
66 | |||
67 | static int da8xx_usb20_phy_power_on(struct phy *phy) | ||
68 | { | ||
69 | struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy); | ||
70 | int ret; | ||
71 | |||
72 | ret = clk_prepare_enable(d_phy->usb20_clk); | ||
73 | if (ret) | ||
74 | return ret; | ||
75 | |||
76 | regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGPWRDN, 0); | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static int da8xx_usb20_phy_power_off(struct phy *phy) | ||
82 | { | ||
83 | struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy); | ||
84 | |||
85 | regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGPWRDN, | ||
86 | CFGCHIP2_OTGPWRDN); | ||
87 | |||
88 | clk_disable_unprepare(d_phy->usb20_clk); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static int da8xx_usb20_phy_set_mode(struct phy *phy, enum phy_mode mode) | ||
94 | { | ||
95 | struct da8xx_usb_phy *d_phy = phy_get_drvdata(phy); | ||
96 | u32 val; | ||
97 | |||
98 | switch (mode) { | ||
99 | case PHY_MODE_USB_HOST: /* Force VBUS valid, ID = 0 */ | ||
100 | val = CFGCHIP2_OTGMODE_FORCE_HOST; | ||
101 | break; | ||
102 | case PHY_MODE_USB_DEVICE: /* Force VBUS valid, ID = 1 */ | ||
103 | val = CFGCHIP2_OTGMODE_FORCE_DEVICE; | ||
104 | break; | ||
105 | case PHY_MODE_USB_OTG: /* Don't override the VBUS/ID comparators */ | ||
106 | val = CFGCHIP2_OTGMODE_NO_OVERRIDE; | ||
107 | break; | ||
108 | default: | ||
109 | return -EINVAL; | ||
110 | } | ||
111 | |||
112 | regmap_write_bits(d_phy->regmap, CFGCHIP(2), CFGCHIP2_OTGMODE_MASK, | ||
113 | val); | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static const struct phy_ops da8xx_usb20_phy_ops = { | ||
119 | .power_on = da8xx_usb20_phy_power_on, | ||
120 | .power_off = da8xx_usb20_phy_power_off, | ||
121 | .set_mode = da8xx_usb20_phy_set_mode, | ||
122 | .owner = THIS_MODULE, | ||
123 | }; | ||
124 | |||
125 | static struct phy *da8xx_usb_phy_of_xlate(struct device *dev, | ||
126 | struct of_phandle_args *args) | ||
127 | { | ||
128 | struct da8xx_usb_phy *d_phy = dev_get_drvdata(dev); | ||
129 | |||
130 | if (!d_phy) | ||
131 | return ERR_PTR(-ENODEV); | ||
132 | |||
133 | switch (args->args[0]) { | ||
134 | case 0: | ||
135 | return d_phy->usb20_phy; | ||
136 | case 1: | ||
137 | return d_phy->usb11_phy; | ||
138 | default: | ||
139 | return ERR_PTR(-EINVAL); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | static int da8xx_usb_phy_probe(struct platform_device *pdev) | ||
144 | { | ||
145 | struct device *dev = &pdev->dev; | ||
146 | struct device_node *node = dev->of_node; | ||
147 | struct da8xx_usb_phy *d_phy; | ||
148 | |||
149 | d_phy = devm_kzalloc(dev, sizeof(*d_phy), GFP_KERNEL); | ||
150 | if (!d_phy) | ||
151 | return -ENOMEM; | ||
152 | |||
153 | if (node) | ||
154 | d_phy->regmap = syscon_regmap_lookup_by_compatible( | ||
155 | "ti,da830-cfgchip"); | ||
156 | else | ||
157 | d_phy->regmap = syscon_regmap_lookup_by_pdevname("syscon.0"); | ||
158 | if (IS_ERR(d_phy->regmap)) { | ||
159 | dev_err(dev, "Failed to get syscon\n"); | ||
160 | return PTR_ERR(d_phy->regmap); | ||
161 | } | ||
162 | |||
163 | d_phy->usb11_clk = devm_clk_get(dev, "usb11_phy"); | ||
164 | if (IS_ERR(d_phy->usb11_clk)) { | ||
165 | dev_err(dev, "Failed to get usb11_phy clock\n"); | ||
166 | return PTR_ERR(d_phy->usb11_clk); | ||
167 | } | ||
168 | |||
169 | d_phy->usb20_clk = devm_clk_get(dev, "usb20_phy"); | ||
170 | if (IS_ERR(d_phy->usb20_clk)) { | ||
171 | dev_err(dev, "Failed to get usb20_phy clock\n"); | ||
172 | return PTR_ERR(d_phy->usb20_clk); | ||
173 | } | ||
174 | |||
175 | d_phy->usb11_phy = devm_phy_create(dev, node, &da8xx_usb11_phy_ops); | ||
176 | if (IS_ERR(d_phy->usb11_phy)) { | ||
177 | dev_err(dev, "Failed to create usb11 phy\n"); | ||
178 | return PTR_ERR(d_phy->usb11_phy); | ||
179 | } | ||
180 | |||
181 | d_phy->usb20_phy = devm_phy_create(dev, node, &da8xx_usb20_phy_ops); | ||
182 | if (IS_ERR(d_phy->usb20_phy)) { | ||
183 | dev_err(dev, "Failed to create usb20 phy\n"); | ||
184 | return PTR_ERR(d_phy->usb20_phy); | ||
185 | } | ||
186 | |||
187 | platform_set_drvdata(pdev, d_phy); | ||
188 | phy_set_drvdata(d_phy->usb11_phy, d_phy); | ||
189 | phy_set_drvdata(d_phy->usb20_phy, d_phy); | ||
190 | |||
191 | if (node) { | ||
192 | d_phy->phy_provider = devm_of_phy_provider_register(dev, | ||
193 | da8xx_usb_phy_of_xlate); | ||
194 | if (IS_ERR(d_phy->phy_provider)) { | ||
195 | dev_err(dev, "Failed to create phy provider\n"); | ||
196 | return PTR_ERR(d_phy->phy_provider); | ||
197 | } | ||
198 | } else { | ||
199 | int ret; | ||
200 | |||
201 | ret = phy_create_lookup(d_phy->usb11_phy, "usb-phy", "ohci.0"); | ||
202 | if (ret) | ||
203 | dev_warn(dev, "Failed to create usb11 phy lookup\n"); | ||
204 | ret = phy_create_lookup(d_phy->usb20_phy, "usb-phy", | ||
205 | "musb-da8xx"); | ||
206 | if (ret) | ||
207 | dev_warn(dev, "Failed to create usb20 phy lookup\n"); | ||
208 | } | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | static int da8xx_usb_phy_remove(struct platform_device *pdev) | ||
214 | { | ||
215 | struct da8xx_usb_phy *d_phy = platform_get_drvdata(pdev); | ||
216 | |||
217 | if (!pdev->dev.of_node) { | ||
218 | phy_remove_lookup(d_phy->usb20_phy, "usb-phy", "musb-da8xx"); | ||
219 | phy_remove_lookup(d_phy->usb11_phy, "usb-phy", "ohci.0"); | ||
220 | } | ||
221 | |||
222 | return 0; | ||
223 | } | ||
224 | |||
225 | static const struct of_device_id da8xx_usb_phy_ids[] = { | ||
226 | { .compatible = "ti,da830-usb-phy" }, | ||
227 | { } | ||
228 | }; | ||
229 | MODULE_DEVICE_TABLE(of, da8xx_usb_phy_ids); | ||
230 | |||
231 | static struct platform_driver da8xx_usb_phy_driver = { | ||
232 | .probe = da8xx_usb_phy_probe, | ||
233 | .remove = da8xx_usb_phy_remove, | ||
234 | .driver = { | ||
235 | .name = "da8xx-usb-phy", | ||
236 | .of_match_table = da8xx_usb_phy_ids, | ||
237 | }, | ||
238 | }; | ||
239 | |||
240 | module_platform_driver(da8xx_usb_phy_driver); | ||
241 | |||
242 | MODULE_ALIAS("platform:da8xx-usb-phy"); | ||
243 | MODULE_AUTHOR("David Lechner <david@lechnology.com>"); | ||
244 | MODULE_DESCRIPTION("TI DA8xx USB PHY driver"); | ||
245 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/phy/phy-qcom-ufs-qmp-14nm.c b/drivers/phy/phy-qcom-ufs-qmp-14nm.c index 56631e77c11d..6ee51490f786 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-14nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-14nm.c | |||
@@ -140,7 +140,6 @@ static int ufs_qcom_phy_qmp_14nm_probe(struct platform_device *pdev) | |||
140 | 140 | ||
141 | phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); | 141 | phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); |
142 | if (!phy) { | 142 | if (!phy) { |
143 | dev_err(dev, "%s: failed to allocate phy\n", __func__); | ||
144 | err = -ENOMEM; | 143 | err = -ENOMEM; |
145 | goto out; | 144 | goto out; |
146 | } | 145 | } |
diff --git a/drivers/phy/phy-qcom-ufs-qmp-20nm.c b/drivers/phy/phy-qcom-ufs-qmp-20nm.c index b16ea77d07b9..770087ab05e2 100644 --- a/drivers/phy/phy-qcom-ufs-qmp-20nm.c +++ b/drivers/phy/phy-qcom-ufs-qmp-20nm.c | |||
@@ -196,7 +196,6 @@ static int ufs_qcom_phy_qmp_20nm_probe(struct platform_device *pdev) | |||
196 | 196 | ||
197 | phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); | 197 | phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); |
198 | if (!phy) { | 198 | if (!phy) { |
199 | dev_err(dev, "%s: failed to allocate phy\n", __func__); | ||
200 | err = -ENOMEM; | 199 | err = -ENOMEM; |
201 | goto out; | 200 | goto out; |
202 | } | 201 | } |
diff --git a/drivers/phy/phy-rcar-gen3-usb2.c b/drivers/phy/phy-rcar-gen3-usb2.c index 4be3f5dbbc9f..31156c9c4707 100644 --- a/drivers/phy/phy-rcar-gen3-usb2.c +++ b/drivers/phy/phy-rcar-gen3-usb2.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/phy/phy.h> | 21 | #include <linux/phy/phy.h> |
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
24 | #include <linux/workqueue.h> | ||
24 | 25 | ||
25 | /******* USB2.0 Host registers (original offset is +0x200) *******/ | 26 | /******* USB2.0 Host registers (original offset is +0x200) *******/ |
26 | #define USB2_INT_ENABLE 0x000 | 27 | #define USB2_INT_ENABLE 0x000 |
@@ -81,9 +82,25 @@ struct rcar_gen3_chan { | |||
81 | struct extcon_dev *extcon; | 82 | struct extcon_dev *extcon; |
82 | struct phy *phy; | 83 | struct phy *phy; |
83 | struct regulator *vbus; | 84 | struct regulator *vbus; |
85 | struct work_struct work; | ||
86 | bool extcon_host; | ||
84 | bool has_otg; | 87 | bool has_otg; |
85 | }; | 88 | }; |
86 | 89 | ||
90 | static void rcar_gen3_phy_usb2_work(struct work_struct *work) | ||
91 | { | ||
92 | struct rcar_gen3_chan *ch = container_of(work, struct rcar_gen3_chan, | ||
93 | work); | ||
94 | |||
95 | if (ch->extcon_host) { | ||
96 | extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, true); | ||
97 | extcon_set_cable_state_(ch->extcon, EXTCON_USB, false); | ||
98 | } else { | ||
99 | extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, false); | ||
100 | extcon_set_cable_state_(ch->extcon, EXTCON_USB, true); | ||
101 | } | ||
102 | } | ||
103 | |||
87 | static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host) | 104 | static void rcar_gen3_set_host_mode(struct rcar_gen3_chan *ch, int host) |
88 | { | 105 | { |
89 | void __iomem *usb2_base = ch->base; | 106 | void __iomem *usb2_base = ch->base; |
@@ -130,8 +147,8 @@ static void rcar_gen3_init_for_host(struct rcar_gen3_chan *ch) | |||
130 | rcar_gen3_set_host_mode(ch, 1); | 147 | rcar_gen3_set_host_mode(ch, 1); |
131 | rcar_gen3_enable_vbus_ctrl(ch, 1); | 148 | rcar_gen3_enable_vbus_ctrl(ch, 1); |
132 | 149 | ||
133 | extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, true); | 150 | ch->extcon_host = true; |
134 | extcon_set_cable_state_(ch->extcon, EXTCON_USB, false); | 151 | schedule_work(&ch->work); |
135 | } | 152 | } |
136 | 153 | ||
137 | static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) | 154 | static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) |
@@ -140,8 +157,8 @@ static void rcar_gen3_init_for_peri(struct rcar_gen3_chan *ch) | |||
140 | rcar_gen3_set_host_mode(ch, 0); | 157 | rcar_gen3_set_host_mode(ch, 0); |
141 | rcar_gen3_enable_vbus_ctrl(ch, 0); | 158 | rcar_gen3_enable_vbus_ctrl(ch, 0); |
142 | 159 | ||
143 | extcon_set_cable_state_(ch->extcon, EXTCON_USB_HOST, false); | 160 | ch->extcon_host = false; |
144 | extcon_set_cable_state_(ch->extcon, EXTCON_USB, true); | 161 | schedule_work(&ch->work); |
145 | } | 162 | } |
146 | 163 | ||
147 | static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) | 164 | static bool rcar_gen3_check_id(struct rcar_gen3_chan *ch) |
@@ -301,6 +318,7 @@ static int rcar_gen3_phy_usb2_probe(struct platform_device *pdev) | |||
301 | if (irq >= 0) { | 318 | if (irq >= 0) { |
302 | int ret; | 319 | int ret; |
303 | 320 | ||
321 | INIT_WORK(&channel->work, rcar_gen3_phy_usb2_work); | ||
304 | irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq, | 322 | irq = devm_request_irq(dev, irq, rcar_gen3_phy_usb2_irq, |
305 | IRQF_SHARED, dev_name(dev), channel); | 323 | IRQF_SHARED, dev_name(dev), channel); |
306 | if (irq < 0) | 324 | if (irq < 0) |
diff --git a/drivers/phy/phy-rockchip-usb.c b/drivers/phy/phy-rockchip-usb.c index d60b149cff0f..2a7381f4fe4c 100644 --- a/drivers/phy/phy-rockchip-usb.c +++ b/drivers/phy/phy-rockchip-usb.c | |||
@@ -236,9 +236,10 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base, | |||
236 | goto err_clk_prov; | 236 | goto err_clk_prov; |
237 | } | 237 | } |
238 | 238 | ||
239 | err = devm_add_action(base->dev, rockchip_usb_phy_action, rk_phy); | 239 | err = devm_add_action_or_reset(base->dev, rockchip_usb_phy_action, |
240 | rk_phy); | ||
240 | if (err) | 241 | if (err) |
241 | goto err_devm_action; | 242 | return err; |
242 | 243 | ||
243 | rk_phy->phy = devm_phy_create(base->dev, child, &ops); | 244 | rk_phy->phy = devm_phy_create(base->dev, child, &ops); |
244 | if (IS_ERR(rk_phy->phy)) { | 245 | if (IS_ERR(rk_phy->phy)) { |
@@ -256,9 +257,6 @@ static int rockchip_usb_phy_init(struct rockchip_usb_phy_base *base, | |||
256 | else | 257 | else |
257 | return rockchip_usb_phy_power(rk_phy, 1); | 258 | return rockchip_usb_phy_power(rk_phy, 1); |
258 | 259 | ||
259 | err_devm_action: | ||
260 | if (!rk_phy->uart_enabled) | ||
261 | of_clk_del_provider(child); | ||
262 | err_clk_prov: | 260 | err_clk_prov: |
263 | if (!rk_phy->uart_enabled) | 261 | if (!rk_phy->uart_enabled) |
264 | clk_unregister(rk_phy->clk480m); | 262 | clk_unregister(rk_phy->clk480m); |
@@ -397,8 +395,13 @@ static int rockchip_usb_phy_probe(struct platform_device *pdev) | |||
397 | phy_base->pdata = match->data; | 395 | phy_base->pdata = match->data; |
398 | 396 | ||
399 | phy_base->dev = dev; | 397 | phy_base->dev = dev; |
400 | phy_base->reg_base = syscon_regmap_lookup_by_phandle(dev->of_node, | 398 | phy_base->reg_base = ERR_PTR(-ENODEV); |
401 | "rockchip,grf"); | 399 | if (dev->parent && dev->parent->of_node) |
400 | phy_base->reg_base = syscon_node_to_regmap( | ||
401 | dev->parent->of_node); | ||
402 | if (IS_ERR(phy_base->reg_base)) | ||
403 | phy_base->reg_base = syscon_regmap_lookup_by_phandle( | ||
404 | dev->of_node, "rockchip,grf"); | ||
402 | if (IS_ERR(phy_base->reg_base)) { | 405 | if (IS_ERR(phy_base->reg_base)) { |
403 | dev_err(&pdev->dev, "Missing rockchip,grf property\n"); | 406 | dev_err(&pdev->dev, "Missing rockchip,grf property\n"); |
404 | return PTR_ERR(phy_base->reg_base); | 407 | return PTR_ERR(phy_base->reg_base); |
@@ -463,7 +466,11 @@ static int __init rockchip_init_usb_uart(void) | |||
463 | return -ENOTSUPP; | 466 | return -ENOTSUPP; |
464 | } | 467 | } |
465 | 468 | ||
466 | grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); | 469 | grf = ERR_PTR(-ENODEV); |
470 | if (np->parent) | ||
471 | grf = syscon_node_to_regmap(np->parent); | ||
472 | if (IS_ERR(grf)) | ||
473 | grf = syscon_regmap_lookup_by_phandle(np, "rockchip,grf"); | ||
467 | if (IS_ERR(grf)) { | 474 | if (IS_ERR(grf)) { |
468 | pr_err("%s: Missing rockchip,grf property, %lu\n", | 475 | pr_err("%s: Missing rockchip,grf property, %lu\n", |
469 | __func__, PTR_ERR(grf)); | 476 | __func__, PTR_ERR(grf)); |
diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index de3101fbbf40..0a45bc6088ae 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c | |||
@@ -94,6 +94,7 @@ | |||
94 | 94 | ||
95 | enum sun4i_usb_phy_type { | 95 | enum sun4i_usb_phy_type { |
96 | sun4i_a10_phy, | 96 | sun4i_a10_phy, |
97 | sun6i_a31_phy, | ||
97 | sun8i_a33_phy, | 98 | sun8i_a33_phy, |
98 | sun8i_h3_phy, | 99 | sun8i_h3_phy, |
99 | }; | 100 | }; |
@@ -122,7 +123,6 @@ struct sun4i_usb_phy_data { | |||
122 | /* phy0 / otg related variables */ | 123 | /* phy0 / otg related variables */ |
123 | struct extcon_dev *extcon; | 124 | struct extcon_dev *extcon; |
124 | bool phy0_init; | 125 | bool phy0_init; |
125 | bool phy0_poll; | ||
126 | struct gpio_desc *id_det_gpio; | 126 | struct gpio_desc *id_det_gpio; |
127 | struct gpio_desc *vbus_det_gpio; | 127 | struct gpio_desc *vbus_det_gpio; |
128 | struct power_supply *vbus_power_supply; | 128 | struct power_supply *vbus_power_supply; |
@@ -343,6 +343,24 @@ static bool sun4i_usb_phy0_have_vbus_det(struct sun4i_usb_phy_data *data) | |||
343 | return data->vbus_det_gpio || data->vbus_power_supply; | 343 | return data->vbus_det_gpio || data->vbus_power_supply; |
344 | } | 344 | } |
345 | 345 | ||
346 | static bool sun4i_usb_phy0_poll(struct sun4i_usb_phy_data *data) | ||
347 | { | ||
348 | if ((data->id_det_gpio && data->id_det_irq <= 0) || | ||
349 | (data->vbus_det_gpio && data->vbus_det_irq <= 0)) | ||
350 | return true; | ||
351 | |||
352 | /* | ||
353 | * The A31 companion pmic (axp221) does not generate vbus change | ||
354 | * interrupts when the board is driving vbus, so we must poll | ||
355 | * when using the pmic for vbus-det _and_ we're driving vbus. | ||
356 | */ | ||
357 | if (data->cfg->type == sun6i_a31_phy && | ||
358 | data->vbus_power_supply && data->phys[0].regulator_on) | ||
359 | return true; | ||
360 | |||
361 | return false; | ||
362 | } | ||
363 | |||
346 | static int sun4i_usb_phy_power_on(struct phy *_phy) | 364 | static int sun4i_usb_phy_power_on(struct phy *_phy) |
347 | { | 365 | { |
348 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); | 366 | struct sun4i_usb_phy *phy = phy_get_drvdata(_phy); |
@@ -364,7 +382,7 @@ static int sun4i_usb_phy_power_on(struct phy *_phy) | |||
364 | phy->regulator_on = true; | 382 | phy->regulator_on = true; |
365 | 383 | ||
366 | /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */ | 384 | /* We must report Vbus high within OTG_TIME_A_WAIT_VRISE msec. */ |
367 | if (phy->index == 0 && data->vbus_det_gpio && data->phy0_poll) | 385 | if (phy->index == 0 && sun4i_usb_phy0_poll(data)) |
368 | mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME); | 386 | mod_delayed_work(system_wq, &data->detect, DEBOUNCE_TIME); |
369 | 387 | ||
370 | return 0; | 388 | return 0; |
@@ -385,7 +403,7 @@ static int sun4i_usb_phy_power_off(struct phy *_phy) | |||
385 | * phy0 vbus typically slowly discharges, sometimes this causes the | 403 | * phy0 vbus typically slowly discharges, sometimes this causes the |
386 | * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan. | 404 | * Vbus gpio to not trigger an edge irq on Vbus off, so force a rescan. |
387 | */ | 405 | */ |
388 | if (phy->index == 0 && data->vbus_det_gpio && !data->phy0_poll) | 406 | if (phy->index == 0 && !sun4i_usb_phy0_poll(data)) |
389 | mod_delayed_work(system_wq, &data->detect, POLL_TIME); | 407 | mod_delayed_work(system_wq, &data->detect, POLL_TIME); |
390 | 408 | ||
391 | return 0; | 409 | return 0; |
@@ -468,7 +486,7 @@ static void sun4i_usb_phy0_id_vbus_det_scan(struct work_struct *work) | |||
468 | if (vbus_notify) | 486 | if (vbus_notify) |
469 | extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det); | 487 | extcon_set_cable_state_(data->extcon, EXTCON_USB, vbus_det); |
470 | 488 | ||
471 | if (data->phy0_poll) | 489 | if (sun4i_usb_phy0_poll(data)) |
472 | queue_delayed_work(system_wq, &data->detect, POLL_TIME); | 490 | queue_delayed_work(system_wq, &data->detect, POLL_TIME); |
473 | } | 491 | } |
474 | 492 | ||
@@ -644,11 +662,6 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
644 | } | 662 | } |
645 | 663 | ||
646 | data->id_det_irq = gpiod_to_irq(data->id_det_gpio); | 664 | data->id_det_irq = gpiod_to_irq(data->id_det_gpio); |
647 | data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio); | ||
648 | if ((data->id_det_gpio && data->id_det_irq <= 0) || | ||
649 | (data->vbus_det_gpio && data->vbus_det_irq <= 0)) | ||
650 | data->phy0_poll = true; | ||
651 | |||
652 | if (data->id_det_irq > 0) { | 665 | if (data->id_det_irq > 0) { |
653 | ret = devm_request_irq(dev, data->id_det_irq, | 666 | ret = devm_request_irq(dev, data->id_det_irq, |
654 | sun4i_usb_phy0_id_vbus_det_irq, | 667 | sun4i_usb_phy0_id_vbus_det_irq, |
@@ -660,6 +673,7 @@ static int sun4i_usb_phy_probe(struct platform_device *pdev) | |||
660 | } | 673 | } |
661 | } | 674 | } |
662 | 675 | ||
676 | data->vbus_det_irq = gpiod_to_irq(data->vbus_det_gpio); | ||
663 | if (data->vbus_det_irq > 0) { | 677 | if (data->vbus_det_irq > 0) { |
664 | ret = devm_request_irq(dev, data->vbus_det_irq, | 678 | ret = devm_request_irq(dev, data->vbus_det_irq, |
665 | sun4i_usb_phy0_id_vbus_det_irq, | 679 | sun4i_usb_phy0_id_vbus_det_irq, |
@@ -711,7 +725,7 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { | |||
711 | 725 | ||
712 | static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { | 726 | static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { |
713 | .num_phys = 3, | 727 | .num_phys = 3, |
714 | .type = sun4i_a10_phy, | 728 | .type = sun6i_a31_phy, |
715 | .disc_thresh = 3, | 729 | .disc_thresh = 3, |
716 | .phyctl_offset = REG_PHYCTL_A10, | 730 | .phyctl_offset = REG_PHYCTL_A10, |
717 | .dedicated_clocks = true, | 731 | .dedicated_clocks = true, |
diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c index 385362e5b2f6..ae266e0c8368 100644 --- a/drivers/phy/phy-xgene.c +++ b/drivers/phy/phy-xgene.c | |||
@@ -518,7 +518,7 @@ enum clk_type_t { | |||
518 | CLK_INT_SING = 2, /* Internal single ended */ | 518 | CLK_INT_SING = 2, /* Internal single ended */ |
519 | }; | 519 | }; |
520 | 520 | ||
521 | enum phy_mode { | 521 | enum xgene_phy_mode { |
522 | MODE_SATA = 0, /* List them for simple reference */ | 522 | MODE_SATA = 0, /* List them for simple reference */ |
523 | MODE_SGMII = 1, | 523 | MODE_SGMII = 1, |
524 | MODE_PCIE = 2, | 524 | MODE_PCIE = 2, |
@@ -542,7 +542,7 @@ struct xgene_sata_override_param { | |||
542 | struct xgene_phy_ctx { | 542 | struct xgene_phy_ctx { |
543 | struct device *dev; | 543 | struct device *dev; |
544 | struct phy *phy; | 544 | struct phy *phy; |
545 | enum phy_mode mode; /* Mode of operation */ | 545 | enum xgene_phy_mode mode; /* Mode of operation */ |
546 | enum clk_type_t clk_type; /* Input clock selection */ | 546 | enum clk_type_t clk_type; /* Input clock selection */ |
547 | void __iomem *sds_base; /* PHY CSR base addr */ | 547 | void __iomem *sds_base; /* PHY CSR base addr */ |
548 | struct clk *clk; /* Optional clock */ | 548 | struct clk *clk; /* Optional clock */ |
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index a810f2a18842..f08b67238b58 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h | |||
@@ -22,12 +22,20 @@ | |||
22 | 22 | ||
23 | struct phy; | 23 | struct phy; |
24 | 24 | ||
25 | enum phy_mode { | ||
26 | PHY_MODE_INVALID, | ||
27 | PHY_MODE_USB_HOST, | ||
28 | PHY_MODE_USB_DEVICE, | ||
29 | PHY_MODE_USB_OTG, | ||
30 | }; | ||
31 | |||
25 | /** | 32 | /** |
26 | * struct phy_ops - set of function pointers for performing phy operations | 33 | * struct phy_ops - set of function pointers for performing phy operations |
27 | * @init: operation to be performed for initializing phy | 34 | * @init: operation to be performed for initializing phy |
28 | * @exit: operation to be performed while exiting | 35 | * @exit: operation to be performed while exiting |
29 | * @power_on: powering on the phy | 36 | * @power_on: powering on the phy |
30 | * @power_off: powering off the phy | 37 | * @power_off: powering off the phy |
38 | * @set_mode: set the mode of the phy | ||
31 | * @owner: the module owner containing the ops | 39 | * @owner: the module owner containing the ops |
32 | */ | 40 | */ |
33 | struct phy_ops { | 41 | struct phy_ops { |
@@ -35,6 +43,7 @@ struct phy_ops { | |||
35 | int (*exit)(struct phy *phy); | 43 | int (*exit)(struct phy *phy); |
36 | int (*power_on)(struct phy *phy); | 44 | int (*power_on)(struct phy *phy); |
37 | int (*power_off)(struct phy *phy); | 45 | int (*power_off)(struct phy *phy); |
46 | int (*set_mode)(struct phy *phy, enum phy_mode mode); | ||
38 | struct module *owner; | 47 | struct module *owner; |
39 | }; | 48 | }; |
40 | 49 | ||
@@ -126,6 +135,7 @@ int phy_init(struct phy *phy); | |||
126 | int phy_exit(struct phy *phy); | 135 | int phy_exit(struct phy *phy); |
127 | int phy_power_on(struct phy *phy); | 136 | int phy_power_on(struct phy *phy); |
128 | int phy_power_off(struct phy *phy); | 137 | int phy_power_off(struct phy *phy); |
138 | int phy_set_mode(struct phy *phy, enum phy_mode mode); | ||
129 | static inline int phy_get_bus_width(struct phy *phy) | 139 | static inline int phy_get_bus_width(struct phy *phy) |
130 | { | 140 | { |
131 | return phy->attrs.bus_width; | 141 | return phy->attrs.bus_width; |
@@ -233,6 +243,13 @@ static inline int phy_power_off(struct phy *phy) | |||
233 | return -ENOSYS; | 243 | return -ENOSYS; |
234 | } | 244 | } |
235 | 245 | ||
246 | static inline int phy_set_mode(struct phy *phy, enum phy_mode mode) | ||
247 | { | ||
248 | if (!phy) | ||
249 | return 0; | ||
250 | return -ENOSYS; | ||
251 | } | ||
252 | |||
236 | static inline int phy_get_bus_width(struct phy *phy) | 253 | static inline int phy_get_bus_width(struct phy *phy) |
237 | { | 254 | { |
238 | return -ENOSYS; | 255 | return -ENOSYS; |