Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 /*
0003  *  include/asm-mips/i8259.h
0004  *
0005  *  i8259A interrupt definitions.
0006  *
0007  *  Copyright (C) 2003  Maciej W. Rozycki
0008  *  Copyright (C) 2003  Ralf Baechle <ralf@linux-mips.org>
0009  */
0010 #ifndef _ASM_I8259_H
0011 #define _ASM_I8259_H
0012 
0013 #include <linux/compiler.h>
0014 #include <linux/spinlock.h>
0015 
0016 #include <asm/io.h>
0017 #include <irq.h>
0018 
0019 /* i8259A PIC registers */
0020 #define PIC_MASTER_CMD      0x20
0021 #define PIC_MASTER_IMR      0x21
0022 #define PIC_MASTER_ISR      PIC_MASTER_CMD
0023 #define PIC_MASTER_POLL     PIC_MASTER_ISR
0024 #define PIC_MASTER_OCW3     PIC_MASTER_ISR
0025 #define PIC_SLAVE_CMD       0xa0
0026 #define PIC_SLAVE_IMR       0xa1
0027 
0028 /* i8259A PIC related value */
0029 #define PIC_CASCADE_IR      2
0030 #define MASTER_ICW4_DEFAULT 0x01
0031 #define SLAVE_ICW4_DEFAULT  0x01
0032 #define PIC_ICW4_AEOI       2
0033 
0034 extern raw_spinlock_t i8259A_lock;
0035 
0036 extern void make_8259A_irq(unsigned int irq);
0037 
0038 extern void init_i8259_irqs(void);
0039 extern struct irq_domain *__init_i8259_irqs(struct device_node *node);
0040 
0041 /**
0042  * i8159_set_poll() - Override the i8259 polling function
0043  * @poll: pointer to platform-specific polling function
0044  *
0045  * Call this to override the generic i8259 polling function, which directly
0046  * accesses i8259 registers, with a platform specific one which may be faster
0047  * in cases where hardware provides a more optimal means of polling for an
0048  * interrupt.
0049  */
0050 extern void i8259_set_poll(int (*poll)(void));
0051 
0052 /*
0053  * Do the traditional i8259 interrupt polling thing.  This is for the few
0054  * cases where no better interrupt acknowledge method is available and we
0055  * absolutely must touch the i8259.
0056  */
0057 static inline int i8259_irq(void)
0058 {
0059     int irq;
0060 
0061     raw_spin_lock(&i8259A_lock);
0062 
0063     /* Perform an interrupt acknowledge cycle on controller 1. */
0064     outb(0x0C, PIC_MASTER_CMD);     /* prepare for poll */
0065     irq = inb(PIC_MASTER_CMD) & 7;
0066     if (irq == PIC_CASCADE_IR) {
0067         /*
0068          * Interrupt is cascaded so perform interrupt
0069          * acknowledge on controller 2.
0070          */
0071         outb(0x0C, PIC_SLAVE_CMD);      /* prepare for poll */
0072         irq = (inb(PIC_SLAVE_CMD) & 7) + 8;
0073     }
0074 
0075     if (unlikely(irq == 7)) {
0076         /*
0077          * This may be a spurious interrupt.
0078          *
0079          * Read the interrupt status register (ISR). If the most
0080          * significant bit is not set then there is no valid
0081          * interrupt.
0082          */
0083         outb(0x0B, PIC_MASTER_ISR);     /* ISR register */
0084         if(~inb(PIC_MASTER_ISR) & 0x80)
0085             irq = -1;
0086     }
0087 
0088     raw_spin_unlock(&i8259A_lock);
0089 
0090     return likely(irq >= 0) ? irq + I8259A_IRQ_BASE : irq;
0091 }
0092 
0093 #endif /* _ASM_I8259_H */