diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/sgi-ip22/ip22-berr.c | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/sgi-ip22/ip22-berr.c')
-rw-r--r-- | arch/mips/sgi-ip22/ip22-berr.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/arch/mips/sgi-ip22/ip22-berr.c b/arch/mips/sgi-ip22/ip22-berr.c new file mode 100644 index 000000000..dc0110a60 --- /dev/null +++ b/arch/mips/sgi-ip22/ip22-berr.c | |||
@@ -0,0 +1,116 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * ip22-berr.c: Bus error handling. | ||
4 | * | ||
5 | * Copyright (C) 2002, 2003 Ladislav Michl (ladis@linux-mips.org) | ||
6 | */ | ||
7 | |||
8 | #include <linux/init.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/sched/signal.h> | ||
11 | |||
12 | #include <asm/addrspace.h> | ||
13 | #include <asm/traps.h> | ||
14 | #include <asm/branch.h> | ||
15 | #include <asm/irq_regs.h> | ||
16 | #include <asm/sgi/mc.h> | ||
17 | #include <asm/sgi/hpc3.h> | ||
18 | #include <asm/sgi/ioc.h> | ||
19 | #include <asm/sgi/ip22.h> | ||
20 | |||
21 | |||
22 | static unsigned int cpu_err_stat; /* Status reg for CPU */ | ||
23 | static unsigned int gio_err_stat; /* Status reg for GIO */ | ||
24 | static unsigned int cpu_err_addr; /* Error address reg for CPU */ | ||
25 | static unsigned int gio_err_addr; /* Error address reg for GIO */ | ||
26 | static unsigned int extio_stat; | ||
27 | static unsigned int hpc3_berr_stat; /* Bus error interrupt status */ | ||
28 | |||
29 | static void save_and_clear_buserr(void) | ||
30 | { | ||
31 | /* save status registers */ | ||
32 | cpu_err_addr = sgimc->cerr; | ||
33 | cpu_err_stat = sgimc->cstat; | ||
34 | gio_err_addr = sgimc->gerr; | ||
35 | gio_err_stat = sgimc->gstat; | ||
36 | extio_stat = ip22_is_fullhouse() ? sgioc->extio : (sgint->errstat << 4); | ||
37 | hpc3_berr_stat = hpc3c0->bestat; | ||
38 | |||
39 | sgimc->cstat = sgimc->gstat = 0; | ||
40 | } | ||
41 | |||
42 | #define GIO_ERRMASK 0xff00 | ||
43 | #define CPU_ERRMASK 0x3f00 | ||
44 | |||
45 | static void print_buserr(void) | ||
46 | { | ||
47 | if (extio_stat & EXTIO_MC_BUSERR) | ||
48 | printk(KERN_ERR "MC Bus Error\n"); | ||
49 | if (extio_stat & EXTIO_HPC3_BUSERR) | ||
50 | printk(KERN_ERR "HPC3 Bus Error 0x%x:<id=0x%x,%s,lane=0x%x>\n", | ||
51 | hpc3_berr_stat, | ||
52 | (hpc3_berr_stat & HPC3_BESTAT_PIDMASK) >> | ||
53 | HPC3_BESTAT_PIDSHIFT, | ||
54 | (hpc3_berr_stat & HPC3_BESTAT_CTYPE) ? "PIO" : "DMA", | ||
55 | hpc3_berr_stat & HPC3_BESTAT_BLMASK); | ||
56 | if (extio_stat & EXTIO_EISA_BUSERR) | ||
57 | printk(KERN_ERR "EISA Bus Error\n"); | ||
58 | if (cpu_err_stat & CPU_ERRMASK) | ||
59 | printk(KERN_ERR "CPU error 0x%x<%s%s%s%s%s%s> @ 0x%08x\n", | ||
60 | cpu_err_stat, | ||
61 | cpu_err_stat & SGIMC_CSTAT_RD ? "RD " : "", | ||
62 | cpu_err_stat & SGIMC_CSTAT_PAR ? "PAR " : "", | ||
63 | cpu_err_stat & SGIMC_CSTAT_ADDR ? "ADDR " : "", | ||
64 | cpu_err_stat & SGIMC_CSTAT_SYSAD_PAR ? "SYSAD " : "", | ||
65 | cpu_err_stat & SGIMC_CSTAT_SYSCMD_PAR ? "SYSCMD " : "", | ||
66 | cpu_err_stat & SGIMC_CSTAT_BAD_DATA ? "BAD_DATA " : "", | ||
67 | cpu_err_addr); | ||
68 | if (gio_err_stat & GIO_ERRMASK) | ||
69 | printk(KERN_ERR "GIO error 0x%x:<%s%s%s%s%s%s%s%s> @ 0x%08x\n", | ||
70 | gio_err_stat, | ||
71 | gio_err_stat & SGIMC_GSTAT_RD ? "RD " : "", | ||
72 | gio_err_stat & SGIMC_GSTAT_WR ? "WR " : "", | ||
73 | gio_err_stat & SGIMC_GSTAT_TIME ? "TIME " : "", | ||
74 | gio_err_stat & SGIMC_GSTAT_PROM ? "PROM " : "", | ||
75 | gio_err_stat & SGIMC_GSTAT_ADDR ? "ADDR " : "", | ||
76 | gio_err_stat & SGIMC_GSTAT_BC ? "BC " : "", | ||
77 | gio_err_stat & SGIMC_GSTAT_PIO_RD ? "PIO_RD " : "", | ||
78 | gio_err_stat & SGIMC_GSTAT_PIO_WR ? "PIO_WR " : "", | ||
79 | gio_err_addr); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * MC sends an interrupt whenever bus or parity errors occur. In addition, | ||
84 | * if the error happened during a CPU read, it also asserts the bus error | ||
85 | * pin on the R4K. Code in bus error handler save the MC bus error registers | ||
86 | * and then clear the interrupt when this happens. | ||
87 | */ | ||
88 | |||
89 | void ip22_be_interrupt(int irq) | ||
90 | { | ||
91 | const int field = 2 * sizeof(unsigned long); | ||
92 | struct pt_regs *regs = get_irq_regs(); | ||
93 | |||
94 | save_and_clear_buserr(); | ||
95 | print_buserr(); | ||
96 | printk(KERN_ALERT "%s bus error, epc == %0*lx, ra == %0*lx\n", | ||
97 | (regs->cp0_cause & 4) ? "Data" : "Instruction", | ||
98 | field, regs->cp0_epc, field, regs->regs[31]); | ||
99 | /* Assume it would be too dangerous to continue ... */ | ||
100 | die_if_kernel("Oops", regs); | ||
101 | force_sig(SIGBUS); | ||
102 | } | ||
103 | |||
104 | static int ip22_be_handler(struct pt_regs *regs, int is_fixup) | ||
105 | { | ||
106 | save_and_clear_buserr(); | ||
107 | if (is_fixup) | ||
108 | return MIPS_BE_FIXUP; | ||
109 | print_buserr(); | ||
110 | return MIPS_BE_FATAL; | ||
111 | } | ||
112 | |||
113 | void __init ip22_be_init(void) | ||
114 | { | ||
115 | board_be_handler = ip22_be_handler; | ||
116 | } | ||