blob: ed5e5194d8c917861f86b82bc69571df55a87122 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Mugunthan V N5b5479c2016-11-17 14:38:08 +05302/*
3 * MISC driver for TI MUSB Glue.
4 *
5 * (C) Copyright 2016
6 * Texas Instruments Incorporated, <www.ti.com>
Mugunthan V N5b5479c2016-11-17 14:38:08 +05307 */
8#include <common.h>
9#include <command.h>
10#include <console.h>
11#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060012#include <log.h>
Simon Glass9bc15642020-02-03 07:36:16 -070013#include <malloc.h>
Simon Glass3ba929a2020-10-30 21:38:53 -060014#include <asm/global_data.h>
Simon Glassbdd5f812023-09-14 18:21:46 -060015#include <linux/printk.h>
Mugunthan V N5b5479c2016-11-17 14:38:08 +053016#include <linux/usb/otg.h>
17#include <dm/device-internal.h>
18#include <dm/lists.h>
19
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053020#include <asm/io.h>
21#include <asm/omap_musb.h>
22#include "musb_uboot.h"
23
Mugunthan V N5b5479c2016-11-17 14:38:08 +053024DECLARE_GLOBAL_DATA_PTR;
25
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +010026#if CONFIG_IS_ENABLED(DM_USB)
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053027/* 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
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +010033#define AM335X_USB0_CTRL 0x0
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053034#define AM335X_USB1_CTRL 0x8
35
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +010036static void ti_musb_set_phy_power(struct udevice *dev, u8 on)
37{
Simon Glassb75b15b2020-12-03 16:55:23 -070038 struct ti_musb_plat *plat = dev_get_plat(dev);
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +010039
Simon Glass71fa5b42020-12-03 16:55:18 -070040 if (!plat->ctrl_mod_base)
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +010041 return;
42
43 if (on) {
Simon Glass71fa5b42020-12-03 16:55:18 -070044 clrsetbits_le32(plat->ctrl_mod_base,
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +010045 CM_PHY_PWRDN | CM_PHY_OTG_PWRDN,
46 OTGVDET_EN | OTGSESSENDEN);
47 } else {
Simon Glass71fa5b42020-12-03 16:55:18 -070048 clrsetbits_le32(plat->ctrl_mod_base, 0,
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +010049 CM_PHY_PWRDN | CM_PHY_OTG_PWRDN);
50 }
51}
52
53#if CONFIG_IS_ENABLED(OF_CONTROL)
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053054
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
Simon Glassaad29ae2020-12-03 16:55:21 -070082static int ti_musb_of_to_plat(struct udevice *dev)
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053083{
Simon Glassb75b15b2020-12-03 16:55:23 -070084 struct ti_musb_plat *plat = dev_get_plat(dev);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053085 const void *fdt = gd->fdt_blob;
Simon Glassdd79d6e2017-01-17 16:52:55 -070086 int node = dev_of_offset(dev);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053087 int phys;
88 int ctrl_mod;
89 int usb_index;
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +010090 struct musb_hdrc_config *musb_config;
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053091
Johan Jonkerb52189e2023-03-13 01:32:31 +010092 plat->base = devfdt_get_addr_index_ptr(dev, 1);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053093
94 phys = fdtdec_lookup_phandle(fdt, node, "phys");
95 ctrl_mod = fdtdec_lookup_phandle(fdt, phys, "ti,ctrl_mod");
Simon Glass71fa5b42020-12-03 16:55:18 -070096 plat->ctrl_mod_base = (void *)fdtdec_get_addr(fdt, ctrl_mod, "reg");
Mugunthan V N2d6f8c02016-11-17 14:38:11 +053097 usb_index = ti_musb_get_usb_index(node);
98 switch (usb_index) {
99 case 1:
Simon Glass71fa5b42020-12-03 16:55:18 -0700100 plat->ctrl_mod_base += AM335X_USB1_CTRL;
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100101 break;
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530102 case 0:
Simon Glass71fa5b42020-12-03 16:55:18 -0700103 plat->ctrl_mod_base += AM335X_USB0_CTRL;
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100104 break;
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530105 default:
106 break;
107 }
108
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100109 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) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900115 pr_err("MUSB multipoint DT entry missing\n");
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530116 return -ENOENT;
117 }
118
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100119 musb_config->dyn_fifo = 1;
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530120
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100121 musb_config->num_eps = fdtdec_get_int(fdt, node, "mentor,num-eps",
122 -1);
123 if (musb_config->num_eps < 0) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900124 pr_err("MUSB num-eps DT entry missing\n");
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530125 return -ENOENT;
126 }
127
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100128 musb_config->ram_bits = fdtdec_get_int(fdt, node, "mentor,ram-bits",
129 -1);
130 if (musb_config->ram_bits < 0) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900131 pr_err("MUSB ram-bits DT entry missing\n");
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530132 return -ENOENT;
133 }
134
Simon Glass71fa5b42020-12-03 16:55:18 -0700135 plat->plat.config = musb_config;
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530136
Simon Glass71fa5b42020-12-03 16:55:18 -0700137 plat->plat.power = fdtdec_get_int(fdt, node, "mentor,power", -1);
138 if (plat->plat.power < 0) {
Masahiro Yamada81e10422017-09-16 14:10:41 +0900139 pr_err("MUSB mentor,power DT entry missing\n");
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530140 return -ENOENT;
141 }
142
Simon Glass71fa5b42020-12-03 16:55:18 -0700143 plat->plat.platform_ops = &musb_dsps_ops;
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530144
145 return 0;
146}
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100147#endif
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530148
149static int ti_musb_host_probe(struct udevice *dev)
150{
151 struct musb_host_data *host = dev_get_priv(dev);
Simon Glassb75b15b2020-12-03 16:55:23 -0700152 struct ti_musb_plat *plat = dev_get_plat(dev);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530153 struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530154 int ret;
155
156 priv->desc_before_addr = true;
157
Simon Glass71fa5b42020-12-03 16:55:18 -0700158 host->host = musb_init_controller(&plat->plat,
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100159 NULL,
Simon Glass71fa5b42020-12-03 16:55:18 -0700160 plat->base);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530161 if (!host->host)
162 return -EIO;
163
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100164 ti_musb_set_phy_power(dev, 1);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530165 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);
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100175 ti_musb_set_phy_power(dev, 0);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530176
177 return 0;
178}
179
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100180#if CONFIG_IS_ENABLED(OF_CONTROL)
Simon Glassaad29ae2020-12-03 16:55:21 -0700181static int ti_musb_host_of_to_plat(struct udevice *dev)
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530182{
Simon Glassb75b15b2020-12-03 16:55:23 -0700183 struct ti_musb_plat *plat = dev_get_plat(dev);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530184 const void *fdt = gd->fdt_blob;
Simon Glassdd79d6e2017-01-17 16:52:55 -0700185 int node = dev_of_offset(dev);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530186 int ret;
187
Simon Glassaad29ae2020-12-03 16:55:21 -0700188 ret = ti_musb_of_to_plat(dev);
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530189 if (ret) {
Simon Glass71fa5b42020-12-03 16:55:18 -0700190 pr_err("plat dt parse error\n");
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530191 return ret;
192 }
193
Simon Glass71fa5b42020-12-03 16:55:18 -0700194 plat->plat.mode = MUSB_HOST;
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530195
196 return 0;
197}
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100198#endif
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530199
200U_BOOT_DRIVER(ti_musb_host) = {
201 .name = "ti-musb-host",
202 .id = UCLASS_USB,
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100203#if CONFIG_IS_ENABLED(OF_CONTROL)
Simon Glassaad29ae2020-12-03 16:55:21 -0700204 .of_to_plat = ti_musb_host_of_to_plat,
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100205#endif
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530206 .probe = ti_musb_host_probe,
207 .remove = ti_musb_host_remove,
208 .ops = &musb_usb_ops,
Simon Glassb75b15b2020-12-03 16:55:23 -0700209 .plat_auto = sizeof(struct ti_musb_plat),
Simon Glass8a2b47f2020-12-03 16:55:17 -0700210 .priv_auto = sizeof(struct musb_host_data),
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530211};
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100212
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)
Simon Glassaad29ae2020-12-03 16:55:21 -0700219static int ti_musb_peripheral_of_to_plat(struct udevice *dev)
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100220{
Simon Glassb75b15b2020-12-03 16:55:23 -0700221 struct ti_musb_plat *plat = dev_get_plat(dev);
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100222 const void *fdt = gd->fdt_blob;
223 int node = dev_of_offset(dev);
224 int ret;
225
Simon Glassaad29ae2020-12-03 16:55:21 -0700226 ret = ti_musb_of_to_plat(dev);
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100227 if (ret) {
Simon Glass71fa5b42020-12-03 16:55:18 -0700228 pr_err("plat dt parse error\n");
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100229 return ret;
230 }
Simon Glass71fa5b42020-12-03 16:55:18 -0700231 plat->plat.mode = MUSB_PERIPHERAL;
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100232
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);
Simon Glassb75b15b2020-12-03 16:55:23 -0700249 struct ti_musb_plat *plat = dev_get_plat(dev);
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100250 int ret;
251
Simon Glass71fa5b42020-12-03 16:55:18 -0700252 priv->periph = musb_init_controller(&plat->plat,
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100253 NULL,
Simon Glass71fa5b42020-12-03 16:55:18 -0700254 plat->base);
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100255 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)
Simon Glassaad29ae2020-12-03 16:55:21 -0700277 .of_to_plat = ti_musb_peripheral_of_to_plat,
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100278#endif
279 .probe = ti_musb_peripheral_probe,
280 .remove = ti_musb_peripheral_remove,
281 .ops = &musb_usb_ops,
Simon Glassb75b15b2020-12-03 16:55:23 -0700282 .plat_auto = sizeof(struct ti_musb_plat),
Simon Glass8a2b47f2020-12-03 16:55:17 -0700283 .priv_auto = sizeof(struct ti_musb_peripheral),
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100284 .flags = DM_FLAG_PRE_RELOC,
285};
286#endif
Mugunthan V N2d6f8c02016-11-17 14:38:11 +0530287
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100288#if CONFIG_IS_ENABLED(OF_CONTROL)
Mugunthan V N5b5479c2016-11-17 14:38:08 +0530289static int ti_musb_wrapper_bind(struct udevice *parent)
290{
Kever Yang1b807052020-03-04 08:59:50 +0800291 ofnode node;
Mugunthan V N5b5479c2016-11-17 14:38:08 +0530292 int ret;
293
Simon Glassa7ece582020-12-19 10:40:14 -0700294 ofnode_for_each_subnode(node, dev_ofnode(parent)) {
Mugunthan V N5b5479c2016-11-17 14:38:08 +0530295 struct udevice *dev;
Kever Yang1b807052020-03-04 08:59:50 +0800296 const char *name = ofnode_get_name(node);
Mugunthan V N5b5479c2016-11-17 14:38:08 +0530297 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 */
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100307 ret = device_bind_driver_to_node(parent,
308 "ti-musb-peripheral",
309 name,
Kever Yang1b807052020-03-04 08:59:50 +0800310 node,
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100311 &dev);
312 if (ret)
313 pr_err("musb - not able to bind usb peripheral node\n");
Mugunthan V N5b5479c2016-11-17 14:38:08 +0530314 break;
315 case USB_DR_MODE_HOST:
316 /* Bind MUSB host */
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100317 ret = device_bind_driver_to_node(parent,
318 "ti-musb-host",
319 name,
Kever Yang1b807052020-03-04 08:59:50 +0800320 node,
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100321 &dev);
322 if (ret)
Masahiro Yamada81e10422017-09-16 14:10:41 +0900323 pr_err("musb - not able to bind usb host node\n");
Mugunthan V N5b5479c2016-11-17 14:38:08 +0530324 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};
Jean-Jacques Hiblot57118f62018-12-04 11:30:57 +0100343#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
Mugunthan V N5b5479c2016-11-17 14:38:08 +0530344
Sven Schwermer8a3cb9f12018-11-21 08:43:56 +0100345#endif /* CONFIG_IS_ENABLED(DM_USB) */