blob: 7375660fa83e00b98090b144ddf879c9b35f7e78 [file] [log] [blame]
Patrick Delaunay22929e12018-10-26 09:02:52 +02001// SPDX-License-Identifier: GPL-2.0
Michal Simek49d67452018-05-18 13:15:06 +02002/*
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
Jean-Jacques Hiblot687ab542018-11-29 10:52:42 +010024#if CONFIG_IS_ENABLED(DM_USB_GADGET)
Jean-Jacques Hiblotff8d7552018-11-29 10:52:43 +010025int dm_usb_gadget_handle_interrupts(struct udevice *dev)
Michal Simek49d67452018-05-18 13:15:06 +020026{
Jean-Jacques Hiblotff8d7552018-11-29 10:52:43 +010027 struct dwc3 *priv = dev_get_priv(dev);
Michal Simek49d67452018-05-18 13:15:06 +020028
29 dwc3_gadget_uboot_handle_interrupt(priv);
30
31 return 0;
32}
33
34static int dwc3_generic_peripheral_probe(struct udevice *dev)
35{
36 struct dwc3 *priv = dev_get_priv(dev);
37
38 return dwc3_init(priv);
39}
40
41static int dwc3_generic_peripheral_remove(struct udevice *dev)
42{
43 struct dwc3 *priv = dev_get_priv(dev);
44
45 dwc3_remove(priv);
46
47 return 0;
48}
49
50static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice *dev)
51{
52 struct dwc3 *priv = dev_get_priv(dev);
53 int node = dev_of_offset(dev);
54
55 priv->regs = (void *)devfdt_get_addr(dev);
56 priv->regs += DWC3_GLOBALS_REGS_START;
57
58 priv->maximum_speed = usb_get_maximum_speed(node);
59 if (priv->maximum_speed == USB_SPEED_UNKNOWN) {
60 pr_err("Invalid usb maximum speed\n");
61 return -ENODEV;
62 }
63
64 priv->dr_mode = usb_get_dr_mode(node);
65 if (priv->dr_mode == USB_DR_MODE_UNKNOWN) {
66 pr_err("Invalid usb mode setup\n");
67 return -ENODEV;
68 }
69
70 return 0;
71}
72
Michal Simek49d67452018-05-18 13:15:06 +020073U_BOOT_DRIVER(dwc3_generic_peripheral) = {
74 .name = "dwc3-generic-peripheral",
Jean-Jacques Hiblot01311622018-11-29 10:52:46 +010075 .id = UCLASS_USB_GADGET_GENERIC,
Michal Simek49d67452018-05-18 13:15:06 +020076 .ofdata_to_platdata = dwc3_generic_peripheral_ofdata_to_platdata,
77 .probe = dwc3_generic_peripheral_probe,
78 .remove = dwc3_generic_peripheral_remove,
Michal Simek49d67452018-05-18 13:15:06 +020079 .platdata_auto_alloc_size = sizeof(struct usb_platdata),
80 .priv_auto_alloc_size = sizeof(struct dwc3),
Michal Simek49d67452018-05-18 13:15:06 +020081};
Jean-Jacques Hiblot687ab542018-11-29 10:52:42 +010082#endif
Michal Simek49d67452018-05-18 13:15:06 +020083
84static int dwc3_generic_bind(struct udevice *parent)
85{
86 const void *fdt = gd->fdt_blob;
87 int node;
88 int ret;
89
90 for (node = fdt_first_subnode(fdt, dev_of_offset(parent)); node > 0;
91 node = fdt_next_subnode(fdt, node)) {
92 const char *name = fdt_get_name(fdt, node, NULL);
93 enum usb_dr_mode dr_mode;
94 struct udevice *dev;
95 const char *driver;
96
97 debug("%s: subnode name: %s\n", __func__, name);
98 if (strncmp(name, "dwc3@", 4))
99 continue;
100
101 dr_mode = usb_get_dr_mode(node);
102
103 switch (dr_mode) {
104 case USB_DR_MODE_PERIPHERAL:
105 case USB_DR_MODE_OTG:
106 debug("%s: dr_mode: OTG or Peripheral\n", __func__);
107 driver = "dwc3-generic-peripheral";
108 break;
109 case USB_DR_MODE_HOST:
110 debug("%s: dr_mode: HOST\n", __func__);
111 driver = "dwc3-generic-host";
112 break;
113 default:
114 debug("%s: unsupported dr_mode\n", __func__);
115 return -ENODEV;
116 };
117
118 ret = device_bind_driver_to_node(parent, driver, name,
119 offset_to_ofnode(node), &dev);
120 if (ret) {
121 debug("%s: not able to bind usb device mode\n",
122 __func__);
123 return ret;
124 }
125 }
126
127 return 0;
128}
129
130static const struct udevice_id dwc3_generic_ids[] = {
131 { .compatible = "xlnx,zynqmp-dwc3" },
132 { }
133};
134
135U_BOOT_DRIVER(dwc3_generic_wrapper) = {
136 .name = "dwc3-generic-wrapper",
137 .id = UCLASS_MISC,
138 .of_match = dwc3_generic_ids,
139 .bind = dwc3_generic_bind,
140};