diff options
-rw-r--r-- | drivers/usb/musb/musb_dsps.c | 89 | ||||
-rw-r--r-- | drivers/usb/musb/musb_regs.h | 7 |
2 files changed, 90 insertions, 6 deletions
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 53a4351aef97..f119a62140ef 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c | |||
@@ -144,6 +144,7 @@ struct dsps_glue { | |||
144 | const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ | 144 | const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ |
145 | struct timer_list timer; /* otg_workaround timer */ | 145 | struct timer_list timer; /* otg_workaround timer */ |
146 | unsigned long last_timer; /* last timer data for each instance */ | 146 | unsigned long last_timer; /* last timer data for each instance */ |
147 | bool sw_babble_enabled; | ||
147 | 148 | ||
148 | struct dsps_context context; | 149 | struct dsps_context context; |
149 | struct debugfs_regset32 regset; | 150 | struct debugfs_regset32 regset; |
@@ -477,6 +478,19 @@ static int dsps_musb_init(struct musb *musb) | |||
477 | val &= ~(1 << wrp->otg_disable); | 478 | val &= ~(1 << wrp->otg_disable); |
478 | dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); | 479 | dsps_writel(musb->ctrl_base, wrp->phy_utmi, val); |
479 | 480 | ||
481 | /* | ||
482 | * Check whether the dsps version has babble control enabled. | ||
483 | * In latest silicon revision the babble control logic is enabled. | ||
484 | * If MUSB_BABBLE_CTL returns 0x4 then we have the babble control | ||
485 | * logic enabled. | ||
486 | */ | ||
487 | val = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); | ||
488 | if (val == MUSB_BABBLE_RCV_DISABLE) { | ||
489 | glue->sw_babble_enabled = true; | ||
490 | val |= MUSB_BABBLE_SW_SESSION_CTRL; | ||
491 | dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, val); | ||
492 | } | ||
493 | |||
480 | ret = dsps_musb_dbg_init(musb, glue); | 494 | ret = dsps_musb_dbg_init(musb, glue); |
481 | if (ret) | 495 | if (ret) |
482 | return ret; | 496 | return ret; |
@@ -544,19 +558,82 @@ static int dsps_musb_set_mode(struct musb *musb, u8 mode) | |||
544 | return 0; | 558 | return 0; |
545 | } | 559 | } |
546 | 560 | ||
561 | static bool sw_babble_control(struct musb *musb) | ||
562 | { | ||
563 | u8 babble_ctl; | ||
564 | bool session_restart = false; | ||
565 | |||
566 | babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); | ||
567 | dev_dbg(musb->controller, "babble: MUSB_BABBLE_CTL value %x\n", | ||
568 | babble_ctl); | ||
569 | /* | ||
570 | * check line monitor flag to check whether babble is | ||
571 | * due to noise | ||
572 | */ | ||
573 | dev_dbg(musb->controller, "STUCK_J is %s\n", | ||
574 | babble_ctl & MUSB_BABBLE_STUCK_J ? "set" : "reset"); | ||
575 | |||
576 | if (babble_ctl & MUSB_BABBLE_STUCK_J) { | ||
577 | int timeout = 10; | ||
578 | |||
579 | /* | ||
580 | * babble is due to noise, then set transmit idle (d7 bit) | ||
581 | * to resume normal operation | ||
582 | */ | ||
583 | babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); | ||
584 | babble_ctl |= MUSB_BABBLE_FORCE_TXIDLE; | ||
585 | dsps_writeb(musb->mregs, MUSB_BABBLE_CTL, babble_ctl); | ||
586 | |||
587 | /* wait till line monitor flag cleared */ | ||
588 | dev_dbg(musb->controller, "Set TXIDLE, wait J to clear\n"); | ||
589 | do { | ||
590 | babble_ctl = dsps_readb(musb->mregs, MUSB_BABBLE_CTL); | ||
591 | udelay(1); | ||
592 | } while ((babble_ctl & MUSB_BABBLE_STUCK_J) && timeout--); | ||
593 | |||
594 | /* check whether stuck_at_j bit cleared */ | ||
595 | if (babble_ctl & MUSB_BABBLE_STUCK_J) { | ||
596 | /* | ||
597 | * real babble condition has occurred | ||
598 | * restart the controller to start the | ||
599 | * session again | ||
600 | */ | ||
601 | dev_dbg(musb->controller, "J not cleared, misc (%x)\n", | ||
602 | babble_ctl); | ||
603 | session_restart = true; | ||
604 | } | ||
605 | } else { | ||
606 | session_restart = true; | ||
607 | } | ||
608 | |||
609 | return session_restart; | ||
610 | } | ||
611 | |||
547 | static int dsps_musb_reset(struct musb *musb) | 612 | static int dsps_musb_reset(struct musb *musb) |
548 | { | 613 | { |
549 | struct device *dev = musb->controller; | 614 | struct device *dev = musb->controller; |
550 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); | 615 | struct dsps_glue *glue = dev_get_drvdata(dev->parent); |
551 | const struct dsps_musb_wrapper *wrp = glue->wrp; | 616 | const struct dsps_musb_wrapper *wrp = glue->wrp; |
617 | int session_restart = 0; | ||
552 | 618 | ||
553 | dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); | 619 | if (glue->sw_babble_enabled) |
554 | usleep_range(100, 200); | 620 | session_restart = sw_babble_control(musb); |
555 | usb_phy_shutdown(musb->xceiv); | 621 | /* |
556 | usleep_range(100, 200); | 622 | * In case of new silicon version babble condition can be recovered |
557 | usb_phy_init(musb->xceiv); | 623 | * without resetting the MUSB. But for older silicon versions, MUSB |
624 | * reset is needed | ||
625 | */ | ||
626 | if (session_restart || !glue->sw_babble_enabled) { | ||
627 | dev_info(musb->controller, "Restarting MUSB to recover from Babble\n"); | ||
628 | dsps_writel(musb->ctrl_base, wrp->control, (1 << wrp->reset)); | ||
629 | usleep_range(100, 200); | ||
630 | usb_phy_shutdown(musb->xceiv); | ||
631 | usleep_range(100, 200); | ||
632 | usb_phy_init(musb->xceiv); | ||
633 | session_restart = 1; | ||
634 | } | ||
558 | 635 | ||
559 | return 0; | 636 | return !session_restart; |
560 | } | 637 | } |
561 | 638 | ||
562 | static struct musb_platform_ops dsps_ops = { | 639 | static struct musb_platform_ops dsps_ops = { |
diff --git a/drivers/usb/musb/musb_regs.h b/drivers/usb/musb/musb_regs.h index 03f2655af290..b9bcda5e3945 100644 --- a/drivers/usb/musb/musb_regs.h +++ b/drivers/usb/musb/musb_regs.h | |||
@@ -72,6 +72,12 @@ | |||
72 | #define MUSB_DEVCTL_HR 0x02 | 72 | #define MUSB_DEVCTL_HR 0x02 |
73 | #define MUSB_DEVCTL_SESSION 0x01 | 73 | #define MUSB_DEVCTL_SESSION 0x01 |
74 | 74 | ||
75 | /* BABBLE_CTL */ | ||
76 | #define MUSB_BABBLE_FORCE_TXIDLE 0x80 | ||
77 | #define MUSB_BABBLE_SW_SESSION_CTRL 0x40 | ||
78 | #define MUSB_BABBLE_STUCK_J 0x20 | ||
79 | #define MUSB_BABBLE_RCV_DISABLE 0x04 | ||
80 | |||
75 | /* MUSB ULPI VBUSCONTROL */ | 81 | /* MUSB ULPI VBUSCONTROL */ |
76 | #define MUSB_ULPI_USE_EXTVBUS 0x01 | 82 | #define MUSB_ULPI_USE_EXTVBUS 0x01 |
77 | #define MUSB_ULPI_USE_EXTVBUSIND 0x02 | 83 | #define MUSB_ULPI_USE_EXTVBUSIND 0x02 |
@@ -246,6 +252,7 @@ | |||
246 | */ | 252 | */ |
247 | 253 | ||
248 | #define MUSB_DEVCTL 0x60 /* 8 bit */ | 254 | #define MUSB_DEVCTL 0x60 /* 8 bit */ |
255 | #define MUSB_BABBLE_CTL 0x61 /* 8 bit */ | ||
249 | 256 | ||
250 | /* These are always controlled through the INDEX register */ | 257 | /* These are always controlled through the INDEX register */ |
251 | #define MUSB_TXFIFOSZ 0x62 /* 8-bit (see masks) */ | 258 | #define MUSB_TXFIFOSZ 0x62 /* 8-bit (see masks) */ |