Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * This file is subject to the terms and conditions of the GNU General Public
0003  * License.  See the file "COPYING" in the main directory of this archive
0004  * for more details.
0005  *
0006  * Code to handle x86 style IRQs plus some generic interrupt stuff.
0007  *
0008  * Copyright (C) 1992 Linus Torvalds
0009  * Copyright (C) 1994 - 2000 Ralf Baechle
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  * This is the 'legacy' 8259A Programmable Interrupt Controller,
0028  * present in the majority of PC/AT boxes.
0029  * plus some generic x86 specific things if generic specifics makes
0030  * any sense at all.
0031  * this file should become arch/i386/kernel/irq.c when the old irq.c
0032  * moves to arch independent land
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  * 8259A PIC functions to handle ISA devices:
0053  */
0054 
0055 void i8259_set_poll(int (*poll)(void))
0056 {
0057     i8259_poll = poll;
0058 }
0059 
0060 /*
0061  * This contains the irq mask for both 8259A irq controllers,
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  * This function assumes to be called rarely. Switching between
0107  * 8259A registers is slow.
0108  * This has to be protected by the irq controller spinlock
0109  * before being called.
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); /* ISR register */
0118         value = inb(PIC_MASTER_CMD) & irqmask;
0119         outb(0x0A, PIC_MASTER_CMD); /* back to the IRR register */
0120         return value;
0121     }
0122     outb(0x0B, PIC_SLAVE_CMD);  /* ISR register */
0123     value = inb(PIC_SLAVE_CMD) & (irqmask >> 8);
0124     outb(0x0A, PIC_SLAVE_CMD);  /* back to the IRR register */
0125     return value;
0126 }
0127 
0128 /*
0129  * Careful! The 8259A is a fragile beast, it pretty
0130  * much _has_ to be done exactly like this (mask it
0131  * first, _then_ send the EOI, and the order of EOI
0132  * to the two 8259s is important!
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      * Lightweight spurious IRQ detection. We do not want
0143      * to overdo spurious IRQ handling - it's usually a sign
0144      * of hardware problems, so we only do the checks we can
0145      * do without slowing down good hardware unnecessarily.
0146      *
0147      * Note that IRQ7 and IRQ15 (the two spurious IRQs
0148      * usually resulting from the 8259A-1|2 PICs) occur
0149      * even if the IRQ is masked in the 8259A. Thus we
0150      * can check spurious 8259A IRQs without doing the
0151      * quite slow i8259A_irq_real() call for every IRQ.
0152      * This does not cover 100% of spurious interrupts,
0153      * but should be enough to warn the user that there
0154      * is something bad going on ...
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); /* DUMMY - (do we need this?) */
0163         outb(cached_slave_mask, PIC_SLAVE_IMR);
0164         outb(0x60+(irq&7), PIC_SLAVE_CMD);/* 'Specific EOI' to slave */
0165         outb(0x60+PIC_CASCADE_IR, PIC_MASTER_CMD); /* 'Specific EOI' to master-IRQ2 */
0166     } else {
0167         inb(PIC_MASTER_IMR);    /* DUMMY - (do we need this?) */
0168         outb(cached_master_mask, PIC_MASTER_IMR);
0169         outb(0x60+irq, PIC_MASTER_CMD); /* 'Specific EOI to master */
0170     }
0171     raw_spin_unlock_irqrestore(&i8259A_lock, flags);
0172     return;
0173 
0174 spurious_8259A_irq:
0175     /*
0176      * this is the slow path - should happen rarely.
0177      */
0178     if (i8259A_irq_real(irq))
0179         /*
0180          * oops, the IRQ _is_ in service according to the
0181          * 8259A - not spurious, go handle it.
0182          */
0183         goto handle_real_irq;
0184 
0185     {
0186         static int spurious_irq_mask;
0187         /*
0188          * At this point we can be sure the IRQ is spurious,
0189          * lets ACK and report it. [once per IRQ]
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          * Theoretically we do not have to handle this IRQ,
0198          * but in Linux this does not cause problems and is
0199          * simpler for us.
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     /* Put the i8259A into a quiescent state that
0214      * the kernel initialization code can get it
0215      * out of.
0216      */
0217     if (i8259A_auto_eoi >= 0) {
0218         outb(0xff, PIC_MASTER_IMR); /* mask all of 8259A-1 */
0219         outb(0xff, PIC_SLAVE_IMR);  /* mask all of 8259A-2 */
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); /* mask all of 8259A-1 */
0237     outb(0xff, PIC_SLAVE_IMR);  /* mask all of 8259A-2 */
0238 
0239     /*
0240      * outb_p - this has to work on a wide range of PC hardware.
0241      */
0242     outb_p(0x11, PIC_MASTER_CMD);   /* ICW1: select 8259A-1 init */
0243     outb_p(I8259A_IRQ_BASE + 0, PIC_MASTER_IMR);    /* ICW2: 8259A-1 IR0 mapped to I8259A_IRQ_BASE + 0x00 */
0244     outb_p(1U << PIC_CASCADE_IR, PIC_MASTER_IMR);   /* 8259A-1 (the master) has a slave on IR2 */
0245     if (auto_eoi)   /* master does Auto EOI */
0246         outb_p(MASTER_ICW4_DEFAULT | PIC_ICW4_AEOI, PIC_MASTER_IMR);
0247     else        /* master expects normal EOI */
0248         outb_p(MASTER_ICW4_DEFAULT, PIC_MASTER_IMR);
0249 
0250     outb_p(0x11, PIC_SLAVE_CMD);    /* ICW1: select 8259A-2 init */
0251     outb_p(I8259A_IRQ_BASE + 8, PIC_SLAVE_IMR); /* ICW2: 8259A-2 IR0 mapped to I8259A_IRQ_BASE + 0x08 */
0252     outb_p(PIC_CASCADE_IR, PIC_SLAVE_IMR);  /* 8259A-2 is a slave on master's IR2 */
0253     outb_p(SLAVE_ICW4_DEFAULT, PIC_SLAVE_IMR); /* (slave's support for AEOI in flat mode is to be investigated) */
0254     if (auto_eoi)
0255         /*
0256          * In AEOI mode we just have to mask the interrupt
0257          * when acking.
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);        /* wait for 8259A to initialize */
0264 
0265     outb(cached_master_mask, PIC_MASTER_IMR); /* restore master IRQ mask */
0266     outb(cached_slave_mask, PIC_SLAVE_IMR);   /* restore slave IRQ mask */
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  * On systems with i8259-style interrupt controllers we assume for
0300  * driver compatibility reasons interrupts 0 - 15 to be the i8259
0301  * interrupts even if the hardware uses a different interrupt numbering.
0302  */
0303 struct irq_domain * __init __init_i8259_irqs(struct device_node *node)
0304 {
0305     /*
0306      * PIC_CASCADE_IR is cascade interrupt to second interrupt controller
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);