arm: mach-k3: Enable dcache in SPL
[oweals/u-boot.git] / drivers / usb / host / ehci-generic.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2015 Alexey Brodkin <abrodkin@synopsys.com>
4  */
5
6 #include <common.h>
7 #include <clk.h>
8 #include <dm/device_compat.h>
9 #include <dm/devres.h>
10 #include <dm/ofnode.h>
11 #include <generic-phy.h>
12 #include <reset.h>
13 #include <asm/io.h>
14 #include <dm.h>
15 #include "ehci.h"
16 #include <power/regulator.h>
17
18 /*
19  * Even though here we don't explicitly use "struct ehci_ctrl"
20  * ehci_register() expects it to be the first thing that resides in
21  * device's private data.
22  */
23 struct generic_ehci {
24         struct ehci_ctrl ctrl;
25         struct clk *clocks;
26         struct reset_ctl *resets;
27         struct phy phy;
28 #ifdef CONFIG_DM_REGULATOR
29         struct udevice *vbus_supply;
30 #endif
31         int clock_count;
32         int reset_count;
33 };
34
35 #ifdef CONFIG_DM_REGULATOR
36 static int ehci_enable_vbus_supply(struct udevice *dev)
37 {
38         struct generic_ehci *priv = dev_get_priv(dev);
39         int ret;
40
41         ret = device_get_supply_regulator(dev, "vbus-supply",
42                                           &priv->vbus_supply);
43         if (ret && ret != -ENOENT)
44                 return ret;
45
46         if (priv->vbus_supply) {
47                 ret = regulator_set_enable(priv->vbus_supply, true);
48                 if (ret) {
49                         dev_err(dev, "Error enabling VBUS supply\n");
50                         return ret;
51                 }
52         } else {
53                 dev_dbg(dev, "No vbus supply\n");
54         }
55
56         return 0;
57 }
58
59 static int ehci_disable_vbus_supply(struct generic_ehci *priv)
60 {
61         if (priv->vbus_supply)
62                 return regulator_set_enable(priv->vbus_supply, false);
63         else
64                 return 0;
65 }
66 #else
67 static int ehci_enable_vbus_supply(struct udevice *dev)
68 {
69         return 0;
70 }
71
72 static int ehci_disable_vbus_supply(struct generic_ehci *priv)
73 {
74         return 0;
75 }
76 #endif
77
78 static int ehci_usb_probe(struct udevice *dev)
79 {
80         struct generic_ehci *priv = dev_get_priv(dev);
81         struct ehci_hccr *hccr;
82         struct ehci_hcor *hcor;
83         int i, err, ret, clock_nb, reset_nb;
84
85         err = 0;
86         priv->clock_count = 0;
87         clock_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "clocks",
88                                                   "#clock-cells");
89         if (clock_nb > 0) {
90                 priv->clocks = devm_kcalloc(dev, clock_nb, sizeof(struct clk),
91                                             GFP_KERNEL);
92                 if (!priv->clocks)
93                         return -ENOMEM;
94
95                 for (i = 0; i < clock_nb; i++) {
96                         err = clk_get_by_index(dev, i, &priv->clocks[i]);
97
98                         if (err < 0)
99                                 break;
100                         err = clk_enable(&priv->clocks[i]);
101                         if (err && err != -ENOSYS) {
102                                 dev_err(dev, "failed to enable clock %d\n", i);
103                                 clk_free(&priv->clocks[i]);
104                                 goto clk_err;
105                         }
106                         priv->clock_count++;
107                 }
108         } else {
109                 if (clock_nb != -ENOENT) {
110                         dev_err(dev, "failed to get clock phandle(%d)\n",
111                                 clock_nb);
112                         return clock_nb;
113                 }
114         }
115
116         priv->reset_count = 0;
117         reset_nb = ofnode_count_phandle_with_args(dev_ofnode(dev), "resets",
118                                                   "#reset-cells");
119         if (reset_nb > 0) {
120                 priv->resets = devm_kcalloc(dev, reset_nb,
121                                             sizeof(struct reset_ctl),
122                                             GFP_KERNEL);
123                 if (!priv->resets)
124                         return -ENOMEM;
125
126                 for (i = 0; i < reset_nb; i++) {
127                         err = reset_get_by_index(dev, i, &priv->resets[i]);
128                         if (err < 0)
129                                 break;
130
131                         if (reset_deassert(&priv->resets[i])) {
132                                 dev_err(dev, "failed to deassert reset %d\n",
133                                         i);
134                                 reset_free(&priv->resets[i]);
135                                 goto reset_err;
136                         }
137                         priv->reset_count++;
138                 }
139         } else {
140                 if (reset_nb != -ENOENT) {
141                         dev_err(dev, "failed to get reset phandle(%d)\n",
142                                 reset_nb);
143                         goto clk_err;
144                 }
145         }
146
147         err = ehci_enable_vbus_supply(dev);
148         if (err)
149                 goto reset_err;
150
151         err = ehci_setup_phy(dev, &priv->phy, 0);
152         if (err)
153                 goto regulator_err;
154
155         hccr = map_physmem(dev_read_addr(dev), 0x100, MAP_NOCACHE);
156         hcor = (struct ehci_hcor *)((uintptr_t)hccr +
157                                     HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
158
159         err = ehci_register(dev, hccr, hcor, NULL, 0, USB_INIT_HOST);
160         if (err)
161                 goto phy_err;
162
163         return 0;
164
165 phy_err:
166         ret = ehci_shutdown_phy(dev, &priv->phy);
167         if (ret)
168                 dev_err(dev, "failed to shutdown usb phy\n");
169
170 regulator_err:
171         ret = ehci_disable_vbus_supply(priv);
172         if (ret)
173                 dev_err(dev, "failed to disable VBUS supply\n");
174
175 reset_err:
176         ret = reset_release_all(priv->resets, priv->reset_count);
177         if (ret)
178                 dev_err(dev, "failed to assert all resets\n");
179 clk_err:
180         ret = clk_release_all(priv->clocks, priv->clock_count);
181         if (ret)
182                 dev_err(dev, "failed to disable all clocks\n");
183
184         return err;
185 }
186
187 static int ehci_usb_remove(struct udevice *dev)
188 {
189         struct generic_ehci *priv = dev_get_priv(dev);
190         int ret;
191
192         ret = ehci_deregister(dev);
193         if (ret)
194                 return ret;
195
196         ret = ehci_shutdown_phy(dev, &priv->phy);
197         if (ret)
198                 return ret;
199
200         ret = ehci_disable_vbus_supply(priv);
201         if (ret)
202                 return ret;
203
204         ret =  reset_release_all(priv->resets, priv->reset_count);
205         if (ret)
206                 return ret;
207
208         return clk_release_all(priv->clocks, priv->clock_count);
209 }
210
211 static const struct udevice_id ehci_usb_ids[] = {
212         { .compatible = "generic-ehci" },
213         { }
214 };
215
216 U_BOOT_DRIVER(ehci_generic) = {
217         .name   = "ehci_generic",
218         .id     = UCLASS_USB,
219         .of_match = ehci_usb_ids,
220         .probe = ehci_usb_probe,
221         .remove = ehci_usb_remove,
222         .ops    = &ehci_usb_ops,
223         .priv_auto_alloc_size = sizeof(struct generic_ehci),
224         .flags  = DM_FLAG_ALLOC_PRIV_DMA,
225 };