usb: gadget: f_hid: added GET_IDLE and SET_IDLE handlers
[linux-2.6-block.git] / drivers / usb / musb / omap2430.c
CommitLineData
5fd54ace 1// SPDX-License-Identifier: GPL-2.0
550a7375
FB
2/*
3 * Copyright (C) 2005-2007 by Texas Instruments
4 * Some code has been taken from tusb6010.c
5 * Copyrights for that are attributable to:
6 * Copyright (C) 2006 Nokia Corporation
550a7375
FB
7 * Tony Lindgren <tony@atomide.com>
8 *
9 * This file is part of the Inventra Controller Driver for Linux.
550a7375
FB
10 */
11#include <linux/module.h>
12#include <linux/kernel.h>
13#include <linux/sched.h>
550a7375
FB
14#include <linux/init.h>
15#include <linux/list.h>
550a7375 16#include <linux/io.h>
00a0b1d5 17#include <linux/of.h>
dc09886b
FB
18#include <linux/platform_device.h>
19#include <linux/dma-mapping.h>
207b0e1f
HH
20#include <linux/pm_runtime.h>
21#include <linux/err.h>
12a19b5f 22#include <linux/delay.h>
8055555f 23#include <linux/usb/musb.h>
14da699b 24#include <linux/phy/omap_control_phy.h>
8934d3e4 25#include <linux/of_platform.h>
550a7375 26
550a7375
FB
27#include "musb_core.h"
28#include "omap2430.h"
29
a3cee12a
FB
30struct omap2430_glue {
31 struct device *dev;
32 struct platform_device *musb;
8055555f 33 enum musb_vbus_id_status status;
1e5acb8d 34 struct work_struct omap_musb_mailbox_work;
ca784be3 35 struct device *control_otghs;
62d472d8
TL
36 unsigned int is_runtime_suspended:1;
37 unsigned int needs_resume:1;
a3cee12a 38};
c20aebb9 39#define glue_to_musb(g) platform_get_drvdata(g->musb)
a3cee12a 40
4b58ed11 41static struct omap2430_glue *_glue;
c9721438 42
c20aebb9
FB
43static inline void omap2430_low_level_exit(struct musb *musb)
44{
45 u32 l;
46
47 /* in any role */
48 l = musb_readl(musb->mregs, OTG_FORCESTDBY);
49 l |= ENABLEFORCE; /* enable MSTANDBY */
50 musb_writel(musb->mregs, OTG_FORCESTDBY, l);
c20aebb9
FB
51}
52
53static inline void omap2430_low_level_init(struct musb *musb)
54{
55 u32 l;
56
c20aebb9
FB
57 l = musb_readl(musb->mregs, OTG_FORCESTDBY);
58 l &= ~ENABLEFORCE; /* disable MSTANDBY */
59 musb_writel(musb->mregs, OTG_FORCESTDBY, l);
60}
61
12b7db2b 62static int omap2430_musb_mailbox(enum musb_vbus_id_status status)
594632ef 63{
c9721438 64 struct omap2430_glue *glue = _glue;
712d8efa 65
f8c4b0e7
AK
66 if (!glue) {
67 pr_err("%s: musb core is not yet initialized\n", __func__);
12b7db2b 68 return -EPROBE_DEFER;
f8c4b0e7
AK
69 }
70 glue->status = status;
71
72 if (!glue_to_musb(glue)) {
80ab72e1 73 pr_err("%s: musb core is not yet ready\n", __func__);
12b7db2b 74 return -EPROBE_DEFER;
c9721438 75 }
712d8efa 76
c9721438 77 schedule_work(&glue->omap_musb_mailbox_work);
12b7db2b
TL
78
79 return 0;
712d8efa
VP
80}
81
98827105
TL
82/*
83 * HDRC controls CPEN, but beware current surges during device connect.
84 * They can trigger transient overcurrent conditions that must be ignored.
85 *
86 * Note that we're skipping A_WAIT_VFALL -> A_IDLE and jumping right to B_IDLE
87 * as set by musb_set_peripheral().
88 */
c9721438 89static void omap_musb_set_mailbox(struct omap2430_glue *glue)
712d8efa 90{
1e5acb8d 91 struct musb *musb = glue_to_musb(glue);
98827105 92 int error;
594632ef 93
ae909fe4 94 pm_runtime_get_sync(musb->controller);
98827105
TL
95
96 dev_dbg(musb->controller, "VBUS %s, devctl %02x\n",
97 usb_otg_state_string(musb->xceiv->otg->state),
98 musb_readb(musb->mregs, MUSB_DEVCTL));
99
c9721438 100 switch (glue->status) {
8055555f 101 case MUSB_ID_GROUND:
ae909fe4 102 dev_dbg(musb->controller, "ID GND\n");
15f1122f 103 switch (musb->xceiv->otg->state) {
98827105
TL
104 case OTG_STATE_A_IDLE:
105 error = musb_set_host(musb);
106 if (error)
107 break;
108 musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
df561f66 109 fallthrough;
15f1122f
TL
110 case OTG_STATE_A_WAIT_VRISE:
111 case OTG_STATE_A_WAIT_BCON:
112 case OTG_STATE_A_HOST:
15f1122f
TL
113 /*
114 * On multiple ID ground interrupts just keep enabling
115 * VBUS. At least cpcap VBUS shuts down otherwise.
116 */
98827105 117 otg_set_vbus(musb->xceiv->otg, 1);
15f1122f
TL
118 break;
119 default:
120 musb->xceiv->otg->state = OTG_STATE_A_IDLE;
121 musb->xceiv->last_event = USB_EVENT_ID;
122 if (musb->gadget_driver) {
123 omap_control_usb_set_mode(glue->control_otghs,
124 USB_MODE_HOST);
98827105 125 otg_set_vbus(musb->xceiv->otg, 1);
15f1122f
TL
126 }
127 break;
594632ef
HH
128 }
129 break;
130
8055555f 131 case MUSB_VBUS_VALID:
ae909fe4 132 dev_dbg(musb->controller, "VBUS Connect\n");
594632ef 133
e47d9254 134 musb->xceiv->otg->state = OTG_STATE_B_IDLE;
c9721438 135 musb->xceiv->last_event = USB_EVENT_VBUS;
ca784be3 136 omap_control_usb_set_mode(glue->control_otghs, USB_MODE_DEVICE);
594632ef
HH
137 break;
138
8055555f
TL
139 case MUSB_ID_FLOAT:
140 case MUSB_VBUS_OFF:
ae909fe4 141 dev_dbg(musb->controller, "VBUS Disconnect\n");
594632ef 142
c9721438 143 musb->xceiv->last_event = USB_EVENT_NONE;
98827105
TL
144 musb_set_peripheral(musb);
145 otg_set_vbus(musb->xceiv->otg, 0);
ca784be3
KVA
146 omap_control_usb_set_mode(glue->control_otghs,
147 USB_MODE_DISCONNECT);
594632ef
HH
148 break;
149 default:
ae909fe4 150 dev_dbg(musb->controller, "ID float\n");
594632ef 151 }
ae909fe4
TL
152 pm_runtime_mark_last_busy(musb->controller);
153 pm_runtime_put_autosuspend(musb->controller);
6fa7178c
PR
154 atomic_notifier_call_chain(&musb->xceiv->notifier,
155 musb->xceiv->last_event, NULL);
594632ef
HH
156}
157
c9721438
KVA
158
159static void omap_musb_mailbox_work(struct work_struct *mailbox_work)
160{
161 struct omap2430_glue *glue = container_of(mailbox_work,
162 struct omap2430_glue, omap_musb_mailbox_work);
8b2bc2c9 163
c9721438
KVA
164 omap_musb_set_mailbox(glue);
165}
166
baef653a
PDS
167static irqreturn_t omap2430_musb_interrupt(int irq, void *__hci)
168{
169 unsigned long flags;
170 irqreturn_t retval = IRQ_NONE;
171 struct musb *musb = __hci;
172
173 spin_lock_irqsave(&musb->lock, flags);
174
175 musb->int_usb = musb_readb(musb->mregs, MUSB_INTRUSB);
176 musb->int_tx = musb_readw(musb->mregs, MUSB_INTRTX);
177 musb->int_rx = musb_readw(musb->mregs, MUSB_INTRRX);
178
179 if (musb->int_usb || musb->int_tx || musb->int_rx)
180 retval = musb_interrupt(musb);
181
182 spin_unlock_irqrestore(&musb->lock, flags);
183
184 return retval;
185}
186
743411b3 187static int omap2430_musb_init(struct musb *musb)
550a7375 188{
ad579699
S
189 u32 l;
190 int status = 0;
ea65df57 191 struct device *dev = musb->controller;
c1a7d67c 192 struct musb_hdrc_platform_data *plat = dev_get_platdata(dev);
ea65df57 193 struct omap_musb_board_data *data = plat->board_data;
550a7375 194
84e250ff
DB
195 /* We require some kind of external transceiver, hooked
196 * up through ULPI. TWL4030-family PMICs include one,
197 * which needs a driver, drivers aren't always needed.
198 */
5ee1787e
JH
199 musb->phy = devm_phy_get(dev->parent, "usb2-phy");
200
201 /* We can't totally remove musb->xceiv as of now because
202 * musb core uses xceiv.state and xceiv.otg. Once we have
203 * a separate state machine to handle otg, these can be moved
204 * out of xceiv and then we can start using the generic PHY
205 * framework
206 */
207 musb->xceiv = devm_usb_get_phy_by_phandle(dev->parent, "usb-phy", 0);
b16604f2 208
a90199bb
FB
209 if (IS_ERR(musb->xceiv)) {
210 status = PTR_ERR(musb->xceiv);
211
212 if (status == -ENXIO)
213 return status;
214
dc66ba8d 215 dev_dbg(dev, "HS USB OTG: no transceiver configured\n");
25736e0c 216 return -EPROBE_DEFER;
84e250ff
DB
217 }
218
3e3101d5 219 if (IS_ERR(musb->phy)) {
71127a79 220 dev_err(dev, "HS USB OTG: no PHY configured\n");
3e3101d5
KVA
221 return PTR_ERR(musb->phy);
222 }
baef653a 223 musb->isr = omap2430_musb_interrupt;
a83e17d0 224 phy_init(musb->phy);
d8e5f0ec 225 phy_power_on(musb->phy);
baef653a 226
8573e6a6 227 l = musb_readl(musb->mregs, OTG_INTERFSEL);
de2e1b0c
MM
228
229 if (data->interface_type == MUSB_INTERFACE_UTMI) {
230 /* OMAP4 uses Internal PHY GS70 which uses UTMI interface */
231 l &= ~ULPI_12PIN; /* Disable ULPI */
232 l |= UTMI_8BIT; /* Enable UTMI */
233 } else {
234 l |= ULPI_12PIN;
235 }
236
8573e6a6 237 musb_writel(musb->mregs, OTG_INTERFSEL, l);
550a7375 238
71127a79 239 dev_dbg(dev, "HS USB OTG: revision 0x%x, sysconfig 0x%02x, "
550a7375 240 "sysstatus 0x%x, intrfsel 0x%x, simenable 0x%x\n",
8573e6a6
FB
241 musb_readl(musb->mregs, OTG_REVISION),
242 musb_readl(musb->mregs, OTG_SYSCONFIG),
243 musb_readl(musb->mregs, OTG_SYSSTATUS),
244 musb_readl(musb->mregs, OTG_INTERFSEL),
245 musb_readl(musb->mregs, OTG_SIMENABLE));
550a7375 246
550a7375
FB
247 return 0;
248}
249
002eda13
HH
250static void omap2430_musb_enable(struct musb *musb)
251{
002eda13 252 struct device *dev = musb->controller;
c9721438 253 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
a83e17d0 254
8b359cbc
TL
255 if (glue->status == MUSB_UNKNOWN)
256 glue->status = MUSB_VBUS_OFF;
257 omap_musb_set_mailbox(glue);
002eda13
HH
258}
259
260static void omap2430_musb_disable(struct musb *musb)
261{
c9721438
KVA
262 struct device *dev = musb->controller;
263 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
264
8055555f 265 if (glue->status != MUSB_UNKNOWN)
ca784be3
KVA
266 omap_control_usb_set_mode(glue->control_otghs,
267 USB_MODE_DISCONNECT);
550a7375
FB
268}
269
743411b3 270static int omap2430_musb_exit(struct musb *musb)
550a7375 271{
a83e17d0
TL
272 struct device *dev = musb->controller;
273 struct omap2430_glue *glue = dev_get_drvdata(dev->parent);
550a7375 274
c20aebb9 275 omap2430_low_level_exit(musb);
d8e5f0ec 276 phy_power_off(musb->phy);
3e3101d5 277 phy_exit(musb->phy);
a83e17d0
TL
278 musb->phy = NULL;
279 cancel_work_sync(&glue->omap_musb_mailbox_work);
c20aebb9 280
550a7375
FB
281 return 0;
282}
743411b3 283
f7ec9437 284static const struct musb_platform_ops omap2430_ops = {
f8e9f34f 285 .quirks = MUSB_DMA_INVENTRA,
7f6283ed
TL
286#ifdef CONFIG_USB_INVENTRA_DMA
287 .dma_init = musbhs_dma_controller_create,
288 .dma_exit = musbhs_dma_controller_destroy,
289#endif
743411b3
FB
290 .init = omap2430_musb_init,
291 .exit = omap2430_musb_exit,
292
002eda13
HH
293 .enable = omap2430_musb_enable,
294 .disable = omap2430_musb_disable,
8055555f
TL
295
296 .phy_callback = omap2430_musb_mailbox,
743411b3 297};
dc09886b
FB
298
299static u64 omap2430_dmamask = DMA_BIT_MASK(32);
300
41ac7b3a 301static int omap2430_probe(struct platform_device *pdev)
dc09886b 302{
c1f01be4 303 struct resource musb_resources[3];
c1a7d67c 304 struct musb_hdrc_platform_data *pdata = dev_get_platdata(&pdev->dev);
00a0b1d5 305 struct omap_musb_board_data *data;
dc09886b 306 struct platform_device *musb;
a3cee12a 307 struct omap2430_glue *glue;
00a0b1d5
KVA
308 struct device_node *np = pdev->dev.of_node;
309 struct musb_hdrc_config *config;
5ee1787e
JH
310 struct device_node *control_node;
311 struct platform_device *control_pdev;
606bf4d5 312 int ret = -ENOMEM, val;
dc09886b 313
5ee1787e
JH
314 if (!np)
315 return -ENODEV;
316
b1183c24 317 glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
af1bdfc9 318 if (!glue)
a3cee12a 319 goto err0;
a3cee12a 320
2f771164 321 musb = platform_device_alloc("musb-hdrc", PLATFORM_DEVID_AUTO);
dc09886b
FB
322 if (!musb) {
323 dev_err(&pdev->dev, "failed to allocate musb device\n");
2f771164 324 goto err0;
dc09886b
FB
325 }
326
327 musb->dev.parent = &pdev->dev;
328 musb->dev.dma_mask = &omap2430_dmamask;
329 musb->dev.coherent_dma_mask = omap2430_dmamask;
330
a3cee12a
FB
331 glue->dev = &pdev->dev;
332 glue->musb = musb;
8055555f 333 glue->status = MUSB_UNKNOWN;
8934d3e4 334 glue->control_otghs = ERR_PTR(-ENODEV);
a3cee12a 335
5ee1787e
JH
336 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
337 if (!pdata)
338 goto err2;
339
340 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
341 if (!data)
342 goto err2;
343
344 config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL);
345 if (!config)
346 goto err2;
347
348 of_property_read_u32(np, "mode", (u32 *)&pdata->mode);
349 of_property_read_u32(np, "interface-type",
350 (u32 *)&data->interface_type);
351 of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps);
352 of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits);
353 of_property_read_u32(np, "power", (u32 *)&pdata->power);
354
355 ret = of_property_read_u32(np, "multipoint", &val);
356 if (!ret && val)
357 config->multipoint = true;
358
359 pdata->board_data = data;
360 pdata->config = config;
361
362 control_node = of_parse_phandle(np, "ctrl-module", 0);
363 if (control_node) {
364 control_pdev = of_find_device_by_node(control_node);
365 if (!control_pdev) {
366 dev_err(&pdev->dev, "Failed to get control device\n");
367 ret = -EINVAL;
2f771164 368 goto err2;
ca784be3 369 }
5ee1787e 370 glue->control_otghs = &control_pdev->dev;
ca784be3 371 }
5ee1787e 372
f7ec9437
FB
373 pdata->platform_ops = &omap2430_ops;
374
a3cee12a 375 platform_set_drvdata(pdev, glue);
dc09886b 376
c9721438
KVA
377 /*
378 * REVISIT if we ever have two instances of the wrapper, we will be
379 * in big trouble
380 */
381 _glue = glue;
382
1e5acb8d
KVA
383 INIT_WORK(&glue->omap_musb_mailbox_work, omap_musb_mailbox_work);
384
3a0ddc71 385 memset(musb_resources, 0x00, sizeof(*musb_resources) *
09fc7d22
FB
386 ARRAY_SIZE(musb_resources));
387
388 musb_resources[0].name = pdev->resource[0].name;
389 musb_resources[0].start = pdev->resource[0].start;
390 musb_resources[0].end = pdev->resource[0].end;
391 musb_resources[0].flags = pdev->resource[0].flags;
392
393 musb_resources[1].name = pdev->resource[1].name;
394 musb_resources[1].start = pdev->resource[1].start;
395 musb_resources[1].end = pdev->resource[1].end;
396 musb_resources[1].flags = pdev->resource[1].flags;
397
c1f01be4
KVA
398 musb_resources[2].name = pdev->resource[2].name;
399 musb_resources[2].start = pdev->resource[2].start;
400 musb_resources[2].end = pdev->resource[2].end;
401 musb_resources[2].flags = pdev->resource[2].flags;
402
09fc7d22
FB
403 ret = platform_device_add_resources(musb, musb_resources,
404 ARRAY_SIZE(musb_resources));
dc09886b
FB
405 if (ret) {
406 dev_err(&pdev->dev, "failed to add resources\n");
65b3d52d 407 goto err2;
dc09886b
FB
408 }
409
410 ret = platform_device_add_data(musb, pdata, sizeof(*pdata));
411 if (ret) {
412 dev_err(&pdev->dev, "failed to add platform_data\n");
65b3d52d 413 goto err2;
dc09886b
FB
414 }
415
87326e85 416 pm_runtime_enable(glue->dev);
3006dc8c 417
dc09886b
FB
418 ret = platform_device_add(musb);
419 if (ret) {
420 dev_err(&pdev->dev, "failed to register musb device\n");
536d599d 421 goto err3;
dc09886b
FB
422 }
423
207b0e1f 424 return 0;
03491761 425
536d599d
TL
426err3:
427 pm_runtime_disable(glue->dev);
428
65b3d52d 429err2:
b1183c24 430 platform_device_put(musb);
a3cee12a 431
dc09886b
FB
432err0:
433 return ret;
434}
435
fb4e98ab 436static int omap2430_remove(struct platform_device *pdev)
dc09886b 437{
21f77bee 438 struct omap2430_glue *glue = platform_get_drvdata(pdev);
dc09886b 439
f039df58 440 platform_device_unregister(glue->musb);
03e43528 441 pm_runtime_disable(glue->dev);
dc09886b
FB
442
443 return 0;
444}
445
c20aebb9 446#ifdef CONFIG_PM
c20aebb9 447
7acc6197 448static int omap2430_runtime_suspend(struct device *dev)
c20aebb9
FB
449{
450 struct omap2430_glue *glue = dev_get_drvdata(dev);
451 struct musb *musb = glue_to_musb(glue);
452
a83e17d0
TL
453 if (!musb)
454 return 0;
e25bec16 455
a83e17d0
TL
456 musb->context.otg_interfsel = musb_readl(musb->mregs,
457 OTG_INTERFSEL);
458
459 omap2430_low_level_exit(musb);
c20aebb9 460
10ac7e77
TL
461 phy_power_off(musb->phy);
462 phy_exit(musb->phy);
463
62d472d8
TL
464 glue->is_runtime_suspended = 1;
465
c20aebb9
FB
466 return 0;
467}
468
7acc6197 469static int omap2430_runtime_resume(struct device *dev)
c20aebb9
FB
470{
471 struct omap2430_glue *glue = dev_get_drvdata(dev);
472 struct musb *musb = glue_to_musb(glue);
c20aebb9 473
8f2279d5 474 if (!musb)
a83e17d0 475 return 0;
8f2279d5 476
10ac7e77
TL
477 phy_init(musb->phy);
478 phy_power_on(musb->phy);
479
8f2279d5
TL
480 omap2430_low_level_init(musb);
481 musb_writel(musb->mregs, OTG_INTERFSEL,
482 musb->context.otg_interfsel);
c20aebb9 483
ce3ab650
TL
484 /* Wait for musb to get oriented. Otherwise we can get babble */
485 usleep_range(200000, 250000);
486
62d472d8
TL
487 glue->is_runtime_suspended = 0;
488
c20aebb9
FB
489 return 0;
490}
491
62d472d8
TL
492static int omap2430_suspend(struct device *dev)
493{
494 struct omap2430_glue *glue = dev_get_drvdata(dev);
495
496 if (glue->is_runtime_suspended)
497 return 0;
498
499 glue->needs_resume = 1;
500
501 return omap2430_runtime_suspend(dev);
502}
503
504static int omap2430_resume(struct device *dev)
505{
506 struct omap2430_glue *glue = dev_get_drvdata(dev);
507
508 if (!glue->needs_resume)
509 return 0;
510
511 glue->needs_resume = 0;
512
513 return omap2430_runtime_resume(dev);
514}
515
c0927fea 516static const struct dev_pm_ops omap2430_pm_ops = {
7acc6197
HH
517 .runtime_suspend = omap2430_runtime_suspend,
518 .runtime_resume = omap2430_runtime_resume,
62d472d8
TL
519 .suspend = omap2430_suspend,
520 .resume = omap2430_resume,
c20aebb9
FB
521};
522
523#define DEV_PM_OPS (&omap2430_pm_ops)
524#else
525#define DEV_PM_OPS NULL
526#endif
527
00a0b1d5
KVA
528#ifdef CONFIG_OF
529static const struct of_device_id omap2430_id_table[] = {
530 {
531 .compatible = "ti,omap4-musb"
532 },
533 {
534 .compatible = "ti,omap3-musb"
535 },
536 {},
537};
538MODULE_DEVICE_TABLE(of, omap2430_id_table);
539#endif
540
dc09886b 541static struct platform_driver omap2430_driver = {
e9e8c85e 542 .probe = omap2430_probe,
7690417d 543 .remove = omap2430_remove,
dc09886b
FB
544 .driver = {
545 .name = "musb-omap2430",
c20aebb9 546 .pm = DEV_PM_OPS,
00a0b1d5 547 .of_match_table = of_match_ptr(omap2430_id_table),
dc09886b
FB
548 },
549};
550
aec373c1
TL
551module_platform_driver(omap2430_driver);
552
dc09886b
FB
553MODULE_DESCRIPTION("OMAP2PLUS MUSB Glue Layer");
554MODULE_AUTHOR("Felipe Balbi <balbi@ti.com>");
555MODULE_LICENSE("GPL v2");