xref: /rk3399_rockchip-uboot/arch/arm/lib/interrupts_64.c (revision 74ab8aa2e78ea08c1672678ea0819929d1e3910f)
10ae76531SDavid Feng /*
20ae76531SDavid Feng  * (C) Copyright 2013
30ae76531SDavid Feng  * David Feng <fenghua@phytium.com.cn>
40ae76531SDavid Feng  *
50ae76531SDavid Feng  * SPDX-License-Identifier:	GPL-2.0+
60ae76531SDavid Feng  */
70ae76531SDavid Feng 
80ae76531SDavid Feng #include <common.h>
90ae76531SDavid Feng #include <linux/compiler.h>
1064982915SAlexander Graf #include <efi_loader.h>
1158d85a14SJoseph Chen #include <iomem.h>
12d554a7b2SJoseph Chen #include <stacktrace.h>
130ae76531SDavid Feng 
145e076729SPeng Fan DECLARE_GLOBAL_DATA_PTR;
15f4fc5f8dSKever Yang #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_IRQ)
165e076729SPeng Fan 
170ae76531SDavid Feng int interrupt_init(void)
180ae76531SDavid Feng {
190ae76531SDavid Feng 	return 0;
200ae76531SDavid Feng }
210ae76531SDavid Feng 
220ae76531SDavid Feng void enable_interrupts(void)
230ae76531SDavid Feng {
240ae76531SDavid Feng 	return;
250ae76531SDavid Feng }
260ae76531SDavid Feng 
270ae76531SDavid Feng int disable_interrupts(void)
280ae76531SDavid Feng {
290ae76531SDavid Feng 	return 0;
300ae76531SDavid Feng }
31fa40f8a0SJoseph Chen #endif
320ae76531SDavid Feng 
33faa7eb0fSJoseph Chen #if (!defined(CONFIG_SPL_BUILD) && !defined(CONFIG_TPL_BUILD))
34faa7eb0fSJoseph Chen #define REG_BITS(val, shift, mask)	(((val) >> (shift)) & (mask))
35faa7eb0fSJoseph Chen 
36faa7eb0fSJoseph Chen void show_regs(struct pt_regs *regs)
37faa7eb0fSJoseph Chen {
38faa7eb0fSJoseph Chen 	int el = current_el();
39*74ab8aa2SJoseph Chen 	int i;
40*74ab8aa2SJoseph Chen 
41faa7eb0fSJoseph Chen 	const char *esr_bits_ec[] = {
42*74ab8aa2SJoseph Chen 		[0]  = "an unknown reason",
43*74ab8aa2SJoseph Chen 		[1]  = "a WFI or WFE instruction",
44*74ab8aa2SJoseph Chen 		[3]  = "an MCR or MRC access",
45*74ab8aa2SJoseph Chen 		[4]  = "an MCRR or MRRC access",
46*74ab8aa2SJoseph Chen 		[5]  = "an MCR or MRC access",
47*74ab8aa2SJoseph Chen 		[6]  = "an LDC or STC access to CP14",
48*74ab8aa2SJoseph Chen 		[7]  = "an access to an Advanced SIMD or floating-point register, resulting from CPACR_EL1.FPEN or CPTR_ELx.TFP",
49*74ab8aa2SJoseph Chen 		[8]  = "an MCR or MRC access",
50*74ab8aa2SJoseph Chen 		[12] = "an MCRR or MRRC access",
51*74ab8aa2SJoseph Chen 		[14] = "an Illegal execution state, or a PC or SP alignment fault",
52*74ab8aa2SJoseph Chen 		[10] = "HVC or SVC instruction execution",
53*74ab8aa2SJoseph Chen 		[18] = "HVC or SVC instruction execution",
54*74ab8aa2SJoseph Chen 		[19] = "SMC instruction execution in AArch32 state",
55*74ab8aa2SJoseph Chen 		[21] = "HVC or SVC instruction execution",
56*74ab8aa2SJoseph Chen 		[22] = "HVC or SVC instruction execution",
57*74ab8aa2SJoseph Chen 		[23] = "SMC instruction execution in AArch64 state",
58*74ab8aa2SJoseph Chen 		[24] = "MSR, MRS, or System instruction execution in AArch64 state",
59*74ab8aa2SJoseph Chen 		[31] = "IMPLEMENTATION DEFINED exception to EL3",
60*74ab8aa2SJoseph Chen 		[32] = "an Instruction abort",
61*74ab8aa2SJoseph Chen 		[33] = "an Instruction abort",
62*74ab8aa2SJoseph Chen 		[34] = "an Illegal execution state, or a PC or SP alignment fault",
63*74ab8aa2SJoseph Chen 		[36] = "a Data abort, from lower exception level",
64*74ab8aa2SJoseph Chen 		[37] = "a Data abort, from current exception level",
65*74ab8aa2SJoseph Chen 		[38] = "an Illegal execution state, or a PC or SP alignment fault",
66*74ab8aa2SJoseph Chen 		[40] = "a trapped Floating-point exception",
67*74ab8aa2SJoseph Chen 		[44] = "a trapped Floating-point exception",
68*74ab8aa2SJoseph Chen 		[47] = "SError interrupt",
69*74ab8aa2SJoseph Chen 		[48] = "a Breakpoint or Vector Catch debug event",
70*74ab8aa2SJoseph Chen 		[49] = "a Breakpoint or Vector Catch debug event",
71*74ab8aa2SJoseph Chen 		[50] = "a Software Step debug event",
72*74ab8aa2SJoseph Chen 		[51] = "a Software Step debug event",
73*74ab8aa2SJoseph Chen 		[52] = "a Watchpoint debug event",
74*74ab8aa2SJoseph Chen 		[53] = "a Watchpoint debug event",
75*74ab8aa2SJoseph Chen 		[56] = "execution of a Software Breakpoint instructio",
76faa7eb0fSJoseph Chen 	};
77faa7eb0fSJoseph Chen 
78*74ab8aa2SJoseph Chen 	printf("\n");
79faa7eb0fSJoseph Chen 
80*74ab8aa2SJoseph Chen 	/* PC/LR/SP ... */
81*74ab8aa2SJoseph Chen 	printf("* Reason:        Exception from %s\n", esr_bits_ec[REG_BITS(regs->esr, 26, 0x3f)]);
82faa7eb0fSJoseph Chen 	if (gd->flags & GD_FLG_RELOC) {
83*74ab8aa2SJoseph Chen 		printf("* PC         =   %016lx\n", regs->elr - gd->reloc_off);
84faa7eb0fSJoseph Chen 		printf("* LR         =   %016lx\n", regs->regs[30] - gd->reloc_off);
85faa7eb0fSJoseph Chen 	} else {
86faa7eb0fSJoseph Chen 		printf("* ELR(PC)    =   %016lx\n", regs->elr);
87faa7eb0fSJoseph Chen 		printf("* LR         =   %016lx\n", regs->regs[30]);
88faa7eb0fSJoseph Chen 	}
89faa7eb0fSJoseph Chen 	printf("* SP         =   %016lx\n", regs->sp);
90faa7eb0fSJoseph Chen 	printf("* ESR_EL%d    =   %016lx\n", el, regs->esr);
91*74ab8aa2SJoseph Chen 	printf("* Reloc Off  =   %016lx\n\n", gd->reloc_off);
92faa7eb0fSJoseph Chen 
93*74ab8aa2SJoseph Chen 	/* CPU */
94faa7eb0fSJoseph Chen 	for (i = 0; i < 29; i += 2)
95faa7eb0fSJoseph Chen 		printf("x%-2d: %016lx x%-2d: %016lx\n",
96faa7eb0fSJoseph Chen 		       i, regs->regs[i], i+1, regs->regs[i+1]);
97faa7eb0fSJoseph Chen 	printf("\n");
9824cd8f36SJoseph Chen 
99*74ab8aa2SJoseph Chen 	/* SoC */
10024cd8f36SJoseph Chen #ifdef CONFIG_ROCKCHIP_CRASH_DUMP
10124cd8f36SJoseph Chen 	iomem_show_by_compatible("-cru", 0, 0x400);
10224cd8f36SJoseph Chen 	iomem_show_by_compatible("-pmucru", 0, 0x400);
10324cd8f36SJoseph Chen 	iomem_show_by_compatible("-grf", 0, 0x400);
10424cd8f36SJoseph Chen 	iomem_show_by_compatible("-pmugrf", 0, 0x400);
10524cd8f36SJoseph Chen #endif
106*74ab8aa2SJoseph Chen 	/* Call trace */
107d554a7b2SJoseph Chen 	dump_core_stack(regs);
108faa7eb0fSJoseph Chen }
109faa7eb0fSJoseph Chen 
110faa7eb0fSJoseph Chen #else
1110ae76531SDavid Feng void show_regs(struct pt_regs *regs)
1120ae76531SDavid Feng {
1130ae76531SDavid Feng 	int i;
1140ae76531SDavid Feng 
1155e076729SPeng Fan 	if (gd->flags & GD_FLG_RELOC) {
1165e076729SPeng Fan 		printf("ELR:     %lx\n", regs->elr - gd->reloc_off);
1175e076729SPeng Fan 		printf("LR:      %lx\n", regs->regs[30] - gd->reloc_off);
1185e076729SPeng Fan 	} else {
1190ae76531SDavid Feng 		printf("ELR:     %lx\n", regs->elr);
1200ae76531SDavid Feng 		printf("LR:      %lx\n", regs->regs[30]);
1215e076729SPeng Fan 	}
1220ae76531SDavid Feng 	for (i = 0; i < 29; i += 2)
1230ae76531SDavid Feng 		printf("x%-2d: %016lx x%-2d: %016lx\n",
1240ae76531SDavid Feng 		       i, regs->regs[i], i+1, regs->regs[i+1]);
1250ae76531SDavid Feng 	printf("\n");
126d554a7b2SJoseph Chen 
127d554a7b2SJoseph Chen 	dump_core_stack(regs);
1280ae76531SDavid Feng }
129faa7eb0fSJoseph Chen #endif
1300ae76531SDavid Feng 
1310ae76531SDavid Feng /*
1320ae76531SDavid Feng  * do_bad_sync handles the impossible case in the Synchronous Abort vector.
1330ae76531SDavid Feng  */
1340ae76531SDavid Feng void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
1350ae76531SDavid Feng {
13664982915SAlexander Graf 	efi_restore_gd();
1370ae76531SDavid Feng 	printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr);
1380ae76531SDavid Feng 	show_regs(pt_regs);
1390ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1400ae76531SDavid Feng }
1410ae76531SDavid Feng 
1420ae76531SDavid Feng /*
1430ae76531SDavid Feng  * do_bad_irq handles the impossible case in the Irq vector.
1440ae76531SDavid Feng  */
1450ae76531SDavid Feng void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
1460ae76531SDavid Feng {
14764982915SAlexander Graf 	efi_restore_gd();
1480ae76531SDavid Feng 	printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr);
1490ae76531SDavid Feng 	show_regs(pt_regs);
1500ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1510ae76531SDavid Feng }
1520ae76531SDavid Feng 
1530ae76531SDavid Feng /*
1540ae76531SDavid Feng  * do_bad_fiq handles the impossible case in the Fiq vector.
1550ae76531SDavid Feng  */
1560ae76531SDavid Feng void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
1570ae76531SDavid Feng {
15864982915SAlexander Graf 	efi_restore_gd();
1590ae76531SDavid Feng 	printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr);
1600ae76531SDavid Feng 	show_regs(pt_regs);
1610ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1620ae76531SDavid Feng }
1630ae76531SDavid Feng 
1640ae76531SDavid Feng /*
1650ae76531SDavid Feng  * do_bad_error handles the impossible case in the Error vector.
1660ae76531SDavid Feng  */
1670ae76531SDavid Feng void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
1680ae76531SDavid Feng {
16964982915SAlexander Graf 	efi_restore_gd();
1700ae76531SDavid Feng 	printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr);
1710ae76531SDavid Feng 	show_regs(pt_regs);
1720ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1730ae76531SDavid Feng }
1740ae76531SDavid Feng 
1750ae76531SDavid Feng /*
1760ae76531SDavid Feng  * do_sync handles the Synchronous Abort exception.
1770ae76531SDavid Feng  */
1780ae76531SDavid Feng void do_sync(struct pt_regs *pt_regs, unsigned int esr)
1790ae76531SDavid Feng {
18064982915SAlexander Graf 	efi_restore_gd();
1810ae76531SDavid Feng 	printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr);
1820ae76531SDavid Feng 	show_regs(pt_regs);
1830ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1840ae76531SDavid Feng }
1850ae76531SDavid Feng 
186f4fc5f8dSKever Yang #if defined(CONFIG_SPL_BUILD) || !defined(CONFIG_IRQ)
1870ae76531SDavid Feng /*
1880ae76531SDavid Feng  * do_irq handles the Irq exception.
1890ae76531SDavid Feng  */
1900ae76531SDavid Feng void do_irq(struct pt_regs *pt_regs, unsigned int esr)
1910ae76531SDavid Feng {
19264982915SAlexander Graf 	efi_restore_gd();
1930ae76531SDavid Feng 	printf("\"Irq\" handler, esr 0x%08x\n", esr);
1940ae76531SDavid Feng 	show_regs(pt_regs);
1950ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1960ae76531SDavid Feng }
197fa40f8a0SJoseph Chen #endif
1980ae76531SDavid Feng 
1990ae76531SDavid Feng /*
2000ae76531SDavid Feng  * do_fiq handles the Fiq exception.
2010ae76531SDavid Feng  */
2020ae76531SDavid Feng void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
2030ae76531SDavid Feng {
20464982915SAlexander Graf 	efi_restore_gd();
2050ae76531SDavid Feng 	printf("\"Fiq\" handler, esr 0x%08x\n", esr);
2060ae76531SDavid Feng 	show_regs(pt_regs);
2070ae76531SDavid Feng 	panic("Resetting CPU ...\n");
2080ae76531SDavid Feng }
2090ae76531SDavid Feng 
2100ae76531SDavid Feng /*
2110ae76531SDavid Feng  * do_error handles the Error exception.
2120ae76531SDavid Feng  * Errors are more likely to be processor specific,
2130ae76531SDavid Feng  * it is defined with weak attribute and can be redefined
2140ae76531SDavid Feng  * in processor specific code.
2150ae76531SDavid Feng  */
2160ae76531SDavid Feng void __weak do_error(struct pt_regs *pt_regs, unsigned int esr)
2170ae76531SDavid Feng {
21864982915SAlexander Graf 	efi_restore_gd();
2190ae76531SDavid Feng 	printf("\"Error\" handler, esr 0x%08x\n", esr);
2200ae76531SDavid Feng 	show_regs(pt_regs);
2210ae76531SDavid Feng 	panic("Resetting CPU ...\n");
2220ae76531SDavid Feng }
223