1 /* $NetBSD: dec_5100.c,v 1.48 2014/03/24 19:31:40 christos Exp $ */
2
3 /*
4 * Copyright (c) 1998 Jonathan Stone. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Jonathan Stone for
17 * the NetBSD Project.
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
33
34 __KERNEL_RCSID(0, "$NetBSD: dec_5100.c,v 1.48 2014/03/24 19:31:40 christos Exp $");
35
36 #define __INTR_PRIVATE
37 #include <sys/param.h>
38 #include <sys/cpu.h>
39 #include <sys/device.h>
40 #include <sys/intr.h>
41 #include <sys/lwp.h>
42 #include <sys/kernel.h>
43 #include <sys/systm.h>
44
45 #include <mips/locore.h>
46
47 #include <mips/mips/mips_mcclock.h> /* mcclock CPUspeed estimation */
48
49 #include <pmax/locore.h>
50 #include <pmax/sysconf.h>
51
52 #include <dev/tc/tcvar.h> /* tc_addr_t */
53
54 #include <pmax/pmax/machdep.h>
55 #include <pmax/pmax/kn01.h> /* common definitions */
56 #include <pmax/pmax/kn230.h>
57
58 #include <pmax/ibus/ibusvar.h>
59
60 #include <pmax/pmax/cons.h>
61
62 void dec_5100_init(void); /* XXX */
63 static void dec_5100_bus_reset(void);
64 static void dec_5100_cons_init(void);
65 static void dec_5100_intr(uint32_t, vaddr_t, uint32_t);
66 static void dec_5100_intr_establish(device_t, void *,
67 int, int (*)(void *), void *);
68 static void dec_5100_memintr(void);
69
70 static const struct ipl_sr_map dec_5100_ipl_sr_map = {
71 .sr_bits = {
72 [IPL_NONE] = 0,
73 [IPL_SOFTCLOCK] = MIPS_SOFT_INT_MASK_0,
74 [IPL_SOFTNET] = MIPS_SOFT_INT_MASK,
75 [IPL_VM] = MIPS_SPL_0_1,
76 [IPL_SCHED] = MIPS_SPLHIGH,
77 [IPL_DDB] = MIPS_SPLHIGH,
78 [IPL_HIGH] = MIPS_SPLHIGH,
79 },
80 };
81
82 void
dec_5100_init(void)83 dec_5100_init(void)
84 {
85
86 platform.iobus = "baseboard";
87 platform.bus_reset = dec_5100_bus_reset;
88 platform.cons_init = dec_5100_cons_init;
89 platform.iointr = dec_5100_intr;
90 platform.intr_establish = dec_5100_intr_establish;
91 platform.memsize = memsize_scan;
92 /* no high resolution timer available */
93
94 /* set correct wbflush routine for this motherboard */
95 mips_set_wbflush(kn230_wbflush);
96
97 ipl_sr_map = dec_5100_ipl_sr_map;
98
99 /* calibrate cpu_mhz value */
100 mc_cpuspeed(MIPS_PHYS_TO_KSEG1(KN01_SYS_CLOCK), MIPS_INT_MASK_2);
101
102 cpu_setmodel("DECsystem 5100 (MIPSMATE)");
103 }
104
105 /*
106 * Initialize the memory system and I/O buses.
107 */
108 static void
dec_5100_bus_reset(void)109 dec_5100_bus_reset(void)
110 {
111 uint32_t icsr;
112
113 /* clear any memory error condition */
114 icsr = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR);
115 icsr |= KN230_CSR_INTR_WMERR;
116 *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR) = icsr;
117
118 /* nothing else to do */
119 kn230_wbflush();
120 }
121
122 static void
dec_5100_cons_init(void)123 dec_5100_cons_init(void)
124 {
125
126 /*
127 * Delay to allow PROM putchars to complete.
128 * FIFO depth * character time,
129 * character time = (1000000 / (defaultrate / 10))
130 */
131 DELAY(160000000 / 9600); /* XXX */
132
133 dz_ibus_cnsetup(KN230_SYS_DZ0);
134 dz_ibus_cnattach(0);
135 }
136
137 static void
dec_5100_intr_establish(device_t dev,void * cookie,int level,int (* handler)(void *),void * arg)138 dec_5100_intr_establish(device_t dev, void *cookie, int level,
139 int (*handler)(void *), void *arg)
140 {
141
142 intrtab[(intptr_t)cookie].ih_func = handler;
143 intrtab[(intptr_t)cookie].ih_arg = arg;
144 }
145
146
147 #define CALLINTR(vvv, ibit) \
148 do { \
149 if ((icsr & (ibit)) && intrtab[vvv].ih_func) { \
150 (*intrtab[vvv].ih_func)(intrtab[vvv].ih_arg); \
151 intrtab[vvv].ih_count.ev_count++; \
152 } \
153 } while (/*CONSTCOND*/0)
154
155 static void
dec_5100_intr(uint32_t status,vaddr_t pc,uint32_t ipending)156 dec_5100_intr(uint32_t status, vaddr_t pc, uint32_t ipending)
157 {
158 uint32_t icsr;
159
160 if (ipending & MIPS_INT_MASK_4) {
161 #ifdef DDB
162 Debugger();
163 #else
164 prom_haltbutton();
165 #endif
166 }
167
168 icsr = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR);
169
170 /* handle clock interrupts ASAP */
171 if (ipending & MIPS_INT_MASK_2) {
172 struct clockframe cf;
173
174 __asm volatile("lbu $0,48(%0)" ::
175 "r"(MIPS_PHYS_TO_KSEG1(KN01_SYS_CLOCK)));
176 cf.pc = pc;
177 cf.sr = status;
178 cf.intr = (curcpu()->ci_idepth > 1);
179 hardclock(&cf);
180 pmax_clock_evcnt.ev_count++;
181 }
182
183 if (ipending & MIPS_INT_MASK_0) {
184 CALLINTR(SYS_DEV_SCC0, KN230_CSR_INTR_DZ0);
185 CALLINTR(SYS_DEV_OPT0, KN230_CSR_INTR_OPT0);
186 CALLINTR(SYS_DEV_OPT1, KN230_CSR_INTR_OPT1);
187 }
188
189 if (ipending & MIPS_INT_MASK_1) {
190 CALLINTR(SYS_DEV_LANCE, KN230_CSR_INTR_LANCE);
191 CALLINTR(SYS_DEV_SCSI, KN230_CSR_INTR_SII);
192 }
193
194 if (ipending & MIPS_INT_MASK_3) {
195 dec_5100_memintr();
196 pmax_memerr_evcnt.ev_count++;
197 }
198 }
199
200
201 /*
202 * Handle write-to-nonexistent-address memory errors on MIPS_INT_MASK_3.
203 * These are reported asynchronously, due to hardware write buffering.
204 * we can't easily figure out process context, so just panic.
205 *
206 * XXX drain writebuffer on contextswitch to avoid panic?
207 */
208 static void
dec_5100_memintr(void)209 dec_5100_memintr(void)
210 {
211 uint32_t icsr;
212
213 /* read icsr and clear error */
214 icsr = *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR);
215 icsr |= KN230_CSR_INTR_WMERR;
216 *(volatile uint32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR) = icsr;
217 kn230_wbflush();
218
219 #ifdef DIAGNOSTIC
220 printf("\nMemory interrupt\n");
221 #endif
222
223 /* ignore errors during probes */
224 if (cold)
225 return;
226
227 if (icsr & KN230_CSR_INTR_WMERR) {
228 panic("write to non-existent memory");
229 } else {
230 panic("stray memory error interrupt");
231 }
232 }
233