1 // SPDX-License-Identifier: GPL-2.0+
3 * MISC driver for TI MUSB Glue.
6 * Texas Instruments Incorporated, <www.ti.com>
14 #include <asm/global_data.h>
15 #include <linux/usb/otg.h>
16 #include <dm/device-internal.h>
20 #include <asm/omap_musb.h>
21 #include "musb_uboot.h"
23 DECLARE_GLOBAL_DATA_PTR
;
25 #if CONFIG_IS_ENABLED(DM_USB)
26 /* USB 2.0 PHY Control */
27 #define CM_PHY_PWRDN (1 << 0)
28 #define CM_PHY_OTG_PWRDN (1 << 1)
29 #define OTGVDET_EN (1 << 19)
30 #define OTGSESSENDEN (1 << 20)
32 #define AM335X_USB0_CTRL 0x0
33 #define AM335X_USB1_CTRL 0x8
35 static void ti_musb_set_phy_power(struct udevice
*dev
, u8 on
)
37 struct ti_musb_plat
*plat
= dev_get_plat(dev
);
39 if (!plat
->ctrl_mod_base
)
43 clrsetbits_le32(plat
->ctrl_mod_base
,
44 CM_PHY_PWRDN
| CM_PHY_OTG_PWRDN
,
45 OTGVDET_EN
| OTGSESSENDEN
);
47 clrsetbits_le32(plat
->ctrl_mod_base
, 0,
48 CM_PHY_PWRDN
| CM_PHY_OTG_PWRDN
);
52 #if CONFIG_IS_ENABLED(OF_CONTROL)
54 static int ti_musb_get_usb_index(int node
)
56 const void *fdt
= gd
->fdt_blob
;
59 const char *alias_path
;
62 fdt_get_path(fdt
, node
, path
, sizeof(path
));
65 snprintf(alias
, sizeof(alias
), "usb%d", i
);
66 alias_path
= fdt_get_alias(fdt
, alias
);
67 if (alias_path
== NULL
) {
68 debug("USB index not found\n");
72 if (!strcmp(path
, alias_path
))
81 static int ti_musb_of_to_plat(struct udevice
*dev
)
83 struct ti_musb_plat
*plat
= dev_get_plat(dev
);
84 const void *fdt
= gd
->fdt_blob
;
85 int node
= dev_of_offset(dev
);
89 struct musb_hdrc_config
*musb_config
;
91 plat
->base
= devfdt_get_addr_index_ptr(dev
, 1);
93 phys
= fdtdec_lookup_phandle(fdt
, node
, "phys");
94 ctrl_mod
= fdtdec_lookup_phandle(fdt
, phys
, "ti,ctrl_mod");
95 plat
->ctrl_mod_base
= (void *)fdtdec_get_addr(fdt
, ctrl_mod
, "reg");
96 usb_index
= ti_musb_get_usb_index(node
);
99 plat
->ctrl_mod_base
+= AM335X_USB1_CTRL
;
102 plat
->ctrl_mod_base
+= AM335X_USB0_CTRL
;
108 musb_config
= malloc(sizeof(struct musb_hdrc_config
));
109 memset(musb_config
, 0, sizeof(struct musb_hdrc_config
));
111 musb_config
->multipoint
= fdtdec_get_int(fdt
, node
,
112 "mentor,multipoint", -1);
113 if (musb_config
->multipoint
< 0) {
114 pr_err("MUSB multipoint DT entry missing\n");
118 musb_config
->dyn_fifo
= 1;
120 musb_config
->num_eps
= fdtdec_get_int(fdt
, node
, "mentor,num-eps",
122 if (musb_config
->num_eps
< 0) {
123 pr_err("MUSB num-eps DT entry missing\n");
127 musb_config
->ram_bits
= fdtdec_get_int(fdt
, node
, "mentor,ram-bits",
129 if (musb_config
->ram_bits
< 0) {
130 pr_err("MUSB ram-bits DT entry missing\n");
134 plat
->plat
.config
= musb_config
;
136 plat
->plat
.power
= fdtdec_get_int(fdt
, node
, "mentor,power", -1);
137 if (plat
->plat
.power
< 0) {
138 pr_err("MUSB mentor,power DT entry missing\n");
142 plat
->plat
.platform_ops
= &musb_dsps_ops
;
148 static int ti_musb_host_probe(struct udevice
*dev
)
150 struct musb_host_data
*host
= dev_get_priv(dev
);
151 struct ti_musb_plat
*plat
= dev_get_plat(dev
);
152 struct usb_bus_priv
*priv
= dev_get_uclass_priv(dev
);
155 priv
->desc_before_addr
= true;
157 host
->host
= musb_init_controller(&plat
->plat
,
163 ti_musb_set_phy_power(dev
, 1);
164 ret
= musb_lowlevel_init(host
);
169 static int ti_musb_host_remove(struct udevice
*dev
)
171 struct musb_host_data
*host
= dev_get_priv(dev
);
173 musb_stop(host
->host
);
174 ti_musb_set_phy_power(dev
, 0);
179 #if CONFIG_IS_ENABLED(OF_CONTROL)
180 static int ti_musb_host_of_to_plat(struct udevice
*dev
)
182 struct ti_musb_plat
*plat
= dev_get_plat(dev
);
183 const void *fdt
= gd
->fdt_blob
;
184 int node
= dev_of_offset(dev
);
187 ret
= ti_musb_of_to_plat(dev
);
189 pr_err("plat dt parse error\n");
193 plat
->plat
.mode
= MUSB_HOST
;
199 U_BOOT_DRIVER(ti_musb_host
) = {
200 .name
= "ti-musb-host",
202 #if CONFIG_IS_ENABLED(OF_CONTROL)
203 .of_to_plat
= ti_musb_host_of_to_plat
,
205 .probe
= ti_musb_host_probe
,
206 .remove
= ti_musb_host_remove
,
207 .ops
= &musb_usb_ops
,
208 .plat_auto
= sizeof(struct ti_musb_plat
),
209 .priv_auto
= sizeof(struct musb_host_data
),
212 #if CONFIG_IS_ENABLED(DM_USB_GADGET)
213 struct ti_musb_peripheral
{
217 #if CONFIG_IS_ENABLED(OF_CONTROL)
218 static int ti_musb_peripheral_of_to_plat(struct udevice
*dev
)
220 struct ti_musb_plat
*plat
= dev_get_plat(dev
);
221 const void *fdt
= gd
->fdt_blob
;
222 int node
= dev_of_offset(dev
);
225 ret
= ti_musb_of_to_plat(dev
);
227 pr_err("plat dt parse error\n");
230 plat
->plat
.mode
= MUSB_PERIPHERAL
;
236 int dm_usb_gadget_handle_interrupts(struct udevice
*dev
)
238 struct ti_musb_peripheral
*priv
= dev_get_priv(dev
);
240 priv
->periph
->isr(0, priv
->periph
);
245 static int ti_musb_peripheral_probe(struct udevice
*dev
)
247 struct ti_musb_peripheral
*priv
= dev_get_priv(dev
);
248 struct ti_musb_plat
*plat
= dev_get_plat(dev
);
251 priv
->periph
= musb_init_controller(&plat
->plat
,
257 ti_musb_set_phy_power(dev
, 1);
258 musb_gadget_setup(priv
->periph
);
259 return usb_add_gadget_udc((struct device
*)dev
, &priv
->periph
->g
);
262 static int ti_musb_peripheral_remove(struct udevice
*dev
)
264 struct ti_musb_peripheral
*priv
= dev_get_priv(dev
);
266 usb_del_gadget_udc(&priv
->periph
->g
);
267 ti_musb_set_phy_power(dev
, 0);
272 U_BOOT_DRIVER(ti_musb_peripheral
) = {
273 .name
= "ti-musb-peripheral",
274 .id
= UCLASS_USB_GADGET_GENERIC
,
275 #if CONFIG_IS_ENABLED(OF_CONTROL)
276 .of_to_plat
= ti_musb_peripheral_of_to_plat
,
278 .probe
= ti_musb_peripheral_probe
,
279 .remove
= ti_musb_peripheral_remove
,
280 .ops
= &musb_usb_ops
,
281 .plat_auto
= sizeof(struct ti_musb_plat
),
282 .priv_auto
= sizeof(struct ti_musb_peripheral
),
283 .flags
= DM_FLAG_PRE_RELOC
,
287 #if CONFIG_IS_ENABLED(OF_CONTROL)
288 static int ti_musb_wrapper_bind(struct udevice
*parent
)
293 ofnode_for_each_subnode(node
, dev_ofnode(parent
)) {
295 const char *name
= ofnode_get_name(node
);
296 enum usb_dr_mode dr_mode
;
299 if (strncmp(name
, "usb@", 4))
302 dr_mode
= usb_get_dr_mode(node
);
304 case USB_DR_MODE_PERIPHERAL
:
305 /* Bind MUSB device */
306 ret
= device_bind_driver_to_node(parent
,
307 "ti-musb-peripheral",
312 pr_err("musb - not able to bind usb peripheral node\n");
314 case USB_DR_MODE_HOST
:
316 ret
= device_bind_driver_to_node(parent
,
322 pr_err("musb - not able to bind usb host node\n");
331 static const struct udevice_id ti_musb_ids
[] = {
332 { .compatible
= "ti,am33xx-usb" },
336 U_BOOT_DRIVER(ti_musb_wrapper
) = {
337 .name
= "ti-musb-wrapper",
339 .of_match
= ti_musb_ids
,
340 .bind
= ti_musb_wrapper_bind
,
342 #endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
344 #endif /* CONFIG_IS_ENABLED(DM_USB) */