xref: /rk3399_rockchip-uboot/arch/arm/lib/interrupts_64.c (revision 4905c8342ef717d3e44c63d4b745e4b0490cafe9)
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>
13*4905c834SHuibin Hong #ifdef CONFIG_ROCKCHIP_MINIDUMP
14*4905c834SHuibin Hong #include <rk_mini_dump.h>
15*4905c834SHuibin Hong #endif
160ae76531SDavid Feng 
175e076729SPeng Fan DECLARE_GLOBAL_DATA_PTR;
183fe16d46SJoseph Chen 
197cef7918SJoseph Chen #if !CONFIG_IS_ENABLED(IRQ)
interrupt_init(void)200ae76531SDavid Feng int interrupt_init(void)
210ae76531SDavid Feng {
220ae76531SDavid Feng 	return 0;
230ae76531SDavid Feng }
240ae76531SDavid Feng 
enable_interrupts(void)250ae76531SDavid Feng void enable_interrupts(void)
260ae76531SDavid Feng {
270ae76531SDavid Feng 	return;
280ae76531SDavid Feng }
290ae76531SDavid Feng 
disable_interrupts(void)300ae76531SDavid Feng int disable_interrupts(void)
310ae76531SDavid Feng {
320ae76531SDavid Feng 	return 0;
330ae76531SDavid Feng }
34fa40f8a0SJoseph Chen #endif
350ae76531SDavid Feng 
36faa7eb0fSJoseph Chen #define REG_BITS(val, shift, mask)	(((val) >> (shift)) & (mask))
37faa7eb0fSJoseph Chen 
387cef7918SJoseph Chen #ifndef CONFIG_SPL_BUILD
show_regs(struct pt_regs * regs)39faa7eb0fSJoseph Chen void show_regs(struct pt_regs *regs)
40faa7eb0fSJoseph Chen {
41faa7eb0fSJoseph Chen 	int el = current_el();
4274ab8aa2SJoseph Chen 	int i;
4374ab8aa2SJoseph Chen 
44faa7eb0fSJoseph Chen 	const char *esr_bits_ec[] = {
4574ab8aa2SJoseph Chen 		[0]  = "an unknown reason",
4674ab8aa2SJoseph Chen 		[1]  = "a WFI or WFE instruction",
4774ab8aa2SJoseph Chen 		[3]  = "an MCR or MRC access",
4874ab8aa2SJoseph Chen 		[4]  = "an MCRR or MRRC access",
4974ab8aa2SJoseph Chen 		[5]  = "an MCR or MRC access",
5074ab8aa2SJoseph Chen 		[6]  = "an LDC or STC access to CP14",
5174ab8aa2SJoseph Chen 		[7]  = "an access to an Advanced SIMD or floating-point register, resulting from CPACR_EL1.FPEN or CPTR_ELx.TFP",
5274ab8aa2SJoseph Chen 		[8]  = "an MCR or MRC access",
5374ab8aa2SJoseph Chen 		[12] = "an MCRR or MRRC access",
5474ab8aa2SJoseph Chen 		[14] = "an Illegal execution state, or a PC or SP alignment fault",
5574ab8aa2SJoseph Chen 		[10] = "HVC or SVC instruction execution",
5674ab8aa2SJoseph Chen 		[18] = "HVC or SVC instruction execution",
5774ab8aa2SJoseph Chen 		[19] = "SMC instruction execution in AArch32 state",
5874ab8aa2SJoseph Chen 		[21] = "HVC or SVC instruction execution",
5974ab8aa2SJoseph Chen 		[22] = "HVC or SVC instruction execution",
6074ab8aa2SJoseph Chen 		[23] = "SMC instruction execution in AArch64 state",
6174ab8aa2SJoseph Chen 		[24] = "MSR, MRS, or System instruction execution in AArch64 state",
6274ab8aa2SJoseph Chen 		[31] = "IMPLEMENTATION DEFINED exception to EL3",
6374ab8aa2SJoseph Chen 		[32] = "an Instruction abort",
6474ab8aa2SJoseph Chen 		[33] = "an Instruction abort",
6574ab8aa2SJoseph Chen 		[34] = "an Illegal execution state, or a PC or SP alignment fault",
6674ab8aa2SJoseph Chen 		[36] = "a Data abort, from lower exception level",
6774ab8aa2SJoseph Chen 		[37] = "a Data abort, from current exception level",
6874ab8aa2SJoseph Chen 		[38] = "an Illegal execution state, or a PC or SP alignment fault",
6974ab8aa2SJoseph Chen 		[40] = "a trapped Floating-point exception",
7074ab8aa2SJoseph Chen 		[44] = "a trapped Floating-point exception",
7174ab8aa2SJoseph Chen 		[47] = "SError interrupt",
7274ab8aa2SJoseph Chen 		[48] = "a Breakpoint or Vector Catch debug event",
7374ab8aa2SJoseph Chen 		[49] = "a Breakpoint or Vector Catch debug event",
7474ab8aa2SJoseph Chen 		[50] = "a Software Step debug event",
7574ab8aa2SJoseph Chen 		[51] = "a Software Step debug event",
7674ab8aa2SJoseph Chen 		[52] = "a Watchpoint debug event",
7774ab8aa2SJoseph Chen 		[53] = "a Watchpoint debug event",
7874ab8aa2SJoseph Chen 		[56] = "execution of a Software Breakpoint instructio",
79faa7eb0fSJoseph Chen 	};
80faa7eb0fSJoseph Chen 
8174ab8aa2SJoseph Chen 	printf("\n");
82faa7eb0fSJoseph Chen 
8374ab8aa2SJoseph Chen 	/* PC/LR/SP ... */
8474ab8aa2SJoseph Chen 	printf("* Reason:        Exception from %s\n", esr_bits_ec[REG_BITS(regs->esr, 26, 0x3f)]);
85faa7eb0fSJoseph Chen 	if (gd->flags & GD_FLG_RELOC) {
8674ab8aa2SJoseph Chen 		printf("* PC         =   %016lx\n", regs->elr - gd->reloc_off);
87faa7eb0fSJoseph Chen 		printf("* LR         =   %016lx\n", regs->regs[30] - gd->reloc_off);
88faa7eb0fSJoseph Chen 	} else {
89faa7eb0fSJoseph Chen 		printf("* ELR(PC)    =   %016lx\n", regs->elr);
90faa7eb0fSJoseph Chen 		printf("* LR         =   %016lx\n", regs->regs[30]);
91faa7eb0fSJoseph Chen 	}
92faa7eb0fSJoseph Chen 	printf("* SP         =   %016lx\n", regs->sp);
93faa7eb0fSJoseph Chen 	printf("* ESR_EL%d    =   %016lx\n", el, regs->esr);
9474ab8aa2SJoseph Chen 	printf("* Reloc Off  =   %016lx\n\n", gd->reloc_off);
95faa7eb0fSJoseph Chen 
9674ab8aa2SJoseph Chen 	/* CPU */
97faa7eb0fSJoseph Chen 	for (i = 0; i < 29; i += 2)
98faa7eb0fSJoseph Chen 		printf("x%-2d: %016lx x%-2d: %016lx\n",
99faa7eb0fSJoseph Chen 		       i, regs->regs[i], i+1, regs->regs[i+1]);
100faa7eb0fSJoseph Chen 	printf("\n");
10124cd8f36SJoseph Chen 
10274ab8aa2SJoseph Chen 	/* SoC */
10324cd8f36SJoseph Chen #ifdef CONFIG_ROCKCHIP_CRASH_DUMP
10424cd8f36SJoseph Chen 	iomem_show_by_compatible("-cru", 0, 0x400);
10524cd8f36SJoseph Chen 	iomem_show_by_compatible("-pmucru", 0, 0x400);
10624cd8f36SJoseph Chen 	iomem_show_by_compatible("-grf", 0, 0x400);
10724cd8f36SJoseph Chen 	iomem_show_by_compatible("-pmugrf", 0, 0x400);
10824cd8f36SJoseph Chen #endif
10974ab8aa2SJoseph Chen 	/* Call trace */
110d554a7b2SJoseph Chen 	dump_core_stack(regs);
111faa7eb0fSJoseph Chen }
112faa7eb0fSJoseph Chen 
113faa7eb0fSJoseph Chen #else
show_regs(struct pt_regs * regs)1140ae76531SDavid Feng void show_regs(struct pt_regs *regs)
1150ae76531SDavid Feng {
1160ae76531SDavid Feng 	int i;
1170ae76531SDavid Feng 
1185e076729SPeng Fan 	if (gd->flags & GD_FLG_RELOC) {
1195e076729SPeng Fan 		printf("ELR:     %lx\n", regs->elr - gd->reloc_off);
1205e076729SPeng Fan 		printf("LR:      %lx\n", regs->regs[30] - gd->reloc_off);
1215e076729SPeng Fan 	} else {
1220ae76531SDavid Feng 		printf("ELR:     %lx\n", regs->elr);
1230ae76531SDavid Feng 		printf("LR:      %lx\n", regs->regs[30]);
1245e076729SPeng Fan 	}
1253fe16d46SJoseph Chen 
1263fe16d46SJoseph Chen 	printf("ESR:     %lx (ec=%ld)\n", regs->esr, REG_BITS(regs->esr, 26, 0x3f));
1273fe16d46SJoseph Chen 
1280ae76531SDavid Feng 	for (i = 0; i < 29; i += 2)
1290ae76531SDavid Feng 		printf("x%-2d: %016lx x%-2d: %016lx\n",
1300ae76531SDavid Feng 		       i, regs->regs[i], i+1, regs->regs[i+1]);
1310ae76531SDavid Feng 	printf("\n");
132d554a7b2SJoseph Chen 
133d554a7b2SJoseph Chen 	dump_core_stack(regs);
1340ae76531SDavid Feng }
135faa7eb0fSJoseph Chen #endif
1360ae76531SDavid Feng 
1370ae76531SDavid Feng /*
1380ae76531SDavid Feng  * do_bad_sync handles the impossible case in the Synchronous Abort vector.
1390ae76531SDavid Feng  */
do_bad_sync(struct pt_regs * pt_regs,unsigned int esr)1400ae76531SDavid Feng void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
1410ae76531SDavid Feng {
14264982915SAlexander Graf 	efi_restore_gd();
1430ae76531SDavid Feng 	printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr);
1440ae76531SDavid Feng 	show_regs(pt_regs);
1450ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1460ae76531SDavid Feng }
1470ae76531SDavid Feng 
1480ae76531SDavid Feng /*
1490ae76531SDavid Feng  * do_bad_irq handles the impossible case in the Irq vector.
1500ae76531SDavid Feng  */
do_bad_irq(struct pt_regs * pt_regs,unsigned int esr)1510ae76531SDavid Feng void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
1520ae76531SDavid Feng {
15364982915SAlexander Graf 	efi_restore_gd();
1540ae76531SDavid Feng 	printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr);
1550ae76531SDavid Feng 	show_regs(pt_regs);
1560ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1570ae76531SDavid Feng }
1580ae76531SDavid Feng 
1590ae76531SDavid Feng /*
1600ae76531SDavid Feng  * do_bad_fiq handles the impossible case in the Fiq vector.
1610ae76531SDavid Feng  */
do_bad_fiq(struct pt_regs * pt_regs,unsigned int esr)1620ae76531SDavid Feng void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
1630ae76531SDavid Feng {
16464982915SAlexander Graf 	efi_restore_gd();
1650ae76531SDavid Feng 	printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr);
1660ae76531SDavid Feng 	show_regs(pt_regs);
1670ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1680ae76531SDavid Feng }
1690ae76531SDavid Feng 
1700ae76531SDavid Feng /*
1710ae76531SDavid Feng  * do_bad_error handles the impossible case in the Error vector.
1720ae76531SDavid Feng  */
do_bad_error(struct pt_regs * pt_regs,unsigned int esr)1730ae76531SDavid Feng void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
1740ae76531SDavid Feng {
17564982915SAlexander Graf 	efi_restore_gd();
1760ae76531SDavid Feng 	printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr);
1770ae76531SDavid Feng 	show_regs(pt_regs);
1780ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1790ae76531SDavid Feng }
1800ae76531SDavid Feng 
1810ae76531SDavid Feng /*
1820ae76531SDavid Feng  * do_sync handles the Synchronous Abort exception.
1830ae76531SDavid Feng  */
do_sync(struct pt_regs * pt_regs,unsigned int esr)1840ae76531SDavid Feng void do_sync(struct pt_regs *pt_regs, unsigned int esr)
1850ae76531SDavid Feng {
18664982915SAlexander Graf 	efi_restore_gd();
187*4905c834SHuibin Hong #ifdef CONFIG_ROCKCHIP_MINIDUMP
188*4905c834SHuibin Hong 	if (md_no_fault_handler(pt_regs, esr)) {
189*4905c834SHuibin Hong 		/* Return to next instruction */
190*4905c834SHuibin Hong 		pt_regs->elr += 4;
191*4905c834SHuibin Hong 		return;
192*4905c834SHuibin Hong 	}
193*4905c834SHuibin Hong #endif
1940ae76531SDavid Feng 	printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr);
1950ae76531SDavid Feng 	show_regs(pt_regs);
1960ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1970ae76531SDavid Feng }
1980ae76531SDavid Feng 
1997cef7918SJoseph Chen #if !CONFIG_IS_ENABLED(IRQ)
2000ae76531SDavid Feng /*
2010ae76531SDavid Feng  * do_irq handles the Irq exception.
2020ae76531SDavid Feng  */
do_irq(struct pt_regs * pt_regs,unsigned int esr)2030ae76531SDavid Feng void do_irq(struct pt_regs *pt_regs, unsigned int esr)
2040ae76531SDavid Feng {
20564982915SAlexander Graf 	efi_restore_gd();
2060ae76531SDavid Feng 	printf("\"Irq\" handler, esr 0x%08x\n", esr);
2070ae76531SDavid Feng 	show_regs(pt_regs);
2080ae76531SDavid Feng 	panic("Resetting CPU ...\n");
2090ae76531SDavid Feng }
210fa40f8a0SJoseph Chen #endif
2110ae76531SDavid Feng 
2120ae76531SDavid Feng /*
2130ae76531SDavid Feng  * do_fiq handles the Fiq exception.
2140ae76531SDavid Feng  */
do_fiq(struct pt_regs * pt_regs,unsigned int esr)2150ae76531SDavid Feng void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
2160ae76531SDavid Feng {
21764982915SAlexander Graf 	efi_restore_gd();
2180ae76531SDavid Feng 	printf("\"Fiq\" handler, esr 0x%08x\n", esr);
2190ae76531SDavid Feng 	show_regs(pt_regs);
2200ae76531SDavid Feng 	panic("Resetting CPU ...\n");
2210ae76531SDavid Feng }
2220ae76531SDavid Feng 
2230ae76531SDavid Feng /*
2240ae76531SDavid Feng  * do_error handles the Error exception.
2250ae76531SDavid Feng  * Errors are more likely to be processor specific,
2260ae76531SDavid Feng  * it is defined with weak attribute and can be redefined
2270ae76531SDavid Feng  * in processor specific code.
2280ae76531SDavid Feng  */
do_error(struct pt_regs * pt_regs,unsigned int esr)2290ae76531SDavid Feng void __weak do_error(struct pt_regs *pt_regs, unsigned int esr)
2300ae76531SDavid Feng {
23164982915SAlexander Graf 	efi_restore_gd();
232*4905c834SHuibin Hong #ifdef CONFIG_ROCKCHIP_MINIDUMP
233*4905c834SHuibin Hong 	if (md_no_fault_handler(pt_regs, esr)) {
234*4905c834SHuibin Hong 		/* Return to next instruction */
235*4905c834SHuibin Hong 		pt_regs->elr += 4;
236*4905c834SHuibin Hong 		return;
237*4905c834SHuibin Hong 	}
238*4905c834SHuibin Hong #endif
2390ae76531SDavid Feng 	printf("\"Error\" handler, esr 0x%08x\n", esr);
2400ae76531SDavid Feng 	show_regs(pt_regs);
2410ae76531SDavid Feng 	panic("Resetting CPU ...\n");
2420ae76531SDavid Feng }
243