Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | // SPDX-License-Identifier: GPL-2.0+ // // Copyright 2003-2005 Simtec Electronics // Ben Dooks <ben@simtec.co.uk> // // http://www.simtec.co.uk/products/EB2410ITX/ #include <linux/init.h> #include <linux/module.h> #include <linux/ioport.h> #include <linux/device.h> #include <linux/io.h> #include <asm/irq.h> #include <asm/mach-types.h> #include <asm/mach/irq.h> #include "regs-irq.h" #include "irqs.h" #include "bast.h" #define irqdbf(x...) #define irqdbf2(x...) /* handle PC104 ISA interrupts from the system CPLD */ /* table of ISA irq nos to the relevant mask... zero means * the irq is not implemented */ static const unsigned char bast_pc104_irqmasks[] = { 0, /* 0 */ 0, /* 1 */ 0, /* 2 */ 1, /* 3 */ 0, /* 4 */ 2, /* 5 */ 0, /* 6 */ 4, /* 7 */ 0, /* 8 */ 0, /* 9 */ 8, /* 10 */ 0, /* 11 */ 0, /* 12 */ 0, /* 13 */ 0, /* 14 */ 0, /* 15 */ }; static const unsigned char bast_pc104_irqs[] = { 3, 5, 7, 10 }; static void bast_pc104_mask(struct irq_data *data) { unsigned long temp; temp = __raw_readb(BAST_VA_PC104_IRQMASK); temp &= ~bast_pc104_irqmasks[data->irq]; __raw_writeb(temp, BAST_VA_PC104_IRQMASK); } static void bast_pc104_maskack(struct irq_data *data) { struct irq_desc *desc = irq_to_desc(BAST_IRQ_ISA); bast_pc104_mask(data); desc->irq_data.chip->irq_ack(&desc->irq_data); } static void bast_pc104_unmask(struct irq_data *data) { unsigned long temp; temp = __raw_readb(BAST_VA_PC104_IRQMASK); temp |= bast_pc104_irqmasks[data->irq]; __raw_writeb(temp, BAST_VA_PC104_IRQMASK); } static struct irq_chip bast_pc104_chip = { .irq_mask = bast_pc104_mask, .irq_unmask = bast_pc104_unmask, .irq_ack = bast_pc104_maskack }; static void bast_irq_pc104_demux(struct irq_desc *desc) { unsigned int stat; unsigned int irqno; int i; stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf; if (unlikely(stat == 0)) { /* ack if we get an irq with nothing (ie, startup) */ desc->irq_data.chip->irq_ack(&desc->irq_data); } else { /* handle the IRQ */ for (i = 0; stat != 0; i++, stat >>= 1) { if (stat & 1) { irqno = bast_pc104_irqs[i]; generic_handle_irq(irqno); } } } } static __init int bast_irq_init(void) { unsigned int i; if (machine_is_bast()) { printk(KERN_INFO "BAST PC104 IRQ routing, Copyright 2005 Simtec Electronics\n"); /* zap all the IRQs */ __raw_writeb(0x0, BAST_VA_PC104_IRQMASK); irq_set_chained_handler(BAST_IRQ_ISA, bast_irq_pc104_demux); /* register our IRQs */ for (i = 0; i < 4; i++) { unsigned int irqno = bast_pc104_irqs[i]; irq_set_chip_and_handler(irqno, &bast_pc104_chip, handle_level_irq); irq_clear_status_flags(irqno, IRQ_NOREQUEST); } } return 0; } arch_initcall(bast_irq_init); |