Annotation of sys/arch/arm/sa11x0/sa1111_intr.c, Revision 1.2
1.2 ! nbrk 1: /* $Id: sa1111_intr.c,v 1.1 2008/03/05 11:19:00 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));
72: /* mask all interrupts.. */
73: bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTEN0, 0);
74: bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTEN1, 0);
75: /* ..and kill all pending ones */
76: bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR0, 0xffffffff);
77: bus_space_write_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR1, 0xffffffff);
78:
79: /* XXX IPL_AUDIO ? */
80: sc->sc_hostih = sa11x0_gpio_intr_establish(saa->sac_xintr, IST_EDGE_RISING, IPL_AUDIO,
81: sacic_dispatcher, NULL, "sacic");
82:
83: sacic_sc = sc;
84: }
85:
86: void
87: sacic_intr_mask(int intrno)
88: {
89: struct sacic_softc *sc = sacic_sc;
90: bus_addr_t reg;
91: uint32_t oldmask;
92:
93: if (sc == NULL)
94: panic("%s: sacic_intr_mask: sacic not configured", sc->sc_dev.dv_xname);
95:
96: /* select apropriate register bank */
97: if (intrno >= 0 && intrno < 32)
98: reg = SACCIC_INTEN0;
99: else {
100: if (intrno >= 32 && intrno < SACCIC_LEN) {
101: reg = SACCIC_INTEN1;
102: /* adjust to be 0..31 */
103: intrno -= 32;
104: }
105: else
106: /* out of range */
107: panic("%s: sacic_intr_mask: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
108: }
109:
110: oldmask = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
111: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldmask & ~(1 << intrno));
112: }
113:
114: void
115: sacic_intr_unmask(int intrno)
116: {
117: struct sacic_softc *sc = sacic_sc;
118: bus_addr_t reg;
119:
120: if (sc == NULL)
121: panic("sacic_intr_mask: sacic not configured");
122:
123: /* select apropriate register bank */
124: if (intrno >= 0 && intrno < 32)
125: reg = SACCIC_INTEN0;
126: else {
127: if (intrno >= 32 && intrno < SACCIC_LEN) {
128: reg = SACCIC_INTEN1;
129: /* adjust to be 0..31 */
130: intrno -= 32;
131: }
132: else
133: /* out of range */
134: panic("%s: sacic_intr_mask: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
135: }
136:
137: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, 1 << intrno);
138: }
139:
140: void
141: sacic_intr_clear(int intrno)
142: {
143: struct sacic_softc *sc = sacic_sc;
144: bus_addr_t reg;
145:
146: /* select apropriate register bank */
147: if (intrno >= 0 && intrno < 32)
148: reg = SACCIC_INTSTATCLR0;
149: else {
150: if (intrno >= 32 && intrno < SACCIC_LEN) {
151: reg = SACCIC_INTSTATCLR1;
152: /* adjust to be 0..31 */
153: intrno -= 32;
154: }
155: else
156: /* out of range */
157: panic("%s: sacic_intr_clear: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
158: }
159:
160: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, 1 << intrno);
161: }
162:
163: void
164: sacic_set_intr_level(int intrno, int level)
165: {
166: /*
167: * Set interrupt polarity to either falling or rising edge.
168: */
169: struct sacic_softc *sc = sacic_sc;
170: bus_addr_t reg;
171: uint32_t oldpol;
172:
173: if (sc == NULL)
174: panic("sacic_set_intr_level: sacic not configured");
175:
176: /* select apropriate register bank */
177: if (intrno >= 0 && intrno < 32)
178: reg = SACCIC_INTPOL0;
179: else {
180: if (intrno >= 32 && intrno < SACCIC_LEN) {
181: reg = SACCIC_INTPOL1;
182: /* adjust to be 0..31 */
183: intrno -= 32;
184: }
185: else
186: /* out of range */
187: panic("%s: sacic_set_intr_level: bogus intrno %d", sc->sc_dev.dv_xname, intrno);
188: }
189:
190: oldpol = bus_space_read_4(sc->sc_bust, sc->sc_bush, reg);
191: switch (level) {
192: case IST_EDGE_FALLING:
193: oldpol |= 1 << intrno;
194: break;
195: case IST_EDGE_RISING:
196: oldpol &= ~(1 << intrno);
197: break;
198: default:
199: panic("%s: bad level: %d", sc->sc_dev.dv_xname, level);
200: break;
201: }
202: bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, oldpol);
203: }
204:
205: int
206: sacic_dispatcher(void *arg)
207: {
208: /*
209: * Process pending interrupt(s).
210: */
211: struct sacic_softc *sc = sacic_sc;
212: uint32_t intstat, intbit;
213: int intrno;
214:
215: /* check first bank */
216: intstat = bus_space_read_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR0);
217: for (intbit = 1, intrno = 0; intbit > 0; intbit <<= 1, intrno++) {
218: if (intstat & intbit) {
219: /* interrupt set */
220: if (sc->sc_handlers[intrno] != NULL)
221: /* jump! */
222: sc->sc_handlers[intrno]->ih_func(sc->sc_handlers[intrno]->ih_arg);
223: else
224: /* no handler */
225: printf("%s: sacic_dispatcher: warning, no handler for pending intrno %d\n",
226: sc->sc_dev.dv_xname, intrno);
227:
228: /* XXX acknowledge intr anyway */
229: sacic_intr_clear(intrno);
230: }
231: }
232:
233: /* check second bank */
234: intstat = bus_space_read_4(sc->sc_bust, sc->sc_bush, SACCIC_INTSTATCLR1);
235: for (intbit = 1, intrno = 32; intbit > 0; intbit <<= 1, intrno++) {
236: if (intstat & intbit) {
237: /* interrupt set */
238: if (sc->sc_handlers[intrno] != NULL)
239: /* jump! */
240: sc->sc_handlers[intrno]->ih_func(sc->sc_handlers[intrno]->ih_arg);
241: else
242: /* no handler */
243: printf("%s: sacic_dispatcher: warning, no handler for pending intrno %d\n",
244: sc->sc_dev.dv_xname, intrno);
245:
246: /* XXX acknowledge intr anyway */
247: sacic_intr_clear(intrno);
248: }
249: }
250: return(0);
251: }
252:
253: void
254: *sa11x1_intr_establish(int irq, int level, int (*func)(void *),
255: void *arg, char *name)
256: {
257: struct sacic_softc *sc = sacic_sc;
258: struct sacic_intrhandler *sih;
259:
260: if (sc == NULL)
261: panic("sa11x1_intr_establish: sacic not configured");
262: if (irq < 0 || irq > 31)
263: panic("sa11x1_intr_establish: bogus intrno %d", irq);
264:
265: MALLOC(sih, struct sacic_intrhandler *, sizeof(struct sacic_intrhandler),
266: M_DEVBUF, M_NOWAIT);
1.2 ! nbrk 267: memset(sih, 0, sizeof(struct sacic_intrhandler));
1.1 nbrk 268: sih->ih_xintr = irq;
269: sih->ih_level = level;
270: sih->ih_func = func;
271: sih->ih_arg = arg;
272: sih->ih_name = name;
273: /* TODO evcount? */
274:
275: sacic_set_intr_level(irq, level);
276:
277: /* XXX silently drops previous handler */
278: sc->sc_handlers[irq] = sih;
279: sacic_intr_unmask(irq);
280:
281: return(sih);
282: }
283:
284: void sa11x1_intr_disestablish(void *cookie)
285: {
1.2 ! nbrk 286: /*
! 287: * Unlink interrupt handler and free its data structures.
! 288: */
! 289: struct sacic_softc *sc = sacic_sc;
! 290: struct sacic_intrhandler *sih = cookie;
! 291:
! 292: sc->sc_handlers[sih->ih_xintr] = NULL;
! 293:
! 294: FREE(sih, M_DEVBUF);
1.1 nbrk 295: }
CVSweb