ipq806x: enable QCE hardware crypto inside the kernel
[oweals/openwrt.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");