summary refs log tree commit diff
path: root/drivers/tty/sysrq.c
diff options
context:
space:
mode:
authorMathieu J. Poirier <mathieu.poirier@linaro.org>2013-08-03 17:22:08 -0700
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-08-12 22:31:55 -0700
commit4c076eb0cfd9fa3f8900ac3dbdcaaca2f5fc2c1e (patch)
tree9b7293b21eb84ca52442acff639f95f6e7f640d9 /drivers/tty/sysrq.c
parent401d7d108fc19595f6a7d7dd7d553458155e31fa (diff)
downloadlinux-4c076eb0cfd9fa3f8900ac3dbdcaaca2f5fc2c1e.tar.gz
Input: sysrq - DT binding for key sequence
Adding a simple device tree binding for the specification of key
sequences. Definition of the keys found in the sequence are located in
'include/uapi/linux/input.h'.

For the sysrq driver, holding the sequence of keys down for a specific
amount of time will reset the system.

Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Acked-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/tty/sysrq.c')
-rw-r--r--drivers/tty/sysrq.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index 55ba46f6207d..749dae8c3489 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -45,6 +45,7 @@
 #include <linux/moduleparam.h>
 #include <linux/jiffies.h>
 #include <linux/syscalls.h>
+#include <linux/of.h>
 
 #include <asm/ptrace.h>
 #include <asm/irq_regs.h>
@@ -681,6 +682,40 @@ static void sysrq_detect_reset_sequence(struct sysrq_state *state,
 	}
 }
 
+#ifdef CONFIG_OF
+static void sysrq_of_get_keyreset_config(void)
+{
+	u32 key;
+	struct device_node *np;
+	struct property *prop;
+	const __be32 *p;
+
+	np = of_find_node_by_path("/chosen/linux,sysrq-reset-seq");
+	if (!np) {
+		pr_debug("No sysrq node found");
+		return;
+	}
+
+	/* Reset in case a __weak definition was present */
+	sysrq_reset_seq_len = 0;
+
+	of_property_for_each_u32(np, "keyset", prop, p, key) {
+		if (key == KEY_RESERVED || key > KEY_MAX ||
+		    sysrq_reset_seq_len == SYSRQ_KEY_RESET_MAX)
+			break;
+
+		sysrq_reset_seq[sysrq_reset_seq_len++] = (unsigned short)key;
+	}
+
+	/* Get reset timeout if any. */
+	of_property_read_u32(np, "timeout-ms", &sysrq_reset_downtime_ms);
+}
+#else
+static void sysrq_of_get_keyreset_config(void)
+{
+}
+#endif
+
 static void sysrq_reinject_alt_sysrq(struct work_struct *work)
 {
 	struct sysrq_state *sysrq =
@@ -914,6 +949,7 @@ static inline void sysrq_register_handler(void)
 	int error;
 	int i;
 
+	/* First check if a __weak interface was instantiated. */
 	for (i = 0; i < ARRAY_SIZE(sysrq_reset_seq); i++) {
 		key = platform_sysrq_reset_seq[i];
 		if (key == KEY_RESERVED || key > KEY_MAX)
@@ -922,6 +958,12 @@ static inline void sysrq_register_handler(void)
 		sysrq_reset_seq[sysrq_reset_seq_len++] = key;
 	}
 
+	/*
+	 * DT configuration takes precedence over anything that would
+	 * have been defined via the __weak interface.
+	 */
+	sysrq_of_get_keyreset_config();
+
 	error = input_register_handler(&sysrq_handler);
 	if (error)
 		pr_err("Failed to register input handler, error %d", error);