1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2013-2014 Synopsys, Inc. All rights reserved.
4 */
5
6#include <irq_func.h>
7#include <vsprintf.h>
8#include <asm/arcregs.h>
9#include <asm/ptrace.h>
10
11/* Bit values in STATUS32 */
12#define E1_MASK		(1 << 1)	/* Level 1 interrupts enable */
13#define E2_MASK		(1 << 2)	/* Level 2 interrupts enable */
14
15int interrupt_init(void)
16{
17	return 0;
18}
19
20/*
21 * returns true if interrupts had been enabled before we disabled them
22 */
23int disable_interrupts(void)
24{
25	int status = read_aux_reg(ARC_AUX_STATUS32);
26	int state = (status & (E1_MASK | E2_MASK)) ? 1 : 0;
27
28	status &= ~(E1_MASK | E2_MASK);
29	/* STATUS32 register is updated indirectly with "FLAG" instruction */
30	__asm__("flag %0" : : "r" (status));
31	return state;
32}
33
34void enable_interrupts(void)
35{
36	unsigned int status = read_aux_reg(ARC_AUX_STATUS32);
37
38	status |= E1_MASK | E2_MASK;
39	/* STATUS32 register is updated indirectly with "FLAG" instruction */
40	__asm__("flag %0" : : "r" (status));
41}
42
43static void print_reg_file(long *reg_rev, int start_num)
44{
45	unsigned int i;
46
47	/* Print 3 registers per line */
48	for (i = start_num; i < start_num + 25; i++) {
49		printf("r%02u: 0x%08lx\t", i, (unsigned long)*reg_rev);
50		if (((i + 1) % 3) == 0)
51			printf("\n");
52
53		/* Because pt_regs has registers reversed */
54		reg_rev--;
55	}
56
57	/* Add new-line if none was inserted in the end of loop above */
58	if (((i + 1) % 3) != 0)
59		printf("\n");
60}
61
62void show_regs(struct pt_regs *regs)
63{
64	printf("ECR:\t0x%08lx\n", regs->ecr);
65	printf("RET:\t0x%08lx\nBLINK:\t0x%08lx\nSTAT32:\t0x%08lx\n",
66	       regs->ret, regs->blink, regs->status32);
67	printf("GP: 0x%08lx\t r25: 0x%08lx\t\n", regs->r26, regs->r25);
68	printf("BTA: 0x%08lx\t SP: 0x%08lx\t FP: 0x%08lx\n", regs->bta,
69	       regs->sp, regs->fp);
70	printf("LPS: 0x%08lx\tLPE: 0x%08lx\tLPC: 0x%08lx\n", regs->lp_start,
71	       regs->lp_end, regs->lp_count);
72
73	print_reg_file(&(regs->r0), 0);
74}
75
76void bad_mode(struct pt_regs *regs)
77{
78	if (regs)
79		show_regs(regs);
80
81	panic("Resetting CPU ...\n");
82}
83
84void do_memory_error(unsigned long address, struct pt_regs *regs)
85{
86	printf("Memory error exception @ 0x%lx\n", address);
87	bad_mode(regs);
88}
89
90void do_instruction_error(unsigned long address, struct pt_regs *regs)
91{
92	printf("Instruction error exception @ 0x%lx\n", address);
93	bad_mode(regs);
94}
95
96void do_machine_check_fault(unsigned long address, struct pt_regs *regs)
97{
98	printf("Machine check exception @ 0x%lx\n", address);
99	bad_mode(regs);
100}
101
102void do_interrupt_handler(void)
103{
104	printf("Interrupt fired\n");
105	bad_mode(0);
106}
107
108void do_itlb_miss(struct pt_regs *regs)
109{
110	printf("I TLB miss exception\n");
111	bad_mode(regs);
112}
113
114void do_dtlb_miss(struct pt_regs *regs)
115{
116	printf("D TLB miss exception\n");
117	bad_mode(regs);
118}
119
120void do_tlb_prot_violation(unsigned long address, struct pt_regs *regs)
121{
122	printf("TLB protection violation or misaligned access @ 0x%lx\n",
123	       address);
124	bad_mode(regs);
125}
126
127void do_privilege_violation(struct pt_regs *regs)
128{
129	printf("Privilege violation exception\n");
130	bad_mode(regs);
131}
132
133void do_trap(struct pt_regs *regs)
134{
135	printf("Trap exception\n");
136	bad_mode(regs);
137}
138
139void do_extension(struct pt_regs *regs)
140{
141	printf("Extension instruction exception\n");
142	bad_mode(regs);
143}
144
145#ifdef CONFIG_ISA_ARCV2
146void do_swi(struct pt_regs *regs)
147{
148	printf("Software Interrupt exception\n");
149	bad_mode(regs);
150}
151
152void do_divzero(unsigned long address, struct pt_regs *regs)
153{
154	printf("Division by zero exception @ 0x%lx\n", address);
155	bad_mode(regs);
156}
157
158void do_dcerror(struct pt_regs *regs)
159{
160	printf("Data cache consistency error exception\n");
161	bad_mode(regs);
162}
163
164void do_maligned(unsigned long address, struct pt_regs *regs)
165{
166	printf("Misaligned data access exception @ 0x%lx\n", address);
167	bad_mode(regs);
168}
169#endif
170