Annotation of sys/arch/arm/sa11x0/sa1111_intr.c, Revision 1.1
1.1 ! nbrk 1: /* $Id$ */
! 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);
! 267: sih->ih_xintr = irq;
! 268: sih->ih_level = level;
! 269: sih->ih_func = func;
! 270: sih->ih_arg = arg;
! 271: sih->ih_name = name;
! 272: /* TODO evcount? */
! 273:
! 274: sacic_set_intr_level(irq, level);
! 275:
! 276: /* XXX silently drops previous handler */
! 277: sc->sc_handlers[irq] = sih;
! 278: sacic_intr_unmask(irq);
! 279:
! 280: return(sih);
! 281: }
! 282:
! 283: void sa11x1_intr_disestablish(void *cookie)
! 284: {
! 285: /* TODO */
! 286: }
CVSweb