blob: 7b2dc8c3c5730880fbe13ef3d53b5e7ca47ee758 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * Copyright (C) 1995 Linus Torvalds
3 * Modifications for ARM processor (c) 1995-2004 Russell King
Duy Truong790f06d2013-02-13 16:38:12 -08004 * Copyright (c) 2010, The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/kernel.h>
12#include <linux/init.h>
13#include <linux/signal.h>
14#include <linux/cpumask.h>
15#include "acpuclock.h"
16
17#define __str(x) #x
18#define MRC(x, v1, v2, v4, v5, v6) do { \
19 unsigned int __##x; \
20 asm("mrc " __str(v1) ", " __str(v2) ", %0, " __str(v4) ", " \
21 __str(v5) ", " __str(v6) "\n" \
22 : "=r" (__##x)); \
23 pr_info("%s: %s = 0x%.8x\n", __func__, #x, __##x); \
24} while (0)
25
26static int msm_imp_ext_abort(unsigned long addr, unsigned int fsr,
27 struct pt_regs *regs)
28{
29 int cpu;
30 unsigned int regval;
31 static unsigned char flush_toggle;
32
33 asm("mrc p15, 7, %0, c15, c0, 1\n" /* read EFSR for fault status */
34 : "=r" (regval));
35 if (regval == 0x2) {
36 /* Fault was caused by icache parity error. Alternate
37 * simply retrying the access and flushing the icache. */
38 flush_toggle ^= 1;
39 if (flush_toggle)
40 asm("mcr p15, 0, %0, c7, c5, 0\n"
41 :
42 : "r" (regval)); /* input value is ignored */
43 /* Clear fault in EFSR. */
44 asm("mcr p15, 7, %0, c15, c0, 1\n"
45 :
46 : "r" (regval));
47 /* Clear fault in ADFSR. */
48 regval = 0;
49 asm("mcr p15, 0, %0, c5, c1, 0\n"
50 :
51 : "r" (regval));
52 return 0;
53 }
54
55 MRC(ADFSR, p15, 0, c5, c1, 0);
56 MRC(DFSR, p15, 0, c5, c0, 0);
57 MRC(ACTLR, p15, 0, c1, c0, 1);
58 MRC(EFSR, p15, 7, c15, c0, 1);
59 MRC(L2SR, p15, 3, c15, c1, 0);
60 MRC(L2CR0, p15, 3, c15, c0, 1);
61 MRC(L2CPUESR, p15, 3, c15, c1, 1);
62 MRC(L2CPUCR, p15, 3, c15, c0, 2);
63 MRC(SPESR, p15, 1, c9, c7, 0);
64 MRC(SPCR, p15, 0, c9, c7, 0);
65 MRC(DMACHSR, p15, 1, c11, c0, 0);
66 MRC(DMACHESR, p15, 1, c11, c0, 1);
67 MRC(DMACHCR, p15, 0, c11, c0, 2);
68 for_each_online_cpu(cpu)
69 pr_info("cpu %d, acpuclk rate: %lu kHz\n", cpu,
70 acpuclk_get_rate(cpu));
71
72 return 1;
73}
74
75static int __init msm_register_fault_handlers(void)
76{
77 /* hook in our handler for imprecise abort for when we get
78 i-cache parity errors */
79 hook_fault_code(22, msm_imp_ext_abort, SIGBUS, 0,
80 "imprecise external abort");
81
82 return 0;
83}
84arch_initcall(msm_register_fault_handlers);