1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/init.h>
16#include <linux/interrupt.h>
17#include <linux/kernel.h>
18#include <linux/sched.h>
19#include <linux/types.h>
20
21#include <asm/addrspace.h>
22#include <asm/bootinfo.h>
23#include <asm/cpu.h>
24#include <asm/irq_regs.h>
25#include <asm/processor.h>
26#include <asm/ptrace.h>
27#include <asm/traps.h>
28
29#include <asm/dec/ecc.h>
30#include <asm/dec/kn02.h>
31#include <asm/dec/kn03.h>
32#include <asm/dec/kn05.h>
33
34static volatile u32 *kn0x_erraddr;
35static volatile u32 *kn0x_chksyn;
36
37static inline void dec_ecc_be_ack(void)
38{
39 *kn0x_erraddr = 0;
40 iob();
41}
42
43static int dec_ecc_be_backend(struct pt_regs *regs, int is_fixup, int invoker)
44{
45 static const char excstr[] = "exception";
46 static const char intstr[] = "interrupt";
47 static const char cpustr[] = "CPU";
48 static const char dmastr[] = "DMA";
49 static const char readstr[] = "read";
50 static const char mreadstr[] = "memory read";
51 static const char writestr[] = "write";
52 static const char mwritstr[] = "partial memory write";
53 static const char timestr[] = "timeout";
54 static const char overstr[] = "overrun";
55 static const char eccstr[] = "ECC error";
56
57 const char *kind, *agent, *cycle, *event;
58 const char *status = "", *xbit = "", *fmt = "";
59 unsigned long address;
60 u16 syn = 0, sngl;
61
62 int i = 0;
63
64 u32 erraddr = *kn0x_erraddr;
65 u32 chksyn = *kn0x_chksyn;
66 int action = MIPS_BE_FATAL;
67
68
69 if ((erraddr & (KN0X_EAR_VALID | KN0X_EAR_ECCERR)) == KN0X_EAR_VALID)
70 dec_ecc_be_ack();
71
72 kind = invoker ? intstr : excstr;
73
74 if (!(erraddr & KN0X_EAR_VALID)) {
75
76 printk(KERN_ALERT "Unidentified bus error %s\n", kind);
77 return action;
78 }
79
80 agent = (erraddr & KN0X_EAR_CPU) ? cpustr : dmastr;
81
82 if (erraddr & KN0X_EAR_ECCERR) {
83
84 cycle = (erraddr & KN0X_EAR_WRITE) ? mwritstr : mreadstr;
85 event = eccstr;
86 } else {
87
88 cycle = (erraddr & KN0X_EAR_WRITE) ? writestr : readstr;
89 event = (erraddr & KN0X_EAR_CPU) ? timestr : overstr;
90 }
91
92 address = erraddr & KN0X_EAR_ADDRESS;
93
94 if ((erraddr & (KN0X_EAR_WRITE | KN0X_EAR_ECCERR)) == KN0X_EAR_ECCERR)
95 address = (address & ~0xfffLL) | ((address - 5) & 0xfffLL);
96 address <<= 2;
97
98
99 if (erraddr & KN0X_EAR_CPU && is_fixup)
100 action = MIPS_BE_FIXUP;
101
102 if (erraddr & KN0X_EAR_ECCERR) {
103 static const u8 data_sbit[32] = {
104 0x4f, 0x4a, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d,
105 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x31, 0x34,
106 0x0e, 0x0b, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
107 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x70, 0x75,
108 };
109 static const u8 data_mbit[25] = {
110 0x07, 0x0d, 0x1f,
111 0x2f, 0x32, 0x37, 0x38, 0x3b, 0x3d, 0x3e,
112 0x43, 0x45, 0x46, 0x49, 0x4c, 0x51, 0x5e,
113 0x61, 0x6e, 0x73, 0x76, 0x79, 0x7a, 0x7c, 0x7f,
114 };
115 static const char sbestr[] = "corrected single";
116 static const char dbestr[] = "uncorrectable double";
117 static const char mbestr[] = "uncorrectable multiple";
118
119 if (!(address & 0x4))
120 syn = chksyn;
121 else
122 syn = chksyn >> 16;
123
124 if (!(syn & KN0X_ESR_VLDLO)) {
125
126 dec_ecc_be_ack();
127
128 fmt = KERN_ALERT "%s" "invalid\n";
129 } else {
130 sngl = syn & KN0X_ESR_SNGLO;
131 syn &= KN0X_ESR_SYNLO;
132
133
134
135
136
137 for (i = 0; i < 25; i++)
138 if (syn == data_mbit[i])
139 break;
140
141 if (i < 25) {
142 status = mbestr;
143 } else if (!sngl) {
144 status = dbestr;
145 } else {
146 volatile u32 *ptr =
147 (void *)CKSEG1ADDR(address);
148
149 *ptr = *ptr;
150 iob();
151
152 status = sbestr;
153 action = MIPS_BE_DISCARD;
154 }
155
156
157 dec_ecc_be_ack();
158
159 if (syn && syn == (syn & -syn)) {
160 if (syn == 0x01) {
161 fmt = KERN_ALERT "%s"
162 "%#04x -- %s bit error "
163 "at check bit C%s\n";
164 xbit = "X";
165 } else {
166 fmt = KERN_ALERT "%s"
167 "%#04x -- %s bit error "
168 "at check bit C%s%u\n";
169 }
170 i = syn >> 2;
171 } else {
172 for (i = 0; i < 32; i++)
173 if (syn == data_sbit[i])
174 break;
175 if (i < 32)
176 fmt = KERN_ALERT "%s"
177 "%#04x -- %s bit error "
178 "at data bit D%s%u\n";
179 else
180 fmt = KERN_ALERT "%s"
181 "%#04x -- %s bit error\n";
182 }
183 }
184 }
185
186 if (action != MIPS_BE_FIXUP)
187 printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
188 kind, agent, cycle, event, address);
189
190 if (action != MIPS_BE_FIXUP && erraddr & KN0X_EAR_ECCERR)
191 printk(fmt, " ECC syndrome ", syn, status, xbit, i);
192
193 return action;
194}
195
196int dec_ecc_be_handler(struct pt_regs *regs, int is_fixup)
197{
198 return dec_ecc_be_backend(regs, is_fixup, 0);
199}
200
201irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id)
202{
203 struct pt_regs *regs = get_irq_regs();
204
205 int action = dec_ecc_be_backend(regs, 0, 1);
206
207 if (action == MIPS_BE_DISCARD)
208 return IRQ_HANDLED;
209
210
211
212
213
214
215
216
217 printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n",
218 regs->cp0_epc, regs->regs[31]);
219 die("Unrecoverable bus error", regs);
220}
221
222
223
224
225
226
227
228static inline void dec_kn02_be_init(void)
229{
230 volatile u32 *csr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR);
231
232 kn0x_erraddr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_ERRADDR);
233 kn0x_chksyn = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CHKSYN);
234
235
236 cached_kn02_csr = *csr | KN02_CSR_LEDS;
237
238
239 cached_kn02_csr &= ~(KN02_CSR_DIAGCHK | KN02_CSR_DIAGGEN);
240
241 cached_kn02_csr |= KN02_CSR_CORRECT;
242 *csr = cached_kn02_csr;
243 iob();
244}
245
246static inline void dec_kn03_be_init(void)
247{
248 volatile u32 *mcr = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_MCR);
249 volatile u32 *mbcs = (void *)CKSEG1ADDR(KN4K_SLOT_BASE + KN4K_MB_CSR);
250
251 kn0x_erraddr = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_ERRADDR);
252 kn0x_chksyn = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_CHKSYN);
253
254
255
256
257
258
259
260
261 *mcr = (*mcr & ~(KN03_MCR_DIAGCHK | KN03_MCR_DIAGGEN)) |
262 KN03_MCR_CORRECT;
263 if (current_cpu_type() == CPU_R4400SC)
264 *mbcs |= KN4K_MB_CSR_EE;
265 fast_iob();
266}
267
268void __init dec_ecc_be_init(void)
269{
270 if (mips_machtype == MACH_DS5000_200)
271 dec_kn02_be_init();
272 else
273 dec_kn03_be_init();
274
275
276 dec_ecc_be_ack();
277}
278