1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-or-later */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * include/asm-mips/i8259.h 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * i8259A interrupt definitions. 6*4882a593Smuzhiyun * 7*4882a593Smuzhiyun * Copyright (C) 2003 Maciej W. Rozycki 8*4882a593Smuzhiyun * Copyright (C) 2003 Ralf Baechle <ralf@linux-mips.org> 9*4882a593Smuzhiyun */ 10*4882a593Smuzhiyun #ifndef _ASM_I8259_H 11*4882a593Smuzhiyun #define _ASM_I8259_H 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun #include <linux/compiler.h> 14*4882a593Smuzhiyun #include <linux/spinlock.h> 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun #include <asm/io.h> 17*4882a593Smuzhiyun #include <irq.h> 18*4882a593Smuzhiyun 19*4882a593Smuzhiyun /* i8259A PIC registers */ 20*4882a593Smuzhiyun #define PIC_MASTER_CMD 0x20 21*4882a593Smuzhiyun #define PIC_MASTER_IMR 0x21 22*4882a593Smuzhiyun #define PIC_MASTER_ISR PIC_MASTER_CMD 23*4882a593Smuzhiyun #define PIC_MASTER_POLL PIC_MASTER_ISR 24*4882a593Smuzhiyun #define PIC_MASTER_OCW3 PIC_MASTER_ISR 25*4882a593Smuzhiyun #define PIC_SLAVE_CMD 0xa0 26*4882a593Smuzhiyun #define PIC_SLAVE_IMR 0xa1 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun /* i8259A PIC related value */ 29*4882a593Smuzhiyun #define PIC_CASCADE_IR 2 30*4882a593Smuzhiyun #define MASTER_ICW4_DEFAULT 0x01 31*4882a593Smuzhiyun #define SLAVE_ICW4_DEFAULT 0x01 32*4882a593Smuzhiyun #define PIC_ICW4_AEOI 2 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun extern raw_spinlock_t i8259A_lock; 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun extern void make_8259A_irq(unsigned int irq); 37*4882a593Smuzhiyun 38*4882a593Smuzhiyun extern void init_i8259_irqs(void); 39*4882a593Smuzhiyun extern struct irq_domain *__init_i8259_irqs(struct device_node *node); 40*4882a593Smuzhiyun 41*4882a593Smuzhiyun /** 42*4882a593Smuzhiyun * i8159_set_poll() - Override the i8259 polling function 43*4882a593Smuzhiyun * @poll: pointer to platform-specific polling function 44*4882a593Smuzhiyun * 45*4882a593Smuzhiyun * Call this to override the generic i8259 polling function, which directly 46*4882a593Smuzhiyun * accesses i8259 registers, with a platform specific one which may be faster 47*4882a593Smuzhiyun * in cases where hardware provides a more optimal means of polling for an 48*4882a593Smuzhiyun * interrupt. 49*4882a593Smuzhiyun */ 50*4882a593Smuzhiyun extern void i8259_set_poll(int (*poll)(void)); 51*4882a593Smuzhiyun 52*4882a593Smuzhiyun /* 53*4882a593Smuzhiyun * Do the traditional i8259 interrupt polling thing. This is for the few 54*4882a593Smuzhiyun * cases where no better interrupt acknowledge method is available and we 55*4882a593Smuzhiyun * absolutely must touch the i8259. 56*4882a593Smuzhiyun */ i8259_irq(void)57*4882a593Smuzhiyunstatic inline int i8259_irq(void) 58*4882a593Smuzhiyun { 59*4882a593Smuzhiyun int irq; 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun raw_spin_lock(&i8259A_lock); 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun /* Perform an interrupt acknowledge cycle on controller 1. */ 64*4882a593Smuzhiyun outb(0x0C, PIC_MASTER_CMD); /* prepare for poll */ 65*4882a593Smuzhiyun irq = inb(PIC_MASTER_CMD) & 7; 66*4882a593Smuzhiyun if (irq == PIC_CASCADE_IR) { 67*4882a593Smuzhiyun /* 68*4882a593Smuzhiyun * Interrupt is cascaded so perform interrupt 69*4882a593Smuzhiyun * acknowledge on controller 2. 70*4882a593Smuzhiyun */ 71*4882a593Smuzhiyun outb(0x0C, PIC_SLAVE_CMD); /* prepare for poll */ 72*4882a593Smuzhiyun irq = (inb(PIC_SLAVE_CMD) & 7) + 8; 73*4882a593Smuzhiyun } 74*4882a593Smuzhiyun 75*4882a593Smuzhiyun if (unlikely(irq == 7)) { 76*4882a593Smuzhiyun /* 77*4882a593Smuzhiyun * This may be a spurious interrupt. 78*4882a593Smuzhiyun * 79*4882a593Smuzhiyun * Read the interrupt status register (ISR). If the most 80*4882a593Smuzhiyun * significant bit is not set then there is no valid 81*4882a593Smuzhiyun * interrupt. 82*4882a593Smuzhiyun */ 83*4882a593Smuzhiyun outb(0x0B, PIC_MASTER_ISR); /* ISR register */ 84*4882a593Smuzhiyun if(~inb(PIC_MASTER_ISR) & 0x80) 85*4882a593Smuzhiyun irq = -1; 86*4882a593Smuzhiyun } 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun raw_spin_unlock(&i8259A_lock); 89*4882a593Smuzhiyun 90*4882a593Smuzhiyun return likely(irq >= 0) ? irq + I8259A_IRQ_BASE : irq; 91*4882a593Smuzhiyun } 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun #endif /* _ASM_I8259_H */ 94