18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/arch/arm/mach-footbridge/irq.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1996-2000 Russell King 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Changelog: 88c2ecf20Sopenharmony_ci * 22-Aug-1998 RMK Restructured IRQ routines 98c2ecf20Sopenharmony_ci * 03-Sep-1998 PJB Merged CATS support 108c2ecf20Sopenharmony_ci * 20-Jan-1998 RMK Started merge of EBSA286, CATS and NetWinder 118c2ecf20Sopenharmony_ci * 26-Jan-1999 PJB Don't use IACK on CATS 128c2ecf20Sopenharmony_ci * 16-Mar-1999 RMK Added autodetect of ISA PICs 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci#include <linux/ioport.h> 158c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 168c2ecf20Sopenharmony_ci#include <linux/list.h> 178c2ecf20Sopenharmony_ci#include <linux/init.h> 188c2ecf20Sopenharmony_ci#include <linux/io.h> 198c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <asm/mach/irq.h> 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#include <mach/hardware.h> 248c2ecf20Sopenharmony_ci#include <asm/hardware/dec21285.h> 258c2ecf20Sopenharmony_ci#include <asm/irq.h> 268c2ecf20Sopenharmony_ci#include <asm/mach-types.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include "common.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic void isa_mask_pic_lo_irq(struct irq_data *d) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci unsigned int mask = 1 << (d->irq & 7); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO); 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic void isa_ack_pic_lo_irq(struct irq_data *d) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci unsigned int mask = 1 << (d->irq & 7); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO); 428c2ecf20Sopenharmony_ci outb(0x20, PIC_LO); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic void isa_unmask_pic_lo_irq(struct irq_data *d) 468c2ecf20Sopenharmony_ci{ 478c2ecf20Sopenharmony_ci unsigned int mask = 1 << (d->irq & 7); 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic struct irq_chip isa_lo_chip = { 538c2ecf20Sopenharmony_ci .irq_ack = isa_ack_pic_lo_irq, 548c2ecf20Sopenharmony_ci .irq_mask = isa_mask_pic_lo_irq, 558c2ecf20Sopenharmony_ci .irq_unmask = isa_unmask_pic_lo_irq, 568c2ecf20Sopenharmony_ci}; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic void isa_mask_pic_hi_irq(struct irq_data *d) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci unsigned int mask = 1 << (d->irq & 7); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI); 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic void isa_ack_pic_hi_irq(struct irq_data *d) 668c2ecf20Sopenharmony_ci{ 678c2ecf20Sopenharmony_ci unsigned int mask = 1 << (d->irq & 7); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI); 708c2ecf20Sopenharmony_ci outb(0x62, PIC_LO); 718c2ecf20Sopenharmony_ci outb(0x20, PIC_HI); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic void isa_unmask_pic_hi_irq(struct irq_data *d) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci unsigned int mask = 1 << (d->irq & 7); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic struct irq_chip isa_hi_chip = { 828c2ecf20Sopenharmony_ci .irq_ack = isa_ack_pic_hi_irq, 838c2ecf20Sopenharmony_ci .irq_mask = isa_mask_pic_hi_irq, 848c2ecf20Sopenharmony_ci .irq_unmask = isa_unmask_pic_hi_irq, 858c2ecf20Sopenharmony_ci}; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic void isa_irq_handler(struct irq_desc *desc) 888c2ecf20Sopenharmony_ci{ 898c2ecf20Sopenharmony_ci unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) { 928c2ecf20Sopenharmony_ci do_bad_IRQ(desc); 938c2ecf20Sopenharmony_ci return; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci generic_handle_irq(isa_irq); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic struct resource pic1_resource = { 1008c2ecf20Sopenharmony_ci .name = "pic1", 1018c2ecf20Sopenharmony_ci .start = 0x20, 1028c2ecf20Sopenharmony_ci .end = 0x3f, 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic struct resource pic2_resource = { 1068c2ecf20Sopenharmony_ci .name = "pic2", 1078c2ecf20Sopenharmony_ci .start = 0xa0, 1088c2ecf20Sopenharmony_ci .end = 0xbf, 1098c2ecf20Sopenharmony_ci}; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_civoid __init isa_init_irq(unsigned int host_irq) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci unsigned int irq; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci /* 1168c2ecf20Sopenharmony_ci * Setup, and then probe for an ISA PIC 1178c2ecf20Sopenharmony_ci * If the PIC is not there, then we 1188c2ecf20Sopenharmony_ci * ignore the PIC. 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_ci outb(0x11, PIC_LO); 1218c2ecf20Sopenharmony_ci outb(_ISA_IRQ(0), PIC_MASK_LO); /* IRQ number */ 1228c2ecf20Sopenharmony_ci outb(0x04, PIC_MASK_LO); /* Slave on Ch2 */ 1238c2ecf20Sopenharmony_ci outb(0x01, PIC_MASK_LO); /* x86 */ 1248c2ecf20Sopenharmony_ci outb(0xf5, PIC_MASK_LO); /* pattern: 11110101 */ 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci outb(0x11, PIC_HI); 1278c2ecf20Sopenharmony_ci outb(_ISA_IRQ(8), PIC_MASK_HI); /* IRQ number */ 1288c2ecf20Sopenharmony_ci outb(0x02, PIC_MASK_HI); /* Slave on Ch1 */ 1298c2ecf20Sopenharmony_ci outb(0x01, PIC_MASK_HI); /* x86 */ 1308c2ecf20Sopenharmony_ci outb(0xfa, PIC_MASK_HI); /* pattern: 11111010 */ 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci outb(0x0b, PIC_LO); 1338c2ecf20Sopenharmony_ci outb(0x0b, PIC_HI); 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) { 1368c2ecf20Sopenharmony_ci outb(0xff, PIC_MASK_LO);/* mask all IRQs */ 1378c2ecf20Sopenharmony_ci outb(0xff, PIC_MASK_HI);/* mask all IRQs */ 1388c2ecf20Sopenharmony_ci } else { 1398c2ecf20Sopenharmony_ci printk(KERN_INFO "IRQ: ISA PIC not found\n"); 1408c2ecf20Sopenharmony_ci host_irq = (unsigned int)-1; 1418c2ecf20Sopenharmony_ci } 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (host_irq != (unsigned int)-1) { 1448c2ecf20Sopenharmony_ci for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) { 1458c2ecf20Sopenharmony_ci irq_set_chip_and_handler(irq, &isa_lo_chip, 1468c2ecf20Sopenharmony_ci handle_level_irq); 1478c2ecf20Sopenharmony_ci irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) { 1518c2ecf20Sopenharmony_ci irq_set_chip_and_handler(irq, &isa_hi_chip, 1528c2ecf20Sopenharmony_ci handle_level_irq); 1538c2ecf20Sopenharmony_ci irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE); 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci request_resource(&ioport_resource, &pic1_resource); 1578c2ecf20Sopenharmony_ci request_resource(&ioport_resource, &pic2_resource); 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci irq = IRQ_ISA_CASCADE; 1608c2ecf20Sopenharmony_ci if (request_irq(irq, no_action, 0, "cascade", NULL)) 1618c2ecf20Sopenharmony_ci pr_err("Failed to request irq %u (cascade)\n", irq); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci irq_set_chained_handler(host_irq, isa_irq_handler); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci /* 1668c2ecf20Sopenharmony_ci * On the NetWinder, don't automatically 1678c2ecf20Sopenharmony_ci * enable ISA IRQ11 when it is requested. 1688c2ecf20Sopenharmony_ci * There appears to be a missing pull-up 1698c2ecf20Sopenharmony_ci * resistor on this line. 1708c2ecf20Sopenharmony_ci */ 1718c2ecf20Sopenharmony_ci if (machine_is_netwinder()) 1728c2ecf20Sopenharmony_ci irq_modify_status(_ISA_IRQ(11), 1738c2ecf20Sopenharmony_ci IRQ_NOREQUEST | IRQ_NOPROBE, IRQ_NOAUTOEN); 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci 178