blob: 89dd75b7d057bba0739a922c5af0d31ba75cce44 [file] [log] [blame]
Stephan Gerholdd2519592021-07-08 20:33:50 +02001// SPDX-License-Identifier: GPL-2.0+
2/* Copyright (C) 2019 Stephan Gerhold */
3
Stephan Gerholdd2519592021-07-08 20:33:50 +02004#include <dm.h>
5#include <generic-phy.h>
6#include <dm/device_compat.h>
7#include "musb_uboot.h"
8
9static struct musb_hdrc_config ux500_musb_hdrc_config = {
10 .multipoint = true,
11 .dyn_fifo = true,
12 .num_eps = 16,
13 .ram_bits = 16,
14};
15
16struct ux500_glue {
17 struct musb_host_data mdata;
18 struct device dev;
19 struct phy phy;
20 bool enabled;
21};
22#define to_ux500_glue(d) container_of(d, struct ux500_glue, dev)
23
24static int ux500_musb_enable(struct musb *musb)
25{
26 struct ux500_glue *glue = to_ux500_glue(musb->controller);
27 int ret;
28
29 if (glue->enabled)
30 return 0;
31
32 ret = generic_phy_power_on(&glue->phy);
33 if (ret) {
34 printf("%s: failed to power on USB PHY\n", __func__);
35 return ret;
36 }
37
38 glue->enabled = true;
39 return 0;
40}
41
42static void ux500_musb_disable(struct musb *musb)
43{
44 struct ux500_glue *glue = to_ux500_glue(musb->controller);
45 int ret;
46
47 if (!glue->enabled)
48 return;
49
50 ret = generic_phy_power_off(&glue->phy);
51 if (ret) {
52 printf("%s: failed to power off USB PHY\n", __func__);
53 return;
54 }
55
56 glue->enabled = false;
57}
58
59static int ux500_musb_init(struct musb *musb)
60{
61 struct ux500_glue *glue = to_ux500_glue(musb->controller);
62 int ret;
63
64 ret = generic_phy_init(&glue->phy);
65 if (ret) {
66 printf("%s: failed to init USB PHY\n", __func__);
67 return ret;
68 }
69
70 return 0;
71}
72
73static int ux500_musb_exit(struct musb *musb)
74{
75 struct ux500_glue *glue = to_ux500_glue(musb->controller);
76 int ret;
77
78 ret = generic_phy_exit(&glue->phy);
79 if (ret) {
80 printf("%s: failed to exit USB PHY\n", __func__);
81 return ret;
82 }
83
84 return 0;
85}
86
87static const struct musb_platform_ops ux500_musb_ops = {
88 .init = ux500_musb_init,
89 .exit = ux500_musb_exit,
90 .enable = ux500_musb_enable,
91 .disable = ux500_musb_disable,
92};
93
Stephan Gerholdd2519592021-07-08 20:33:50 +020094static int ux500_musb_probe(struct udevice *dev)
95{
96#ifdef CONFIG_USB_MUSB_HOST
97 struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
98#endif
99 struct ux500_glue *glue = dev_get_priv(dev);
100 struct musb_host_data *host = &glue->mdata;
101 struct musb_hdrc_platform_data pdata;
102 void *base = dev_read_addr_ptr(dev);
103 int ret;
104
105 if (!base)
106 return -EINVAL;
107
108 ret = generic_phy_get_by_name(dev, "usb", &glue->phy);
109 if (ret) {
110 dev_err(dev, "failed to get USB PHY: %d\n", ret);
111 return ret;
112 }
113
114 memset(&pdata, 0, sizeof(pdata));
115 pdata.platform_ops = &ux500_musb_ops;
116 pdata.config = &ux500_musb_hdrc_config;
117
118#ifdef CONFIG_USB_MUSB_HOST
119 priv->desc_before_addr = true;
120 pdata.mode = MUSB_HOST;
121
122 host->host = musb_init_controller(&pdata, &glue->dev, base);
123 if (!host->host)
124 return -EIO;
125
126 return musb_lowlevel_init(host);
127#else
128 pdata.mode = MUSB_PERIPHERAL;
129 host->host = musb_init_controller(&pdata, &glue->dev, base);
130 if (!host->host)
131 return -EIO;
132
133 return usb_add_gadget_udc(&glue->dev, &host->host->g);
134#endif
135}
136
137static int ux500_musb_remove(struct udevice *dev)
138{
139 struct ux500_glue *glue = dev_get_priv(dev);
140 struct musb_host_data *host = &glue->mdata;
141
142 usb_del_gadget_udc(&host->host->g);
143 musb_stop(host->host);
144 free(host->host);
145 host->host = NULL;
146
147 return 0;
148}
149
Marek Vasutd7aac2e2024-06-14 02:51:24 +0200150static int ux500_gadget_handle_interrupts(struct udevice *dev)
151{
152 struct ux500_glue *glue = dev_get_priv(dev);
153
154 glue->mdata.host->isr(0, glue->mdata.host);
155
156 return 0;
157}
158
159static const struct usb_gadget_generic_ops ux500_gadget_ops = {
160 .handle_interrupts = ux500_gadget_handle_interrupts,
161};
162
Stephan Gerholdd2519592021-07-08 20:33:50 +0200163static const struct udevice_id ux500_musb_ids[] = {
164 { .compatible = "stericsson,db8500-musb" },
165 { }
166};
167
168U_BOOT_DRIVER(ux500_musb) = {
169 .name = "ux500-musb",
170#ifdef CONFIG_USB_MUSB_HOST
171 .id = UCLASS_USB,
172#else
173 .id = UCLASS_USB_GADGET_GENERIC,
174#endif
175 .of_match = ux500_musb_ids,
Marek Vasutd7aac2e2024-06-14 02:51:24 +0200176 .ops = &ux500_gadget_ops,
Stephan Gerholdd2519592021-07-08 20:33:50 +0200177 .probe = ux500_musb_probe,
178 .remove = ux500_musb_remove,
179#ifdef CONFIG_USB_MUSB_HOST
180 .ops = &musb_usb_ops,
181#endif
182 .plat_auto = sizeof(struct usb_plat),
183 .priv_auto = sizeof(struct ux500_glue),
184};