0001
0002 #include <linux/init.h>
0003 #include <linux/list.h>
0004 #include <linux/io.h>
0005
0006 #include <asm/mach/irq.h>
0007 #include <asm/hardware/iomd.h>
0008 #include <asm/irq.h>
0009 #include <asm/fiq.h>
0010
0011
0012 #define STAT 0x00
0013 #define REQ 0x04
0014 #define CLR 0x04
0015 #define MASK 0x08
0016
0017 static const u8 irq_prio_h[256] = {
0018 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
0019 12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
0020 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
0021 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
0022 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
0023 14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
0024 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
0025 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
0026 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
0027 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
0028 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
0029 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
0030 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
0031 15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
0032 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
0033 13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
0034 };
0035
0036 static const u8 irq_prio_d[256] = {
0037 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0038 20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0039 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0040 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0041 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0042 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0043 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0044 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0045 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0046 23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0047 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0048 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0049 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0050 22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0051 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0052 21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
0053 };
0054
0055 static const u8 irq_prio_l[256] = {
0056 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
0057 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
0058 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
0059 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
0060 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
0061 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
0062 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
0063 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
0064 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0065 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0066 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0067 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0068 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0069 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0070 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0071 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
0072 };
0073
0074 static int iomd_get_irq_nr(void)
0075 {
0076 int irq;
0077 u8 reg;
0078
0079
0080 reg = readb(IOC_BASE + IOMD_IRQREQB);
0081 irq = irq_prio_h[reg];
0082 if (irq)
0083 return irq;
0084
0085
0086 reg = readb(IOC_BASE + IOMD_DMAREQ);
0087 irq = irq_prio_d[reg];
0088 if (irq)
0089 return irq;
0090
0091
0092 reg = readb(IOC_BASE + IOMD_IRQREQA);
0093 irq = irq_prio_l[reg];
0094 if (irq)
0095 return irq;
0096 return 0;
0097 }
0098
0099 static void iomd_handle_irq(struct pt_regs *regs)
0100 {
0101 int irq;
0102
0103 do {
0104 irq = iomd_get_irq_nr();
0105 if (irq)
0106 generic_handle_irq(irq);
0107 } while (irq);
0108 }
0109
0110 static void __iomem *iomd_get_base(struct irq_data *d)
0111 {
0112 void *cd = irq_data_get_irq_chip_data(d);
0113
0114 return (void __iomem *)(unsigned long)cd;
0115 }
0116
0117 static void iomd_set_base_mask(unsigned int irq, void __iomem *base, u32 mask)
0118 {
0119 struct irq_data *d = irq_get_irq_data(irq);
0120
0121 d->mask = mask;
0122 irq_set_chip_data(irq, (void *)(unsigned long)base);
0123 }
0124
0125 static void iomd_irq_mask_ack(struct irq_data *d)
0126 {
0127 void __iomem *base = iomd_get_base(d);
0128 unsigned int val, mask = d->mask;
0129
0130 val = readb(base + MASK);
0131 writeb(val & ~mask, base + MASK);
0132 writeb(mask, base + CLR);
0133 }
0134
0135 static void iomd_irq_mask(struct irq_data *d)
0136 {
0137 void __iomem *base = iomd_get_base(d);
0138 unsigned int val, mask = d->mask;
0139
0140 val = readb(base + MASK);
0141 writeb(val & ~mask, base + MASK);
0142 }
0143
0144 static void iomd_irq_unmask(struct irq_data *d)
0145 {
0146 void __iomem *base = iomd_get_base(d);
0147 unsigned int val, mask = d->mask;
0148
0149 val = readb(base + MASK);
0150 writeb(val | mask, base + MASK);
0151 }
0152
0153 static struct irq_chip iomd_chip_clr = {
0154 .irq_mask_ack = iomd_irq_mask_ack,
0155 .irq_mask = iomd_irq_mask,
0156 .irq_unmask = iomd_irq_unmask,
0157 };
0158
0159 static struct irq_chip iomd_chip_noclr = {
0160 .irq_mask = iomd_irq_mask,
0161 .irq_unmask = iomd_irq_unmask,
0162 };
0163
0164 extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
0165
0166 void __init rpc_init_irq(void)
0167 {
0168 unsigned int irq, clr, set;
0169
0170 iomd_writeb(0, IOMD_IRQMASKA);
0171 iomd_writeb(0, IOMD_IRQMASKB);
0172 iomd_writeb(0, IOMD_FIQMASK);
0173 iomd_writeb(0, IOMD_DMAMASK);
0174
0175 set_fiq_handler(&rpc_default_fiq_start,
0176 &rpc_default_fiq_end - &rpc_default_fiq_start);
0177
0178 set_handle_irq(iomd_handle_irq);
0179
0180 for (irq = 0; irq < NR_IRQS; irq++) {
0181 clr = IRQ_NOREQUEST;
0182 set = 0;
0183
0184 if (irq <= 6 || (irq >= 9 && irq <= 15))
0185 clr |= IRQ_NOPROBE;
0186
0187 if (irq == 21 || (irq >= 16 && irq <= 19) ||
0188 irq == IRQ_KEYBOARDTX)
0189 set |= IRQ_NOAUTOEN;
0190
0191 switch (irq) {
0192 case 0 ... 7:
0193 irq_set_chip_and_handler(irq, &iomd_chip_clr,
0194 handle_level_irq);
0195 irq_modify_status(irq, clr, set);
0196 iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATA,
0197 BIT(irq));
0198 break;
0199
0200 case 8 ... 15:
0201 irq_set_chip_and_handler(irq, &iomd_chip_noclr,
0202 handle_level_irq);
0203 irq_modify_status(irq, clr, set);
0204 iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATB,
0205 BIT(irq - 8));
0206 break;
0207
0208 case 16 ... 21:
0209 irq_set_chip_and_handler(irq, &iomd_chip_noclr,
0210 handle_level_irq);
0211 irq_modify_status(irq, clr, set);
0212 iomd_set_base_mask(irq, IOMD_BASE + IOMD_DMASTAT,
0213 BIT(irq - 16));
0214 break;
0215
0216 case 64 ... 71:
0217 irq_set_chip(irq, &iomd_chip_noclr);
0218 irq_modify_status(irq, clr, set);
0219 iomd_set_base_mask(irq, IOMD_BASE + IOMD_FIQSTAT,
0220 BIT(irq - 64));
0221 break;
0222 }
0223 }
0224
0225 init_FIQ(FIQ_START);
0226 }