usb: dwc3-generic: remove dm_scan_fdt_dev() from the remove() callback
[oweals/u-boot.git] / drivers / usb / dwc3 / dwc3-uniphier.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * UniPhier Specific Glue Layer for DWC3
4  *
5  * Copyright (C) 2016-2017 Socionext Inc.
6  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
7  */
8
9 #include <dm.h>
10 #include <linux/bitops.h>
11 #include <linux/errno.h>
12 #include <linux/io.h>
13 #include <linux/sizes.h>
14
15 #define UNIPHIER_PRO4_DWC3_RESET        0x40
16 #define   UNIPHIER_PRO4_DWC3_RESET_XIOMMU       BIT(5)
17 #define   UNIPHIER_PRO4_DWC3_RESET_XLINK        BIT(4)
18 #define   UNIPHIER_PRO4_DWC3_RESET_PHY_SS       BIT(2)
19
20 #define UNIPHIER_PRO5_DWC3_RESET        0x00
21 #define   UNIPHIER_PRO5_DWC3_RESET_PHY_S1       BIT(17)
22 #define   UNIPHIER_PRO5_DWC3_RESET_PHY_S0       BIT(16)
23 #define   UNIPHIER_PRO5_DWC3_RESET_XLINK        BIT(15)
24 #define   UNIPHIER_PRO5_DWC3_RESET_XIOMMU       BIT(14)
25
26 #define UNIPHIER_PXS2_DWC3_RESET        0x00
27 #define   UNIPHIER_PXS2_DWC3_RESET_XLINK        BIT(15)
28
29 static int uniphier_pro4_dwc3_init(void __iomem *regs)
30 {
31         u32 tmp;
32
33         tmp = readl(regs + UNIPHIER_PRO4_DWC3_RESET);
34         tmp &= ~UNIPHIER_PRO4_DWC3_RESET_PHY_SS;
35         tmp |= UNIPHIER_PRO4_DWC3_RESET_XIOMMU | UNIPHIER_PRO4_DWC3_RESET_XLINK;
36         writel(tmp, regs + UNIPHIER_PRO4_DWC3_RESET);
37
38         return 0;
39 }
40
41 static int uniphier_pro5_dwc3_init(void __iomem *regs)
42 {
43         u32 tmp;
44
45         tmp = readl(regs + UNIPHIER_PRO5_DWC3_RESET);
46         tmp &= ~(UNIPHIER_PRO5_DWC3_RESET_PHY_S1 |
47                  UNIPHIER_PRO5_DWC3_RESET_PHY_S0);
48         tmp |= UNIPHIER_PRO5_DWC3_RESET_XLINK | UNIPHIER_PRO5_DWC3_RESET_XIOMMU;
49         writel(tmp, regs + UNIPHIER_PRO5_DWC3_RESET);
50
51         return 0;
52 }
53
54 static int uniphier_pxs2_dwc3_init(void __iomem *regs)
55 {
56         u32 tmp;
57
58         tmp = readl(regs + UNIPHIER_PXS2_DWC3_RESET);
59         tmp |= UNIPHIER_PXS2_DWC3_RESET_XLINK;
60         writel(tmp, regs + UNIPHIER_PXS2_DWC3_RESET);
61
62         return 0;
63 }
64
65 static int uniphier_dwc3_probe(struct udevice *dev)
66 {
67         fdt_addr_t base;
68         void __iomem *regs;
69         int (*init)(void __iomem *regs);
70         int ret;
71
72         base = devfdt_get_addr(dev);
73         if (base == FDT_ADDR_T_NONE)
74                 return -EINVAL;
75
76         regs = ioremap(base, SZ_32K);
77         if (!regs)
78                 return -ENOMEM;
79
80         init = (typeof(init))dev_get_driver_data(dev);
81         ret = init(regs);
82         if (ret)
83                 dev_err(dev, "failed to init glue layer\n");
84
85         iounmap(regs);
86
87         return ret;
88 }
89
90 static const struct udevice_id uniphier_dwc3_match[] = {
91         {
92                 .compatible = "socionext,uniphier-pro4-dwc3",
93                 .data = (ulong)uniphier_pro4_dwc3_init,
94         },
95         {
96                 .compatible = "socionext,uniphier-pro5-dwc3",
97                 .data = (ulong)uniphier_pro5_dwc3_init,
98         },
99         {
100                 .compatible = "socionext,uniphier-pxs2-dwc3",
101                 .data = (ulong)uniphier_pxs2_dwc3_init,
102         },
103         {
104                 .compatible = "socionext,uniphier-ld20-dwc3",
105                 .data = (ulong)uniphier_pxs2_dwc3_init,
106         },
107         {
108                 .compatible = "socionext,uniphier-pxs3-dwc3",
109                 .data = (ulong)uniphier_pxs2_dwc3_init,
110         },
111         { /* sentinel */ }
112 };
113
114 U_BOOT_DRIVER(usb_xhci) = {
115         .name = "uniphier-dwc3",
116         .id = UCLASS_SIMPLE_BUS,
117         .of_match = uniphier_dwc3_match,
118         .probe = uniphier_dwc3_probe,
119 };