0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/init.h>
0009 #include <linux/module.h>
0010 #include <linux/ioport.h>
0011 #include <linux/device.h>
0012 #include <linux/io.h>
0013
0014 #include <asm/irq.h>
0015 #include <asm/mach-types.h>
0016 #include <asm/mach/irq.h>
0017
0018 #include "regs-irq.h"
0019 #include "irqs.h"
0020
0021 #include "bast.h"
0022
0023 #define irqdbf(x...)
0024 #define irqdbf2(x...)
0025
0026
0027
0028
0029
0030
0031 static const unsigned char bast_pc104_irqmasks[] = {
0032 0,
0033 0,
0034 0,
0035 1,
0036 0,
0037 2,
0038 0,
0039 4,
0040 0,
0041 0,
0042 8,
0043 0,
0044 0,
0045 0,
0046 0,
0047 0,
0048 };
0049
0050 static const unsigned char bast_pc104_irqs[] = { 3, 5, 7, 10 };
0051
0052 static void
0053 bast_pc104_mask(struct irq_data *data)
0054 {
0055 unsigned long temp;
0056
0057 temp = __raw_readb(BAST_VA_PC104_IRQMASK);
0058 temp &= ~bast_pc104_irqmasks[data->irq];
0059 __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
0060 }
0061
0062 static void
0063 bast_pc104_maskack(struct irq_data *data)
0064 {
0065 struct irq_desc *desc = irq_to_desc(BAST_IRQ_ISA);
0066
0067 bast_pc104_mask(data);
0068 desc->irq_data.chip->irq_ack(&desc->irq_data);
0069 }
0070
0071 static void
0072 bast_pc104_unmask(struct irq_data *data)
0073 {
0074 unsigned long temp;
0075
0076 temp = __raw_readb(BAST_VA_PC104_IRQMASK);
0077 temp |= bast_pc104_irqmasks[data->irq];
0078 __raw_writeb(temp, BAST_VA_PC104_IRQMASK);
0079 }
0080
0081 static struct irq_chip bast_pc104_chip = {
0082 .irq_mask = bast_pc104_mask,
0083 .irq_unmask = bast_pc104_unmask,
0084 .irq_ack = bast_pc104_maskack
0085 };
0086
0087 static void bast_irq_pc104_demux(struct irq_desc *desc)
0088 {
0089 unsigned int stat;
0090 unsigned int irqno;
0091 int i;
0092
0093 stat = __raw_readb(BAST_VA_PC104_IRQREQ) & 0xf;
0094
0095 if (unlikely(stat == 0)) {
0096
0097 desc->irq_data.chip->irq_ack(&desc->irq_data);
0098 } else {
0099
0100
0101 for (i = 0; stat != 0; i++, stat >>= 1) {
0102 if (stat & 1) {
0103 irqno = bast_pc104_irqs[i];
0104 generic_handle_irq(irqno);
0105 }
0106 }
0107 }
0108 }
0109
0110 static __init int bast_irq_init(void)
0111 {
0112 unsigned int i;
0113
0114 if (machine_is_bast()) {
0115 printk(KERN_INFO "BAST PC104 IRQ routing, Copyright 2005 Simtec Electronics\n");
0116
0117
0118
0119 __raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
0120
0121 irq_set_chained_handler(BAST_IRQ_ISA, bast_irq_pc104_demux);
0122
0123
0124
0125 for (i = 0; i < 4; i++) {
0126 unsigned int irqno = bast_pc104_irqs[i];
0127
0128 irq_set_chip_and_handler(irqno, &bast_pc104_chip,
0129 handle_level_irq);
0130 irq_clear_status_flags(irqno, IRQ_NOREQUEST);
0131 }
0132 }
0133
0134 return 0;
0135 }
0136
0137 arch_initcall(bast_irq_init);