summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Quadros <rogerq@ti.com>2012-07-30 13:05:09 +0800
committerAndy Green <andy.green@linaro.org>2012-07-30 13:05:09 +0800
commit237ab3b2d4d50db8c11aa2e4ebc903353863f622 (patch)
treee0b6ff76400a03f63b6d20ac6a7ee5597eb6796f
parente9a283315f425e89f8fbed2e97f8d506d9e9171b (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 c78108eb398..f94d91e80af 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 f4a40f001c8..8c349e0952f 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)