ipq806x: sync image filename with dt compatible string
[openwrt/staging/wigyori.git] / target / linux / ipq806x / patches-4.9 / 820-qcom-ipq4019-Add-IPQ4019-USB-HS-SS-PHY-drivers.patch
1 From e73682ec4455c34f3f3edc7f40d90ed297521012 Mon Sep 17 00:00:00 2001
2 From: Senthilkumar N L <snlakshm@codeaurora.org>
3 Date: Tue, 6 Jan 2015 12:52:23 +0530
4 Subject: [PATCH] qcom: ipq4019: Add IPQ4019 USB HS/SS PHY drivers
5
6 These drivers handles control and configuration of the HS
7 and SS USB PHY transceivers.
8
9 Signed-off-by: Senthilkumar N L <snlakshm@codeaurora.org>
10 Signed-off-by: Christian Lamparter <chunkeey@gmail.com>
11
12 ---
13 Changed:
14 - replaced spaces with tabs
15 - remove emulation and host variables
16 ---
17 drivers/usb/phy/Kconfig | 11 ++
18 drivers/usb/phy/Makefile | 2 +
19 drivers/usb/phy/phy-qca-baldur.c | 233 +++++++++++++++++++++++++++++++++++++++
20 drivers/usb/phy/phy-qca-uniphy.c | 141 +++++++++++++++++++++++
21 4 files changed, 387 insertions(+)
22 create mode 100644 drivers/usb/phy/phy-qca-baldur.c
23 create mode 100644 drivers/usb/phy/phy-qca-uniphy.c
24
25 --- a/drivers/usb/phy/Kconfig
26 +++ b/drivers/usb/phy/Kconfig
27 @@ -194,6 +194,17 @@ config USB_MXS_PHY
28
29 MXS Phy is used by some of the i.MX SoCs, for example imx23/28/6x.
30
31 +config USB_IPQ4019_PHY
32 + tristate "IPQ4019 PHY wrappers support"
33 + depends on (USB || USB_GADGET) && ARCH_QCOM
34 + select USB_PHY
35 + help
36 + Enable this to support the USB PHY transceivers on QCA961x chips.
37 + It handles PHY initialization, clock management required after
38 + resetting the hardware and power management.
39 + This driver is required even for peripheral only or host only
40 + mode configurations.
41 +
42 config USB_ULPI
43 bool "Generic ULPI Transceiver Driver"
44 depends on ARM || ARM64
45 --- a/drivers/usb/phy/Makefile
46 +++ b/drivers/usb/phy/Makefile
47 @@ -21,6 +21,8 @@ obj-$(CONFIG_USB_GPIO_VBUS) += phy-gpio
48 obj-$(CONFIG_USB_ISP1301) += phy-isp1301.o
49 obj-$(CONFIG_USB_MSM_OTG) += phy-msm-usb.o
50 obj-$(CONFIG_USB_QCOM_8X16_PHY) += phy-qcom-8x16-usb.o
51 +obj-$(CONFIG_USB_IPQ4019_PHY) += phy-qca-baldur.o
52 +obj-$(CONFIG_USB_IPQ4019_PHY) += phy-qca-uniphy.o
53 obj-$(CONFIG_USB_MV_OTG) += phy-mv-usb.o
54 obj-$(CONFIG_USB_MXS_PHY) += phy-mxs-usb.o
55 obj-$(CONFIG_USB_ULPI) += phy-ulpi.o
56 --- /dev/null
57 +++ b/drivers/usb/phy/phy-qca-baldur.c
58 @@ -0,0 +1,233 @@
59 +/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
60 + *
61 + * Permission to use, copy, modify, and/or distribute this software for any
62 + * purpose with or without fee is hereby granted, provided that the above
63 + * copyright notice and this permission notice appear in all copies.
64 + *
65 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
66 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
67 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
68 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
69 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
70 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
71 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
72 + *
73 + */
74 +
75 +#include <linux/clk.h>
76 +#include <linux/err.h>
77 +#include <linux/io.h>
78 +#include <linux/module.h>
79 +#include <linux/of.h>
80 +#include <linux/platform_device.h>
81 +#include <linux/regulator/consumer.h>
82 +#include <linux/usb/phy.h>
83 +#include <linux/reset.h>
84 +#include <linux/of_device.h>
85 +
86 +/**
87 + * USB Hardware registers
88 + */
89 +#define PHY_CTRL0_ADDR 0x000
90 +#define PHY_CTRL1_ADDR 0x004
91 +#define PHY_CTRL2_ADDR 0x008
92 +#define PHY_CTRL3_ADDR 0x00C
93 +#define PHY_CTRL4_ADDR 0x010
94 +#define PHY_MISC_ADDR 0x024
95 +#define PHY_IPG_ADDR 0x030
96 +
97 +#define PHY_CTRL0_VAL 0xA4600015
98 +#define PHY_CTRL1_VAL 0x09500000
99 +#define PHY_CTRL2_VAL 0x00058180
100 +#define PHY_CTRL3_VAL 0x6DB6DCD6
101 +#define PHY_CTRL4_VAL 0x836DB6DB
102 +#define PHY_MISC_VAL 0x3803FB0C
103 +#define PHY_IPG_VAL 0x47323232
104 +
105 +#define USB30_HS_PHY_HOST_MODE (0x01 << 21)
106 +#define USB20_HS_PHY_HOST_MODE (0x01 << 5)
107 +
108 +/* used to differentiate between USB3 HS and USB2 HS PHY */
109 +struct qca_baldur_hs_data {
110 + unsigned int usb3_hs_phy;
111 + unsigned int phy_config_offset;
112 +};
113 +
114 +struct qca_baldur_hs_phy {
115 + struct device *dev;
116 + struct usb_phy phy;
117 +
118 + void __iomem *base;
119 + void __iomem *qscratch_base;
120 +
121 + struct reset_control *por_rst;
122 + struct reset_control *srif_rst;
123 +
124 + const struct qca_baldur_hs_data *data;
125 +};
126 +
127 +#define phy_to_dw_phy(x) container_of((x), struct qca_baldur_hs_phy, phy)
128 +
129 +static int qca_baldur_phy_read(struct usb_phy *x, u32 reg)
130 +{
131 + struct qca_baldur_hs_phy *phy = phy_to_dw_phy(x);
132 +
133 + return readl(phy->base + reg);
134 +}
135 +
136 +static int qca_baldur_phy_write(struct usb_phy *x, u32 val, u32 reg)
137 +{
138 + struct qca_baldur_hs_phy *phy = phy_to_dw_phy(x);
139 +
140 + writel(val, phy->base + reg);
141 + return 0;
142 +}
143 +
144 +static int qca_baldur_hs_phy_init(struct usb_phy *x)
145 +{
146 + struct qca_baldur_hs_phy *phy = phy_to_dw_phy(x);
147 +
148 + /* assert HS PHY POR reset */
149 + reset_control_assert(phy->por_rst);
150 + msleep(10);
151 +
152 + /* assert HS PHY SRIF reset */
153 + reset_control_assert(phy->srif_rst);
154 + msleep(10);
155 +
156 + /* deassert HS PHY SRIF reset and program HS PHY registers */
157 + reset_control_deassert(phy->srif_rst);
158 + msleep(10);
159 +
160 + /* perform PHY register writes */
161 + writel(PHY_CTRL0_VAL, phy->base + PHY_CTRL0_ADDR);
162 + writel(PHY_CTRL1_VAL, phy->base + PHY_CTRL1_ADDR);
163 + writel(PHY_CTRL2_VAL, phy->base + PHY_CTRL2_ADDR);
164 + writel(PHY_CTRL3_VAL, phy->base + PHY_CTRL3_ADDR);
165 + writel(PHY_CTRL4_VAL, phy->base + PHY_CTRL4_ADDR);
166 + writel(PHY_MISC_VAL, phy->base + PHY_MISC_ADDR);
167 + writel(PHY_IPG_VAL, phy->base + PHY_IPG_ADDR);
168 +
169 + msleep(10);
170 +
171 + /* de-assert USB3 HS PHY POR reset */
172 + reset_control_deassert(phy->por_rst);
173 +
174 + return 0;
175 +}
176 +
177 +static int qca_baldur_hs_get_resources(struct qca_baldur_hs_phy *phy)
178 +{
179 + struct platform_device *pdev = to_platform_device(phy->dev);
180 + struct resource *res;
181 +
182 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
183 + phy->base = devm_ioremap_resource(phy->dev, res);
184 + if (IS_ERR(phy->base))
185 + return PTR_ERR(phy->base);
186 +
187 + phy->por_rst = devm_reset_control_get(phy->dev, "por_rst");
188 + if (IS_ERR(phy->por_rst))
189 + return PTR_ERR(phy->por_rst);
190 +
191 + phy->srif_rst = devm_reset_control_get(phy->dev, "srif_rst");
192 + if (IS_ERR(phy->srif_rst))
193 + return PTR_ERR(phy->srif_rst);
194 +
195 + return 0;
196 +}
197 +
198 +static void qca_baldur_hs_put_resources(struct qca_baldur_hs_phy *phy)
199 +{
200 + reset_control_assert(phy->srif_rst);
201 + reset_control_assert(phy->por_rst);
202 +}
203 +
204 +static int qca_baldur_hs_remove(struct platform_device *pdev)
205 +{
206 + struct qca_baldur_hs_phy *phy = platform_get_drvdata(pdev);
207 +
208 + usb_remove_phy(&phy->phy);
209 + return 0;
210 +}
211 +
212 +static void qca_baldur_hs_phy_shutdown(struct usb_phy *x)
213 +{
214 + struct qca_baldur_hs_phy *phy = phy_to_dw_phy(x);
215 +
216 + qca_baldur_hs_put_resources(phy);
217 +}
218 +
219 +static struct usb_phy_io_ops qca_baldur_io_ops = {
220 + .read = qca_baldur_phy_read,
221 + .write = qca_baldur_phy_write,
222 +};
223 +
224 +static const struct qca_baldur_hs_data usb3_hs_data = {
225 + .usb3_hs_phy = 1,
226 + .phy_config_offset = USB30_HS_PHY_HOST_MODE,
227 +};
228 +
229 +static const struct qca_baldur_hs_data usb2_hs_data = {
230 + .usb3_hs_phy = 0,
231 + .phy_config_offset = USB20_HS_PHY_HOST_MODE,
232 +};
233 +
234 +static const struct of_device_id qca_baldur_hs_id_table[] = {
235 + { .compatible = "qca,baldur-usb3-hsphy", .data = &usb3_hs_data },
236 + { .compatible = "qca,baldur-usb2-hsphy", .data = &usb2_hs_data },
237 + { /* Sentinel */ }
238 +};
239 +MODULE_DEVICE_TABLE(of, qca_baldur_hs_id_table);
240 +
241 +static int qca_baldur_hs_probe(struct platform_device *pdev)
242 +{
243 + const struct of_device_id *match;
244 + struct qca_baldur_hs_phy *phy;
245 + int err;
246 +
247 + match = of_match_device(qca_baldur_hs_id_table, &pdev->dev);
248 + if (!match)
249 + return -ENODEV;
250 +
251 + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
252 + if (!phy)
253 + return -ENOMEM;
254 +
255 + platform_set_drvdata(pdev, phy);
256 + phy->dev = &pdev->dev;
257 +
258 + phy->data = match->data;
259 +
260 + err = qca_baldur_hs_get_resources(phy);
261 + if (err < 0) {
262 + dev_err(&pdev->dev, "failed to request resources: %d\n", err);
263 + return err;
264 + }
265 +
266 + phy->phy.dev = phy->dev;
267 + phy->phy.label = "qca-baldur-hsphy";
268 + phy->phy.init = qca_baldur_hs_phy_init;
269 + phy->phy.shutdown = qca_baldur_hs_phy_shutdown;
270 + phy->phy.type = USB_PHY_TYPE_USB2;
271 + phy->phy.io_ops = &qca_baldur_io_ops;
272 +
273 + err = usb_add_phy_dev(&phy->phy);
274 + return err;
275 +}
276 +
277 +static struct platform_driver qca_baldur_hs_driver = {
278 + .probe = qca_baldur_hs_probe,
279 + .remove = qca_baldur_hs_remove,
280 + .driver = {
281 + .name = "qca-baldur-hsphy",
282 + .owner = THIS_MODULE,
283 + .of_match_table = qca_baldur_hs_id_table,
284 + },
285 +};
286 +
287 +module_platform_driver(qca_baldur_hs_driver);
288 +
289 +MODULE_ALIAS("platform:qca-baldur-hsphy");
290 +MODULE_LICENSE("Dual BSD/GPL");
291 +MODULE_DESCRIPTION("USB3 QCA BALDUR HSPHY driver");
292 --- /dev/null
293 +++ b/drivers/usb/phy/phy-qca-uniphy.c
294 @@ -0,0 +1,135 @@
295 +/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
296 + *
297 + * Permission to use, copy, modify, and/or distribute this software for any
298 + * purpose with or without fee is hereby granted, provided that the above
299 + * copyright notice and this permission notice appear in all copies.
300 + *
301 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
302 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
303 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
304 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
305 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
306 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
307 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
308 + *
309 + */
310 +
311 +#include <linux/clk.h>
312 +#include <linux/err.h>
313 +#include <linux/io.h>
314 +#include <linux/module.h>
315 +#include <linux/of.h>
316 +#include <linux/platform_device.h>
317 +#include <linux/regulator/consumer.h>
318 +#include <linux/usb/phy.h>
319 +#include <linux/reset.h>
320 +#include <linux/of_device.h>
321 +
322 +struct qca_uni_ss_phy {
323 + struct usb_phy phy;
324 + struct device *dev;
325 +
326 + void __iomem *base;
327 +
328 + struct reset_control *por_rst;
329 +};
330 +
331 +#define phy_to_dw_phy(x) container_of((x), struct qca_uni_ss_phy, phy)
332 +
333 +static void qca_uni_ss_phy_shutdown(struct usb_phy *x)
334 +{
335 + struct qca_uni_ss_phy *phy = phy_to_dw_phy(x);
336 +
337 + /* assert SS PHY POR reset */
338 + reset_control_assert(phy->por_rst);
339 +}
340 +
341 +static int qca_uni_ss_phy_init(struct usb_phy *x)
342 +{
343 + struct qca_uni_ss_phy *phy = phy_to_dw_phy(x);
344 +
345 + /* assert SS PHY POR reset */
346 + reset_control_assert(phy->por_rst);
347 +
348 + msleep(20);
349 +
350 + /* deassert SS PHY POR reset */
351 + reset_control_deassert(phy->por_rst);
352 +
353 + return 0;
354 +}
355 +
356 +static int qca_uni_ss_get_resources(struct platform_device *pdev,
357 + struct qca_uni_ss_phy *phy)
358 +{
359 + struct resource *res;
360 +
361 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
362 + phy->base = devm_ioremap_resource(phy->dev, res);
363 + if (IS_ERR(phy->base))
364 + return PTR_ERR(phy->base);
365 +
366 + phy->por_rst = devm_reset_control_get(phy->dev, "por_rst");
367 + if (IS_ERR(phy->por_rst))
368 + return PTR_ERR(phy->por_rst);
369 +
370 + return 0;
371 +}
372 +
373 +static int qca_uni_ss_remove(struct platform_device *pdev)
374 +{
375 + struct qca_uni_ss_phy *phy = platform_get_drvdata(pdev);
376 +
377 + usb_remove_phy(&phy->phy);
378 + return 0;
379 +}
380 +
381 +static const struct of_device_id qca_uni_ss_id_table[] = {
382 + { .compatible = "qca,uni-ssphy" },
383 + { /* Sentinel */ }
384 +};
385 +MODULE_DEVICE_TABLE(of, qca_uni_ss_id_table);
386 +
387 +static int qca_uni_ss_probe(struct platform_device *pdev)
388 +{
389 + struct qca_uni_ss_phy *phy;
390 + int ret;
391 +
392 + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
393 + if (!phy)
394 + return -ENOMEM;
395 +
396 + platform_set_drvdata(pdev, phy);
397 + phy->dev = &pdev->dev;
398 +
399 + ret = qca_uni_ss_get_resources(pdev, phy);
400 + if (ret < 0) {
401 + dev_err(&pdev->dev, "failed to request resources: %d\n", ret);
402 + return ret;
403 + }
404 +
405 + phy->phy.dev = phy->dev;
406 + phy->phy.label = "qca-uni-ssphy";
407 + phy->phy.init = qca_uni_ss_phy_init;
408 + phy->phy.shutdown = qca_uni_ss_phy_shutdown;
409 + phy->phy.type = USB_PHY_TYPE_USB3;
410 +
411 + ret = usb_add_phy_dev(&phy->phy);
412 + return ret;
413 +}
414 +
415 +static struct platform_driver qca_uni_ss_driver = {
416 + .probe = qca_uni_ss_probe,
417 + .remove = qca_uni_ss_remove,
418 + .driver = {
419 + .name = "qca-uni-ssphy",
420 + .owner = THIS_MODULE,
421 + .of_match_table = qca_uni_ss_id_table,
422 + },
423 +};
424 +
425 +module_platform_driver(qca_uni_ss_driver);
426 +
427 +MODULE_ALIAS("platform:qca-uni-ssphy");
428 +MODULE_LICENSE("Dual BSD/GPL");
429 +MODULE_DESCRIPTION("USB3 QCA UNI SSPHY driver");