^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/arch/arm/mach-footbridge/irq.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 1996-2000 Russell King
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Changelog:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * 22-Aug-1998 RMK Restructured IRQ routines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * 03-Sep-1998 PJB Merged CATS support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * 26-Jan-1999 PJB Don't use IACK on CATS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * 16-Mar-1999 RMK Added autodetect of ISA PICs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/mach/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <mach/hardware.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/hardware/dec21285.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <asm/mach-types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "common.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) static void isa_mask_pic_lo_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) unsigned int mask = 1 << (d->irq & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static void isa_ack_pic_lo_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) unsigned int mask = 1 << (d->irq & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) outb(0x20, PIC_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static void isa_unmask_pic_lo_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned int mask = 1 << (d->irq & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) static struct irq_chip isa_lo_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) .irq_ack = isa_ack_pic_lo_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) .irq_mask = isa_mask_pic_lo_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) .irq_unmask = isa_unmask_pic_lo_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static void isa_mask_pic_hi_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) unsigned int mask = 1 << (d->irq & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static void isa_ack_pic_hi_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) unsigned int mask = 1 << (d->irq & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) outb(0x62, PIC_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) outb(0x20, PIC_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) static void isa_unmask_pic_hi_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned int mask = 1 << (d->irq & 7);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static struct irq_chip isa_hi_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) .irq_ack = isa_ack_pic_hi_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .irq_mask = isa_mask_pic_hi_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) .irq_unmask = isa_unmask_pic_hi_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static void isa_irq_handler(struct irq_desc *desc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) do_bad_IRQ(desc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) generic_handle_irq(isa_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static struct resource pic1_resource = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) .name = "pic1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .start = 0x20,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .end = 0x3f,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) static struct resource pic2_resource = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) .name = "pic2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) .start = 0xa0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) .end = 0xbf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) void __init isa_init_irq(unsigned int host_irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) unsigned int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * Setup, and then probe for an ISA PIC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * If the PIC is not there, then we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * ignore the PIC.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) outb(0x11, PIC_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) outb(_ISA_IRQ(0), PIC_MASK_LO); /* IRQ number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) outb(0x04, PIC_MASK_LO); /* Slave on Ch2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) outb(0x01, PIC_MASK_LO); /* x86 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) outb(0xf5, PIC_MASK_LO); /* pattern: 11110101 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) outb(0x11, PIC_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) outb(_ISA_IRQ(8), PIC_MASK_HI); /* IRQ number */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) outb(0x02, PIC_MASK_HI); /* Slave on Ch1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) outb(0x01, PIC_MASK_HI); /* x86 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) outb(0xfa, PIC_MASK_HI); /* pattern: 11111010 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) outb(0x0b, PIC_LO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) outb(0x0b, PIC_HI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) outb(0xff, PIC_MASK_LO);/* mask all IRQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) outb(0xff, PIC_MASK_HI);/* mask all IRQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) printk(KERN_INFO "IRQ: ISA PIC not found\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) host_irq = (unsigned int)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (host_irq != (unsigned int)-1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) irq_set_chip_and_handler(irq, &isa_lo_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) irq_set_chip_and_handler(irq, &isa_hi_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) request_resource(&ioport_resource, &pic1_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) request_resource(&ioport_resource, &pic2_resource);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) irq = IRQ_ISA_CASCADE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (request_irq(irq, no_action, 0, "cascade", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) pr_err("Failed to request irq %u (cascade)\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) irq_set_chained_handler(host_irq, isa_irq_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * On the NetWinder, don't automatically
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * enable ISA IRQ11 when it is requested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * There appears to be a missing pull-up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * resistor on this line.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (machine_is_netwinder())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) irq_modify_status(_ISA_IRQ(11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) IRQ_NOREQUEST | IRQ_NOPROBE, IRQ_NOAUTOEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)