usb: musb: omap2430: fix occasional musb breakage on boot
authorGrazvydas Ignotas <notasas@gmail.com>
Tue, 10 Dec 2013 00:02:38 +0000 (02:02 +0200)
committerGrazvydas Ignotas <notasas@gmail.com>
Tue, 10 Dec 2013 23:00:25 +0000 (01:00 +0200)
This is a hard to reproduce problem which leads to non-functional
USB-OTG port in 0.1%-1% of all boots. Tracked it down to commit
e25bec160158abe86c "omap2+: save and restore OTG_INTERFSEL",
which introduces save/restore of OTG_INTERFSEL over suspend.

Since the resume function is also called early in driver init, it uses a
non-initialized value (which is 0 and a non-supported setting in DM37xx
for INTERFSEL). Shortly after the correct value is set. Apparently this
works most time, but not always.

Fix it by not writing the value on runtime resume if it is 0
(0 should never be saved in the context as it's invalid value).

This issue was originally found by Andreas Naumann:
http://marc.info/?l=linux-usb&m=138562574719654&w=2

drivers/usb/musb/omap2430.c

index 55c0b93..58ca5e4 100644 (file)
@@ -513,7 +513,8 @@ static int omap2430_runtime_resume(struct device *dev)
        struct musb                     *musb = glue_to_musb(glue);
 
        omap2430_low_level_init(musb);
        struct musb                     *musb = glue_to_musb(glue);
 
        omap2430_low_level_init(musb);
-       musb_writel(musb->mregs, OTG_INTERFSEL,
+       if (musb->context.otg_interfsel != 0)
+               musb_writel(musb->mregs, OTG_INTERFSEL,
                                        musb->context.otg_interfsel);
 
        otg_set_suspend(musb->xceiv, 0);
                                        musb->context.otg_interfsel);
 
        otg_set_suspend(musb->xceiv, 0);