]> git.ipfire.org Git - thirdparty/u-boot.git/blame - drivers/usb/musb-new/ti-musb.c
Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
[thirdparty/u-boot.git] / drivers / usb / musb-new / ti-musb.c
CommitLineData
83d290c5 1// SPDX-License-Identifier: GPL-2.0+
28b8d5fd
M
2/*
3 * MISC driver for TI MUSB Glue.
4 *
5 * (C) Copyright 2016
6 * Texas Instruments Incorporated, <www.ti.com>
28b8d5fd 7 */
d678a59d 8#include <common.h>
28b8d5fd
M
9#include <command.h>
10#include <console.h>
11#include <dm.h>
f7ae49fc 12#include <log.h>
336d4615 13#include <malloc.h>
401d1c4f 14#include <asm/global_data.h>
1e94b46f 15#include <linux/printk.h>
28b8d5fd
M
16#include <linux/usb/otg.h>
17#include <dm/device-internal.h>
18#include <dm/lists.h>
19
ae6acf9f
M
20#include <asm/io.h>
21#include <asm/omap_musb.h>
22#include "musb_uboot.h"
23
28b8d5fd
M
24DECLARE_GLOBAL_DATA_PTR;
25
fd09c205 26#if CONFIG_IS_ENABLED(DM_USB)
ae6acf9f
M
27/* USB 2.0 PHY Control */
28#define CM_PHY_PWRDN (1 << 0)
29#define CM_PHY_OTG_PWRDN (1 << 1)
30#define OTGVDET_EN (1 << 19)
31#define OTGSESSENDEN (1 << 20)
32
7d98dbcc 33#define AM335X_USB0_CTRL 0x0
ae6acf9f
M
34#define AM335X_USB1_CTRL 0x8
35
7d98dbcc
JJH
36static void ti_musb_set_phy_power(struct udevice *dev, u8 on)
37{
8a8d24bd 38 struct ti_musb_plat *plat = dev_get_plat(dev);
7d98dbcc 39
caa4daa2 40 if (!plat->ctrl_mod_base)
7d98dbcc
JJH
41 return;
42
43 if (on) {
caa4daa2 44 clrsetbits_le32(plat->ctrl_mod_base,
7d98dbcc
JJH
45 CM_PHY_PWRDN | CM_PHY_OTG_PWRDN,
46 OTGVDET_EN | OTGSESSENDEN);
47 } else {
caa4daa2 48 clrsetbits_le32(plat->ctrl_mod_base, 0,
7d98dbcc
JJH
49 CM_PHY_PWRDN | CM_PHY_OTG_PWRDN);
50 }
51}
52
53#if CONFIG_IS_ENABLED(OF_CONTROL)
ae6acf9f
M
54
55static int ti_musb_get_usb_index(int node)
56{
57 const void *fdt = gd->fdt_blob;
58 int i = 0;
59 char path[64];
60 const char *alias_path;
61 char alias[16];
62
63 fdt_get_path(fdt, node, path, sizeof(path));
64
65 do {
66 snprintf(alias, sizeof(alias), "usb%d", i);
67 alias_path = fdt_get_alias(fdt, alias);
68 if (alias_path == NULL) {
69 debug("USB index not found\n");
70 return -ENOENT;
71 }
72
73 if (!strcmp(path, alias_path))
74 return i;
75
76 i++;
77 } while (alias_path);
78
79 return -ENOENT;
80}
81
d1998a9f 82static int ti_musb_of_to_plat(struct udevice *dev)
ae6acf9f 83{
8a8d24bd 84 struct ti_musb_plat *plat = dev_get_plat(dev);
ae6acf9f 85 const void *fdt = gd->fdt_blob;
e160f7d4 86 int node = dev_of_offset(dev);
ae6acf9f
M
87 int phys;
88 int ctrl_mod;
89 int usb_index;
7d98dbcc 90 struct musb_hdrc_config *musb_config;
ae6acf9f 91
320a1938 92 plat->base = devfdt_get_addr_index_ptr(dev, 1);
ae6acf9f
M
93
94 phys = fdtdec_lookup_phandle(fdt, node, "phys");
95 ctrl_mod = fdtdec_lookup_phandle(fdt, phys, "ti,ctrl_mod");
caa4daa2 96 plat->ctrl_mod_base = (void *)fdtdec_get_addr(fdt, ctrl_mod, "reg");
ae6acf9f
M
97 usb_index = ti_musb_get_usb_index(node);
98 switch (usb_index) {
99 case 1:
caa4daa2 100 plat->ctrl_mod_base += AM335X_USB1_CTRL;
7d98dbcc 101 break;
ae6acf9f 102 case 0:
caa4daa2 103 plat->ctrl_mod_base += AM335X_USB0_CTRL;
7d98dbcc 104 break;
ae6acf9f
M
105 default:
106 break;
107 }
108
7d98dbcc
JJH
109 musb_config = malloc(sizeof(struct musb_hdrc_config));
110 memset(musb_config, 0, sizeof(struct musb_hdrc_config));
111
112 musb_config->multipoint = fdtdec_get_int(fdt, node,
113 "mentor,multipoint", -1);
114 if (musb_config->multipoint < 0) {
9b643e31 115 pr_err("MUSB multipoint DT entry missing\n");
ae6acf9f
M
116 return -ENOENT;
117 }
118
7d98dbcc 119 musb_config->dyn_fifo = 1;
ae6acf9f 120
7d98dbcc
JJH
121 musb_config->num_eps = fdtdec_get_int(fdt, node, "mentor,num-eps",
122 -1);
123 if (musb_config->num_eps < 0) {
9b643e31 124 pr_err("MUSB num-eps DT entry missing\n");
ae6acf9f
M
125 return -ENOENT;
126 }
127
7d98dbcc
JJH
128 musb_config->ram_bits = fdtdec_get_int(fdt, node, "mentor,ram-bits",
129 -1);
130 if (musb_config->ram_bits < 0) {
9b643e31 131 pr_err("MUSB ram-bits DT entry missing\n");
ae6acf9f
M
132 return -ENOENT;
133 }
134
caa4daa2 135 plat->plat.config = musb_config;
ae6acf9f 136
caa4daa2
SG
137 plat->plat.power = fdtdec_get_int(fdt, node, "mentor,power", -1);
138 if (plat->plat.power < 0) {
9b643e31 139 pr_err("MUSB mentor,power DT entry missing\n");
ae6acf9f
M
140 return -ENOENT;
141 }
142
caa4daa2 143 plat->plat.platform_ops = &musb_dsps_ops;
ae6acf9f
M
144
145 return 0;
146}
7d98dbcc 147#endif
ae6acf9f
M
148
149static int ti_musb_host_probe(struct udevice *dev)
150{
151 struct musb_host_data *host = dev_get_priv(dev);
8a8d24bd 152 struct ti_musb_plat *plat = dev_get_plat(dev);
ae6acf9f 153 struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
ae6acf9f
M
154 int ret;
155
156 priv->desc_before_addr = true;
157
caa4daa2 158 host->host = musb_init_controller(&plat->plat,
7d98dbcc 159 NULL,
caa4daa2 160 plat->base);
ae6acf9f
M
161 if (!host->host)
162 return -EIO;
163
7d98dbcc 164 ti_musb_set_phy_power(dev, 1);
ae6acf9f
M
165 ret = musb_lowlevel_init(host);
166
167 return ret;
168}
169
170static int ti_musb_host_remove(struct udevice *dev)
171{
172 struct musb_host_data *host = dev_get_priv(dev);
173
174 musb_stop(host->host);
7d98dbcc 175 ti_musb_set_phy_power(dev, 0);
ae6acf9f
M
176
177 return 0;
178}
179
7d98dbcc 180#if CONFIG_IS_ENABLED(OF_CONTROL)
d1998a9f 181static int ti_musb_host_of_to_plat(struct udevice *dev)
ae6acf9f 182{
8a8d24bd 183 struct ti_musb_plat *plat = dev_get_plat(dev);
ae6acf9f 184 const void *fdt = gd->fdt_blob;
e160f7d4 185 int node = dev_of_offset(dev);
ae6acf9f
M
186 int ret;
187
d1998a9f 188 ret = ti_musb_of_to_plat(dev);
ae6acf9f 189 if (ret) {
caa4daa2 190 pr_err("plat dt parse error\n");
ae6acf9f
M
191 return ret;
192 }
193
caa4daa2 194 plat->plat.mode = MUSB_HOST;
ae6acf9f
M
195
196 return 0;
197}
7d98dbcc 198#endif
ae6acf9f
M
199
200U_BOOT_DRIVER(ti_musb_host) = {
201 .name = "ti-musb-host",
202 .id = UCLASS_USB,
7d98dbcc 203#if CONFIG_IS_ENABLED(OF_CONTROL)
d1998a9f 204 .of_to_plat = ti_musb_host_of_to_plat,
7d98dbcc 205#endif
ae6acf9f
M
206 .probe = ti_musb_host_probe,
207 .remove = ti_musb_host_remove,
208 .ops = &musb_usb_ops,
8a8d24bd 209 .plat_auto = sizeof(struct ti_musb_plat),
41575d8e 210 .priv_auto = sizeof(struct musb_host_data),
ae6acf9f
M
211};
212
7d98dbcc
JJH
213#if CONFIG_IS_ENABLED(DM_USB_GADGET)
214struct ti_musb_peripheral {
215 struct musb *periph;
216};
217
218#if CONFIG_IS_ENABLED(OF_CONTROL)
d1998a9f 219static int ti_musb_peripheral_of_to_plat(struct udevice *dev)
7d98dbcc 220{
8a8d24bd 221 struct ti_musb_plat *plat = dev_get_plat(dev);
7d98dbcc
JJH
222 const void *fdt = gd->fdt_blob;
223 int node = dev_of_offset(dev);
224 int ret;
225
d1998a9f 226 ret = ti_musb_of_to_plat(dev);
7d98dbcc 227 if (ret) {
caa4daa2 228 pr_err("plat dt parse error\n");
7d98dbcc
JJH
229 return ret;
230 }
caa4daa2 231 plat->plat.mode = MUSB_PERIPHERAL;
7d98dbcc
JJH
232
233 return 0;
234}
235#endif
236
237int dm_usb_gadget_handle_interrupts(struct udevice *dev)
238{
239 struct ti_musb_peripheral *priv = dev_get_priv(dev);
240
241 priv->periph->isr(0, priv->periph);
242
243 return 0;
244}
245
246static int ti_musb_peripheral_probe(struct udevice *dev)
247{
248 struct ti_musb_peripheral *priv = dev_get_priv(dev);
8a8d24bd 249 struct ti_musb_plat *plat = dev_get_plat(dev);
7d98dbcc
JJH
250 int ret;
251
caa4daa2 252 priv->periph = musb_init_controller(&plat->plat,
7d98dbcc 253 NULL,
caa4daa2 254 plat->base);
7d98dbcc
JJH
255 if (!priv->periph)
256 return -EIO;
257
258 ti_musb_set_phy_power(dev, 1);
259 musb_gadget_setup(priv->periph);
260 return usb_add_gadget_udc((struct device *)dev, &priv->periph->g);
261}
262
263static int ti_musb_peripheral_remove(struct udevice *dev)
264{
265 struct ti_musb_peripheral *priv = dev_get_priv(dev);
266
267 usb_del_gadget_udc(&priv->periph->g);
268 ti_musb_set_phy_power(dev, 0);
269
270 return 0;
271}
272
273U_BOOT_DRIVER(ti_musb_peripheral) = {
274 .name = "ti-musb-peripheral",
275 .id = UCLASS_USB_GADGET_GENERIC,
276#if CONFIG_IS_ENABLED(OF_CONTROL)
d1998a9f 277 .of_to_plat = ti_musb_peripheral_of_to_plat,
7d98dbcc
JJH
278#endif
279 .probe = ti_musb_peripheral_probe,
280 .remove = ti_musb_peripheral_remove,
281 .ops = &musb_usb_ops,
8a8d24bd 282 .plat_auto = sizeof(struct ti_musb_plat),
41575d8e 283 .priv_auto = sizeof(struct ti_musb_peripheral),
7d98dbcc
JJH
284 .flags = DM_FLAG_PRE_RELOC,
285};
286#endif
287
288#if CONFIG_IS_ENABLED(OF_CONTROL)
28b8d5fd
M
289static int ti_musb_wrapper_bind(struct udevice *parent)
290{
ac28e59a 291 ofnode node;
28b8d5fd
M
292 int ret;
293
f10643cf 294 ofnode_for_each_subnode(node, dev_ofnode(parent)) {
28b8d5fd 295 struct udevice *dev;
ac28e59a 296 const char *name = ofnode_get_name(node);
28b8d5fd
M
297 enum usb_dr_mode dr_mode;
298 struct driver *drv;
299
300 if (strncmp(name, "usb@", 4))
301 continue;
302
303 dr_mode = usb_get_dr_mode(node);
304 switch (dr_mode) {
305 case USB_DR_MODE_PERIPHERAL:
306 /* Bind MUSB device */
7d98dbcc
JJH
307 ret = device_bind_driver_to_node(parent,
308 "ti-musb-peripheral",
309 name,
ac28e59a 310 node,
7d98dbcc
JJH
311 &dev);
312 if (ret)
313 pr_err("musb - not able to bind usb peripheral node\n");
28b8d5fd
M
314 break;
315 case USB_DR_MODE_HOST:
316 /* Bind MUSB host */
7d98dbcc
JJH
317 ret = device_bind_driver_to_node(parent,
318 "ti-musb-host",
319 name,
ac28e59a 320 node,
7d98dbcc
JJH
321 &dev);
322 if (ret)
9b643e31 323 pr_err("musb - not able to bind usb host node\n");
28b8d5fd
M
324 break;
325 default:
326 break;
327 };
328 }
329 return 0;
330}
331
332static const struct udevice_id ti_musb_ids[] = {
333 { .compatible = "ti,am33xx-usb" },
334 { }
335};
336
337U_BOOT_DRIVER(ti_musb_wrapper) = {
338 .name = "ti-musb-wrapper",
339 .id = UCLASS_MISC,
340 .of_match = ti_musb_ids,
341 .bind = ti_musb_wrapper_bind,
342};
7d98dbcc 343#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
28b8d5fd 344
fd09c205 345#endif /* CONFIG_IS_ENABLED(DM_USB) */