aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/phy
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2014-03-03 06:38:12 -0500
committerKishon Vijay Abraham I <kishon@ti.com>2014-03-06 04:19:33 -0500
commita70143bbef6bf06050c32a26d99e917b3e82deb7 (patch)
tree7d84ccb6eddc7768cb688600d7069193a54b9908 /drivers/usb/phy
parent06c886a95cbb533fb3c4178ec0362460b17926ed (diff)
drivers: phy: usb3/pipe3: Adapt pipe3 driver to Generic PHY Framework
Adapted omap-usb3 PHY driver to Generic PHY Framework and moved phy-omap-usb3 driver in drivers/usb/phy to drivers/phy and also renamed the file to phy-ti-pipe3 since this same driver will be used for SATA PHY and PCIE PHY. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
Diffstat (limited to 'drivers/usb/phy')
-rw-r--r--drivers/usb/phy/Kconfig11
-rw-r--r--drivers/usb/phy/Makefile1
-rw-r--r--drivers/usb/phy/phy-omap-usb3.c361
3 files changed, 0 insertions, 373 deletions
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig
index 7d1451d5bbea..c337ba2d066b 100644
--- a/drivers/usb/phy/Kconfig
+++ b/drivers/usb/phy/Kconfig
@@ -85,17 +85,6 @@ config OMAP_CONTROL_USB
85 power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an 85 power on the USB2 PHY is present in OMAP4 and OMAP5. OMAP5 has an
86 additional register to power on USB3 PHY. 86 additional register to power on USB3 PHY.
87 87
88config OMAP_USB3
89 tristate "OMAP USB3 PHY Driver"
90 depends on ARCH_OMAP2PLUS || COMPILE_TEST
91 select OMAP_CONTROL_USB
92 select USB_PHY
93 help
94 Enable this to support the USB3 PHY that is part of SOC. This
95 driver takes care of all the PHY functionality apart from comparator.
96 This driver interacts with the "OMAP Control USB Driver" to power
97 on/off the PHY.
98
99config AM335X_CONTROL_USB 88config AM335X_CONTROL_USB
100 tristate 89 tristate
101 90
diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile
index be58adae3496..15f1878388f4 100644
--- a/drivers/usb/phy/Makefile
+++ b/drivers/usb/phy/Makefile
@@ -17,7 +17,6 @@ obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o
17obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o 17obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o
18obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o 18obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o
19obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o 19obj-$(CONFIG_OMAP_OTG) += phy-omap-otg.o
20obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o
21obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o 20obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o
22obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o 21obj-$(CONFIG_SAMSUNG_USB2PHY) += phy-samsung-usb2.o
23obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o 22obj-$(CONFIG_SAMSUNG_USB3PHY) += phy-samsung-usb3.o
diff --git a/drivers/usb/phy/phy-omap-usb3.c b/drivers/usb/phy/phy-omap-usb3.c
deleted file mode 100644
index 0c6ba29bdddd..000000000000
--- a/drivers/usb/phy/phy-omap-usb3.c
+++ /dev/null
@@ -1,361 +0,0 @@
1/*
2 * omap-usb3 - USB PHY, talking to dwc3 controller in OMAP.
3 *
4 * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * Author: Kishon Vijay Abraham I <kishon@ti.com>
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/module.h>
20#include <linux/platform_device.h>
21#include <linux/slab.h>
22#include <linux/usb/omap_usb.h>
23#include <linux/of.h>
24#include <linux/clk.h>
25#include <linux/err.h>
26#include <linux/pm_runtime.h>
27#include <linux/delay.h>
28#include <linux/usb/omap_control_usb.h>
29#include <linux/of_platform.h>
30
31#define PLL_STATUS 0x00000004
32#define PLL_GO 0x00000008
33#define PLL_CONFIGURATION1 0x0000000C
34#define PLL_CONFIGURATION2 0x00000010
35#define PLL_CONFIGURATION3 0x00000014
36#define PLL_CONFIGURATION4 0x00000020
37
38#define PLL_REGM_MASK 0x001FFE00
39#define PLL_REGM_SHIFT 0x9
40#define PLL_REGM_F_MASK 0x0003FFFF
41#define PLL_REGM_F_SHIFT 0x0
42#define PLL_REGN_MASK 0x000001FE
43#define PLL_REGN_SHIFT 0x1
44#define PLL_SELFREQDCO_MASK 0x0000000E
45#define PLL_SELFREQDCO_SHIFT 0x1
46#define PLL_SD_MASK 0x0003FC00
47#define PLL_SD_SHIFT 0x9
48#define SET_PLL_GO 0x1
49#define PLL_TICOPWDN 0x10000
50#define PLL_LOCK 0x2
51#define PLL_IDLE 0x1
52
53/*
54 * This is an Empirical value that works, need to confirm the actual
55 * value required for the USB3PHY_PLL_CONFIGURATION2.PLL_IDLE status
56 * to be correctly reflected in the USB3PHY_PLL_STATUS register.
57 */
58# define PLL_IDLE_TIME 100;
59
60struct usb_dpll_map {
61 unsigned long rate;
62 struct usb_dpll_params params;
63};
64
65static struct usb_dpll_map dpll_map[] = {
66 {12000000, {1250, 5, 4, 20, 0} }, /* 12 MHz */
67 {16800000, {3125, 20, 4, 20, 0} }, /* 16.8 MHz */
68 {19200000, {1172, 8, 4, 20, 65537} }, /* 19.2 MHz */
69 {20000000, {1000, 7, 4, 10, 0} }, /* 20 MHz */
70 {26000000, {1250, 12, 4, 20, 0} }, /* 26 MHz */
71 {38400000, {3125, 47, 4, 20, 92843} }, /* 38.4 MHz */
72};
73
74static struct usb_dpll_params *omap_usb3_get_dpll_params(unsigned long rate)
75{
76 int i;
77
78 for (i = 0; i < ARRAY_SIZE(dpll_map); i++) {
79 if (rate == dpll_map[i].rate)
80 return &dpll_map[i].params;
81 }
82
83 return NULL;
84}
85
86static int omap_usb3_suspend(struct usb_phy *x, int suspend)
87{
88 struct omap_usb *phy = phy_to_omapusb(x);
89 int val;
90 int timeout = PLL_IDLE_TIME;
91
92 if (suspend && !phy->is_suspended) {
93 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
94 val |= PLL_IDLE;
95 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
96
97 do {
98 val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
99 if (val & PLL_TICOPWDN)
100 break;
101 udelay(1);
102 } while (--timeout);
103
104 omap_control_usb_phy_power(phy->control_dev, 0);
105
106 phy->is_suspended = 1;
107 } else if (!suspend && phy->is_suspended) {
108 phy->is_suspended = 0;
109
110 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
111 val &= ~PLL_IDLE;
112 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
113
114 do {
115 val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
116 if (!(val & PLL_TICOPWDN))
117 break;
118 udelay(1);
119 } while (--timeout);
120 }
121
122 return 0;
123}
124
125static void omap_usb_dpll_relock(struct omap_usb *phy)
126{
127 u32 val;
128 unsigned long timeout;
129
130 omap_usb_writel(phy->pll_ctrl_base, PLL_GO, SET_PLL_GO);
131
132 timeout = jiffies + msecs_to_jiffies(20);
133 do {
134 val = omap_usb_readl(phy->pll_ctrl_base, PLL_STATUS);
135 if (val & PLL_LOCK)
136 break;
137 } while (!WARN_ON(time_after(jiffies, timeout)));
138}
139
140static int omap_usb_dpll_lock(struct omap_usb *phy)
141{
142 u32 val;
143 unsigned long rate;
144 struct usb_dpll_params *dpll_params;
145
146 rate = clk_get_rate(phy->sys_clk);
147 dpll_params = omap_usb3_get_dpll_params(rate);
148 if (!dpll_params) {
149 dev_err(phy->dev,
150 "No DPLL configuration for %lu Hz SYS CLK\n", rate);
151 return -EINVAL;
152 }
153
154 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
155 val &= ~PLL_REGN_MASK;
156 val |= dpll_params->n << PLL_REGN_SHIFT;
157 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
158
159 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION2);
160 val &= ~PLL_SELFREQDCO_MASK;
161 val |= dpll_params->freq << PLL_SELFREQDCO_SHIFT;
162 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION2, val);
163
164 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION1);
165 val &= ~PLL_REGM_MASK;
166 val |= dpll_params->m << PLL_REGM_SHIFT;
167 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION1, val);
168
169 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION4);
170 val &= ~PLL_REGM_F_MASK;
171 val |= dpll_params->mf << PLL_REGM_F_SHIFT;
172 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION4, val);
173
174 val = omap_usb_readl(phy->pll_ctrl_base, PLL_CONFIGURATION3);
175 val &= ~PLL_SD_MASK;
176 val |= dpll_params->sd << PLL_SD_SHIFT;
177 omap_usb_writel(phy->pll_ctrl_base, PLL_CONFIGURATION3, val);
178
179 omap_usb_dpll_relock(phy);
180
181 return 0;
182}
183
184static int omap_usb3_init(struct usb_phy *x)
185{
186 struct omap_usb *phy = phy_to_omapusb(x);
187 int ret;
188
189 ret = omap_usb_dpll_lock(phy);
190 if (ret)
191 return ret;
192
193 omap_control_usb_phy_power(phy->control_dev, 1);
194
195 return 0;
196}
197
198static int omap_usb3_probe(struct platform_device *pdev)
199{
200 struct omap_usb *phy;
201 struct resource *res;
202 struct device_node *node = pdev->dev.of_node;
203 struct device_node *control_node;
204 struct platform_device *control_pdev;
205
206 if (!node)
207 return -EINVAL;
208
209 phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
210 if (!phy) {
211 dev_err(&pdev->dev, "unable to alloc mem for OMAP USB3 PHY\n");
212 return -ENOMEM;
213 }
214
215 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
216 phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
217 if (IS_ERR(phy->pll_ctrl_base))
218 return PTR_ERR(phy->pll_ctrl_base);
219
220 phy->dev = &pdev->dev;
221
222 phy->phy.dev = phy->dev;
223 phy->phy.label = "omap-usb3";
224 phy->phy.init = omap_usb3_init;
225 phy->phy.set_suspend = omap_usb3_suspend;
226 phy->phy.type = USB_PHY_TYPE_USB3;
227
228 phy->is_suspended = 1;
229 phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k");
230 if (IS_ERR(phy->wkupclk)) {
231 dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n");
232 return PTR_ERR(phy->wkupclk);
233 }
234 clk_prepare(phy->wkupclk);
235
236 phy->optclk = devm_clk_get(phy->dev, "usb_otg_ss_refclk960m");
237 if (IS_ERR(phy->optclk)) {
238 dev_err(&pdev->dev, "unable to get usb_otg_ss_refclk960m\n");
239 return PTR_ERR(phy->optclk);
240 }
241 clk_prepare(phy->optclk);
242
243 phy->sys_clk = devm_clk_get(phy->dev, "sys_clkin");
244 if (IS_ERR(phy->sys_clk)) {
245 pr_err("%s: unable to get sys_clkin\n", __func__);
246 return -EINVAL;
247 }
248
249 control_node = of_parse_phandle(node, "ctrl-module", 0);
250 if (!control_node) {
251 dev_err(&pdev->dev, "Failed to get control device phandle\n");
252 return -EINVAL;
253 }
254 control_pdev = of_find_device_by_node(control_node);
255 if (!control_pdev) {
256 dev_err(&pdev->dev, "Failed to get control device\n");
257 return -EINVAL;
258 }
259
260 phy->control_dev = &control_pdev->dev;
261
262 omap_control_usb_phy_power(phy->control_dev, 0);
263 usb_add_phy_dev(&phy->phy);
264
265 platform_set_drvdata(pdev, phy);
266
267 pm_runtime_enable(phy->dev);
268 pm_runtime_get(&pdev->dev);
269
270 return 0;
271}
272
273static int omap_usb3_remove(struct platform_device *pdev)
274{
275 struct omap_usb *phy = platform_get_drvdata(pdev);
276
277 clk_unprepare(phy->wkupclk);
278 clk_unprepare(phy->optclk);
279 usb_remove_phy(&phy->phy);
280 if (!pm_runtime_suspended(&pdev->dev))
281 pm_runtime_put(&pdev->dev);
282 pm_runtime_disable(&pdev->dev);
283
284 return 0;
285}
286
287#ifdef CONFIG_PM_RUNTIME
288
289static int omap_usb3_runtime_suspend(struct device *dev)
290{
291 struct platform_device *pdev = to_platform_device(dev);
292 struct omap_usb *phy = platform_get_drvdata(pdev);
293
294 clk_disable(phy->wkupclk);
295 clk_disable(phy->optclk);
296
297 return 0;
298}
299
300static int omap_usb3_runtime_resume(struct device *dev)
301{
302 u32 ret = 0;
303 struct platform_device *pdev = to_platform_device(dev);
304 struct omap_usb *phy = platform_get_drvdata(pdev);
305
306 ret = clk_enable(phy->optclk);
307 if (ret) {
308 dev_err(phy->dev, "Failed to enable optclk %d\n", ret);
309 goto err1;
310 }
311
312 ret = clk_enable(phy->wkupclk);
313 if (ret) {
314 dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret);
315 goto err2;
316 }
317
318 return 0;
319
320err2:
321 clk_disable(phy->optclk);
322
323err1:
324 return ret;
325}
326
327static const struct dev_pm_ops omap_usb3_pm_ops = {
328 SET_RUNTIME_PM_OPS(omap_usb3_runtime_suspend, omap_usb3_runtime_resume,
329 NULL)
330};
331
332#define DEV_PM_OPS (&omap_usb3_pm_ops)
333#else
334#define DEV_PM_OPS NULL
335#endif
336
337#ifdef CONFIG_OF
338static const struct of_device_id omap_usb3_id_table[] = {
339 { .compatible = "ti,omap-usb3" },
340 {}
341};
342MODULE_DEVICE_TABLE(of, omap_usb3_id_table);
343#endif
344
345static struct platform_driver omap_usb3_driver = {
346 .probe = omap_usb3_probe,
347 .remove = omap_usb3_remove,
348 .driver = {
349 .name = "omap-usb3",
350 .owner = THIS_MODULE,
351 .pm = DEV_PM_OPS,
352 .of_match_table = of_match_ptr(omap_usb3_id_table),
353 },
354};
355
356module_platform_driver(omap_usb3_driver);
357
358MODULE_ALIAS("platform: omap_usb3");
359MODULE_AUTHOR("Texas Instruments Inc.");
360MODULE_DESCRIPTION("OMAP USB3 phy driver");
361MODULE_LICENSE("GPL v2");