aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/phy
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/Kconfig18
-rw-r--r--drivers/phy/Makefile2
-rw-r--r--drivers/phy/phy-berlin-sata.c2
-rw-r--r--drivers/phy/phy-berlin-usb.c19
-rw-r--r--drivers/phy/phy-dm816x-usb.c290
-rw-r--r--drivers/phy/phy-exynos5-usbdrd.c10
-rw-r--r--drivers/phy/phy-miphy28lp.c5
-rw-r--r--drivers/phy/phy-miphy365x.c14
-rw-r--r--drivers/phy/phy-omap-control.c10
-rw-r--r--drivers/phy/phy-omap-usb2.c6
-rw-r--r--drivers/phy/phy-qcom-ufs.c33
-rw-r--r--drivers/phy/phy-samsung-usb2.c10
-rw-r--r--drivers/phy/phy-spear1310-miphy.c4
-rw-r--r--drivers/phy/phy-spear1340-miphy.c4
-rw-r--r--drivers/phy/phy-stih41x-usb.c8
-rw-r--r--drivers/phy/phy-sun9i-usb.c202
-rw-r--r--drivers/phy/phy-ti-pipe3.c9
-rw-r--r--drivers/phy/phy-xgene.c23
18 files changed, 580 insertions, 89 deletions
diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
index 2962de205ba7..a53bd5b52df9 100644
--- a/drivers/phy/Kconfig
+++ b/drivers/phy/Kconfig
@@ -35,6 +35,13 @@ config ARMADA375_USBCLUSTER_PHY
35 depends on OF 35 depends on OF
36 select GENERIC_PHY 36 select GENERIC_PHY
37 37
38config PHY_DM816X_USB
39 tristate "TI dm816x USB PHY driver"
40 depends on ARCH_OMAP2PLUS
41 select GENERIC_PHY
42 help
43 Enable this for dm816x USB to work.
44
38config PHY_EXYNOS_MIPI_VIDEO 45config PHY_EXYNOS_MIPI_VIDEO
39 tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver" 46 tristate "S5P/EXYNOS SoC series MIPI CSI-2/DSI PHY driver"
40 depends on HAS_IOMEM 47 depends on HAS_IOMEM
@@ -174,6 +181,17 @@ config PHY_SUN4I_USB
174 This driver controls the entire USB PHY block, both the USB OTG 181 This driver controls the entire USB PHY block, both the USB OTG
175 parts, as well as the 2 regular USB 2 host PHYs. 182 parts, as well as the 2 regular USB 2 host PHYs.
176 183
184config PHY_SUN9I_USB
185 tristate "Allwinner sun9i SoC USB PHY driver"
186 depends on ARCH_SUNXI && HAS_IOMEM && OF
187 depends on RESET_CONTROLLER
188 select GENERIC_PHY
189 help
190 Enable this to support the transceiver that is part of Allwinner
191 sun9i SoCs.
192
193 This driver controls each individual USB 2 host PHY.
194
177config PHY_SAMSUNG_USB2 195config PHY_SAMSUNG_USB2
178 tristate "Samsung USB 2.0 PHY driver" 196 tristate "Samsung USB 2.0 PHY driver"
179 depends on HAS_IOMEM 197 depends on HAS_IOMEM
diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
index f080e1bb2a74..f12625178780 100644
--- a/drivers/phy/Makefile
+++ b/drivers/phy/Makefile
@@ -5,6 +5,7 @@
5obj-$(CONFIG_GENERIC_PHY) += phy-core.o 5obj-$(CONFIG_GENERIC_PHY) += phy-core.o
6obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o 6obj-$(CONFIG_PHY_BERLIN_USB) += phy-berlin-usb.o
7obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o 7obj-$(CONFIG_PHY_BERLIN_SATA) += phy-berlin-sata.o
8obj-$(CONFIG_PHY_DM816X_USB) += phy-dm816x-usb.o
8obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o 9obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY) += phy-armada375-usb2.o
9obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o 10obj-$(CONFIG_BCM_KONA_USB2_PHY) += phy-bcm-kona-usb2.o
10obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o 11obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o
@@ -20,6 +21,7 @@ obj-$(CONFIG_TWL4030_USB) += phy-twl4030-usb.o
20obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o 21obj-$(CONFIG_PHY_EXYNOS5250_SATA) += phy-exynos5250-sata.o
21obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o 22obj-$(CONFIG_PHY_HIX5HD2_SATA) += phy-hix5hd2-sata.o
22obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o 23obj-$(CONFIG_PHY_SUN4I_USB) += phy-sun4i-usb.o
24obj-$(CONFIG_PHY_SUN9I_USB) += phy-sun9i-usb.o
23obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o 25obj-$(CONFIG_PHY_SAMSUNG_USB2) += phy-exynos-usb2.o
24phy-exynos-usb2-y += phy-samsung-usb2.o 26phy-exynos-usb2-y += phy-samsung-usb2.o
25phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o 27phy-exynos-usb2-$(CONFIG_PHY_EXYNOS4210_USB2) += phy-exynos4210-usb2.o
diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c
index 099eee8851e5..6f3e06d687de 100644
--- a/drivers/phy/phy-berlin-sata.c
+++ b/drivers/phy/phy-berlin-sata.c
@@ -218,7 +218,7 @@ static int phy_berlin_sata_probe(struct platform_device *pdev)
218 if (priv->nphys == 0) 218 if (priv->nphys == 0)
219 return -ENODEV; 219 return -ENODEV;
220 220
221 priv->phys = devm_kzalloc(dev, priv->nphys * sizeof(*priv->phys), 221 priv->phys = devm_kcalloc(dev, priv->nphys, sizeof(*priv->phys),
222 GFP_KERNEL); 222 GFP_KERNEL);
223 if (!priv->phys) 223 if (!priv->phys)
224 return -ENOMEM; 224 return -ENOMEM;
diff --git a/drivers/phy/phy-berlin-usb.c b/drivers/phy/phy-berlin-usb.c
index c8a8d53a6ece..c6fc95b53083 100644
--- a/drivers/phy/phy-berlin-usb.c
+++ b/drivers/phy/phy-berlin-usb.c
@@ -103,9 +103,6 @@
103#define MODE_TEST_EN BIT(11) 103#define MODE_TEST_EN BIT(11)
104#define ANA_TEST_DC_CTRL(x) ((x) << 12) 104#define ANA_TEST_DC_CTRL(x) ((x) << 12)
105 105
106#define to_phy_berlin_usb_priv(p) \
107 container_of((p), struct phy_berlin_usb_priv, phy)
108
109static const u32 phy_berlin_pll_dividers[] = { 106static const u32 phy_berlin_pll_dividers[] = {
110 /* Berlin 2 */ 107 /* Berlin 2 */
111 CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54), 108 CLK_REF_DIV(0xc) | FEEDBACK_CLK_DIV(0x54),
@@ -115,14 +112,13 @@ static const u32 phy_berlin_pll_dividers[] = {
115 112
116struct phy_berlin_usb_priv { 113struct phy_berlin_usb_priv {
117 void __iomem *base; 114 void __iomem *base;
118 struct phy *phy;
119 struct reset_control *rst_ctrl; 115 struct reset_control *rst_ctrl;
120 u32 pll_divider; 116 u32 pll_divider;
121}; 117};
122 118
123static int phy_berlin_usb_power_on(struct phy *phy) 119static int phy_berlin_usb_power_on(struct phy *phy)
124{ 120{
125 struct phy_berlin_usb_priv *priv = dev_get_drvdata(phy->dev.parent); 121 struct phy_berlin_usb_priv *priv = phy_get_drvdata(phy);
126 122
127 reset_control_reset(priv->rst_ctrl); 123 reset_control_reset(priv->rst_ctrl);
128 124
@@ -175,6 +171,7 @@ static int phy_berlin_usb_probe(struct platform_device *pdev)
175 of_match_device(phy_berlin_sata_of_match, &pdev->dev); 171 of_match_device(phy_berlin_sata_of_match, &pdev->dev);
176 struct phy_berlin_usb_priv *priv; 172 struct phy_berlin_usb_priv *priv;
177 struct resource *res; 173 struct resource *res;
174 struct phy *phy;
178 struct phy_provider *phy_provider; 175 struct phy_provider *phy_provider;
179 176
180 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 177 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -192,20 +189,18 @@ static int phy_berlin_usb_probe(struct platform_device *pdev)
192 189
193 priv->pll_divider = *((u32 *)match->data); 190 priv->pll_divider = *((u32 *)match->data);
194 191
195 priv->phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops); 192 phy = devm_phy_create(&pdev->dev, NULL, &phy_berlin_usb_ops);
196 if (IS_ERR(priv->phy)) { 193 if (IS_ERR(phy)) {
197 dev_err(&pdev->dev, "failed to create PHY\n"); 194 dev_err(&pdev->dev, "failed to create PHY\n");
198 return PTR_ERR(priv->phy); 195 return PTR_ERR(phy);
199 } 196 }
200 197
201 platform_set_drvdata(pdev, priv); 198 platform_set_drvdata(pdev, priv);
199 phy_set_drvdata(phy, priv);
202 200
203 phy_provider = 201 phy_provider =
204 devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate); 202 devm_of_phy_provider_register(&pdev->dev, of_phy_simple_xlate);
205 if (IS_ERR(phy_provider)) 203 return PTR_ERR_OR_ZERO(phy_provider);
206 return PTR_ERR(phy_provider);
207
208 return 0;
209} 204}
210 205
211static struct platform_driver phy_berlin_usb_driver = { 206static struct platform_driver phy_berlin_usb_driver = {
diff --git a/drivers/phy/phy-dm816x-usb.c b/drivers/phy/phy-dm816x-usb.c
new file mode 100644
index 000000000000..7b42555ddd51
--- /dev/null
+++ b/drivers/phy/phy-dm816x-usb.c
@@ -0,0 +1,290 @@
1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation version 2.
5 *
6 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
7 * kind, whether express or implied; without even the implied warranty
8 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 */
11
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/regmap.h>
15
16#include <linux/slab.h>
17#include <linux/of.h>
18#include <linux/io.h>
19#include <linux/usb/phy_companion.h>
20#include <linux/clk.h>
21#include <linux/err.h>
22#include <linux/pm_runtime.h>
23#include <linux/delay.h>
24#include <linux/phy/phy.h>
25#include <linux/of_platform.h>
26
27#include <linux/mfd/syscon.h>
28
29/*
30 * TRM has two sets of USB_CTRL registers.. The correct register bits
31 * are in TRM section 24.9.8.2 USB_CTRL Register. The TRM documents the
32 * phy as being SR70LX Synopsys USB 2.0 OTG nanoPHY. It also seems at
33 * least dm816x rev c ignores writes to USB_CTRL register, but the TI
34 * kernel is writing to those so it's possible that later revisions
35 * have worknig USB_CTRL register.
36 *
37 * Also note that At least USB_CTRL register seems to be dm816x specific
38 * according to the TRM. It's possible that USBPHY_CTRL is more generic,
39 * but that would have to be checked against the SR70LX documentation
40 * which does not seem to be publicly available.
41 *
42 * Finally, the phy on dm814x and am335x is different from dm816x.
43 */
44#define DM816X_USB_CTRL_PHYCLKSRC BIT(8) /* 1 = PLL ref clock */
45#define DM816X_USB_CTRL_PHYSLEEP1 BIT(1) /* Enable the first phy */
46#define DM816X_USB_CTRL_PHYSLEEP0 BIT(0) /* Enable the second phy */
47
48#define DM816X_USBPHY_CTRL_TXRISETUNE 1
49#define DM816X_USBPHY_CTRL_TXVREFTUNE 0xc
50#define DM816X_USBPHY_CTRL_TXPREEMTUNE 0x2
51
52struct dm816x_usb_phy {
53 struct regmap *syscon;
54 struct device *dev;
55 unsigned int instance;
56 struct clk *refclk;
57 struct usb_phy phy;
58 unsigned int usb_ctrl; /* Shared between phy0 and phy1 */
59 unsigned int usbphy_ctrl;
60};
61
62static int dm816x_usb_phy_set_host(struct usb_otg *otg, struct usb_bus *host)
63{
64 otg->host = host;
65 if (!host)
66 otg->state = OTG_STATE_UNDEFINED;
67
68 return 0;
69}
70
71static int dm816x_usb_phy_set_peripheral(struct usb_otg *otg,
72 struct usb_gadget *gadget)
73{
74 otg->gadget = gadget;
75 if (!gadget)
76 otg->state = OTG_STATE_UNDEFINED;
77
78 return 0;
79}
80
81static int dm816x_usb_phy_init(struct phy *x)
82{
83 struct dm816x_usb_phy *phy = phy_get_drvdata(x);
84 unsigned int val;
85 int error;
86
87 if (clk_get_rate(phy->refclk) != 24000000)
88 dev_warn(phy->dev, "nonstandard phy refclk\n");
89
90 /* Set PLL ref clock and put phys to sleep */
91 error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
92 DM816X_USB_CTRL_PHYCLKSRC |
93 DM816X_USB_CTRL_PHYSLEEP1 |
94 DM816X_USB_CTRL_PHYSLEEP0,
95 0);
96 regmap_read(phy->syscon, phy->usb_ctrl, &val);
97 if ((val & 3) != 0)
98 dev_info(phy->dev,
99 "Working dm816x USB_CTRL! (0x%08x)\n",
100 val);
101
102 /*
103 * TI kernel sets these values for "symmetrical eye diagram and
104 * better signal quality" so let's assume somebody checked the
105 * values with a scope and set them here too.
106 */
107 regmap_read(phy->syscon, phy->usbphy_ctrl, &val);
108 val |= DM816X_USBPHY_CTRL_TXRISETUNE |
109 DM816X_USBPHY_CTRL_TXVREFTUNE |
110 DM816X_USBPHY_CTRL_TXPREEMTUNE;
111 regmap_write(phy->syscon, phy->usbphy_ctrl, val);
112
113 return 0;
114}
115
116static struct phy_ops ops = {
117 .init = dm816x_usb_phy_init,
118 .owner = THIS_MODULE,
119};
120
121static int dm816x_usb_phy_runtime_suspend(struct device *dev)
122{
123 struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
124 unsigned int mask, val;
125 int error = 0;
126
127 mask = BIT(phy->instance);
128 val = ~BIT(phy->instance);
129 error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
130 mask, val);
131 if (error)
132 dev_err(phy->dev, "phy%i failed to power off\n",
133 phy->instance);
134 clk_disable(phy->refclk);
135
136 return 0;
137}
138
139static int dm816x_usb_phy_runtime_resume(struct device *dev)
140{
141 struct dm816x_usb_phy *phy = dev_get_drvdata(dev);
142 unsigned int mask, val;
143 int error;
144
145 error = clk_enable(phy->refclk);
146 if (error)
147 return error;
148
149 /*
150 * Note that at least dm816x rev c does not seem to do
151 * anything with the USB_CTRL register. But let's follow
152 * what the TI tree is doing in case later revisions use
153 * USB_CTRL.
154 */
155 mask = BIT(phy->instance);
156 val = BIT(phy->instance);
157 error = regmap_update_bits(phy->syscon, phy->usb_ctrl,
158 mask, val);
159 if (error) {
160 dev_err(phy->dev, "phy%i failed to power on\n",
161 phy->instance);
162 clk_disable(phy->refclk);
163 return error;
164 }
165
166 return 0;
167}
168
169static UNIVERSAL_DEV_PM_OPS(dm816x_usb_phy_pm_ops,
170 dm816x_usb_phy_runtime_suspend,
171 dm816x_usb_phy_runtime_resume,
172 NULL);
173
174#ifdef CONFIG_OF
175static const struct of_device_id dm816x_usb_phy_id_table[] = {
176 {
177 .compatible = "ti,dm8168-usb-phy",
178 },
179 {},
180};
181MODULE_DEVICE_TABLE(of, dm816x_usb_phy_id_table);
182#endif
183
184static int dm816x_usb_phy_probe(struct platform_device *pdev)
185{
186 struct dm816x_usb_phy *phy;
187 struct resource *res;
188 struct phy *generic_phy;
189 struct phy_provider *phy_provider;
190 struct usb_otg *otg;
191 const struct of_device_id *of_id;
192 const struct usb_phy_data *phy_data;
193 int error;
194
195 of_id = of_match_device(of_match_ptr(dm816x_usb_phy_id_table),
196 &pdev->dev);
197 if (!of_id)
198 return -EINVAL;
199
200 phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
201 if (!phy)
202 return -ENOMEM;
203
204 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
205 if (!res)
206 return -ENOENT;
207
208 phy->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
209 "syscon");
210 if (IS_ERR(phy->syscon))
211 return PTR_ERR(phy->syscon);
212
213 /*
214 * According to sprs614e.pdf, the first usb_ctrl is shared and
215 * the second instance for usb_ctrl is reserved.. Also the
216 * register bits are different from earlier TRMs.
217 */
218 phy->usb_ctrl = 0x20;
219 phy->usbphy_ctrl = (res->start & 0xff) + 4;
220 if (phy->usbphy_ctrl == 0x2c)
221 phy->instance = 1;
222
223 phy_data = of_id->data;
224
225 otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL);
226 if (!otg)
227 return -ENOMEM;
228
229 phy->dev = &pdev->dev;
230 phy->phy.dev = phy->dev;
231 phy->phy.label = "dm8168_usb_phy";
232 phy->phy.otg = otg;
233 phy->phy.type = USB_PHY_TYPE_USB2;
234 otg->set_host = dm816x_usb_phy_set_host;
235 otg->set_peripheral = dm816x_usb_phy_set_peripheral;
236 otg->usb_phy = &phy->phy;
237
238 platform_set_drvdata(pdev, phy);
239
240 phy->refclk = devm_clk_get(phy->dev, "refclk");
241 if (IS_ERR(phy->refclk))
242 return PTR_ERR(phy->refclk);
243 error = clk_prepare(phy->refclk);
244 if (error)
245 return error;
246
247 pm_runtime_enable(phy->dev);
248 generic_phy = devm_phy_create(phy->dev, NULL, &ops);
249 if (IS_ERR(generic_phy))
250 return PTR_ERR(generic_phy);
251
252 phy_set_drvdata(generic_phy, phy);
253
254 phy_provider = devm_of_phy_provider_register(phy->dev,
255 of_phy_simple_xlate);
256 if (IS_ERR(phy_provider))
257 return PTR_ERR(phy_provider);
258
259 usb_add_phy_dev(&phy->phy);
260
261 return 0;
262}
263
264static int dm816x_usb_phy_remove(struct platform_device *pdev)
265{
266 struct dm816x_usb_phy *phy = platform_get_drvdata(pdev);
267
268 usb_remove_phy(&phy->phy);
269 pm_runtime_disable(phy->dev);
270 clk_unprepare(phy->refclk);
271
272 return 0;
273}
274
275static struct platform_driver dm816x_usb_phy_driver = {
276 .probe = dm816x_usb_phy_probe,
277 .remove = dm816x_usb_phy_remove,
278 .driver = {
279 .name = "dm816x-usb-phy",
280 .pm = &dm816x_usb_phy_pm_ops,
281 .of_match_table = of_match_ptr(dm816x_usb_phy_id_table),
282 },
283};
284
285module_platform_driver(dm816x_usb_phy_driver);
286
287MODULE_ALIAS("platform:dm816x_usb");
288MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
289MODULE_DESCRIPTION("dm816x usb phy driver");
290MODULE_LICENSE("GPL v2");
diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c
index e2a0be750ad9..d72ef15b0d68 100644
--- a/drivers/phy/phy-exynos5-usbdrd.c
+++ b/drivers/phy/phy-exynos5-usbdrd.c
@@ -624,6 +624,13 @@ static const struct exynos5_usbdrd_phy_drvdata exynos5250_usbdrd_phy = {
624 .has_common_clk_gate = true, 624 .has_common_clk_gate = true,
625}; 625};
626 626
627static const struct exynos5_usbdrd_phy_drvdata exynos5433_usbdrd_phy = {
628 .phy_cfg = phy_cfg_exynos5,
629 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
630 .pmu_offset_usbdrd1_phy = EXYNOS5433_USBHOST30_PHY_CONTROL,
631 .has_common_clk_gate = false,
632};
633
627static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = { 634static const struct exynos5_usbdrd_phy_drvdata exynos7_usbdrd_phy = {
628 .phy_cfg = phy_cfg_exynos5, 635 .phy_cfg = phy_cfg_exynos5,
629 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL, 636 .pmu_offset_usbdrd0_phy = EXYNOS5_USBDRD_PHY_CONTROL,
@@ -638,6 +645,9 @@ static const struct of_device_id exynos5_usbdrd_phy_of_match[] = {
638 .compatible = "samsung,exynos5420-usbdrd-phy", 645 .compatible = "samsung,exynos5420-usbdrd-phy",
639 .data = &exynos5420_usbdrd_phy 646 .data = &exynos5420_usbdrd_phy
640 }, { 647 }, {
648 .compatible = "samsung,exynos5433-usbdrd-phy",
649 .data = &exynos5433_usbdrd_phy
650 }, {
641 .compatible = "samsung,exynos7-usbdrd-phy", 651 .compatible = "samsung,exynos7-usbdrd-phy",
642 .data = &exynos7_usbdrd_phy 652 .data = &exynos7_usbdrd_phy
643 }, 653 },
diff --git a/drivers/phy/phy-miphy28lp.c b/drivers/phy/phy-miphy28lp.c
index 933435214acc..c4cc11dcb2a2 100644
--- a/drivers/phy/phy-miphy28lp.c
+++ b/drivers/phy/phy-miphy28lp.c
@@ -1259,10 +1259,7 @@ static int miphy28lp_probe(struct platform_device *pdev)
1259 } 1259 }
1260 1260
1261 provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate); 1261 provider = devm_of_phy_provider_register(&pdev->dev, miphy28lp_xlate);
1262 if (IS_ERR(provider)) 1262 return PTR_ERR_OR_ZERO(provider);
1263 return PTR_ERR(provider);
1264
1265 return 0;
1266} 1263}
1267 1264
1268static const struct of_device_id miphy28lp_of_match[] = { 1265static const struct of_device_id miphy28lp_of_match[] = {
diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c
index 51b459db9137..019c2d75344e 100644
--- a/drivers/phy/phy-miphy365x.c
+++ b/drivers/phy/phy-miphy365x.c
@@ -25,7 +25,7 @@
25#include <linux/mfd/syscon.h> 25#include <linux/mfd/syscon.h>
26#include <linux/regmap.h> 26#include <linux/regmap.h>
27 27
28#include <dt-bindings/phy/phy-miphy365x.h> 28#include <dt-bindings/phy/phy.h>
29 29
30#define HFC_TIMEOUT 100 30#define HFC_TIMEOUT 100
31 31
@@ -177,7 +177,7 @@ static u8 rx_tx_spd[] = {
177static int miphy365x_set_path(struct miphy365x_phy *miphy_phy, 177static int miphy365x_set_path(struct miphy365x_phy *miphy_phy,
178 struct miphy365x_dev *miphy_dev) 178 struct miphy365x_dev *miphy_dev)
179{ 179{
180 bool sata = (miphy_phy->type == MIPHY_TYPE_SATA); 180 bool sata = (miphy_phy->type == PHY_TYPE_SATA);
181 181
182 return regmap_update_bits(miphy_dev->regmap, 182 return regmap_update_bits(miphy_dev->regmap,
183 miphy_phy->ctrlreg, 183 miphy_phy->ctrlreg,
@@ -431,7 +431,7 @@ static int miphy365x_init(struct phy *phy)
431 } 431 }
432 432
433 /* Initialise Miphy for PCIe or SATA */ 433 /* Initialise Miphy for PCIe or SATA */
434 if (miphy_phy->type == MIPHY_TYPE_PCIE) 434 if (miphy_phy->type == PHY_TYPE_PCIE)
435 ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev); 435 ret = miphy365x_init_pcie_port(miphy_phy, miphy_dev);
436 else 436 else
437 ret = miphy365x_init_sata_port(miphy_phy, miphy_dev); 437 ret = miphy365x_init_sata_port(miphy_phy, miphy_dev);
@@ -455,8 +455,8 @@ int miphy365x_get_addr(struct device *dev, struct miphy365x_phy *miphy_phy,
455 return ret; 455 return ret;
456 } 456 }
457 457
458 if (!((!strncmp(name, "sata", 4) && type == MIPHY_TYPE_SATA) || 458 if (!((!strncmp(name, "sata", 4) && type == PHY_TYPE_SATA) ||
459 (!strncmp(name, "pcie", 4) && type == MIPHY_TYPE_PCIE))) 459 (!strncmp(name, "pcie", 4) && type == PHY_TYPE_PCIE)))
460 return 0; 460 return 0;
461 461
462 miphy_phy->base = of_iomap(phynode, index); 462 miphy_phy->base = of_iomap(phynode, index);
@@ -499,8 +499,8 @@ static struct phy *miphy365x_xlate(struct device *dev,
499 499
500 miphy_phy->type = args->args[0]; 500 miphy_phy->type = args->args[0];
501 501
502 if (!(miphy_phy->type == MIPHY_TYPE_SATA || 502 if (!(miphy_phy->type == PHY_TYPE_SATA ||
503 miphy_phy->type == MIPHY_TYPE_PCIE)) { 503 miphy_phy->type == PHY_TYPE_PCIE)) {
504 dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type); 504 dev_err(dev, "Unsupported device type: %d\n", miphy_phy->type);
505 return ERR_PTR(-EINVAL); 505 return ERR_PTR(-EINVAL);
506 } 506 }
diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c
index 93252e053a31..e9c41b3fa0ee 100644
--- a/drivers/phy/phy-omap-control.c
+++ b/drivers/phy/phy-omap-control.c
@@ -216,7 +216,6 @@ void omap_control_usb_set_mode(struct device *dev,
216 return; 216 return;
217 217
218 ctrl_phy = dev_get_drvdata(dev); 218 ctrl_phy = dev_get_drvdata(dev);
219
220 if (!ctrl_phy) { 219 if (!ctrl_phy) {
221 dev_err(dev, "Invalid control phy device\n"); 220 dev_err(dev, "Invalid control phy device\n");
222 return; 221 return;
@@ -241,8 +240,6 @@ void omap_control_usb_set_mode(struct device *dev,
241} 240}
242EXPORT_SYMBOL_GPL(omap_control_usb_set_mode); 241EXPORT_SYMBOL_GPL(omap_control_usb_set_mode);
243 242
244#ifdef CONFIG_OF
245
246static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS; 243static const enum omap_control_phy_type otghs_data = OMAP_CTRL_TYPE_OTGHS;
247static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2; 244static const enum omap_control_phy_type usb2_data = OMAP_CTRL_TYPE_USB2;
248static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3; 245static const enum omap_control_phy_type pipe3_data = OMAP_CTRL_TYPE_PIPE3;
@@ -278,8 +275,6 @@ static const struct of_device_id omap_control_phy_id_table[] = {
278 {}, 275 {},
279}; 276};
280MODULE_DEVICE_TABLE(of, omap_control_phy_id_table); 277MODULE_DEVICE_TABLE(of, omap_control_phy_id_table);
281#endif
282
283 278
284static int omap_control_phy_probe(struct platform_device *pdev) 279static int omap_control_phy_probe(struct platform_device *pdev)
285{ 280{
@@ -287,8 +282,7 @@ static int omap_control_phy_probe(struct platform_device *pdev)
287 const struct of_device_id *of_id; 282 const struct of_device_id *of_id;
288 struct omap_control_phy *control_phy; 283 struct omap_control_phy *control_phy;
289 284
290 of_id = of_match_device(of_match_ptr(omap_control_phy_id_table), 285 of_id = of_match_device(omap_control_phy_id_table, &pdev->dev);
291 &pdev->dev);
292 if (!of_id) 286 if (!of_id)
293 return -EINVAL; 287 return -EINVAL;
294 288
@@ -344,7 +338,7 @@ static struct platform_driver omap_control_phy_driver = {
344 .probe = omap_control_phy_probe, 338 .probe = omap_control_phy_probe,
345 .driver = { 339 .driver = {
346 .name = "omap-control-phy", 340 .name = "omap-control-phy",
347 .of_match_table = of_match_ptr(omap_control_phy_id_table), 341 .of_match_table = omap_control_phy_id_table,
348 }, 342 },
349}; 343};
350 344
diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c
index 4757e765696a..183ef4368101 100644
--- a/drivers/phy/phy-omap-usb2.c
+++ b/drivers/phy/phy-omap-usb2.c
@@ -144,7 +144,6 @@ static struct phy_ops ops = {
144 .owner = THIS_MODULE, 144 .owner = THIS_MODULE,
145}; 145};
146 146
147#ifdef CONFIG_OF
148static const struct usb_phy_data omap_usb2_data = { 147static const struct usb_phy_data omap_usb2_data = {
149 .label = "omap_usb2", 148 .label = "omap_usb2",
150 .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS, 149 .flags = OMAP_USB2_HAS_START_SRP | OMAP_USB2_HAS_SET_VBUS,
@@ -185,7 +184,6 @@ static const struct of_device_id omap_usb2_id_table[] = {
185 {}, 184 {},
186}; 185};
187MODULE_DEVICE_TABLE(of, omap_usb2_id_table); 186MODULE_DEVICE_TABLE(of, omap_usb2_id_table);
188#endif
189 187
190static int omap_usb2_probe(struct platform_device *pdev) 188static int omap_usb2_probe(struct platform_device *pdev)
191{ 189{
@@ -200,7 +198,7 @@ static int omap_usb2_probe(struct platform_device *pdev)
200 const struct of_device_id *of_id; 198 const struct of_device_id *of_id;
201 struct usb_phy_data *phy_data; 199 struct usb_phy_data *phy_data;
202 200
203 of_id = of_match_device(of_match_ptr(omap_usb2_id_table), &pdev->dev); 201 of_id = of_match_device(omap_usb2_id_table, &pdev->dev);
204 202
205 if (!of_id) 203 if (!of_id)
206 return -EINVAL; 204 return -EINVAL;
@@ -378,7 +376,7 @@ static struct platform_driver omap_usb2_driver = {
378 .driver = { 376 .driver = {
379 .name = "omap-usb2", 377 .name = "omap-usb2",
380 .pm = DEV_PM_OPS, 378 .pm = DEV_PM_OPS,
381 .of_match_table = of_match_ptr(omap_usb2_id_table), 379 .of_match_table = omap_usb2_id_table,
382 }, 380 },
383}; 381};
384 382
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
index 86665e9dc399..f9c618f0ab6e 100644
--- a/drivers/phy/phy-qcom-ufs.c
+++ b/drivers/phy/phy-qcom-ufs.c
@@ -73,6 +73,7 @@ int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
73out: 73out:
74 return ret; 74 return ret;
75} 75}
76EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate);
76 77
77struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev, 78struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
78 struct ufs_qcom_phy *common_cfg, 79 struct ufs_qcom_phy *common_cfg,
@@ -101,6 +102,7 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
101 if (IS_ERR(generic_phy)) { 102 if (IS_ERR(generic_phy)) {
102 err = PTR_ERR(generic_phy); 103 err = PTR_ERR(generic_phy);
103 dev_err(dev, "%s: failed to create phy %d\n", __func__, err); 104 dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
105 generic_phy = NULL;
104 goto out; 106 goto out;
105 } 107 }
106 108
@@ -110,6 +112,7 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
110out: 112out:
111 return generic_phy; 113 return generic_phy;
112} 114}
115EXPORT_SYMBOL_GPL(ufs_qcom_phy_generic_probe);
113 116
114/* 117/*
115 * This assumes the embedded phy structure inside generic_phy is of type 118 * This assumes the embedded phy structure inside generic_phy is of type
@@ -121,6 +124,7 @@ struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy)
121{ 124{
122 return (struct ufs_qcom_phy *)phy_get_drvdata(generic_phy); 125 return (struct ufs_qcom_phy *)phy_get_drvdata(generic_phy);
123} 126}
127EXPORT_SYMBOL_GPL(get_ufs_qcom_phy);
124 128
125static 129static
126int ufs_qcom_phy_base_init(struct platform_device *pdev, 130int ufs_qcom_phy_base_init(struct platform_device *pdev,
@@ -131,40 +135,23 @@ int ufs_qcom_phy_base_init(struct platform_device *pdev,
131 int err = 0; 135 int err = 0;
132 136
133 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem"); 137 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_mem");
134 if (!res) {
135 dev_err(dev, "%s: phy_mem resource not found\n", __func__);
136 err = -ENOMEM;
137 goto out;
138 }
139
140 phy_common->mmio = devm_ioremap_resource(dev, res); 138 phy_common->mmio = devm_ioremap_resource(dev, res);
141 if (IS_ERR((void const *)phy_common->mmio)) { 139 if (IS_ERR((void const *)phy_common->mmio)) {
142 err = PTR_ERR((void const *)phy_common->mmio); 140 err = PTR_ERR((void const *)phy_common->mmio);
143 phy_common->mmio = NULL; 141 phy_common->mmio = NULL;
144 dev_err(dev, "%s: ioremap for phy_mem resource failed %d\n", 142 dev_err(dev, "%s: ioremap for phy_mem resource failed %d\n",
145 __func__, err); 143 __func__, err);
146 goto out; 144 return err;
147 } 145 }
148 146
149 /* "dev_ref_clk_ctrl_mem" is optional resource */ 147 /* "dev_ref_clk_ctrl_mem" is optional resource */
150 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, 148 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
151 "dev_ref_clk_ctrl_mem"); 149 "dev_ref_clk_ctrl_mem");
152 if (!res) {
153 dev_dbg(dev, "%s: dev_ref_clk_ctrl_mem resource not found\n",
154 __func__);
155 goto out;
156 }
157
158 phy_common->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res); 150 phy_common->dev_ref_clk_ctrl_mmio = devm_ioremap_resource(dev, res);
159 if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio)) { 151 if (IS_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio))
160 err = PTR_ERR((void const *)phy_common->dev_ref_clk_ctrl_mmio);
161 phy_common->dev_ref_clk_ctrl_mmio = NULL; 152 phy_common->dev_ref_clk_ctrl_mmio = NULL;
162 dev_err(dev, "%s: ioremap for dev_ref_clk_ctrl_mem resource failed %d\n",
163 __func__, err);
164 }
165 153
166out: 154 return 0;
167 return err;
168} 155}
169 156
170static int __ufs_qcom_phy_clk_get(struct phy *phy, 157static int __ufs_qcom_phy_clk_get(struct phy *phy,
@@ -228,6 +215,7 @@ ufs_qcom_phy_init_clks(struct phy *generic_phy,
228out: 215out:
229 return err; 216 return err;
230} 217}
218EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_clks);
231 219
232int 220int
233ufs_qcom_phy_init_vregulators(struct phy *generic_phy, 221ufs_qcom_phy_init_vregulators(struct phy *generic_phy,
@@ -252,6 +240,7 @@ ufs_qcom_phy_init_vregulators(struct phy *generic_phy,
252out: 240out:
253 return err; 241 return err;
254} 242}
243EXPORT_SYMBOL_GPL(ufs_qcom_phy_init_vregulators);
255 244
256static int __ufs_qcom_phy_init_vreg(struct phy *phy, 245static int __ufs_qcom_phy_init_vreg(struct phy *phy,
257 struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional) 246 struct ufs_qcom_phy_vreg *vreg, const char *name, bool optional)
@@ -647,6 +636,7 @@ int ufs_qcom_phy_remove(struct phy *generic_phy,
647 636
648 return 0; 637 return 0;
649} 638}
639EXPORT_SYMBOL_GPL(ufs_qcom_phy_remove);
650 640
651int ufs_qcom_phy_exit(struct phy *generic_phy) 641int ufs_qcom_phy_exit(struct phy *generic_phy)
652{ 642{
@@ -657,6 +647,7 @@ int ufs_qcom_phy_exit(struct phy *generic_phy)
657 647
658 return 0; 648 return 0;
659} 649}
650EXPORT_SYMBOL_GPL(ufs_qcom_phy_exit);
660 651
661int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy) 652int ufs_qcom_phy_is_pcs_ready(struct phy *generic_phy)
662{ 653{
@@ -725,6 +716,7 @@ out_disable_phy:
725out: 716out:
726 return err; 717 return err;
727} 718}
719EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_on);
728 720
729int ufs_qcom_phy_power_off(struct phy *generic_phy) 721int ufs_qcom_phy_power_off(struct phy *generic_phy)
730{ 722{
@@ -743,3 +735,4 @@ int ufs_qcom_phy_power_off(struct phy *generic_phy)
743 735
744 return 0; 736 return 0;
745} 737}
738EXPORT_SYMBOL_GPL(ufs_qcom_phy_power_off);
diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c
index 4a12f66b7fb5..55b6994932e3 100644
--- a/drivers/phy/phy-samsung-usb2.c
+++ b/drivers/phy/phy-samsung-usb2.c
@@ -37,10 +37,14 @@ static int samsung_usb2_phy_power_on(struct phy *phy)
37 spin_lock(&drv->lock); 37 spin_lock(&drv->lock);
38 ret = inst->cfg->power_on(inst); 38 ret = inst->cfg->power_on(inst);
39 spin_unlock(&drv->lock); 39 spin_unlock(&drv->lock);
40 if (ret)
41 goto err_power_on;
40 } 42 }
41 43
42 return 0; 44 return 0;
43 45
46err_power_on:
47 clk_disable_unprepare(drv->ref_clk);
44err_instance_clk: 48err_instance_clk:
45 clk_disable_unprepare(drv->clk); 49 clk_disable_unprepare(drv->clk);
46err_main_clk: 50err_main_clk:
@@ -51,7 +55,7 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
51{ 55{
52 struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy); 56 struct samsung_usb2_phy_instance *inst = phy_get_drvdata(phy);
53 struct samsung_usb2_phy_driver *drv = inst->drv; 57 struct samsung_usb2_phy_driver *drv = inst->drv;
54 int ret = 0; 58 int ret;
55 59
56 dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n", 60 dev_dbg(drv->dev, "Request to power_off \"%s\" usb phy\n",
57 inst->cfg->label); 61 inst->cfg->label);
@@ -59,10 +63,12 @@ static int samsung_usb2_phy_power_off(struct phy *phy)
59 spin_lock(&drv->lock); 63 spin_lock(&drv->lock);
60 ret = inst->cfg->power_off(inst); 64 ret = inst->cfg->power_off(inst);
61 spin_unlock(&drv->lock); 65 spin_unlock(&drv->lock);
66 if (ret)
67 return ret;
62 } 68 }
63 clk_disable_unprepare(drv->ref_clk); 69 clk_disable_unprepare(drv->ref_clk);
64 clk_disable_unprepare(drv->clk); 70 clk_disable_unprepare(drv->clk);
65 return ret; 71 return 0;
66} 72}
67 73
68static struct phy_ops samsung_usb2_phy_ops = { 74static struct phy_ops samsung_usb2_phy_ops = {
diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/phy-spear1310-miphy.c
index 9f47fae7eecb..65ae640cfbd1 100644
--- a/drivers/phy/phy-spear1310-miphy.c
+++ b/drivers/phy/phy-spear1310-miphy.c
@@ -192,14 +192,14 @@ static struct phy *spear1310_miphy_xlate(struct device *dev,
192 192
193 if (args->args_count < 1) { 193 if (args->args_count < 1) {
194 dev_err(dev, "DT did not pass correct no of args\n"); 194 dev_err(dev, "DT did not pass correct no of args\n");
195 return NULL; 195 return ERR_PTR(-ENODEV);
196 } 196 }
197 197
198 priv->mode = args->args[0]; 198 priv->mode = args->args[0];
199 199
200 if (priv->mode != SATA && priv->mode != PCIE) { 200 if (priv->mode != SATA && priv->mode != PCIE) {
201 dev_err(dev, "DT did not pass correct phy mode\n"); 201 dev_err(dev, "DT did not pass correct phy mode\n");
202 return NULL; 202 return ERR_PTR(-ENODEV);
203 } 203 }
204 204
205 return priv->phy; 205 return priv->phy;
diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/phy-spear1340-miphy.c
index e42bc200275f..1a00c2817f34 100644
--- a/drivers/phy/phy-spear1340-miphy.c
+++ b/drivers/phy/phy-spear1340-miphy.c
@@ -229,14 +229,14 @@ static struct phy *spear1340_miphy_xlate(struct device *dev,
229 229
230 if (args->args_count < 1) { 230 if (args->args_count < 1) {
231 dev_err(dev, "DT did not pass correct no of args\n"); 231 dev_err(dev, "DT did not pass correct no of args\n");
232 return NULL; 232 return ERR_PTR(-ENODEV);
233 } 233 }
234 234
235 priv->mode = args->args[0]; 235 priv->mode = args->args[0];
236 236
237 if (priv->mode != SATA && priv->mode != PCIE) { 237 if (priv->mode != SATA && priv->mode != PCIE) {
238 dev_err(dev, "DT did not pass correct phy mode\n"); 238 dev_err(dev, "DT did not pass correct phy mode\n");
239 return NULL; 239 return ERR_PTR(-ENODEV);
240 } 240 }
241 241
242 return priv->phy; 242 return priv->phy;
diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c
index a603801293ff..c093b472b57d 100644
--- a/drivers/phy/phy-stih41x-usb.c
+++ b/drivers/phy/phy-stih41x-usb.c
@@ -87,8 +87,12 @@ static int stih41x_usb_phy_power_on(struct phy *phy)
87 return ret; 87 return ret;
88 } 88 }
89 89
90 return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, 90 ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg,
91 phy_dev->cfg->oscok, phy_dev->cfg->oscok); 91 phy_dev->cfg->oscok, phy_dev->cfg->oscok);
92 if (ret)
93 clk_disable_unprepare(phy_dev->clk);
94
95 return ret;
92} 96}
93 97
94static int stih41x_usb_phy_power_off(struct phy *phy) 98static int stih41x_usb_phy_power_off(struct phy *phy)
diff --git a/drivers/phy/phy-sun9i-usb.c b/drivers/phy/phy-sun9i-usb.c
new file mode 100644
index 000000000000..0095914a662c
--- /dev/null
+++ b/drivers/phy/phy-sun9i-usb.c
@@ -0,0 +1,202 @@
1/*
2 * Allwinner sun9i USB phy driver
3 *
4 * Copyright (C) 2014-2015 Chen-Yu Tsai <wens@csie.org>
5 *
6 * Based on phy-sun4i-usb.c from
7 * Hans de Goede <hdegoede@redhat.com>
8 *
9 * and code from
10 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 */
22
23#include <linux/clk.h>
24#include <linux/err.h>
25#include <linux/io.h>
26#include <linux/module.h>
27#include <linux/phy/phy.h>
28#include <linux/usb/of.h>
29#include <linux/platform_device.h>
30#include <linux/reset.h>
31
32#define SUNXI_AHB_INCR16_BURST_EN BIT(11)
33#define SUNXI_AHB_INCR8_BURST_EN BIT(10)
34#define SUNXI_AHB_INCR4_BURST_EN BIT(9)
35#define SUNXI_AHB_INCRX_ALIGN_EN BIT(8)
36#define SUNXI_ULPI_BYPASS_EN BIT(0)
37
38/* usb1 HSIC specific bits */
39#define SUNXI_EHCI_HS_FORCE BIT(20)
40#define SUNXI_HSIC_CONNECT_DET BIT(17)
41#define SUNXI_HSIC_CONNECT_INT BIT(16)
42#define SUNXI_HSIC BIT(1)
43
44struct sun9i_usb_phy {
45 struct phy *phy;
46 void __iomem *pmu;
47 struct reset_control *reset;
48 struct clk *clk;
49 struct clk *hsic_clk;
50 enum usb_phy_interface type;
51};
52
53static void sun9i_usb_phy_passby(struct sun9i_usb_phy *phy, int enable)
54{
55 u32 bits, reg_value;
56
57 bits = SUNXI_AHB_INCR16_BURST_EN | SUNXI_AHB_INCR8_BURST_EN |
58 SUNXI_AHB_INCR4_BURST_EN | SUNXI_AHB_INCRX_ALIGN_EN |
59 SUNXI_ULPI_BYPASS_EN;
60
61 if (phy->type == USBPHY_INTERFACE_MODE_HSIC)
62 bits |= SUNXI_HSIC | SUNXI_EHCI_HS_FORCE |
63 SUNXI_HSIC_CONNECT_DET | SUNXI_HSIC_CONNECT_INT;
64
65 reg_value = readl(phy->pmu);
66
67 if (enable)
68 reg_value |= bits;
69 else
70 reg_value &= ~bits;
71
72 writel(reg_value, phy->pmu);
73}
74
75static int sun9i_usb_phy_init(struct phy *_phy)
76{
77 struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
78 int ret;
79
80 ret = clk_prepare_enable(phy->clk);
81 if (ret)
82 goto err_clk;
83
84 ret = clk_prepare_enable(phy->hsic_clk);
85 if (ret)
86 goto err_hsic_clk;
87
88 ret = reset_control_deassert(phy->reset);
89 if (ret)
90 goto err_reset;
91
92 sun9i_usb_phy_passby(phy, 1);
93 return 0;
94
95err_reset:
96 clk_disable_unprepare(phy->hsic_clk);
97
98err_hsic_clk:
99 clk_disable_unprepare(phy->clk);
100
101err_clk:
102 return ret;
103}
104
105static int sun9i_usb_phy_exit(struct phy *_phy)
106{
107 struct sun9i_usb_phy *phy = phy_get_drvdata(_phy);
108
109 sun9i_usb_phy_passby(phy, 0);
110 reset_control_assert(phy->reset);
111 clk_disable_unprepare(phy->hsic_clk);
112 clk_disable_unprepare(phy->clk);
113
114 return 0;
115}
116
117static struct phy_ops sun9i_usb_phy_ops = {
118 .init = sun9i_usb_phy_init,
119 .exit = sun9i_usb_phy_exit,
120 .owner = THIS_MODULE,
121};
122
123static int sun9i_usb_phy_probe(struct platform_device *pdev)
124{
125 struct sun9i_usb_phy *phy;
126 struct device *dev = &pdev->dev;
127 struct device_node *np = dev->of_node;
128 struct phy_provider *phy_provider;
129 struct resource *res;
130
131 phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
132 if (!phy)
133 return -ENOMEM;
134
135 phy->type = of_usb_get_phy_mode(np);
136 if (phy->type == USBPHY_INTERFACE_MODE_HSIC) {
137 phy->clk = devm_clk_get(dev, "hsic_480M");
138 if (IS_ERR(phy->clk)) {
139 dev_err(dev, "failed to get hsic_480M clock\n");
140 return PTR_ERR(phy->clk);
141 }
142
143 phy->hsic_clk = devm_clk_get(dev, "hsic_12M");
144 if (IS_ERR(phy->clk)) {
145 dev_err(dev, "failed to get hsic_12M clock\n");
146 return PTR_ERR(phy->clk);
147 }
148
149 phy->reset = devm_reset_control_get(dev, "hsic");
150 if (IS_ERR(phy->reset)) {
151 dev_err(dev, "failed to get reset control\n");
152 return PTR_ERR(phy->reset);
153 }
154 } else {
155 phy->clk = devm_clk_get(dev, "phy");
156 if (IS_ERR(phy->clk)) {
157 dev_err(dev, "failed to get phy clock\n");
158 return PTR_ERR(phy->clk);
159 }
160
161 phy->reset = devm_reset_control_get(dev, "phy");
162 if (IS_ERR(phy->reset)) {
163 dev_err(dev, "failed to get reset control\n");
164 return PTR_ERR(phy->reset);
165 }
166 }
167
168 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
169 phy->pmu = devm_ioremap_resource(dev, res);
170 if (IS_ERR(phy->pmu))
171 return PTR_ERR(phy->pmu);
172
173 phy->phy = devm_phy_create(dev, NULL, &sun9i_usb_phy_ops);
174 if (IS_ERR(phy->phy)) {
175 dev_err(dev, "failed to create PHY\n");
176 return PTR_ERR(phy->phy);
177 }
178
179 phy_set_drvdata(phy->phy, phy);
180 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
181
182 return PTR_ERR_OR_ZERO(phy_provider);
183}
184
185static const struct of_device_id sun9i_usb_phy_of_match[] = {
186 { .compatible = "allwinner,sun9i-a80-usb-phy" },
187 { },
188};
189MODULE_DEVICE_TABLE(of, sun9i_usb_phy_of_match);
190
191static struct platform_driver sun9i_usb_phy_driver = {
192 .probe = sun9i_usb_phy_probe,
193 .driver = {
194 .of_match_table = sun9i_usb_phy_of_match,
195 .name = "sun9i-usb-phy",
196 }
197};
198module_platform_driver(sun9i_usb_phy_driver);
199
200MODULE_DESCRIPTION("Allwinner sun9i USB phy driver");
201MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");
202MODULE_LICENSE("GPL");
diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c
index 2ba610b72ca2..53f295c1bab1 100644
--- a/drivers/phy/phy-ti-pipe3.c
+++ b/drivers/phy/phy-ti-pipe3.c
@@ -287,9 +287,7 @@ static struct phy_ops ops = {
287 .owner = THIS_MODULE, 287 .owner = THIS_MODULE,
288}; 288};
289 289
290#ifdef CONFIG_OF
291static const struct of_device_id ti_pipe3_id_table[]; 290static const struct of_device_id ti_pipe3_id_table[];
292#endif
293 291
294static int ti_pipe3_probe(struct platform_device *pdev) 292static int ti_pipe3_probe(struct platform_device *pdev)
295{ 293{
@@ -311,8 +309,7 @@ static int ti_pipe3_probe(struct platform_device *pdev)
311 spin_lock_init(&phy->lock); 309 spin_lock_init(&phy->lock);
312 310
313 if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { 311 if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) {
314 match = of_match_device(of_match_ptr(ti_pipe3_id_table), 312 match = of_match_device(ti_pipe3_id_table, &pdev->dev);
315 &pdev->dev);
316 if (!match) 313 if (!match)
317 return -EINVAL; 314 return -EINVAL;
318 315
@@ -570,7 +567,6 @@ static const struct dev_pm_ops ti_pipe3_pm_ops = {
570 SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume) 567 SET_SYSTEM_SLEEP_PM_OPS(ti_pipe3_suspend, ti_pipe3_resume)
571}; 568};
572 569
573#ifdef CONFIG_OF
574static const struct of_device_id ti_pipe3_id_table[] = { 570static const struct of_device_id ti_pipe3_id_table[] = {
575 { 571 {
576 .compatible = "ti,phy-usb3", 572 .compatible = "ti,phy-usb3",
@@ -590,7 +586,6 @@ static const struct of_device_id ti_pipe3_id_table[] = {
590 {} 586 {}
591}; 587};
592MODULE_DEVICE_TABLE(of, ti_pipe3_id_table); 588MODULE_DEVICE_TABLE(of, ti_pipe3_id_table);
593#endif
594 589
595static struct platform_driver ti_pipe3_driver = { 590static struct platform_driver ti_pipe3_driver = {
596 .probe = ti_pipe3_probe, 591 .probe = ti_pipe3_probe,
@@ -598,7 +593,7 @@ static struct platform_driver ti_pipe3_driver = {
598 .driver = { 593 .driver = {
599 .name = "ti-pipe3", 594 .name = "ti-pipe3",
600 .pm = &ti_pipe3_pm_ops, 595 .pm = &ti_pipe3_pm_ops,
601 .of_match_table = of_match_ptr(ti_pipe3_id_table), 596 .of_match_table = ti_pipe3_id_table,
602 }, 597 },
603}; 598};
604 599
diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c
index 2263cd010032..385362e5b2f6 100644
--- a/drivers/phy/phy-xgene.c
+++ b/drivers/phy/phy-xgene.c
@@ -1657,7 +1657,6 @@ static int xgene_phy_probe(struct platform_device *pdev)
1657 struct phy_provider *phy_provider; 1657 struct phy_provider *phy_provider;
1658 struct xgene_phy_ctx *ctx; 1658 struct xgene_phy_ctx *ctx;
1659 struct resource *res; 1659 struct resource *res;
1660 int rc = 0;
1661 u32 default_spd[] = DEFAULT_SATA_SPD_SEL; 1660 u32 default_spd[] = DEFAULT_SATA_SPD_SEL;
1662 u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN; 1661 u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN;
1663 u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION; 1662 u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION;
@@ -1676,10 +1675,8 @@ static int xgene_phy_probe(struct platform_device *pdev)
1676 1675
1677 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1676 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1678 ctx->sds_base = devm_ioremap_resource(&pdev->dev, res); 1677 ctx->sds_base = devm_ioremap_resource(&pdev->dev, res);
1679 if (IS_ERR(ctx->sds_base)) { 1678 if (IS_ERR(ctx->sds_base))
1680 rc = PTR_ERR(ctx->sds_base); 1679 return PTR_ERR(ctx->sds_base);
1681 goto error;
1682 }
1683 1680
1684 /* Retrieve optional clock */ 1681 /* Retrieve optional clock */
1685 ctx->clk = clk_get(&pdev->dev, NULL); 1682 ctx->clk = clk_get(&pdev->dev, NULL);
@@ -1709,22 +1706,12 @@ static int xgene_phy_probe(struct platform_device *pdev)
1709 ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops); 1706 ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops);
1710 if (IS_ERR(ctx->phy)) { 1707 if (IS_ERR(ctx->phy)) {
1711 dev_dbg(&pdev->dev, "Failed to create PHY\n"); 1708 dev_dbg(&pdev->dev, "Failed to create PHY\n");
1712 rc = PTR_ERR(ctx->phy); 1709 return PTR_ERR(ctx->phy);
1713 goto error;
1714 } 1710 }
1715 phy_set_drvdata(ctx->phy, ctx); 1711 phy_set_drvdata(ctx->phy, ctx);
1716 1712
1717 phy_provider = devm_of_phy_provider_register(ctx->dev, 1713 phy_provider = devm_of_phy_provider_register(ctx->dev, xgene_phy_xlate);
1718 xgene_phy_xlate); 1714 return PTR_ERR_OR_ZERO(phy_provider);
1719 if (IS_ERR(phy_provider)) {
1720 rc = PTR_ERR(phy_provider);
1721 goto error;
1722 }
1723
1724 return 0;
1725
1726error:
1727 return rc;
1728} 1715}
1729 1716
1730static const struct of_device_id xgene_phy_of_match[] = { 1717static const struct of_device_id xgene_phy_of_match[] = {