Annotation of sys/arch/arm/sa11x0/sa1111_intr.c, Revision 1.3
1.3 ! nbrk 1: /* $Id: sa1111_intr.c,v 1.2 2008/03/05 14:06:41 nbrk Exp $ */
1.1 nbrk 2: #include <sys/cdefs.h>
3:
4: #include <sys/param.h>
5: #include <sys/systm.h>
6: #include <sys/device.h>
7: #include <sys/malloc.h>
8: #include <sys/evcount.h>
9: #include <sys/queue.h>
10: #include <uvm/uvm_extern.h>
11:
12: #include <machine/bus.h>
13: #include <machine/intr.h>
14: #include <machine/lock.h>
15:
16: #include <arm/sa11x0/sa11x0_intr.h>
17: #include <arm/sa11x0/sa11x0_gpiovar.h>
18: #include <arm/sa11x0/sa11x1_var.h>
19: #include <arm/sa11x0/sa1111_reg.h>
20: #include <arm/sa11x0/sa1111_intr.h>
21: /*
22: * TODO:
23: * - SPL
24: */
25:
26: /*
27: * Autoconf glue.
28: */
29: int sacic_match(struct device *, void *, void *);
30: void sacic_attach(struct device *, struct device *, void *);
31: int sacic_dispatcher(void *arg);
32: void sacic_intr_mask(int intrno);
33: void sacic_intr_unmask(int intrno);
34: void sacic_intr_clear(int intrno);
35: void sacic_set_intr_level(int intrno, int level);
36:
37: struct cfattach sacic_ca = {
38: sizeof(struct sacic_softc), sacic_match, sacic_attach
39: };
40:
41: struct cfdriver sacic_cd = {
42: NULL, "sacic", DV_DULL
43: };
44:
45: struct sacic_softc *sacic_sc;
46:
47: int
48: sacic_match(struct device *parent, void *cf, void *aux)
49: {
50: struct sacc_attach_args *saa = aux;
51:
52: if (sacic_sc != NULL || saa->sac_typecookie != SACC_TYPE_INTC)
53: return(0);
54:
55: return(1);
56: }
57:
58: void
59: sacic_attach(struct device *parent, struct device *self, void *aux)
60: {
61: /*
62: * Initialize ourselfes and establish our dispatcher on host irq xintr.
63: */
64: struct sacic_softc *sc = (struct sacic_softc *)self;
65: struct sacc_attach_args *saa = aux;
66:
67: sc->sc_bust = saa->sac_iot;
68: sc->sc_bush = saa->sac_bush;
69:
70: /* NULLify handlers */
71: memset(sc->sc_handlers, 0, sizeof(sc->sc_handlers));
1.3 ! nbrk 72: #if 0
1.1 nbrk 73: /* mask all interrupts.. */
74: bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTEN0, 0);
75: bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTEN1, 0);
76: /* ..and kill all pending ones */
77: bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR0, 0xffffffff);
78: bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR1, 0xffffffff);
1.3 ! nbrk 79: #endif
! 80: printf(": SA-1111 Interrupt Controller\n");
1.1 nbrk 81: /* XXX IPL_AUDIO ? */
1.3 ! nbrk 82: sc->sc_hostih = sa11x0_gpio_intr_establish(saa->sac_xintr, IST_EDGE_RISING, IPL_TTY,
1.1 nbrk 83: sacic_dispatcher, NULL, "sacic");
84:
85: sacic_sc = sc;
86: }
87:
88: void
89: sacic_intr_mask(int intrno)
90: {
91: struct sacic_softc *sc = sacic_sc;
92: bus_addr_t reg;
93: uint32_t oldmask;
94:
95: if (sc == NULL)
96: panic("%s: sacic_intr_mask: sacic not configured", sc->sc_dev.dv_xname);
97:
98: /* select apropriate register bank */
99: if (intrno >= 0 && intrno < 32)
100: reg = SACCIC_INTEN0;
101: else {
102: if (intrno >= 32 && intrno < SACCIC_LEN) {
103: reg = SACCIC_INTEN1;
104: /* adjust to be 0..31 */
105: intrno -= 32;
106: }
107: else
108: /* out of range */
109: panic("%s: sacic_intr_mask: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
110: }
111:
112: oldmask = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
113: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldmask & ~(1 << intrno));
114: }
115:
116: void
117: sacic_intr_unmask(int intrno)
118: {
119: struct sacic_softc *sc = sacic_sc;
120: bus_addr_t reg;
121:
122: if (sc == NULL)
123: panic("sacic_intr_mask: sacic not configured");
124:
125: /* select apropriate register bank */
126: if (intrno >= 0 && intrno < 32)
127: reg = SACCIC_INTEN0;
128: else {
129: if (intrno >= 32 && intrno < SACCIC_LEN) {
130: reg = SACCIC_INTEN1;
131: /* adjust to be 0..31 */
132: intrno -= 32;
133: }
134: else
135: /* out of range */
136: panic("%s: sacic_intr_mask: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
137: }
138:
139: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, 1 << intrno);
140: }
141:
142: void
143: sacic_intr_clear(int intrno)
144: {
145: struct sacic_softc *sc = sacic_sc;
146: bus_addr_t reg;
147:
148: /* select apropriate register bank */
149: if (intrno >= 0 && intrno < 32)
150: reg = SACCIC_INTSTATCLR0;
151: else {
152: if (intrno >= 32 && intrno < SACCIC_LEN) {
153: reg = SACCIC_INTSTATCLR1;
154: /* adjust to be 0..31 */
155: intrno -= 32;
156: }
157: else
158: /* out of range */
159: panic("%s: sacic_intr_clear: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
160: }
161:
162: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, 1 << intrno);
163: }
164:
165: void
166: sacic_set_intr_level(int intrno, int level)
167: {
168: /*
169: * Set interrupt polarity to either falling or rising edge.
170: */
171: struct sacic_softc *sc = sacic_sc;
172: bus_addr_t reg;
173: uint32_t oldpol;
174:
175: if (sc == NULL)
176: panic("sacic_set_intr_level: sacic not configured");
177:
178: /* select apropriate register bank */
179: if (intrno >= 0 && intrno < 32)
180: reg = SACCIC_INTPOL0;
181: else {
182: if (intrno >= 32 && intrno < SACCIC_LEN) {
183: reg = SACCIC_INTPOL1;
184: /* adjust to be 0..31 */
185: intrno -= 32;
186: }
187: else
188: /* out of range */
189: panic("%s: sacic_set_intr_level: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
190: }
191:
192: oldpol = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
193: switch (level) {
194: case IST_EDGE_FALLING:
195: oldpol |= 1 << intrno;
196: break;
197: case IST_EDGE_RISING:
198: oldpol &= ~(1 << intrno);
199: break;
200: default:
201: panic("%s: bad level: %d", sc->sc_dev.dv_xname, level);
202: break;
203: }
204: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldpol);
205: }
206:
207: int
208: sacic_dispatcher(void *arg)
209: {
210: /*
211: * Process pending interrupt(s).
212: */
213: struct sacic_softc *sc = sacic_sc;
214: uint32_t intstat, intbit;
215: int intrno;
216:
217: /* check first bank */
218: intstat = bus_space_read_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR0);
219: for (intbit = 1, intrno = 0; intbit > 0; intbit <<= 1, intrno++) {
220: if (intstat & intbit) {
221: /* interrupt set */
222: if (sc->sc_handlers[intrno] != NULL)
223: /* jump! */
224: sc->sc_handlers[intrno]->ih_func(sc->sc_handlers[intrno]->ih_arg);
225:
226: /* XXX acknowledge intr anyway */
227: sacic_intr_clear(intrno);
228: }
229: }
230:
231: /* check second bank */
232: intstat = bus_space_read_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR1);
233: for (intbit = 1, intrno = 32; intbit > 0; intbit <<= 1, intrno++) {
234: if (intstat & intbit) {
235: /* interrupt set */
236: if (sc->sc_handlers[intrno] != NULL)
237: /* jump! */
238: sc->sc_handlers[intrno]->ih_func(sc->sc_handlers[intrno]->ih_arg);
239:
240: /* XXX acknowledge intr anyway */
241: sacic_intr_clear(intrno);
242: }
243: }
244: return(0);
245: }
246:
247: void
248: *sa11x1_intr_establish(int irq, int level, int (*func)(void *),
249: void *arg, char *name)
250: {
251: struct sacic_softc *sc = sacic_sc;
252: struct sacic_intrhandler *sih;
253:
254: if (sc == NULL)
255: panic("sa11x1_intr_establish: sacic not configured");
256: if (irq < 0 || irq > 31)
257: panic("sa11x1_intr_establish: bogus intrno %d", irq);
258:
259: MALLOC(sih, struct sacic_intrhandler *, sizeof(struct sacic_intrhandler),
260: M_DEVBUF, M_NOWAIT);
1.2 nbrk 261: memset(sih, 0, sizeof(struct sacic_intrhandler));
1.1 nbrk 262: sih->ih_xintr = irq;
263: sih->ih_level = level;
264: sih->ih_func = func;
265: sih->ih_arg = arg;
266: sih->ih_name = name;
267: /* TODO evcount? */
268:
269: sacic_set_intr_level(irq, level);
270:
271: /* XXX silently drops previous handler */
272: sc->sc_handlers[irq] = sih;
273: sacic_intr_unmask(irq);
274:
275: return(sih);
276: }
277:
278: void sa11x1_intr_disestablish(void *cookie)
279: {
1.2 nbrk 280: /*
281: * Unlink interrupt handler and free its data structures.
282: */
283: struct sacic_softc *sc = sacic_sc;
284: struct sacic_intrhandler *sih = cookie;
285:
286: sc->sc_handlers[sih->ih_xintr] = NULL;
287:
288: FREE(sih, M_DEVBUF);
1.1 nbrk 289: }
CVSweb