Prepare v2023.10
[platform/kernel/u-boot.git] / drivers / phy / allwinner / phy-sun4i-usb.c
1 /*
2  * Allwinner sun4i USB PHY driver
3  *
4  * Copyright (C) 2017 Jagan Teki <jagan@amarulasolutions.com>
5  * Copyright (C) 2015 Hans de Goede <hdegoede@redhat.com>
6  * Copyright (C) 2014 Roman Byshko <rbyshko@gmail.com>
7  *
8  * Modelled arch/arm/mach-sunxi/usb_phy.c to compatible with generic-phy.
9  *
10  * SPDX-License-Identifier:     GPL-2.0+
11  */
12
13 #include <common.h>
14 #include <clk.h>
15 #include <dm.h>
16 #include <log.h>
17 #include <dm/device.h>
18 #include <generic-phy.h>
19 #include <phy-sun4i-usb.h>
20 #include <reset.h>
21 #include <asm/gpio.h>
22 #include <asm/io.h>
23 #include <dm/device_compat.h>
24 #include <linux/bitops.h>
25 #include <linux/delay.h>
26 #include <linux/err.h>
27 #include <power/regulator.h>
28
29 #define REG_ISCR                        0x00
30 #define REG_PHYCTL_A10                  0x04
31 #define REG_PHYBIST                     0x08
32 #define REG_PHYTUNE                     0x0c
33 #define REG_PHYCTL_A33                  0x10
34 #define REG_PHY_OTGCTL                  0x20
35
36 #define REG_HCI_PHY_CTL                 0x10
37
38 /* Common Control Bits for Both PHYs */
39 #define PHY_PLL_BW                      0x03
40 #define PHY_RES45_CAL_EN                0x0c
41
42 /* Private Control Bits for Each PHY */
43 #define PHY_TX_AMPLITUDE_TUNE           0x20
44 #define PHY_TX_SLEWRATE_TUNE            0x22
45 #define PHY_DISCON_TH_SEL               0x2a
46 #define PHY_SQUELCH_DETECT              0x3c
47
48 #define PHYCTL_DATA                     BIT(7)
49 #define OTGCTL_ROUTE_MUSB               BIT(0)
50
51 #define PHY_TX_RATE                     BIT(4)
52 #define PHY_TX_MAGNITUDE                BIT(2)
53 #define PHY_TX_AMPLITUDE_LEN            5
54
55 #define PHY_RES45_CAL_DATA              BIT(0)
56 #define PHY_RES45_CAL_LEN               1
57 #define PHY_DISCON_TH_LEN               2
58
59 #define SUNXI_AHB_ICHR8_EN              BIT(10)
60 #define SUNXI_AHB_INCR4_BURST_EN        BIT(9)
61 #define SUNXI_AHB_INCRX_ALIGN_EN        BIT(8)
62 #define SUNXI_ULPI_BYPASS_EN            BIT(0)
63
64 /* A83T specific control bits for PHY0 */
65 #define PHY_CTL_VBUSVLDEXT              BIT(5)
66 #define PHY_CTL_SIDDQ                   BIT(3)
67 #define PHY_CTL_H3_SIDDQ                BIT(1)
68
69 /* A83T specific control bits for PHY2 HSIC */
70 #define SUNXI_EHCI_HS_FORCE             BIT(20)
71 #define SUNXI_HSIC_CONNECT_INT          BIT(16)
72 #define SUNXI_HSIC                      BIT(1)
73
74 #define MAX_PHYS                        4
75
76 struct sun4i_usb_phy_cfg {
77         int num_phys;
78         int hsic_index;
79         u32 disc_thresh;
80         u32 hci_phy_ctl_clear;
81         u8 phyctl_offset;
82         bool dedicated_clocks;
83         bool phy0_dual_route;
84         bool siddq_in_base;
85         bool needs_phy2_siddq;
86         int missing_phys;
87 };
88
89 struct sun4i_usb_phy_info {
90         const char *gpio_vbus;
91         const char *gpio_vbus_det;
92         const char *gpio_id_det;
93 } phy_info[] = {
94         {
95                 .gpio_vbus = CONFIG_USB0_VBUS_PIN,
96                 .gpio_vbus_det = CONFIG_USB0_VBUS_DET,
97                 .gpio_id_det = CONFIG_USB0_ID_DET,
98         },
99         {
100                 .gpio_vbus = CONFIG_USB1_VBUS_PIN,
101                 .gpio_vbus_det = NULL,
102                 .gpio_id_det = NULL,
103         },
104         {
105                 .gpio_vbus = CONFIG_USB2_VBUS_PIN,
106                 .gpio_vbus_det = NULL,
107                 .gpio_id_det = NULL,
108         },
109         {
110                 .gpio_vbus = CONFIG_USB3_VBUS_PIN,
111                 .gpio_vbus_det = NULL,
112                 .gpio_id_det = NULL,
113         },
114 };
115
116 struct sun4i_usb_phy_plat {
117         void __iomem *pmu;
118         struct gpio_desc gpio_vbus;
119         struct gpio_desc gpio_vbus_det;
120         struct gpio_desc gpio_id_det;
121         struct clk clocks;
122         struct clk clk2;
123         struct reset_ctl resets;
124         int id;
125 };
126
127 struct sun4i_usb_phy_data {
128         void __iomem *base;
129         const struct sun4i_usb_phy_cfg *cfg;
130         struct sun4i_usb_phy_plat *usb_phy;
131         struct udevice *vbus_power_supply;
132 };
133
134 static int initial_usb_scan_delay = CONFIG_INITIAL_USB_SCAN_DELAY;
135
136 static void sun4i_usb_phy_write(struct phy *phy, u32 addr, u32 data, int len)
137 {
138         struct sun4i_usb_phy_data *phy_data = dev_get_priv(phy->dev);
139         struct sun4i_usb_phy_plat *usb_phy = &phy_data->usb_phy[phy->id];
140         u32 temp, usbc_bit = BIT(usb_phy->id * 2);
141         void __iomem *phyctl = phy_data->base + phy_data->cfg->phyctl_offset;
142         int i;
143
144         if (phy_data->cfg->phyctl_offset == REG_PHYCTL_A33) {
145                 /* SoCs newer than A33 need us to set phyctl to 0 explicitly */
146                 writel(0, phyctl);
147         }
148
149         for (i = 0; i < len; i++) {
150                 temp = readl(phyctl);
151
152                 /* clear the address portion */
153                 temp &= ~(0xff << 8);
154
155                 /* set the address */
156                 temp |= ((addr + i) << 8);
157                 writel(temp, phyctl);
158
159                 /* set the data bit and clear usbc bit*/
160                 temp = readb(phyctl);
161                 if (data & 0x1)
162                         temp |= PHYCTL_DATA;
163                 else
164                         temp &= ~PHYCTL_DATA;
165                 temp &= ~usbc_bit;
166                 writeb(temp, phyctl);
167
168                 /* pulse usbc_bit */
169                 temp = readb(phyctl);
170                 temp |= usbc_bit;
171                 writeb(temp, phyctl);
172
173                 temp = readb(phyctl);
174                 temp &= ~usbc_bit;
175                 writeb(temp, phyctl);
176
177                 data >>= 1;
178         }
179 }
180
181 static void sun4i_usb_phy_passby(struct phy *phy, bool enable)
182 {
183         struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
184         struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
185         u32 bits, reg_value;
186
187         if (!usb_phy->pmu)
188                 return;
189
190         bits = SUNXI_AHB_ICHR8_EN | SUNXI_AHB_INCR4_BURST_EN |
191                 SUNXI_AHB_INCRX_ALIGN_EN | SUNXI_ULPI_BYPASS_EN;
192
193         /* A83T USB2 is HSIC */
194         if (data->cfg->hsic_index && usb_phy->id == data->cfg->hsic_index)
195                 bits |= SUNXI_EHCI_HS_FORCE | SUNXI_HSIC_CONNECT_INT |
196                         SUNXI_HSIC;
197
198         reg_value = readl(usb_phy->pmu);
199
200         if (enable)
201                 reg_value |= bits;
202         else
203                 reg_value &= ~bits;
204
205         writel(reg_value, usb_phy->pmu);
206 }
207
208 static int sun4i_usb_phy_power_on(struct phy *phy)
209 {
210         struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
211         struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
212
213         if (initial_usb_scan_delay) {
214                 mdelay(initial_usb_scan_delay);
215                 initial_usb_scan_delay = 0;
216         }
217
218         /* For phy0 only turn on Vbus if we don't have an ext. Vbus */
219         if (phy->id == 0 && sun4i_usb_phy_vbus_detect(phy)) {
220                 dev_warn(phy->dev, "External vbus detected, not enabling our own vbus\n");
221                 return 0;
222         }
223
224         if (dm_gpio_is_valid(&usb_phy->gpio_vbus))
225                 dm_gpio_set_value(&usb_phy->gpio_vbus, 1);
226
227         return 0;
228 }
229
230 static int sun4i_usb_phy_power_off(struct phy *phy)
231 {
232         struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
233         struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
234
235         if (dm_gpio_is_valid(&usb_phy->gpio_vbus))
236                 dm_gpio_set_value(&usb_phy->gpio_vbus, 0);
237
238         return 0;
239 }
240
241 static void sun4i_usb_phy0_reroute(struct sun4i_usb_phy_data *data, bool id_det)
242 {
243         u32 regval;
244
245         regval = readl(data->base + REG_PHY_OTGCTL);
246         if (!id_det) {
247                 /* Host mode. Route phy0 to EHCI/OHCI */
248                 regval &= ~OTGCTL_ROUTE_MUSB;
249         } else {
250                 /* Peripheral mode. Route phy0 to MUSB */
251                 regval |= OTGCTL_ROUTE_MUSB;
252         }
253         writel(regval, data->base + REG_PHY_OTGCTL);
254 }
255
256 static int sun4i_usb_phy_init(struct phy *phy)
257 {
258         struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
259         struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
260         u32 val;
261         int ret;
262
263         ret = clk_enable(&usb_phy->clocks);
264         if (ret) {
265                 dev_err(phy->dev, "failed to enable usb_%ldphy clock\n",
266                         phy->id);
267                 return ret;
268         }
269
270         ret = reset_deassert(&usb_phy->resets);
271         if (ret) {
272                 dev_err(phy->dev, "failed to deassert usb_%ldreset reset\n",
273                         phy->id);
274                 return ret;
275         }
276
277         /* Some PHYs on some SoCs (the H616) need the help of PHY2 to work. */
278         if (data->cfg->needs_phy2_siddq && phy->id != 2) {
279                 struct sun4i_usb_phy_plat *phy2 = &data->usb_phy[2];
280
281                 ret = clk_enable(&phy2->clocks);
282                 if (ret) {
283                         dev_err(phy->dev, "failed to enable aux clock\n");
284                         return ret;
285                 }
286
287                 ret = reset_deassert(&phy2->resets);
288                 if (ret) {
289                         dev_err(phy->dev, "failed to deassert aux reset\n");
290                         return ret;
291                 }
292
293                 /*
294                  * This extra clock is just needed to access the
295                  * REG_HCI_PHY_CTL PMU register for PHY2.
296                  */
297                 ret = clk_enable(&phy2->clk2);
298                 if (ret) {
299                         dev_err(phy->dev, "failed to enable PHY2 clock\n");
300                         return ret;
301                 }
302
303                 if (phy2->pmu && data->cfg->hci_phy_ctl_clear) {
304                         val = readl(phy2->pmu + REG_HCI_PHY_CTL);
305                         val &= ~data->cfg->hci_phy_ctl_clear;
306                         writel(val, phy2->pmu + REG_HCI_PHY_CTL);
307                 }
308
309                 clk_disable(&phy2->clk2);
310         }
311
312         if (usb_phy->pmu && data->cfg->hci_phy_ctl_clear) {
313                 val = readl(usb_phy->pmu + REG_HCI_PHY_CTL);
314                 val &= ~data->cfg->hci_phy_ctl_clear;
315                 writel(val, usb_phy->pmu + REG_HCI_PHY_CTL);
316         }
317
318         if (data->cfg->siddq_in_base) {
319                 if (phy->id == 0) {
320                         val = readl(data->base + data->cfg->phyctl_offset);
321                         val |= PHY_CTL_VBUSVLDEXT;
322                         val &= ~PHY_CTL_SIDDQ;
323                         writel(val, data->base + data->cfg->phyctl_offset);
324                 }
325         } else {
326                 if (usb_phy->id == 0)
327                         sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN,
328                                             PHY_RES45_CAL_DATA,
329                                             PHY_RES45_CAL_LEN);
330
331                 /* Adjust PHY's magnitude and rate */
332                 sun4i_usb_phy_write(phy, PHY_TX_AMPLITUDE_TUNE,
333                                     PHY_TX_MAGNITUDE | PHY_TX_RATE,
334                                     PHY_TX_AMPLITUDE_LEN);
335
336                 /* Disconnect threshold adjustment */
337                 sun4i_usb_phy_write(phy, PHY_DISCON_TH_SEL,
338                                     data->cfg->disc_thresh, PHY_DISCON_TH_LEN);
339         }
340
341 #ifdef CONFIG_USB_MUSB_SUNXI
342         /* Needed for HCI and conflicts with MUSB, keep PHY0 on MUSB */
343         if (usb_phy->id != 0)
344                 sun4i_usb_phy_passby(phy, true);
345
346         /* Route PHY0 to MUSB to allow USB gadget */
347         if (data->cfg->phy0_dual_route)
348                 sun4i_usb_phy0_reroute(data, true);
349 #else
350         sun4i_usb_phy_passby(phy, true);
351
352         /* Route PHY0 to HCI to allow USB host */
353         if (data->cfg->phy0_dual_route)
354                 sun4i_usb_phy0_reroute(data, false);
355 #endif
356
357         return 0;
358 }
359
360 static int sun4i_usb_phy_exit(struct phy *phy)
361 {
362         struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
363         struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
364         int ret;
365
366         if (phy->id == 0) {
367                 if (data->cfg->siddq_in_base) {
368                         void __iomem *phyctl = data->base +
369                                 data->cfg->phyctl_offset;
370
371                         writel(readl(phyctl) | PHY_CTL_SIDDQ, phyctl);
372                 }
373         }
374
375         sun4i_usb_phy_passby(phy, false);
376
377         ret = clk_disable(&usb_phy->clocks);
378         if (ret) {
379                 dev_err(phy->dev, "failed to disable usb_%ldphy clock\n",
380                         phy->id);
381                 return ret;
382         }
383
384         ret = reset_assert(&usb_phy->resets);
385         if (ret) {
386                 dev_err(phy->dev, "failed to assert usb_%ldreset reset\n",
387                         phy->id);
388                 return ret;
389         }
390
391         return 0;
392 }
393
394 static int sun4i_usb_phy_xlate(struct phy *phy,
395                                struct ofnode_phandle_args *args)
396 {
397         struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
398
399         if (args->args_count != 1)
400                 return -EINVAL;
401
402         if (args->args[0] >= data->cfg->num_phys)
403                 return -EINVAL;
404
405         if (data->cfg->missing_phys & BIT(args->args[0]))
406                 return -ENODEV;
407
408         if (args->args_count)
409                 phy->id = args->args[0];
410         else
411                 phy->id = 0;
412
413         debug("%s: phy_id = %ld\n", __func__, phy->id);
414         return 0;
415 }
416
417 int sun4i_usb_phy_vbus_detect(struct phy *phy)
418 {
419         struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
420         struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
421         int err = 1, retries = 3;
422
423         if (dm_gpio_is_valid(&usb_phy->gpio_vbus_det)) {
424                 err = dm_gpio_get_value(&usb_phy->gpio_vbus_det);
425                 /*
426                  * Vbus may have been provided by the board and just turned off
427                  * some milliseconds ago on reset. What we're measuring then is
428                  * a residual charge on Vbus. Sleep a bit and try again.
429                  */
430                 while (err > 0 && retries--) {
431                         mdelay(100);
432                         err = dm_gpio_get_value(&usb_phy->gpio_vbus_det);
433                 }
434         } else if (data->vbus_power_supply) {
435                 err = regulator_get_enable(data->vbus_power_supply);
436         }
437
438         return err;
439 }
440
441 int sun4i_usb_phy_id_detect(struct phy *phy)
442 {
443         struct sun4i_usb_phy_data *data = dev_get_priv(phy->dev);
444         struct sun4i_usb_phy_plat *usb_phy = &data->usb_phy[phy->id];
445
446         if (!dm_gpio_is_valid(&usb_phy->gpio_id_det))
447                 return -1;
448
449         return dm_gpio_get_value(&usb_phy->gpio_id_det);
450 }
451
452 void sun4i_usb_phy_set_squelch_detect(struct phy *phy, bool enabled)
453 {
454         sun4i_usb_phy_write(phy, PHY_SQUELCH_DETECT, enabled ? 0 : 2, 2);
455 }
456
457 static struct phy_ops sun4i_usb_phy_ops = {
458         .of_xlate = sun4i_usb_phy_xlate,
459         .init = sun4i_usb_phy_init,
460         .power_on = sun4i_usb_phy_power_on,
461         .power_off = sun4i_usb_phy_power_off,
462         .exit = sun4i_usb_phy_exit,
463 };
464
465 static int sun4i_usb_phy_probe(struct udevice *dev)
466 {
467         struct sun4i_usb_phy_plat *plat = dev_get_plat(dev);
468         struct sun4i_usb_phy_data *data = dev_get_priv(dev);
469         int i, ret;
470
471         data->cfg = (const struct sun4i_usb_phy_cfg *)dev_get_driver_data(dev);
472         if (!data->cfg)
473                 return -EINVAL;
474
475         data->base = (void __iomem *)devfdt_get_addr_name(dev, "phy_ctrl");
476         if (IS_ERR(data->base))
477                 return PTR_ERR(data->base);
478
479         device_get_supply_regulator(dev, "usb0_vbus_power-supply",
480                                     &data->vbus_power_supply);
481
482         data->usb_phy = plat;
483         for (i = 0; i < data->cfg->num_phys; i++) {
484                 struct sun4i_usb_phy_plat *phy = &plat[i];
485                 struct sun4i_usb_phy_info *info = &phy_info[i];
486                 char name[16];
487
488                 if (data->cfg->missing_phys & BIT(i))
489                         continue;
490
491                 ret = dm_gpio_lookup_name(info->gpio_vbus, &phy->gpio_vbus);
492                 if (ret == 0) {
493                         ret = dm_gpio_request(&phy->gpio_vbus, "usb_vbus");
494                         if (ret)
495                                 return ret;
496                         ret = dm_gpio_set_dir_flags(&phy->gpio_vbus,
497                                                     GPIOD_IS_OUT);
498                         if (ret)
499                                 return ret;
500                         ret = dm_gpio_set_value(&phy->gpio_vbus, 0);
501                         if (ret)
502                                 return ret;
503                 }
504
505                 ret = dm_gpio_lookup_name(info->gpio_vbus_det,
506                                           &phy->gpio_vbus_det);
507                 if (ret == 0) {
508                         ret = dm_gpio_request(&phy->gpio_vbus_det,
509                                               "usb_vbus_det");
510                         if (ret)
511                                 return ret;
512                         ret = dm_gpio_set_dir_flags(&phy->gpio_vbus_det,
513                                                     GPIOD_IS_IN);
514                         if (ret)
515                                 return ret;
516                 }
517
518                 ret = dm_gpio_lookup_name(info->gpio_id_det, &phy->gpio_id_det);
519                 if (ret == 0) {
520                         ret = dm_gpio_request(&phy->gpio_id_det, "usb_id_det");
521                         if (ret)
522                                 return ret;
523                         ret = dm_gpio_set_dir_flags(&phy->gpio_id_det,
524                                                 GPIOD_IS_IN | GPIOD_PULL_UP);
525                         if (ret)
526                                 return ret;
527                 }
528
529                 if (data->cfg->dedicated_clocks)
530                         snprintf(name, sizeof(name), "usb%d_phy", i);
531                 else
532                         strlcpy(name, "usb_phy", sizeof(name));
533
534                 ret = clk_get_by_name(dev, name, &phy->clocks);
535                 if (ret) {
536                         dev_err(dev, "failed to get usb%d_phy clock phandle\n", i);
537                         return ret;
538                 }
539
540                 /* Helper clock from PHY2 for the H616 PHY quirk */
541                 snprintf(name, sizeof(name), "pmu%d_clk", i);
542                 ret = clk_get_by_name_optional(dev, name, &phy->clk2);
543                 if (ret) {
544                         dev_err(dev, "failed to get pmu%d_clk clock phandle\n",
545                                 i);
546                         return ret;
547                 }
548
549                 snprintf(name, sizeof(name), "usb%d_reset", i);
550                 ret = reset_get_by_name(dev, name, &phy->resets);
551                 if (ret) {
552                         dev_err(dev, "failed to get usb%d_reset reset phandle\n", i);
553                         return ret;
554                 }
555
556                 if (i || data->cfg->phy0_dual_route) {
557                         snprintf(name, sizeof(name), "pmu%d", i);
558                         phy->pmu = (void __iomem *)devfdt_get_addr_name(dev, name);
559                         if (IS_ERR(phy->pmu))
560                                 return PTR_ERR(phy->pmu);
561                 }
562
563                 phy->id = i;
564         };
565
566         debug("Allwinner Sun4I USB PHY driver loaded\n");
567         return 0;
568 }
569
570 static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = {
571         .num_phys = 3,
572         .disc_thresh = 3,
573         .phyctl_offset = REG_PHYCTL_A10,
574         .dedicated_clocks = false,
575 };
576
577 static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = {
578         .num_phys = 2,
579         .disc_thresh = 2,
580         .phyctl_offset = REG_PHYCTL_A10,
581         .dedicated_clocks = false,
582 };
583
584 static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = {
585         .num_phys = 3,
586         .disc_thresh = 3,
587         .phyctl_offset = REG_PHYCTL_A10,
588         .dedicated_clocks = true,
589 };
590
591 static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = {
592         .num_phys = 3,
593         .disc_thresh = 2,
594         .phyctl_offset = REG_PHYCTL_A10,
595         .dedicated_clocks = false,
596 };
597
598 static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = {
599         .num_phys = 2,
600         .disc_thresh = 3,
601         .phyctl_offset = REG_PHYCTL_A10,
602         .dedicated_clocks = true,
603 };
604
605 static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = {
606         .num_phys = 2,
607         .disc_thresh = 3,
608         .phyctl_offset = REG_PHYCTL_A33,
609         .dedicated_clocks = true,
610 };
611
612 static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = {
613         .num_phys = 3,
614         .hsic_index = 2,
615         .phyctl_offset = REG_PHYCTL_A33,
616         .dedicated_clocks = true,
617         .siddq_in_base = true,
618 };
619
620 static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = {
621         .num_phys = 4,
622         .disc_thresh = 3,
623         .phyctl_offset = REG_PHYCTL_A33,
624         .dedicated_clocks = true,
625         .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
626         .phy0_dual_route = true,
627 };
628
629 static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = {
630         .num_phys = 3,
631         .disc_thresh = 3,
632         .phyctl_offset = REG_PHYCTL_A33,
633         .dedicated_clocks = true,
634         .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
635         .phy0_dual_route = true,
636 };
637
638 static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = {
639         .num_phys = 1,
640         .disc_thresh = 3,
641         .phyctl_offset = REG_PHYCTL_A33,
642         .dedicated_clocks = true,
643         .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
644         .phy0_dual_route = true,
645 };
646
647 static const struct sun4i_usb_phy_cfg sun20i_d1_cfg = {
648         .num_phys = 2,
649         .phyctl_offset = REG_PHYCTL_A33,
650         .dedicated_clocks = true,
651         .hci_phy_ctl_clear = PHY_CTL_SIDDQ,
652         .phy0_dual_route = true,
653         .siddq_in_base = true,
654 };
655
656 static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = {
657         .num_phys = 2,
658         .disc_thresh = 3,
659         .phyctl_offset = REG_PHYCTL_A33,
660         .dedicated_clocks = true,
661         .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ,
662         .phy0_dual_route = true,
663 };
664
665 static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = {
666         .num_phys = 4,
667         .disc_thresh = 3,
668         .phyctl_offset = REG_PHYCTL_A33,
669         .dedicated_clocks = true,
670         .phy0_dual_route = true,
671         .siddq_in_base = true,
672         .missing_phys = BIT(1) | BIT(2),
673 };
674
675 static const struct sun4i_usb_phy_cfg sun50i_h616_cfg = {
676         .num_phys = 4,
677         .disc_thresh = 3,
678         .phyctl_offset = REG_PHYCTL_A33,
679         .dedicated_clocks = true,
680         .phy0_dual_route = true,
681         .hci_phy_ctl_clear = PHY_CTL_SIDDQ,
682         .needs_phy2_siddq = true,
683         .siddq_in_base = true,
684 };
685
686 static const struct sun4i_usb_phy_cfg suniv_f1c100s_cfg = {
687         .num_phys = 1,
688         .disc_thresh = 3,
689         .phyctl_offset = REG_PHYCTL_A10,
690         .dedicated_clocks = true,
691 };
692
693 static const struct udevice_id sun4i_usb_phy_ids[] = {
694         { .compatible = "allwinner,sun4i-a10-usb-phy", .data = (ulong)&sun4i_a10_cfg },
695         { .compatible = "allwinner,sun5i-a13-usb-phy", .data = (ulong)&sun5i_a13_cfg },
696         { .compatible = "allwinner,sun6i-a31-usb-phy", .data = (ulong)&sun6i_a31_cfg },
697         { .compatible = "allwinner,sun7i-a20-usb-phy", .data = (ulong)&sun7i_a20_cfg },
698         { .compatible = "allwinner,sun8i-a23-usb-phy", .data = (ulong)&sun8i_a23_cfg },
699         { .compatible = "allwinner,sun8i-a33-usb-phy", .data = (ulong)&sun8i_a33_cfg },
700         { .compatible = "allwinner,sun8i-a83t-usb-phy", .data = (ulong)&sun8i_a83t_cfg },
701         { .compatible = "allwinner,sun8i-h3-usb-phy", .data = (ulong)&sun8i_h3_cfg },
702         { .compatible = "allwinner,sun8i-r40-usb-phy", .data = (ulong)&sun8i_r40_cfg },
703         { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = (ulong)&sun8i_v3s_cfg },
704         { .compatible = "allwinner,sun20i-d1-usb-phy", .data = (ulong)&sun20i_d1_cfg },
705         { .compatible = "allwinner,sun50i-a64-usb-phy", .data = (ulong)&sun50i_a64_cfg},
706         { .compatible = "allwinner,sun50i-h6-usb-phy", .data = (ulong)&sun50i_h6_cfg},
707         { .compatible = "allwinner,sun50i-h616-usb-phy", .data = (ulong)&sun50i_h616_cfg },
708         { .compatible = "allwinner,suniv-f1c100s-usb-phy", .data = (ulong)&suniv_f1c100s_cfg },
709         { }
710 };
711
712 U_BOOT_DRIVER(sun4i_usb_phy) = {
713         .name   = "sun4i_usb_phy",
714         .id     = UCLASS_PHY,
715         .of_match = sun4i_usb_phy_ids,
716         .ops = &sun4i_usb_phy_ops,
717         .probe = sun4i_usb_phy_probe,
718         .plat_auto      = sizeof(struct sun4i_usb_phy_plat[MAX_PHYS]),
719         .priv_auto      = sizeof(struct sun4i_usb_phy_data),
720 };