hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/usb/musb/jz4740.c
....@@ -10,22 +10,28 @@
1010 #include <linux/errno.h>
1111 #include <linux/kernel.h>
1212 #include <linux/module.h>
13
+#include <linux/of_device.h>
1314 #include <linux/platform_device.h>
15
+#include <linux/usb/role.h>
1416 #include <linux/usb/usb_phy_generic.h>
1517
1618 #include "musb_core.h"
1719
1820 struct jz4740_glue {
19
- struct device *dev;
20
- struct platform_device *musb;
21
+ struct platform_device *pdev;
22
+ struct musb *musb;
2123 struct clk *clk;
24
+ struct usb_role_switch *role_sw;
2225 };
2326
2427 static irqreturn_t jz4740_musb_interrupt(int irq, void *__hci)
2528 {
26
- unsigned long flags;
27
- irqreturn_t retval = IRQ_NONE;
28
- struct musb *musb = __hci;
29
+ unsigned long flags;
30
+ irqreturn_t retval = IRQ_NONE, retval_dma = IRQ_NONE;
31
+ struct musb *musb = __hci;
32
+
33
+ if (IS_ENABLED(CONFIG_USB_INVENTRA_DMA) && musb->dma_controller)
34
+ retval_dma = dma_controller_irq(irq, musb->dma_controller);
2935
3036 spin_lock_irqsave(&musb->lock, flags);
3137
....@@ -39,48 +45,89 @@
3945 * never see them set
4046 */
4147 musb->int_usb &= MUSB_INTR_SUSPEND | MUSB_INTR_RESUME |
42
- MUSB_INTR_RESET | MUSB_INTR_SOF;
48
+ MUSB_INTR_RESET | MUSB_INTR_SOF;
4349
4450 if (musb->int_usb || musb->int_tx || musb->int_rx)
4551 retval = musb_interrupt(musb);
4652
4753 spin_unlock_irqrestore(&musb->lock, flags);
4854
49
- return retval;
55
+ if (retval == IRQ_HANDLED || retval_dma == IRQ_HANDLED)
56
+ return IRQ_HANDLED;
57
+
58
+ return IRQ_NONE;
5059 }
5160
5261 static struct musb_fifo_cfg jz4740_musb_fifo_cfg[] = {
53
-{ .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
54
-{ .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
55
-{ .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
62
+ { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
63
+ { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
64
+ { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 64, },
5665 };
5766
5867 static const struct musb_hdrc_config jz4740_musb_config = {
5968 /* Silicon does not implement USB OTG. */
60
- .multipoint = 0,
69
+ .multipoint = 0,
6170 /* Max EPs scanned, driver will decide which EP can be used. */
62
- .num_eps = 4,
71
+ .num_eps = 4,
6372 /* RAMbits needed to configure EPs from table */
64
- .ram_bits = 9,
65
- .fifo_cfg = jz4740_musb_fifo_cfg,
66
- .fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
73
+ .ram_bits = 9,
74
+ .fifo_cfg = jz4740_musb_fifo_cfg,
75
+ .fifo_cfg_size = ARRAY_SIZE(jz4740_musb_fifo_cfg),
6776 };
6877
69
-static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
70
- .mode = MUSB_PERIPHERAL,
71
- .config = &jz4740_musb_config,
72
-};
78
+static int jz4740_musb_role_switch_set(struct usb_role_switch *sw,
79
+ enum usb_role role)
80
+{
81
+ struct jz4740_glue *glue = usb_role_switch_get_drvdata(sw);
82
+ struct usb_phy *phy = glue->musb->xceiv;
83
+
84
+ switch (role) {
85
+ case USB_ROLE_NONE:
86
+ atomic_notifier_call_chain(&phy->notifier, USB_EVENT_NONE, phy);
87
+ break;
88
+ case USB_ROLE_DEVICE:
89
+ atomic_notifier_call_chain(&phy->notifier, USB_EVENT_VBUS, phy);
90
+ break;
91
+ case USB_ROLE_HOST:
92
+ atomic_notifier_call_chain(&phy->notifier, USB_EVENT_ID, phy);
93
+ break;
94
+ }
95
+
96
+ return 0;
97
+}
7398
7499 static int jz4740_musb_init(struct musb *musb)
75100 {
76
- usb_phy_generic_register();
77
- musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2);
101
+ struct device *dev = musb->controller->parent;
102
+ struct jz4740_glue *glue = dev_get_drvdata(dev);
103
+ struct usb_role_switch_desc role_sw_desc = {
104
+ .set = jz4740_musb_role_switch_set,
105
+ .driver_data = glue,
106
+ .fwnode = dev_fwnode(dev),
107
+ };
108
+ int err;
109
+
110
+ glue->musb = musb;
111
+
112
+ if (dev->of_node)
113
+ musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0);
114
+ else
115
+ musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
78116 if (IS_ERR(musb->xceiv)) {
79
- pr_err("HS UDC: no transceiver configured\n");
80
- return PTR_ERR(musb->xceiv);
117
+ err = PTR_ERR(musb->xceiv);
118
+ if (err != -EPROBE_DEFER)
119
+ dev_err(dev, "No transceiver configured: %d", err);
120
+ return err;
81121 }
82122
83
- /* Silicon does not implement ConfigData register.
123
+ glue->role_sw = usb_role_switch_register(dev, &role_sw_desc);
124
+ if (IS_ERR(glue->role_sw)) {
125
+ dev_err(dev, "Failed to register USB role switch");
126
+ return PTR_ERR(glue->role_sw);
127
+ }
128
+
129
+ /*
130
+ * Silicon does not implement ConfigData register.
84131 * Set dyn_fifo to avoid reading EP config from hardware.
85132 */
86133 musb->dyn_fifo = true;
....@@ -92,79 +139,120 @@
92139
93140 static int jz4740_musb_exit(struct musb *musb)
94141 {
95
- usb_put_phy(musb->xceiv);
142
+ struct jz4740_glue *glue = dev_get_drvdata(musb->controller->parent);
143
+
144
+ usb_role_switch_unregister(glue->role_sw);
96145
97146 return 0;
98147 }
99148
100
-/*
101
- * DMA has not been confirmed to work with CONFIG_USB_INVENTRA_DMA,
102
- * so let's not set up the dma function pointers yet.
103
- */
104149 static const struct musb_platform_ops jz4740_musb_ops = {
105150 .quirks = MUSB_DMA_INVENTRA | MUSB_INDEXED_EP,
106151 .fifo_mode = 2,
107152 .init = jz4740_musb_init,
108153 .exit = jz4740_musb_exit,
154
+#ifdef CONFIG_USB_INVENTRA_DMA
155
+ .dma_init = musbhs_dma_controller_create_noirq,
156
+ .dma_exit = musbhs_dma_controller_destroy,
157
+#endif
158
+};
159
+
160
+static const struct musb_hdrc_platform_data jz4740_musb_pdata = {
161
+ .mode = MUSB_PERIPHERAL,
162
+ .config = &jz4740_musb_config,
163
+ .platform_ops = &jz4740_musb_ops,
164
+};
165
+
166
+static struct musb_fifo_cfg jz4770_musb_fifo_cfg[] = {
167
+ { .hw_ep_num = 1, .style = FIFO_TX, .maxpacket = 512, },
168
+ { .hw_ep_num = 1, .style = FIFO_RX, .maxpacket = 512, },
169
+ { .hw_ep_num = 2, .style = FIFO_TX, .maxpacket = 512, },
170
+ { .hw_ep_num = 2, .style = FIFO_RX, .maxpacket = 512, },
171
+ { .hw_ep_num = 3, .style = FIFO_TX, .maxpacket = 512, },
172
+ { .hw_ep_num = 3, .style = FIFO_RX, .maxpacket = 512, },
173
+ { .hw_ep_num = 4, .style = FIFO_TX, .maxpacket = 512, },
174
+ { .hw_ep_num = 4, .style = FIFO_RX, .maxpacket = 512, },
175
+ { .hw_ep_num = 5, .style = FIFO_TX, .maxpacket = 512, },
176
+ { .hw_ep_num = 5, .style = FIFO_RX, .maxpacket = 512, },
177
+};
178
+
179
+static struct musb_hdrc_config jz4770_musb_config = {
180
+ .multipoint = 1,
181
+ .num_eps = 11,
182
+ .ram_bits = 11,
183
+ .fifo_cfg = jz4770_musb_fifo_cfg,
184
+ .fifo_cfg_size = ARRAY_SIZE(jz4770_musb_fifo_cfg),
185
+};
186
+
187
+static const struct musb_hdrc_platform_data jz4770_musb_pdata = {
188
+ .mode = MUSB_PERIPHERAL, /* TODO: support OTG */
189
+ .config = &jz4770_musb_config,
190
+ .platform_ops = &jz4740_musb_ops,
109191 };
110192
111193 static int jz4740_probe(struct platform_device *pdev)
112194 {
113
- struct musb_hdrc_platform_data *pdata = &jz4740_musb_platform_data;
195
+ struct device *dev = &pdev->dev;
196
+ const struct musb_hdrc_platform_data *pdata;
114197 struct platform_device *musb;
115198 struct jz4740_glue *glue;
116
- struct clk *clk;
199
+ struct clk *clk;
117200 int ret;
118201
119
- glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
202
+ glue = devm_kzalloc(dev, sizeof(*glue), GFP_KERNEL);
120203 if (!glue)
121204 return -ENOMEM;
122205
206
+ pdata = of_device_get_match_data(dev);
207
+ if (!pdata) {
208
+ dev_err(dev, "missing platform data");
209
+ return -EINVAL;
210
+ }
211
+
123212 musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
124213 if (!musb) {
125
- dev_err(&pdev->dev, "failed to allocate musb device\n");
214
+ dev_err(dev, "failed to allocate musb device");
126215 return -ENOMEM;
127216 }
128217
129
- clk = devm_clk_get(&pdev->dev, "udc");
218
+ clk = devm_clk_get(dev, "udc");
130219 if (IS_ERR(clk)) {
131
- dev_err(&pdev->dev, "failed to get clock\n");
220
+ dev_err(dev, "failed to get clock");
132221 ret = PTR_ERR(clk);
133222 goto err_platform_device_put;
134223 }
135224
136225 ret = clk_prepare_enable(clk);
137226 if (ret) {
138
- dev_err(&pdev->dev, "failed to enable clock\n");
227
+ dev_err(dev, "failed to enable clock");
139228 goto err_platform_device_put;
140229 }
141230
142
- musb->dev.parent = &pdev->dev;
231
+ musb->dev.parent = dev;
232
+ musb->dev.dma_mask = &musb->dev.coherent_dma_mask;
233
+ musb->dev.coherent_dma_mask = DMA_BIT_MASK(32);
143234
144
- glue->dev = &pdev->dev;
145
- glue->musb = musb;
235
+ glue->pdev = musb;
146236 glue->clk = clk;
147
-
148
- pdata->platform_ops = &jz4740_musb_ops;
149237
150238 platform_set_drvdata(pdev, glue);
151239
152240 ret = platform_device_add_resources(musb, pdev->resource,
153241 pdev->num_resources);
154242 if (ret) {
155
- dev_err(&pdev->dev, "failed to add resources\n");
243
+ dev_err(dev, "failed to add resources");
156244 goto err_clk_disable;
157245 }
158246
159247 ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
160248 if (ret) {
161
- dev_err(&pdev->dev, "failed to add platform_data\n");
249
+ dev_err(dev, "failed to add platform_data");
162250 goto err_clk_disable;
163251 }
164252
165253 ret = platform_device_add(musb);
166254 if (ret) {
167
- dev_err(&pdev->dev, "failed to register musb device\n");
255
+ dev_err(dev, "failed to register musb device");
168256 goto err_clk_disable;
169257 }
170258
....@@ -179,20 +267,27 @@
179267
180268 static int jz4740_remove(struct platform_device *pdev)
181269 {
182
- struct jz4740_glue *glue = platform_get_drvdata(pdev);
270
+ struct jz4740_glue *glue = platform_get_drvdata(pdev);
183271
184
- platform_device_unregister(glue->musb);
185
- usb_phy_generic_unregister(pdev);
272
+ platform_device_unregister(glue->pdev);
186273 clk_disable_unprepare(glue->clk);
187274
188275 return 0;
189276 }
277
+
278
+static const struct of_device_id jz4740_musb_of_match[] = {
279
+ { .compatible = "ingenic,jz4740-musb", .data = &jz4740_musb_pdata },
280
+ { .compatible = "ingenic,jz4770-musb", .data = &jz4770_musb_pdata },
281
+ { /* sentinel */ },
282
+};
283
+MODULE_DEVICE_TABLE(of, jz4740_musb_of_match);
190284
191285 static struct platform_driver jz4740_driver = {
192286 .probe = jz4740_probe,
193287 .remove = jz4740_remove,
194288 .driver = {
195289 .name = "musb-jz4740",
290
+ .of_match_table = jz4740_musb_of_match,
196291 },
197292 };
198293