0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/delay.h>
0012 #include <linux/init.h>
0013 #include <linux/ioport.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/irqchip.h>
0016 #include <linux/irqdomain.h>
0017 #include <linux/kernel.h>
0018 #include <linux/of_irq.h>
0019 #include <linux/spinlock.h>
0020 #include <linux/syscore_ops.h>
0021 #include <linux/irq.h>
0022
0023 #include <asm/i8259.h>
0024 #include <asm/io.h>
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 static int i8259A_auto_eoi = -1;
0036 DEFINE_RAW_SPINLOCK(i8259A_lock);
0037 static void disable_8259A_irq(struct irq_data *d);
0038 static void enable_8259A_irq(struct irq_data *d);
0039 static void mask_and_ack_8259A(struct irq_data *d);
0040 static void init_8259A(int auto_eoi);
0041 static int (*i8259_poll)(void) = i8259_irq;
0042
0043 static struct irq_chip i8259A_chip = {
0044 .name = "XT-PIC",
0045 .irq_mask = disable_8259A_irq,
0046 .irq_disable = disable_8259A_irq,
0047 .irq_unmask = enable_8259A_irq,
0048 .irq_mask_ack = mask_and_ack_8259A,
0049 };
0050
0051
0052
0053
0054
0055 void i8259_set_poll(int (*poll)(void))
0056 {
0057 i8259_poll = poll;
0058 }
0059
0060
0061
0062
0063 static unsigned int cached_irq_mask = 0xffff;
0064
0065 #define cached_master_mask (cached_irq_mask)
0066 #define cached_slave_mask (cached_irq_mask >> 8)
0067
0068 static void disable_8259A_irq(struct irq_data *d)
0069 {
0070 unsigned int mask, irq = d->irq - I8259A_IRQ_BASE;
0071 unsigned long flags;
0072
0073 mask = 1 << irq;
0074 raw_spin_lock_irqsave(&i8259A_lock, flags);
0075 cached_irq_mask |= mask;
0076 if (irq & 8)
0077 outb(cached_slave_mask, PIC_SLAVE_IMR);
0078 else
0079 outb(cached_master_mask, PIC_MASTER_IMR);
0080 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0081 }
0082
0083 static void enable_8259A_irq(struct irq_data *d)
0084 {
0085 unsigned int mask, irq = d->irq - I8259A_IRQ_BASE;
0086 unsigned long flags;
0087
0088 mask = ~(1 << irq);
0089 raw_spin_lock_irqsave(&i8259A_lock, flags);
0090 cached_irq_mask &= mask;
0091 if (irq & 8)
0092 outb(cached_slave_mask, PIC_SLAVE_IMR);
0093 else
0094 outb(cached_master_mask, PIC_MASTER_IMR);
0095 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0096 }
0097
0098 void make_8259A_irq(unsigned int irq)
0099 {
0100 disable_irq_nosync(irq);
0101 irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
0102 enable_irq(irq);
0103 }
0104
0105
0106
0107
0108
0109
0110
0111 static inline int i8259A_irq_real(unsigned int irq)
0112 {
0113 int value;
0114 int irqmask = 1 << irq;
0115
0116 if (irq < 8) {
0117 outb(0x0B, PIC_MASTER_CMD);
0118 value = inb(PIC_MASTER_CMD) & irqmask;
0119 outb(0x0A, PIC_MASTER_CMD);
0120 return value;
0121 }
0122 outb(0x0B, PIC_SLAVE_CMD);
0123 value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
0124 outb(0x0A, PIC_SLAVE_CMD);
0125 return value;
0126 }
0127
0128
0129
0130
0131
0132
0133
0134 static void mask_and_ack_8259A(struct irq_data *d)
0135 {
0136 unsigned int irqmask, irq = d->irq - I8259A_IRQ_BASE;
0137 unsigned long flags;
0138
0139 irqmask = 1 << irq;
0140 raw_spin_lock_irqsave(&i8259A_lock, flags);
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156 if (cached_irq_mask & irqmask)
0157 goto spurious_8259A_irq;
0158 cached_irq_mask |= irqmask;
0159
0160 handle_real_irq:
0161 if (irq & 8) {
0162 inb(PIC_SLAVE_IMR);
0163 outb(cached_slave_mask, PIC_SLAVE_IMR);
0164 outb(0x60+(irq&7), PIC_SLAVE_CMD);
0165 outb(0x60+PIC_CASCADE_IR, PIC_MASTER_CMD);
0166 } else {
0167 inb(PIC_MASTER_IMR);
0168 outb(cached_master_mask, PIC_MASTER_IMR);
0169 outb(0x60+irq, PIC_MASTER_CMD);
0170 }
0171 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0172 return;
0173
0174 spurious_8259A_irq:
0175
0176
0177
0178 if (i8259A_irq_real(irq))
0179
0180
0181
0182
0183 goto handle_real_irq;
0184
0185 {
0186 static int spurious_irq_mask;
0187
0188
0189
0190
0191 if (!(spurious_irq_mask & irqmask)) {
0192 printk(KERN_DEBUG "spurious 8259A interrupt: IRQ%d.\n", irq);
0193 spurious_irq_mask |= irqmask;
0194 }
0195 atomic_inc(&irq_err_count);
0196
0197
0198
0199
0200
0201 goto handle_real_irq;
0202 }
0203 }
0204
0205 static void i8259A_resume(void)
0206 {
0207 if (i8259A_auto_eoi >= 0)
0208 init_8259A(i8259A_auto_eoi);
0209 }
0210
0211 static void i8259A_shutdown(void)
0212 {
0213
0214
0215
0216
0217 if (i8259A_auto_eoi >= 0) {
0218 outb(0xff, PIC_MASTER_IMR);
0219 outb(0xff, PIC_SLAVE_IMR);
0220 }
0221 }
0222
0223 static struct syscore_ops i8259_syscore_ops = {
0224 .resume = i8259A_resume,
0225 .shutdown = i8259A_shutdown,
0226 };
0227
0228 static void init_8259A(int auto_eoi)
0229 {
0230 unsigned long flags;
0231
0232 i8259A_auto_eoi = auto_eoi;
0233
0234 raw_spin_lock_irqsave(&i8259A_lock, flags);
0235
0236 outb(0xff, PIC_MASTER_IMR);
0237 outb(0xff, PIC_SLAVE_IMR);
0238
0239
0240
0241
0242 outb_p(0x11, PIC_MASTER_CMD);
0243 outb_p(I8259A_IRQ_BASE + 0, PIC_MASTER_IMR);
0244 outb_p(1U << PIC_CASCADE_IR, PIC_MASTER_IMR);
0245 if (auto_eoi)
0246 outb_p(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
0247 else
0248 outb_p(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
0249
0250 outb_p(0x11, PIC_SLAVE_CMD);
0251 outb_p(I8259A_IRQ_BASE + 8, PIC_SLAVE_IMR);
0252 outb_p(PIC_CASCADE_IR, PIC_SLAVE_IMR);
0253 outb_p(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR);
0254 if (auto_eoi)
0255
0256
0257
0258
0259 i8259A_chip.irq_mask_ack = disable_8259A_irq;
0260 else
0261 i8259A_chip.irq_mask_ack = mask_and_ack_8259A;
0262
0263 udelay(100);
0264
0265 outb(cached_master_mask, PIC_MASTER_IMR);
0266 outb(cached_slave_mask, PIC_SLAVE_IMR);
0267
0268 raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0269 }
0270
0271 static struct resource pic1_io_resource = {
0272 .name = "pic1",
0273 .start = PIC_MASTER_CMD,
0274 .end = PIC_MASTER_IMR,
0275 .flags = IORESOURCE_IO | IORESOURCE_BUSY
0276 };
0277
0278 static struct resource pic2_io_resource = {
0279 .name = "pic2",
0280 .start = PIC_SLAVE_CMD,
0281 .end = PIC_SLAVE_IMR,
0282 .flags = IORESOURCE_IO | IORESOURCE_BUSY
0283 };
0284
0285 static int i8259A_irq_domain_map(struct irq_domain *d, unsigned int virq,
0286 irq_hw_number_t hw)
0287 {
0288 irq_set_chip_and_handler(virq, &i8259A_chip, handle_level_irq);
0289 irq_set_probe(virq);
0290 return 0;
0291 }
0292
0293 static const struct irq_domain_ops i8259A_ops = {
0294 .map = i8259A_irq_domain_map,
0295 .xlate = irq_domain_xlate_onecell,
0296 };
0297
0298
0299
0300
0301
0302
0303 struct irq_domain * __init __init_i8259_irqs(struct device_node *node)
0304 {
0305
0306
0307
0308 int irq = I8259A_IRQ_BASE + PIC_CASCADE_IR;
0309 struct irq_domain *domain;
0310
0311 insert_resource(&ioport_resource, &pic1_io_resource);
0312 insert_resource(&ioport_resource, &pic2_io_resource);
0313
0314 init_8259A(0);
0315
0316 domain = irq_domain_add_legacy(node, 16, I8259A_IRQ_BASE, 0,
0317 &i8259A_ops, NULL);
0318 if (!domain)
0319 panic("Failed to add i8259 IRQ domain");
0320
0321 if (request_irq(irq, no_action, IRQF_NO_THREAD, "cascade", NULL))
0322 pr_err("Failed to register cascade interrupt\n");
0323 register_syscore_ops(&i8259_syscore_ops);
0324 return domain;
0325 }
0326
0327 void __init init_i8259_irqs(void)
0328 {
0329 __init_i8259_irqs(NULL);
0330 }
0331
0332 static void i8259_irq_dispatch(struct irq_desc *desc)
0333 {
0334 struct irq_domain *domain = irq_desc_get_handler_data(desc);
0335 int hwirq = i8259_poll();
0336
0337 if (hwirq < 0)
0338 return;
0339
0340 generic_handle_domain_irq(domain, hwirq);
0341 }
0342
0343 int __init i8259_of_init(struct device_node *node, struct device_node *parent)
0344 {
0345 struct irq_domain *domain;
0346 unsigned int parent_irq;
0347
0348 domain = __init_i8259_irqs(node);
0349
0350 parent_irq = irq_of_parse_and_map(node, 0);
0351 if (!parent_irq) {
0352 pr_err("Failed to map i8259 parent IRQ\n");
0353 irq_domain_remove(domain);
0354 return -ENODEV;
0355 }
0356
0357 irq_set_chained_handler_and_data(parent_irq, i8259_irq_dispatch,
0358 domain);
0359 return 0;
0360 }
0361 IRQCHIP_DECLARE(i8259, "intel,i8259", i8259_of_init);