summaryrefslogtreecommitdiff
path: root/drivers/platform/sprd/sprd_debug.c
diff options
context:
space:
mode:
authorYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
committerYuval Adam <_@yuv.al>2017-08-30 08:25:59 +0000
commit8e4bff4cab0ddac6060645b0715210484d02ff40 (patch)
tree3a5c3024371a04692a3a6d9974d001cdff8ebf84 /drivers/platform/sprd/sprd_debug.c
Initial file dump from open source releaseHEADmaster
Diffstat (limited to 'drivers/platform/sprd/sprd_debug.c')
-rw-r--r--drivers/platform/sprd/sprd_debug.c249
1 files changed, 249 insertions, 0 deletions
diff --git a/drivers/platform/sprd/sprd_debug.c b/drivers/platform/sprd/sprd_debug.c
new file mode 100644
index 00000000..1025c20e
--- /dev/null
+++ b/drivers/platform/sprd/sprd_debug.c
@@ -0,0 +1,249 @@
+/*
+ * sprd_debug.c
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/ctype.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/sysrq.h>
+//#include <mach/regs-pmu.h>
+
+/* FIXME: This is temporary solution come from Midas */
+#ifndef CONFIG_64BIT
+#include <asm/outercache.h>
+#endif
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/uaccess.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/swiotlb.h>
+#include <soc/sprd/pm_debug.h>
+#include <soc/sprd/sprd_persistent_clock.h>
+#include <soc/sprd/hardware.h>
+#include <soc/sprd/system.h>
+#include <soc/sprd/sprd_debug.h>
+#include <linux/fs.h>
+#include <linux/seq_file.h>
+#include <linux/regs_debug.h>
+
+#define MY_DEBUG 0
+
+struct sprd_debug_regs_access *sprd_debug_last_regs_access;
+EXPORT_SYMBOL(sprd_debug_last_regs_access);
+
+/* enable/disable sprd_debug feature
+ * level = 0 when enable = 0 && enable_user = 0
+ * level = 1 when enable = 1 && enable_user = 0
+ * level = 0x10001 when enable = 1 && enable_user = 1
+ * The other cases are not considered
+ */
+union sprd_debug_level_t sprd_debug_level = { .en.kernel_fault = 1, };
+
+module_param_named(enable, sprd_debug_level.en.kernel_fault, ushort, 0644);
+module_param_named(enable_user, sprd_debug_level.en.user_fault, ushort, 0644);
+module_param_named(level, sprd_debug_level.uint_val, uint, 0644);
+
+
+static const char *gkernel_sprd_build_info_date_time[] = {
+ __DATE__,
+ __TIME__
+};
+
+static char gkernel_sprd_build_info[100];
+
+/* klaatu - schedule log */
+#ifdef CONFIG_SPRD_DEBUG_SCHED_LOG
+static struct sched_log sprd_debug_log __cacheline_aligned;
+static atomic_t task_log_idx[NR_CPUS] = { ATOMIC_INIT(-1), ATOMIC_INIT(-1) };
+static atomic_t irq_log_idx[NR_CPUS] = { ATOMIC_INIT(-1), ATOMIC_INIT(-1) };
+static atomic_t work_log_idx[NR_CPUS] = { ATOMIC_INIT(-1), ATOMIC_INIT(-1) };
+static atomic_t hrtimer_log_idx[NR_CPUS] = { ATOMIC_INIT(-1), ATOMIC_INIT(-1) };
+struct sched_log (*psprd_debug_log) = (&sprd_debug_log);
+#endif
+
+
+
+void sprd_debug_save_pte(void *pte, int task_addr)
+{
+
+// memcpy(&per_cpu(sprd_debug_fault_status,smp_processor_id()), pte,sizeof(struct sprd_debug_fault_status_t));
+// per_cpu(sprd_debug_fault_status,smp_processor_id()).cur_process_magic =task_addr;
+}
+void sprd_debug_check_crash_key(unsigned int code, int value)
+{
+ static bool volup_p;
+ static bool voldown_p;
+ static int loopcount;
+
+ if (!sprd_debug_level.en.kernel_fault)
+ return;
+
+#if 0
+ /* Must be deleted later */
+ pr_info("Test %s:key code(%d) value(%d),(up:%d,down:%d)\n", __func__, code, value, volup_p, voldown_p);
+#endif
+
+ /* Enter Force Upload
+ * Hold volume down key first
+ * and then press power key twice
+ * and volume up key should not be pressed
+ */
+ if (value) {
+ if (code == KEY_VOLUMEUP)
+ volup_p = true;
+ if (code == KEY_VOLUMEDOWN)
+ voldown_p = true;
+ if (volup_p && voldown_p) {
+ static unsigned long stack_dump_jiffies = 0;
+
+ if (!stack_dump_jiffies || jiffies > stack_dump_jiffies + HZ * 10) {
+ pr_info("trigger sysrq w & m\n");
+
+ /* show blocked thread */
+ handle_sysrq('w');
+
+ /* show memory */
+ handle_sysrq('m');
+ stack_dump_jiffies = jiffies;
+ }
+ if (code == KEY_POWER) {
+ pr_info("%s: Crash key count : %d\n", __func__, ++loopcount);
+ if (loopcount == 2)
+ panic("Crash Key");
+ }
+ }
+ } else {
+ if (code == KEY_VOLUMEUP)
+ volup_p = false;
+ if (code == KEY_VOLUMEDOWN) {
+ loopcount = 0;
+ voldown_p = false;
+ }
+ }
+}
+
+static void sprd_debug_set_build_info(void)
+{
+ char *p = gkernel_sprd_build_info;
+ sprintf(p, "Kernel Build Info : ");
+ strcat(p, " Date:");
+ strncat(p, gkernel_sprd_build_info_date_time[0], 12);
+ strcat(p, " Time:");
+ strncat(p, gkernel_sprd_build_info_date_time[1], 9);
+}
+
+__init int sprd_debug_init(void)
+{
+ dma_addr_t addr;
+
+ if (!sprd_debug_level.en.kernel_fault)
+ return -1;
+
+ sprd_debug_set_build_info();
+#ifndef CONFIG_64BIT
+ sprd_debug_last_regs_access = (struct sprd_debug_regs_access*)dma_alloc_coherent(
+ NULL, sizeof(struct sprd_debug_regs_access)*NR_CPUS, &addr, GFP_KERNEL);
+#else
+ sprd_debug_last_regs_access = (struct sprd_debug_regs_access*)swiotlb_alloc_coherent(
+ NULL, sizeof(struct sprd_debug_regs_access)*NR_CPUS, &addr, GFP_KERNEL);
+#endif
+ printk("*** %s, size:%u, sprd_debug_last_regs_access:%p *** \n",
+ __func__, sizeof(struct sprd_debug_regs_access)*NR_CPUS, sprd_debug_last_regs_access);
+
+ return 0;
+}
+subsys_initcall(sprd_debug_init);
+
+int get_sprd_debug_level(void)
+{
+ return sprd_debug_level.uint_val;
+}
+
+/* klaatu - schedule log */
+#ifdef CONFIG_SPRD_DEBUG_SCHED_LOG
+void __sprd_debug_task_log(int cpu, struct task_struct *task)
+{
+ unsigned i;
+
+ i = atomic_inc_return(&task_log_idx[cpu]) &
+ (ARRAY_SIZE(psprd_debug_log->task[0]) - 1);
+ psprd_debug_log->task[cpu][i].time = cpu_clock(cpu);
+#ifdef CP_DEBUG
+ psprd_debug_log->task[cpu][i].sys_cnt = get_sys_cnt();
+#endif
+ strcpy(psprd_debug_log->task[cpu][i].comm, task->comm);
+ psprd_debug_log->task[cpu][i].pid = task->pid;
+}
+
+void __sprd_debug_irq_log(unsigned int irq, void *fn, int en)
+{
+ int cpu = raw_smp_processor_id();
+ unsigned i;
+
+ i = atomic_inc_return(&irq_log_idx[cpu]) &
+ (ARRAY_SIZE(psprd_debug_log->irq[0]) - 1);
+ psprd_debug_log->irq[cpu][i].time = cpu_clock(cpu);
+#ifdef CP_DEBUG
+ psprd_debug_log->irq[cpu][i].sys_cnt = get_sys_cnt();
+#endif
+ psprd_debug_log->irq[cpu][i].irq = irq;
+ psprd_debug_log->irq[cpu][i].fn = (void *)fn;
+ psprd_debug_log->irq[cpu][i].en = en;
+}
+
+void __sprd_debug_work_log(struct worker *worker,
+ struct work_struct *work, work_func_t f)
+{
+ int cpu = raw_smp_processor_id();
+ unsigned i;
+
+ i = atomic_inc_return(&work_log_idx[cpu]) &
+ (ARRAY_SIZE(psprd_debug_log->work[0]) - 1);
+ psprd_debug_log->work[cpu][i].time = cpu_clock(cpu);
+#ifdef CP_DEBUG
+ psprd_debug_log->work[cpu][i].sys_cnt = get_sys_cnt();
+#endif
+ psprd_debug_log->work[cpu][i].worker = worker;
+ psprd_debug_log->work[cpu][i].work = work;
+ psprd_debug_log->work[cpu][i].f = f;
+}
+
+void __sprd_debug_hrtimer_log(struct hrtimer *timer,
+ enum hrtimer_restart (*fn) (struct hrtimer *), int en)
+{
+ int cpu = raw_smp_processor_id();
+ unsigned i;
+
+ i = atomic_inc_return(&hrtimer_log_idx[cpu]) &
+ (ARRAY_SIZE(psprd_debug_log->hrtimers[0]) - 1);
+ psprd_debug_log->hrtimers[cpu][i].time = cpu_clock(cpu);
+#ifdef CP_DEBUG
+ psprd_debug_log->hrtimers[cpu][i].sys_cnt = get_sys_cnt();
+#endif
+ psprd_debug_log->hrtimers[cpu][i].timer = timer;
+ psprd_debug_log->hrtimers[cpu][i].fn = fn;
+ psprd_debug_log->hrtimers[cpu][i].en = en;
+}
+
+int get_task_log_idx(int cpu)
+{
+ return atomic_inc_return(&task_log_idx[cpu]) & (ARRAY_SIZE(psprd_debug_log->task[0]) - 1);
+}
+
+int get_irq_log_idx(int cpu)
+{
+ return atomic_inc_return(&irq_log_idx[cpu]) & (ARRAY_SIZE(psprd_debug_log->irq[0]) - 1);
+}
+
+#endif /* CONFIG_SPRD_DEBUG_SCHED_LOG */
+