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