xref: /netbsd-src/sys/arch/pmax/pmax/dec_5100.c (revision e691d98f971f4464abb0774514c0188372cde33f)
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