aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/musb/musb_dsps.c
diff options
context:
space:
mode:
authorFelipe Balbi <balbi@ti.com>2013-10-29 13:17:16 -0400
committerFelipe Balbi <balbi@ti.com>2013-11-26 11:35:14 -0500
commit943c13971c08ddeb06f4cb9dea1addb76f6b4423 (patch)
tree0712df52363977e91d0f4d875c51e7e7e885358d /drivers/usb/musb/musb_dsps.c
parent989c78dd56307c85f710533130a2a464f6f3c5ae (diff)
usb: musb: dsps: implement ->set_mode()
this will let us support broken designs such as AM335x EVM SK where ID pin isn't routed anywhere on a host port. With this we can toggle internal IDDIG signal and make sure MUSB goes into host mode as necessary. Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/musb/musb_dsps.c')
-rw-r--r--drivers/usb/musb/musb_dsps.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 1901f6fe5807..ce7ec014a125 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -106,6 +106,7 @@ struct dsps_musb_wrapper {
106 106
107 /* bit positions for mode */ 107 /* bit positions for mode */
108 unsigned iddig:5; 108 unsigned iddig:5;
109 unsigned iddig_mux:5;
109 /* miscellaneous stuff */ 110 /* miscellaneous stuff */
110 u8 poll_seconds; 111 u8 poll_seconds;
111}; 112};
@@ -406,6 +407,54 @@ static int dsps_musb_exit(struct musb *musb)
406 return 0; 407 return 0;
407} 408}
408 409
410static int dsps_musb_set_mode(struct musb *musb, u8 mode)
411{
412 struct device *dev = musb->controller;
413 struct dsps_glue *glue = dev_get_drvdata(dev->parent);
414 const struct dsps_musb_wrapper *wrp = glue->wrp;
415 void __iomem *ctrl_base = musb->ctrl_base;
416 void __iomem *base = musb->mregs;
417 u32 reg;
418
419 reg = dsps_readl(base, wrp->mode);
420
421 switch (mode) {
422 case MUSB_HOST:
423 reg &= ~(1 << wrp->iddig);
424
425 /*
426 * if we're setting mode to host-only or device-only, we're
427 * going to ignore whatever the PHY sends us and just force
428 * ID pin status by SW
429 */
430 reg |= (1 << wrp->iddig_mux);
431
432 dsps_writel(base, wrp->mode, reg);
433 dsps_writel(ctrl_base, wrp->phy_utmi, 0x02);
434 break;
435 case MUSB_PERIPHERAL:
436 reg |= (1 << wrp->iddig);
437
438 /*
439 * if we're setting mode to host-only or device-only, we're
440 * going to ignore whatever the PHY sends us and just force
441 * ID pin status by SW
442 */
443 reg |= (1 << wrp->iddig_mux);
444
445 dsps_writel(base, wrp->mode, reg);
446 break;
447 case MUSB_OTG:
448 dsps_writel(base, wrp->phy_utmi, 0x02);
449 break;
450 default:
451 dev_err(glue->dev, "unsupported mode %d\n", mode);
452 return -EINVAL;
453 }
454
455 return 0;
456}
457
409static struct musb_platform_ops dsps_ops = { 458static struct musb_platform_ops dsps_ops = {
410 .init = dsps_musb_init, 459 .init = dsps_musb_init,
411 .exit = dsps_musb_exit, 460 .exit = dsps_musb_exit,
@@ -414,6 +463,7 @@ static struct musb_platform_ops dsps_ops = {
414 .disable = dsps_musb_disable, 463 .disable = dsps_musb_disable,
415 464
416 .try_idle = dsps_musb_try_idle, 465 .try_idle = dsps_musb_try_idle,
466 .set_mode = dsps_musb_set_mode,
417}; 467};
418 468
419static u64 musb_dmamask = DMA_BIT_MASK(32); 469static u64 musb_dmamask = DMA_BIT_MASK(32);
@@ -608,6 +658,7 @@ static const struct dsps_musb_wrapper am33xx_driver_data = {
608 .reset = 0, 658 .reset = 0,
609 .otg_disable = 21, 659 .otg_disable = 21,
610 .iddig = 8, 660 .iddig = 8,
661 .iddig_mux = 7,
611 .usb_shift = 0, 662 .usb_shift = 0,
612 .usb_mask = 0x1ff, 663 .usb_mask = 0x1ff,
613 .usb_bitmap = (0x1ff << 0), 664 .usb_bitmap = (0x1ff << 0),