xref: /rk3399_rockchip-uboot/arch/arm/lib/interrupts_64.c (revision 7cef79185b7a019281d828de6ba3f6fbcec95d45)
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;
153fe16d46SJoseph Chen 
16*7cef7918SJoseph Chen #if !CONFIG_IS_ENABLED(IRQ)
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 #define REG_BITS(val, shift, mask)	(((val) >> (shift)) & (mask))
34faa7eb0fSJoseph Chen 
35*7cef7918SJoseph Chen #ifndef CONFIG_SPL_BUILD
36faa7eb0fSJoseph Chen void show_regs(struct pt_regs *regs)
37faa7eb0fSJoseph Chen {
38faa7eb0fSJoseph Chen 	int el = current_el();
3974ab8aa2SJoseph Chen 	int i;
4074ab8aa2SJoseph Chen 
41faa7eb0fSJoseph Chen 	const char *esr_bits_ec[] = {
4274ab8aa2SJoseph Chen 		[0]  = "an unknown reason",
4374ab8aa2SJoseph Chen 		[1]  = "a WFI or WFE instruction",
4474ab8aa2SJoseph Chen 		[3]  = "an MCR or MRC access",
4574ab8aa2SJoseph Chen 		[4]  = "an MCRR or MRRC access",
4674ab8aa2SJoseph Chen 		[5]  = "an MCR or MRC access",
4774ab8aa2SJoseph Chen 		[6]  = "an LDC or STC access to CP14",
4874ab8aa2SJoseph Chen 		[7]  = "an access to an Advanced SIMD or floating-point register, resulting from CPACR_EL1.FPEN or CPTR_ELx.TFP",
4974ab8aa2SJoseph Chen 		[8]  = "an MCR or MRC access",
5074ab8aa2SJoseph Chen 		[12] = "an MCRR or MRRC access",
5174ab8aa2SJoseph Chen 		[14] = "an Illegal execution state, or a PC or SP alignment fault",
5274ab8aa2SJoseph Chen 		[10] = "HVC or SVC instruction execution",
5374ab8aa2SJoseph Chen 		[18] = "HVC or SVC instruction execution",
5474ab8aa2SJoseph Chen 		[19] = "SMC instruction execution in AArch32 state",
5574ab8aa2SJoseph Chen 		[21] = "HVC or SVC instruction execution",
5674ab8aa2SJoseph Chen 		[22] = "HVC or SVC instruction execution",
5774ab8aa2SJoseph Chen 		[23] = "SMC instruction execution in AArch64 state",
5874ab8aa2SJoseph Chen 		[24] = "MSR, MRS, or System instruction execution in AArch64 state",
5974ab8aa2SJoseph Chen 		[31] = "IMPLEMENTATION DEFINED exception to EL3",
6074ab8aa2SJoseph Chen 		[32] = "an Instruction abort",
6174ab8aa2SJoseph Chen 		[33] = "an Instruction abort",
6274ab8aa2SJoseph Chen 		[34] = "an Illegal execution state, or a PC or SP alignment fault",
6374ab8aa2SJoseph Chen 		[36] = "a Data abort, from lower exception level",
6474ab8aa2SJoseph Chen 		[37] = "a Data abort, from current exception level",
6574ab8aa2SJoseph Chen 		[38] = "an Illegal execution state, or a PC or SP alignment fault",
6674ab8aa2SJoseph Chen 		[40] = "a trapped Floating-point exception",
6774ab8aa2SJoseph Chen 		[44] = "a trapped Floating-point exception",
6874ab8aa2SJoseph Chen 		[47] = "SError interrupt",
6974ab8aa2SJoseph Chen 		[48] = "a Breakpoint or Vector Catch debug event",
7074ab8aa2SJoseph Chen 		[49] = "a Breakpoint or Vector Catch debug event",
7174ab8aa2SJoseph Chen 		[50] = "a Software Step debug event",
7274ab8aa2SJoseph Chen 		[51] = "a Software Step debug event",
7374ab8aa2SJoseph Chen 		[52] = "a Watchpoint debug event",
7474ab8aa2SJoseph Chen 		[53] = "a Watchpoint debug event",
7574ab8aa2SJoseph Chen 		[56] = "execution of a Software Breakpoint instructio",
76faa7eb0fSJoseph Chen 	};
77faa7eb0fSJoseph Chen 
7874ab8aa2SJoseph Chen 	printf("\n");
79faa7eb0fSJoseph Chen 
8074ab8aa2SJoseph Chen 	/* PC/LR/SP ... */
8174ab8aa2SJoseph Chen 	printf("* Reason:        Exception from %s\n", esr_bits_ec[REG_BITS(regs->esr, 26, 0x3f)]);
82faa7eb0fSJoseph Chen 	if (gd->flags & GD_FLG_RELOC) {
8374ab8aa2SJoseph 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);
9174ab8aa2SJoseph Chen 	printf("* Reloc Off  =   %016lx\n\n", gd->reloc_off);
92faa7eb0fSJoseph Chen 
9374ab8aa2SJoseph 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 
9974ab8aa2SJoseph 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
10674ab8aa2SJoseph 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 	}
1223fe16d46SJoseph Chen 
1233fe16d46SJoseph Chen 	printf("ESR:     %lx (ec=%ld)\n", regs->esr, REG_BITS(regs->esr, 26, 0x3f));
1243fe16d46SJoseph Chen 
1250ae76531SDavid Feng 	for (i = 0; i < 29; i += 2)
1260ae76531SDavid Feng 		printf("x%-2d: %016lx x%-2d: %016lx\n",
1270ae76531SDavid Feng 		       i, regs->regs[i], i+1, regs->regs[i+1]);
1280ae76531SDavid Feng 	printf("\n");
129d554a7b2SJoseph Chen 
130d554a7b2SJoseph Chen 	dump_core_stack(regs);
1310ae76531SDavid Feng }
132faa7eb0fSJoseph Chen #endif
1330ae76531SDavid Feng 
1340ae76531SDavid Feng /*
1350ae76531SDavid Feng  * do_bad_sync handles the impossible case in the Synchronous Abort vector.
1360ae76531SDavid Feng  */
1370ae76531SDavid Feng void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
1380ae76531SDavid Feng {
13964982915SAlexander Graf 	efi_restore_gd();
1400ae76531SDavid Feng 	printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr);
1410ae76531SDavid Feng 	show_regs(pt_regs);
1420ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1430ae76531SDavid Feng }
1440ae76531SDavid Feng 
1450ae76531SDavid Feng /*
1460ae76531SDavid Feng  * do_bad_irq handles the impossible case in the Irq vector.
1470ae76531SDavid Feng  */
1480ae76531SDavid Feng void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
1490ae76531SDavid Feng {
15064982915SAlexander Graf 	efi_restore_gd();
1510ae76531SDavid Feng 	printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr);
1520ae76531SDavid Feng 	show_regs(pt_regs);
1530ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1540ae76531SDavid Feng }
1550ae76531SDavid Feng 
1560ae76531SDavid Feng /*
1570ae76531SDavid Feng  * do_bad_fiq handles the impossible case in the Fiq vector.
1580ae76531SDavid Feng  */
1590ae76531SDavid Feng void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
1600ae76531SDavid Feng {
16164982915SAlexander Graf 	efi_restore_gd();
1620ae76531SDavid Feng 	printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr);
1630ae76531SDavid Feng 	show_regs(pt_regs);
1640ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1650ae76531SDavid Feng }
1660ae76531SDavid Feng 
1670ae76531SDavid Feng /*
1680ae76531SDavid Feng  * do_bad_error handles the impossible case in the Error vector.
1690ae76531SDavid Feng  */
1700ae76531SDavid Feng void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
1710ae76531SDavid Feng {
17264982915SAlexander Graf 	efi_restore_gd();
1730ae76531SDavid Feng 	printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr);
1740ae76531SDavid Feng 	show_regs(pt_regs);
1750ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1760ae76531SDavid Feng }
1770ae76531SDavid Feng 
1780ae76531SDavid Feng /*
1790ae76531SDavid Feng  * do_sync handles the Synchronous Abort exception.
1800ae76531SDavid Feng  */
1810ae76531SDavid Feng void do_sync(struct pt_regs *pt_regs, unsigned int esr)
1820ae76531SDavid Feng {
18364982915SAlexander Graf 	efi_restore_gd();
1840ae76531SDavid Feng 	printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr);
1850ae76531SDavid Feng 	show_regs(pt_regs);
1860ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1870ae76531SDavid Feng }
1880ae76531SDavid Feng 
189*7cef7918SJoseph Chen #if !CONFIG_IS_ENABLED(IRQ)
1900ae76531SDavid Feng /*
1910ae76531SDavid Feng  * do_irq handles the Irq exception.
1920ae76531SDavid Feng  */
1930ae76531SDavid Feng void do_irq(struct pt_regs *pt_regs, unsigned int esr)
1940ae76531SDavid Feng {
19564982915SAlexander Graf 	efi_restore_gd();
1960ae76531SDavid Feng 	printf("\"Irq\" handler, esr 0x%08x\n", esr);
1970ae76531SDavid Feng 	show_regs(pt_regs);
1980ae76531SDavid Feng 	panic("Resetting CPU ...\n");
1990ae76531SDavid Feng }
200fa40f8a0SJoseph Chen #endif
2010ae76531SDavid Feng 
2020ae76531SDavid Feng /*
2030ae76531SDavid Feng  * do_fiq handles the Fiq exception.
2040ae76531SDavid Feng  */
2050ae76531SDavid Feng void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
2060ae76531SDavid Feng {
20764982915SAlexander Graf 	efi_restore_gd();
2080ae76531SDavid Feng 	printf("\"Fiq\" handler, esr 0x%08x\n", esr);
2090ae76531SDavid Feng 	show_regs(pt_regs);
2100ae76531SDavid Feng 	panic("Resetting CPU ...\n");
2110ae76531SDavid Feng }
2120ae76531SDavid Feng 
2130ae76531SDavid Feng /*
2140ae76531SDavid Feng  * do_error handles the Error exception.
2150ae76531SDavid Feng  * Errors are more likely to be processor specific,
2160ae76531SDavid Feng  * it is defined with weak attribute and can be redefined
2170ae76531SDavid Feng  * in processor specific code.
2180ae76531SDavid Feng  */
2190ae76531SDavid Feng void __weak do_error(struct pt_regs *pt_regs, unsigned int esr)
2200ae76531SDavid Feng {
22164982915SAlexander Graf 	efi_restore_gd();
2220ae76531SDavid Feng 	printf("\"Error\" handler, esr 0x%08x\n", esr);
2230ae76531SDavid Feng 	show_regs(pt_regs);
2240ae76531SDavid Feng 	panic("Resetting CPU ...\n");
2250ae76531SDavid Feng }
226