xref: /netbsd-src/sys/arch/powerpc/booke/e500_intr.c (revision c2f76ff004a2cb67efe5b12d97bd3ef7fe89e18d)
1 /*	$NetBSD: e500_intr.c,v 1.2 2011/01/18 01:02:52 matt Exp $	*/
2 /*-
3  * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to The NetBSD Foundation
7  * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
8  * Agency and which was developed by Matt Thomas of 3am Software Foundry.
9  *
10  * This material is based upon work supported by the Defense Advanced Research
11  * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
12  * Contract No. N66001-09-C-2073.
13  * Approved for Public Release, Distribution Unlimited
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  */
36 
37 #define __INTR_PRIVATE
38 
39 #include <sys/param.h>
40 #include <sys/proc.h>
41 #include <sys/intr.h>
42 #include <sys/cpu.h>
43 #include <sys/kmem.h>
44 #include <sys/atomic.h>
45 #include <sys/bus.h>
46 
47 #include <uvm/uvm_extern.h>
48 
49 #include <powerpc/spr.h>
50 #include <powerpc/booke/spr.h>
51 
52 #include <powerpc/booke/cpuvar.h>
53 #include <powerpc/booke/e500reg.h>
54 #include <powerpc/booke/e500var.h>
55 #include <powerpc/booke/openpicreg.h>
56 
57 #define	IPL2CTPR(ipl)		((ipl) + 15 - IPL_HIGH)
58 #define CTPR2IPL(ctpr)		((ctpr) - (15 - IPL_HIGH))
59 
60 #define	IST_PERCPU_P(ist)	((ist) >= IST_TIMER)
61 
62 #define	IPL_SOFTMASK \
63 	    ((1 << IPL_SOFTSERIAL) | (1 << IPL_SOFTNET   )	\
64 	    |(1 << IPL_SOFTBIO   ) | (1 << IPL_SOFTCLOCK ))
65 
66 #define SOFTINT2IPL_MAP \
67 	    ((IPL_SOFTSERIAL << (4*SOFTINT_SERIAL))	\
68 	    |(IPL_SOFTNET    << (4*SOFTINT_NET   ))	\
69 	    |(IPL_SOFTBIO    << (4*SOFTINT_BIO   ))	\
70 	    |(IPL_SOFTCLOCK  << (4*SOFTINT_CLOCK )))
71 #define	SOFTINT2IPL(si_level)	((SOFTINT2IPL_MAP >> (4 * si_level)) & 0x0f)
72 
73 struct e500_intr_irq_info {
74 	bus_addr_t irq_vpr;
75 	bus_addr_t irq_dr;
76 	u_int irq_vector;
77 };
78 
79 struct intr_source {
80 	int (*is_func)(void *);
81 	void *is_arg;
82 	int8_t is_ipl;
83 	uint8_t is_ist;
84 	uint8_t is_irq;
85 	bus_size_t is_vpr;
86 	bus_size_t is_dr;
87 };
88 
89 #define	INTR_SOURCE_INITIALIZER \
90 	{ .is_func = e500_intr_spurious, .is_arg = NULL, \
91 	.is_irq = -1, .is_ipl = IPL_NONE, .is_ist = IST_NONE, }
92 
93 struct e500_intr_name {
94 	uint8_t in_irq;
95 	const char in_name[15];
96 };
97 
98 static const struct e500_intr_name e500_onchip_intr_names[] = {
99 	{ ISOURCE_L2, "l2" },
100 	{ ISOURCE_ECM, "ecm" },
101 	{ ISOURCE_DDR, "ddr" },
102 	{ ISOURCE_LBC, "lbc" },
103 	{ ISOURCE_DMA_CHAN1, "dma-chan1" },
104 	{ ISOURCE_DMA_CHAN2, "dma-chan2" },
105 	{ ISOURCE_DMA_CHAN3, "dma-chan3" },
106 	{ ISOURCE_DMA_CHAN4, "dma-chan4" },
107 	{ ISOURCE_PCI1, "pci1" },
108 	{ ISOURCE_PCIEX2, "pcie2" },
109 	{ ISOURCE_PCIEX	, "pcie1" },
110 	{ ISOURCE_PCIEX3, "pcie3" },
111 	{ ISOURCE_ETSEC1_TX, "etsec1-tx" },
112 	{ ISOURCE_ETSEC1_RX, "etsec1-rx" },
113 	{ ISOURCE_ETSEC3_TX, "etsec3-tx" },
114 	{ ISOURCE_ETSEC3_RX, "etsec3-rx" },
115 	{ ISOURCE_ETSEC3_ERR, "etsec3-err" },
116 	{ ISOURCE_ETSEC1_ERR, "etsec1-err" },
117 	{ ISOURCE_ETSEC2_TX, "etsec2-tx" },
118 	{ ISOURCE_ETSEC2_RX, "etsec2-rx" },
119 	{ ISOURCE_ETSEC4_TX, "etsec4-tx" },
120 	{ ISOURCE_ETSEC4_RX, "etsec4-rx" },
121 	{ ISOURCE_ETSEC4_ERR, "etsec4-err" },
122 	{ ISOURCE_ETSEC2_ERR, "etsec2-err" },
123 	{ ISOURCE_DUART, "duart" },
124 	{ ISOURCE_I2C, "i2c" },
125 	{ ISOURCE_PERFMON, "perfmon" },
126 	{ ISOURCE_SECURITY1, "sec1" },
127 	{ ISOURCE_SRIO_EWPU, "srio-ewpu" },
128 	{ ISOURCE_SRIO_ODBELL, "srio-odbell" },
129 	{ ISOURCE_SRIO_IDBELL, "srio-idbell" },
130 	{ ISOURCE_SRIO_OMU1, "srio-omu1" },
131 	{ ISOURCE_SRIO_IMU1, "srio-imu1" },
132 	{ ISOURCE_SRIO_OMU2, "srio-omu2" },
133 	{ ISOURCE_SRIO_IMU2, "srio-imu2" },
134 	{ 0, "" },
135 };
136 
137 const struct e500_intr_name mpc8548_external_intr_names[] = {
138 	{ 0, "" },
139 };
140 
141 const struct e500_intr_name mpc8536_external_intr_names[] = {
142 	{ 0, "" },
143 };
144 
145 const struct e500_intr_name mpc8572_external_intr_names[] = {
146 	{ 0, "" },
147 };
148 
149 const struct e500_intr_name mpc8548_onchip_intr_names[] = {
150 	{ ISOURCE_PCI1, "pci1" },
151 	{ ISOURCE_PCI2, "pci2" },
152 	{ 0, "" },
153 };
154 
155 const struct e500_intr_name mpc8544_onchip_intr_names[] = {
156 	{ 0, "" },
157 };
158 
159 const struct e500_intr_name mpc8536_onchip_intr_names[] = {
160 	{ ISOURCE_USB1, "usb1" },
161 	{ ISOURCE_SATA2, "sata2" },
162 	{ ISOURCE_USB2, "usb2" },
163 	{ ISOURCE_SECURITY2, "sec2" },
164 	{ ISOURCE_SPI, "spi" },
165 	{ ISOURCE_USB3, "usb3" },
166 	{ ISOURCE_ETSEC1_PTP, "etsec1-ptp" },
167 	{ ISOURCE_ETSEC3_PTP, "etsec3-ptp" },
168 	{ ISOURCE_ESDHC, "esdhc" },
169 	{ ISOURCE_SATA1, "sata1" },
170 	{ 0, "" },
171 };
172 
173 const struct e500_intr_name mpc8572_onchip_intr_names[] = {
174 	{ ISOURCE_PCIEX3_MPC8572, "pcie3" },
175 	{ ISOURCE_FEC, "fec" },
176 	{ ISOURCE_GPIO, "gpio" },
177 	{ ISOURCE_PME_GENERAL, "pme" },
178 	{ ISOURCE_SECURITY2, "sec2" },
179 	{ ISOURCE_TLU1, "tlu1" },
180 	{ ISOURCE_TLU2, "tlu2" },
181 	{ ISOURCE_PME_CHAN1, "pme-chan1" },
182 	{ ISOURCE_PME_CHAN2, "pme-chan2" },
183 	{ ISOURCE_PME_CHAN3, "pme-chan3" },
184 	{ ISOURCE_PME_CHAN4, "pme-chan4" },
185 	{ ISOURCE_ETSEC1_PTP, "etsec1-ptp" },
186 	{ ISOURCE_ETSEC2_PTP, "etsec2-ptp" },
187 	{ ISOURCE_ETSEC3_PTP, "etsec3-ptp" },
188 	{ ISOURCE_ETSEC4_PTP, "etsec4-ptp" },
189 	{ ISOURCE_DMA2_CHAN1, "dma2-chan1" },
190 	{ ISOURCE_DMA2_CHAN2, "dma2-chan2" },
191 	{ ISOURCE_DMA2_CHAN3, "dma2-chan3" },
192 	{ ISOURCE_DMA2_CHAN4, "dma2-chan4" },
193 	{ 0, "" },
194 };
195 
196 static const struct e500_intr_name e500_msigroup_intr_names[] = {
197 	{ 0, "msigroup0" },
198 	{ 1, "msigroup1" },
199 	{ 2, "msigroup2" },
200 	{ 3, "msigroup3" },
201 	{ 4, "msigroup4" },
202 	{ 5, "msigroup5" },
203 	{ 6, "msigroup6" },
204 	{ 7, "msigroup7" },
205 	{ 0, "" },
206 };
207 
208 static const struct e500_intr_name e500_timer_intr_names[] = {
209 	{ 0, "timer0" },
210 	{ 1, "timer1" },
211 	{ 2, "timer2" },
212 	{ 3, "timer3" },
213 	{ 0, "" },
214 };
215 
216 static const struct e500_intr_name e500_ipi_intr_names[] = {
217 	{ 0, "ipi0" },
218 	{ 1, "ipi1" },
219 	{ 2, "ipi2" },
220 	{ 3, "ipi3" },
221 	{ 0, "" },
222 };
223 
224 static const struct e500_intr_name e500_mi_intr_names[] = {
225 	{ 0, "mi0" },
226 	{ 1, "mi1" },
227 	{ 2, "mi2" },
228 	{ 3, "mi3" },
229 	{ 0, "" },
230 };
231 
232 struct e500_intr_info {
233 	u_int ii_external_sources;
234 	uint32_t ii_onchip_bitmap[2];
235 	u_int ii_onchip_sources;
236 	u_int ii_msigroup_sources;
237 	u_int ii_ipi_sources;			/* per-cpu */
238 	u_int ii_timer_sources;			/* per-cpu */
239 	u_int ii_mi_sources;			/* per-cpu */
240 	u_int ii_percpu_sources;
241 	const struct e500_intr_name *ii_external_intr_names;
242 	const struct e500_intr_name *ii_onchip_intr_names;
243 	u_int8_t ii_ist_vectors[IST_MAX+1];
244 };
245 
246 static kmutex_t e500_intr_lock __aligned(32);
247 static struct e500_intr_info e500_intr_info;
248 
249 static const struct e500_intr_info mpc8548_intr_info = {
250 	.ii_external_sources = MPC8548_EXTERNALSOURCES,
251 	.ii_onchip_bitmap = MPC8548_ONCHIPBITMAP,
252 	.ii_onchip_sources = MPC8548_ONCHIPSOURCES,
253 	.ii_msigroup_sources = MPC8548_MSIGROUPSOURCES,
254 	.ii_timer_sources = MPC8548_TIMERSOURCES,
255 	.ii_ipi_sources = MPC8548_IPISOURCES,
256 	.ii_mi_sources = MPC8548_MISOURCES,
257 	.ii_percpu_sources = MPC8548_TIMERSOURCES
258 	    + MPC8548_IPISOURCES + MPC8548_MISOURCES,
259 	.ii_external_intr_names = mpc8548_external_intr_names,
260 	.ii_onchip_intr_names = mpc8548_onchip_intr_names,
261 	.ii_ist_vectors = {
262 		[IST_NONE]		= ~0,
263 		[IST_EDGE]		= 0,
264 		[IST_LEVEL_LOW]		= 0,
265 		[IST_LEVEL_HIGH]	= 0,
266 		[IST_ONCHIP]		= MPC8548_EXTERNALSOURCES,
267 		[IST_MSIGROUP]		= MPC8548_EXTERNALSOURCES
268 					    + MPC8548_ONCHIPSOURCES,
269 		[IST_TIMER]		= MPC8548_EXTERNALSOURCES
270 					    + MPC8548_ONCHIPSOURCES
271 					    + MPC8548_MSIGROUPSOURCES,
272 		[IST_IPI]		= MPC8548_EXTERNALSOURCES
273 					    + MPC8548_ONCHIPSOURCES
274 					    + MPC8548_MSIGROUPSOURCES
275 					    + MPC8548_TIMERSOURCES,
276 		[IST_MI]		= MPC8548_EXTERNALSOURCES
277 					    + MPC8548_ONCHIPSOURCES
278 					    + MPC8548_MSIGROUPSOURCES
279 					    + MPC8548_TIMERSOURCES
280 					    + MPC8548_IPISOURCES,
281 		[IST_MAX]		= MPC8548_EXTERNALSOURCES
282 					    + MPC8548_ONCHIPSOURCES
283 					    + MPC8548_MSIGROUPSOURCES
284 					    + MPC8548_TIMERSOURCES
285 					    + MPC8548_IPISOURCES
286 					    + MPC8548_MISOURCES,
287 	},
288 };
289 
290 static const struct e500_intr_info mpc8536_intr_info = {
291 	.ii_external_sources = MPC8536_EXTERNALSOURCES,
292 	.ii_onchip_bitmap = MPC8536_ONCHIPBITMAP,
293 	.ii_onchip_sources = MPC8536_ONCHIPSOURCES,
294 	.ii_msigroup_sources = MPC8536_MSIGROUPSOURCES,
295 	.ii_timer_sources = MPC8536_TIMERSOURCES,
296 	.ii_ipi_sources = MPC8536_IPISOURCES,
297 	.ii_mi_sources = MPC8536_MISOURCES,
298 	.ii_percpu_sources = MPC8536_TIMERSOURCES
299 	    + MPC8536_IPISOURCES + MPC8536_MISOURCES,
300 	.ii_external_intr_names = mpc8536_external_intr_names,
301 	.ii_onchip_intr_names = mpc8536_onchip_intr_names,
302 	.ii_ist_vectors = {
303 		[IST_NONE]		= ~0,
304 		[IST_EDGE]		= 0,
305 		[IST_LEVEL_LOW]		= 0,
306 		[IST_LEVEL_HIGH]	= 0,
307 		[IST_ONCHIP]		= MPC8536_EXTERNALSOURCES,
308 		[IST_MSIGROUP]		= MPC8536_EXTERNALSOURCES
309 					    + MPC8536_ONCHIPSOURCES,
310 		[IST_TIMER]		= MPC8536_EXTERNALSOURCES
311 					    + MPC8536_ONCHIPSOURCES
312 					    + MPC8536_MSIGROUPSOURCES,
313 		[IST_IPI]		= MPC8536_EXTERNALSOURCES
314 					    + MPC8536_ONCHIPSOURCES
315 					    + MPC8536_MSIGROUPSOURCES
316 					    + MPC8536_TIMERSOURCES,
317 		[IST_MI]		= MPC8536_EXTERNALSOURCES
318 					    + MPC8536_ONCHIPSOURCES
319 					    + MPC8536_MSIGROUPSOURCES
320 					    + MPC8536_TIMERSOURCES
321 					    + MPC8536_IPISOURCES,
322 		[IST_MAX]		= MPC8536_EXTERNALSOURCES
323 					    + MPC8536_ONCHIPSOURCES
324 					    + MPC8536_MSIGROUPSOURCES
325 					    + MPC8536_TIMERSOURCES
326 					    + MPC8536_IPISOURCES
327 					    + MPC8536_MISOURCES,
328 	},
329 };
330 
331 static const struct e500_intr_info mpc8572_intr_info = {
332 	.ii_external_sources = MPC8572_EXTERNALSOURCES,
333 	.ii_onchip_bitmap = MPC8572_ONCHIPBITMAP,
334 	.ii_onchip_sources = MPC8572_ONCHIPSOURCES,
335 	.ii_msigroup_sources = MPC8572_MSIGROUPSOURCES,
336 	.ii_timer_sources = MPC8572_TIMERSOURCES,
337 	.ii_ipi_sources = MPC8572_IPISOURCES,
338 	.ii_mi_sources = MPC8572_MISOURCES,
339 	.ii_percpu_sources = MPC8572_TIMERSOURCES
340 	    + MPC8572_IPISOURCES + MPC8572_MISOURCES,
341 	.ii_external_intr_names = mpc8572_external_intr_names,
342 	.ii_onchip_intr_names = mpc8572_onchip_intr_names,
343 	.ii_ist_vectors = {
344 		[IST_NONE]		= ~0,
345 		[IST_EDGE]		= 0,
346 		[IST_LEVEL_LOW]		= 0,
347 		[IST_LEVEL_HIGH]	= 0,
348 		[IST_ONCHIP]		= MPC8572_EXTERNALSOURCES,
349 		[IST_MSIGROUP]		= MPC8572_EXTERNALSOURCES
350 					    + MPC8572_ONCHIPSOURCES,
351 		[IST_TIMER]		= MPC8572_EXTERNALSOURCES
352 					    + MPC8572_ONCHIPSOURCES
353 					    + MPC8572_MSIGROUPSOURCES,
354 		[IST_IPI]		= MPC8572_EXTERNALSOURCES
355 					    + MPC8572_ONCHIPSOURCES
356 					    + MPC8572_MSIGROUPSOURCES
357 					    + MPC8572_TIMERSOURCES,
358 		[IST_MI]		= MPC8572_EXTERNALSOURCES
359 					    + MPC8572_ONCHIPSOURCES
360 					    + MPC8572_MSIGROUPSOURCES
361 					    + MPC8572_TIMERSOURCES
362 					    + MPC8572_IPISOURCES,
363 		[IST_MAX]		= MPC8572_EXTERNALSOURCES
364 					    + MPC8572_ONCHIPSOURCES
365 					    + MPC8572_MSIGROUPSOURCES
366 					    + MPC8572_TIMERSOURCES
367 					    + MPC8572_IPISOURCES
368 					    + MPC8572_MISOURCES,
369 	},
370 };
371 
372 static const char ist_names[][12] = {
373 	[IST_NONE] = "none",
374 	[IST_EDGE] = "edge",
375 	[IST_LEVEL_LOW] = "level-",
376 	[IST_LEVEL_HIGH] = "level+",
377 	[IST_MSI] = "msi",
378 	[IST_ONCHIP] = "onchip",
379 	[IST_MSIGROUP] = "msigroup",
380 	[IST_TIMER] = "timer",
381 	[IST_IPI] = "ipi",
382 	[IST_MI] = "msgint",
383 };
384 
385 static struct intr_source *e500_intr_sources;
386 static const struct intr_source *e500_intr_last_source;
387 
388 static void 	*e500_intr_establish(int, int, int, int (*)(void *), void *);
389 static void 	e500_intr_disestablish(void *);
390 static void 	e500_intr_cpu_init(struct cpu_info *ci);
391 static void 	e500_intr_init(void);
392 static const char *e500_intr_string(int, int);
393 static void 	e500_critintr(struct trapframe *tf);
394 static void 	e500_decrintr(struct trapframe *tf);
395 static void 	e500_extintr(struct trapframe *tf);
396 static void 	e500_fitintr(struct trapframe *tf);
397 static void 	e500_wdogintr(struct trapframe *tf);
398 static void	e500_spl0(void);
399 static int 	e500_splraise(int);
400 static void 	e500_splx(int);
401 #ifdef __HAVE_FAST_SOFTINTS
402 static void 	e500_softint_init_md(lwp_t *l, u_int si_level, uintptr_t *machdep_p);
403 static void 	e500_softint_trigger(uintptr_t machdep);
404 #endif
405 
406 const struct intrsw e500_intrsw = {
407 	.intrsw_establish = e500_intr_establish,
408 	.intrsw_disestablish = e500_intr_disestablish,
409 	.intrsw_init = e500_intr_init,
410 	.intrsw_cpu_init = e500_intr_cpu_init,
411 	.intrsw_string = e500_intr_string,
412 
413 	.intrsw_critintr = e500_critintr,
414 	.intrsw_decrintr = e500_decrintr,
415 	.intrsw_extintr = e500_extintr,
416 	.intrsw_fitintr = e500_fitintr,
417 	.intrsw_wdogintr = e500_wdogintr,
418 
419 	.intrsw_splraise = e500_splraise,
420 	.intrsw_splx = e500_splx,
421 	.intrsw_spl0 = e500_spl0,
422 
423 #ifdef __HAVE_FAST_SOFTINTS
424 	.intrsw_softint_init_md = e500_softint_init_md,
425 	.intrsw_softint_trigger = e500_softint_trigger,
426 #endif
427 };
428 
429 static inline uint32_t
430 openpic_read(struct cpu_softc *cpu, bus_size_t offset)
431 {
432 
433 	return bus_space_read_4(cpu->cpu_bst, cpu->cpu_bsh,
434 	    OPENPIC_BASE + offset);
435 }
436 
437 static inline void
438 openpic_write(struct cpu_softc *cpu, bus_size_t offset, uint32_t val)
439 {
440 
441 	return bus_space_write_4(cpu->cpu_bst, cpu->cpu_bsh,
442 	    OPENPIC_BASE + offset, val);
443 }
444 
445 static const char *
446 e500_intr_external_name_lookup(int irq)
447 {
448 	prop_array_t extirqs = board_info_get_object("external-irqs");
449 	prop_string_t irqname = prop_array_get(extirqs, irq);
450 	KASSERT(irqname != NULL);
451 	KASSERT(prop_object_type(irqname) == PROP_TYPE_STRING);
452 
453 	return prop_string_cstring_nocopy(irqname);
454 }
455 
456 static const char *
457 e500_intr_name_lookup(const struct e500_intr_name *names, int irq)
458 {
459 	for (; names->in_name[0] != '\0'; names++) {
460 		if (names->in_irq == irq)
461 			return names->in_name;
462 	}
463 
464 	return NULL;
465 }
466 
467 static const char *
468 e500_intr_onchip_name_lookup(int irq)
469 {
470 	const char *name;
471 
472 	return e500_intr_name_lookup(e500_intr_info.ii_onchip_intr_names, irq);
473 	if (name != NULL)
474 		return name;
475 
476 	name = e500_intr_name_lookup(e500_onchip_intr_names, irq);
477 }
478 
479 #ifdef __HAVE_FAST_SOFTINTS
480 static inline void
481 e500_softint_deliver(struct cpu_info *ci, struct cpu_softc *cpu,
482 	int ipl, int si_level)
483 {
484 	KASSERT(ci->ci_data.cpu_softints & (1 << ipl));
485 	ci->ci_data.cpu_softints ^= 1 << ipl;
486 	softint_fast_dispatch(cpu->cpu_softlwps[si_level], ipl);
487 	KASSERT(cpu->cpu_softlwps[si_level]->l_ctxswtch == 0);
488 	KASSERTMSG(ci->ci_cpl == IPL_HIGH,
489 	    ("%s: cpl (%d) != HIGH", __func__, ci->ci_cpl));
490 }
491 
492 static inline void
493 e500_softint(struct cpu_info *ci, struct cpu_softc *cpu, int old_ipl)
494 {
495 	const u_int softint_mask = (IPL_SOFTMASK << old_ipl) & IPL_SOFTMASK;
496 	u_int softints;
497 
498 	KASSERT(ci->ci_mtx_count == 0);
499 	KASSERT(ci->ci_cpl == IPL_HIGH);
500 	while ((softints = (ci->ci_data.cpu_softints & softint_mask)) != 0) {
501 		KASSERT(old_ipl < IPL_SOFTSERIAL);
502 		if (softints & (1 << IPL_SOFTSERIAL)) {
503 			e500_softint_deliver(ci, cpu, IPL_SOFTSERIAL,
504 			    SOFTINT_SERIAL);
505 			continue;
506 		}
507 		KASSERT(old_ipl < IPL_SOFTNET);
508 		if (softints & (1 << IPL_SOFTNET)) {
509 			e500_softint_deliver(ci, cpu, IPL_SOFTNET,
510 			    SOFTINT_NET);
511 			continue;
512 		}
513 		KASSERT(old_ipl < IPL_SOFTBIO);
514 		if (softints & (1 << IPL_SOFTBIO)) {
515 			e500_softint_deliver(ci, cpu, IPL_SOFTBIO,
516 			    SOFTINT_BIO);
517 			continue;
518 		}
519 		KASSERT(old_ipl < IPL_SOFTCLOCK);
520 		if (softints & (1 << IPL_SOFTCLOCK)) {
521 			e500_softint_deliver(ci, cpu, IPL_SOFTCLOCK,
522 			    SOFTINT_CLOCK);
523 			continue;
524 		}
525 	}
526 }
527 #endif /* __HAVE_FAST_SOFTINTS */
528 
529 static inline void
530 e500_splset(struct cpu_info *ci, int ipl)
531 {
532 	struct cpu_softc * const cpu = ci->ci_softc;
533 	//KASSERT(!cpu_intr_p() || ipl >= IPL_VM);
534 	KASSERT((curlwp->l_pflag & LP_INTR) == 0 || ipl != IPL_NONE);
535 #if 0
536 	u_int ctpr = ipl;
537 	KASSERT(openpic_read(cpu, OPENPIC_CTPR) == ci->ci_cpl);
538 #elif 0
539 	u_int old_ctpr = (ci->ci_cpl >= IPL_VM ? 15 : ci->ci_cpl);
540 	u_int ctpr = (ipl >= IPL_VM ? 15 : ipl);
541 	KASSERT(openpic_read(cpu, OPENPIC_CTPR) == old_ctpr);
542 #else
543 	u_int old_ctpr = IPL2CTPR(ci->ci_cpl);
544 	u_int ctpr = IPL2CTPR(ipl);
545 	KASSERT(openpic_read(cpu, OPENPIC_CTPR) == old_ctpr);
546 #endif
547 	openpic_write(cpu, OPENPIC_CTPR, ctpr);
548 	KASSERT(openpic_read(cpu, OPENPIC_CTPR) == ctpr);
549 	ci->ci_cpl = ipl;
550 }
551 
552 static void
553 e500_spl0(void)
554 {
555 	struct cpu_info * const ci = curcpu();
556 
557 	wrtee(0);
558 
559 #ifdef __HAVE_FAST_SOFTINTS
560 	if (__predict_false(ci->ci_data.cpu_softints != 0)) {
561 		e500_splset(ci, IPL_HIGH);
562 		e500_softint(ci, ci->ci_softc, IPL_NONE);
563 	}
564 #endif /* __HAVE_FAST_SOFTINTS */
565 	e500_splset(ci, IPL_NONE);
566 
567 	wrtee(PSL_EE);
568 }
569 
570 static void
571 e500_splx(int ipl)
572 {
573 	struct cpu_info * const ci = curcpu();
574 	const int old_ipl = ci->ci_cpl;
575 
576 	KASSERT(mfmsr() & PSL_CE);
577 
578 	if (ipl == old_ipl)
579 		return;
580 
581 	if (__predict_false(ipl > old_ipl)) {
582 		printf("%s: %p: cpl=%u: ignoring splx(%u) to raise ipl\n",
583 		    __func__, __builtin_return_address(0), old_ipl, ipl);
584 		if (old_ipl == IPL_NONE)
585 			Debugger();
586 	}
587 
588 	// const
589 	register_t msr = wrtee(0);
590 #ifdef __HAVE_FAST_SOFTINTS
591 	const u_int softints = (ci->ci_data.cpu_softints << ipl) & IPL_SOFTMASK;
592 	if (__predict_false(softints != 0)) {
593 		e500_splset(ci, IPL_HIGH);
594 		e500_softint(ci, ci->ci_softc, ipl);
595 	}
596 #endif /* __HAVE_FAST_SOFTINTS */
597 	e500_splset(ci, ipl);
598 #if 1
599 	if (ipl < IPL_VM && old_ipl >= IPL_VM)
600 		msr = PSL_EE;
601 #endif
602 	wrtee(msr);
603 }
604 
605 static int
606 e500_splraise(int ipl)
607 {
608 	struct cpu_info * const ci = curcpu();
609 	const int old_ipl = ci->ci_cpl;
610 
611 	KASSERT(mfmsr() & PSL_CE);
612 
613 	if (old_ipl < ipl) {
614 		//const
615 		register_t msr = wrtee(0);
616 		e500_splset(ci, ipl);
617 #if 1
618 		if (old_ipl < IPL_VM && ipl >= IPL_VM)
619 			msr = 0;
620 #endif
621 		wrtee(msr);
622 	} else if (ipl == IPL_NONE) {
623 		panic("%s: %p: cpl=%u: attempt to splraise(IPL_NONE)",
624 		    __func__, __builtin_return_address(0), old_ipl);
625 #if 0
626 	} else if (old_ipl > ipl) {
627 		printf("%s: %p: cpl=%u: ignoring splraise(%u) to lower ipl\n",
628 		    __func__, __builtin_return_address(0), old_ipl, ipl);
629 #endif
630 	}
631 
632 	return old_ipl;
633 }
634 
635 #ifdef __HAVE_FAST_SOFTINTS
636 static void
637 e500_softint_init_md(lwp_t *l, u_int si_level, uintptr_t *machdep_p)
638 {
639 	struct cpu_info * const ci = l->l_cpu;
640 	struct cpu_softc * const cpu = ci->ci_softc;
641 
642 	*machdep_p = 1 << SOFTINT2IPL(si_level);
643 	KASSERT(*machdep_p & IPL_SOFTMASK);
644 	cpu->cpu_softlwps[si_level] = l;
645 }
646 
647 static void
648 e500_softint_trigger(uintptr_t machdep)
649 {
650 	struct cpu_info * const ci = curcpu();
651 
652 	atomic_or_uint(&ci->ci_data.cpu_softints, machdep);
653 	if (machdep == (1 << IPL_SOFTBIO))
654 		printf("%s(%u): cpl=%u\n", __func__, machdep, ci->ci_cpl);
655 }
656 #endif /* __HAVE_FAST_SOFTINTS */
657 
658 static int
659 e500_intr_spurious(void *arg)
660 {
661 	return 0;
662 }
663 
664 static bool
665 e500_intr_irq_info_get(struct cpu_info *ci, u_int irq, int ipl, int ist,
666 	struct e500_intr_irq_info *ii)
667 {
668 	const struct e500_intr_info * const info = &e500_intr_info;
669 	bool ok;
670 
671 #if DEBUG > 2
672 	printf("%s(%p,irq=%u,ipl=%u,ist=%u,%p)\n", __func__, ci, irq, ipl, ist, ii);
673 #endif
674 
675 	if (ipl < IPL_VM || ipl > IPL_HIGH) {
676 #if DEBUG > 2
677 		printf("%s:%d ipl=%u\n", __func__, __LINE__, ipl);
678 #endif
679 		return false;
680 	}
681 
682 	if (ist <= IST_NONE || ist >= IST_MAX) {
683 #if DEBUG > 2
684 		printf("%s:%d ist=%u\n", __func__, __LINE__, ist);
685 #endif
686 		return false;
687 	}
688 
689 	ii->irq_vector = irq + info->ii_ist_vectors[ist];
690 	if (IST_PERCPU_P(ist))
691 		ii->irq_vector += ci->ci_cpuid * info->ii_percpu_sources;
692 
693 	switch (ist) {
694 	default:
695 		ii->irq_vpr = OPENPIC_EIVPR(irq);
696 		ii->irq_dr  = OPENPIC_EIDR(irq);
697 		ok = irq < info->ii_external_sources
698 		    && (ist == IST_EDGE
699 			|| ist == IST_LEVEL_LOW
700 			|| ist == IST_LEVEL_HIGH);
701 		break;
702 	case IST_ONCHIP:
703 		ii->irq_vpr = OPENPIC_IIVPR(irq);
704 		ii->irq_dr  = OPENPIC_IIDR(irq);
705 		ok = irq < 32 * __arraycount(info->ii_onchip_bitmap);
706 #if DEBUG > 2
707 		printf("%s: irq=%u: ok=%u\n", __func__, irq, ok);
708 #endif
709 		ok = ok && (info->ii_onchip_bitmap[irq/32] & (1 << (irq & 31)));
710 #if DEBUG > 2
711 		printf("%s: %08x%08x -> %08x%08x: ok=%u\n", __func__,
712 		    irq < 32 ? 0 : (1 << irq), irq < 32 ? (1 << irq) : 0,
713 		    info->ii_onchip_bitmap[1], info->ii_onchip_bitmap[0],
714 		    ok);
715 #endif
716 		break;
717 	case IST_MSIGROUP:
718 		ii->irq_vpr = OPENPIC_MSIVPR(irq);
719 		ii->irq_dr  = OPENPIC_MSIDR(irq);
720 		ok = irq < info->ii_msigroup_sources
721 		    && ipl == IPL_VM;
722 		break;
723 	case IST_TIMER:
724 		ii->irq_vpr = OPENPIC_GTVPR(ci->ci_cpuid, irq);
725 		ii->irq_dr  = OPENPIC_GTDR(ci->ci_cpuid, irq);
726 		ok = irq < info->ii_timer_sources;
727 #if DEBUG > 2
728 		printf("%s: IST_TIMER irq=%u: ok=%u\n", __func__, irq, ok);
729 #endif
730 		break;
731 	case IST_IPI:
732 		ii->irq_vpr = OPENPIC_IPIVPR(irq);
733 		ii->irq_dr  = OPENPIC_IPIDR(irq);
734 		ok = irq < info->ii_ipi_sources;
735 		break;
736 	case IST_MI:
737 		ii->irq_vpr = OPENPIC_MIVPR(irq);
738 		ii->irq_dr  = OPENPIC_MIDR(irq);
739 		ok = irq < info->ii_mi_sources;
740 		break;
741 	}
742 
743 	return ok;
744 }
745 
746 static const char *
747 e500_intr_string(int irq, int ist)
748 {
749 	struct cpu_info * const ci = curcpu();
750 	struct cpu_softc * const cpu = ci->ci_softc;
751 	struct e500_intr_irq_info ii;
752 
753 	if (!e500_intr_irq_info_get(ci, irq, IPL_VM, ist, &ii))
754 		return NULL;
755 
756 	return cpu->cpu_evcnt_intrs[ii.irq_vector].ev_name;
757 }
758 
759 static void *
760 e500_intr_cpu_establish(struct cpu_info *ci, int irq, int ipl, int ist,
761 	int (*handler)(void *), void *arg)
762 {
763 	struct cpu_softc * const cpu = ci->ci_softc;
764 	struct e500_intr_irq_info ii;
765 
766 	KASSERT(ipl >= IPL_VM && ipl <= IPL_HIGH);
767 	KASSERT(ist > IST_NONE && ist < IST_MAX && ist != IST_MSI);
768 
769 	if (!e500_intr_irq_info_get(ci, irq, ipl, ist, &ii)) {
770 		printf("%s: e500_intr_irq_info_get(%p,%u,%u,%u,%p) failed\n",
771 		    __func__, ci, irq, ipl, ist, &ii);
772 		return NULL;
773 	}
774 
775 	struct intr_source * const is = &e500_intr_sources[ii.irq_vector];
776 	mutex_enter(&e500_intr_lock);
777 	if (is->is_ipl != IPL_NONE)
778 		return NULL;
779 
780 	is->is_func = handler;
781 	is->is_arg = arg;
782 	is->is_ipl = ipl;
783 	is->is_ist = ist;
784 	is->is_irq = irq;
785 	is->is_vpr = ii.irq_vpr;
786 	is->is_dr = ii.irq_dr;
787 
788 	uint32_t vpr = VPR_PRIORITY_MAKE(IPL2CTPR(ipl))
789 	    | VPR_VECTOR_MAKE(((ii.irq_vector + 1) << 4) | ipl)
790 	    | (ist == IST_LEVEL_LOW
791 		? VPR_LEVEL_LOW
792 		: (ist == IST_LEVEL_HIGH
793 		    ? VPR_LEVEL_HIGH
794 		    : (ist == IST_ONCHIP
795 		      ? VPR_P_HIGH
796 		      : 0)));
797 
798 	/*
799 	 * All interrupts go to the primary except per-cpu interrupts which get
800 	 * routed to the appropriate cpu.
801 	 */
802 	uint32_t dr = IST_PERCPU_P(ist) ? 1 << ci->ci_cpuid : 1;
803 
804 	/*
805 	 * Update the vector/priority and destination registers keeping the
806 	 * interrupt masked.
807 	 */
808 	const register_t msr = wrtee(0);	/* disable interrupts */
809 	openpic_write(cpu, ii.irq_vpr, vpr | VPR_MSK);
810 	openpic_write(cpu, ii.irq_dr, dr);
811 
812 	/*
813 	 * Now unmask the interrupt.
814 	 */
815 	openpic_write(cpu, ii.irq_vpr, vpr);
816 
817 	wrtee(msr);				/* re-enable interrupts */
818 
819 	mutex_exit(&e500_intr_lock);
820 
821 	return is;
822 }
823 
824 static void *
825 e500_intr_establish(int irq, int ipl, int ist,
826 	int (*handler)(void *), void *arg)
827 {
828 	return e500_intr_cpu_establish(curcpu(), irq, ipl, ist, handler, arg);
829 }
830 
831 static void
832 e500_intr_disestablish(void *vis)
833 {
834 	struct cpu_softc * const cpu = curcpu()->ci_softc;
835 	struct intr_source * const is = vis;
836 	struct e500_intr_irq_info ii;
837 
838 	KASSERT(e500_intr_sources <= is);
839 	KASSERT(is < e500_intr_last_source);
840 	KASSERT(!cpu_intr_p());
841 
842 	bool ok = e500_intr_irq_info_get(curcpu(), is->is_irq, is->is_ipl,
843 	    is->is_ist, &ii);
844 	(void)ok;	/* appease gcc */
845 	KASSERT(ok);
846 	KASSERT(is - e500_intr_sources == ii.irq_vector);
847 
848 	mutex_enter(&e500_intr_lock);
849 	/*
850 	 * Mask the source using the mask (MSK) bit in the vector/priority reg.
851 	 */
852 	uint32_t vpr = openpic_read(cpu, ii.irq_vpr);
853 	openpic_write(cpu, ii.irq_vpr, VPR_MSK | vpr);
854 
855 	/*
856 	 * Wait for the Activity (A) bit for the source to be cleared.
857 	 */
858 	while (openpic_read(cpu, ii.irq_vpr) & VPR_A)
859 		;
860 
861 	/*
862 	 * Now the source can be modified.
863 	 */
864 	openpic_write(cpu, ii.irq_dr, 0);		/* stop delivery */
865 	openpic_write(cpu, ii.irq_vpr, VPR_MSK);	/* mask/reset it */
866 
867 	*is = (struct intr_source)INTR_SOURCE_INITIALIZER;
868 
869 	mutex_exit(&e500_intr_lock);
870 }
871 
872 static void
873 e500_critintr(struct trapframe *tf)
874 {
875 	panic("%s: srr0/srr1=%#lx/%#lx", __func__, tf->tf_srr0, tf->tf_srr1);
876 }
877 
878 static void
879 e500_decrintr(struct trapframe *tf)
880 {
881 	panic("%s: srr0/srr1=%#lx/%#lx", __func__, tf->tf_srr0, tf->tf_srr1);
882 }
883 
884 static void
885 e500_fitintr(struct trapframe *tf)
886 {
887 	panic("%s: srr0/srr1=%#lx/%#lx", __func__, tf->tf_srr0, tf->tf_srr1);
888 }
889 
890 static void
891 e500_wdogintr(struct trapframe *tf)
892 {
893 	mtspr(SPR_TSR, TSR_ENW|TSR_WIS);
894 	panic("%s: tf=%p tb=%"PRId64" srr0/srr1=%#lx/%#lx", __func__, tf,
895 	    mftb(), tf->tf_srr0, tf->tf_srr1);
896 }
897 
898 static void
899 e500_extintr(struct trapframe *tf)
900 {
901 	struct cpu_info * const ci = curcpu();
902 	struct cpu_softc * const cpu = ci->ci_softc;
903 	const int old_ipl = ci->ci_cpl;
904 
905 	KASSERT(mfmsr() & PSL_CE);
906 
907 #if 0
908 //	printf("%s(%p): idepth=%d enter\n", __func__, tf, ci->ci_idepth);
909 	if ((register_t)tf >= (register_t)curlwp->l_addr + USPACE
910 	    || (register_t)tf < (register_t)curlwp->l_addr + NBPG) {
911 		printf("%s(entry): pid %d.%d (%s): srr0/srr1=%#lx/%#lx: invalid tf addr %p\n",
912 		    __func__, curlwp->l_proc->p_pid, curlwp->l_lid,
913 		    curlwp->l_proc->p_comm, tf->tf_srr0, tf->tf_srr1, tf);
914 	}
915 #endif
916 
917 
918 	ci->ci_data.cpu_nintr++;
919 	tf->tf_cf.cf_idepth = ci->ci_idepth++;
920 	cpu->cpu_pcpls[ci->ci_idepth] = old_ipl;
921 #if 1
922 	if (mfmsr() & PSL_EE)
923 		panic("%s(%p): MSR[EE] is on (%#lx)!", __func__, tf, mfmsr());
924 	if (old_ipl == IPL_HIGH
925 	    || IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
926 		panic("%s(%p): old_ipl(%u) == IPL_HIGH(%u) "
927 		    "|| old_ipl + %u != OPENPIC_CTPR (%u)",
928 		    __func__, tf, old_ipl, IPL_HIGH,
929 		    15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
930 #else
931 	if (old_ipl >= IPL_VM)
932 		panic("%s(%p): old_ipl(%u) >= IPL_VM(%u) CTPR=%u",
933 		    __func__, tf, old_ipl, IPL_VM, openpic_read(cpu, OPENPIC_CTPR));
934 #endif
935 
936 	for (;;) {
937 		/*
938 		 * Find out the pending interrupt.
939 		 */
940 	if (mfmsr() & PSL_EE)
941 		panic("%s(%p): MSR[EE] turned on (%#lx)!", __func__, tf, mfmsr());
942 		if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
943 			panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
944 			    __func__, tf, __LINE__, old_ipl,
945 			    15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
946 		const uint32_t iack = openpic_read(cpu, OPENPIC_IACK);
947 		const int ipl = iack & 0xf;
948 		const int irq = (iack >> 4) - 1;
949 #if 0
950 		printf("%s: iack=%d ipl=%d irq=%d <%s>\n",
951 		    __func__, iack, ipl, irq,
952 		    (iack != IRQ_SPURIOUS ?
953 			cpu->cpu_evcnt_intrs[irq].ev_name : "spurious"));
954 #endif
955 		if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
956 			panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
957 			    __func__, tf, __LINE__, old_ipl,
958 			    15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
959 		if (iack == IRQ_SPURIOUS)
960 			break;
961 
962 		struct intr_source * const is = &e500_intr_sources[irq];
963 		if (__predict_true(is < e500_intr_last_source)) {
964 			/*
965 			 * Timer interrupts get their argument overriden with
966 			 * the pointer to the trapframe.
967 			 */
968 			KASSERT(is->is_ipl == ipl);
969 			void *arg = (is->is_ist == IST_TIMER ? tf : is->is_arg);
970 			if (is->is_ipl <= old_ipl)
971 				panic("%s(%p): %s (%u): is->is_ipl (%u) <= old_ipl (%u)\n",
972 				    __func__, tf,
973 				    cpu->cpu_evcnt_intrs[irq].ev_name, irq,
974 				    is->is_ipl, old_ipl);
975 			KASSERT(is->is_ipl > old_ipl);
976 			e500_splset(ci, is->is_ipl);	/* change IPL */
977 			if (__predict_false(is->is_func == NULL)) {
978 				aprint_error_dev(ci->ci_dev,
979 				    "interrupt from unestablished irq %d\n",
980 				    irq);
981 			} else {
982 				int (*func)(void *) = is->is_func;
983 				wrtee(PSL_EE);
984 				int rv = (*func)(arg);
985 				wrtee(0);
986 #if DEBUG > 2
987 				printf("%s: %s handler %p(%p) returned %d\n",
988 				    __func__,
989 				    cpu->cpu_evcnt_intrs[irq].ev_name,
990 				    func, arg, rv);
991 #endif
992 				if (rv == 0)
993 					cpu->cpu_evcnt_spurious_intr.ev_count++;
994 			}
995 			e500_splset(ci, old_ipl);	/* restore IPL */
996 			cpu->cpu_evcnt_intrs[irq].ev_count++;
997 		} else {
998 			aprint_error_dev(ci->ci_dev,
999 			    "interrupt from illegal irq %d\n", irq);
1000 			cpu->cpu_evcnt_spurious_intr.ev_count++;
1001 		}
1002 		/*
1003 		 * If this is a nested interrupt, simply ack it and exit
1004 		 * because the loop we interrupted will complete looking
1005 		 * for interrupts.
1006 		 */
1007 	if (mfmsr() & PSL_EE)
1008 		panic("%s(%p): MSR[EE] left on (%#lx)!", __func__, tf, mfmsr());
1009 		if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
1010 			panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
1011 			    __func__, tf, __LINE__, old_ipl,
1012 			    15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
1013 
1014 		openpic_write(cpu, OPENPIC_EOI, 0);
1015 		if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
1016 			panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
1017 			    __func__, tf, __LINE__, old_ipl,
1018 			    15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
1019 		if (ci->ci_idepth > 0)
1020 			break;
1021 	}
1022 
1023 	ci->ci_idepth--;
1024 
1025 #ifdef __HAVE_FAST_SOFTINTS
1026 	/*
1027 	 * Before exiting, deal with any softints that need to be dealt with.
1028 	 */
1029 	const u_int softints = (ci->ci_data.cpu_softints << old_ipl) & IPL_SOFTMASK;
1030 	if (__predict_false(softints != 0)) {
1031 		KASSERT(old_ipl < IPL_VM);
1032 		e500_splset(ci, IPL_HIGH);	/* pop to high */
1033 		e500_softint(ci, cpu, old_ipl);	/* deal with them */
1034 		e500_splset(ci, old_ipl);	/* and drop back */
1035 	}
1036 #endif /* __HAVE_FAST_SOFTINTS */
1037 #if 1
1038 	KASSERT(ci->ci_cpl == old_ipl);
1039 #else
1040 	e500_splset(ci, old_ipl);		/* and drop back */
1041 #endif
1042 
1043 //	printf("%s(%p): idepth=%d exit\n", __func__, tf, ci->ci_idepth);
1044 }
1045 
1046 static void
1047 e500_intr_init(void)
1048 {
1049 	struct cpu_info * const ci = curcpu();
1050 	struct cpu_softc * const cpu = ci->ci_softc;
1051 	const uint32_t frr = openpic_read(cpu, OPENPIC_FRR);
1052 	const u_int nirq = FRR_NIRQ_GET(frr) + 1;
1053 //	const u_int ncpu = FRR_NCPU_GET(frr) + 1;
1054 	struct intr_source *is;
1055 	struct e500_intr_info * const ii = &e500_intr_info;
1056 
1057 	switch (nirq) {
1058 	case MPC8548_SOURCES: {
1059 		CTASSERT(MPC8548_ONCHIPSOURCES == MPC8544_ONCHIPSOURCES);
1060 		*ii = mpc8548_intr_info;
1061 		if ((mfspr(SPR_SVR) >> 16) == (SVR_MPC8544v1 >> 16)) {
1062 			uint32_t bitmap[2] = MPC8548_ONCHIPBITMAP;
1063 			ii->ii_onchip_bitmap[0] = bitmap[0];
1064 			ii->ii_onchip_bitmap[1] = bitmap[1];
1065 			ii->ii_onchip_sources = MPC8544_ONCHIPSOURCES;
1066 			ii->ii_onchip_intr_names = mpc8544_onchip_intr_names;
1067 		}
1068 		break;
1069 	}
1070 	case MPC8536_SOURCES:
1071 		*ii = mpc8536_intr_info;
1072 		break;
1073 	case MPC8572_SOURCES:
1074 		*ii = mpc8572_intr_info;
1075 		break;
1076 	default:
1077 		panic("%s: don't know how to deal with %u interrupt sources",
1078 		    __func__, nirq);
1079 	}
1080 
1081 	/*
1082 	 * We need to be in mixed mode.
1083 	 */
1084 	openpic_write(cpu, OPENPIC_GCR, GCR_M);
1085 
1086 	/*
1087 	 * Make we and the openpic both agree about the current SPL level.
1088 	 */
1089 	e500_splset(ci, ci->ci_cpl);
1090 
1091 	/*
1092 	 * Allow the required number of interrupt sources.
1093 	 */
1094 	is = kmem_zalloc(nirq * sizeof(*is), KM_SLEEP);
1095 	KASSERT(is);
1096 	e500_intr_sources = is;
1097 	e500_intr_last_source = is + nirq;
1098 
1099 	/*
1100 	 * Initialize all the external interrupts as active low.
1101 	 */
1102 	for (u_int irq = 0; irq < e500_intr_info.ii_external_sources; irq++) {
1103 		openpic_write(cpu, OPENPIC_EIVPR(irq),
1104 		    VPR_VECTOR_MAKE(irq) | VPR_LEVEL_LOW);
1105 	}
1106 }
1107 
1108 static void
1109 e500_intr_cpu_init(struct cpu_info *ci)
1110 {
1111 	struct cpu_softc * const cpu = ci->ci_softc;
1112 	const char * const xname = device_xname(ci->ci_dev);
1113 
1114 	const u_int32_t frr = openpic_read(cpu, OPENPIC_FRR);
1115 	const u_int nirq = FRR_NIRQ_GET(frr) + 1;
1116 //	const u_int ncpu = FRR_NCPU_GET(frr) + 1;
1117 
1118 	const struct e500_intr_info * const info = &e500_intr_info;
1119 
1120 	cpu->cpu_clock_gtbcr = OPENPIC_GTBCR(ci->ci_cpuid, E500_CLOCK_TIMER);
1121 
1122 	cpu->cpu_evcnt_intrs =
1123 	    kmem_zalloc(nirq * sizeof(cpu->cpu_evcnt_intrs[0]), KM_SLEEP);
1124 	KASSERT(cpu->cpu_evcnt_intrs);
1125 
1126 	struct evcnt *evcnt = cpu->cpu_evcnt_intrs;
1127 	for (size_t j = 0; j < info->ii_external_sources; j++, evcnt++) {
1128 		const char *name = e500_intr_external_name_lookup(j);
1129 		evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR, NULL, xname, name);
1130 	}
1131 	KASSERT(evcnt == cpu->cpu_evcnt_intrs + info->ii_ist_vectors[IST_ONCHIP]);
1132 	for (size_t j = 0; j < info->ii_onchip_sources; j++, evcnt++) {
1133 		const char *name = e500_intr_onchip_name_lookup(j);
1134 		if (name != NULL) {
1135 			evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1136 			    NULL, xname, name);
1137 		}
1138 	}
1139 
1140 	KASSERT(evcnt == cpu->cpu_evcnt_intrs + info->ii_ist_vectors[IST_MSIGROUP]);
1141 	for (size_t j = 0; j < info->ii_msigroup_sources; j++, evcnt++) {
1142 		evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1143 		    NULL, xname, e500_msigroup_intr_names[j].in_name);
1144 	}
1145 
1146 	KASSERT(evcnt == cpu->cpu_evcnt_intrs + info->ii_ist_vectors[IST_TIMER]);
1147 	evcnt += ci->ci_cpuid * info->ii_percpu_sources;
1148 	for (size_t j = 0; j < info->ii_timer_sources; j++, evcnt++) {
1149 		evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1150 		    NULL, xname, e500_timer_intr_names[j].in_name);
1151 	}
1152 
1153 	for (size_t j = 0; j < info->ii_ipi_sources; j++, evcnt++) {
1154 		evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1155 		    NULL, xname, e500_ipi_intr_names[j].in_name);
1156 	}
1157 
1158 	for (size_t j = 0; j < info->ii_mi_sources; j++, evcnt++) {
1159 		evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1160 		    NULL, xname, e500_mi_intr_names[j].in_name);
1161 	}
1162 
1163 	/*
1164 	 * Establish interrupt for this CPU.
1165 	 */
1166 	if (e500_intr_cpu_establish(ci, E500_CLOCK_TIMER, IPL_CLOCK, IST_TIMER,
1167 	    e500_clock_intr, NULL) == NULL)
1168 		panic("%s: failed to establish clock interrupt!", __func__);
1169 
1170 	/*
1171 	 * Enable watchdog interrupts.
1172 	 */
1173 	uint32_t tcr = mfspr(SPR_TCR);
1174 	tcr |= TCR_WIE;
1175 	mtspr(SPR_TCR, tcr);
1176 }
1177