extern void (*arm_pm_restart)(enum reboot_mode str, const char *cmd);
+static struct err_variant arm64_err_type_1[] = {
+ ERR_VAR("AV", 31, 31),
+ ERR_VAR("Valid", 30, 30),
+ ERR_VAR("UC", 29, 29),
+ ERR_VAR("ER", 28, 28),
+ ERR_VAR("OF", 27, 27),
+ ERR_VAR("MV", 26, 26),
+ ERR_VAR("CE", 25, 24),
+ ERR_VAR("DE", 23, 23),
+ ERR_VAR("PN", 22, 22),
+ ERR_VAR("UET", 21, 20),
+ ERR_VAR("RES0", 19, 16),
+ ERR_VAR("IERR", 15, 8),
+ ERR_VAR("SERR", 7, 0),
+ ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_2[] = {
+ ERR_VAR("Count1", 63, 56),
+ ERR_VAR("Count0", 55, 48),
+ ERR_VAR("RES1", 47, 41),
+ ERR_VAR("Syndrom", 40, 32),
+ ERR_VAR("Stype2", 31, 28),
+ ERR_VAR("SType1", 27, 24),
+ ERR_VAR("SType0", 23, 16),
+ ERR_VAR("Type", 15, 12),
+ ERR_VAR("RES0", 11, 6),
+ ERR_VAR("RE", 5, 5),
+ ERR_VAR("SynValid", 4, 4),
+ ERR_VAR("AddrValid", 3, 3),
+ ERR_VAR("UnContained", 2, 2),
+ ERR_VAR("UC", 1, 1),
+ ERR_VAR("Vaild", 0, 0),
+ ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_3[] = {
+ ERR_VAR("RES0", 63, 32),
+ ERR_VAR("A", 31, 31),
+ ERR_VAR("RES0", 30, 25),
+ ERR_VAR("RES2", 24, 16),
+ ERR_VAR("AEType", 15, 14),
+ ERR_VAR("RES1", 13, 13),
+ ERR_VAR("EXT", 12, 12),
+ ERR_VAR("AET", 11, 10),
+ ERR_VAR("EA", 9, 9),
+ ERR_VAR("EA", 8, 6),
+ ERR_VAR("DFSC", 5, 0),
+ ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_4[] = {
+ ERR_VAR("Fatal", 63, 63),
+ ERR_VAR("RES0", 62, 48),
+ ERR_VAR("Other error count", 47, 40),
+ ERR_VAR("Repeat error count", 39, 32),
+ ERR_VAR("Valid", 31, 31),
+ ERR_VAR("RAMID", 30, 24),
+ ERR_VAR("RES0", 23, 21),
+ ERR_VAR("CPUID", 20, 18),
+ ERR_VAR("RES0", 17, 12),
+ ERR_VAR("RAM address", 11, 0),
+ ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_TCR[] = {
+// ERR_VAR("HPD1", 42, 42),
+// ERR_VAR("HPD0", 41, 41),
+// ERR_VAR("HD", 40, 40),
+// ERR_VAR("HA", 39, 39),
+ ERR_VAR("TBI1", 38, 38),
+ ERR_VAR("TBI0", 37, 37),
+// ERR_VAR("AS", 36, 36),
+// ERR_VAR("IPS", 34, 32),
+// ERR_VAR("TG1", 31, 30),
+// ERR_VAR("SH1", 29, 28),
+// ERR_VAR("ORGN1", 27, 26),
+// ERR_VAR("IRGN1", 25, 24),
+// ERR_VAR("EPD1", 23, 23),
+// ERR_VAR("A1", 22, 22),
+// ERR_VAR("T1SZ", 21, 16),
+// ERR_VAR("TG0", 15, 14),
+// ERR_VAR("SH0", 13, 12),
+// ERR_VAR("ORGN0", 11, 10),
+// ERR_VAR("IRGN0", 9, 8),
+// ERR_VAR("EPD0", 7, 7),
+// ERR_VAR("T1SZ", 5, 0),
+// ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_VBAR[] = {
+ ERR_VAR("VBA[63:56]", 63, 56),
+ ERR_VAR("VBA[55]", 55, 55),
+ ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_L2ECTLR[] = {
+ ERR_VAR("L2AsyncErr", 30, 30),
+ ERR_VAR("END", 64, 64),
+};
+
+static struct err_variant arm64_err_type_L3ECTLR[] = {
+ ERR_VAR("L3IntrnAsyncErr", 30, 30),
+ ERR_VAR("ExtBusAsyncErr", 29, 29),
+ ERR_VAR("EnTmrIncChk", 3, 3),
+ ERR_VAR("ClusterQactiveCtl", 2, 0),
+ ERR_VAR("END", 64, 64),
+};
+
+enum {
+ FEMERR0SR = 0,
+ LSMERR0SR,
+ TBWMERR0SR,
+ L2MERR0SR,
+ L3MERR0SR,
+ DISR_EL1,
+ ERXSTATUS_EL1,
+ CPUMERRSR,
+ L2MERRSR,
+ TCR_EL1,
+ VBAR_EL1,
+ L2ECTLR_EL1,
+ L3ECTLR
+};
+
+static struct err_variant_data exynos_cpu_err_table[] = {
+ ERR_REG(arm64_err_type_2, 0, "FEMERR0SR"),
+ ERR_REG(arm64_err_type_2, 0, "LSMERR0SR"),
+ ERR_REG(arm64_err_type_2, 0, "TBWMERR0SR"),
+ ERR_REG(arm64_err_type_2, 0, "L2MERR0SR"),
+ ERR_REG(arm64_err_type_2, 0, "L3MERR0SR"),
+ ERR_REG(arm64_err_type_3, 31, "DISR_EL1"),
+ ERR_REG(arm64_err_type_1, 30, "ERXSTATUS_EL1"),
+ ERR_REG(arm64_err_type_4, 31, "CPUMERRSR"),
+ ERR_REG(arm64_err_type_4, 31, "L2MERRSR"),
+ ERR_REG(arm64_err_type_TCR, 0xFF, "TCR_EL1"),
+ ERR_REG(arm64_err_type_VBAR, 0xFF, "VBAR_EL1"),
+ ERR_REG(arm64_err_type_L2ECTLR, 30, "L2ECTLR_EL1"),
+ ERR_REG(arm64_err_type_L3ECTLR, 30, "L3ECTLR")
+};
+
+void exynos_err_parse(u32 reg_idx, u64 reg, struct err_variant_data *exynos_cpu_err)
+{
+ u8 i = 0;
+ u8 fld_offset, fld_end;
+ u64 valid;
+ u32 field;
+ const struct err_variant *variant;
+
+
+ if (exynos_cpu_err->valid_bit == 0xFF)
+ goto run_valid;
+
+ valid = reg & BIT(exynos_cpu_err->valid_bit);
+ if (!valid) {
+ pr_emerg("%s valid_bit(%d) is NOT set (0x%lx)\n",
+ exynos_cpu_err->reg_name, exynos_cpu_err->valid_bit, valid);
+ return;
+ }
+
+run_valid:
+ variant = exynos_cpu_err->variant;
+ while (true) {
+ fld_offset = variant[i].fld_offset;
+ fld_end = variant[i].fld_end;
+
+ if (fld_end > 63)
+ break;
+
+ field = (reg & GENMASK_ULL(fld_end, fld_offset)) >> fld_offset;
+ if (field != 0)
+ pr_emerg("%s (%d:%d) %s 0x%lx\n",
+ exynos_cpu_err->reg_name,
+ fld_end, fld_offset,
+ variant[i].fld_name, field);
+ i++;
+ };
+};
+
+static void exynos_cpu_err_parse(u32 reg_idx, u64 reg)
+{
+ if (reg_idx >= ARRAY_SIZE(exynos_cpu_err_table)) {
+ pr_err("%s: there is no parse data\n", __func__);
+ return;
+ }
+
+ exynos_err_parse(reg_idx, reg, &exynos_cpu_err_table[reg_idx]);
+}
+
static void exynos_early_panic(void *val)
{
exynos_bcm_dbg_stop(PANIC_HANDLE);
{
struct pt_regs *core_reg = (struct pt_regs *)val;
- asm("str x0, [%0, #0]\n\t"
+ asm volatile ("str x0, [%0, #0]\n\t"
"mov x0, %0\n\t"
"str x1, [x0, #8]\n\t"
"str x2, [x0, #16]\n\t"
(struct dbg_snapshot_mmu_reg *)val;
#ifdef CONFIG_ARM64
- asm("mrs x1, SCTLR_EL1\n\t" /* SCTLR_EL1 */
+ asm volatile ("mrs x1, SCTLR_EL1\n\t" /* SCTLR_EL1 */
"str x1, [%0]\n\t"
"mrs x1, TTBR0_EL1\n\t" /* TTBR0_EL1 */
"str x1, [%0,#8]\n\t"
: "%x1", "memory" /* clobbered register */
);
#else
- asm("mrc p15, 0, r1, c1, c0, 0\n\t" /* SCTLR */
+ asm volatile ("mrc p15, 0, r1, c1, c0, 0\n\t" /* SCTLR */
"str r1, [%0]\n\t"
"mrc p15, 0, r1, c2, c0, 0\n\t" /* TTBR0 */
"str r1, [%0,#4]\n\t"
#endif
}
+void exynos_dump_common_cpu_reg(void)
+{
+ unsigned long reg1, reg2;
+
+ asm volatile ("mrs %0, vbar_el1\n\t"
+ "mrs %1, tcr_el1\n"
+ : "=r" (reg1), "=r" (reg2));
+
+ exynos_cpu_err_parse(VBAR_EL1, reg1);
+ exynos_cpu_err_parse(TCR_EL1, reg2);
+}
+
static void exynos_dump_info(void *val)
{
/*
switch (read_cpuid_part_number()) {
case ARM_CPU_PART_MONGOOSE:
case ARM_CPU_PART_MEERKAT:
- asm ("mrs %0, S3_1_c15_c2_0\n\t"
- "mrs %1, S3_1_c15_c2_4\n"
- : "=r" (reg1), "=r" (reg2));
- pr_emerg("FEMERR0SR: %016lx, FEMERR1SR: %016lx\n", reg1, reg2);
- asm ("mrs %0, S3_1_c15_c2_1\n\t"
- "mrs %1, S3_1_c15_c2_5\n"
- : "=r" (reg1), "=r" (reg2));
- pr_emerg("LSMERR0SR: %016lx, LSMERR1SR: %016lx\n", reg1, reg2);
- asm ("mrs %0, S3_1_c15_c2_2\n\t"
- "mrs %1, S3_1_c15_c2_6\n"
- : "=r" (reg1), "=r" (reg2));
- pr_emerg("TBWMERR0SR: %016lx, TBWMERR1SR: %016lx\n", reg1, reg2);
- asm ("mrs %0, S3_1_c15_c2_3\n\t"
- "mrs %1, S3_1_c15_c2_7\n"
- : "=r" (reg1), "=r" (reg2));
- pr_emerg("L2MERR0SR: %016lx, L2MERR1SR: %016lx\n", reg1, reg2);
-
- /* L3 MERR */
- asm ("msr S3_1_c15_c7_1, %0\n\t"
- "isb\n"
- :: "r" (0));
- asm ("mrs %0, S3_1_c15_c3_0\n\t"
- "mrs %1, S3_1_c15_c3_4\n"
- : "=r" (reg1), "=r" (reg2));
- pr_emerg("BANK0 L3MERR0SR: %016lx, L3MERR1SR: %016lx\n", reg1, reg2);
- asm ("msr S3_1_c15_c7_1, %0\n\t"
- "isb\n"
- :: "r" (1));
- asm ("mrs %0, S3_1_c15_c3_0\n\t"
- "mrs %1, S3_1_c15_c3_4\n"
- : "=r" (reg1), "=r" (reg2));
- pr_emerg("BANK1 L3MERR0SR: %016lx, L3MERR1SR: %016lx\n", reg1, reg2);
- asm ("msr S3_1_c15_c7_1, %0\n\t"
- "isb\n"
- :: "r" (2));
- asm ("mrs %0, S3_1_c15_c3_0\n\t"
- "mrs %1, S3_1_c15_c3_4\n"
- : "=r" (reg1), "=r" (reg2));
- pr_emerg("BANK2 L3MERR0SR: %016lx, L3MERR1SR: %016lx\n", reg1, reg2);
- asm ("msr S3_1_c15_c7_1, %0\n\t"
- "isb\n"
- :: "r" (3));
- asm ("mrs %0, S3_1_c15_c3_0\n\t"
- "mrs %1, S3_1_c15_c3_4\n"
- : "=r" (reg1), "=r" (reg2));
- pr_emerg("BANK3 L3MERR0SR: %016lx, L3MERR1SR: %016lx\n", reg1, reg2);
-
break;
default:
break;
switch (read_cpuid_part_number()) {
case ARM_CPU_PART_CORTEX_A57:
case ARM_CPU_PART_CORTEX_A53:
- asm ("mrs %0, S3_1_c15_c2_2\n\t"
+ asm volatile ("mrs %0, S3_1_c11_c0_3\n\t"
+ : "=r" (reg1));
+ pr_emerg("L2ECTLR_EL1: %016lx", reg1);
+ exynos_cpu_err_parse(L2ECTLR_EL1, reg1);
+
+ asm volatile ("mrs %0, S3_1_c15_c2_2\n\t"
"mrs %1, S3_1_c15_c2_3\n"
: "=r" (reg1), "=r" (reg2));
pr_emerg("CPUMERRSR: %016lx, L2MERRSR: %016lx\n", reg1, reg2);
+ exynos_cpu_err_parse(CPUMERRSR, reg1);
+ exynos_cpu_err_parse(L2MERRSR, reg2);
break;
case ARM_CPU_PART_ANANKE:
+ case ARM_CPU_PART_CORTEX_A73:
+ asm volatile ("mrs %0, S3_1_c11_c0_3\n\t"
+ "mrs %1, S3_1_c15_c2_3\n"
+ : "=r" (reg1), "=r" (reg2));
+ pr_emerg("L2ECTLR_EL1: %016lx, L2MERRSR: %016lx\n", reg1, reg2);
+ exynos_cpu_err_parse(L2ECTLR_EL1, reg1);
+ exynos_cpu_err_parse(L2MERRSR, reg2);
+ break;
case ARM_CPU_PART_CORTEX_A75:
- asm ("HINT #16");
- asm ("mrs %0, S3_0_c12_c1_1\n" : "=r" (reg1)); /* read DISR_EL1 */
+ asm volatile ("HINT #16");
+ asm volatile ("mrs %0, S3_0_c12_c1_1\n" : "=r" (reg1)); /* read DISR_EL1 */
pr_emerg("DISR_EL1: %016lx\n", reg1);
+ exynos_cpu_err_parse(DISR_EL1, reg1);
- asm ("msr S3_0_c5_c3_1, %0\n"
+ asm volatile ("msr S3_0_c5_c3_1, %0\n"
"isb\n"
- :: "r" (0)); /* set 1st ERRSELR_EL1 */
+ :: "r" (0)); /* set CPU ERRSELR_EL1 */
- asm ("mrs %0, S3_0_c5_c4_2\n"
+ asm volatile ("mrs %0, S3_0_c5_c4_2\n"
"mrs %1, S3_0_c5_c4_3\n"
"mrs %2, S3_0_c5_c5_0\n"
: "=r" (reg1), "=r" (reg2), "=r" (reg3));
- pr_emerg("1st : ERXSTATUS_EL1: %016lx, ERXADDR_EL1: %016lx, "
+ pr_emerg("CPU : ERXSTATUS_EL1: %016lx, ERXADDR_EL1: %016lx, "
"ERXMISC0_EL1: %016lx\n", reg1, reg2, reg3);
+ exynos_cpu_err_parse(ERXSTATUS_EL1, reg1);
- asm ("msr S3_0_c5_c3_1, %0\n"
+ asm volatile ("msr S3_0_c5_c3_1, %0\n"
"isb\n"
- :: "r" (1)); /* set 2nd ERRSELR_EL1 */
+ :: "r" (1)); /* set DSU ERRSELR_EL1 */
- asm ("mrs %0, S3_0_c5_c4_2\n"
+ asm volatile ("mrs %0, S3_0_c5_c4_2\n"
"mrs %1, S3_0_c5_c4_3\n"
"mrs %2, S3_0_c5_c5_0\n"
: "=r" (reg1), "=r" (reg2), "=r" (reg3));
- pr_emerg("2nd : ERXSTATUS_EL1: %016lx, ERXADDR_EL1: %016lx, "
+ pr_emerg("DSU : ERXSTATUS_EL1: %016lx, ERXADDR_EL1: %016lx, "
"ERXMISC0_EL1: %016lx\n", reg1, reg2, reg3);
+ exynos_cpu_err_parse(ERXSTATUS_EL1, reg1);
break;
default:
}
#else
unsigned long reg0;
- asm ("mrc p15, 0, %0, c0, c0, 0\n": "=r" (reg0));
+ asm volatile ("mrc p15, 0, %0, c0, c0, 0\n": "=r" (reg0));
if (((reg0 >> 4) & 0xFFF) == 0xC0F) {
/* Only Cortex-A15 */
unsigned long reg1, reg2, reg3;
- asm ("mrrc p15, 0, %0, %1, c15\n\t"
+ asm volatile ("mrrc p15, 0, %0, %1, c15\n\t"
"mrrc p15, 1, %2, %3, c15\n"
: "=r" (reg0), "=r" (reg1),
"=r" (reg2), "=r" (reg3));