diff mbox

[3/3] ARM: hw_breakpoint: Debug powerdown support for self-hosted debug

Message ID 1357918138-20222-4-git-send-email-will.deacon@arm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Will Deacon Jan. 11, 2013, 3:28 p.m. UTC
From: Dietmar Eggemann <dietmar.eggemann@arm.com>

This patch introduces debug powerdown support for self-hosted debug for v7
and v7.1 debug architecture for a SinglePower system, i.e. a system without a
separate core and debug power domain. On a SinglePower system the OS Lock is
lost over a powerdown.

If CONFIG_CPU_PM is set the new function pm_init() registers hw_breakpoint
with CPU PM for a system supporting OS Save and Restore.

Receiving a CPU PM EXIT notifier indicates that a single CPU has exited a low
power state. A call to reset_ctrl_regs() is hooked into the CPU PM EXIT
notifier chain. This function makes sure that the sticky power-down is clear
(only v7 debug), the OS Double Lock is clear (only v7.1 debug) and it clears
the OS Lock for v7 debug (for a system supporting OS Save and Restore) and
v7.1 debug. Furthermore, it clears any vector-catch events and all
breakpoint/watchpoint control/value registers for v7 and v7.1 debug.

Signed-off-by: Dietmar Eggemann <dietmar.eggemann@arm.com>
[will: removed redundant has_ossr check]
Signed-off-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm/kernel/hw_breakpoint.c | 28 +++++++++++++++++++++++++++-
 1 file changed, 27 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c
index 201d440..5eae53e 100644
--- a/arch/arm/kernel/hw_breakpoint.c
+++ b/arch/arm/kernel/hw_breakpoint.c
@@ -28,6 +28,7 @@ 
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/smp.h>
+#include <linux/cpu_pm.h>
 
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
@@ -1032,6 +1033,30 @@  static struct notifier_block __cpuinitdata dbg_reset_nb = {
 	.notifier_call = dbg_reset_notify,
 };
 
+#ifdef CONFIG_CPU_PM
+static int dbg_cpu_pm_notify(struct notifier_block *self, unsigned long action,
+			     void *v)
+{
+	if (action == CPU_PM_EXIT)
+		reset_ctrl_regs(NULL);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block __cpuinitdata dbg_cpu_pm_nb = {
+	.notifier_call = dbg_cpu_pm_notify,
+};
+
+static void __init pm_init(void)
+{
+	cpu_pm_register_notifier(&dbg_cpu_pm_nb);
+}
+#else
+static inline void pm_init(void)
+{
+}
+#endif
+
 static int __init arch_hw_breakpoint_init(void)
 {
 	debug_arch = get_debug_arch();
@@ -1081,8 +1106,9 @@  static int __init arch_hw_breakpoint_init(void)
 	hook_ifault_code(FAULT_CODE_DEBUG, hw_breakpoint_pending, SIGTRAP,
 			TRAP_HWBKPT, "breakpoint debug exception");
 
-	/* Register hotplug notifier. */
+	/* Register hotplug and PM notifiers. */
 	register_cpu_notifier(&dbg_reset_nb);
+	pm_init();
 	return 0;
 }
 arch_initcall(arch_hw_breakpoint_init);