]>
Commit | Line | Data |
---|---|---|
22929e12 | 1 | // SPDX-License-Identifier: GPL-2.0 |
49d67454 MS |
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 <dm.h> | |
12 | #include <dm/device-internal.h> | |
13 | #include <dm/lists.h> | |
14 | #include <linux/usb/otg.h> | |
15 | #include <linux/compat.h> | |
16 | #include <linux/usb/ch9.h> | |
17 | #include <linux/usb/gadget.h> | |
18 | #include <malloc.h> | |
19 | #include <usb.h> | |
20 | #include "core.h" | |
21 | #include "gadget.h" | |
22 | #include "linux-compat.h" | |
23 | ||
687ab545 | 24 | #if CONFIG_IS_ENABLED(DM_USB_GADGET) |
49d67454 MS |
25 | int usb_gadget_handle_interrupts(int index) |
26 | { | |
27 | struct dwc3 *priv; | |
28 | struct udevice *dev; | |
29 | int ret; | |
30 | ||
31 | ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev); | |
32 | if (!dev || ret) { | |
33 | pr_err("No USB device found\n"); | |
34 | return -ENODEV; | |
35 | } | |
36 | ||
37 | priv = dev_get_priv(dev); | |
38 | ||
39 | dwc3_gadget_uboot_handle_interrupt(priv); | |
40 | ||
41 | return 0; | |
42 | } | |
43 | ||
44 | static int dwc3_generic_peripheral_probe(struct udevice *dev) | |
45 | { | |
46 | struct dwc3 *priv = dev_get_priv(dev); | |
47 | ||
48 | return dwc3_init(priv); | |
49 | } | |
50 | ||
51 | static int dwc3_generic_peripheral_remove(struct udevice *dev) | |
52 | { | |
53 | struct dwc3 *priv = dev_get_priv(dev); | |
54 | ||
55 | dwc3_remove(priv); | |
56 | ||
57 | return 0; | |
58 | } | |
59 | ||
60 | static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev) | |
61 | { | |
62 | struct dwc3 *priv = dev_get_priv(dev); | |
63 | int node = dev_of_offset(dev); | |
64 | ||
65 | priv->regs = (void *)devfdt_get_addr(dev); | |
66 | priv->regs += DWC3_GLOBALS_REGS_START; | |
67 | ||
68 | priv->maximum_speed = usb_get_maximum_speed(node); | |
69 | if (priv->maximum_speed == USB_SPEED_UNKNOWN) { | |
70 | pr_err("Invalid usb maximum speed\n"); | |
71 | return -ENODEV; | |
72 | } | |
73 | ||
74 | priv->dr_mode = usb_get_dr_mode(node); | |
75 | if (priv->dr_mode == USB_DR_MODE_UNKNOWN) { | |
76 | pr_err("Invalid usb mode setup\n"); | |
77 | return -ENODEV; | |
78 | } | |
79 | ||
80 | return 0; | |
81 | } | |
82 | ||
83 | static int dwc3_generic_peripheral_bind(struct udevice *dev) | |
84 | { | |
85 | return device_probe(dev); | |
86 | } | |
87 | ||
88 | U_BOOT_DRIVER(dwc3_generic_peripheral) = { | |
89 | .name = "dwc3-generic-peripheral", | |
90 | .id = UCLASS_USB_DEV_GENERIC, | |
91 | .ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata, | |
92 | .probe = dwc3_generic_peripheral_probe, | |
93 | .remove = dwc3_generic_peripheral_remove, | |
94 | .bind = dwc3_generic_peripheral_bind, | |
95 | .platdata_auto_alloc_size = sizeof(struct usb_platdata), | |
96 | .priv_auto_alloc_size = sizeof(struct dwc3), | |
97 | .flags = DM_FLAG_ALLOC_PRIV_DMA, | |
98 | }; | |
687ab545 | 99 | #endif |
49d67454 MS |
100 | |
101 | static int dwc3_generic_bind(struct udevice *parent) | |
102 | { | |
103 | const void *fdt = gd->fdt_blob; | |
104 | int node; | |
105 | int ret; | |
106 | ||
107 | for (node = fdt_first_subnode(fdt, dev_of_offset(parent)); node > 0; | |
108 | node = fdt_next_subnode(fdt, node)) { | |
109 | const char *name = fdt_get_name(fdt, node, NULL); | |
110 | enum usb_dr_mode dr_mode; | |
111 | struct udevice *dev; | |
112 | const char *driver; | |
113 | ||
114 | debug("%s: subnode name: %s\n", __func__, name); | |
115 | if (strncmp(name, "dwc3@", 4)) | |
116 | continue; | |
117 | ||
118 | dr_mode = usb_get_dr_mode(node); | |
119 | ||
120 | switch (dr_mode) { | |
121 | case USB_DR_MODE_PERIPHERAL: | |
122 | case USB_DR_MODE_OTG: | |
123 | debug("%s: dr_mode: OTG or Peripheral\n", __func__); | |
124 | driver = "dwc3-generic-peripheral"; | |
125 | break; | |
126 | case USB_DR_MODE_HOST: | |
127 | debug("%s: dr_mode: HOST\n", __func__); | |
128 | driver = "dwc3-generic-host"; | |
129 | break; | |
130 | default: | |
131 | debug("%s: unsupported dr_mode\n", __func__); | |
132 | return -ENODEV; | |
133 | }; | |
134 | ||
135 | ret = device_bind_driver_to_node(parent, driver, name, | |
136 | offset_to_ofnode(node), &dev); | |
137 | if (ret) { | |
138 | debug("%s: not able to bind usb device mode\n", | |
139 | __func__); | |
140 | return ret; | |
141 | } | |
142 | } | |
143 | ||
144 | return 0; | |
145 | } | |
146 | ||
147 | static const struct udevice_id dwc3_generic_ids[] = { | |
148 | { .compatible = "xlnx,zynqmp-dwc3" }, | |
149 | { } | |
150 | }; | |
151 | ||
152 | U_BOOT_DRIVER(dwc3_generic_wrapper) = { | |
153 | .name = "dwc3-generic-wrapper", | |
154 | .id = UCLASS_MISC, | |
155 | .of_match = dwc3_generic_ids, | |
156 | .bind = dwc3_generic_bind, | |
157 | }; |