Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  linux/arch/arm/mach-footbridge/irq.c
0004  *
0005  *  Copyright (C) 1996-2000 Russell King
0006  *
0007  *  Changelog:
0008  *   22-Aug-1998 RMK    Restructured IRQ routines
0009  *   03-Sep-1998 PJB    Merged CATS support
0010  *   20-Jan-1998 RMK    Started merge of EBSA286, CATS and NetWinder
0011  *   26-Jan-1999 PJB    Don't use IACK on CATS
0012  *   16-Mar-1999 RMK    Added autodetect of ISA PICs
0013  */
0014 #include <linux/ioport.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/list.h>
0017 #include <linux/init.h>
0018 #include <linux/io.h>
0019 #include <linux/spinlock.h>
0020 
0021 #include <asm/mach/irq.h>
0022 
0023 #include <mach/hardware.h>
0024 #include <asm/hardware/dec21285.h>
0025 #include <asm/irq.h>
0026 #include <asm/mach-types.h>
0027 
0028 #include "common.h"
0029 
0030 static void isa_mask_pic_lo_irq(struct irq_data *d)
0031 {
0032     unsigned int mask = 1 << (d->irq & 7);
0033 
0034     outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
0035 }
0036 
0037 static void isa_ack_pic_lo_irq(struct irq_data *d)
0038 {
0039     unsigned int mask = 1 << (d->irq & 7);
0040 
0041     outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
0042     outb(0x20, PIC_LO);
0043 }
0044 
0045 static void isa_unmask_pic_lo_irq(struct irq_data *d)
0046 {
0047     unsigned int mask = 1 << (d->irq & 7);
0048 
0049     outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
0050 }
0051 
0052 static struct irq_chip isa_lo_chip = {
0053     .irq_ack    = isa_ack_pic_lo_irq,
0054     .irq_mask   = isa_mask_pic_lo_irq,
0055     .irq_unmask = isa_unmask_pic_lo_irq,
0056 };
0057 
0058 static void isa_mask_pic_hi_irq(struct irq_data *d)
0059 {
0060     unsigned int mask = 1 << (d->irq & 7);
0061 
0062     outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
0063 }
0064 
0065 static void isa_ack_pic_hi_irq(struct irq_data *d)
0066 {
0067     unsigned int mask = 1 << (d->irq & 7);
0068 
0069     outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
0070     outb(0x62, PIC_LO);
0071     outb(0x20, PIC_HI);
0072 }
0073 
0074 static void isa_unmask_pic_hi_irq(struct irq_data *d)
0075 {
0076     unsigned int mask = 1 << (d->irq & 7);
0077 
0078     outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
0079 }
0080 
0081 static struct irq_chip isa_hi_chip = {
0082     .irq_ack    = isa_ack_pic_hi_irq,
0083     .irq_mask   = isa_mask_pic_hi_irq,
0084     .irq_unmask = isa_unmask_pic_hi_irq,
0085 };
0086 
0087 static void isa_irq_handler(struct irq_desc *desc)
0088 {
0089     unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE;
0090 
0091     if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) {
0092         do_bad_IRQ(desc);
0093         return;
0094     }
0095 
0096     generic_handle_irq(isa_irq);
0097 }
0098 
0099 static struct resource pic1_resource = {
0100     .name   = "pic1",
0101     .start  = 0x20,
0102     .end    = 0x3f,
0103 };
0104 
0105 static struct resource pic2_resource = {
0106     .name   = "pic2",
0107     .start  = 0xa0,
0108     .end    = 0xbf,
0109 };
0110 
0111 void __init isa_init_irq(unsigned int host_irq)
0112 {
0113     unsigned int irq;
0114 
0115     /*
0116      * Setup, and then probe for an ISA PIC
0117      * If the PIC is not there, then we
0118      * ignore the PIC.
0119      */
0120     outb(0x11, PIC_LO);
0121     outb(_ISA_IRQ(0), PIC_MASK_LO); /* IRQ number       */
0122     outb(0x04, PIC_MASK_LO);    /* Slave on Ch2     */
0123     outb(0x01, PIC_MASK_LO);    /* x86          */
0124     outb(0xf5, PIC_MASK_LO);    /* pattern: 11110101    */
0125 
0126     outb(0x11, PIC_HI);
0127     outb(_ISA_IRQ(8), PIC_MASK_HI); /* IRQ number       */
0128     outb(0x02, PIC_MASK_HI);    /* Slave on Ch1     */
0129     outb(0x01, PIC_MASK_HI);    /* x86          */
0130     outb(0xfa, PIC_MASK_HI);    /* pattern: 11111010    */
0131 
0132     outb(0x0b, PIC_LO);
0133     outb(0x0b, PIC_HI);
0134 
0135     if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) {
0136         outb(0xff, PIC_MASK_LO);/* mask all IRQs    */
0137         outb(0xff, PIC_MASK_HI);/* mask all IRQs    */
0138     } else {
0139         printk(KERN_INFO "IRQ: ISA PIC not found\n");
0140         host_irq = (unsigned int)-1;
0141     }
0142 
0143     if (host_irq != (unsigned int)-1) {
0144         for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
0145             irq_set_chip_and_handler(irq, &isa_lo_chip,
0146                          handle_level_irq);
0147             irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
0148         }
0149 
0150         for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
0151             irq_set_chip_and_handler(irq, &isa_hi_chip,
0152                          handle_level_irq);
0153             irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
0154         }
0155 
0156         request_resource(&ioport_resource, &pic1_resource);
0157         request_resource(&ioport_resource, &pic2_resource);
0158 
0159         irq = IRQ_ISA_CASCADE;
0160         if (request_irq(irq, no_action, 0, "cascade", NULL))
0161             pr_err("Failed to request irq %u (cascade)\n", irq);
0162 
0163         irq_set_chained_handler(host_irq, isa_irq_handler);
0164 
0165         /*
0166          * On the NetWinder, don't automatically
0167          * enable ISA IRQ11 when it is requested.
0168          * There appears to be a missing pull-up
0169          * resistor on this line.
0170          */
0171         if (machine_is_netwinder())
0172             irq_modify_status(_ISA_IRQ(11),
0173                 IRQ_NOREQUEST | IRQ_NOPROBE, IRQ_NOAUTOEN);
0174     }
0175 }
0176 
0177