Merge branch 'master' of git://git.denx.de/u-boot
[oweals/u-boot.git] / drivers / usb / dwc3 / dwc3-generic.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Generic DWC3 Glue layer
4  *
5  * Copyright (C) 2016 - 2018 Xilinx, Inc.
6  *
7  * Based on dwc3-omap.c.
8  */
9
10 #include <common.h>
11 #include <cpu_func.h>
12 #include <asm-generic/io.h>
13 #include <dm.h>
14 #include <dm/device-internal.h>
15 #include <dm/lists.h>
16 #include <dwc3-uboot.h>
17 #include <linux/usb/ch9.h>
18 #include <linux/usb/gadget.h>
19 #include <malloc.h>
20 #include <usb.h>
21 #include "core.h"
22 #include "gadget.h"
23 #include <reset.h>
24 #include <clk.h>
25 #include <usb/xhci.h>
26
27 struct dwc3_generic_plat {
28         fdt_addr_t base;
29         u32 maximum_speed;
30         enum usb_dr_mode dr_mode;
31 };
32
33 struct dwc3_generic_priv {
34         void *base;
35         struct dwc3 dwc3;
36         struct phy_bulk phys;
37 };
38
39 struct dwc3_generic_host_priv {
40         struct xhci_ctrl xhci_ctrl;
41         struct dwc3_generic_priv gen_priv;
42 };
43
44 static int dwc3_generic_probe(struct udevice *dev,
45                               struct dwc3_generic_priv *priv)
46 {
47         int rc;
48         struct dwc3_generic_plat *plat = dev_get_platdata(dev);
49         struct dwc3 *dwc3 = &priv->dwc3;
50
51         dwc3->dev = dev;
52         dwc3->maximum_speed = plat->maximum_speed;
53         dwc3->dr_mode = plat->dr_mode;
54 #if CONFIG_IS_ENABLED(OF_CONTROL)
55         dwc3_of_parse(dwc3);
56 #endif
57
58         rc = dwc3_setup_phy(dev, &priv->phys);
59         if (rc)
60                 return rc;
61
62         priv->base = map_physmem(plat->base, DWC3_OTG_REGS_END, MAP_NOCACHE);
63         dwc3->regs = priv->base + DWC3_GLOBALS_REGS_START;
64
65
66         rc =  dwc3_init(dwc3);
67         if (rc) {
68                 unmap_physmem(priv->base, MAP_NOCACHE);
69                 return rc;
70         }
71
72         return 0;
73 }
74
75 static int dwc3_generic_remove(struct udevice *dev,
76                                struct dwc3_generic_priv *priv)
77 {
78         struct dwc3 *dwc3 = &priv->dwc3;
79
80         dwc3_remove(dwc3);
81         dwc3_shutdown_phy(dev, &priv->phys);
82         unmap_physmem(dwc3->regs, MAP_NOCACHE);
83
84         return 0;
85 }
86
87 static int dwc3_generic_ofdata_to_platdata(struct udevice *dev)
88 {
89         struct dwc3_generic_plat *plat = dev_get_platdata(dev);
90         ofnode node = dev->node;
91
92         plat->base = dev_read_addr(dev);
93
94         plat->maximum_speed = usb_get_maximum_speed(node);
95         if (plat->maximum_speed == USB_SPEED_UNKNOWN) {
96                 pr_info("No USB maximum speed specified. Using super speed\n");
97                 plat->maximum_speed = USB_SPEED_SUPER;
98         }
99
100         plat->dr_mode = usb_get_dr_mode(node);
101         if (plat->dr_mode == USB_DR_MODE_UNKNOWN) {
102                 pr_err("Invalid usb mode setup\n");
103                 return -ENODEV;
104         }
105
106         return 0;
107 }
108
109 #if CONFIG_IS_ENABLED(DM_USB_GADGET)
110 int dm_usb_gadget_handle_interrupts(struct udevice *dev)
111 {
112         struct dwc3_generic_priv *priv = dev_get_priv(dev);
113         struct dwc3 *dwc3 = &priv->dwc3;
114
115         dwc3_gadget_uboot_handle_interrupt(dwc3);
116
117         return 0;
118 }
119
120 static int dwc3_generic_peripheral_probe(struct udevice *dev)
121 {
122         struct dwc3_generic_priv *priv = dev_get_priv(dev);
123
124         return dwc3_generic_probe(dev, priv);
125 }
126
127 static int dwc3_generic_peripheral_remove(struct udevice *dev)
128 {
129         struct dwc3_generic_priv *priv = dev_get_priv(dev);
130
131         return dwc3_generic_remove(dev, priv);
132 }
133
134 U_BOOT_DRIVER(dwc3_generic_peripheral) = {
135         .name   = "dwc3-generic-peripheral",
136         .id     = UCLASS_USB_GADGET_GENERIC,
137         .ofdata_to_platdata = dwc3_generic_ofdata_to_platdata,
138         .probe = dwc3_generic_peripheral_probe,
139         .remove = dwc3_generic_peripheral_remove,
140         .priv_auto_alloc_size = sizeof(struct dwc3_generic_priv),
141         .platdata_auto_alloc_size = sizeof(struct dwc3_generic_plat),
142 };
143 #endif
144
145 #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD)
146 static int dwc3_generic_host_probe(struct udevice *dev)
147 {
148         struct xhci_hcor *hcor;
149         struct xhci_hccr *hccr;
150         struct dwc3_generic_host_priv *priv = dev_get_priv(dev);
151         int rc;
152
153         rc = dwc3_generic_probe(dev, &priv->gen_priv);
154         if (rc)
155                 return rc;
156
157         hccr = (struct xhci_hccr *)priv->gen_priv.base;
158         hcor = (struct xhci_hcor *)(priv->gen_priv.base +
159                         HC_LENGTH(xhci_readl(&(hccr)->cr_capbase)));
160
161         return xhci_register(dev, hccr, hcor);
162 }
163
164 static int dwc3_generic_host_remove(struct udevice *dev)
165 {
166         struct dwc3_generic_host_priv *priv = dev_get_priv(dev);
167         int rc;
168
169         rc = xhci_deregister(dev);
170         if (rc)
171                 return rc;
172
173         return dwc3_generic_remove(dev, &priv->gen_priv);
174 }
175
176 U_BOOT_DRIVER(dwc3_generic_host) = {
177         .name   = "dwc3-generic-host",
178         .id     = UCLASS_USB,
179         .ofdata_to_platdata = dwc3_generic_ofdata_to_platdata,
180         .probe = dwc3_generic_host_probe,
181         .remove = dwc3_generic_host_remove,
182         .priv_auto_alloc_size = sizeof(struct dwc3_generic_host_priv),
183         .platdata_auto_alloc_size = sizeof(struct dwc3_generic_plat),
184         .ops = &xhci_usb_ops,
185         .flags = DM_FLAG_ALLOC_PRIV_DMA,
186 };
187 #endif
188
189 struct dwc3_glue_data {
190         struct clk_bulk         clks;
191         struct reset_ctl_bulk   resets;
192         fdt_addr_t regs;
193 };
194
195 struct dwc3_glue_ops {
196         void (*select_dr_mode)(struct udevice *dev, int index,
197                                enum usb_dr_mode mode);
198 };
199
200 void dwc3_ti_select_dr_mode(struct udevice *dev, int index,
201                             enum usb_dr_mode mode)
202 {
203 #define USBOTGSS_UTMI_OTG_STATUS                0x0084
204 #define USBOTGSS_UTMI_OTG_OFFSET                0x0480
205
206 /* UTMI_OTG_STATUS REGISTER */
207 #define USBOTGSS_UTMI_OTG_STATUS_SW_MODE        BIT(31)
208 #define USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT   BIT(9)
209 #define USBOTGSS_UTMI_OTG_STATUS_TXBITSTUFFENABLE BIT(8)
210 #define USBOTGSS_UTMI_OTG_STATUS_IDDIG          BIT(4)
211 #define USBOTGSS_UTMI_OTG_STATUS_SESSEND        BIT(3)
212 #define USBOTGSS_UTMI_OTG_STATUS_SESSVALID      BIT(2)
213 #define USBOTGSS_UTMI_OTG_STATUS_VBUSVALID      BIT(1)
214 enum dwc3_omap_utmi_mode {
215         DWC3_OMAP_UTMI_MODE_UNKNOWN = 0,
216         DWC3_OMAP_UTMI_MODE_HW,
217         DWC3_OMAP_UTMI_MODE_SW,
218 };
219
220         u32 use_id_pin;
221         u32 host_mode;
222         u32 reg;
223         u32 utmi_mode;
224         u32 utmi_status_offset = USBOTGSS_UTMI_OTG_STATUS;
225
226         struct dwc3_glue_data *glue = dev_get_platdata(dev);
227         void *base = map_physmem(glue->regs, 0x10000, MAP_NOCACHE);
228
229         if (device_is_compatible(dev, "ti,am437x-dwc3"))
230                 utmi_status_offset += USBOTGSS_UTMI_OTG_OFFSET;
231
232         utmi_mode = dev_read_u32_default(dev, "utmi-mode",
233                                          DWC3_OMAP_UTMI_MODE_UNKNOWN);
234         if (utmi_mode != DWC3_OMAP_UTMI_MODE_HW) {
235                 debug("%s: OTG is not supported. defaulting to PERIPHERAL\n",
236                       dev->name);
237                 mode = USB_DR_MODE_PERIPHERAL;
238         }
239
240         switch (mode)  {
241         case USB_DR_MODE_PERIPHERAL:
242                 use_id_pin = 0;
243                 host_mode = 0;
244                 break;
245         case USB_DR_MODE_HOST:
246                 use_id_pin = 0;
247                 host_mode = 1;
248                 break;
249         case USB_DR_MODE_OTG:
250         default:
251                 use_id_pin = 1;
252                 host_mode = 0;
253                 break;
254         }
255
256         reg = readl(base + utmi_status_offset);
257
258         reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SW_MODE);
259         if (!use_id_pin)
260                 reg |= USBOTGSS_UTMI_OTG_STATUS_SW_MODE;
261
262         writel(reg, base + utmi_status_offset);
263
264         reg &= ~(USBOTGSS_UTMI_OTG_STATUS_SESSEND |
265                 USBOTGSS_UTMI_OTG_STATUS_VBUSVALID |
266                 USBOTGSS_UTMI_OTG_STATUS_IDDIG);
267
268         reg |= USBOTGSS_UTMI_OTG_STATUS_SESSVALID |
269                 USBOTGSS_UTMI_OTG_STATUS_POWERPRESENT;
270
271         if (!host_mode)
272                 reg |= USBOTGSS_UTMI_OTG_STATUS_IDDIG |
273                         USBOTGSS_UTMI_OTG_STATUS_VBUSVALID;
274
275         writel(reg, base + utmi_status_offset);
276
277         unmap_physmem(base, MAP_NOCACHE);
278 }
279
280 struct dwc3_glue_ops ti_ops = {
281         .select_dr_mode = dwc3_ti_select_dr_mode,
282 };
283
284 static int dwc3_glue_bind(struct udevice *parent)
285 {
286         ofnode node;
287         int ret;
288
289         ofnode_for_each_subnode(node, parent->node) {
290                 const char *name = ofnode_get_name(node);
291                 enum usb_dr_mode dr_mode;
292                 struct udevice *dev;
293                 const char *driver = NULL;
294
295                 debug("%s: subnode name: %s\n", __func__, name);
296
297                 dr_mode = usb_get_dr_mode(node);
298
299                 switch (dr_mode) {
300                 case USB_DR_MODE_PERIPHERAL:
301                 case USB_DR_MODE_OTG:
302 #if CONFIG_IS_ENABLED(DM_USB_GADGET)
303                         debug("%s: dr_mode: OTG or Peripheral\n", __func__);
304                         driver = "dwc3-generic-peripheral";
305 #endif
306                         break;
307 #if defined(CONFIG_SPL_USB_HOST_SUPPORT) || !defined(CONFIG_SPL_BUILD)
308                 case USB_DR_MODE_HOST:
309                         debug("%s: dr_mode: HOST\n", __func__);
310                         driver = "dwc3-generic-host";
311                         break;
312 #endif
313                 default:
314                         debug("%s: unsupported dr_mode\n", __func__);
315                         return -ENODEV;
316                 };
317
318                 if (!driver)
319                         continue;
320
321                 ret = device_bind_driver_to_node(parent, driver, name,
322                                                  node, &dev);
323                 if (ret) {
324                         debug("%s: not able to bind usb device mode\n",
325                               __func__);
326                         return ret;
327                 }
328         }
329
330         return 0;
331 }
332
333 static int dwc3_glue_reset_init(struct udevice *dev,
334                                 struct dwc3_glue_data *glue)
335 {
336         int ret;
337
338         ret = reset_get_bulk(dev, &glue->resets);
339         if (ret == -ENOTSUPP || ret == -ENOENT)
340                 return 0;
341         else if (ret)
342                 return ret;
343
344         ret = reset_deassert_bulk(&glue->resets);
345         if (ret) {
346                 reset_release_bulk(&glue->resets);
347                 return ret;
348         }
349
350         return 0;
351 }
352
353 static int dwc3_glue_clk_init(struct udevice *dev,
354                               struct dwc3_glue_data *glue)
355 {
356         int ret;
357
358         ret = clk_get_bulk(dev, &glue->clks);
359         if (ret == -ENOSYS || ret == -ENOENT)
360                 return 0;
361         if (ret)
362                 return ret;
363
364 #if CONFIG_IS_ENABLED(CLK)
365         ret = clk_enable_bulk(&glue->clks);
366         if (ret) {
367                 clk_release_bulk(&glue->clks);
368                 return ret;
369         }
370 #endif
371
372         return 0;
373 }
374
375 static int dwc3_glue_probe(struct udevice *dev)
376 {
377         struct dwc3_glue_ops *ops = (struct dwc3_glue_ops *)dev_get_driver_data(dev);
378         struct dwc3_glue_data *glue = dev_get_platdata(dev);
379         struct udevice *child = NULL;
380         int index = 0;
381         int ret;
382
383         glue->regs = dev_read_addr(dev);
384
385         ret = dwc3_glue_clk_init(dev, glue);
386         if (ret)
387                 return ret;
388
389         ret = dwc3_glue_reset_init(dev, glue);
390         if (ret)
391                 return ret;
392
393         ret = device_find_first_child(dev, &child);
394         if (ret)
395                 return ret;
396
397         while (child) {
398                 enum usb_dr_mode dr_mode;
399
400                 dr_mode = usb_get_dr_mode(child->node);
401                 device_find_next_child(&child);
402                 if (ops && ops->select_dr_mode)
403                         ops->select_dr_mode(dev, index, dr_mode);
404                 index++;
405         }
406
407         return 0;
408 }
409
410 static int dwc3_glue_remove(struct udevice *dev)
411 {
412         struct dwc3_glue_data *glue = dev_get_platdata(dev);
413
414         reset_release_bulk(&glue->resets);
415
416         clk_release_bulk(&glue->clks);
417
418         return 0;
419 }
420
421 static const struct udevice_id dwc3_glue_ids[] = {
422         { .compatible = "xlnx,zynqmp-dwc3" },
423         { .compatible = "ti,keystone-dwc3"},
424         { .compatible = "ti,dwc3", .data = (ulong)&ti_ops },
425         { .compatible = "ti,am437x-dwc3", .data = (ulong)&ti_ops },
426         { .compatible = "ti,am654-dwc3" },
427         { }
428 };
429
430 U_BOOT_DRIVER(dwc3_generic_wrapper) = {
431         .name   = "dwc3-generic-wrapper",
432         .id     = UCLASS_NOP,
433         .of_match = dwc3_glue_ids,
434         .bind = dwc3_glue_bind,
435         .probe = dwc3_glue_probe,
436         .remove = dwc3_glue_remove,
437         .platdata_auto_alloc_size = sizeof(struct dwc3_glue_data),
438
439 };