xref: /netbsd/sys/arch/pmax/pmax/dec_5100.c (revision bf9ec67e)
1 /* $NetBSD: dec_5100.c,v 1.33 2001/09/18 16:15:20 tsutsui 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.33 2001/09/18 16:15:20 tsutsui Exp $");
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/kernel.h>
40 
41 #include <machine/cpu.h>
42 #include <machine/intr.h>
43 #include <machine/locore.h>
44 #include <machine/sysconf.h>
45 
46 #include <mips/mips/mips_mcclock.h>	/* mcclock CPUspeed estimation */
47 
48 #include <pmax/pmax/machdep.h>
49 #include <pmax/pmax/kn01.h>		/* common definitions */
50 #include <pmax/pmax/kn230.h>
51 #include <pmax/dev/dcvar.h>
52 
53 #include <pmax/ibus/ibusvar.h>
54 
55 void		dec_5100_init __P((void));		/* XXX */
56 static void	dec_5100_bus_reset __P((void));
57 static void	dec_5100_cons_init __P((void));
58 static void	dec_5100_intr __P((unsigned, unsigned, unsigned, unsigned));
59 static void	dec_5100_intr_establish __P((struct device *, void *,
60 		    int, int (*)(void *), void *));
61 static void	dec_5100_memintr __P((void));
62 
63 void
64 dec_5100_init()
65 {
66 	platform.iobus = "baseboard";
67 	platform.bus_reset = dec_5100_bus_reset;
68 	platform.cons_init = dec_5100_cons_init;
69 	platform.iointr = dec_5100_intr;
70 	platform.intr_establish = dec_5100_intr_establish;
71 	platform.memsize = memsize_scan;
72 	/* no high resolution timer available */
73 
74 	/* set correct wbflush routine for this motherboard */
75 	mips_set_wbflush(kn230_wbflush);
76 
77 	splvec.splbio = MIPS_SPL1;
78 	splvec.splnet = MIPS_SPL1;
79 	splvec.spltty = MIPS_SPL_0_1;
80 	splvec.splvm = MIPS_SPL_0_1_2;
81 	splvec.splclock = MIPS_SPL_0_1_2;
82 	splvec.splstatclock = MIPS_SPL_0_1_2;
83 
84 	/* calibrate cpu_mhz value */
85 	mc_cpuspeed(MIPS_PHYS_TO_KSEG1(KN01_SYS_CLOCK), MIPS_INT_MASK_2);
86 
87 	sprintf(cpu_model, "DECsystem 5100 (MIPSMATE)");
88 }
89 
90 /*
91  * Initialize the memory system and I/O buses.
92  */
93 static void
94 dec_5100_bus_reset()
95 {
96 	u_int32_t icsr;
97 
98 	/* clear any memory error condition */
99 	icsr = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR);
100 	icsr |= KN230_CSR_INTR_WMERR;
101 	*(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR) = icsr;
102 
103 	/* nothing else to do */
104 	kn230_wbflush();
105 }
106 
107 static void
108 dec_5100_cons_init()
109 {
110 	/*
111 	 * Delay to allow PROM putchars to complete.
112 	 * FIFO depth * character time,
113 	 * character time = (1000000 / (defaultrate / 10))
114 	 */
115 	DELAY(160000000 / 9600);	/* XXX */
116 
117 	dc_cnattach(KN230_SYS_DZ0, 0);
118 }
119 
120 static void
121 dec_5100_intr_establish(dev, cookie, level, handler, arg)
122 	struct device *dev;
123 	void *cookie;
124 	int level;
125 	int (*handler) __P((void *));
126 	void *arg;
127 {
128 
129 	intrtab[(int)cookie].ih_func = handler;
130 	intrtab[(int)cookie].ih_arg = arg;
131 }
132 
133 
134 #define CALLINTR(vvv, ibit)						\
135     do {								\
136 	if ((icsr & (ibit)) && intrtab[vvv].ih_func) {			\
137 		(*intrtab[vvv].ih_func)(intrtab[vvv].ih_arg);		\
138 		intrcnt[vvv]++;						\
139 	}								\
140     } while (0)
141 
142 static void
143 dec_5100_intr(status, cause, pc, ipending)
144 	unsigned status;
145 	unsigned cause;
146 	unsigned pc;
147 	unsigned ipending;
148 {
149 	u_int32_t icsr;
150 
151 	if (ipending & MIPS_INT_MASK_4) {
152 #ifdef DDB
153 		Debugger();
154 #else
155 		prom_haltbutton();
156 #endif
157 	}
158 
159 	icsr = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR);
160 
161 	/* handle clock interrupts ASAP */
162 	if (ipending & MIPS_INT_MASK_2) {
163 		struct clockframe cf;
164 
165 		__asm __volatile("lbu $0,48(%0)" ::
166 			"r"(MIPS_PHYS_TO_KSEG1(KN01_SYS_CLOCK)));
167 		cf.pc = pc;
168 		cf.sr = status;
169 		hardclock(&cf);
170 		pmax_clock_evcnt.ev_count++;
171 
172 		/* keep clock interrupts enabled when we return */
173 		cause &= ~MIPS_INT_MASK_2;
174 	}
175 
176 	/* If clock interrupts were enabled, re-enable them ASAP. */
177 	_splset(MIPS_SR_INT_IE | (status & MIPS_INT_MASK_2));
178 
179 	if (ipending & MIPS_INT_MASK_0) {
180 		CALLINTR(SYS_DEV_SCC0, KN230_CSR_INTR_DZ0);
181 		CALLINTR(SYS_DEV_OPT0, KN230_CSR_INTR_OPT0);
182 		CALLINTR(SYS_DEV_OPT1, KN230_CSR_INTR_OPT1);
183 	}
184 
185 	if (ipending & MIPS_INT_MASK_1) {
186 		CALLINTR(SYS_DEV_LANCE, KN230_CSR_INTR_LANCE);
187 		CALLINTR(SYS_DEV_SCSI, KN230_CSR_INTR_SII);
188 	}
189 
190 	if (ipending & MIPS_INT_MASK_3) {
191 		dec_5100_memintr();
192 		pmax_memerr_evcnt.ev_count++;
193 	}
194 
195 	_splset(MIPS_SR_INT_IE | (status & ~cause & MIPS_HARD_INT_MASK));
196 }
197 
198 
199 /*
200  * Handle write-to-nonexistent-address memory errors on MIPS_INT_MASK_3.
201  * These are reported asynchronously, due to hardware write buffering.
202  * we can't easily figure out process context, so just panic.
203  *
204  * XXX drain writebuffer on contextswitch to avoid panic?
205  */
206 static void
207 dec_5100_memintr()
208 {
209 	u_int32_t icsr;
210 
211 	/* read icsr and clear error  */
212 	icsr = *(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR);
213 	icsr |= KN230_CSR_INTR_WMERR;
214 	*(volatile u_int32_t *)MIPS_PHYS_TO_KSEG1(KN230_SYS_ICSR) = icsr;
215 	kn230_wbflush();
216 
217 #ifdef DIAGNOSTIC
218 	printf("\nMemory interrupt\n");
219 #endif
220 
221 	/* ignore errors during probes */
222 	if (cold)
223 		return;
224 
225 	if (icsr & KN230_CSR_INTR_WMERR) {
226 		panic("write to non-existent memory");
227 	}
228 	else {
229 		panic("stray memory error interrupt");
230 	}
231 }
232