xref: /rk3399_rockchip-uboot/arch/arm/lib/interrupts_64.c (revision 4905c8342ef717d3e44c63d4b745e4b0490cafe9)
1 /*
2  * (C) Copyright 2013
3  * David Feng <fenghua@phytium.com.cn>
4  *
5  * SPDX-License-Identifier:	GPL-2.0+
6  */
7 
8 #include <common.h>
9 #include <linux/compiler.h>
10 #include <efi_loader.h>
11 #include <iomem.h>
12 #include <stacktrace.h>
13 #ifdef CONFIG_ROCKCHIP_MINIDUMP
14 #include <rk_mini_dump.h>
15 #endif
16 
17 DECLARE_GLOBAL_DATA_PTR;
18 
19 #if !CONFIG_IS_ENABLED(IRQ)
interrupt_init(void)20 int interrupt_init(void)
21 {
22 	return 0;
23 }
24 
enable_interrupts(void)25 void enable_interrupts(void)
26 {
27 	return;
28 }
29 
disable_interrupts(void)30 int disable_interrupts(void)
31 {
32 	return 0;
33 }
34 #endif
35 
36 #define REG_BITS(val, shift, mask)	(((val) >> (shift)) & (mask))
37 
38 #ifndef CONFIG_SPL_BUILD
show_regs(struct pt_regs * regs)39 void show_regs(struct pt_regs *regs)
40 {
41 	int el = current_el();
42 	int i;
43 
44 	const char *esr_bits_ec[] = {
45 		[0]  = "an unknown reason",
46 		[1]  = "a WFI or WFE instruction",
47 		[3]  = "an MCR or MRC access",
48 		[4]  = "an MCRR or MRRC access",
49 		[5]  = "an MCR or MRC access",
50 		[6]  = "an LDC or STC access to CP14",
51 		[7]  = "an access to an Advanced SIMD or floating-point register, resulting from CPACR_EL1.FPEN or CPTR_ELx.TFP",
52 		[8]  = "an MCR or MRC access",
53 		[12] = "an MCRR or MRRC access",
54 		[14] = "an Illegal execution state, or a PC or SP alignment fault",
55 		[10] = "HVC or SVC instruction execution",
56 		[18] = "HVC or SVC instruction execution",
57 		[19] = "SMC instruction execution in AArch32 state",
58 		[21] = "HVC or SVC instruction execution",
59 		[22] = "HVC or SVC instruction execution",
60 		[23] = "SMC instruction execution in AArch64 state",
61 		[24] = "MSR, MRS, or System instruction execution in AArch64 state",
62 		[31] = "IMPLEMENTATION DEFINED exception to EL3",
63 		[32] = "an Instruction abort",
64 		[33] = "an Instruction abort",
65 		[34] = "an Illegal execution state, or a PC or SP alignment fault",
66 		[36] = "a Data abort, from lower exception level",
67 		[37] = "a Data abort, from current exception level",
68 		[38] = "an Illegal execution state, or a PC or SP alignment fault",
69 		[40] = "a trapped Floating-point exception",
70 		[44] = "a trapped Floating-point exception",
71 		[47] = "SError interrupt",
72 		[48] = "a Breakpoint or Vector Catch debug event",
73 		[49] = "a Breakpoint or Vector Catch debug event",
74 		[50] = "a Software Step debug event",
75 		[51] = "a Software Step debug event",
76 		[52] = "a Watchpoint debug event",
77 		[53] = "a Watchpoint debug event",
78 		[56] = "execution of a Software Breakpoint instructio",
79 	};
80 
81 	printf("\n");
82 
83 	/* PC/LR/SP ... */
84 	printf("* Reason:        Exception from %s\n", esr_bits_ec[REG_BITS(regs->esr, 26, 0x3f)]);
85 	if (gd->flags & GD_FLG_RELOC) {
86 		printf("* PC         =   %016lx\n", regs->elr - gd->reloc_off);
87 		printf("* LR         =   %016lx\n", regs->regs[30] - gd->reloc_off);
88 	} else {
89 		printf("* ELR(PC)    =   %016lx\n", regs->elr);
90 		printf("* LR         =   %016lx\n", regs->regs[30]);
91 	}
92 	printf("* SP         =   %016lx\n", regs->sp);
93 	printf("* ESR_EL%d    =   %016lx\n", el, regs->esr);
94 	printf("* Reloc Off  =   %016lx\n\n", gd->reloc_off);
95 
96 	/* CPU */
97 	for (i = 0; i < 29; i += 2)
98 		printf("x%-2d: %016lx x%-2d: %016lx\n",
99 		       i, regs->regs[i], i+1, regs->regs[i+1]);
100 	printf("\n");
101 
102 	/* SoC */
103 #ifdef CONFIG_ROCKCHIP_CRASH_DUMP
104 	iomem_show_by_compatible("-cru", 0, 0x400);
105 	iomem_show_by_compatible("-pmucru", 0, 0x400);
106 	iomem_show_by_compatible("-grf", 0, 0x400);
107 	iomem_show_by_compatible("-pmugrf", 0, 0x400);
108 #endif
109 	/* Call trace */
110 	dump_core_stack(regs);
111 }
112 
113 #else
show_regs(struct pt_regs * regs)114 void show_regs(struct pt_regs *regs)
115 {
116 	int i;
117 
118 	if (gd->flags & GD_FLG_RELOC) {
119 		printf("ELR:     %lx\n", regs->elr - gd->reloc_off);
120 		printf("LR:      %lx\n", regs->regs[30] - gd->reloc_off);
121 	} else {
122 		printf("ELR:     %lx\n", regs->elr);
123 		printf("LR:      %lx\n", regs->regs[30]);
124 	}
125 
126 	printf("ESR:     %lx (ec=%ld)\n", regs->esr, REG_BITS(regs->esr, 26, 0x3f));
127 
128 	for (i = 0; i < 29; i += 2)
129 		printf("x%-2d: %016lx x%-2d: %016lx\n",
130 		       i, regs->regs[i], i+1, regs->regs[i+1]);
131 	printf("\n");
132 
133 	dump_core_stack(regs);
134 }
135 #endif
136 
137 /*
138  * do_bad_sync handles the impossible case in the Synchronous Abort vector.
139  */
do_bad_sync(struct pt_regs * pt_regs,unsigned int esr)140 void do_bad_sync(struct pt_regs *pt_regs, unsigned int esr)
141 {
142 	efi_restore_gd();
143 	printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08x\n", esr);
144 	show_regs(pt_regs);
145 	panic("Resetting CPU ...\n");
146 }
147 
148 /*
149  * do_bad_irq handles the impossible case in the Irq vector.
150  */
do_bad_irq(struct pt_regs * pt_regs,unsigned int esr)151 void do_bad_irq(struct pt_regs *pt_regs, unsigned int esr)
152 {
153 	efi_restore_gd();
154 	printf("Bad mode in \"Irq\" handler, esr 0x%08x\n", esr);
155 	show_regs(pt_regs);
156 	panic("Resetting CPU ...\n");
157 }
158 
159 /*
160  * do_bad_fiq handles the impossible case in the Fiq vector.
161  */
do_bad_fiq(struct pt_regs * pt_regs,unsigned int esr)162 void do_bad_fiq(struct pt_regs *pt_regs, unsigned int esr)
163 {
164 	efi_restore_gd();
165 	printf("Bad mode in \"Fiq\" handler, esr 0x%08x\n", esr);
166 	show_regs(pt_regs);
167 	panic("Resetting CPU ...\n");
168 }
169 
170 /*
171  * do_bad_error handles the impossible case in the Error vector.
172  */
do_bad_error(struct pt_regs * pt_regs,unsigned int esr)173 void do_bad_error(struct pt_regs *pt_regs, unsigned int esr)
174 {
175 	efi_restore_gd();
176 	printf("Bad mode in \"Error\" handler, esr 0x%08x\n", esr);
177 	show_regs(pt_regs);
178 	panic("Resetting CPU ...\n");
179 }
180 
181 /*
182  * do_sync handles the Synchronous Abort exception.
183  */
do_sync(struct pt_regs * pt_regs,unsigned int esr)184 void do_sync(struct pt_regs *pt_regs, unsigned int esr)
185 {
186 	efi_restore_gd();
187 #ifdef CONFIG_ROCKCHIP_MINIDUMP
188 	if (md_no_fault_handler(pt_regs, esr)) {
189 		/* Return to next instruction */
190 		pt_regs->elr += 4;
191 		return;
192 	}
193 #endif
194 	printf("\"Synchronous Abort\" handler, esr 0x%08x\n", esr);
195 	show_regs(pt_regs);
196 	panic("Resetting CPU ...\n");
197 }
198 
199 #if !CONFIG_IS_ENABLED(IRQ)
200 /*
201  * do_irq handles the Irq exception.
202  */
do_irq(struct pt_regs * pt_regs,unsigned int esr)203 void do_irq(struct pt_regs *pt_regs, unsigned int esr)
204 {
205 	efi_restore_gd();
206 	printf("\"Irq\" handler, esr 0x%08x\n", esr);
207 	show_regs(pt_regs);
208 	panic("Resetting CPU ...\n");
209 }
210 #endif
211 
212 /*
213  * do_fiq handles the Fiq exception.
214  */
do_fiq(struct pt_regs * pt_regs,unsigned int esr)215 void do_fiq(struct pt_regs *pt_regs, unsigned int esr)
216 {
217 	efi_restore_gd();
218 	printf("\"Fiq\" handler, esr 0x%08x\n", esr);
219 	show_regs(pt_regs);
220 	panic("Resetting CPU ...\n");
221 }
222 
223 /*
224  * do_error handles the Error exception.
225  * Errors are more likely to be processor specific,
226  * it is defined with weak attribute and can be redefined
227  * in processor specific code.
228  */
do_error(struct pt_regs * pt_regs,unsigned int esr)229 void __weak do_error(struct pt_regs *pt_regs, unsigned int esr)
230 {
231 	efi_restore_gd();
232 #ifdef CONFIG_ROCKCHIP_MINIDUMP
233 	if (md_no_fault_handler(pt_regs, esr)) {
234 		/* Return to next instruction */
235 		pt_regs->elr += 4;
236 		return;
237 	}
238 #endif
239 	printf("\"Error\" handler, esr 0x%08x\n", esr);
240 	show_regs(pt_regs);
241 	panic("Resetting CPU ...\n");
242 }
243