xref: /openbsd-src/sys/arch/macppc/dev/openpic.c (revision de0524796acd867538c2bb2b0f4ab84447da8e6c)
1*de052479Scheloha /*	$OpenBSD: openpic.c,v 1.90 2022/07/24 00:28:09 cheloha Exp $	*/
2d9a5f17fSdrahn 
3d9a5f17fSdrahn /*-
4d7469fedSdrahn  * Copyright (c) 2008 Dale Rahn <drahn@openbsd.org>
5d9a5f17fSdrahn  * Copyright (c) 1995 Per Fogelstrom
6d9a5f17fSdrahn  * Copyright (c) 1993, 1994 Charles M. Hannum.
7d9a5f17fSdrahn  * Copyright (c) 1990 The Regents of the University of California.
8d9a5f17fSdrahn  * All rights reserved.
9d9a5f17fSdrahn  *
10d9a5f17fSdrahn  * This code is derived from software contributed to Berkeley by
11d9a5f17fSdrahn  * William Jolitz and Don Ahn.
12d9a5f17fSdrahn  *
13d9a5f17fSdrahn  * Redistribution and use in source and binary forms, with or without
14d9a5f17fSdrahn  * modification, are permitted provided that the following conditions
15d9a5f17fSdrahn  * are met:
16d9a5f17fSdrahn  * 1. Redistributions of source code must retain the above copyright
17d9a5f17fSdrahn  *    notice, this list of conditions and the following disclaimer.
18d9a5f17fSdrahn  * 2. Redistributions in binary form must reproduce the above copyright
19d9a5f17fSdrahn  *    notice, this list of conditions and the following disclaimer in the
20d9a5f17fSdrahn  *    documentation and/or other materials provided with the distribution.
2129295d1cSmillert  * 3. Neither the name of the University nor the names of its contributors
22d9a5f17fSdrahn  *    may be used to endorse or promote products derived from this software
23d9a5f17fSdrahn  *    without specific prior written permission.
24d9a5f17fSdrahn  *
25d9a5f17fSdrahn  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26d9a5f17fSdrahn  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27d9a5f17fSdrahn  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28d9a5f17fSdrahn  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29d9a5f17fSdrahn  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30d9a5f17fSdrahn  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31d9a5f17fSdrahn  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32d9a5f17fSdrahn  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33d9a5f17fSdrahn  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34d9a5f17fSdrahn  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35d9a5f17fSdrahn  * SUCH DAMAGE.
36d9a5f17fSdrahn  *
37d9a5f17fSdrahn  *	@(#)isa.c	7.2 (Berkeley) 5/12/91
38d9a5f17fSdrahn  */
39d9a5f17fSdrahn 
40ba99a0edSmpi #include "hpb.h"
41ba99a0edSmpi 
42d9a5f17fSdrahn #include <sys/param.h>
43d9a5f17fSdrahn #include <sys/device.h>
44d9a5f17fSdrahn #include <sys/systm.h>
45417aa565Smpi #include <sys/malloc.h>
46ba99a0edSmpi #include <sys/atomic.h>
4730c76742Smickey 
48417aa565Smpi #include <uvm/uvm_extern.h>
49d9a5f17fSdrahn 
50d9a5f17fSdrahn #include <machine/autoconf.h>
51d9a5f17fSdrahn #include <machine/intr.h>
52d9a5f17fSdrahn #include <machine/psl.h>
53d9a5f17fSdrahn #include <machine/pio.h>
54d9a5f17fSdrahn #include <dev/ofw/openfirm.h>
55d9a5f17fSdrahn 
56bccc5538Smpi #include <macppc/dev/openpicreg.h>
57bccc5538Smpi 
58cc150176Smpi #ifdef OPENPIC_DEBUG
59cc150176Smpi #define DPRINTF(x...)	do { printf(x); } while(0)
60cc150176Smpi #else
61cc150176Smpi #define DPRINTF(x...)
62cc150176Smpi #endif
63cc150176Smpi 
64d9a5f17fSdrahn #define ICU_LEN 128
65d7469fedSdrahn int openpic_numirq = ICU_LEN;
66d9a5f17fSdrahn #define LEGAL_IRQ(x) ((x >= 0) && (x < ICU_LEN))
67d9a5f17fSdrahn 
68d7469fedSdrahn int openpic_pri_share[IPL_NUM];
69d9a5f17fSdrahn 
70d7469fedSdrahn struct intrq openpic_handler[ICU_LEN];
71d7469fedSdrahn 
72d9a5f17fSdrahn struct openpic_softc {
73d9a5f17fSdrahn 	struct device sc_dev;
74d9a5f17fSdrahn };
75d9a5f17fSdrahn 
76cc150176Smpi vaddr_t openpic_base;
77cc150176Smpi int	openpic_big_endian;
78cc150176Smpi struct	evcount openpic_spurious;
79cc150176Smpi int	openpic_spurious_irq = 255;
80cc150176Smpi 
81c4071fd1Smillert int	openpic_match(struct device *parent, void *cf, void *aux);
82c4071fd1Smillert void	openpic_attach(struct device *, struct device *, void *);
83cc150176Smpi 
84cc150176Smpi int	openpic_splraise(int);
85cc150176Smpi int	openpic_spllower(int);
86cc150176Smpi void	openpic_splx(int);
87cc150176Smpi 
88cc150176Smpi u_int	openpic_read(int reg);
89cc150176Smpi void	openpic_write(int reg, u_int val);
90ba99a0edSmpi 
91ba99a0edSmpi void	openpic_acknowledge_irq(int, int);
92ba99a0edSmpi void	openpic_enable_irq(int, int, int);
93ba99a0edSmpi void	openpic_disable_irq(int, int);
94ba99a0edSmpi 
95cc150176Smpi void	openpic_calc_mask(void);
96cc150176Smpi void	openpic_set_priority(int, int);
97cc150176Smpi void	*openpic_intr_establish(void *, int, int, int, int (*)(void *), void *,
98cc150176Smpi 	    const char *);
99ba99a0edSmpi void	openpic_intr_disestablish(void *, void *);
100c4071fd1Smillert void	openpic_collect_preconf_intr(void);
101d7469fedSdrahn void	openpic_ext_intr(void);
1027bf9d514Smpi int	openpic_ext_intr_handler(struct intrhand *, int *);
103d9a5f17fSdrahn 
104ba99a0edSmpi /* Generic IRQ management routines. */
105ba99a0edSmpi void	openpic_gen_acknowledge_irq(int, int);
106ba99a0edSmpi void	openpic_gen_enable_irq(int, int, int);
107ba99a0edSmpi void	openpic_gen_disable_irq(int, int);
108ba99a0edSmpi 
109ba99a0edSmpi #if NHPB > 0
110ba99a0edSmpi /* CPC945 IRQ management routines. */
111ba99a0edSmpi void	openpic_cpc945_acknowledge_irq(int, int);
112ba99a0edSmpi void	openpic_cpc945_enable_irq(int, int, int);
113ba99a0edSmpi void	openpic_cpc945_disable_irq(int, int);
114ba99a0edSmpi #endif /* NHPB */
115ba99a0edSmpi 
116ba99a0edSmpi struct openpic_ops {
117ba99a0edSmpi 	void	(*acknowledge_irq)(int, int);
118ba99a0edSmpi 	void	(*enable_irq)(int, int, int);
119ba99a0edSmpi 	void	(*disable_irq)(int, int);
120ba99a0edSmpi } openpic_ops = {
121ba99a0edSmpi 	openpic_gen_acknowledge_irq,
122ba99a0edSmpi 	openpic_gen_enable_irq,
123ba99a0edSmpi 	openpic_gen_disable_irq
124ba99a0edSmpi };
125ba99a0edSmpi 
126cc150176Smpi #ifdef MULTIPROCESSOR
127cc150176Smpi void	openpic_ipi_ddb(void);
128cc150176Smpi 
129cc150176Smpi /* IRQ vector used for inter-processor interrupts. */
130cc150176Smpi #define IPI_VECTOR_NOP	64
131cc150176Smpi #define IPI_VECTOR_DDB	65
132cc150176Smpi 
133da646a34Smpi static struct evcount ipi_count;
134cc150176Smpi 
135da646a34Smpi static int ipi_irq = IPI_VECTOR_NOP;
136cc150176Smpi 
137cc150176Smpi intr_send_ipi_t openpic_send_ipi;
138cc150176Smpi #endif /* MULTIPROCESSOR */
139cc150176Smpi 
140cc150176Smpi const struct cfattach openpic_ca = {
141cc150176Smpi 	sizeof(struct openpic_softc), openpic_match, openpic_attach
142d9a5f17fSdrahn };
143d9a5f17fSdrahn 
144d9a5f17fSdrahn struct cfdriver openpic_cd = {
145d9a5f17fSdrahn 	NULL, "openpic", DV_DULL
146d9a5f17fSdrahn };
147d9a5f17fSdrahn 
148d7469fedSdrahn u_int
openpic_read(int reg)149d7469fedSdrahn openpic_read(int reg)
150d7469fedSdrahn {
151d7469fedSdrahn 	char *addr = (void *)(openpic_base + reg);
152d7469fedSdrahn 
153ba99a0edSmpi 	membar_sync();
154d7469fedSdrahn 	if (openpic_big_endian)
155d7469fedSdrahn 		return in32(addr);
156d7469fedSdrahn 	else
157d7469fedSdrahn 		return in32rb(addr);
158d7469fedSdrahn }
159d7469fedSdrahn 
160d7469fedSdrahn void
openpic_write(int reg,u_int val)161d7469fedSdrahn openpic_write(int reg, u_int val)
162d7469fedSdrahn {
163d7469fedSdrahn 	char *addr = (void *)(openpic_base + reg);
164d7469fedSdrahn 
165d7469fedSdrahn 	if (openpic_big_endian)
166d7469fedSdrahn 		out32(addr, val);
167d7469fedSdrahn 	else
168d7469fedSdrahn 		out32rb(addr, val);
169ba99a0edSmpi 	membar_sync();
170d7469fedSdrahn }
171d7469fedSdrahn 
172d7469fedSdrahn static inline int
openpic_read_irq(int cpu)173d7469fedSdrahn openpic_read_irq(int cpu)
174d7469fedSdrahn {
175d7469fedSdrahn 	return openpic_read(OPENPIC_IACK(cpu)) & OPENPIC_VECTOR_MASK;
176d7469fedSdrahn }
177d7469fedSdrahn 
178d7469fedSdrahn static inline void
openpic_eoi(int cpu)179d7469fedSdrahn openpic_eoi(int cpu)
180d7469fedSdrahn {
181d7469fedSdrahn 	openpic_write(OPENPIC_EOI(cpu), 0);
182d7469fedSdrahn }
183d7469fedSdrahn 
184d9a5f17fSdrahn int
openpic_match(struct device * parent,void * cf,void * aux)185093da1aaSdrahn openpic_match(struct device *parent, void *cf, void *aux)
186d9a5f17fSdrahn {
187d9a5f17fSdrahn 	char type[40];
188eb32ac1fSdrahn 	int pirq;
189d9a5f17fSdrahn 	struct confargs *ca = aux;
190d9a5f17fSdrahn 
191d9a5f17fSdrahn 	bzero (type, sizeof(type));
192d9a5f17fSdrahn 
193eb32ac1fSdrahn 	if (OF_getprop(ca->ca_node, "interrupt-parent", &pirq, sizeof(pirq))
194eb32ac1fSdrahn 	    == sizeof(pirq))
195eb32ac1fSdrahn 		return 0; /* XXX */
196eb32ac1fSdrahn 
19784b94647Smiod 	if (strcmp(ca->ca_name, "interrupt-controller") != 0 &&
19884b94647Smiod 	    strcmp(ca->ca_name, "mpic") != 0)
199d9a5f17fSdrahn 		return 0;
20084b94647Smiod 
20184b94647Smiod 	OF_getprop(ca->ca_node, "device_type", type, sizeof(type));
20284b94647Smiod 	if (strcmp(type, "open-pic") != 0)
20384b94647Smiod 		return 0;
20484b94647Smiod 
20584b94647Smiod 	if (ca->ca_nreg < 8)
20684b94647Smiod 		return 0;
20784b94647Smiod 
20884b94647Smiod 	return 1;
209d9a5f17fSdrahn }
210d9a5f17fSdrahn 
211d9a5f17fSdrahn void
openpic_attach(struct device * parent,struct device * self,void * aux)212093da1aaSdrahn openpic_attach(struct device *parent, struct device *self, void *aux)
213d9a5f17fSdrahn {
214d7469fedSdrahn 	struct cpu_info *ci = curcpu();
215d9a5f17fSdrahn 	struct confargs *ca = aux;
216af5ae5b8Smpi 	struct intrq *iq;
217af5ae5b8Smpi 	uint32_t reg = 0;
218af5ae5b8Smpi 	int i, irq;
219af5ae5b8Smpi 	u_int x;
2206a034491Sdrahn 
2216a034491Sdrahn 	if (OF_getprop(ca->ca_node, "big-endian", &reg, sizeof reg) == 0)
2226a034491Sdrahn 		openpic_big_endian = 1;
223d9a5f17fSdrahn 
224d9a5f17fSdrahn 	openpic_base = (vaddr_t) mapiodev (ca->ca_baseaddr +
225eb32ac1fSdrahn 			ca->ca_reg[0], 0x40000);
226d9a5f17fSdrahn 
227ba99a0edSmpi 	/* Reset the PIC */
228ba99a0edSmpi 	x = openpic_read(OPENPIC_CONFIG) | OPENPIC_CONFIG_RESET;
229ba99a0edSmpi 	openpic_write(OPENPIC_CONFIG, x);
230ba99a0edSmpi 
231ba99a0edSmpi 	while (openpic_read(OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET)
232ba99a0edSmpi 		delay(100);
233ba99a0edSmpi 
23436fd90dcSjsg 	/* openpic may support more than 128 interrupts but driver doesn't */
235d7469fedSdrahn 	openpic_numirq = ((openpic_read(OPENPIC_FEATURE) >> 16) & 0x7f)+1;
236d7469fedSdrahn 
237d7469fedSdrahn 	printf(": version 0x%x feature %x %s",
238d7469fedSdrahn 	    openpic_read(OPENPIC_VENDOR_ID),
239d7469fedSdrahn 	    openpic_read(OPENPIC_FEATURE),
240d7469fedSdrahn 		openpic_big_endian ? "BE" : "LE" );
241d9a5f17fSdrahn 
242af5ae5b8Smpi 	openpic_set_priority(ci->ci_cpuid, 15);
243af5ae5b8Smpi 
244af5ae5b8Smpi 	/* disable all interrupts */
245af5ae5b8Smpi 	for (irq = 0; irq < openpic_numirq; irq++)
246af5ae5b8Smpi 		openpic_write(OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
247af5ae5b8Smpi 
248af5ae5b8Smpi 	for (i = 0; i < openpic_numirq; i++) {
249af5ae5b8Smpi 		iq = &openpic_handler[i];
250af5ae5b8Smpi 		TAILQ_INIT(&iq->iq_list);
251af5ae5b8Smpi 	}
252af5ae5b8Smpi 
253af5ae5b8Smpi 	/* we don't need 8259 pass through mode */
254af5ae5b8Smpi 	x = openpic_read(OPENPIC_CONFIG);
255af5ae5b8Smpi 	x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE;
256af5ae5b8Smpi 	openpic_write(OPENPIC_CONFIG, x);
257af5ae5b8Smpi 
258af5ae5b8Smpi 	/* initialize all vectors to something sane */
259af5ae5b8Smpi 	for (irq = 0; irq < ICU_LEN; irq++) {
260af5ae5b8Smpi 		x = irq;
261af5ae5b8Smpi 		x |= OPENPIC_IMASK;
262af5ae5b8Smpi 		x |= OPENPIC_POLARITY_NEGATIVE;
263af5ae5b8Smpi 		x |= OPENPIC_SENSE_LEVEL;
264af5ae5b8Smpi 		x |= 8 << OPENPIC_PRIORITY_SHIFT;
265af5ae5b8Smpi 		openpic_write(OPENPIC_SRC_VECTOR(irq), x);
266af5ae5b8Smpi 	}
267af5ae5b8Smpi 
268af5ae5b8Smpi 	/* send all interrupts to cpu 0 */
269af5ae5b8Smpi 	for (irq = 0; irq < openpic_numirq; irq++)
270af5ae5b8Smpi 		openpic_write(OPENPIC_IDEST(irq), 1 << 0);
271af5ae5b8Smpi 
272d744f4d2Sjsg 	/* clear all pending interrupts */
273af5ae5b8Smpi 	for (irq = 0; irq < ICU_LEN; irq++) {
274af5ae5b8Smpi 		openpic_read_irq(ci->ci_cpuid);
275af5ae5b8Smpi 		openpic_eoi(ci->ci_cpuid);
276af5ae5b8Smpi 	}
277af5ae5b8Smpi 
278af5ae5b8Smpi #ifdef MULTIPROCESSOR
279af5ae5b8Smpi 	/* Set up inter-processor interrupts. */
280af5ae5b8Smpi 	/* IPI0 - NOP */
281af5ae5b8Smpi 	x = IPI_VECTOR_NOP;
282af5ae5b8Smpi 	x |= 15 << OPENPIC_PRIORITY_SHIFT;
283af5ae5b8Smpi 	openpic_write(OPENPIC_IPI_VECTOR(0), x);
284af5ae5b8Smpi 	/* IPI1 - DDB */
285af5ae5b8Smpi 	x = IPI_VECTOR_DDB;
286af5ae5b8Smpi 	x |= 15 << OPENPIC_PRIORITY_SHIFT;
287af5ae5b8Smpi 	openpic_write(OPENPIC_IPI_VECTOR(1), x);
288af5ae5b8Smpi 
289da646a34Smpi 	evcount_attach(&ipi_count, "ipi", &ipi_irq);
290af5ae5b8Smpi #endif
291af5ae5b8Smpi 
292d744f4d2Sjsg 	/* clear all pending interrupts */
293af5ae5b8Smpi 	for (irq = 0; irq < ICU_LEN; irq++) {
294af5ae5b8Smpi 		openpic_read_irq(0);
295af5ae5b8Smpi 		openpic_eoi(0);
296af5ae5b8Smpi 	}
297af5ae5b8Smpi 
298af5ae5b8Smpi #if 0
299af5ae5b8Smpi 	openpic_write(OPENPIC_SPURIOUS_VECTOR, 255);
300af5ae5b8Smpi #endif
301af5ae5b8Smpi 
302ba99a0edSmpi #if NHPB > 0
303ba99a0edSmpi 	/* Only U4 systems have a big-endian MPIC. */
304ba99a0edSmpi 	if (openpic_big_endian) {
305ba99a0edSmpi 		openpic_ops.acknowledge_irq = openpic_cpc945_acknowledge_irq;
306ba99a0edSmpi 		openpic_ops.enable_irq = openpic_cpc945_enable_irq;
307ba99a0edSmpi 		openpic_ops.disable_irq = openpic_cpc945_disable_irq;
308ba99a0edSmpi 	}
309ba99a0edSmpi #endif
310ba99a0edSmpi 
311af5ae5b8Smpi 	install_extint(openpic_ext_intr);
312af5ae5b8Smpi 
313af5ae5b8Smpi 	openpic_set_priority(ci->ci_cpuid, 0);
314d9a5f17fSdrahn 
315d9a5f17fSdrahn 	intr_establish_func  = openpic_intr_establish;
316d9a5f17fSdrahn 	intr_disestablish_func = openpic_intr_disestablish;
3178d4cccd1Sdrahn #ifdef MULTIPROCESSOR
3188d4cccd1Sdrahn 	intr_send_ipi_func = openpic_send_ipi;
3198d4cccd1Sdrahn #endif
320d9a5f17fSdrahn 
321d7469fedSdrahn 	ppc_smask_init();
322d7469fedSdrahn 
323d9a5f17fSdrahn 	openpic_collect_preconf_intr();
324d7469fedSdrahn 
325d7469fedSdrahn 	evcount_attach(&openpic_spurious, "spurious", &openpic_spurious_irq);
326d7469fedSdrahn 
327d7469fedSdrahn 	ppc_intr_func.raise = openpic_splraise;
328d7469fedSdrahn 	ppc_intr_func.lower = openpic_spllower;
329d7469fedSdrahn 	ppc_intr_func.x = openpic_splx;
330d7469fedSdrahn 
331d7469fedSdrahn 	openpic_set_priority(0, ci->ci_cpl);
332d9a5f17fSdrahn 
333d9a5f17fSdrahn 	ppc_intr_enable(1);
334d9a5f17fSdrahn 
335d9a5f17fSdrahn 	printf("\n");
336d9a5f17fSdrahn }
337d9a5f17fSdrahn 
3381c471f42Smpi /* Must be called with interrupt disable. */
339d7469fedSdrahn static inline void
openpic_setipl(int newcpl)340d7469fedSdrahn openpic_setipl(int newcpl)
341d7469fedSdrahn {
342d7469fedSdrahn 	struct cpu_info *ci = curcpu();
3431c471f42Smpi 
344d7469fedSdrahn 	ci->ci_cpl = newcpl;
345d7469fedSdrahn 	openpic_set_priority(ci->ci_cpuid, newcpl);
346d7469fedSdrahn }
347de98894eSjasper 
348d7469fedSdrahn int
openpic_splraise(int newcpl)349d7469fedSdrahn openpic_splraise(int newcpl)
350d7469fedSdrahn {
351d7469fedSdrahn 	struct cpu_info *ci = curcpu();
352d7469fedSdrahn 	int ocpl = ci->ci_cpl;
3531c471f42Smpi 	int s;
3541c471f42Smpi 
3551c471f42Smpi 	newcpl = openpic_pri_share[newcpl];
356d7469fedSdrahn 	if (ocpl > newcpl)
357d7469fedSdrahn 		newcpl = ocpl;
358d7469fedSdrahn 
3591c471f42Smpi 	s = ppc_intr_disable();
360d7469fedSdrahn 	openpic_setipl(newcpl);
3611c471f42Smpi 	ppc_intr_enable(s);
362d7469fedSdrahn 
363d7469fedSdrahn 	return ocpl;
364d7469fedSdrahn }
365d7469fedSdrahn 
366d7469fedSdrahn int
openpic_spllower(int newcpl)367d7469fedSdrahn openpic_spllower(int newcpl)
368d7469fedSdrahn {
369d7469fedSdrahn 	struct cpu_info *ci = curcpu();
370d7469fedSdrahn 	int ocpl = ci->ci_cpl;
371d7469fedSdrahn 
372d7469fedSdrahn 	openpic_splx(newcpl);
373d7469fedSdrahn 
374d7469fedSdrahn 	return ocpl;
375d7469fedSdrahn }
376d7469fedSdrahn 
377d7469fedSdrahn void
openpic_splx(int newcpl)378d7469fedSdrahn openpic_splx(int newcpl)
379d7469fedSdrahn {
3801c471f42Smpi 	struct cpu_info *ci = curcpu();
3811c471f42Smpi 	int intr, s;
3821c471f42Smpi 
3831c471f42Smpi 	intr = ppc_intr_disable();
3841c471f42Smpi 	openpic_setipl(newcpl);
385*de052479Scheloha 	if (ci->ci_dec_deferred && newcpl < IPL_CLOCK) {
386*de052479Scheloha 		ppc_mtdec(0);
387*de052479Scheloha 		ppc_mtdec(UINT32_MAX);	/* raise DEC exception */
388*de052479Scheloha 	}
3891c471f42Smpi 	if (newcpl < IPL_SOFTTTY && (ci->ci_ipending & ppc_smask[newcpl])) {
3901c471f42Smpi 		s = splsofttty();
3911c471f42Smpi 		dosoftint(newcpl);
3921c471f42Smpi 		openpic_setipl(s); /* no-overhead splx */
3931c471f42Smpi 	}
3941c471f42Smpi 	ppc_intr_enable(intr);
395d7469fedSdrahn }
396de98894eSjasper 
397d9a5f17fSdrahn void
openpic_collect_preconf_intr(void)398af7e7ea9Sderaadt openpic_collect_preconf_intr(void)
399d9a5f17fSdrahn {
400d9a5f17fSdrahn 	int i;
401d9a5f17fSdrahn 	for (i = 0; i < ppc_configed_intr_cnt; i++) {
402cc150176Smpi 		DPRINTF("\n\t%s irq %d level %d fun %p arg %p",
403d9a5f17fSdrahn 		    ppc_configed_intr[i].ih_what, ppc_configed_intr[i].ih_irq,
404d9a5f17fSdrahn 		    ppc_configed_intr[i].ih_level, ppc_configed_intr[i].ih_fun,
405d9a5f17fSdrahn 		    ppc_configed_intr[i].ih_arg);
406d9a5f17fSdrahn 		openpic_intr_establish(NULL, ppc_configed_intr[i].ih_irq,
407d9a5f17fSdrahn 		    IST_LEVEL, ppc_configed_intr[i].ih_level,
408d9a5f17fSdrahn 		    ppc_configed_intr[i].ih_fun, ppc_configed_intr[i].ih_arg,
409d9a5f17fSdrahn 		    ppc_configed_intr[i].ih_what);
410d9a5f17fSdrahn 	}
411d9a5f17fSdrahn }
412d9a5f17fSdrahn 
413d9a5f17fSdrahn /*
414d9a5f17fSdrahn  * Register an interrupt handler.
415d9a5f17fSdrahn  */
416d9a5f17fSdrahn void *
openpic_intr_establish(void * lcv,int irq,int type,int level,int (* ih_fun)(void *),void * ih_arg,const char * name)417093da1aaSdrahn openpic_intr_establish(void *lcv, int irq, int type, int level,
418c03b1b92Smk     int (*ih_fun)(void *), void *ih_arg, const char *name)
419d9a5f17fSdrahn {
420d7469fedSdrahn 	struct intrhand *ih;
421d7469fedSdrahn 	struct intrq *iq;
422bb536b7dSmpi 	int s, flags;
423d9a5f17fSdrahn 
424f0144ea9Smpi 	if (!LEGAL_IRQ(irq) || type == IST_NONE) {
425f0144ea9Smpi 		printf("%s: bogus irq %d or type %d", __func__, irq, type);
426f0144ea9Smpi 		return (NULL);
427f0144ea9Smpi 	}
428f0144ea9Smpi 
429d9a5f17fSdrahn 	/* no point in sleeping unless someone can free memory. */
430d9a5f17fSdrahn 	ih = malloc(sizeof *ih, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
431d9a5f17fSdrahn 	if (ih == NULL)
432f0144ea9Smpi 		panic("%s: can't malloc handler info", __func__);
433d9a5f17fSdrahn 
434bb536b7dSmpi 	iq = &openpic_handler[irq];
435d7469fedSdrahn 	switch (iq->iq_ist) {
436d9a5f17fSdrahn 	case IST_NONE:
437d7469fedSdrahn 		iq->iq_ist = type;
438d9a5f17fSdrahn 		break;
439d9a5f17fSdrahn 	case IST_EDGE:
4402edcc96aSderaadt 		intr_shared_edge = 1;
4412edcc96aSderaadt 		/* FALLTHROUGH */
442d9a5f17fSdrahn 	case IST_LEVEL:
443d7469fedSdrahn 		if (type == iq->iq_ist)
444d9a5f17fSdrahn 			break;
445d9a5f17fSdrahn 	case IST_PULSE:
446d9a5f17fSdrahn 		if (type != IST_NONE)
447d9a5f17fSdrahn 			panic("intr_establish: can't share %s with %s",
448d7469fedSdrahn 			    ppc_intr_typename(iq->iq_ist),
449d7469fedSdrahn 			    ppc_intr_typename(type));
450d9a5f17fSdrahn 		break;
451d9a5f17fSdrahn 	}
452d9a5f17fSdrahn 
453bb536b7dSmpi 	flags = level & IPL_MPSAFE;
454bb536b7dSmpi 	level &= ~IPL_MPSAFE;
455bb536b7dSmpi 
456bb536b7dSmpi 	KASSERT(level <= IPL_TTY || level >= IPL_CLOCK || flags & IPL_MPSAFE);
457bb536b7dSmpi 
4585e058f67Sderaadt 	ih->ih_fun = ih_fun;
4595e058f67Sderaadt 	ih->ih_arg = ih_arg;
4605e058f67Sderaadt 	ih->ih_level = level;
461bb536b7dSmpi 	ih->ih_flags = flags;
4625e058f67Sderaadt 	ih->ih_irq = irq;
463d7469fedSdrahn 
464d7469fedSdrahn 	evcount_attach(&ih->ih_count, name, &ih->ih_irq);
465d7469fedSdrahn 
466d7469fedSdrahn 	/*
467d7469fedSdrahn 	 * Append handler to end of list
468d7469fedSdrahn 	 */
469d7469fedSdrahn 	s = ppc_intr_disable();
470d7469fedSdrahn 
471d7469fedSdrahn 	TAILQ_INSERT_TAIL(&iq->iq_list, ih, ih_list);
472d7469fedSdrahn 	openpic_calc_mask();
473d7469fedSdrahn 
474d7469fedSdrahn 	ppc_intr_enable(s);
475d9a5f17fSdrahn 
476d9a5f17fSdrahn 	return (ih);
477d9a5f17fSdrahn }
478d9a5f17fSdrahn 
479d9a5f17fSdrahn /*
480d9a5f17fSdrahn  * Deregister an interrupt handler.
481d9a5f17fSdrahn  */
482d9a5f17fSdrahn void
openpic_intr_disestablish(void * lcp,void * arg)483093da1aaSdrahn openpic_intr_disestablish(void *lcp, void *arg)
484d9a5f17fSdrahn {
485d9a5f17fSdrahn 	struct intrhand *ih = arg;
486d9a5f17fSdrahn 	int irq = ih->ih_irq;
487fc5790baSjsg 	struct intrq *iq;
488d7469fedSdrahn 	int s;
489d9a5f17fSdrahn 
490f0144ea9Smpi 	if (!LEGAL_IRQ(irq)) {
491f0144ea9Smpi 		printf("%s: bogus irq %d", __func__, irq);
492f0144ea9Smpi 		return;
493f0144ea9Smpi 	}
494fc5790baSjsg 	iq = &openpic_handler[irq];
495d9a5f17fSdrahn 
496d9a5f17fSdrahn 	/*
497d9a5f17fSdrahn 	 * Remove the handler from the chain.
498d9a5f17fSdrahn 	 */
499d7469fedSdrahn 	s = ppc_intr_disable();
500d7469fedSdrahn 
501d7469fedSdrahn 	TAILQ_REMOVE(&iq->iq_list, ih, ih_list);
502d7469fedSdrahn 	openpic_calc_mask();
503d7469fedSdrahn 
504d7469fedSdrahn 	ppc_intr_enable(s);
505a4867f13Saaron 
506a4867f13Saaron 	evcount_detach(&ih->ih_count);
50758d5cf8aSderaadt 	free(ih, M_DEVBUF, sizeof *ih);
508d9a5f17fSdrahn 
509d7469fedSdrahn 	if (TAILQ_EMPTY(&iq->iq_list))
510d7469fedSdrahn 		iq->iq_ist = IST_NONE;
511d9a5f17fSdrahn }
512d9a5f17fSdrahn 
513d9a5f17fSdrahn /*
514d9a5f17fSdrahn  * Recalculate the interrupt masks from scratch.
515d9a5f17fSdrahn  * We could code special registry and deregistry versions of this function that
516d9a5f17fSdrahn  * would be faster, but the code would be nastier, and we don't expect this to
517d9a5f17fSdrahn  * happen very much anyway.
518d9a5f17fSdrahn  */
519548be99eSdrahn 
520548be99eSdrahn void
openpic_calc_mask(void)521af7e7ea9Sderaadt openpic_calc_mask(void)
522d9a5f17fSdrahn {
523d7469fedSdrahn 	struct cpu_info *ci = curcpu();
524548be99eSdrahn 	int irq;
525548be99eSdrahn 	struct intrhand *ih;
526548be99eSdrahn 	int i;
527d3fed0b3Sdrahn 
528d3fed0b3Sdrahn 	/* disable all openpic interrupts */
529d7469fedSdrahn 	openpic_set_priority(ci->ci_cpuid, 15);
530d9a5f17fSdrahn 
531d7469fedSdrahn 	for (i = IPL_NONE; i < IPL_NUM; i++) {
532d7469fedSdrahn 		openpic_pri_share[i] = i;
533d9a5f17fSdrahn 	}
534d9a5f17fSdrahn 
535d7469fedSdrahn 	for (irq = 0; irq < openpic_numirq; irq++) {
536d7469fedSdrahn 		int maxipl = IPL_NONE;
537d7469fedSdrahn 		int minipl = IPL_HIGH;
538d7469fedSdrahn 		struct intrq *iq = &openpic_handler[irq];
539548be99eSdrahn 
540d7469fedSdrahn 		TAILQ_FOREACH(ih, &iq->iq_list, ih_list) {
541d7469fedSdrahn 			if (ih->ih_level > maxipl)
542d7469fedSdrahn 				maxipl = ih->ih_level;
543d7469fedSdrahn 			if (ih->ih_level < minipl)
544d7469fedSdrahn 				minipl = ih->ih_level;
545d3fed0b3Sdrahn 		}
546d3fed0b3Sdrahn 
547d7469fedSdrahn 		if (maxipl == IPL_NONE) {
548d7469fedSdrahn 			minipl = IPL_NONE; /* Interrupt not enabled */
549548be99eSdrahn 
550ba99a0edSmpi 			openpic_disable_irq(irq, iq->iq_ist);
551d7469fedSdrahn 		} else {
552d7469fedSdrahn 			for (i = minipl; i <= maxipl; i++) {
553d7469fedSdrahn 				openpic_pri_share[i] = maxipl;
554d9a5f17fSdrahn 			}
555ba99a0edSmpi 			openpic_enable_irq(irq, iq->iq_ist, maxipl);
556d7469fedSdrahn 		}
557d7469fedSdrahn 
558d7469fedSdrahn 		iq->iq_ipl = maxipl;
559548be99eSdrahn 	}
560d3fed0b3Sdrahn 
561d3fed0b3Sdrahn 	/* restore interrupts */
562d7469fedSdrahn 	openpic_set_priority(ci->ci_cpuid, ci->ci_cpl);
563747d31e5Sderaadt }
5645e058f67Sderaadt 
565d9a5f17fSdrahn void
openpic_gen_acknowledge_irq(int irq,int cpuid)566ba99a0edSmpi openpic_gen_acknowledge_irq(int irq, int cpuid)
567ba99a0edSmpi {
568ba99a0edSmpi 	openpic_eoi(cpuid);
569ba99a0edSmpi }
570ba99a0edSmpi 
571ba99a0edSmpi void
openpic_gen_enable_irq(int irq,int ist,int pri)572ba99a0edSmpi openpic_gen_enable_irq(int irq, int ist, int pri)
573d9a5f17fSdrahn {
574d9a5f17fSdrahn 	u_int x;
575d9a5f17fSdrahn 
576d7469fedSdrahn 	x = irq;
577ba99a0edSmpi 
578ba99a0edSmpi 	if (ist == IST_LEVEL)
579d9a5f17fSdrahn 		x |= OPENPIC_SENSE_LEVEL;
580093da1aaSdrahn 	else
581d9a5f17fSdrahn 		x |= OPENPIC_SENSE_EDGE;
582d7469fedSdrahn 	x |= OPENPIC_POLARITY_NEGATIVE;
583d7469fedSdrahn 	x |= pri << OPENPIC_PRIORITY_SHIFT;
5841f58a4a3Sdrahn 	openpic_write(OPENPIC_SRC_VECTOR(irq), x);
5851f58a4a3Sdrahn }
586d9a5f17fSdrahn 
587d9a5f17fSdrahn void
openpic_gen_disable_irq(int irq,int ist)588ba99a0edSmpi openpic_gen_disable_irq(int irq, int ist)
589d9a5f17fSdrahn {
590d9a5f17fSdrahn 	u_int x;
591d9a5f17fSdrahn 
592d9a5f17fSdrahn 	x = openpic_read(OPENPIC_SRC_VECTOR(irq));
593d9a5f17fSdrahn 	x |= OPENPIC_IMASK;
594d9a5f17fSdrahn 	openpic_write(OPENPIC_SRC_VECTOR(irq), x);
595d9a5f17fSdrahn }
596d9a5f17fSdrahn 
597d9a5f17fSdrahn void
openpic_set_priority(int cpu,int pri)5985e058f67Sderaadt openpic_set_priority(int cpu, int pri)
599d9a5f17fSdrahn {
600d7469fedSdrahn 	openpic_write(OPENPIC_CPU_PRIORITY(cpu), pri);
601d9a5f17fSdrahn }
602d9a5f17fSdrahn 
603d7469fedSdrahn int openpic_irqnest[PPC_MAXPROCS];
604d7469fedSdrahn int openpic_irqloop[PPC_MAXPROCS];
605ba99a0edSmpi 
606d9a5f17fSdrahn void
openpic_ext_intr(void)607ba99a0edSmpi openpic_ext_intr(void)
608d9a5f17fSdrahn {
6099e61e18aSkettenis 	struct cpu_info *ci = curcpu();
610d7469fedSdrahn 	int irq, pcpl, ret;
611d7469fedSdrahn 	int maxipl = IPL_NONE;
612d9a5f17fSdrahn 	struct intrhand *ih;
613d7469fedSdrahn 	struct intrq *iq;
614d7469fedSdrahn 	int spurious;
615d9a5f17fSdrahn 
6169e61e18aSkettenis 	pcpl = ci->ci_cpl;
617d9a5f17fSdrahn 
618d7469fedSdrahn 	openpic_irqloop[ci->ci_cpuid] = 0;
619d7469fedSdrahn 	irq = openpic_read_irq(ci->ci_cpuid);
620d7469fedSdrahn 	openpic_irqnest[ci->ci_cpuid]++;
621d9a5f17fSdrahn 
622d7469fedSdrahn 	while (irq != 255) {
623d7469fedSdrahn 		openpic_irqloop[ci->ci_cpuid]++;
624cc150176Smpi #ifdef OPENPIC_DEBUG
625d7469fedSdrahn 		if (openpic_irqloop[ci->ci_cpuid] > 20 ||
626d7469fedSdrahn 		    openpic_irqnest[ci->ci_cpuid] > 3) {
627d7469fedSdrahn 			printf("irqloop %d irqnest %d\n",
628d7469fedSdrahn 			    openpic_irqloop[ci->ci_cpuid],
629d7469fedSdrahn 			    openpic_irqnest[ci->ci_cpuid]);
630d7469fedSdrahn 		}
6319aecfc33Sderaadt #endif
63231855013Sdrahn 		if (openpic_irqloop[ci->ci_cpuid] > 20) {
633cc150176Smpi 			DPRINTF("irqloop %d irqnest %d: returning\n",
63431855013Sdrahn 			    openpic_irqloop[ci->ci_cpuid],
63531855013Sdrahn 			    openpic_irqnest[ci->ci_cpuid]);
63631855013Sdrahn 			openpic_irqnest[ci->ci_cpuid]--;
63731855013Sdrahn 			return;
63831855013Sdrahn 		}
6391c49a0a6Skettenis #ifdef MULTIPROCESSOR
640da646a34Smpi 		if (irq == IPI_VECTOR_NOP || irq == IPI_VECTOR_DDB) {
641da646a34Smpi 			ipi_count.ec_count++;
6421c49a0a6Skettenis 			openpic_eoi(ci->ci_cpuid);
643da646a34Smpi 			if (irq == IPI_VECTOR_DDB)
6448d4cccd1Sdrahn 				openpic_ipi_ddb();
645d7469fedSdrahn 			irq = openpic_read_irq(ci->ci_cpuid);
6468d4cccd1Sdrahn 			continue;
6478d4cccd1Sdrahn 		}
6481c49a0a6Skettenis #endif
649d7469fedSdrahn 		iq = &openpic_handler[irq];
6501c49a0a6Skettenis 
651bb536b7dSmpi #ifdef OPENPIC_DEBUG
652bb536b7dSmpi 		if (iq->iq_ipl <= pcpl)
653d7469fedSdrahn 			printf("invalid interrupt %d lvl %d at %d hw %d\n",
654bb536b7dSmpi 			    irq, iq->iq_ipl, pcpl,
655d7469fedSdrahn 			    openpic_read(OPENPIC_CPU_PRIORITY(ci->ci_cpuid)));
656bb536b7dSmpi #endif
657bb536b7dSmpi 
658d7469fedSdrahn 		if (iq->iq_ipl > maxipl)
659d7469fedSdrahn 			maxipl = iq->iq_ipl;
6601c471f42Smpi 		openpic_splraise(iq->iq_ipl);
661ba99a0edSmpi 		openpic_acknowledge_irq(irq, ci->ci_cpuid);
662f8e13b6fSdrahn 
663d7469fedSdrahn 		spurious = 1;
664d7469fedSdrahn 		TAILQ_FOREACH(ih, &iq->iq_list, ih_list) {
6651f58a4a3Sdrahn 			ppc_intr_enable(1);
6667bf9d514Smpi 			ret = openpic_ext_intr_handler(ih, &spurious);
6671f58a4a3Sdrahn 			(void)ppc_intr_disable();
6682edcc96aSderaadt 			if (intr_shared_edge == 00 && ret == 1)
6692edcc96aSderaadt 				break;
670d7469fedSdrahn  		}
671d7469fedSdrahn 		if (spurious) {
672d7469fedSdrahn 			openpic_spurious.ec_count++;
673cc150176Smpi 			DPRINTF("spurious intr %d\n", irq);
674d9a5f17fSdrahn 		}
675d9a5f17fSdrahn 
676d9a5f17fSdrahn 		uvmexp.intrs++;
677d7469fedSdrahn 		openpic_setipl(pcpl);
678d7469fedSdrahn 
679d7469fedSdrahn 		irq = openpic_read_irq(ci->ci_cpuid);
680d9a5f17fSdrahn 	}
681747d31e5Sderaadt 
6821c471f42Smpi 	openpic_splx(pcpl);	/* Process pendings. */
683d7469fedSdrahn 	openpic_irqnest[ci->ci_cpuid]--;
684d9a5f17fSdrahn }
685b3f09b5bSkettenis 
686bb536b7dSmpi int
openpic_ext_intr_handler(struct intrhand * ih,int * spurious)6877bf9d514Smpi openpic_ext_intr_handler(struct intrhand *ih, int *spurious)
688bb536b7dSmpi {
689bb536b7dSmpi 	int ret;
690bb536b7dSmpi #ifdef MULTIPROCESSOR
691bb536b7dSmpi 	int need_lock;
692bb536b7dSmpi 
693bb536b7dSmpi 	if (ih->ih_flags & IPL_MPSAFE)
694bb536b7dSmpi 		need_lock = 0;
695bb536b7dSmpi 	else
6967bf9d514Smpi 		need_lock = 1;
697bb536b7dSmpi 
698bb536b7dSmpi 	if (need_lock)
699bb536b7dSmpi 		KERNEL_LOCK();
700bb536b7dSmpi #endif
701bb536b7dSmpi 	ret = (*ih->ih_fun)(ih->ih_arg);
702bb536b7dSmpi 	if (ret) {
703bb536b7dSmpi 		ih->ih_count.ec_count++;
704bb536b7dSmpi 		*spurious = 0;
705bb536b7dSmpi 	}
706bb536b7dSmpi 
707bb536b7dSmpi #ifdef MULTIPROCESSOR
708bb536b7dSmpi 	if (need_lock)
709bb536b7dSmpi 		KERNEL_UNLOCK();
710bb536b7dSmpi #endif
711bb536b7dSmpi 
712bb536b7dSmpi 	return (ret);
713bb536b7dSmpi }
714bb536b7dSmpi 
715ba99a0edSmpi void
openpic_acknowledge_irq(int irq,int cpuid)716ba99a0edSmpi openpic_acknowledge_irq(int irq, int cpuid)
717ba99a0edSmpi {
718ba99a0edSmpi 	(openpic_ops.acknowledge_irq)(irq, cpuid);
719ba99a0edSmpi }
720ba99a0edSmpi 
721ba99a0edSmpi void
openpic_enable_irq(int irq,int ist,int pri)722ba99a0edSmpi openpic_enable_irq(int irq, int ist, int pri)
723ba99a0edSmpi {
724ba99a0edSmpi 	(openpic_ops.enable_irq)(irq, ist, pri);
725ba99a0edSmpi }
726ba99a0edSmpi 
727ba99a0edSmpi void
openpic_disable_irq(int irq,int ist)728ba99a0edSmpi openpic_disable_irq(int irq, int ist)
729ba99a0edSmpi {
730ba99a0edSmpi 	(openpic_ops.disable_irq)(irq, ist);
731ba99a0edSmpi }
732ba99a0edSmpi 
733cc150176Smpi #ifdef MULTIPROCESSOR
7348d4cccd1Sdrahn void
openpic_send_ipi(struct cpu_info * ci,int id)735ba99a0edSmpi openpic_send_ipi(struct cpu_info *ci, int id)
736ba99a0edSmpi {
737ba99a0edSmpi 	switch (id) {
738ba99a0edSmpi 	case PPC_IPI_NOP:
739ba99a0edSmpi 		id = 0;
740ba99a0edSmpi 		break;
741ba99a0edSmpi 	case PPC_IPI_DDB:
742ba99a0edSmpi 		id = 1;
743ba99a0edSmpi 		break;
744ba99a0edSmpi 	default:
745ba99a0edSmpi 		panic("invalid ipi send to cpu %d %d", ci->ci_cpuid, id);
746ba99a0edSmpi 	}
747ba99a0edSmpi 
748ba99a0edSmpi 	openpic_write(OPENPIC_IPI(curcpu()->ci_cpuid, id), 1 << ci->ci_cpuid);
749ba99a0edSmpi }
750ba99a0edSmpi 
751ba99a0edSmpi void
openpic_ipi_ddb(void)752ba99a0edSmpi openpic_ipi_ddb(void)
7538d4cccd1Sdrahn {
7545dbffadbSderaadt #ifdef DDB
755e97088d6Smpi 	db_enter();
7565dbffadbSderaadt #endif
7578d4cccd1Sdrahn }
758cc150176Smpi #endif /* MULTIPROCESSOR */
759ba99a0edSmpi 
760ba99a0edSmpi #if NHPB > 0
761ba99a0edSmpi extern int	hpb_enable_irq(int, int);
762ba99a0edSmpi extern int	hpb_disable_irq(int, int);
763ba99a0edSmpi extern void	hpb_eoi(int);
764ba99a0edSmpi 
765ba99a0edSmpi void
openpic_cpc945_acknowledge_irq(int irq,int cpuid)766ba99a0edSmpi openpic_cpc945_acknowledge_irq(int irq, int cpuid)
767ba99a0edSmpi {
768ba99a0edSmpi 	hpb_eoi(irq);
769ba99a0edSmpi 	openpic_gen_acknowledge_irq(irq, cpuid);
770ba99a0edSmpi }
771ba99a0edSmpi 
772ba99a0edSmpi void
openpic_cpc945_enable_irq(int irq,int ist,int pri)773ba99a0edSmpi openpic_cpc945_enable_irq(int irq, int ist, int pri)
774ba99a0edSmpi {
775ba99a0edSmpi 	if (hpb_enable_irq(irq, ist)) {
776ba99a0edSmpi 		u_int x = irq;
777ba99a0edSmpi 
778ba99a0edSmpi 		x |= OPENPIC_SENSE_EDGE;
779ba99a0edSmpi 		x |= OPENPIC_POLARITY_POSITIVE;
780ba99a0edSmpi 		x |= pri << OPENPIC_PRIORITY_SHIFT;
781ba99a0edSmpi 		openpic_write(OPENPIC_SRC_VECTOR(irq), x);
782ba99a0edSmpi 
783ba99a0edSmpi 		hpb_eoi(irq);
784ba99a0edSmpi 	} else
785ba99a0edSmpi 		openpic_gen_enable_irq(irq, ist, pri);
786ba99a0edSmpi }
787ba99a0edSmpi 
788ba99a0edSmpi void
openpic_cpc945_disable_irq(int irq,int ist)789ba99a0edSmpi openpic_cpc945_disable_irq(int irq, int ist)
790ba99a0edSmpi {
791ba99a0edSmpi 	hpb_disable_irq(irq, ist);
792ba99a0edSmpi 	openpic_gen_disable_irq(irq, ist);
793ba99a0edSmpi }
794ba99a0edSmpi #endif /* NHPB */
795ba99a0edSmpi 
796