summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@ti.com>2014-02-04 15:29:33 +0200
committerFelipe Balbi <balbi@ti.com>2014-02-18 10:32:26 -0600
commit33f8d75f5771993ef16ed6bd56d7210f54226203 (patch)
tree5b00defb25c73b993608528758489ef67a0ac6ea
parent3c4653c1f62ea5f1706084090a5a3bcf3402dc8f (diff)
usb: musb: core: Fix remote-wakeup resume
During resume don't touch SUSPENDM/RESUME bits of POWER register while restoring controller context. These bits might be changed by the controller during resume operation and so will be different than what they were during suspend. e.g. SUSPENDM bit is set by software during USB global suspend but automatically cleared by the controller during remote wakeup or during resume. Setting this bit back while restoring context causes undesired behaviour. i.e. Babble interrupt is generated and USB is broken. Signed-off-by: Roger Quadros <rogerq@ti.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--drivers/usb/musb/musb_core.c10
1 files changed, 9 insertions, 1 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index fc192ad9cc6a..a501542dfeb5 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2157,11 +2157,19 @@ static void musb_restore_context(struct musb *musb)
void __iomem *musb_base = musb->mregs;
void __iomem *ep_target_regs;
void __iomem *epio;
+ u8 power;
musb_writew(musb_base, MUSB_FRAME, musb->context.frame);
musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode);
musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl);
- musb_writeb(musb_base, MUSB_POWER, musb->context.power);
+
+ /* Don't affect SUSPENDM/RESUME bits in POWER reg */
+ power = musb_readb(musb_base, MUSB_POWER);
+ power &= MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME;
+ musb->context.power &= ~(MUSB_POWER_SUSPENDM | MUSB_POWER_RESUME);
+ power |= musb->context.power;
+ musb_writeb(musb_base, MUSB_POWER, power);
+
musb_writew(musb_base, MUSB_INTRTXE, musb->intrtxe);
musb_writew(musb_base, MUSB_INTRRXE, musb->intrrxe);
musb_writeb(musb_base, MUSB_INTRUSBE, musb->context.intrusbe);