summaryrefslogtreecommitdiff
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorLiang Cheng <licheng@nvidia.com>2012-10-23 13:23:15 -0500
committerDan Willemsen <dwillemsen@nvidia.com>2013-09-14 12:41:19 -0700
commitcbb871c29a702feb375430eef77c2bb55a4aa019 (patch)
treec0c361be3933e11086242c80f14c9040ed1f9b00 /arch/arm/kernel
parent9262118640b63b3827538a1d7e745bf0968b5763 (diff)
arm: enable the control of CORENPDRQ bit
Transitions to suspend states cripple any ongoing JTAG or coresight debug session. It can be prevented by setting the bit CORENPDRQ in debug register DBGPRCR. This change provides the control interface. Bug 1029902 Change-Id: I1d82dfdce4136f3c9bd40f1a5d6dc619020fe6fc Signed-off-by: Liang Cheng <licheng@nvidia.com> Reviewed-on: http://git-master/r/147012 Reviewed-by: Krishna Reddy <vdumpa@nvidia.com>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile1
-rw-r--r--arch/arm/kernel/corenpdrq.c127
2 files changed, 128 insertions, 0 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 5f3338eacad2..796639bc6bba 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_ISA_DMA_API) += dma.o
obj-$(CONFIG_FIQ) += fiq.o fiqasm.o
obj-$(CONFIG_MODULES) += armksyms.o module.o
obj-$(CONFIG_ARTHUR) += arthur.o
+obj-$(CONFIG_DEBUG_FS) += corenpdrq.o
obj-$(CONFIG_ISA_DMA) += dma-isa.o
obj-$(CONFIG_PCI) += bios32.o isa.o
obj-$(CONFIG_ARM_CPU_SUSPEND) += sleep.o suspend.o
diff --git a/arch/arm/kernel/corenpdrq.c b/arch/arm/kernel/corenpdrq.c
new file mode 100644
index 000000000000..86008577c01d
--- /dev/null
+++ b/arch/arm/kernel/corenpdrq.c
@@ -0,0 +1,127 @@
+/*
+ * Bit COREPDRQ toggling interface
+ *
+ * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/debugfs.h>
+
+static inline uint32_t read_dbgprcr(void)
+{
+ uint32_t ret_val = 0;
+
+ asm volatile("mrc p14, 0, %[result], c1, c4, 4"
+ : [result] "=r" (ret_val)
+ : /* no input */
+ : /* no clobber */
+ );
+ return ret_val;
+}
+
+static inline void write_dbgprcr(uint32_t val)
+{
+ asm volatile("mov r8, %[val_in]\n\t"
+ "mcr p14, 0, r8, c1, c4, 4"
+ : /* no output */
+ : [val_in] "r" (val)
+ : "r8"
+ );
+ return;
+}
+
+static struct dentry *corenpdrq_debugfs_root;
+
+static ssize_t corenpdrq_toggle_show(struct seq_file *s, void *data)
+{
+ uint32_t ret_val = 0;
+
+ ret_val = read_dbgprcr();
+ seq_printf(s, "%X\n", (ret_val & 0x1));
+
+ return 0;
+}
+
+static int corenpdrq_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, corenpdrq_toggle_show, inode->i_private);
+}
+
+static int corenpdrq_write(struct file *file, const char __user *userbuf,
+ size_t count, loff_t *f_pos)
+{
+ char buf[32];
+ uint32_t in_val = 0;
+ uint32_t val = 0;
+
+ if (sizeof buf <= count)
+ goto write_err;
+
+ if (copy_from_user(buf, userbuf, count))
+ goto write_err;
+
+ buf[count] = '\0';
+ strim(buf);
+
+ if (kstrtoul(buf, 10, &in_val) < 0)
+ goto write_err;
+
+ val = read_dbgprcr();
+ if (in_val)
+ val |= 1;
+ else
+ val &= ~1;
+
+ write_dbgprcr(val);
+ return count;
+
+write_err:
+ pr_err("can't program bit CORENPDRQ\n");
+
+ return -EINVAL;
+}
+
+static const struct file_operations corenpdrq_fops = {
+ .open = corenpdrq_open,
+ .read = seq_read,
+ .write = corenpdrq_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init corenpdrq_debug_init(void)
+{
+ corenpdrq_debugfs_root = debugfs_create_dir("corenpdrq", NULL);
+ if (!corenpdrq_debugfs_root)
+ return -ENOMEM;
+
+ if (!debugfs_create_file(
+ "core_npdrq", S_IRUGO | S_IWUSR, corenpdrq_debugfs_root, NULL,
+ &corenpdrq_fops))
+ goto err_out;
+
+ return 0;
+
+err_out:
+ debugfs_remove_recursive(corenpdrq_debugfs_root);
+ return -ENOMEM;
+}
+
+late_initcall(corenpdrq_debug_init);