Annotation of sys/arch/arm/xscale/pxa2x0_intr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pxa2x0_intr.c,v 1.15 2007/05/19 15:47:16 miod Exp $ */
2: /* $NetBSD: pxa2x0_intr.c,v 1.5 2003/07/15 00:24:55 lukem Exp $ */
3:
4: /*
5: * Copyright (c) 2002 Genetec Corporation. All rights reserved.
6: * Written by Hiroyuki Bessho for Genetec Corporation.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed for the NetBSD Project by
19: * Genetec Corporation.
20: * 4. The name of Genetec Corporation may not be used to endorse or
21: * promote products derived from this software without specific prior
22: * written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
25: * 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 GENETEC CORPORATION
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: /*
38: * IRQ handler for the Intel PXA2X0 processor.
39: * It has integrated interrupt controller.
40: */
41:
42: #include <sys/cdefs.h>
43: /*
44: __KERNEL_RCSID(0, "$NetBSD: pxa2x0_intr.c,v 1.5 2003/07/15 00:24:55 lukem Exp $");
45: */
46:
47: #include <sys/cdefs.h>
48:
49: #include <sys/param.h>
50: #include <sys/systm.h>
51: #include <sys/malloc.h>
52: #include <sys/evcount.h>
53: #include <sys/queue.h>
54: #include <uvm/uvm_extern.h>
55:
56: #include <machine/bus.h>
57: #include <machine/intr.h>
58: #include <machine/lock.h>
59:
60: #include <arm/xscale/pxa2x0reg.h>
61: #include <arm/xscale/pxa2x0var.h>
62: #include <arm/xscale/pxa2x0_intr.h>
63: #include <arm/sa11x0/sa11x0_var.h>
64:
65: /*
66: * INTC autoconf glue
67: */
68: int pxaintc_match(struct device *, void *, void *);
69: void pxaintc_attach(struct device *, struct device *, void *);
70:
71: #ifdef __NetBSD__
72: CFATTACH_DECL(pxaintc, sizeof(struct device),
73: pxaintc_match, pxaintc_attach, NULL, NULL);
74: #else
75: struct cfattach pxaintc_ca = {
76: sizeof(struct device), pxaintc_match, pxaintc_attach
77: };
78:
79: struct cfdriver pxaintc_cd = {
80: NULL, "pxaintc", DV_DULL
81: };
82:
83: #endif
84:
85: static int pxaintc_attached;
86:
87: int pxa2x0_stray_interrupt(void *);
88: void pxa2x0_init_interrupt_masks(void);
89:
90: /*
91: * interrupt dispatch table.
92: */
93: #if 1
94: #define MULTIPLE_HANDLERS_ON_ONE_IRQ
95: #endif
96: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
97: struct intrhand {
98: TAILQ_ENTRY(intrhand) ih_list; /* link on intrq list */
99: int (*ih_func)(void *); /* handler */
100: void *ih_arg; /* arg for handler */
101: char *ih_name;
102: struct evcount ih_count;
103: int ih_irq;
104: int ih_level;
105: };
106: #endif
107:
108: static struct intrhandler{
109: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
110: TAILQ_HEAD(,intrhand) list;
111: #else
112: pxa2x0_irq_handler_t func;
113: char *name;
114: void *arg; /* NULL for stackframe */
115: int ih_irq;
116: struct evcount ih_count;
117: #endif
118: } handler[ICU_LEN];
119:
120: __volatile int softint_pending;
121: __volatile int current_spl_level;
122: /* interrupt masks for each level */
123: int pxa2x0_imask[NIPL];
124: static int extirq_level[ICU_LEN];
125:
126:
127: int
128: pxaintc_match(struct device *parent, void *cf, void *aux)
129: {
130: struct pxaip_attach_args *pxa = aux;
131:
132: if (pxaintc_attached || pxa->pxa_addr != PXA2X0_INTCTL_BASE)
133: return (0);
134:
135: return (1);
136: }
137:
138: void
139: pxaintc_attach(struct device *parent, struct device *self, void *args)
140: {
141: int i;
142:
143: pxaintc_attached = 1;
144:
145: printf(": Interrupt Controller\n");
146:
147: #define SAIPIC_ICCR 0x14
148:
149: write_icu(SAIPIC_ICCR, 1);
150: write_icu(SAIPIC_MR, 0);
151:
152: for(i = 0; i < sizeof handler / sizeof handler[0]; ++i){
153: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
154: TAILQ_INIT(&handler[i].list);
155: extirq_level[i] = IPL_NONE;
156: #else
157: handler[i].name = "stray";
158: handler[i].func = pxa2x0_stray_interrupt;
159: handler[i].arg = (void *)(u_int32_t) i;
160: extirq_level[i] = IPL_SERIAL;
161: #endif
162:
163: }
164:
165: pxa2x0_init_interrupt_masks();
166:
167: _splraise(IPL_SERIAL);
168: enable_interrupts(I32_bit);
169: }
170:
171: /*
172: * Invoked very early on from the board-specific initarm(), in order to
173: * inform us the virtual address of the interrupt controller's registers.
174: */
175: vaddr_t pxaic_base;
176: void
177: pxa2x0_intr_bootstrap(vaddr_t addr)
178: {
179:
180: pxaic_base = addr;
181: }
182:
183: /*
184: * PXA27x has MSL interface and SSP3 interrupts [0,1], USIM interface
185: * and SSP2 interrupts [15,16]. PXA255 has bits [0..6,15] reserved and
186: * bit [16] network SSP interrupt. We don't need any of those, so we
187: * map software interrupts to bits [0..1,15..16]. Sadly there are no
188: * four contiguous bits safe enough to use on both processors.
189: */
190: #define SI_TO_IRQBIT(si) ((si) < 2 ? 1U<<(si) : 1U<<(15-2+(si)))
191:
192: /*
193: * Map a software interrupt queue to an interrupt priority level.
194: */
195: static const int si_to_ipl[SI_NQUEUES] = {
196: IPL_SOFT, /* SI_SOFT */
197: IPL_SOFTCLOCK, /* SI_SOFTCLOCK */
198: IPL_SOFTNET, /* SI_SOFTNET */
199: IPL_SOFTSERIAL, /* SI_SOFTSERIAL */
200: };
201:
202: /*
203: * called from irq_entry.
204: */
205: void
206: pxa2x0_irq_handler(void *arg)
207: {
208: struct clockframe *frame = arg;
209: uint32_t irqbits;
210: int irqno;
211: int saved_spl_level;
212: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
213: struct intrhand *ih;
214: #endif
215:
216: saved_spl_level = current_spl_level;
217:
218: /* get pending IRQs */
219: irqbits = read_icu(SAIPIC_IP);
220:
221: while ((irqno = find_first_bit(irqbits)) >= 0) {
222: /* XXX: Should we handle IRQs in priority order? */
223:
224: /* raise spl to stop interrupts of lower priorities */
225: if (saved_spl_level < extirq_level[irqno])
226: pxa2x0_setipl(extirq_level[irqno]);
227:
228: /* Enable interrupt */
229: enable_interrupts(I32_bit);
230:
231: #ifndef MULTIPLE_HANDLERS_ON_ONE_IRQ
232: (* handler[irqno].func)(
233: handler[irqno].arg == 0
234: ? frame : handler[irqno].arg );
235: handler[irqno].ih_count.ec_count++;
236: #else
237: TAILQ_FOREACH(ih, &handler[irqno].list, ih_list) {
238: if ((ih->ih_func)( ih->ih_arg == 0
239: ? frame : ih->ih_arg))
240: ih->ih_count.ec_count++;
241: }
242: #endif
243:
244: /* Disable interrupt */
245: disable_interrupts(I32_bit);
246:
247: irqbits &= ~(1<<irqno);
248: }
249:
250: /* restore spl to that was when this interrupt happen */
251: pxa2x0_setipl(saved_spl_level);
252:
253: if(softint_pending & pxa2x0_imask[current_spl_level])
254: pxa2x0_do_pending();
255: }
256:
257: int
258: pxa2x0_stray_interrupt(void *cookie)
259: {
260: int irqno = (int)cookie;
261: printf("stray interrupt %d\n", irqno);
262:
263: if (PXA2X0_IRQ_MIN <= irqno && irqno < ICU_LEN){
264: int save = disable_interrupts(I32_bit);
265: write_icu(SAIPIC_MR,
266: read_icu(SAIPIC_MR) & ~(1U<<irqno));
267: restore_interrupts(save);
268: }
269:
270: return 0;
271: }
272:
273:
274:
275: /*
276: * Interrupt Mask Handling
277: */
278:
279: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
280: void pxa2x0_update_intr_masks(void);
281:
282: void
283: pxa2x0_update_intr_masks()
284: #else
285: void pxa2x0_update_intr_masks(int irqno, int level);
286:
287: void
288: pxa2x0_update_intr_masks(int irqno, int irqlevel)
289: #endif
290: {
291: int psw;
292:
293: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
294: int irq;
295: #ifdef DEBUG
296: int level;
297: #endif
298: struct intrhand *ih;
299: psw = disable_interrupts(I32_bit);
300:
301: /* First figure out which levels each IRQ uses. */
302: for (irq = 0; irq < ICU_LEN; irq++) {
303: int i;
304: int max = IPL_NONE;
305: int min = IPL_HIGH; /* XXX kill IPL_SERIAL */
306: TAILQ_FOREACH(ih, &handler[irq].list, ih_list) {
307: if (ih->ih_level > max)
308: max = ih->ih_level;
309:
310: if (ih->ih_level < min)
311: min = ih->ih_level;
312: }
313:
314: extirq_level[irq] = max;
315:
316: if (min == IPL_HIGH)
317: min = IPL_NONE;
318:
319: /* Enable interrupt at lower level */
320: for(i = 0; i < min; ++i)
321: pxa2x0_imask[i] |= (1 << irq);
322:
323: /* Disable interrupt at upper level */
324: for( ; i < NIPL-1; ++i)
325: pxa2x0_imask[i] &= ~(1 << irq);
326: }
327:
328: /* fixup */
329: pxa2x0_imask[IPL_NONE] |=
330: SI_TO_IRQBIT(SI_SOFT) |
331: SI_TO_IRQBIT(SI_SOFTCLOCK) |
332: SI_TO_IRQBIT(SI_SOFTNET) |
333: SI_TO_IRQBIT(SI_SOFTSERIAL);
334: pxa2x0_imask[IPL_SOFT] |=
335: SI_TO_IRQBIT(SI_SOFTCLOCK) |
336: SI_TO_IRQBIT(SI_SOFTNET) |
337: SI_TO_IRQBIT(SI_SOFTSERIAL);
338: pxa2x0_imask[IPL_SOFTCLOCK] |=
339: SI_TO_IRQBIT(SI_SOFTNET) |
340: SI_TO_IRQBIT(SI_SOFTSERIAL);
341: pxa2x0_imask[IPL_SOFTNET] |=
342: SI_TO_IRQBIT(SI_SOFTSERIAL);
343: pxa2x0_imask[IPL_SOFTSERIAL] |=
344: 0;
345: #else
346: int level; /* debug */
347: int mask = 1U<<irqno;
348: int i;
349: psw = disable_interrupts(I32_bit);
350:
351: for(i = 0; i < irqlevel; ++i)
352: pxa2x0_imask[i] |= mask; /* Enable interrupt at lower level */
353:
354: for( ; i < NIPL-1; ++i)
355: pxa2x0_imask[i] &= ~mask; /* Disable interrupt at upper level */
356: #endif
357:
358: /*
359: * Enforce a hierarchy that gives "slow" device (or devices with
360: * limited input buffer space/"real-time" requirements) a better
361: * chance at not dropping data.
362: */
363: pxa2x0_imask[IPL_BIO] &= pxa2x0_imask[IPL_SOFTNET];
364: pxa2x0_imask[IPL_NET] &= pxa2x0_imask[IPL_BIO];
365: pxa2x0_imask[IPL_SOFTSERIAL] &= pxa2x0_imask[IPL_NET];
366: pxa2x0_imask[IPL_TTY] &= pxa2x0_imask[IPL_SOFTSERIAL];
367:
368: /*
369: * splvm() blocks all interrupts that use the kernel memory
370: * allocation facilities.
371: */
372: pxa2x0_imask[IPL_VM] &= pxa2x0_imask[IPL_TTY];
373:
374: /*
375: * Audio devices are not allowed to perform memory allocation
376: * in their interrupt routines, and they have fairly "real-time"
377: * requirements, so give them a high interrupt priority.
378: */
379: pxa2x0_imask[IPL_AUDIO] &= pxa2x0_imask[IPL_VM];
380:
381: /*
382: * splclock() must block anything that uses the scheduler.
383: */
384: pxa2x0_imask[IPL_CLOCK] &= pxa2x0_imask[IPL_AUDIO];
385:
386: /*
387: * splhigh() must block "everything".
388: */
389: pxa2x0_imask[IPL_HIGH] &= pxa2x0_imask[IPL_STATCLOCK];
390:
391: /*
392: * XXX We need serial drivers to run at the absolute highest priority
393: * in order to avoid overruns, so serial > high.
394: */
395: pxa2x0_imask[IPL_SERIAL] &= pxa2x0_imask[IPL_HIGH];
396:
397: #ifdef DEBUG
398: for (level = IPL_NONE; level < NIPL; level++) {
399: printf("imask %d, %x\n", level, pxa2x0_imask[level]);
400: }
401: #endif
402:
403: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
404: for (irq = 0; irq < ICU_LEN; irq++) {
405: int max_irq = IPL_NONE;
406: TAILQ_FOREACH(ih, &handler[irq].list, ih_list) {
407: if (ih->ih_level > max_irq)
408: max_irq = ih->ih_level;
409: }
410: extirq_level[irq] = max_irq;
411: }
412: #endif
413:
414: write_icu(SAIPIC_MR, pxa2x0_imask[current_spl_level]);
415:
416: restore_interrupts(psw);
417: }
418:
419:
420: void
421: pxa2x0_init_interrupt_masks(void)
422: {
423:
424: memset(pxa2x0_imask, 0, sizeof(pxa2x0_imask));
425:
426: /*
427: * IPL_NONE has soft interrupts enabled only, at least until
428: * hardware handlers are installed.
429: */
430: pxa2x0_imask[IPL_NONE] =
431: SI_TO_IRQBIT(SI_SOFT) |
432: SI_TO_IRQBIT(SI_SOFTCLOCK) |
433: SI_TO_IRQBIT(SI_SOFTNET) |
434: SI_TO_IRQBIT(SI_SOFTSERIAL);
435:
436: /*
437: * Initialize the soft interrupt masks to block themselves.
438: */
439: pxa2x0_imask[IPL_SOFT] = ~SI_TO_IRQBIT(SI_SOFT);
440: pxa2x0_imask[IPL_SOFTCLOCK] = ~SI_TO_IRQBIT(SI_SOFTCLOCK);
441: pxa2x0_imask[IPL_SOFTNET] = ~SI_TO_IRQBIT(SI_SOFTNET);
442: pxa2x0_imask[IPL_SOFTSERIAL] = ~SI_TO_IRQBIT(SI_SOFTSERIAL);
443:
444: pxa2x0_imask[IPL_SOFT] &= pxa2x0_imask[IPL_NONE];
445:
446: /*
447: * splsoftclock() is the only interface that users of the
448: * generic software interrupt facility have to block their
449: * soft intrs, so splsoftclock() must also block IPL_SOFT.
450: */
451: pxa2x0_imask[IPL_SOFTCLOCK] &= pxa2x0_imask[IPL_SOFT];
452:
453: /*
454: * splsoftnet() must also block splsoftclock(), since we don't
455: * want timer-driven network events to occur while we're
456: * processing incoming packets.
457: */
458: pxa2x0_imask[IPL_SOFTNET] &= pxa2x0_imask[IPL_SOFTCLOCK];
459: }
460:
461: void
462: pxa2x0_do_pending(void)
463: {
464: static __cpu_simple_lock_t processing = __SIMPLELOCK_UNLOCKED;
465: int oldirqstate, spl_save;
466:
467: if (__cpu_simple_lock_try(&processing) == 0)
468: return;
469:
470: spl_save = current_spl_level;
471:
472: oldirqstate = disable_interrupts(I32_bit);
473:
474: #if 1
475: #define DO_SOFTINT(si,ipl) \
476: if ((softint_pending & pxa2x0_imask[current_spl_level]) & \
477: SI_TO_IRQBIT(si)) { \
478: softint_pending &= ~SI_TO_IRQBIT(si); \
479: if (current_spl_level < ipl) \
480: pxa2x0_setipl(ipl); \
481: restore_interrupts(oldirqstate); \
482: softintr_dispatch(si); \
483: oldirqstate = disable_interrupts(I32_bit); \
484: pxa2x0_setipl(spl_save); \
485: }
486:
487: do {
488: DO_SOFTINT(SI_SOFTSERIAL,IPL_SOFTSERIAL);
489: DO_SOFTINT(SI_SOFTNET, IPL_SOFTNET);
490: DO_SOFTINT(SI_SOFTCLOCK, IPL_SOFTCLOCK);
491: DO_SOFTINT(SI_SOFT, IPL_SOFT);
492: } while( softint_pending & pxa2x0_imask[current_spl_level] );
493: #else
494: while( (si = find_first_bit(softint_pending & pxa2x0_imask[current_spl_level])) >= 0 ){
495: softint_pending &= ~SI_TO_IRQBIT(si);
496: if (current_spl_level < ipl)
497: pxa2x0_setipl(ipl);
498: restore_interrupts(oldirqstate);
499: softintr_dispatch(si);
500: oldirqstate = disable_interrupts(I32_bit);
501: pxa2x0_setipl(spl_save);
502: }
503: #endif
504:
505: __cpu_simple_unlock(&processing);
506:
507: restore_interrupts(oldirqstate);
508: }
509:
510:
511: #undef splx
512: void
513: splx(int ipl)
514: {
515:
516: pxa2x0_splx(ipl);
517: }
518:
519: #undef _splraise
520: int
521: _splraise(int ipl)
522: {
523:
524: return pxa2x0_splraise(ipl);
525: }
526:
527: #undef _spllower
528: int
529: _spllower(int ipl)
530: {
531:
532: return pxa2x0_spllower(ipl);
533: }
534:
535: #undef _setsoftintr
536: void
537: _setsoftintr(int si)
538: {
539:
540: return pxa2x0_setsoftintr(si);
541: }
542:
543: void *
544: pxa2x0_intr_establish(int irqno, int level,
545: int (*func)(void *), void *arg, char *name)
546: {
547: int psw;
548: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
549: struct intrhand *ih;
550: #else
551: struct intrhandler *ih;
552: #endif
553:
554: if (irqno < PXA2X0_IRQ_MIN || irqno >= ICU_LEN)
555: panic("intr_establish: bogus irq number %d", irqno);
556:
557: psw = disable_interrupts(I32_bit);
558:
559: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
560: /* no point in sleeping unless someone can free memory. */
561: MALLOC(ih, struct intrhand *, sizeof *ih, M_DEVBUF,
562: cold ? M_NOWAIT : M_WAITOK);
563: if (ih == NULL)
564: panic("intr_establish: can't malloc handler info");
565: ih->ih_func = func;
566: ih->ih_arg = arg;
567: ih->ih_level = level;
568: ih->ih_irq = irqno;
569:
570: TAILQ_INSERT_TAIL(&handler[irqno].list, ih, ih_list);
571: #else
572: ih = &handler[irqno];
573: ih->arg = arg;
574: ih->func = func;
575: ih->name = name;
576: ih->ih_irq = irqno;
577: extirq_level[irqno] = level;
578: #endif
579:
580: if (name != NULL)
581: evcount_attach(&ih->ih_count, name, (void *)&ih->ih_irq,
582: &evcount_intr);
583:
584: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
585: pxa2x0_update_intr_masks();
586: #else
587: pxa2x0_update_intr_masks(irqno, level);
588: #endif
589:
590: restore_interrupts(psw);
591:
592: return (ih);
593: }
594:
595: void
596: pxa2x0_intr_disestablish(void *cookie)
597: {
598:
599: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
600: int psw;
601: struct intrhand *ih = cookie;
602: int irqno = ih->ih_irq;
603:
604: psw = disable_interrupts(I32_bit);
605: TAILQ_REMOVE(&handler[irqno].list, ih, ih_list);
606:
607: FREE(ih, M_DEVBUF);
608:
609: pxa2x0_update_intr_masks();
610:
611: restore_interrupts(psw);
612: #else
613: struct intrhandler *lhandler = cookie;
614: int irqno;
615: int psw;
616: struct intrhandler *ih;
617: irqno = lhandler - handler;
618:
619: if (irqno < PXA2X0_IRQ_MIN || irqno >= ICU_LEN)
620: panic("intr_disestablish: bogus irq number %d", irqno);
621:
622: psw = disable_interrupts(I32_bit);
623:
624: ih = &handler[irqno];
625: if (ih->name != NULL)
626: evcount_detach(&ih->ih_count);
627:
628: ih->arg = (void *) irqno;
629: ih->func = pxa2x0_stray_interrupt;
630: ih->name = "stray";
631: extirq_level[irqno] = IPL_SERIAL;
632: pxa2x0_update_intr_masks(irqno, IPL_SERIAL);
633:
634: restore_interrupts(psw);
635: #endif
636: }
637:
638: /*
639: * Glue for drivers of sa11x0 compatible integrated logic.
640: */
641: void *
642: sa11x0_intr_establish(sa11x0_chipset_tag_t ic, int irq, int type, int level,
643: int (*ih_fun)(void *), void *ih_arg, char *name)
644: {
645:
646: return pxa2x0_intr_establish(irq, level, ih_fun, ih_arg, name);
647: }
648:
649: void
650: pxa2x0_setipl(int new)
651: {
652: u_int32_t intr_mask;
653:
654: intr_mask = pxa2x0_imask[new];
655: current_spl_level = new;
656: write_icu( SAIPIC_MR, intr_mask );
657: }
658:
659:
660: void
661: pxa2x0_splx(int new)
662: {
663: int psw;
664:
665: psw = disable_interrupts(I32_bit);
666: pxa2x0_setipl(new);
667: restore_interrupts(psw);
668:
669: /* If there are pending software interrupts, process them. */
670: if (softint_pending & pxa2x0_imask[current_spl_level])
671: pxa2x0_do_pending();
672: }
673:
674:
675: int
676: pxa2x0_splraise(int ipl)
677: {
678: int old, psw;
679:
680: old = current_spl_level;
681: if( ipl > current_spl_level ){
682: psw = disable_interrupts(I32_bit);
683: pxa2x0_setipl(ipl);
684: restore_interrupts(psw);
685: }
686:
687: return (old);
688: }
689:
690: int
691: pxa2x0_spllower(int ipl)
692: {
693: int old = current_spl_level;
694: int psw = disable_interrupts(I32_bit);
695: pxa2x0_splx(ipl);
696: restore_interrupts(psw);
697: return(old);
698: }
699:
700: void
701: pxa2x0_setsoftintr(int si)
702: {
703: #if 0
704: atomic_set_bit( (u_int *)&softint_pending, SI_TO_IRQBIT(si) );
705: #else
706: softint_pending |= SI_TO_IRQBIT(si);
707: #endif
708:
709: /* Process unmasked pending soft interrupts. */
710: if ( softint_pending & pxa2x0_imask[current_spl_level] )
711: pxa2x0_do_pending();
712: }
713:
714: const char *
715: pxa2x0_intr_string(void *cookie)
716: {
717: #ifdef MULTIPLE_HANDLERS_ON_ONE_IRQ
718: struct intrhand *ih = cookie;
719: #else
720: struct intrhandler *lhandler = cookie;
721: #endif
722: static char irqstr[32];
723:
724: if (ih == NULL)
725: snprintf(irqstr, sizeof irqstr, "couldn't establish interrupt");
726: else
727: snprintf(irqstr, sizeof irqstr, "irq %ld", ih->ih_irq);
728:
729: return irqstr;
730: }
731:
732: #ifdef DIAGNOSTIC
733: void
734: pxa2x0_splassert_check(int wantipl, const char *func)
735: {
736: int oldipl = current_spl_level, psw;
737:
738: if (oldipl < wantipl) {
739: splassert_fail(wantipl, oldipl, func);
740: /*
741: * If the splassert_ctl is set to not panic, raise the ipl
742: * in a feeble attempt to reduce damage.
743: */
744: psw = disable_interrupts(I32_bit);
745: pxa2x0_setipl(wantipl);
746: restore_interrupts(psw);
747: }
748: }
749: #endif
CVSweb