1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2016-17 Microsemi Corporation.
4  * Padmarao Begari, Microsemi Corporation <padmarao.begari@microsemi.com>
5  *
6  * Copyright (C) 2017 Andes Technology Corporation
7  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
8  *
9  * Copyright (C) 2019 Sean Anderson <seanga2@gmail.com>
10  */
11 
12 #include <common.h>
13 #include <efi_loader.h>
14 #include <hang.h>
15 #include <irq_func.h>
16 #include <asm/global_data.h>
17 #include <asm/ptrace.h>
18 #include <asm/system.h>
19 #include <asm/encoding.h>
20 
21 DECLARE_GLOBAL_DATA_PTR;
22 
show_efi_loaded_images(uintptr_t epc)23 static void show_efi_loaded_images(uintptr_t epc)
24 {
25 	efi_print_image_infos((void *)epc);
26 }
27 
show_regs(struct pt_regs * regs)28 static void show_regs(struct pt_regs *regs)
29 {
30 #ifdef CONFIG_SHOW_REGS
31 	printf("\nSP:  " REG_FMT " GP:  " REG_FMT " TP:  " REG_FMT "\n",
32 	       regs->sp, regs->gp, regs->tp);
33 	printf("T0:  " REG_FMT " T1:  " REG_FMT " T2:  " REG_FMT "\n",
34 	       regs->t0, regs->t1, regs->t2);
35 	printf("S0:  " REG_FMT " S1:  " REG_FMT " A0:  " REG_FMT "\n",
36 	       regs->s0, regs->s1, regs->a0);
37 	printf("A1:  " REG_FMT " A2:  " REG_FMT " A3:  " REG_FMT "\n",
38 	       regs->a1, regs->a2, regs->a3);
39 	printf("A4:  " REG_FMT " A5:  " REG_FMT " A6:  " REG_FMT "\n",
40 	       regs->a4, regs->a5, regs->a6);
41 	printf("A7:  " REG_FMT " S2:  " REG_FMT " S3:  " REG_FMT "\n",
42 	       regs->a7, regs->s2, regs->s3);
43 	printf("S4:  " REG_FMT " S5:  " REG_FMT " S6:  " REG_FMT "\n",
44 	       regs->s4, regs->s5, regs->s6);
45 	printf("S7:  " REG_FMT " S8:  " REG_FMT " S9:  " REG_FMT "\n",
46 	       regs->s7, regs->s8, regs->s9);
47 	printf("S10: " REG_FMT " S11: " REG_FMT " T3:  " REG_FMT "\n",
48 	       regs->s10, regs->s11, regs->t3);
49 	printf("T4:  " REG_FMT " T5:  " REG_FMT " T6:  " REG_FMT "\n",
50 	       regs->t4, regs->t5, regs->t6);
51 #endif
52 }
53 
_exit_trap(ulong code,ulong epc,ulong tval,struct pt_regs * regs)54 static void _exit_trap(ulong code, ulong epc, ulong tval, struct pt_regs *regs)
55 {
56 	static const char * const exception_code[] = {
57 		"Instruction address misaligned",
58 		"Instruction access fault",
59 		"Illegal instruction",
60 		"Breakpoint",
61 		"Load address misaligned",
62 		"Load access fault",
63 		"Store/AMO address misaligned",
64 		"Store/AMO access fault",
65 		"Environment call from U-mode",
66 		"Environment call from S-mode",
67 		"Reserved",
68 		"Environment call from M-mode",
69 		"Instruction page fault",
70 		"Load page fault",
71 		"Reserved",
72 		"Store/AMO page fault",
73 	};
74 
75 	if (code < ARRAY_SIZE(exception_code))
76 		printf("Unhandled exception: %s\n", exception_code[code]);
77 	else
78 		printf("Unhandled exception code: %ld\n", code);
79 
80 	printf("EPC: " REG_FMT " RA: " REG_FMT " TVAL: " REG_FMT "\n",
81 	       epc, regs->ra, tval);
82 	/* Print relocation adjustments, but only if gd is initialized */
83 	if (gd && gd->flags & GD_FLG_RELOC)
84 		printf("EPC: " REG_FMT " RA: " REG_FMT " reloc adjusted\n",
85 		       epc - gd->reloc_off, regs->ra - gd->reloc_off);
86 
87 	show_regs(regs);
88 	show_efi_loaded_images(epc);
89 	panic("\n");
90 }
91 
interrupt_init(void)92 int interrupt_init(void)
93 {
94 	return 0;
95 }
96 
97 /*
98  * enable interrupts
99  */
enable_interrupts(void)100 void enable_interrupts(void)
101 {
102 }
103 
104 /*
105  * disable interrupts
106  */
disable_interrupts(void)107 int disable_interrupts(void)
108 {
109 	return 0;
110 }
111 
handle_trap(ulong cause,ulong epc,ulong tval,struct pt_regs * regs)112 ulong handle_trap(ulong cause, ulong epc, ulong tval, struct pt_regs *regs)
113 {
114 	ulong is_irq, irq;
115 
116 	/* An UEFI application may have changed gd. Restore U-Boot's gd. */
117 	efi_restore_gd();
118 
119 	is_irq = (cause & MCAUSE_INT);
120 	irq = (cause & ~MCAUSE_INT);
121 
122 	if (is_irq) {
123 		switch (irq) {
124 		case IRQ_M_EXT:
125 		case IRQ_S_EXT:
126 			external_interrupt(0);	/* handle external interrupt */
127 			break;
128 		case IRQ_M_TIMER:
129 		case IRQ_S_TIMER:
130 			timer_interrupt(0);	/* handle timer interrupt */
131 			break;
132 		default:
133 			_exit_trap(cause, epc, tval, regs);
134 			break;
135 		};
136 	} else {
137 		_exit_trap(cause, epc, tval, regs);
138 	}
139 
140 	return epc;
141 }
142 
143 /*
144  *Entry Point for PLIC Interrupt Handler
145  */
external_interrupt(struct pt_regs * regs)146 __attribute__((weak)) void external_interrupt(struct pt_regs *regs)
147 {
148 }
149 
timer_interrupt(struct pt_regs * regs)150 __attribute__((weak)) void timer_interrupt(struct pt_regs *regs)
151 {
152 }
153