xref: /linux/arch/arm/mach-footbridge/isa-irq.c (revision 5926e7e1)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds  *  linux/arch/arm/mach-footbridge/irq.c
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  *  Copyright (C) 1996-2000 Russell King
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  *  Changelog:
81da177e4SLinus Torvalds  *   22-Aug-1998 RMK	Restructured IRQ routines
91da177e4SLinus Torvalds  *   03-Sep-1998 PJB	Merged CATS support
101da177e4SLinus Torvalds  *   20-Jan-1998 RMK	Started merge of EBSA286, CATS and NetWinder
111da177e4SLinus Torvalds  *   26-Jan-1999 PJB	Don't use IACK on CATS
121da177e4SLinus Torvalds  *   16-Mar-1999 RMK	Added autodetect of ISA PICs
131da177e4SLinus Torvalds  */
141da177e4SLinus Torvalds #include <linux/ioport.h>
151da177e4SLinus Torvalds #include <linux/interrupt.h>
161da177e4SLinus Torvalds #include <linux/list.h>
171da177e4SLinus Torvalds #include <linux/init.h>
18fced80c7SRussell King #include <linux/io.h>
1970d13e08SRussell King #include <linux/spinlock.h>
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds #include <asm/mach/irq.h>
221da177e4SLinus Torvalds 
23a09e64fbSRussell King #include <mach/hardware.h>
241da177e4SLinus Torvalds #include <asm/hardware/dec21285.h>
251da177e4SLinus Torvalds #include <asm/irq.h>
261da177e4SLinus Torvalds #include <asm/mach-types.h>
271da177e4SLinus Torvalds 
2839ebfd3fSBen Dooks #include "common.h"
2939ebfd3fSBen Dooks 
isa_mask_pic_lo_irq(struct irq_data * d)30dc2caf6cSLennert Buytenhek static void isa_mask_pic_lo_irq(struct irq_data *d)
311da177e4SLinus Torvalds {
32dc2caf6cSLennert Buytenhek 	unsigned int mask = 1 << (d->irq & 7);
331da177e4SLinus Torvalds 
341da177e4SLinus Torvalds 	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
351da177e4SLinus Torvalds }
361da177e4SLinus Torvalds 
isa_ack_pic_lo_irq(struct irq_data * d)37dc2caf6cSLennert Buytenhek static void isa_ack_pic_lo_irq(struct irq_data *d)
381da177e4SLinus Torvalds {
39dc2caf6cSLennert Buytenhek 	unsigned int mask = 1 << (d->irq & 7);
401da177e4SLinus Torvalds 
411da177e4SLinus Torvalds 	outb(inb(PIC_MASK_LO) | mask, PIC_MASK_LO);
421da177e4SLinus Torvalds 	outb(0x20, PIC_LO);
431da177e4SLinus Torvalds }
441da177e4SLinus Torvalds 
isa_unmask_pic_lo_irq(struct irq_data * d)45dc2caf6cSLennert Buytenhek static void isa_unmask_pic_lo_irq(struct irq_data *d)
461da177e4SLinus Torvalds {
47dc2caf6cSLennert Buytenhek 	unsigned int mask = 1 << (d->irq & 7);
481da177e4SLinus Torvalds 
491da177e4SLinus Torvalds 	outb(inb(PIC_MASK_LO) & ~mask, PIC_MASK_LO);
501da177e4SLinus Torvalds }
511da177e4SLinus Torvalds 
5210dd5ce2SRussell King static struct irq_chip isa_lo_chip = {
53dc2caf6cSLennert Buytenhek 	.irq_ack	= isa_ack_pic_lo_irq,
54dc2caf6cSLennert Buytenhek 	.irq_mask	= isa_mask_pic_lo_irq,
55dc2caf6cSLennert Buytenhek 	.irq_unmask	= isa_unmask_pic_lo_irq,
561da177e4SLinus Torvalds };
571da177e4SLinus Torvalds 
isa_mask_pic_hi_irq(struct irq_data * d)58dc2caf6cSLennert Buytenhek static void isa_mask_pic_hi_irq(struct irq_data *d)
591da177e4SLinus Torvalds {
60dc2caf6cSLennert Buytenhek 	unsigned int mask = 1 << (d->irq & 7);
611da177e4SLinus Torvalds 
621da177e4SLinus Torvalds 	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
631da177e4SLinus Torvalds }
641da177e4SLinus Torvalds 
isa_ack_pic_hi_irq(struct irq_data * d)65dc2caf6cSLennert Buytenhek static void isa_ack_pic_hi_irq(struct irq_data *d)
661da177e4SLinus Torvalds {
67dc2caf6cSLennert Buytenhek 	unsigned int mask = 1 << (d->irq & 7);
681da177e4SLinus Torvalds 
691da177e4SLinus Torvalds 	outb(inb(PIC_MASK_HI) | mask, PIC_MASK_HI);
701da177e4SLinus Torvalds 	outb(0x62, PIC_LO);
711da177e4SLinus Torvalds 	outb(0x20, PIC_HI);
721da177e4SLinus Torvalds }
731da177e4SLinus Torvalds 
isa_unmask_pic_hi_irq(struct irq_data * d)74dc2caf6cSLennert Buytenhek static void isa_unmask_pic_hi_irq(struct irq_data *d)
751da177e4SLinus Torvalds {
76dc2caf6cSLennert Buytenhek 	unsigned int mask = 1 << (d->irq & 7);
771da177e4SLinus Torvalds 
781da177e4SLinus Torvalds 	outb(inb(PIC_MASK_HI) & ~mask, PIC_MASK_HI);
791da177e4SLinus Torvalds }
801da177e4SLinus Torvalds 
8110dd5ce2SRussell King static struct irq_chip isa_hi_chip = {
82dc2caf6cSLennert Buytenhek 	.irq_ack	= isa_ack_pic_hi_irq,
83dc2caf6cSLennert Buytenhek 	.irq_mask	= isa_mask_pic_hi_irq,
84dc2caf6cSLennert Buytenhek 	.irq_unmask	= isa_unmask_pic_hi_irq,
851da177e4SLinus Torvalds };
861da177e4SLinus Torvalds 
isa_irq_handler(struct irq_desc * desc)87bd0b9ac4SThomas Gleixner static void isa_irq_handler(struct irq_desc *desc)
881da177e4SLinus Torvalds {
891da177e4SLinus Torvalds 	unsigned int isa_irq = *(unsigned char *)PCIIACK_BASE;
901da177e4SLinus Torvalds 
911da177e4SLinus Torvalds 	if (isa_irq < _ISA_IRQ(0) || isa_irq >= _ISA_IRQ(16)) {
92bd0b9ac4SThomas Gleixner 		do_bad_IRQ(desc);
931da177e4SLinus Torvalds 		return;
941da177e4SLinus Torvalds 	}
951da177e4SLinus Torvalds 
96d8aa0251SDmitry Baryshkov 	generic_handle_irq(isa_irq);
971da177e4SLinus Torvalds }
981da177e4SLinus Torvalds 
99020732adSRussell King static struct resource pic1_resource = {
100020732adSRussell King 	.name	= "pic1",
101020732adSRussell King 	.start	= 0x20,
102020732adSRussell King 	.end	= 0x3f,
103020732adSRussell King };
104020732adSRussell King 
105020732adSRussell King static struct resource pic2_resource = {
106020732adSRussell King 	.name	= "pic2",
107020732adSRussell King 	.start	= 0xa0,
108020732adSRussell King 	.end	= 0xbf,
109020732adSRussell King };
1101da177e4SLinus Torvalds 
isa_init_irq(unsigned int host_irq)1111da177e4SLinus Torvalds void __init isa_init_irq(unsigned int host_irq)
1121da177e4SLinus Torvalds {
1131da177e4SLinus Torvalds 	unsigned int irq;
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds 	/*
1161da177e4SLinus Torvalds 	 * Setup, and then probe for an ISA PIC
1171da177e4SLinus Torvalds 	 * If the PIC is not there, then we
1181da177e4SLinus Torvalds 	 * ignore the PIC.
1191da177e4SLinus Torvalds 	 */
1201da177e4SLinus Torvalds 	outb(0x11, PIC_LO);
1211da177e4SLinus Torvalds 	outb(_ISA_IRQ(0), PIC_MASK_LO);	/* IRQ number		*/
1221da177e4SLinus Torvalds 	outb(0x04, PIC_MASK_LO);	/* Slave on Ch2		*/
1231da177e4SLinus Torvalds 	outb(0x01, PIC_MASK_LO);	/* x86			*/
1241da177e4SLinus Torvalds 	outb(0xf5, PIC_MASK_LO);	/* pattern: 11110101	*/
1251da177e4SLinus Torvalds 
1261da177e4SLinus Torvalds 	outb(0x11, PIC_HI);
1271da177e4SLinus Torvalds 	outb(_ISA_IRQ(8), PIC_MASK_HI);	/* IRQ number		*/
1281da177e4SLinus Torvalds 	outb(0x02, PIC_MASK_HI);	/* Slave on Ch1		*/
1291da177e4SLinus Torvalds 	outb(0x01, PIC_MASK_HI);	/* x86			*/
1301da177e4SLinus Torvalds 	outb(0xfa, PIC_MASK_HI);	/* pattern: 11111010	*/
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds 	outb(0x0b, PIC_LO);
1331da177e4SLinus Torvalds 	outb(0x0b, PIC_HI);
1341da177e4SLinus Torvalds 
1351da177e4SLinus Torvalds 	if (inb(PIC_MASK_LO) == 0xf5 && inb(PIC_MASK_HI) == 0xfa) {
1361da177e4SLinus Torvalds 		outb(0xff, PIC_MASK_LO);/* mask all IRQs	*/
1371da177e4SLinus Torvalds 		outb(0xff, PIC_MASK_HI);/* mask all IRQs	*/
1381da177e4SLinus Torvalds 	} else {
1391da177e4SLinus Torvalds 		printk(KERN_INFO "IRQ: ISA PIC not found\n");
1401da177e4SLinus Torvalds 		host_irq = (unsigned int)-1;
1411da177e4SLinus Torvalds 	}
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds 	if (host_irq != (unsigned int)-1) {
1441da177e4SLinus Torvalds 		for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
145f38c02f3SThomas Gleixner 			irq_set_chip_and_handler(irq, &isa_lo_chip,
146f38c02f3SThomas Gleixner 						 handle_level_irq);
147e8d36d5dSRob Herring 			irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
1481da177e4SLinus Torvalds 		}
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds 		for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
151f38c02f3SThomas Gleixner 			irq_set_chip_and_handler(irq, &isa_hi_chip,
152f38c02f3SThomas Gleixner 						 handle_level_irq);
153e8d36d5dSRob Herring 			irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
1541da177e4SLinus Torvalds 		}
1551da177e4SLinus Torvalds 
1561da177e4SLinus Torvalds 		request_resource(&ioport_resource, &pic1_resource);
1571da177e4SLinus Torvalds 		request_resource(&ioport_resource, &pic2_resource);
158*5926e7e1Safzal mohammed 
159*5926e7e1Safzal mohammed 		irq = IRQ_ISA_CASCADE;
160*5926e7e1Safzal mohammed 		if (request_irq(irq, no_action, 0, "cascade", NULL))
161*5926e7e1Safzal mohammed 			pr_err("Failed to request irq %u (cascade)\n", irq);
1621da177e4SLinus Torvalds 
1636845664aSThomas Gleixner 		irq_set_chained_handler(host_irq, isa_irq_handler);
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds 		/*
1661da177e4SLinus Torvalds 		 * On the NetWinder, don't automatically
1671da177e4SLinus Torvalds 		 * enable ISA IRQ11 when it is requested.
1681da177e4SLinus Torvalds 		 * There appears to be a missing pull-up
1691da177e4SLinus Torvalds 		 * resistor on this line.
1701da177e4SLinus Torvalds 		 */
1711da177e4SLinus Torvalds 		if (machine_is_netwinder())
172e8d36d5dSRob Herring 			irq_modify_status(_ISA_IRQ(11),
173e8d36d5dSRob Herring 				IRQ_NOREQUEST | IRQ_NOPROBE, IRQ_NOAUTOEN);
1741da177e4SLinus Torvalds 	}
1751da177e4SLinus Torvalds }
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds 
178