aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/dec
diff options
context:
space:
mode:
authorWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
committerWe-unite <3205135446@qq.com>2025-03-08 22:04:20 +0800
commita07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch)
tree84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/dec
downloadohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz
ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/dec')
-rw-r--r--arch/mips/dec/Makefile10
-rw-r--r--arch/mips/dec/Platform7
-rw-r--r--arch/mips/dec/ecc-berr.c274
-rw-r--r--arch/mips/dec/int-handler.S311
-rw-r--r--arch/mips/dec/ioasic-irq.c112
-rw-r--r--arch/mips/dec/kn01-berr.c196
-rw-r--r--arch/mips/dec/kn02-irq.c75
-rw-r--r--arch/mips/dec/kn02xa-berr.c135
-rw-r--r--arch/mips/dec/platform.c40
-rw-r--r--arch/mips/dec/prom/Makefile9
-rw-r--r--arch/mips/dec/prom/cmdline.c40
-rw-r--r--arch/mips/dec/prom/console.c41
-rw-r--r--arch/mips/dec/prom/dectypes.h15
-rw-r--r--arch/mips/dec/prom/identify.c187
-rw-r--r--arch/mips/dec/prom/init.c137
-rw-r--r--arch/mips/dec/prom/locore.S30
-rw-r--r--arch/mips/dec/prom/memory.c117
-rw-r--r--arch/mips/dec/reset.c41
-rw-r--r--arch/mips/dec/setup.c784
-rw-r--r--arch/mips/dec/tc.c95
-rw-r--r--arch/mips/dec/time.c172
-rw-r--r--arch/mips/dec/wbflush.c92
22 files changed, 2920 insertions, 0 deletions
diff --git a/arch/mips/dec/Makefile b/arch/mips/dec/Makefile
new file mode 100644
index 000000000..c9f62f1da
--- /dev/null
+++ b/arch/mips/dec/Makefile
@@ -0,0 +1,10 @@
1# SPDX-License-Identifier: GPL-2.0-only
2#
3# Makefile for the DECstation family specific parts of the kernel
4#
5
6obj-y := ecc-berr.o int-handler.o ioasic-irq.o kn01-berr.o \
7 kn02-irq.o kn02xa-berr.o platform.o reset.o setup.o time.o
8
9obj-$(CONFIG_TC) += tc.o
10obj-$(CONFIG_CPU_HAS_WB) += wbflush.o
diff --git a/arch/mips/dec/Platform b/arch/mips/dec/Platform
new file mode 100644
index 000000000..c82391e83
--- /dev/null
+++ b/arch/mips/dec/Platform
@@ -0,0 +1,7 @@
1#
2# DECstation family
3#
4cflags-$(CONFIG_MACH_DECSTATION) += \
5 -I$(srctree)/arch/mips/include/asm/mach-dec
6libs-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/prom/
7load-$(CONFIG_MACH_DECSTATION) += 0xffffffff80040000
diff --git a/arch/mips/dec/ecc-berr.c b/arch/mips/dec/ecc-berr.c
new file mode 100644
index 000000000..1eb356fdd
--- /dev/null
+++ b/arch/mips/dec/ecc-berr.c
@@ -0,0 +1,274 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Bus error event handling code for systems equipped with ECC
4 * handling logic, i.e. DECstation/DECsystem 5000/200 (KN02),
5 * 5000/240 (KN03), 5000/260 (KN05) and DECsystem 5900 (KN03),
6 * 5900/260 (KN05) systems.
7 *
8 * Copyright (c) 2003, 2005 Maciej W. Rozycki
9 */
10
11#include <linux/init.h>
12#include <linux/interrupt.h>
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/types.h>
16
17#include <asm/addrspace.h>
18#include <asm/bootinfo.h>
19#include <asm/cpu.h>
20#include <asm/cpu-type.h>
21#include <asm/irq_regs.h>
22#include <asm/processor.h>
23#include <asm/ptrace.h>
24#include <asm/traps.h>
25
26#include <asm/dec/ecc.h>
27#include <asm/dec/kn02.h>
28#include <asm/dec/kn03.h>
29#include <asm/dec/kn05.h>
30
31static volatile u32 *kn0x_erraddr;
32static volatile u32 *kn0x_chksyn;
33
34static inline void dec_ecc_be_ack(void)
35{
36 *kn0x_erraddr = 0; /* any write clears the IRQ */
37 iob();
38}
39
40static int dec_ecc_be_backend(struct pt_regs *regs, int is_fixup, int invoker)
41{
42 static const char excstr[] = "exception";
43 static const char intstr[] = "interrupt";
44 static const char cpustr[] = "CPU";
45 static const char dmastr[] = "DMA";
46 static const char readstr[] = "read";
47 static const char mreadstr[] = "memory read";
48 static const char writestr[] = "write";
49 static const char mwritstr[] = "partial memory write";
50 static const char timestr[] = "timeout";
51 static const char overstr[] = "overrun";
52 static const char eccstr[] = "ECC error";
53
54 const char *kind, *agent, *cycle, *event;
55 const char *status = "", *xbit = "", *fmt = "";
56 unsigned long address;
57 u16 syn = 0, sngl;
58
59 int i = 0;
60
61 u32 erraddr = *kn0x_erraddr;
62 u32 chksyn = *kn0x_chksyn;
63 int action = MIPS_BE_FATAL;
64
65 /* For non-ECC ack ASAP, so that any subsequent errors get caught. */
66 if ((erraddr & (KN0X_EAR_VALID | KN0X_EAR_ECCERR)) == KN0X_EAR_VALID)
67 dec_ecc_be_ack();
68
69 kind = invoker ? intstr : excstr;
70
71 if (!(erraddr & KN0X_EAR_VALID)) {
72 /* No idea what happened. */
73 printk(KERN_ALERT "Unidentified bus error %s\n", kind);
74 return action;
75 }
76
77 agent = (erraddr & KN0X_EAR_CPU) ? cpustr : dmastr;
78
79 if (erraddr & KN0X_EAR_ECCERR) {
80 /* An ECC error on a CPU or DMA transaction. */
81 cycle = (erraddr & KN0X_EAR_WRITE) ? mwritstr : mreadstr;
82 event = eccstr;
83 } else {
84 /* A CPU timeout or a DMA overrun. */
85 cycle = (erraddr & KN0X_EAR_WRITE) ? writestr : readstr;
86 event = (erraddr & KN0X_EAR_CPU) ? timestr : overstr;
87 }
88
89 address = erraddr & KN0X_EAR_ADDRESS;
90 /* For ECC errors on reads adjust for MT pipelining. */
91 if ((erraddr & (KN0X_EAR_WRITE | KN0X_EAR_ECCERR)) == KN0X_EAR_ECCERR)
92 address = (address & ~0xfffLL) | ((address - 5) & 0xfffLL);
93 address <<= 2;
94
95 /* Only CPU errors are fixable. */
96 if (erraddr & KN0X_EAR_CPU && is_fixup)
97 action = MIPS_BE_FIXUP;
98
99 if (erraddr & KN0X_EAR_ECCERR) {
100 static const u8 data_sbit[32] = {
101 0x4f, 0x4a, 0x52, 0x54, 0x57, 0x58, 0x5b, 0x5d,
102 0x23, 0x25, 0x26, 0x29, 0x2a, 0x2c, 0x31, 0x34,
103 0x0e, 0x0b, 0x13, 0x15, 0x16, 0x19, 0x1a, 0x1c,
104 0x62, 0x64, 0x67, 0x68, 0x6b, 0x6d, 0x70, 0x75,
105 };
106 static const u8 data_mbit[25] = {
107 0x07, 0x0d, 0x1f,
108 0x2f, 0x32, 0x37, 0x38, 0x3b, 0x3d, 0x3e,
109 0x43, 0x45, 0x46, 0x49, 0x4c, 0x51, 0x5e,
110 0x61, 0x6e, 0x73, 0x76, 0x79, 0x7a, 0x7c, 0x7f,
111 };
112 static const char sbestr[] = "corrected single";
113 static const char dbestr[] = "uncorrectable double";
114 static const char mbestr[] = "uncorrectable multiple";
115
116 if (!(address & 0x4))
117 syn = chksyn; /* Low bank. */
118 else
119 syn = chksyn >> 16; /* High bank. */
120
121 if (!(syn & KN0X_ESR_VLDLO)) {
122 /* Ack now, no rewrite will happen. */
123 dec_ecc_be_ack();
124
125 fmt = KERN_ALERT "%s" "invalid\n";
126 } else {
127 sngl = syn & KN0X_ESR_SNGLO;
128 syn &= KN0X_ESR_SYNLO;
129
130 /*
131 * Multibit errors may be tagged incorrectly;
132 * check the syndrome explicitly.
133 */
134 for (i = 0; i < 25; i++)
135 if (syn == data_mbit[i])
136 break;
137
138 if (i < 25) {
139 status = mbestr;
140 } else if (!sngl) {
141 status = dbestr;
142 } else {
143 volatile u32 *ptr =
144 (void *)CKSEG1ADDR(address);
145
146 *ptr = *ptr; /* Rewrite. */
147 iob();
148
149 status = sbestr;
150 action = MIPS_BE_DISCARD;
151 }
152
153 /* Ack now, now we've rewritten (or not). */
154 dec_ecc_be_ack();
155
156 if (syn && syn == (syn & -syn)) {
157 if (syn == 0x01) {
158 fmt = KERN_ALERT "%s"
159 "%#04x -- %s bit error "
160 "at check bit C%s\n";
161 xbit = "X";
162 } else {
163 fmt = KERN_ALERT "%s"
164 "%#04x -- %s bit error "
165 "at check bit C%s%u\n";
166 }
167 i = syn >> 2;
168 } else {
169 for (i = 0; i < 32; i++)
170 if (syn == data_sbit[i])
171 break;
172 if (i < 32)
173 fmt = KERN_ALERT "%s"
174 "%#04x -- %s bit error "
175 "at data bit D%s%u\n";
176 else
177 fmt = KERN_ALERT "%s"
178 "%#04x -- %s bit error\n";
179 }
180 }
181 }
182
183 if (action != MIPS_BE_FIXUP)
184 printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
185 kind, agent, cycle, event, address);
186
187 if (action != MIPS_BE_FIXUP && erraddr & KN0X_EAR_ECCERR)
188 printk(fmt, " ECC syndrome ", syn, status, xbit, i);
189
190 return action;
191}
192
193int dec_ecc_be_handler(struct pt_regs *regs, int is_fixup)
194{
195 return dec_ecc_be_backend(regs, is_fixup, 0);
196}
197
198irqreturn_t dec_ecc_be_interrupt(int irq, void *dev_id)
199{
200 struct pt_regs *regs = get_irq_regs();
201
202 int action = dec_ecc_be_backend(regs, 0, 1);
203
204 if (action == MIPS_BE_DISCARD)
205 return IRQ_HANDLED;
206
207 /*
208 * FIXME: Find the affected processes and kill them, otherwise
209 * we must die.
210 *
211 * The interrupt is asynchronously delivered thus EPC and RA
212 * may be irrelevant, but are printed for a reference.
213 */
214 printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n",
215 regs->cp0_epc, regs->regs[31]);
216 die("Unrecoverable bus error", regs);
217}
218
219
220/*
221 * Initialization differs a bit between KN02 and KN03/KN05, so we
222 * need two variants. Once set up, all systems can be handled the
223 * same way.
224 */
225static inline void dec_kn02_be_init(void)
226{
227 volatile u32 *csr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR);
228
229 kn0x_erraddr = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_ERRADDR);
230 kn0x_chksyn = (void *)CKSEG1ADDR(KN02_SLOT_BASE + KN02_CHKSYN);
231
232 /* Preset write-only bits of the Control Register cache. */
233 cached_kn02_csr = *csr | KN02_CSR_LEDS;
234
235 /* Set normal ECC detection and generation. */
236 cached_kn02_csr &= ~(KN02_CSR_DIAGCHK | KN02_CSR_DIAGGEN);
237 /* Enable ECC correction. */
238 cached_kn02_csr |= KN02_CSR_CORRECT;
239 *csr = cached_kn02_csr;
240 iob();
241}
242
243static inline void dec_kn03_be_init(void)
244{
245 volatile u32 *mcr = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_MCR);
246 volatile u32 *mbcs = (void *)CKSEG1ADDR(KN4K_SLOT_BASE + KN4K_MB_CSR);
247
248 kn0x_erraddr = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_ERRADDR);
249 kn0x_chksyn = (void *)CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_CHKSYN);
250
251 /*
252 * Set normal ECC detection and generation, enable ECC correction.
253 * For KN05 we also need to make sure EE (?) is enabled in the MB.
254 * Otherwise DBE/IBE exceptions would be masked but bus error
255 * interrupts would still arrive, resulting in an inevitable crash
256 * if get_dbe() triggers one.
257 */
258 *mcr = (*mcr & ~(KN03_MCR_DIAGCHK | KN03_MCR_DIAGGEN)) |
259 KN03_MCR_CORRECT;
260 if (current_cpu_type() == CPU_R4400SC)
261 *mbcs |= KN4K_MB_CSR_EE;
262 fast_iob();
263}
264
265void __init dec_ecc_be_init(void)
266{
267 if (mips_machtype == MACH_DS5000_200)
268 dec_kn02_be_init();
269 else
270 dec_kn03_be_init();
271
272 /* Clear any leftover errors from the firmware. */
273 dec_ecc_be_ack();
274}
diff --git a/arch/mips/dec/int-handler.S b/arch/mips/dec/int-handler.S
new file mode 100644
index 000000000..011d1d678
--- /dev/null
+++ b/arch/mips/dec/int-handler.S
@@ -0,0 +1,311 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (C) 1995, 1996, 1997 Paul M. Antoine and Harald Koerfgen
4 * Copyright (C) 2000, 2001, 2002, 2003, 2005 Maciej W. Rozycki
5 *
6 * Written by Ralf Baechle and Andreas Busse, modified for DECstation
7 * support by Paul Antoine and Harald Koerfgen.
8 *
9 * completely rewritten:
10 * Copyright (C) 1998 Harald Koerfgen
11 *
12 * Rewritten extensively for controller-driven IRQ support
13 * by Maciej W. Rozycki.
14 */
15
16#include <asm/addrspace.h>
17#include <asm/asm.h>
18#include <asm/mipsregs.h>
19#include <asm/regdef.h>
20#include <asm/stackframe.h>
21
22#include <asm/dec/interrupts.h>
23#include <asm/dec/ioasic_addrs.h>
24#include <asm/dec/ioasic_ints.h>
25#include <asm/dec/kn01.h>
26#include <asm/dec/kn02.h>
27#include <asm/dec/kn02xa.h>
28#include <asm/dec/kn03.h>
29
30#define KN02_CSR_BASE CKSEG1ADDR(KN02_SLOT_BASE + KN02_CSR)
31#define KN02XA_IOASIC_BASE CKSEG1ADDR(KN02XA_SLOT_BASE + IOASIC_IOCTL)
32#define KN03_IOASIC_BASE CKSEG1ADDR(KN03_SLOT_BASE + IOASIC_IOCTL)
33
34 .text
35 .set noreorder
36/*
37 * plat_irq_dispatch: Interrupt handler for DECstations
38 *
39 * We follow the model in the Indy interrupt code by David Miller, where he
40 * says: a lot of complication here is taken away because:
41 *
42 * 1) We handle one interrupt and return, sitting in a loop
43 * and moving across all the pending IRQ bits in the cause
44 * register is _NOT_ the answer, the common case is one
45 * pending IRQ so optimize in that direction.
46 *
47 * 2) We need not check against bits in the status register
48 * IRQ mask, that would make this routine slow as hell.
49 *
50 * 3) Linux only thinks in terms of all IRQs on or all IRQs
51 * off, nothing in between like BSD spl() brain-damage.
52 *
53 * Furthermore, the IRQs on the DECstations look basically (barring
54 * software IRQs which we don't use at all) like...
55 *
56 * DS2100/3100's, aka kn01, aka Pmax:
57 *
58 * MIPS IRQ Source
59 * -------- ------
60 * 0 Software (ignored)
61 * 1 Software (ignored)
62 * 2 SCSI
63 * 3 Lance Ethernet
64 * 4 DZ11 serial
65 * 5 RTC
66 * 6 Memory Controller & Video
67 * 7 FPU
68 *
69 * DS5000/200, aka kn02, aka 3max:
70 *
71 * MIPS IRQ Source
72 * -------- ------
73 * 0 Software (ignored)
74 * 1 Software (ignored)
75 * 2 TurboChannel
76 * 3 RTC
77 * 4 Reserved
78 * 5 Memory Controller
79 * 6 Reserved
80 * 7 FPU
81 *
82 * DS5000/1xx's, aka kn02ba, aka 3min:
83 *
84 * MIPS IRQ Source
85 * -------- ------
86 * 0 Software (ignored)
87 * 1 Software (ignored)
88 * 2 TurboChannel Slot 0
89 * 3 TurboChannel Slot 1
90 * 4 TurboChannel Slot 2
91 * 5 TurboChannel Slot 3 (ASIC)
92 * 6 Halt button
93 * 7 FPU/R4k timer
94 *
95 * DS5000/2x's, aka kn02ca, aka maxine:
96 *
97 * MIPS IRQ Source
98 * -------- ------
99 * 0 Software (ignored)
100 * 1 Software (ignored)
101 * 2 Periodic Interrupt (100usec)
102 * 3 RTC
103 * 4 I/O write timeout
104 * 5 TurboChannel (ASIC)
105 * 6 Halt Keycode from Access.Bus keyboard (CTRL-ALT-ENTER)
106 * 7 FPU/R4k timer
107 *
108 * DS5000/2xx's, aka kn03, aka 3maxplus:
109 *
110 * MIPS IRQ Source
111 * -------- ------
112 * 0 Software (ignored)
113 * 1 Software (ignored)
114 * 2 System Board (ASIC)
115 * 3 RTC
116 * 4 Reserved
117 * 5 Memory
118 * 6 Halt Button
119 * 7 FPU/R4k timer
120 *
121 * We handle the IRQ according to _our_ priority (see setup.c),
122 * then we just return. If multiple IRQs are pending then we will
123 * just take another exception, big deal.
124 */
125 .align 5
126 NESTED(plat_irq_dispatch, PT_SIZE, ra)
127 .set noreorder
128
129 /*
130 * Get pending Interrupts
131 */
132 mfc0 t0,CP0_CAUSE # get pending interrupts
133 mfc0 t1,CP0_STATUS
134#if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
135 lw t2,cpu_fpu_mask
136#endif
137 andi t0,ST0_IM # CAUSE.CE may be non-zero!
138 and t0,t1 # isolate allowed ones
139
140 beqz t0,spurious
141
142#if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
143 and t2,t0
144 bnez t2,fpu # handle FPU immediately
145#endif
146
147 /*
148 * Find irq with highest priority
149 */
150 # open coded PTR_LA t1, cpu_mask_nr_tbl
151#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
152 # open coded la t1, cpu_mask_nr_tbl
153 lui t1, %hi(cpu_mask_nr_tbl)
154 addiu t1, %lo(cpu_mask_nr_tbl)
155#else
156#error GCC `-msym32' option required for 64-bit DECstation builds
157#endif
1581: lw t2,(t1)
159 nop
160 and t2,t0
161 beqz t2,1b
162 addu t1,2*PTRSIZE # delay slot
163
164 /*
165 * Do the low-level stuff
166 */
167 lw a0,(-PTRSIZE)(t1)
168 nop
169 bgez a0,handle_it # irq_nr >= 0?
170 # irq_nr < 0: it is an address
171 nop
172 jr a0
173 # a trick to save a branch:
174 lui t2,(KN03_IOASIC_BASE>>16)&0xffff
175 # upper part of IOASIC Address
176
177/*
178 * Handle "IRQ Controller" Interrupts
179 * Masked Interrupts are still visible and have to be masked "by hand".
180 */
181 FEXPORT(kn02_io_int) # 3max
182 lui t0,(KN02_CSR_BASE>>16)&0xffff
183 # get interrupt status and mask
184 lw t0,(t0)
185 nop
186 andi t1,t0,KN02_IRQ_ALL
187 b 1f
188 srl t0,16 # shift interrupt mask
189
190 FEXPORT(kn02xa_io_int) # 3min/maxine
191 lui t2,(KN02XA_IOASIC_BASE>>16)&0xffff
192 # upper part of IOASIC Address
193
194 FEXPORT(kn03_io_int) # 3max+ (t2 loaded earlier)
195 lw t0,IO_REG_SIR(t2) # get status: IOASIC sir
196 lw t1,IO_REG_SIMR(t2) # get mask: IOASIC simr
197 nop
198
1991: and t0,t1 # mask out allowed ones
200
201 beqz t0,spurious
202
203 /*
204 * Find irq with highest priority
205 */
206 # open coded PTR_LA t1,asic_mask_nr_tbl
207#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32)
208 # open coded la t1, asic_mask_nr_tbl
209 lui t1, %hi(asic_mask_nr_tbl)
210 addiu t1, %lo(asic_mask_nr_tbl)
211#else
212#error GCC `-msym32' option required for 64-bit DECstation builds
213#endif
2142: lw t2,(t1)
215 nop
216 and t2,t0
217 beq zero,t2,2b
218 addu t1,2*PTRSIZE # delay slot
219
220 /*
221 * Do the low-level stuff
222 */
223 lw a0,%lo(-PTRSIZE)(t1)
224 nop
225 bgez a0,handle_it # irq_nr >= 0?
226 # irq_nr < 0: it is an address
227 nop
228 jr a0
229 nop # delay slot
230
231/*
232 * Dispatch low-priority interrupts. We reconsider all status
233 * bits again, which looks like a lose, but it makes the code
234 * simple and O(log n), so it gets compensated.
235 */
236 FEXPORT(cpu_all_int) # HALT, timers, software junk
237 li a0,DEC_CPU_IRQ_BASE
238 srl t0,CAUSEB_IP
239 li t1,CAUSEF_IP>>CAUSEB_IP # mask
240 b 1f
241 li t2,4 # nr of bits / 2
242
243 FEXPORT(kn02_all_int) # impossible ?
244 li a0,KN02_IRQ_BASE
245 li t1,KN02_IRQ_ALL # mask
246 b 1f
247 li t2,4 # nr of bits / 2
248
249 FEXPORT(asic_all_int) # various I/O ASIC junk
250 li a0,IO_IRQ_BASE
251 li t1,IO_IRQ_ALL # mask
252 b 1f
253 li t2,8 # nr of bits / 2
254
255/*
256 * Dispatch DMA interrupts -- O(log n).
257 */
258 FEXPORT(asic_dma_int) # I/O ASIC DMA events
259 li a0,IO_IRQ_BASE+IO_INR_DMA
260 srl t0,IO_INR_DMA
261 li t1,IO_IRQ_DMA>>IO_INR_DMA # mask
262 li t2,8 # nr of bits / 2
263
264 /*
265 * Find irq with highest priority.
266 * Highest irq number takes precedence.
267 */
2681: srlv t3,t1,t2
2692: xor t1,t3
270 and t3,t0,t1
271 beqz t3,3f
272 nop
273 move t0,t3
274 addu a0,t2
2753: srl t2,1
276 bnez t2,2b
277 srlv t3,t1,t2
278
279handle_it:
280 j dec_irq_dispatch
281 nop
282
283#if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
284fpu:
285 lw t0,fpu_kstat_irq
286 nop
287 lw t1,(t0)
288 nop
289 addu t1,1
290 j handle_fpe_int
291 sw t1,(t0)
292#endif
293
294spurious:
295 j spurious_interrupt
296 nop
297 END(plat_irq_dispatch)
298
299/*
300 * Generic unimplemented interrupt routines -- cpu_mask_nr_tbl
301 * and asic_mask_nr_tbl are initialized to point all interrupts here.
302 * The tables are then filled in by machine-specific initialisation
303 * in dec_setup().
304 */
305 FEXPORT(dec_intr_unimplemented)
306 move a1,t0 # cheats way of printing an arg!
307 ASM_PANIC("Unimplemented cpu interrupt! CP0_CAUSE: 0x%08x");
308
309 FEXPORT(asic_intr_unimplemented)
310 move a1,t0 # cheats way of printing an arg!
311 ASM_PANIC("Unimplemented asic interrupt! ASIC ISR: 0x%08x");
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c
new file mode 100644
index 000000000..130eb67bd
--- /dev/null
+++ b/arch/mips/dec/ioasic-irq.c
@@ -0,0 +1,112 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * DEC I/O ASIC interrupts.
4 *
5 * Copyright (c) 2002, 2003, 2013 Maciej W. Rozycki
6 */
7
8#include <linux/init.h>
9#include <linux/irq.h>
10#include <linux/types.h>
11
12#include <asm/dec/ioasic.h>
13#include <asm/dec/ioasic_addrs.h>
14#include <asm/dec/ioasic_ints.h>
15
16static int ioasic_irq_base;
17
18static void unmask_ioasic_irq(struct irq_data *d)
19{
20 u32 simr;
21
22 simr = ioasic_read(IO_REG_SIMR);
23 simr |= (1 << (d->irq - ioasic_irq_base));
24 ioasic_write(IO_REG_SIMR, simr);
25}
26
27static void mask_ioasic_irq(struct irq_data *d)
28{
29 u32 simr;
30
31 simr = ioasic_read(IO_REG_SIMR);
32 simr &= ~(1 << (d->irq - ioasic_irq_base));
33 ioasic_write(IO_REG_SIMR, simr);
34}
35
36static void ack_ioasic_irq(struct irq_data *d)
37{
38 mask_ioasic_irq(d);
39 fast_iob();
40}
41
42static struct irq_chip ioasic_irq_type = {
43 .name = "IO-ASIC",
44 .irq_ack = ack_ioasic_irq,
45 .irq_mask = mask_ioasic_irq,
46 .irq_mask_ack = ack_ioasic_irq,
47 .irq_unmask = unmask_ioasic_irq,
48};
49
50static void clear_ioasic_dma_irq(struct irq_data *d)
51{
52 u32 sir;
53
54 sir = ~(1 << (d->irq - ioasic_irq_base));
55 ioasic_write(IO_REG_SIR, sir);
56 fast_iob();
57}
58
59static struct irq_chip ioasic_dma_irq_type = {
60 .name = "IO-ASIC-DMA",
61 .irq_ack = clear_ioasic_dma_irq,
62 .irq_mask = mask_ioasic_irq,
63 .irq_unmask = unmask_ioasic_irq,
64 .irq_eoi = clear_ioasic_dma_irq,
65};
66
67/*
68 * I/O ASIC implements two kinds of DMA interrupts, informational and
69 * error interrupts.
70 *
71 * The formers do not stop DMA and should be cleared as soon as possible
72 * so that if they retrigger before the handler has completed, usually as
73 * a side effect of actions taken by the handler, then they are reissued.
74 * These use the `handle_edge_irq' handler that clears the request right
75 * away.
76 *
77 * The latters stop DMA and do not resume it until the interrupt has been
78 * cleared. This cannot be done until after a corrective action has been
79 * taken and this also means they will not retrigger. Therefore they use
80 * the `handle_fasteoi_irq' handler that only clears the request on the
81 * way out. Because MIPS processor interrupt inputs, one of which the I/O
82 * ASIC is cascaded to, are level-triggered it is recommended that error
83 * DMA interrupt action handlers are registered with the IRQF_ONESHOT flag
84 * set so that they are run with the interrupt line masked.
85 *
86 * This mask has `1' bits in the positions of informational interrupts.
87 */
88#define IO_IRQ_DMA_INFO \
89 (IO_IRQ_MASK(IO_INR_SCC0A_RXDMA) | \
90 IO_IRQ_MASK(IO_INR_SCC1A_RXDMA) | \
91 IO_IRQ_MASK(IO_INR_ISDN_TXDMA) | \
92 IO_IRQ_MASK(IO_INR_ISDN_RXDMA) | \
93 IO_IRQ_MASK(IO_INR_ASC_DMA))
94
95void __init init_ioasic_irqs(int base)
96{
97 int i;
98
99 /* Mask interrupts. */
100 ioasic_write(IO_REG_SIMR, 0);
101 fast_iob();
102
103 for (i = base; i < base + IO_INR_DMA; i++)
104 irq_set_chip_and_handler(i, &ioasic_irq_type,
105 handle_level_irq);
106 for (; i < base + IO_IRQ_LINES; i++)
107 irq_set_chip_and_handler(i, &ioasic_dma_irq_type,
108 1 << (i - base) & IO_IRQ_DMA_INFO ?
109 handle_edge_irq : handle_fasteoi_irq);
110
111 ioasic_irq_base = base;
112}
diff --git a/arch/mips/dec/kn01-berr.c b/arch/mips/dec/kn01-berr.c
new file mode 100644
index 000000000..76efed7bc
--- /dev/null
+++ b/arch/mips/dec/kn01-berr.c
@@ -0,0 +1,196 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Bus error event handling code for DECstation/DECsystem 3100
4 * and 2100 (KN01) systems equipped with parity error detection
5 * logic.
6 *
7 * Copyright (c) 2005 Maciej W. Rozycki
8 */
9
10#include <linux/init.h>
11#include <linux/interrupt.h>
12#include <linux/kernel.h>
13#include <linux/spinlock.h>
14#include <linux/types.h>
15
16#include <asm/inst.h>
17#include <asm/irq_regs.h>
18#include <asm/mipsregs.h>
19#include <asm/page.h>
20#include <asm/ptrace.h>
21#include <asm/traps.h>
22#include <linux/uaccess.h>
23
24#include <asm/dec/kn01.h>
25
26
27/* CP0 hazard avoidance. */
28#define BARRIER \
29 __asm__ __volatile__( \
30 ".set push\n\t" \
31 ".set noreorder\n\t" \
32 "nop\n\t" \
33 ".set pop\n\t")
34
35/*
36 * Bits 7:0 of the Control Register are write-only -- the
37 * corresponding bits of the Status Register have a different
38 * meaning. Hence we use a cache. It speeds up things a bit
39 * as well.
40 *
41 * There is no default value -- it has to be initialized.
42 */
43u16 cached_kn01_csr;
44static DEFINE_RAW_SPINLOCK(kn01_lock);
45
46
47static inline void dec_kn01_be_ack(void)
48{
49 volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
50 unsigned long flags;
51
52 raw_spin_lock_irqsave(&kn01_lock, flags);
53
54 *csr = cached_kn01_csr | KN01_CSR_MEMERR; /* Clear bus IRQ. */
55 iob();
56
57 raw_spin_unlock_irqrestore(&kn01_lock, flags);
58}
59
60static int dec_kn01_be_backend(struct pt_regs *regs, int is_fixup, int invoker)
61{
62 volatile u32 *kn01_erraddr = (void *)CKSEG1ADDR(KN01_SLOT_BASE +
63 KN01_ERRADDR);
64
65 static const char excstr[] = "exception";
66 static const char intstr[] = "interrupt";
67 static const char cpustr[] = "CPU";
68 static const char mreadstr[] = "memory read";
69 static const char readstr[] = "read";
70 static const char writestr[] = "write";
71 static const char timestr[] = "timeout";
72 static const char paritystr[] = "parity error";
73
74 int data = regs->cp0_cause & 4;
75 unsigned int __user *pc = (unsigned int __user *)regs->cp0_epc +
76 ((regs->cp0_cause & CAUSEF_BD) != 0);
77 union mips_instruction insn;
78 unsigned long entrylo, offset;
79 long asid, entryhi, vaddr;
80
81 const char *kind, *agent, *cycle, *event;
82 unsigned long address;
83
84 u32 erraddr = *kn01_erraddr;
85 int action = MIPS_BE_FATAL;
86
87 /* Ack ASAP, so that any subsequent errors get caught. */
88 dec_kn01_be_ack();
89
90 kind = invoker ? intstr : excstr;
91
92 agent = cpustr;
93
94 if (invoker)
95 address = erraddr;
96 else {
97 /* Bloody hardware doesn't record the address for reads... */
98 if (data) {
99 /* This never faults. */
100 __get_user(insn.word, pc);
101 vaddr = regs->regs[insn.i_format.rs] +
102 insn.i_format.simmediate;
103 } else
104 vaddr = (long)pc;
105 if (KSEGX(vaddr) == CKSEG0 || KSEGX(vaddr) == CKSEG1)
106 address = CPHYSADDR(vaddr);
107 else {
108 /* Peek at what physical address the CPU used. */
109 asid = read_c0_entryhi();
110 entryhi = asid & (PAGE_SIZE - 1);
111 entryhi |= vaddr & ~(PAGE_SIZE - 1);
112 write_c0_entryhi(entryhi);
113 BARRIER;
114 tlb_probe();
115 /* No need to check for presence. */
116 tlb_read();
117 entrylo = read_c0_entrylo0();
118 write_c0_entryhi(asid);
119 offset = vaddr & (PAGE_SIZE - 1);
120 address = (entrylo & ~(PAGE_SIZE - 1)) | offset;
121 }
122 }
123
124 /* Treat low 256MB as memory, high -- as I/O. */
125 if (address < 0x10000000) {
126 cycle = mreadstr;
127 event = paritystr;
128 } else {
129 cycle = invoker ? writestr : readstr;
130 event = timestr;
131 }
132
133 if (is_fixup)
134 action = MIPS_BE_FIXUP;
135
136 if (action != MIPS_BE_FIXUP)
137 printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
138 kind, agent, cycle, event, address);
139
140 return action;
141}
142
143int dec_kn01_be_handler(struct pt_regs *regs, int is_fixup)
144{
145 return dec_kn01_be_backend(regs, is_fixup, 0);
146}
147
148irqreturn_t dec_kn01_be_interrupt(int irq, void *dev_id)
149{
150 volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
151 struct pt_regs *regs = get_irq_regs();
152 int action;
153
154 if (!(*csr & KN01_CSR_MEMERR))
155 return IRQ_NONE; /* Must have been video. */
156
157 action = dec_kn01_be_backend(regs, 0, 1);
158
159 if (action == MIPS_BE_DISCARD)
160 return IRQ_HANDLED;
161
162 /*
163 * FIXME: Find the affected processes and kill them, otherwise
164 * we must die.
165 *
166 * The interrupt is asynchronously delivered thus EPC and RA
167 * may be irrelevant, but are printed for a reference.
168 */
169 printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n",
170 regs->cp0_epc, regs->regs[31]);
171 die("Unrecoverable bus error", regs);
172}
173
174
175void __init dec_kn01_be_init(void)
176{
177 volatile u16 *csr = (void *)CKSEG1ADDR(KN01_SLOT_BASE + KN01_CSR);
178 unsigned long flags;
179
180 raw_spin_lock_irqsave(&kn01_lock, flags);
181
182 /* Preset write-only bits of the Control Register cache. */
183 cached_kn01_csr = *csr;
184 cached_kn01_csr &= KN01_CSR_STATUS | KN01_CSR_PARDIS | KN01_CSR_TXDIS;
185 cached_kn01_csr |= KN01_CSR_LEDS;
186
187 /* Enable parity error detection. */
188 cached_kn01_csr &= ~KN01_CSR_PARDIS;
189 *csr = cached_kn01_csr;
190 iob();
191
192 raw_spin_unlock_irqrestore(&kn01_lock, flags);
193
194 /* Clear any leftover errors from the firmware. */
195 dec_kn01_be_ack();
196}
diff --git a/arch/mips/dec/kn02-irq.c b/arch/mips/dec/kn02-irq.c
new file mode 100644
index 000000000..7e18de574
--- /dev/null
+++ b/arch/mips/dec/kn02-irq.c
@@ -0,0 +1,75 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * DECstation 5000/200 (KN02) Control and Status Register
4 * interrupts.
5 *
6 * Copyright (c) 2002, 2003, 2005 Maciej W. Rozycki
7 */
8
9#include <linux/init.h>
10#include <linux/irq.h>
11#include <linux/types.h>
12
13#include <asm/dec/kn02.h>
14
15
16/*
17 * Bits 7:0 of the Control Register are write-only -- the
18 * corresponding bits of the Status Register have a different
19 * meaning. Hence we use a cache. It speeds up things a bit
20 * as well.
21 *
22 * There is no default value -- it has to be initialized.
23 */
24u32 cached_kn02_csr;
25
26static int kn02_irq_base;
27
28static void unmask_kn02_irq(struct irq_data *d)
29{
30 volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
31 KN02_CSR);
32
33 cached_kn02_csr |= (1 << (d->irq - kn02_irq_base + 16));
34 *csr = cached_kn02_csr;
35}
36
37static void mask_kn02_irq(struct irq_data *d)
38{
39 volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
40 KN02_CSR);
41
42 cached_kn02_csr &= ~(1 << (d->irq - kn02_irq_base + 16));
43 *csr = cached_kn02_csr;
44}
45
46static void ack_kn02_irq(struct irq_data *d)
47{
48 mask_kn02_irq(d);
49 iob();
50}
51
52static struct irq_chip kn02_irq_type = {
53 .name = "KN02-CSR",
54 .irq_ack = ack_kn02_irq,
55 .irq_mask = mask_kn02_irq,
56 .irq_mask_ack = ack_kn02_irq,
57 .irq_unmask = unmask_kn02_irq,
58};
59
60void __init init_kn02_irqs(int base)
61{
62 volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
63 KN02_CSR);
64 int i;
65
66 /* Mask interrupts. */
67 cached_kn02_csr &= ~KN02_CSR_IOINTEN;
68 *csr = cached_kn02_csr;
69 iob();
70
71 for (i = base; i < base + KN02_IRQ_LINES; i++)
72 irq_set_chip_and_handler(i, &kn02_irq_type, handle_level_irq);
73
74 kn02_irq_base = base;
75}
diff --git a/arch/mips/dec/kn02xa-berr.c b/arch/mips/dec/kn02xa-berr.c
new file mode 100644
index 000000000..9699fc4e6
--- /dev/null
+++ b/arch/mips/dec/kn02xa-berr.c
@@ -0,0 +1,135 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Bus error event handling code for 5000-series systems equipped
4 * with parity error detection logic, i.e. DECstation/DECsystem
5 * 5000/120, /125, /133 (KN02-BA), 5000/150 (KN04-BA) and Personal
6 * DECstation/DECsystem 5000/20, /25, /33 (KN02-CA), 5000/50
7 * (KN04-CA) systems.
8 *
9 * Copyright (c) 2005 Maciej W. Rozycki
10 */
11
12#include <linux/init.h>
13#include <linux/interrupt.h>
14#include <linux/kernel.h>
15#include <linux/types.h>
16
17#include <asm/addrspace.h>
18#include <asm/cpu-type.h>
19#include <asm/irq_regs.h>
20#include <asm/ptrace.h>
21#include <asm/traps.h>
22
23#include <asm/dec/kn02ca.h>
24#include <asm/dec/kn02xa.h>
25#include <asm/dec/kn05.h>
26
27static inline void dec_kn02xa_be_ack(void)
28{
29 volatile u32 *mer = (void *)CKSEG1ADDR(KN02XA_MER);
30 volatile u32 *mem_intr = (void *)CKSEG1ADDR(KN02XA_MEM_INTR);
31
32 *mer = KN02CA_MER_INTR; /* Clear errors; keep the ARC IRQ. */
33 *mem_intr = 0; /* Any write clears the bus IRQ. */
34 iob();
35}
36
37static int dec_kn02xa_be_backend(struct pt_regs *regs, int is_fixup,
38 int invoker)
39{
40 volatile u32 *kn02xa_mer = (void *)CKSEG1ADDR(KN02XA_MER);
41 volatile u32 *kn02xa_ear = (void *)CKSEG1ADDR(KN02XA_EAR);
42
43 static const char excstr[] = "exception";
44 static const char intstr[] = "interrupt";
45 static const char cpustr[] = "CPU";
46 static const char mreadstr[] = "memory read";
47 static const char readstr[] = "read";
48 static const char writestr[] = "write";
49 static const char timestr[] = "timeout";
50 static const char paritystr[] = "parity error";
51 static const char lanestat[][4] = { " OK", "BAD" };
52
53 const char *kind, *agent, *cycle, *event;
54 unsigned long address;
55
56 u32 mer = *kn02xa_mer;
57 u32 ear = *kn02xa_ear;
58 int action = MIPS_BE_FATAL;
59
60 /* Ack ASAP, so that any subsequent errors get caught. */
61 dec_kn02xa_be_ack();
62
63 kind = invoker ? intstr : excstr;
64
65 /* No DMA errors? */
66 agent = cpustr;
67
68 address = ear & KN02XA_EAR_ADDRESS;
69
70 /* Low 256MB is decoded as memory, high -- as TC. */
71 if (address < 0x10000000) {
72 cycle = mreadstr;
73 event = paritystr;
74 } else {
75 cycle = invoker ? writestr : readstr;
76 event = timestr;
77 }
78
79 if (is_fixup)
80 action = MIPS_BE_FIXUP;
81
82 if (action != MIPS_BE_FIXUP)
83 printk(KERN_ALERT "Bus error %s: %s %s %s at %#010lx\n",
84 kind, agent, cycle, event, address);
85
86 if (action != MIPS_BE_FIXUP && address < 0x10000000)
87 printk(KERN_ALERT " Byte lane status %#3x -- "
88 "#3: %s, #2: %s, #1: %s, #0: %s\n",
89 (mer & KN02XA_MER_BYTERR) >> 8,
90 lanestat[(mer & KN02XA_MER_BYTERR_3) != 0],
91 lanestat[(mer & KN02XA_MER_BYTERR_2) != 0],
92 lanestat[(mer & KN02XA_MER_BYTERR_1) != 0],
93 lanestat[(mer & KN02XA_MER_BYTERR_0) != 0]);
94
95 return action;
96}
97
98int dec_kn02xa_be_handler(struct pt_regs *regs, int is_fixup)
99{
100 return dec_kn02xa_be_backend(regs, is_fixup, 0);
101}
102
103irqreturn_t dec_kn02xa_be_interrupt(int irq, void *dev_id)
104{
105 struct pt_regs *regs = get_irq_regs();
106 int action = dec_kn02xa_be_backend(regs, 0, 1);
107
108 if (action == MIPS_BE_DISCARD)
109 return IRQ_HANDLED;
110
111 /*
112 * FIXME: Find the affected processes and kill them, otherwise
113 * we must die.
114 *
115 * The interrupt is asynchronously delivered thus EPC and RA
116 * may be irrelevant, but are printed for a reference.
117 */
118 printk(KERN_ALERT "Fatal bus interrupt, epc == %08lx, ra == %08lx\n",
119 regs->cp0_epc, regs->regs[31]);
120 die("Unrecoverable bus error", regs);
121}
122
123
124void __init dec_kn02xa_be_init(void)
125{
126 volatile u32 *mbcs = (void *)CKSEG1ADDR(KN4K_SLOT_BASE + KN4K_MB_CSR);
127
128 /* For KN04 we need to make sure EE (?) is enabled in the MB. */
129 if (current_cpu_type() == CPU_R4000SC)
130 *mbcs |= KN4K_MB_CSR_EE;
131 fast_iob();
132
133 /* Clear any leftover errors from the firmware. */
134 dec_kn02xa_be_ack();
135}
diff --git a/arch/mips/dec/platform.c b/arch/mips/dec/platform.c
new file mode 100644
index 000000000..c4fcb8c58
--- /dev/null
+++ b/arch/mips/dec/platform.c
@@ -0,0 +1,40 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * DEC platform devices.
4 *
5 * Copyright (c) 2014 Maciej W. Rozycki
6 */
7
8#include <linux/ioport.h>
9#include <linux/kernel.h>
10#include <linux/mc146818rtc.h>
11#include <linux/platform_device.h>
12
13static struct resource dec_rtc_resources[] = {
14 {
15 .name = "rtc",
16 .flags = IORESOURCE_MEM,
17 },
18};
19
20static struct cmos_rtc_board_info dec_rtc_info = {
21 .flags = CMOS_RTC_FLAGS_NOFREQ,
22 .address_space = 64,
23};
24
25static struct platform_device dec_rtc_device = {
26 .name = "rtc_cmos",
27 .id = PLATFORM_DEVID_NONE,
28 .dev.platform_data = &dec_rtc_info,
29 .resource = dec_rtc_resources,
30 .num_resources = ARRAY_SIZE(dec_rtc_resources),
31};
32
33static int __init dec_add_devices(void)
34{
35 dec_rtc_resources[0].start = RTC_PORT(0);
36 dec_rtc_resources[0].end = RTC_PORT(0) + dec_kn_slot_size - 1;
37 return platform_device_register(&dec_rtc_device);
38}
39
40device_initcall(dec_add_devices);
diff --git a/arch/mips/dec/prom/Makefile b/arch/mips/dec/prom/Makefile
new file mode 100644
index 000000000..2bad87551
--- /dev/null
+++ b/arch/mips/dec/prom/Makefile
@@ -0,0 +1,9 @@
1# SPDX-License-Identifier: GPL-2.0-only
2#
3# Makefile for the DECstation prom monitor library routines
4# under Linux.
5#
6
7lib-y += init.o memory.o cmdline.o identify.o console.o
8
9lib-$(CONFIG_CPU_R3000) += locore.o
diff --git a/arch/mips/dec/prom/cmdline.c b/arch/mips/dec/prom/cmdline.c
new file mode 100644
index 000000000..3ed63280a
--- /dev/null
+++ b/arch/mips/dec/prom/cmdline.c
@@ -0,0 +1,40 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * cmdline.c: read the command line passed to us by the PROM.
4 *
5 * Copyright (C) 1998 Harald Koerfgen
6 * Copyright (C) 2002, 2004 Maciej W. Rozycki
7 */
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/string.h>
11#include <linux/types.h>
12
13#include <asm/bootinfo.h>
14#include <asm/dec/prom.h>
15
16#undef PROM_DEBUG
17
18void __init prom_init_cmdline(s32 argc, s32 *argv, u32 magic)
19{
20 char *arg;
21 int start_arg, i;
22
23 /*
24 * collect args and prepare cmd_line
25 */
26 if (!prom_is_rex(magic))
27 start_arg = 1;
28 else
29 start_arg = 2;
30 for (i = start_arg; i < argc; i++) {
31 arg = (void *)(long)(argv[i]);
32 strcat(arcs_cmdline, arg);
33 if (i < (argc - 1))
34 strcat(arcs_cmdline, " ");
35 }
36
37#ifdef PROM_DEBUG
38 printk("arcs_cmdline: %s\n", &(arcs_cmdline[0]));
39#endif
40}
diff --git a/arch/mips/dec/prom/console.c b/arch/mips/dec/prom/console.c
new file mode 100644
index 000000000..31a8441d8
--- /dev/null
+++ b/arch/mips/dec/prom/console.c
@@ -0,0 +1,41 @@
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * DECstation PROM-based early console support.
4 *
5 * Copyright (C) 2004, 2007 Maciej W. Rozycki
6 */
7#include <linux/console.h>
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/string.h>
11
12#include <asm/dec/prom.h>
13
14static void __init prom_console_write(struct console *con, const char *s,
15 unsigned int c)
16{
17 char buf[81];
18 unsigned int chunk = sizeof(buf) - 1;
19
20 while (c > 0) {
21 if (chunk > c)
22 chunk = c;
23 memcpy(buf, s, chunk);
24 buf[chunk] = '\0';
25 prom_printf("%s", buf);
26 s += chunk;
27 c -= chunk;
28 }
29}
30
31static struct console promcons __initdata = {
32 .name = "prom",
33 .write = prom_console_write,
34 .flags = CON_BOOT | CON_PRINTBUFFER,
35 .index = -1,
36};
37
38void __init register_prom_console(void)
39{
40 register_console(&promcons);
41}
diff --git a/arch/mips/dec/prom/dectypes.h b/arch/mips/dec/prom/dectypes.h
new file mode 100644
index 000000000..9fcbcc7cd
--- /dev/null
+++ b/arch/mips/dec/prom/dectypes.h
@@ -0,0 +1,15 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef DECTYPES
3#define DECTYPES
4
5#define DS2100_3100 1 /* DS2100/3100 Pmax */
6#define DS5000_200 2 /* DS5000/200 3max */
7#define DS5000_1XX 3 /* DS5000/1xx kmin */
8#define DS5000_2X0 4 /* DS5000/2x0 3max+ */
9#define DS5800 5 /* DS5800 Isis */
10#define DS5400 6 /* DS5400 MIPSfair */
11#define DS5000_XX 7 /* DS5000/xx maxine */
12#define DS5500 11 /* DS5500 MIPSfair-2 */
13#define DS5100 12 /* DS5100 MIPSmate */
14
15#endif
diff --git a/arch/mips/dec/prom/identify.c b/arch/mips/dec/prom/identify.c
new file mode 100644
index 000000000..80cd14cd1
--- /dev/null
+++ b/arch/mips/dec/prom/identify.c
@@ -0,0 +1,187 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * identify.c: machine identification code.
4 *
5 * Copyright (C) 1998 Harald Koerfgen and Paul M. Antoine
6 * Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki
7 */
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/mc146818rtc.h>
11#include <linux/export.h>
12#include <linux/string.h>
13#include <linux/types.h>
14
15#include <asm/bootinfo.h>
16
17#include <asm/dec/ioasic.h>
18#include <asm/dec/ioasic_addrs.h>
19#include <asm/dec/kn01.h>
20#include <asm/dec/kn02.h>
21#include <asm/dec/kn02ba.h>
22#include <asm/dec/kn02ca.h>
23#include <asm/dec/kn03.h>
24#include <asm/dec/kn230.h>
25#include <asm/dec/prom.h>
26#include <asm/dec/system.h>
27
28#include "dectypes.h"
29
30static const char *dec_system_strings[] = {
31 [MACH_DSUNKNOWN] "unknown DECstation",
32 [MACH_DS23100] "DECstation 2100/3100",
33 [MACH_DS5100] "DECsystem 5100",
34 [MACH_DS5000_200] "DECstation 5000/200",
35 [MACH_DS5000_1XX] "DECstation 5000/1xx",
36 [MACH_DS5000_XX] "Personal DECstation 5000/xx",
37 [MACH_DS5000_2X0] "DECstation 5000/2x0",
38 [MACH_DS5400] "DECsystem 5400",
39 [MACH_DS5500] "DECsystem 5500",
40 [MACH_DS5800] "DECsystem 5800",
41 [MACH_DS5900] "DECsystem 5900",
42};
43
44const char *get_system_type(void)
45{
46#define STR_BUF_LEN 64
47 static char system[STR_BUF_LEN];
48 static int called = 0;
49
50 if (called == 0) {
51 called = 1;
52 snprintf(system, STR_BUF_LEN, "Digital %s",
53 dec_system_strings[mips_machtype]);
54 }
55
56 return system;
57}
58
59
60/*
61 * Setup essential system-specific memory addresses. We need them
62 * early. Semantically the functions belong to prom/init.c, but they
63 * are compact enough we want them inlined. --macro
64 */
65volatile u8 *dec_rtc_base;
66
67EXPORT_SYMBOL(dec_rtc_base);
68
69static inline void prom_init_kn01(void)
70{
71 dec_kn_slot_base = KN01_SLOT_BASE;
72 dec_kn_slot_size = KN01_SLOT_SIZE;
73
74 dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC);
75}
76
77static inline void prom_init_kn230(void)
78{
79 dec_kn_slot_base = KN01_SLOT_BASE;
80 dec_kn_slot_size = KN01_SLOT_SIZE;
81
82 dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN01_RTC);
83}
84
85static inline void prom_init_kn02(void)
86{
87 dec_kn_slot_base = KN02_SLOT_BASE;
88 dec_kn_slot_size = KN02_SLOT_SIZE;
89 dec_tc_bus = 1;
90
91 dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + KN02_RTC);
92}
93
94static inline void prom_init_kn02xa(void)
95{
96 dec_kn_slot_base = KN02XA_SLOT_BASE;
97 dec_kn_slot_size = IOASIC_SLOT_SIZE;
98 dec_tc_bus = 1;
99
100 ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
101 dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
102}
103
104static inline void prom_init_kn03(void)
105{
106 dec_kn_slot_base = KN03_SLOT_BASE;
107 dec_kn_slot_size = IOASIC_SLOT_SIZE;
108 dec_tc_bus = 1;
109
110 ioasic_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_IOCTL);
111 dec_rtc_base = (void *)CKSEG1ADDR(dec_kn_slot_base + IOASIC_TOY);
112}
113
114
115void __init prom_identify_arch(u32 magic)
116{
117 unsigned char dec_cpunum, dec_firmrev, dec_etc, dec_systype;
118 u32 dec_sysid;
119
120 if (!prom_is_rex(magic)) {
121 dec_sysid = simple_strtoul(prom_getenv("systype"),
122 (char **)0, 0);
123 } else {
124 dec_sysid = rex_getsysid();
125 if (dec_sysid == 0) {
126 printk("Zero sysid returned from PROM! "
127 "Assuming a PMAX-like machine.\n");
128 dec_sysid = 1;
129 }
130 }
131
132 dec_cpunum = (dec_sysid & 0xff000000) >> 24;
133 dec_systype = (dec_sysid & 0xff0000) >> 16;
134 dec_firmrev = (dec_sysid & 0xff00) >> 8;
135 dec_etc = dec_sysid & 0xff;
136
137 /*
138 * FIXME: This may not be an exhaustive list of DECStations/Servers!
139 * Put all model-specific initialisation calls here.
140 */
141 switch (dec_systype) {
142 case DS2100_3100:
143 mips_machtype = MACH_DS23100;
144 prom_init_kn01();
145 break;
146 case DS5100: /* DS5100 MIPSMATE */
147 mips_machtype = MACH_DS5100;
148 prom_init_kn230();
149 break;
150 case DS5000_200: /* DS5000 3max */
151 mips_machtype = MACH_DS5000_200;
152 prom_init_kn02();
153 break;
154 case DS5000_1XX: /* DS5000/100 3min */
155 mips_machtype = MACH_DS5000_1XX;
156 prom_init_kn02xa();
157 break;
158 case DS5000_2X0: /* DS5000/240 3max+ or DS5900 bigmax */
159 mips_machtype = MACH_DS5000_2X0;
160 prom_init_kn03();
161 if (!(ioasic_read(IO_REG_SIR) & KN03_IO_INR_3MAXP))
162 mips_machtype = MACH_DS5900;
163 break;
164 case DS5000_XX: /* Personal DS5000/xx maxine */
165 mips_machtype = MACH_DS5000_XX;
166 prom_init_kn02xa();
167 break;
168 case DS5800: /* DS5800 Isis */
169 mips_machtype = MACH_DS5800;
170 break;
171 case DS5400: /* DS5400 MIPSfair */
172 mips_machtype = MACH_DS5400;
173 break;
174 case DS5500: /* DS5500 MIPSfair-2 */
175 mips_machtype = MACH_DS5500;
176 break;
177 default:
178 mips_machtype = MACH_DSUNKNOWN;
179 break;
180 }
181
182 if (mips_machtype == MACH_DSUNKNOWN)
183 printk("This is an %s, id is %x\n",
184 dec_system_strings[mips_machtype], dec_systype);
185 else
186 printk("This is a %s\n", dec_system_strings[mips_machtype]);
187}
diff --git a/arch/mips/dec/prom/init.c b/arch/mips/dec/prom/init.c
new file mode 100644
index 000000000..cc988bbd2
--- /dev/null
+++ b/arch/mips/dec/prom/init.c
@@ -0,0 +1,137 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * init.c: PROM library initialisation code.
4 *
5 * Copyright (C) 1998 Harald Koerfgen
6 * Copyright (C) 2002, 2004 Maciej W. Rozycki
7 */
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/linkage.h>
11#include <linux/smp.h>
12#include <linux/string.h>
13#include <linux/types.h>
14
15#include <asm/bootinfo.h>
16#include <asm/cpu.h>
17#include <asm/cpu-type.h>
18#include <asm/processor.h>
19
20#include <asm/dec/prom.h>
21
22
23int (*__rex_bootinit)(void);
24int (*__rex_bootread)(void);
25int (*__rex_getbitmap)(memmap *);
26unsigned long *(*__rex_slot_address)(int);
27void *(*__rex_gettcinfo)(void);
28int (*__rex_getsysid)(void);
29void (*__rex_clear_cache)(void);
30
31int (*__prom_getchar)(void);
32char *(*__prom_getenv)(char *);
33int (*__prom_printf)(char *, ...);
34
35int (*__pmax_open)(char*, int);
36int (*__pmax_lseek)(int, long, int);
37int (*__pmax_read)(int, void *, int);
38int (*__pmax_close)(int);
39
40
41/*
42 * Detect which PROM the DECSTATION has, and set the callback vectors
43 * appropriately.
44 */
45void __init which_prom(s32 magic, s32 *prom_vec)
46{
47 /*
48 * No sign of the REX PROM's magic number means we assume a non-REX
49 * machine (i.e. we're on a DS2100/3100, DS5100 or DS5000/2xx)
50 */
51 if (prom_is_rex(magic)) {
52 /*
53 * Set up prom abstraction structure with REX entry points.
54 */
55 __rex_bootinit =
56 (void *)(long)*(prom_vec + REX_PROM_BOOTINIT);
57 __rex_bootread =
58 (void *)(long)*(prom_vec + REX_PROM_BOOTREAD);
59 __rex_getbitmap =
60 (void *)(long)*(prom_vec + REX_PROM_GETBITMAP);
61 __prom_getchar =
62 (void *)(long)*(prom_vec + REX_PROM_GETCHAR);
63 __prom_getenv =
64 (void *)(long)*(prom_vec + REX_PROM_GETENV);
65 __rex_getsysid =
66 (void *)(long)*(prom_vec + REX_PROM_GETSYSID);
67 __rex_gettcinfo =
68 (void *)(long)*(prom_vec + REX_PROM_GETTCINFO);
69 __prom_printf =
70 (void *)(long)*(prom_vec + REX_PROM_PRINTF);
71 __rex_slot_address =
72 (void *)(long)*(prom_vec + REX_PROM_SLOTADDR);
73 __rex_clear_cache =
74 (void *)(long)*(prom_vec + REX_PROM_CLEARCACHE);
75 } else {
76 /*
77 * Set up prom abstraction structure with non-REX entry points.
78 */
79 __prom_getchar = (void *)PMAX_PROM_GETCHAR;
80 __prom_getenv = (void *)PMAX_PROM_GETENV;
81 __prom_printf = (void *)PMAX_PROM_PRINTF;
82 __pmax_open = (void *)PMAX_PROM_OPEN;
83 __pmax_lseek = (void *)PMAX_PROM_LSEEK;
84 __pmax_read = (void *)PMAX_PROM_READ;
85 __pmax_close = (void *)PMAX_PROM_CLOSE;
86 }
87}
88
89void __init prom_init(void)
90{
91 extern void dec_machine_halt(void);
92 static const char cpu_msg[] __initconst =
93 "Sorry, this kernel is compiled for a wrong CPU type!\n";
94 s32 argc = fw_arg0;
95 s32 *argv = (void *)fw_arg1;
96 u32 magic = fw_arg2;
97 s32 *prom_vec = (void *)fw_arg3;
98
99 /*
100 * Determine which PROM we have
101 * (and therefore which machine we're on!)
102 */
103 which_prom(magic, prom_vec);
104
105 if (prom_is_rex(magic))
106 rex_clear_cache();
107
108 /* Register the early console. */
109 register_prom_console();
110
111 /* Were we compiled with the right CPU option? */
112#if defined(CONFIG_CPU_R3000)
113 if ((current_cpu_type() == CPU_R4000SC) ||
114 (current_cpu_type() == CPU_R4400SC)) {
115 static const char r4k_msg[] __initconst =
116 "Please recompile with \"CONFIG_CPU_R4x00 = y\".\n";
117 printk(cpu_msg);
118 printk(r4k_msg);
119 dec_machine_halt();
120 }
121#endif
122
123#if defined(CONFIG_CPU_R4X00)
124 if ((current_cpu_type() == CPU_R3000) ||
125 (current_cpu_type() == CPU_R3000A)) {
126 static const char r3k_msg[] __initconst =
127 "Please recompile with \"CONFIG_CPU_R3000 = y\".\n";
128 printk(cpu_msg);
129 printk(r3k_msg);
130 dec_machine_halt();
131 }
132#endif
133
134 prom_meminit(magic);
135 prom_identify_arch(magic);
136 prom_init_cmdline(argc, argv, magic);
137}
diff --git a/arch/mips/dec/prom/locore.S b/arch/mips/dec/prom/locore.S
new file mode 100644
index 000000000..0eb8fab62
--- /dev/null
+++ b/arch/mips/dec/prom/locore.S
@@ -0,0 +1,30 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * locore.S
4 */
5#include <asm/asm.h>
6#include <asm/regdef.h>
7#include <asm/mipsregs.h>
8
9 .text
10
11/*
12 * Simple general exception handling routine. This one is used for the
13 * Memory sizing routine for pmax machines. HK
14 */
15
16NESTED(genexcept_early, 0, sp)
17 .set noat
18 .set noreorder
19
20 mfc0 k0, CP0_STATUS
21 la k1, mem_err
22
23 sw k0, 0(k1)
24
25 mfc0 k0, CP0_EPC
26 nop
27 addiu k0, 4 # skip the causing instruction
28 jr k0
29 rfe
30END(genexcept_early)
diff --git a/arch/mips/dec/prom/memory.c b/arch/mips/dec/prom/memory.c
new file mode 100644
index 000000000..44490c30d
--- /dev/null
+++ b/arch/mips/dec/prom/memory.c
@@ -0,0 +1,117 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * memory.c: memory initialisation code.
4 *
5 * Copyright (C) 1998 Harald Koerfgen, Frieder Streffer and Paul M. Antoine
6 * Copyright (C) 2000, 2002 Maciej W. Rozycki
7 */
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/mm.h>
11#include <linux/memblock.h>
12#include <linux/types.h>
13
14#include <asm/addrspace.h>
15#include <asm/dec/machtype.h>
16#include <asm/dec/prom.h>
17#include <asm/page.h>
18#include <asm/sections.h>
19
20
21volatile unsigned long mem_err; /* So we know an error occurred */
22
23/*
24 * Probe memory in 4MB chunks, waiting for an error to tell us we've fallen
25 * off the end of real memory. Only suitable for the 2100/3100's (PMAX).
26 */
27
28#define CHUNK_SIZE 0x400000
29
30static __init void pmax_setup_memory_region(void)
31{
32 volatile unsigned char *memory_page, dummy;
33 char old_handler[0x80];
34 extern char genexcept_early;
35
36 /* Install exception handler */
37 memcpy(&old_handler, (void *)(CKSEG0 + 0x80), 0x80);
38 memcpy((void *)(CKSEG0 + 0x80), &genexcept_early, 0x80);
39
40 /* read unmapped and uncached (KSEG1)
41 * DECstations have at least 4MB RAM
42 * Assume less than 480MB of RAM, as this is max for 5000/2xx
43 * FIXME this should be replaced by the first free page!
44 */
45 for (memory_page = (unsigned char *)CKSEG1 + CHUNK_SIZE;
46 mem_err == 0 && memory_page < (unsigned char *)CKSEG1 + 0x1e00000;
47 memory_page += CHUNK_SIZE) {
48 dummy = *memory_page;
49 }
50 memcpy((void *)(CKSEG0 + 0x80), &old_handler, 0x80);
51
52 memblock_add(0, (unsigned long)memory_page - CKSEG1 - CHUNK_SIZE);
53}
54
55/*
56 * Use the REX prom calls to get hold of the memory bitmap, and thence
57 * determine memory size.
58 */
59static __init void rex_setup_memory_region(void)
60{
61 int i, bitmap_size;
62 unsigned long mem_start = 0, mem_size = 0;
63 memmap *bm;
64
65 /* some free 64k */
66 bm = (memmap *)CKSEG0ADDR(0x28000);
67
68 bitmap_size = rex_getbitmap(bm);
69
70 for (i = 0; i < bitmap_size; i++) {
71 /* FIXME: very simplistically only add full sets of pages */
72 if (bm->bitmap[i] == 0xff)
73 mem_size += (8 * bm->pagesize);
74 else if (!mem_size)
75 mem_start += (8 * bm->pagesize);
76 else {
77 memblock_add(mem_start, mem_size);
78 mem_start += mem_size + (8 * bm->pagesize);
79 mem_size = 0;
80 }
81 }
82 if (mem_size)
83 memblock_add(mem_start, mem_size);
84}
85
86void __init prom_meminit(u32 magic)
87{
88 if (!prom_is_rex(magic))
89 pmax_setup_memory_region();
90 else
91 rex_setup_memory_region();
92}
93
94void __init prom_free_prom_memory(void)
95{
96 unsigned long end;
97
98 /*
99 * Free everything below the kernel itself but leave
100 * the first page reserved for the exception handlers.
101 */
102
103#if IS_ENABLED(CONFIG_DECLANCE)
104 /*
105 * Leave 128 KB reserved for Lance memory for
106 * IOASIC DECstations.
107 *
108 * XXX: save this address for use in dec_lance.c?
109 */
110 if (IOASIC)
111 end = __pa(&_text) - 0x00020000;
112 else
113#endif
114 end = __pa(&_text);
115
116 free_init_pages("unused PROM memory", PAGE_SIZE, end);
117}
diff --git a/arch/mips/dec/reset.c b/arch/mips/dec/reset.c
new file mode 100644
index 000000000..3df01f1da
--- /dev/null
+++ b/arch/mips/dec/reset.c
@@ -0,0 +1,41 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Reset a DECstation machine.
4 *
5 * Copyright (C) 199x the Anonymous
6 * Copyright (C) 2001, 2002, 2003 Maciej W. Rozycki
7 */
8#include <linux/interrupt.h>
9#include <linux/linkage.h>
10
11#include <asm/addrspace.h>
12
13typedef void __noreturn (* noret_func_t)(void);
14
15static inline void __noreturn back_to_prom(void)
16{
17 noret_func_t func = (void *)CKSEG1ADDR(0x1fc00000);
18
19 func();
20}
21
22void __noreturn dec_machine_restart(char *command)
23{
24 back_to_prom();
25}
26
27void __noreturn dec_machine_halt(void)
28{
29 back_to_prom();
30}
31
32void __noreturn dec_machine_power_off(void)
33{
34 /* DECstations don't have a software power switch */
35 back_to_prom();
36}
37
38irqreturn_t dec_intr_halt(int irq, void *dev_id)
39{
40 dec_machine_halt();
41}
diff --git a/arch/mips/dec/setup.c b/arch/mips/dec/setup.c
new file mode 100644
index 000000000..99b9b2975
--- /dev/null
+++ b/arch/mips/dec/setup.c
@@ -0,0 +1,784 @@
1/*
2 * System-specific setup, especially interrupts.
3 *
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details.
7 *
8 * Copyright (C) 1998 Harald Koerfgen
9 * Copyright (C) 2000, 2001, 2002, 2003, 2005, 2020 Maciej W. Rozycki
10 */
11#include <linux/console.h>
12#include <linux/export.h>
13#include <linux/init.h>
14#include <linux/interrupt.h>
15#include <linux/ioport.h>
16#include <linux/irq.h>
17#include <linux/irqnr.h>
18#include <linux/memblock.h>
19#include <linux/param.h>
20#include <linux/percpu-defs.h>
21#include <linux/sched.h>
22#include <linux/spinlock.h>
23#include <linux/types.h>
24#include <linux/pm.h>
25
26#include <asm/addrspace.h>
27#include <asm/bootinfo.h>
28#include <asm/cpu.h>
29#include <asm/cpu-features.h>
30#include <asm/cpu-type.h>
31#include <asm/irq.h>
32#include <asm/irq_cpu.h>
33#include <asm/mipsregs.h>
34#include <asm/page.h>
35#include <asm/reboot.h>
36#include <asm/sections.h>
37#include <asm/time.h>
38#include <asm/traps.h>
39#include <asm/wbflush.h>
40
41#include <asm/dec/interrupts.h>
42#include <asm/dec/ioasic.h>
43#include <asm/dec/ioasic_addrs.h>
44#include <asm/dec/ioasic_ints.h>
45#include <asm/dec/kn01.h>
46#include <asm/dec/kn02.h>
47#include <asm/dec/kn02ba.h>
48#include <asm/dec/kn02ca.h>
49#include <asm/dec/kn03.h>
50#include <asm/dec/kn230.h>
51#include <asm/dec/system.h>
52
53
54extern void dec_machine_restart(char *command);
55extern void dec_machine_halt(void);
56extern void dec_machine_power_off(void);
57extern irqreturn_t dec_intr_halt(int irq, void *dev_id);
58
59unsigned long dec_kn_slot_base, dec_kn_slot_size;
60
61EXPORT_SYMBOL(dec_kn_slot_base);
62EXPORT_SYMBOL(dec_kn_slot_size);
63
64int dec_tc_bus;
65
66DEFINE_SPINLOCK(ioasic_ssr_lock);
67EXPORT_SYMBOL(ioasic_ssr_lock);
68
69volatile u32 *ioasic_base;
70
71EXPORT_SYMBOL(ioasic_base);
72
73/*
74 * IRQ routing and priority tables. Priorites are set as follows:
75 *
76 * KN01 KN230 KN02 KN02-BA KN02-CA KN03
77 *
78 * MEMORY CPU CPU CPU ASIC CPU CPU
79 * RTC CPU CPU CPU ASIC CPU CPU
80 * DMA - - - ASIC ASIC ASIC
81 * SERIAL0 CPU CPU CSR ASIC ASIC ASIC
82 * SERIAL1 - - - ASIC - ASIC
83 * SCSI CPU CPU CSR ASIC ASIC ASIC
84 * ETHERNET CPU * CSR ASIC ASIC ASIC
85 * other - - - ASIC - -
86 * TC2 - - CSR CPU ASIC ASIC
87 * TC1 - - CSR CPU ASIC ASIC
88 * TC0 - - CSR CPU ASIC ASIC
89 * other - CPU - CPU ASIC ASIC
90 * other - - - - CPU CPU
91 *
92 * * -- shared with SCSI
93 */
94
95int dec_interrupt[DEC_NR_INTS] = {
96 [0 ... DEC_NR_INTS - 1] = -1
97};
98
99EXPORT_SYMBOL(dec_interrupt);
100
101int_ptr cpu_mask_nr_tbl[DEC_MAX_CPU_INTS][2] = {
102 { { .i = ~0 }, { .p = dec_intr_unimplemented } },
103};
104int_ptr asic_mask_nr_tbl[DEC_MAX_ASIC_INTS][2] = {
105 { { .i = ~0 }, { .p = asic_intr_unimplemented } },
106};
107int cpu_fpu_mask = DEC_CPU_IRQ_MASK(DEC_CPU_INR_FPU);
108int *fpu_kstat_irq;
109
110static irq_handler_t busirq_handler;
111static unsigned int busirq_flags = IRQF_NO_THREAD;
112
113/*
114 * Bus error (DBE/IBE exceptions and bus interrupts) handling setup.
115 */
116static void __init dec_be_init(void)
117{
118 switch (mips_machtype) {
119 case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */
120 board_be_handler = dec_kn01_be_handler;
121 busirq_handler = dec_kn01_be_interrupt;
122 busirq_flags |= IRQF_SHARED;
123 dec_kn01_be_init();
124 break;
125 case MACH_DS5000_1XX: /* DS5000/1xx 3min */
126 case MACH_DS5000_XX: /* DS5000/xx Maxine */
127 board_be_handler = dec_kn02xa_be_handler;
128 busirq_handler = dec_kn02xa_be_interrupt;
129 dec_kn02xa_be_init();
130 break;
131 case MACH_DS5000_200: /* DS5000/200 3max */
132 case MACH_DS5000_2X0: /* DS5000/240 3max+ */
133 case MACH_DS5900: /* DS5900 bigmax */
134 board_be_handler = dec_ecc_be_handler;
135 busirq_handler = dec_ecc_be_interrupt;
136 dec_ecc_be_init();
137 break;
138 }
139}
140
141void __init plat_mem_setup(void)
142{
143 board_be_init = dec_be_init;
144
145 wbflush_setup();
146
147 _machine_restart = dec_machine_restart;
148 _machine_halt = dec_machine_halt;
149 pm_power_off = dec_machine_power_off;
150
151 ioport_resource.start = ~0UL;
152 ioport_resource.end = 0UL;
153
154 /* Stay away from the firmware working memory area for now. */
155 memblock_reserve(PHYS_OFFSET, __pa_symbol(&_text) - PHYS_OFFSET);
156}
157
158/*
159 * Machine-specific initialisation for KN01, aka DS2100 (aka Pmin)
160 * or DS3100 (aka Pmax).
161 */
162static int kn01_interrupt[DEC_NR_INTS] __initdata = {
163 [DEC_IRQ_CASCADE] = -1,
164 [DEC_IRQ_AB_RECV] = -1,
165 [DEC_IRQ_AB_XMIT] = -1,
166 [DEC_IRQ_DZ11] = DEC_CPU_IRQ_NR(KN01_CPU_INR_DZ11),
167 [DEC_IRQ_ASC] = -1,
168 [DEC_IRQ_FLOPPY] = -1,
169 [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
170 [DEC_IRQ_HALT] = -1,
171 [DEC_IRQ_ISDN] = -1,
172 [DEC_IRQ_LANCE] = DEC_CPU_IRQ_NR(KN01_CPU_INR_LANCE),
173 [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN01_CPU_INR_BUS),
174 [DEC_IRQ_PSU] = -1,
175 [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN01_CPU_INR_RTC),
176 [DEC_IRQ_SCC0] = -1,
177 [DEC_IRQ_SCC1] = -1,
178 [DEC_IRQ_SII] = DEC_CPU_IRQ_NR(KN01_CPU_INR_SII),
179 [DEC_IRQ_TC0] = -1,
180 [DEC_IRQ_TC1] = -1,
181 [DEC_IRQ_TC2] = -1,
182 [DEC_IRQ_TIMER] = -1,
183 [DEC_IRQ_VIDEO] = DEC_CPU_IRQ_NR(KN01_CPU_INR_VIDEO),
184 [DEC_IRQ_ASC_MERR] = -1,
185 [DEC_IRQ_ASC_ERR] = -1,
186 [DEC_IRQ_ASC_DMA] = -1,
187 [DEC_IRQ_FLOPPY_ERR] = -1,
188 [DEC_IRQ_ISDN_ERR] = -1,
189 [DEC_IRQ_ISDN_RXDMA] = -1,
190 [DEC_IRQ_ISDN_TXDMA] = -1,
191 [DEC_IRQ_LANCE_MERR] = -1,
192 [DEC_IRQ_SCC0A_RXERR] = -1,
193 [DEC_IRQ_SCC0A_RXDMA] = -1,
194 [DEC_IRQ_SCC0A_TXERR] = -1,
195 [DEC_IRQ_SCC0A_TXDMA] = -1,
196 [DEC_IRQ_AB_RXERR] = -1,
197 [DEC_IRQ_AB_RXDMA] = -1,
198 [DEC_IRQ_AB_TXERR] = -1,
199 [DEC_IRQ_AB_TXDMA] = -1,
200 [DEC_IRQ_SCC1A_RXERR] = -1,
201 [DEC_IRQ_SCC1A_RXDMA] = -1,
202 [DEC_IRQ_SCC1A_TXERR] = -1,
203 [DEC_IRQ_SCC1A_TXDMA] = -1,
204};
205
206static int_ptr kn01_cpu_mask_nr_tbl[][2] __initdata = {
207 { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_BUS) },
208 { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_BUS) } },
209 { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_RTC) },
210 { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_RTC) } },
211 { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_DZ11) },
212 { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_DZ11) } },
213 { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_SII) },
214 { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_SII) } },
215 { { .i = DEC_CPU_IRQ_MASK(KN01_CPU_INR_LANCE) },
216 { .i = DEC_CPU_IRQ_NR(KN01_CPU_INR_LANCE) } },
217 { { .i = DEC_CPU_IRQ_ALL },
218 { .p = cpu_all_int } },
219};
220
221static void __init dec_init_kn01(void)
222{
223 /* IRQ routing. */
224 memcpy(&dec_interrupt, &kn01_interrupt,
225 sizeof(kn01_interrupt));
226
227 /* CPU IRQ priorities. */
228 memcpy(&cpu_mask_nr_tbl, &kn01_cpu_mask_nr_tbl,
229 sizeof(kn01_cpu_mask_nr_tbl));
230
231 mips_cpu_irq_init();
232
233} /* dec_init_kn01 */
234
235
236/*
237 * Machine-specific initialisation for KN230, aka DS5100, aka MIPSmate.
238 */
239static int kn230_interrupt[DEC_NR_INTS] __initdata = {
240 [DEC_IRQ_CASCADE] = -1,
241 [DEC_IRQ_AB_RECV] = -1,
242 [DEC_IRQ_AB_XMIT] = -1,
243 [DEC_IRQ_DZ11] = DEC_CPU_IRQ_NR(KN230_CPU_INR_DZ11),
244 [DEC_IRQ_ASC] = -1,
245 [DEC_IRQ_FLOPPY] = -1,
246 [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
247 [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN230_CPU_INR_HALT),
248 [DEC_IRQ_ISDN] = -1,
249 [DEC_IRQ_LANCE] = DEC_CPU_IRQ_NR(KN230_CPU_INR_LANCE),
250 [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN230_CPU_INR_BUS),
251 [DEC_IRQ_PSU] = -1,
252 [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN230_CPU_INR_RTC),
253 [DEC_IRQ_SCC0] = -1,
254 [DEC_IRQ_SCC1] = -1,
255 [DEC_IRQ_SII] = DEC_CPU_IRQ_NR(KN230_CPU_INR_SII),
256 [DEC_IRQ_TC0] = -1,
257 [DEC_IRQ_TC1] = -1,
258 [DEC_IRQ_TC2] = -1,
259 [DEC_IRQ_TIMER] = -1,
260 [DEC_IRQ_VIDEO] = -1,
261 [DEC_IRQ_ASC_MERR] = -1,
262 [DEC_IRQ_ASC_ERR] = -1,
263 [DEC_IRQ_ASC_DMA] = -1,
264 [DEC_IRQ_FLOPPY_ERR] = -1,
265 [DEC_IRQ_ISDN_ERR] = -1,
266 [DEC_IRQ_ISDN_RXDMA] = -1,
267 [DEC_IRQ_ISDN_TXDMA] = -1,
268 [DEC_IRQ_LANCE_MERR] = -1,
269 [DEC_IRQ_SCC0A_RXERR] = -1,
270 [DEC_IRQ_SCC0A_RXDMA] = -1,
271 [DEC_IRQ_SCC0A_TXERR] = -1,
272 [DEC_IRQ_SCC0A_TXDMA] = -1,
273 [DEC_IRQ_AB_RXERR] = -1,
274 [DEC_IRQ_AB_RXDMA] = -1,
275 [DEC_IRQ_AB_TXERR] = -1,
276 [DEC_IRQ_AB_TXDMA] = -1,
277 [DEC_IRQ_SCC1A_RXERR] = -1,
278 [DEC_IRQ_SCC1A_RXDMA] = -1,
279 [DEC_IRQ_SCC1A_TXERR] = -1,
280 [DEC_IRQ_SCC1A_TXDMA] = -1,
281};
282
283static int_ptr kn230_cpu_mask_nr_tbl[][2] __initdata = {
284 { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_BUS) },
285 { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_BUS) } },
286 { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_RTC) },
287 { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_RTC) } },
288 { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_DZ11) },
289 { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_DZ11) } },
290 { { .i = DEC_CPU_IRQ_MASK(KN230_CPU_INR_SII) },
291 { .i = DEC_CPU_IRQ_NR(KN230_CPU_INR_SII) } },
292 { { .i = DEC_CPU_IRQ_ALL },
293 { .p = cpu_all_int } },
294};
295
296static void __init dec_init_kn230(void)
297{
298 /* IRQ routing. */
299 memcpy(&dec_interrupt, &kn230_interrupt,
300 sizeof(kn230_interrupt));
301
302 /* CPU IRQ priorities. */
303 memcpy(&cpu_mask_nr_tbl, &kn230_cpu_mask_nr_tbl,
304 sizeof(kn230_cpu_mask_nr_tbl));
305
306 mips_cpu_irq_init();
307
308} /* dec_init_kn230 */
309
310
311/*
312 * Machine-specific initialisation for KN02, aka DS5000/200, aka 3max.
313 */
314static int kn02_interrupt[DEC_NR_INTS] __initdata = {
315 [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02_CPU_INR_CASCADE),
316 [DEC_IRQ_AB_RECV] = -1,
317 [DEC_IRQ_AB_XMIT] = -1,
318 [DEC_IRQ_DZ11] = KN02_IRQ_NR(KN02_CSR_INR_DZ11),
319 [DEC_IRQ_ASC] = KN02_IRQ_NR(KN02_CSR_INR_ASC),
320 [DEC_IRQ_FLOPPY] = -1,
321 [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
322 [DEC_IRQ_HALT] = -1,
323 [DEC_IRQ_ISDN] = -1,
324 [DEC_IRQ_LANCE] = KN02_IRQ_NR(KN02_CSR_INR_LANCE),
325 [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN02_CPU_INR_BUS),
326 [DEC_IRQ_PSU] = -1,
327 [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN02_CPU_INR_RTC),
328 [DEC_IRQ_SCC0] = -1,
329 [DEC_IRQ_SCC1] = -1,
330 [DEC_IRQ_SII] = -1,
331 [DEC_IRQ_TC0] = KN02_IRQ_NR(KN02_CSR_INR_TC0),
332 [DEC_IRQ_TC1] = KN02_IRQ_NR(KN02_CSR_INR_TC1),
333 [DEC_IRQ_TC2] = KN02_IRQ_NR(KN02_CSR_INR_TC2),
334 [DEC_IRQ_TIMER] = -1,
335 [DEC_IRQ_VIDEO] = -1,
336 [DEC_IRQ_ASC_MERR] = -1,
337 [DEC_IRQ_ASC_ERR] = -1,
338 [DEC_IRQ_ASC_DMA] = -1,
339 [DEC_IRQ_FLOPPY_ERR] = -1,
340 [DEC_IRQ_ISDN_ERR] = -1,
341 [DEC_IRQ_ISDN_RXDMA] = -1,
342 [DEC_IRQ_ISDN_TXDMA] = -1,
343 [DEC_IRQ_LANCE_MERR] = -1,
344 [DEC_IRQ_SCC0A_RXERR] = -1,
345 [DEC_IRQ_SCC0A_RXDMA] = -1,
346 [DEC_IRQ_SCC0A_TXERR] = -1,
347 [DEC_IRQ_SCC0A_TXDMA] = -1,
348 [DEC_IRQ_AB_RXERR] = -1,
349 [DEC_IRQ_AB_RXDMA] = -1,
350 [DEC_IRQ_AB_TXERR] = -1,
351 [DEC_IRQ_AB_TXDMA] = -1,
352 [DEC_IRQ_SCC1A_RXERR] = -1,
353 [DEC_IRQ_SCC1A_RXDMA] = -1,
354 [DEC_IRQ_SCC1A_TXERR] = -1,
355 [DEC_IRQ_SCC1A_TXDMA] = -1,
356};
357
358static int_ptr kn02_cpu_mask_nr_tbl[][2] __initdata = {
359 { { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_BUS) },
360 { .i = DEC_CPU_IRQ_NR(KN02_CPU_INR_BUS) } },
361 { { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_RTC) },
362 { .i = DEC_CPU_IRQ_NR(KN02_CPU_INR_RTC) } },
363 { { .i = DEC_CPU_IRQ_MASK(KN02_CPU_INR_CASCADE) },
364 { .p = kn02_io_int } },
365 { { .i = DEC_CPU_IRQ_ALL },
366 { .p = cpu_all_int } },
367};
368
369static int_ptr kn02_asic_mask_nr_tbl[][2] __initdata = {
370 { { .i = KN02_IRQ_MASK(KN02_CSR_INR_DZ11) },
371 { .i = KN02_IRQ_NR(KN02_CSR_INR_DZ11) } },
372 { { .i = KN02_IRQ_MASK(KN02_CSR_INR_ASC) },
373 { .i = KN02_IRQ_NR(KN02_CSR_INR_ASC) } },
374 { { .i = KN02_IRQ_MASK(KN02_CSR_INR_LANCE) },
375 { .i = KN02_IRQ_NR(KN02_CSR_INR_LANCE) } },
376 { { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC2) },
377 { .i = KN02_IRQ_NR(KN02_CSR_INR_TC2) } },
378 { { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC1) },
379 { .i = KN02_IRQ_NR(KN02_CSR_INR_TC1) } },
380 { { .i = KN02_IRQ_MASK(KN02_CSR_INR_TC0) },
381 { .i = KN02_IRQ_NR(KN02_CSR_INR_TC0) } },
382 { { .i = KN02_IRQ_ALL },
383 { .p = kn02_all_int } },
384};
385
386static void __init dec_init_kn02(void)
387{
388 /* IRQ routing. */
389 memcpy(&dec_interrupt, &kn02_interrupt,
390 sizeof(kn02_interrupt));
391
392 /* CPU IRQ priorities. */
393 memcpy(&cpu_mask_nr_tbl, &kn02_cpu_mask_nr_tbl,
394 sizeof(kn02_cpu_mask_nr_tbl));
395
396 /* KN02 CSR IRQ priorities. */
397 memcpy(&asic_mask_nr_tbl, &kn02_asic_mask_nr_tbl,
398 sizeof(kn02_asic_mask_nr_tbl));
399
400 mips_cpu_irq_init();
401 init_kn02_irqs(KN02_IRQ_BASE);
402
403} /* dec_init_kn02 */
404
405
406/*
407 * Machine-specific initialisation for KN02-BA, aka DS5000/1xx
408 * (xx = 20, 25, 33), aka 3min. Also applies to KN04(-BA), aka
409 * DS5000/150, aka 4min.
410 */
411static int kn02ba_interrupt[DEC_NR_INTS] __initdata = {
412 [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_CASCADE),
413 [DEC_IRQ_AB_RECV] = -1,
414 [DEC_IRQ_AB_XMIT] = -1,
415 [DEC_IRQ_DZ11] = -1,
416 [DEC_IRQ_ASC] = IO_IRQ_NR(KN02BA_IO_INR_ASC),
417 [DEC_IRQ_FLOPPY] = -1,
418 [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
419 [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_HALT),
420 [DEC_IRQ_ISDN] = -1,
421 [DEC_IRQ_LANCE] = IO_IRQ_NR(KN02BA_IO_INR_LANCE),
422 [DEC_IRQ_BUS] = IO_IRQ_NR(KN02BA_IO_INR_BUS),
423 [DEC_IRQ_PSU] = IO_IRQ_NR(KN02BA_IO_INR_PSU),
424 [DEC_IRQ_RTC] = IO_IRQ_NR(KN02BA_IO_INR_RTC),
425 [DEC_IRQ_SCC0] = IO_IRQ_NR(KN02BA_IO_INR_SCC0),
426 [DEC_IRQ_SCC1] = IO_IRQ_NR(KN02BA_IO_INR_SCC1),
427 [DEC_IRQ_SII] = -1,
428 [DEC_IRQ_TC0] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC0),
429 [DEC_IRQ_TC1] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC1),
430 [DEC_IRQ_TC2] = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC2),
431 [DEC_IRQ_TIMER] = -1,
432 [DEC_IRQ_VIDEO] = -1,
433 [DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR),
434 [DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR),
435 [DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA),
436 [DEC_IRQ_FLOPPY_ERR] = -1,
437 [DEC_IRQ_ISDN_ERR] = -1,
438 [DEC_IRQ_ISDN_RXDMA] = -1,
439 [DEC_IRQ_ISDN_TXDMA] = -1,
440 [DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR),
441 [DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR),
442 [DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA),
443 [DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR),
444 [DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA),
445 [DEC_IRQ_AB_RXERR] = -1,
446 [DEC_IRQ_AB_RXDMA] = -1,
447 [DEC_IRQ_AB_TXERR] = -1,
448 [DEC_IRQ_AB_TXDMA] = -1,
449 [DEC_IRQ_SCC1A_RXERR] = IO_IRQ_NR(IO_INR_SCC1A_RXERR),
450 [DEC_IRQ_SCC1A_RXDMA] = IO_IRQ_NR(IO_INR_SCC1A_RXDMA),
451 [DEC_IRQ_SCC1A_TXERR] = IO_IRQ_NR(IO_INR_SCC1A_TXERR),
452 [DEC_IRQ_SCC1A_TXDMA] = IO_IRQ_NR(IO_INR_SCC1A_TXDMA),
453};
454
455static int_ptr kn02ba_cpu_mask_nr_tbl[][2] __initdata = {
456 { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_CASCADE) },
457 { .p = kn02xa_io_int } },
458 { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC2) },
459 { .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC2) } },
460 { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC1) },
461 { .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC1) } },
462 { { .i = DEC_CPU_IRQ_MASK(KN02BA_CPU_INR_TC0) },
463 { .i = DEC_CPU_IRQ_NR(KN02BA_CPU_INR_TC0) } },
464 { { .i = DEC_CPU_IRQ_ALL },
465 { .p = cpu_all_int } },
466};
467
468static int_ptr kn02ba_asic_mask_nr_tbl[][2] __initdata = {
469 { { .i = IO_IRQ_MASK(KN02BA_IO_INR_BUS) },
470 { .i = IO_IRQ_NR(KN02BA_IO_INR_BUS) } },
471 { { .i = IO_IRQ_MASK(KN02BA_IO_INR_RTC) },
472 { .i = IO_IRQ_NR(KN02BA_IO_INR_RTC) } },
473 { { .i = IO_IRQ_DMA },
474 { .p = asic_dma_int } },
475 { { .i = IO_IRQ_MASK(KN02BA_IO_INR_SCC0) },
476 { .i = IO_IRQ_NR(KN02BA_IO_INR_SCC0) } },
477 { { .i = IO_IRQ_MASK(KN02BA_IO_INR_SCC1) },
478 { .i = IO_IRQ_NR(KN02BA_IO_INR_SCC1) } },
479 { { .i = IO_IRQ_MASK(KN02BA_IO_INR_ASC) },
480 { .i = IO_IRQ_NR(KN02BA_IO_INR_ASC) } },
481 { { .i = IO_IRQ_MASK(KN02BA_IO_INR_LANCE) },
482 { .i = IO_IRQ_NR(KN02BA_IO_INR_LANCE) } },
483 { { .i = IO_IRQ_ALL },
484 { .p = asic_all_int } },
485};
486
487static void __init dec_init_kn02ba(void)
488{
489 /* IRQ routing. */
490 memcpy(&dec_interrupt, &kn02ba_interrupt,
491 sizeof(kn02ba_interrupt));
492
493 /* CPU IRQ priorities. */
494 memcpy(&cpu_mask_nr_tbl, &kn02ba_cpu_mask_nr_tbl,
495 sizeof(kn02ba_cpu_mask_nr_tbl));
496
497 /* I/O ASIC IRQ priorities. */
498 memcpy(&asic_mask_nr_tbl, &kn02ba_asic_mask_nr_tbl,
499 sizeof(kn02ba_asic_mask_nr_tbl));
500
501 mips_cpu_irq_init();
502 init_ioasic_irqs(IO_IRQ_BASE);
503
504} /* dec_init_kn02ba */
505
506
507/*
508 * Machine-specific initialisation for KN02-CA, aka DS5000/xx,
509 * (xx = 20, 25, 33), aka MAXine. Also applies to KN04(-CA), aka
510 * DS5000/50, aka 4MAXine.
511 */
512static int kn02ca_interrupt[DEC_NR_INTS] __initdata = {
513 [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_CASCADE),
514 [DEC_IRQ_AB_RECV] = IO_IRQ_NR(KN02CA_IO_INR_AB_RECV),
515 [DEC_IRQ_AB_XMIT] = IO_IRQ_NR(KN02CA_IO_INR_AB_XMIT),
516 [DEC_IRQ_DZ11] = -1,
517 [DEC_IRQ_ASC] = IO_IRQ_NR(KN02CA_IO_INR_ASC),
518 [DEC_IRQ_FLOPPY] = IO_IRQ_NR(KN02CA_IO_INR_FLOPPY),
519 [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
520 [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_HALT),
521 [DEC_IRQ_ISDN] = IO_IRQ_NR(KN02CA_IO_INR_ISDN),
522 [DEC_IRQ_LANCE] = IO_IRQ_NR(KN02CA_IO_INR_LANCE),
523 [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_BUS),
524 [DEC_IRQ_PSU] = -1,
525 [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_RTC),
526 [DEC_IRQ_SCC0] = IO_IRQ_NR(KN02CA_IO_INR_SCC0),
527 [DEC_IRQ_SCC1] = -1,
528 [DEC_IRQ_SII] = -1,
529 [DEC_IRQ_TC0] = IO_IRQ_NR(KN02CA_IO_INR_TC0),
530 [DEC_IRQ_TC1] = IO_IRQ_NR(KN02CA_IO_INR_TC1),
531 [DEC_IRQ_TC2] = -1,
532 [DEC_IRQ_TIMER] = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_TIMER),
533 [DEC_IRQ_VIDEO] = IO_IRQ_NR(KN02CA_IO_INR_VIDEO),
534 [DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR),
535 [DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR),
536 [DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA),
537 [DEC_IRQ_FLOPPY_ERR] = IO_IRQ_NR(IO_INR_FLOPPY_ERR),
538 [DEC_IRQ_ISDN_ERR] = IO_IRQ_NR(IO_INR_ISDN_ERR),
539 [DEC_IRQ_ISDN_RXDMA] = IO_IRQ_NR(IO_INR_ISDN_RXDMA),
540 [DEC_IRQ_ISDN_TXDMA] = IO_IRQ_NR(IO_INR_ISDN_TXDMA),
541 [DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR),
542 [DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR),
543 [DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA),
544 [DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR),
545 [DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA),
546 [DEC_IRQ_AB_RXERR] = IO_IRQ_NR(IO_INR_AB_RXERR),
547 [DEC_IRQ_AB_RXDMA] = IO_IRQ_NR(IO_INR_AB_RXDMA),
548 [DEC_IRQ_AB_TXERR] = IO_IRQ_NR(IO_INR_AB_TXERR),
549 [DEC_IRQ_AB_TXDMA] = IO_IRQ_NR(IO_INR_AB_TXDMA),
550 [DEC_IRQ_SCC1A_RXERR] = -1,
551 [DEC_IRQ_SCC1A_RXDMA] = -1,
552 [DEC_IRQ_SCC1A_TXERR] = -1,
553 [DEC_IRQ_SCC1A_TXDMA] = -1,
554};
555
556static int_ptr kn02ca_cpu_mask_nr_tbl[][2] __initdata = {
557 { { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_BUS) },
558 { .i = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_BUS) } },
559 { { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_RTC) },
560 { .i = DEC_CPU_IRQ_NR(KN02CA_CPU_INR_RTC) } },
561 { { .i = DEC_CPU_IRQ_MASK(KN02CA_CPU_INR_CASCADE) },
562 { .p = kn02xa_io_int } },
563 { { .i = DEC_CPU_IRQ_ALL },
564 { .p = cpu_all_int } },
565};
566
567static int_ptr kn02ca_asic_mask_nr_tbl[][2] __initdata = {
568 { { .i = IO_IRQ_DMA },
569 { .p = asic_dma_int } },
570 { { .i = IO_IRQ_MASK(KN02CA_IO_INR_SCC0) },
571 { .i = IO_IRQ_NR(KN02CA_IO_INR_SCC0) } },
572 { { .i = IO_IRQ_MASK(KN02CA_IO_INR_ASC) },
573 { .i = IO_IRQ_NR(KN02CA_IO_INR_ASC) } },
574 { { .i = IO_IRQ_MASK(KN02CA_IO_INR_LANCE) },
575 { .i = IO_IRQ_NR(KN02CA_IO_INR_LANCE) } },
576 { { .i = IO_IRQ_MASK(KN02CA_IO_INR_TC1) },
577 { .i = IO_IRQ_NR(KN02CA_IO_INR_TC1) } },
578 { { .i = IO_IRQ_MASK(KN02CA_IO_INR_TC0) },
579 { .i = IO_IRQ_NR(KN02CA_IO_INR_TC0) } },
580 { { .i = IO_IRQ_ALL },
581 { .p = asic_all_int } },
582};
583
584static void __init dec_init_kn02ca(void)
585{
586 /* IRQ routing. */
587 memcpy(&dec_interrupt, &kn02ca_interrupt,
588 sizeof(kn02ca_interrupt));
589
590 /* CPU IRQ priorities. */
591 memcpy(&cpu_mask_nr_tbl, &kn02ca_cpu_mask_nr_tbl,
592 sizeof(kn02ca_cpu_mask_nr_tbl));
593
594 /* I/O ASIC IRQ priorities. */
595 memcpy(&asic_mask_nr_tbl, &kn02ca_asic_mask_nr_tbl,
596 sizeof(kn02ca_asic_mask_nr_tbl));
597
598 mips_cpu_irq_init();
599 init_ioasic_irqs(IO_IRQ_BASE);
600
601} /* dec_init_kn02ca */
602
603
604/*
605 * Machine-specific initialisation for KN03, aka DS5000/240,
606 * aka 3max+ and DS5900, aka BIGmax. Also applies to KN05, aka
607 * DS5000/260, aka 4max+ and DS5900/260.
608 */
609static int kn03_interrupt[DEC_NR_INTS] __initdata = {
610 [DEC_IRQ_CASCADE] = DEC_CPU_IRQ_NR(KN03_CPU_INR_CASCADE),
611 [DEC_IRQ_AB_RECV] = -1,
612 [DEC_IRQ_AB_XMIT] = -1,
613 [DEC_IRQ_DZ11] = -1,
614 [DEC_IRQ_ASC] = IO_IRQ_NR(KN03_IO_INR_ASC),
615 [DEC_IRQ_FLOPPY] = -1,
616 [DEC_IRQ_FPU] = DEC_CPU_IRQ_NR(DEC_CPU_INR_FPU),
617 [DEC_IRQ_HALT] = DEC_CPU_IRQ_NR(KN03_CPU_INR_HALT),
618 [DEC_IRQ_ISDN] = -1,
619 [DEC_IRQ_LANCE] = IO_IRQ_NR(KN03_IO_INR_LANCE),
620 [DEC_IRQ_BUS] = DEC_CPU_IRQ_NR(KN03_CPU_INR_BUS),
621 [DEC_IRQ_PSU] = IO_IRQ_NR(KN03_IO_INR_PSU),
622 [DEC_IRQ_RTC] = DEC_CPU_IRQ_NR(KN03_CPU_INR_RTC),
623 [DEC_IRQ_SCC0] = IO_IRQ_NR(KN03_IO_INR_SCC0),
624 [DEC_IRQ_SCC1] = IO_IRQ_NR(KN03_IO_INR_SCC1),
625 [DEC_IRQ_SII] = -1,
626 [DEC_IRQ_TC0] = IO_IRQ_NR(KN03_IO_INR_TC0),
627 [DEC_IRQ_TC1] = IO_IRQ_NR(KN03_IO_INR_TC1),
628 [DEC_IRQ_TC2] = IO_IRQ_NR(KN03_IO_INR_TC2),
629 [DEC_IRQ_TIMER] = -1,
630 [DEC_IRQ_VIDEO] = -1,
631 [DEC_IRQ_ASC_MERR] = IO_IRQ_NR(IO_INR_ASC_MERR),
632 [DEC_IRQ_ASC_ERR] = IO_IRQ_NR(IO_INR_ASC_ERR),
633 [DEC_IRQ_ASC_DMA] = IO_IRQ_NR(IO_INR_ASC_DMA),
634 [DEC_IRQ_FLOPPY_ERR] = -1,
635 [DEC_IRQ_ISDN_ERR] = -1,
636 [DEC_IRQ_ISDN_RXDMA] = -1,
637 [DEC_IRQ_ISDN_TXDMA] = -1,
638 [DEC_IRQ_LANCE_MERR] = IO_IRQ_NR(IO_INR_LANCE_MERR),
639 [DEC_IRQ_SCC0A_RXERR] = IO_IRQ_NR(IO_INR_SCC0A_RXERR),
640 [DEC_IRQ_SCC0A_RXDMA] = IO_IRQ_NR(IO_INR_SCC0A_RXDMA),
641 [DEC_IRQ_SCC0A_TXERR] = IO_IRQ_NR(IO_INR_SCC0A_TXERR),
642 [DEC_IRQ_SCC0A_TXDMA] = IO_IRQ_NR(IO_INR_SCC0A_TXDMA),
643 [DEC_IRQ_AB_RXERR] = -1,
644 [DEC_IRQ_AB_RXDMA] = -1,
645 [DEC_IRQ_AB_TXERR] = -1,
646 [DEC_IRQ_AB_TXDMA] = -1,
647 [DEC_IRQ_SCC1A_RXERR] = IO_IRQ_NR(IO_INR_SCC1A_RXERR),
648 [DEC_IRQ_SCC1A_RXDMA] = IO_IRQ_NR(IO_INR_SCC1A_RXDMA),
649 [DEC_IRQ_SCC1A_TXERR] = IO_IRQ_NR(IO_INR_SCC1A_TXERR),
650 [DEC_IRQ_SCC1A_TXDMA] = IO_IRQ_NR(IO_INR_SCC1A_TXDMA),
651};
652
653static int_ptr kn03_cpu_mask_nr_tbl[][2] __initdata = {
654 { { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_BUS) },
655 { .i = DEC_CPU_IRQ_NR(KN03_CPU_INR_BUS) } },
656 { { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_RTC) },
657 { .i = DEC_CPU_IRQ_NR(KN03_CPU_INR_RTC) } },
658 { { .i = DEC_CPU_IRQ_MASK(KN03_CPU_INR_CASCADE) },
659 { .p = kn03_io_int } },
660 { { .i = DEC_CPU_IRQ_ALL },
661 { .p = cpu_all_int } },
662};
663
664static int_ptr kn03_asic_mask_nr_tbl[][2] __initdata = {
665 { { .i = IO_IRQ_DMA },
666 { .p = asic_dma_int } },
667 { { .i = IO_IRQ_MASK(KN03_IO_INR_SCC0) },
668 { .i = IO_IRQ_NR(KN03_IO_INR_SCC0) } },
669 { { .i = IO_IRQ_MASK(KN03_IO_INR_SCC1) },
670 { .i = IO_IRQ_NR(KN03_IO_INR_SCC1) } },
671 { { .i = IO_IRQ_MASK(KN03_IO_INR_ASC) },
672 { .i = IO_IRQ_NR(KN03_IO_INR_ASC) } },
673 { { .i = IO_IRQ_MASK(KN03_IO_INR_LANCE) },
674 { .i = IO_IRQ_NR(KN03_IO_INR_LANCE) } },
675 { { .i = IO_IRQ_MASK(KN03_IO_INR_TC2) },
676 { .i = IO_IRQ_NR(KN03_IO_INR_TC2) } },
677 { { .i = IO_IRQ_MASK(KN03_IO_INR_TC1) },
678 { .i = IO_IRQ_NR(KN03_IO_INR_TC1) } },
679 { { .i = IO_IRQ_MASK(KN03_IO_INR_TC0) },
680 { .i = IO_IRQ_NR(KN03_IO_INR_TC0) } },
681 { { .i = IO_IRQ_ALL },
682 { .p = asic_all_int } },
683};
684
685static void __init dec_init_kn03(void)
686{
687 /* IRQ routing. */
688 memcpy(&dec_interrupt, &kn03_interrupt,
689 sizeof(kn03_interrupt));
690
691 /* CPU IRQ priorities. */
692 memcpy(&cpu_mask_nr_tbl, &kn03_cpu_mask_nr_tbl,
693 sizeof(kn03_cpu_mask_nr_tbl));
694
695 /* I/O ASIC IRQ priorities. */
696 memcpy(&asic_mask_nr_tbl, &kn03_asic_mask_nr_tbl,
697 sizeof(kn03_asic_mask_nr_tbl));
698
699 mips_cpu_irq_init();
700 init_ioasic_irqs(IO_IRQ_BASE);
701
702} /* dec_init_kn03 */
703
704
705void __init arch_init_irq(void)
706{
707 switch (mips_machtype) {
708 case MACH_DS23100: /* DS2100/DS3100 Pmin/Pmax */
709 dec_init_kn01();
710 break;
711 case MACH_DS5100: /* DS5100 MIPSmate */
712 dec_init_kn230();
713 break;
714 case MACH_DS5000_200: /* DS5000/200 3max */
715 dec_init_kn02();
716 break;
717 case MACH_DS5000_1XX: /* DS5000/1xx 3min */
718 dec_init_kn02ba();
719 break;
720 case MACH_DS5000_2X0: /* DS5000/240 3max+ */
721 case MACH_DS5900: /* DS5900 bigmax */
722 dec_init_kn03();
723 break;
724 case MACH_DS5000_XX: /* Personal DS5000/xx */
725 dec_init_kn02ca();
726 break;
727 case MACH_DS5800: /* DS5800 Isis */
728 panic("Don't know how to set this up!");
729 break;
730 case MACH_DS5400: /* DS5400 MIPSfair */
731 panic("Don't know how to set this up!");
732 break;
733 case MACH_DS5500: /* DS5500 MIPSfair-2 */
734 panic("Don't know how to set this up!");
735 break;
736 }
737
738 /* Free the FPU interrupt if the exception is present. */
739 if (!cpu_has_nofpuex) {
740 cpu_fpu_mask = 0;
741 dec_interrupt[DEC_IRQ_FPU] = -1;
742 }
743 /* Free the halt interrupt unused on R4k systems. */
744 if (current_cpu_type() == CPU_R4000SC ||
745 current_cpu_type() == CPU_R4400SC)
746 dec_interrupt[DEC_IRQ_HALT] = -1;
747
748 /* Register board interrupts: FPU and cascade. */
749 if (IS_ENABLED(CONFIG_MIPS_FP_SUPPORT) &&
750 dec_interrupt[DEC_IRQ_FPU] >= 0 && cpu_has_fpu) {
751 struct irq_desc *desc_fpu;
752 int irq_fpu;
753
754 irq_fpu = dec_interrupt[DEC_IRQ_FPU];
755 if (request_irq(irq_fpu, no_action, IRQF_NO_THREAD, "fpu",
756 NULL))
757 pr_err("Failed to register fpu interrupt\n");
758 desc_fpu = irq_to_desc(irq_fpu);
759 fpu_kstat_irq = this_cpu_ptr(desc_fpu->kstat_irqs);
760 }
761 if (dec_interrupt[DEC_IRQ_CASCADE] >= 0) {
762 if (request_irq(dec_interrupt[DEC_IRQ_CASCADE], no_action,
763 IRQF_NO_THREAD, "cascade", NULL))
764 pr_err("Failed to register cascade interrupt\n");
765 }
766 /* Register the bus error interrupt. */
767 if (dec_interrupt[DEC_IRQ_BUS] >= 0 && busirq_handler) {
768 if (request_irq(dec_interrupt[DEC_IRQ_BUS], busirq_handler,
769 busirq_flags, "bus error", busirq_handler))
770 pr_err("Failed to register bus error interrupt\n");
771 }
772 /* Register the HALT interrupt. */
773 if (dec_interrupt[DEC_IRQ_HALT] >= 0) {
774 if (request_irq(dec_interrupt[DEC_IRQ_HALT], dec_intr_halt,
775 IRQF_NO_THREAD, "halt", NULL))
776 pr_err("Failed to register halt interrupt\n");
777 }
778}
779
780asmlinkage unsigned int dec_irq_dispatch(unsigned int irq)
781{
782 do_IRQ(irq);
783 return 0;
784}
diff --git a/arch/mips/dec/tc.c b/arch/mips/dec/tc.c
new file mode 100644
index 000000000..dba583976
--- /dev/null
+++ b/arch/mips/dec/tc.c
@@ -0,0 +1,95 @@
1/*
2 * TURBOchannel architecture calls.
3 *
4 * Copyright (c) Harald Koerfgen, 1998
5 * Copyright (c) 2001, 2003, 2005, 2006 Maciej W. Rozycki
6 * Copyright (c) 2005 James Simmons
7 *
8 * This file is subject to the terms and conditions of the GNU
9 * General Public License. See the file "COPYING" in the main
10 * directory of this archive for more details.
11 */
12#include <linux/compiler.h>
13#include <linux/errno.h>
14#include <linux/init.h>
15#include <linux/string.h>
16#include <linux/tc.h>
17#include <linux/types.h>
18
19#include <asm/addrspace.h>
20#include <asm/bootinfo.h>
21#include <asm/paccess.h>
22
23#include <asm/dec/interrupts.h>
24#include <asm/dec/prom.h>
25#include <asm/dec/system.h>
26
27/*
28 * Protected read byte from TURBOchannel slot space.
29 */
30int tc_preadb(u8 *valp, void __iomem *addr)
31{
32 return get_dbe(*valp, (u8 *)addr);
33}
34
35/*
36 * Get TURBOchannel bus information as specified by the spec, plus
37 * the slot space base address and the number of slots.
38 */
39int __init tc_bus_get_info(struct tc_bus *tbus)
40{
41 if (!dec_tc_bus)
42 return -ENXIO;
43
44 memcpy(&tbus->info, rex_gettcinfo(), sizeof(tbus->info));
45 tbus->slot_base = CPHYSADDR((long)rex_slot_address(0));
46
47 switch (mips_machtype) {
48 case MACH_DS5000_200:
49 tbus->num_tcslots = 7;
50 break;
51 case MACH_DS5000_2X0:
52 case MACH_DS5900:
53 tbus->ext_slot_base = 0x20000000;
54 tbus->ext_slot_size = 0x20000000;
55 fallthrough;
56 case MACH_DS5000_1XX:
57 tbus->num_tcslots = 3;
58 break;
59 case MACH_DS5000_XX:
60 tbus->num_tcslots = 2;
61 default:
62 break;
63 }
64 return 0;
65}
66
67/*
68 * Get the IRQ for the specified slot.
69 */
70void __init tc_device_get_irq(struct tc_dev *tdev)
71{
72 switch (tdev->slot) {
73 case 0:
74 tdev->interrupt = dec_interrupt[DEC_IRQ_TC0];
75 break;
76 case 1:
77 tdev->interrupt = dec_interrupt[DEC_IRQ_TC1];
78 break;
79 case 2:
80 tdev->interrupt = dec_interrupt[DEC_IRQ_TC2];
81 break;
82 /*
83 * Yuck! DS5000/200 onboard devices
84 */
85 case 5:
86 tdev->interrupt = dec_interrupt[DEC_IRQ_TC5];
87 break;
88 case 6:
89 tdev->interrupt = dec_interrupt[DEC_IRQ_TC6];
90 break;
91 default:
92 tdev->interrupt = -1;
93 break;
94 }
95}
diff --git a/arch/mips/dec/time.c b/arch/mips/dec/time.c
new file mode 100644
index 000000000..c38686f89
--- /dev/null
+++ b/arch/mips/dec/time.c
@@ -0,0 +1,172 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 1991, 1992, 1995 Linus Torvalds
4 * Copyright (C) 2000, 2003 Maciej W. Rozycki
5 *
6 * This file contains the time handling details for PC-style clocks as
7 * found in some MIPS systems.
8 *
9 */
10#include <linux/bcd.h>
11#include <linux/init.h>
12#include <linux/mc146818rtc.h>
13#include <linux/param.h>
14
15#include <asm/cpu-features.h>
16#include <asm/ds1287.h>
17#include <asm/time.h>
18#include <asm/dec/interrupts.h>
19#include <asm/dec/ioasic.h>
20#include <asm/dec/machtype.h>
21
22void read_persistent_clock64(struct timespec64 *ts)
23{
24 unsigned int year, mon, day, hour, min, sec, real_year;
25 unsigned long flags;
26
27 spin_lock_irqsave(&rtc_lock, flags);
28
29 do {
30 sec = CMOS_READ(RTC_SECONDS);
31 min = CMOS_READ(RTC_MINUTES);
32 hour = CMOS_READ(RTC_HOURS);
33 day = CMOS_READ(RTC_DAY_OF_MONTH);
34 mon = CMOS_READ(RTC_MONTH);
35 year = CMOS_READ(RTC_YEAR);
36 /*
37 * The PROM will reset the year to either '72 or '73.
38 * Therefore we store the real year separately, in one
39 * of unused BBU RAM locations.
40 */
41 real_year = CMOS_READ(RTC_DEC_YEAR);
42 } while (sec != CMOS_READ(RTC_SECONDS));
43
44 spin_unlock_irqrestore(&rtc_lock, flags);
45
46 if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
47 sec = bcd2bin(sec);
48 min = bcd2bin(min);
49 hour = bcd2bin(hour);
50 day = bcd2bin(day);
51 mon = bcd2bin(mon);
52 year = bcd2bin(year);
53 }
54
55 year += real_year - 72 + 2000;
56
57 ts->tv_sec = mktime64(year, mon, day, hour, min, sec);
58 ts->tv_nsec = 0;
59}
60
61/*
62 * In order to set the CMOS clock precisely, update_persistent_clock64 has to
63 * be called 500 ms after the second nowtime has started, because when
64 * nowtime is written into the registers of the CMOS clock, it will
65 * jump to the next second precisely 500 ms later. Check the Dallas
66 * DS1287 data sheet for details.
67 */
68int update_persistent_clock64(struct timespec64 now)
69{
70 time64_t nowtime = now.tv_sec;
71 int retval = 0;
72 int real_seconds, real_minutes, cmos_minutes;
73 unsigned char save_control, save_freq_select;
74
75 /* irq are locally disabled here */
76 spin_lock(&rtc_lock);
77 /* tell the clock it's being set */
78 save_control = CMOS_READ(RTC_CONTROL);
79 CMOS_WRITE((save_control | RTC_SET), RTC_CONTROL);
80
81 /* stop and reset prescaler */
82 save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
83 CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT);
84
85 cmos_minutes = CMOS_READ(RTC_MINUTES);
86 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
87 cmos_minutes = bcd2bin(cmos_minutes);
88
89 /*
90 * since we're only adjusting minutes and seconds,
91 * don't interfere with hour overflow. This avoids
92 * messing with unknown time zones but requires your
93 * RTC not to be off by more than 15 minutes
94 */
95 real_minutes = div_s64_rem(nowtime, 60, &real_seconds);
96 if (((abs(real_minutes - cmos_minutes) + 15) / 30) & 1)
97 real_minutes += 30; /* correct for half hour time zone */
98 real_minutes %= 60;
99
100 if (abs(real_minutes - cmos_minutes) < 30) {
101 if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) {
102 real_seconds = bin2bcd(real_seconds);
103 real_minutes = bin2bcd(real_minutes);
104 }
105 CMOS_WRITE(real_seconds, RTC_SECONDS);
106 CMOS_WRITE(real_minutes, RTC_MINUTES);
107 } else {
108 printk_once(KERN_NOTICE
109 "set_rtc_mmss: can't update from %d to %d\n",
110 cmos_minutes, real_minutes);
111 retval = -1;
112 }
113
114 /* The following flags have to be released exactly in this order,
115 * otherwise the DS1287 will not reset the oscillator and will not
116 * update precisely 500 ms later. You won't find this mentioned
117 * in the Dallas Semiconductor data sheets, but who believes data
118 * sheets anyway ... -- Markus Kuhn
119 */
120 CMOS_WRITE(save_control, RTC_CONTROL);
121 CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);
122 spin_unlock(&rtc_lock);
123
124 return retval;
125}
126
127void __init plat_time_init(void)
128{
129 int ioasic_clock = 0;
130 u32 start, end;
131 int i = HZ / 8;
132
133 /* Set up the rate of periodic DS1287 interrupts. */
134 ds1287_set_base_clock(HZ);
135
136 /* On some I/O ASIC systems we have the I/O ASIC's counter. */
137 if (IOASIC)
138 ioasic_clock = dec_ioasic_clocksource_init() == 0;
139 if (cpu_has_counter) {
140 ds1287_timer_state();
141 while (!ds1287_timer_state())
142 ;
143
144 start = read_c0_count();
145
146 while (i--)
147 while (!ds1287_timer_state())
148 ;
149
150 end = read_c0_count();
151
152 mips_hpt_frequency = (end - start) * 8;
153 printk(KERN_INFO "MIPS counter frequency %dHz\n",
154 mips_hpt_frequency);
155
156 /*
157 * All R4k DECstations suffer from the CP0 Count erratum,
158 * so we can't use the timer as a clock source, and a clock
159 * event both at a time. An accurate wall clock is more
160 * important than a high-precision interval timer so only
161 * use the timer as a clock source, and not a clock event
162 * if there's no I/O ASIC counter available to serve as a
163 * clock source.
164 */
165 if (!ioasic_clock) {
166 init_r4k_clocksource();
167 mips_hpt_frequency = 0;
168 }
169 }
170
171 ds1287_clockevent_init(dec_interrupt[DEC_IRQ_RTC]);
172}
diff --git a/arch/mips/dec/wbflush.c b/arch/mips/dec/wbflush.c
new file mode 100644
index 000000000..dad64d178
--- /dev/null
+++ b/arch/mips/dec/wbflush.c
@@ -0,0 +1,92 @@
1/*
2 * Setup the right wbflush routine for the different DECstations.
3 *
4 * Created with information from:
5 * DECstation 3100 Desktop Workstation Functional Specification
6 * DECstation 5000/200 KN02 System Module Functional Specification
7 * mipsel-linux-objdump --disassemble vmunix | grep "wbflush" :-)
8 *
9 * This file is subject to the terms and conditions of the GNU General Public
10 * License. See the file "COPYING" in the main directory of this archive
11 * for more details.
12 *
13 * Copyright (C) 1998 Harald Koerfgen
14 * Copyright (C) 2002 Maciej W. Rozycki
15 */
16
17#include <linux/export.h>
18#include <linux/init.h>
19
20#include <asm/bootinfo.h>
21#include <asm/wbflush.h>
22#include <asm/barrier.h>
23
24static void wbflush_kn01(void);
25static void wbflush_kn210(void);
26static void wbflush_mips(void);
27
28void (*__wbflush) (void);
29
30void __init wbflush_setup(void)
31{
32 switch (mips_machtype) {
33 case MACH_DS23100:
34 case MACH_DS5000_200: /* DS5000 3max */
35 __wbflush = wbflush_kn01;
36 break;
37 case MACH_DS5100: /* DS5100 MIPSMATE */
38 __wbflush = wbflush_kn210;
39 break;
40 case MACH_DS5000_1XX: /* DS5000/100 3min */
41 case MACH_DS5000_XX: /* Personal DS5000/2x */
42 case MACH_DS5000_2X0: /* DS5000/240 3max+ */
43 case MACH_DS5900: /* DS5900 bigmax */
44 default:
45 __wbflush = wbflush_mips;
46 break;
47 }
48}
49
50/*
51 * For the DS3100 and DS5000/200 the R2020/R3220 writeback buffer functions
52 * as part of Coprocessor 0.
53 */
54static void wbflush_kn01(void)
55{
56 asm(".set\tpush\n\t"
57 ".set\tnoreorder\n\t"
58 "1:\tbc0f\t1b\n\t"
59 "nop\n\t"
60 ".set\tpop");
61}
62
63/*
64 * For the DS5100 the writeback buffer seems to be a part of Coprocessor 3.
65 * But CP3 has to enabled first.
66 */
67static void wbflush_kn210(void)
68{
69 asm(".set\tpush\n\t"
70 ".set\tnoreorder\n\t"
71 "mfc0\t$2,$12\n\t"
72 "lui\t$3,0x8000\n\t"
73 "or\t$3,$2,$3\n\t"
74 "mtc0\t$3,$12\n\t"
75 "nop\n"
76 "1:\tbc3f\t1b\n\t"
77 "nop\n\t"
78 "mtc0\t$2,$12\n\t"
79 "nop\n\t"
80 ".set\tpop"
81 : : : "$2", "$3");
82}
83
84/*
85 * I/O ASIC systems use a standard writeback buffer that gets flushed
86 * upon an uncached read.
87 */
88static void wbflush_mips(void)
89{
90 __fast_iob();
91}
92EXPORT_SYMBOL(__wbflush);