Annotation of funnyos/arch/sam7s64/dev/saaic.c, Revision 1.2
1.1 nbrk 1: /*
1.2 ! nbrk 2: * $Id: saaic.c,v 1.1 2007/11/24 20:49:44 nbrk Exp $
1.1 nbrk 3: */
4: #include <sys/types.h>
5: #include <sys/device.h>
6: #include <sys/bus.h>
7: #include <sys/kern_irq.h>
8:
9: #include <dev/cpuvar.h>
10:
11: #include <arch/sam7s64/dev/saaicvar.h>
12: #include <arch/sam7s64/dev/at91sam7.h>
13: #include <libkern/printf.h>
14:
1.2 ! nbrk 15: #define SAAIC_DEBUG
1.1 nbrk 16:
17: #ifdef SAAIC_DEBUG
18: #define DPRINTF(x...) do { printf(x); } while (0)
19: #else
20: #define DPRINTF(x...) { }
21: #endif
22:
23: /*
24: * Advanced Interrupt Controller.
25: */
26: extern void (*irq_trampoline_func)(void);
1.2 ! nbrk 27: extern struct intr_vector *irqtable;
1.1 nbrk 28: struct saaic_dd *irqcdd; /* current irqc device */
29:
30: struct driver saaic_dr = {
31: sizeof(struct saaic_dd),
32: saaic_attach,
33: NULL,
34: NULL
35: };
36:
37:
38: int
39: saaic_attach(struct device *self, uint32_t loc, uint8_t flags)
40: {
41: struct saaic_dd *ddp = self->dv_devdata;
1.2 ! nbrk 42: uint8_t intrno;
! 43: struct intr_vector *ivp = irqtable;
1.1 nbrk 44:
45: /* leap to parent's bus_handle */
46: ddp->sa_bhp = self->dv_parent->dv_aux;
47:
48: /* make this controller default */
49: irqcdd = ddp;
50:
51: printf("SAM7 Advanced Interrupt Controller (32 sources, 8 pri_levels)\n");
52:
53: /* override trampoline so core irq jumps to us */
54: irq_trampoline_func = saaic_irq;
55:
56: /* mask all interrupts */
57: for (intrno = 0; intrno < 32; intrno++)
58: saaic_unmask_intr(intrno);
59:
1.2 ! nbrk 60: /* clear all interrupts */
! 61: for (intrno = 0; intrno < 32; intrno++)
! 62: saaic_clear_intr(intrno);
! 63:
! 64: /* look in system irqtable for claimed interrupts and unmask them */
! 65: while(ivp != NULL) {
! 66: saaic_unmask_intr(ivp->iv_intrno);
! 67:
! 68: ivp = ivp->iv_next;
! 69: }
! 70:
1.1 nbrk 71: __cpu_enable_irq();
72:
73: return(0);
74: }
75:
76:
77: void
78: saaic_mask_intr(uint8_t intrno)
79: {
80: bus_write_4(irqcdd->sa_bhp, (uint32_t)AT91C_AIC_IDCR, 1 << intrno);
81: DPRINTF("saaic_mask_intr: masked interrupt no. %d (status=0x%x)\n", intrno, saaic_intrstatus());
82: }
83:
84:
85: void
86: saaic_unmask_intr(uint8_t intrno)
87: {
88: bus_write_1(irqcdd->sa_bhp, (uint32_t)AT91C_AIC_IECR, 1 << intrno);
89: DPRINTF("saaic_unmask_intr: unmasked interrupt no. %d (status=0x%x)\n", intrno, saaic_intrstatus());
90: }
91:
92:
1.2 ! nbrk 93: void
! 94: saaic_clear_intr(uint8_t intrno)
! 95: {
! 96: bus_write_1(irqcdd->sa_bhp, (uint32_t)AT91C_AIC_ICCR, 1 << intrno);
! 97: DPRINTF("saaic_clear_intr: cleared interrupt no. %d (status=0x%x)\n", intrno, saaic_intrstatus());
! 98: }
! 99:
! 100:
! 101: void
! 102: saaic_ack_intr(void)
! 103: {
! 104: bus_write_1(irqcdd->sa_bhp, (uint32_t)AT91C_AIC_EOICR, 1);
! 105: DPRINTF("saaic_ack_intr: acknowledged current interrupt (status=0x%x)\n", saaic_intrstatus());
! 106: }
! 107:
! 108:
! 109:
1.1 nbrk 110: uint32_t
111: saaic_intrstatus(void)
112: {
1.2 ! nbrk 113: return( bus_read_4(irqcdd->sa_bhp, (uint32_t)AT91C_AIC_IPR));
1.1 nbrk 114: }
115:
116:
117: void
118: saaic_irq(void)
119: {
120: /*
121: * Process an IRQ.
122: * Check interrupt status of the irqc and execute corresponding intr handlers.
123: */
124: uint32_t irqstatus;
125: uint8_t intrno;
126:
127: /* read intr status; one bit per intr source */
128: irqstatus = saaic_intrstatus();
129:
1.2 ! nbrk 130: DPRINTF("saaic_irq: got interrupt (pending mask=0x%x)\n", irqstatus);
1.1 nbrk 131:
132: /* exit if no interrupts; should not happen */
1.2 ! nbrk 133: // if (irqstatus == 0)
! 134: // return;
1.1 nbrk 135:
136: /* let kern_irq throw us to the right place */
137: for (intrno = 0; intrno < 32; intrno++)
138: if (irqstatus & (1 << intrno)) {
139: /* interrupt line is active */
140: intr_execute(intrno);
1.2 ! nbrk 141:
! 142: /* XXX */
! 143: saaic_clear_intr(intrno);
! 144:
! 145: /* XXX acknowledge this interrupt */
! 146: saaic_ack_intr();
1.1 nbrk 147: }
148:
149: }
150:
CVSweb