summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@ti.com>2012-07-26 18:08:09 +0300
committerXavier Boudet <x-boudet@ti.com>2012-07-26 17:21:09 +0200
commit651c1e3dd877011714b0f6d50d7c653e731df6db (patch)
tree3868c055a43209b0fab7be6700dfd4a893087e0f
parent692a9a995256d0813a7c494913f66c28f8d53e58 (diff)
usb: musb: fix suspend/resume after gadget driver is loaded and unloaded
If the MUSB controller is already suspended via runtime suspend then it will be disabled (and clocks gated) thus accessing the controller while system suspend to save state will cause L3 bus errors. This problem can be reproduced by loading a gadget driver, unloading it and putting the system to suspend. There is no need to save/restore controller state in this case as the corresponding runtime suspend/resume functions are already doing that. This patch makes sure we don't access the MUSB controller registers in the suspend path if it is already disabled. Signed-off-by: Roger Quadros <rogerq@ti.com>
-rw-r--r--drivers/usb/musb/musb_core.c16
-rw-r--r--drivers/usb/musb/musb_core.h2
2 files changed, 16 insertions, 2 deletions
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index c78108eb398d..f94d91e80aff 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2327,7 +2327,11 @@ static int musb_suspend(struct device *dev)
}
spin_unlock_irqrestore(&musb->lock, flags);
- musb_save_context(musb);
+
+ /* Need to save state only if it is not yet runtime suspended */
+ if (!musb->suspended) {
+ musb_save_context(musb);
+ }
return 0;
}
@@ -2340,7 +2344,13 @@ static int musb_resume_noirq(struct device *dev)
* module got reset through the PSC (vs just being disabled).
*/
- musb_restore_context(musb);
+ /*
+ * Restore state only if device was not runtime suspended before
+ * the system suspend
+ */
+ if (!musb->suspended) {
+ musb_restore_context(musb);
+ }
return 0;
}
@@ -2349,6 +2359,7 @@ static int musb_runtime_suspend(struct device *dev)
struct musb *musb = dev_to_musb(dev);
musb_save_context(musb);
+ musb->suspended = true;
return 0;
}
@@ -2370,6 +2381,7 @@ static int musb_runtime_resume(struct device *dev)
if (!first)
musb_restore_context(musb);
first = 0;
+ musb->suspended = false;
return 0;
}
diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h
index f4a40f001c88..8c349e0952f1 100644
--- a/drivers/usb/musb/musb_core.h
+++ b/drivers/usb/musb/musb_core.h
@@ -456,6 +456,8 @@ struct musb {
#ifdef MUSB_CONFIG_PROC_FS
struct proc_dir_entry *proc_entry;
#endif
+
+ unsigned suspended:1; /* module disabled */
};
static inline struct musb *gadget_to_musb(struct usb_gadget *g)