^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Bus error event handling code for systems equipped with ECC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * handling logic, i.e. DECstation/DECsystem 5000/200 (KN02),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * 5000/240 (KN03), 5000/260 (KN05) and DECsystem 5900 (KN03),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * 5900/260 (KN05) systems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (c) 2003, 2005 Maciej W. Rozycki
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <asm/addrspace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/bootinfo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/cpu.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/cpu-type.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/irq_regs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/processor.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/dec/ecc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <asm/dec/kn02.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include <asm/dec/kn03.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include <asm/dec/kn05.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static volatile u32 *kn0x_erraddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static volatile u32 *kn0x_chksyn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static inline void dec_ecc_be_ack(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *kn0x_erraddr = 0; /* any write clears the IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) iob();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int dec_ecc_be_backend(struct pt_regs *regs, int is_fixup, int invoker)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static const char excstr[] = "exception";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static const char intstr[] = "interrupt";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const char cpustr[] = "CPU";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static const char dmastr[] = "DMA";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static const char readstr[] = "read";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) static const char mreadstr[] = "memory read";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static const char writestr[] = "write";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static const char mwritstr[] = "partial memory write";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static const char timestr[] = "timeout";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static const char overstr[] = "overrun";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static const char eccstr[] = "ECC error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) const char *kind, *agent, *cycle, *event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) const char *status = "", *xbit = "", *fmt = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) unsigned long address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u16 syn = 0, sngl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) u32 erraddr = *kn0x_erraddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) u32 chksyn = *kn0x_chksyn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int action = MIPS_BE_FATAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) /* For non-ECC ack ASAP, so that any subsequent errors get caught. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if ((erraddr & (KN0X_EAR_VALID | KN0X_EAR_ECCERR)) == KN0X_EAR_VALID)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) dec_ecc_be_ack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) kind = invoker ? intstr : excstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (!(erraddr & KN0X_EAR_VALID)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /* No idea what happened. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) printk(KERN_ALERT "Unidentified bus error %s\n", kind);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) agent = (erraddr & KN0X_EAR_CPU) ? cpustr : dmastr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if (erraddr & KN0X_EAR_ECCERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* An ECC error on a CPU or DMA transaction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) cycle = (erraddr & KN0X_EAR_WRITE) ? mwritstr : mreadstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) event = eccstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* A CPU timeout or a DMA overrun. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) cycle = (erraddr & KN0X_EAR_WRITE) ? writestr : readstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) event = (erraddr & KN0X_EAR_CPU) ? timestr : overstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) address = erraddr & KN0X_EAR_ADDRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* For ECC errors on reads adjust for MT pipelining. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if ((erraddr & (KN0X_EAR_WRITE | KN0X_EAR_ECCERR)) == KN0X_EAR_ECCERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) address = (address & ~0xfffLL) | ((address - 5) & 0xfffLL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) address <<= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /* Only CPU errors are fixable. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (erraddr & KN0X_EAR_CPU && is_fixup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) action = MIPS_BE_FIXUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (erraddr & KN0X_EAR_ECCERR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static const u8 data_sbit[32] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 0x4f, 0x4a, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x31, 0x34,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 0x0e, 0x0b, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x70, 0x75,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) static const u8 data_mbit[25] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 0x07, 0x0d, 0x1f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 0x2f, 0x32, 0x37, 0x38, 0x3b, 0x3d, 0x3e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 0x43, 0x45, 0x46, 0x49, 0x4c, 0x51, 0x5e,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 0x61, 0x6e, 0x73, 0x76, 0x79, 0x7a, 0x7c, 0x7f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static const char sbestr[] = "corrected single";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) static const char dbestr[] = "uncorrectable double";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static const char mbestr[] = "uncorrectable multiple";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (!(address & 0x4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) syn = chksyn; /* Low bank. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) syn = chksyn >> 16; /* High bank. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!(syn & KN0X_ESR_VLDLO)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* Ack now, no rewrite will happen. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dec_ecc_be_ack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) fmt = KERN_ALERT "%s" "invalid\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) sngl = syn & KN0X_ESR_SNGLO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) syn &= KN0X_ESR_SYNLO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * Multibit errors may be tagged incorrectly;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * check the syndrome explicitly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) for (i = 0; i < 25; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (syn == data_mbit[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (i < 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) status = mbestr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) } else if (!sngl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) status = dbestr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) volatile u32 *ptr =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) (void *)CKSEG1ADDR(address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) *ptr = *ptr; /* Rewrite. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) iob();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) status = sbestr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) action = MIPS_BE_DISCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* Ack now, now we've rewritten (or not). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) dec_ecc_be_ack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) if (syn && syn == (syn & -syn)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (syn == 0x01) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) fmt = KERN_ALERT "%s"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) "%#04x -- %s bit error "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) "at check bit C%s\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) xbit = "X";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) fmt = KERN_ALERT "%s"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) "%#04x -- %s bit error "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) "at check bit C%s%u\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) i = syn >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) for (i = 0; i < 32; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (syn == data_sbit[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (i < 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) fmt = KERN_ALERT "%s"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) "%#04x -- %s bit error "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) "at data bit D%s%u\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) fmt = KERN_ALERT "%s"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) "%#04x -- %s bit error\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (action != MIPS_BE_FIXUP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) kind, agent, cycle, event, address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (action != MIPS_BE_FIXUP && erraddr & KN0X_EAR_ECCERR)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) printk(fmt, " ECC syndrome ", syn, status, xbit, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return action;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int dec_ecc_be_handler(struct pt_regs *regs, int is_fixup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return dec_ecc_be_backend(regs, is_fixup, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) struct pt_regs *regs = get_irq_regs();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) int action = dec_ecc_be_backend(regs, 0, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (action == MIPS_BE_DISCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * FIXME: Find the affected processes and kill them, otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * we must die.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * The interrupt is asynchronously delivered thus EPC and RA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * may be irrelevant, but are printed for a reference.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) regs->cp0_epc, regs->regs[31]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) die("Unrecoverable bus error", regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * Initialization differs a bit between KN02 and KN03/KN05, so we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * need two variants. Once set up, all systems can be handled the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * same way.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static inline void dec_kn02_be_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) volatile u32 *csr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) kn0x_erraddr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_ERRADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) kn0x_chksyn = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CHKSYN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) /* Preset write-only bits of the Control Register cache. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) cached_kn02_csr = *csr | KN02_CSR_LEDS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) /* Set normal ECC detection and generation. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) cached_kn02_csr &= ~(KN02_CSR_DIAGCHK | KN02_CSR_DIAGGEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* Enable ECC correction. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) cached_kn02_csr |= KN02_CSR_CORRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) *csr = cached_kn02_csr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) iob();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static inline void dec_kn03_be_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) volatile u32 *mcr = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_MCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) volatile u32 *mbcs = (void *)CKSEG1ADDR(KN4K_SLOT_BASE + KN4K_MB_CSR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) kn0x_erraddr = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_ERRADDR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) kn0x_chksyn = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_CHKSYN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * Set normal ECC detection and generation, enable ECC correction.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * For KN05 we also need to make sure EE (?) is enabled in the MB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * Otherwise DBE/IBE exceptions would be masked but bus error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * interrupts would still arrive, resulting in an inevitable crash
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * if get_dbe() triggers one.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) *mcr = (*mcr & ~(KN03_MCR_DIAGCHK | KN03_MCR_DIAGGEN)) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) KN03_MCR_CORRECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (current_cpu_type() == CPU_R4400SC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *mbcs |= KN4K_MB_CSR_EE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) fast_iob();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) void __init dec_ecc_be_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (mips_machtype == MACH_DS5000_200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) dec_kn02_be_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) dec_kn03_be_init();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) /* Clear any leftover errors from the firmware. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) dec_ecc_be_ack();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }