1 // SPDX-License-Identifier: GPL-2.0
3 * Generic DWC3 Glue layer
5 * Copyright (C) 2016 - 2018 Xilinx, Inc.
7 * Based on dwc3-omap.c.
12 #include <dm/device-internal.h>
14 #include <dwc3-uboot.h>
15 #include <linux/usb/ch9.h>
16 #include <linux/usb/gadget.h>
24 #if CONFIG_IS_ENABLED(DM_USB_GADGET)
25 struct dwc3_generic_peripheral
{
32 int dm_usb_gadget_handle_interrupts(struct udevice
*dev
)
34 struct dwc3_generic_peripheral
*priv
= dev_get_priv(dev
);
35 struct dwc3
*dwc3
= &priv
->dwc3
;
37 dwc3_gadget_uboot_handle_interrupt(dwc3
);
42 static int dwc3_generic_peripheral_probe(struct udevice
*dev
)
45 struct dwc3_generic_peripheral
*priv
= dev_get_priv(dev
);
46 struct dwc3
*dwc3
= &priv
->dwc3
;
48 rc
= dwc3_setup_phy(dev
, &priv
->phys
, &priv
->num_phys
);
52 dwc3
->regs
= map_physmem(priv
->base
, DWC3_OTG_REGS_END
, MAP_NOCACHE
);
53 dwc3
->regs
+= DWC3_GLOBALS_REGS_START
;
58 unmap_physmem(dwc3
->regs
, MAP_NOCACHE
);
65 static int dwc3_generic_peripheral_remove(struct udevice
*dev
)
67 struct dwc3_generic_peripheral
*priv
= dev_get_priv(dev
);
68 struct dwc3
*dwc3
= &priv
->dwc3
;
71 dwc3_shutdown_phy(dev
, priv
->phys
, priv
->num_phys
);
72 unmap_physmem(dwc3
->regs
, MAP_NOCACHE
);
77 static int dwc3_generic_peripheral_ofdata_to_platdata(struct udevice
*dev
)
79 struct dwc3_generic_peripheral
*priv
= dev_get_priv(dev
);
80 struct dwc3
*dwc3
= &priv
->dwc3
;
81 int node
= dev_of_offset(dev
);
83 priv
->base
= devfdt_get_addr(dev
);
85 dwc3
->maximum_speed
= usb_get_maximum_speed(node
);
86 if (dwc3
->maximum_speed
== USB_SPEED_UNKNOWN
) {
87 pr_err("Invalid usb maximum speed\n");
91 dwc3
->dr_mode
= usb_get_dr_mode(node
);
92 if (dwc3
->dr_mode
== USB_DR_MODE_UNKNOWN
) {
93 pr_err("Invalid usb mode setup\n");
100 U_BOOT_DRIVER(dwc3_generic_peripheral
) = {
101 .name
= "dwc3-generic-peripheral",
102 .id
= UCLASS_USB_GADGET_GENERIC
,
103 .ofdata_to_platdata
= dwc3_generic_peripheral_ofdata_to_platdata
,
104 .probe
= dwc3_generic_peripheral_probe
,
105 .remove
= dwc3_generic_peripheral_remove
,
106 .priv_auto_alloc_size
= sizeof(struct dwc3_generic_peripheral
),
110 struct dwc3_glue_data
{
111 struct clk_bulk clks
;
112 struct reset_ctl_bulk resets
;
115 static int dwc3_glue_bind(struct udevice
*parent
)
117 const void *fdt
= gd
->fdt_blob
;
121 for (node
= fdt_first_subnode(fdt
, dev_of_offset(parent
)); node
> 0;
122 node
= fdt_next_subnode(fdt
, node
)) {
123 const char *name
= fdt_get_name(fdt
, node
, NULL
);
124 enum usb_dr_mode dr_mode
;
126 const char *driver
= NULL
;
128 debug("%s: subnode name: %s\n", __func__
, name
);
130 dr_mode
= usb_get_dr_mode(node
);
133 case USB_DR_MODE_PERIPHERAL
:
134 case USB_DR_MODE_OTG
:
135 #if CONFIG_IS_ENABLED(DM_USB_GADGET)
136 debug("%s: dr_mode: OTG or Peripheral\n", __func__
);
137 driver
= "dwc3-generic-peripheral";
140 case USB_DR_MODE_HOST
:
141 debug("%s: dr_mode: HOST\n", __func__
);
142 driver
= "xhci-dwc3";
145 debug("%s: unsupported dr_mode\n", __func__
);
152 ret
= device_bind_driver_to_node(parent
, driver
, name
,
153 offset_to_ofnode(node
), &dev
);
155 debug("%s: not able to bind usb device mode\n",
164 static int dwc3_glue_reset_init(struct udevice
*dev
,
165 struct dwc3_glue_data
*glue
)
169 ret
= reset_get_bulk(dev
, &glue
->resets
);
170 if (ret
== -ENOTSUPP
)
175 ret
= reset_deassert_bulk(&glue
->resets
);
177 reset_release_bulk(&glue
->resets
);
184 static int dwc3_glue_clk_init(struct udevice
*dev
,
185 struct dwc3_glue_data
*glue
)
189 ret
= clk_get_bulk(dev
, &glue
->clks
);
195 #if CONFIG_IS_ENABLED(CLK)
196 ret
= clk_enable_bulk(&glue
->clks
);
198 clk_release_bulk(&glue
->clks
);
206 static int dwc3_glue_probe(struct udevice
*dev
)
208 struct dwc3_glue_data
*glue
= dev_get_platdata(dev
);
211 ret
= dwc3_glue_clk_init(dev
, glue
);
215 ret
= dwc3_glue_reset_init(dev
, glue
);
222 static int dwc3_glue_remove(struct udevice
*dev
)
224 struct dwc3_glue_data
*glue
= dev_get_platdata(dev
);
226 reset_release_bulk(&glue
->resets
);
228 clk_release_bulk(&glue
->clks
);
230 return dm_scan_fdt_dev(dev
);
233 static const struct udevice_id dwc3_glue_ids
[] = {
234 { .compatible
= "xlnx,zynqmp-dwc3" },
238 U_BOOT_DRIVER(dwc3_generic_wrapper
) = {
239 .name
= "dwc3-generic-wrapper",
241 .of_match
= dwc3_glue_ids
,
242 .bind
= dwc3_glue_bind
,
243 .probe
= dwc3_glue_probe
,
244 .remove
= dwc3_glue_remove
,
245 .platdata_auto_alloc_size
= sizeof(struct dwc3_glue_data
),