Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *      linux/arch/alpha/kernel/irq_i8259.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * This is the 'legacy' 8259A Programmable Interrupt Controller,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * present in the majority of PC/AT boxes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  * Started hacking from linux-2.3.30pre6/arch/i386/kernel/i8259.c.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/cache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/irq.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) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "proto.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include "irq_impl.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) /* Note mask bit is true for DISABLED irqs.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) static unsigned int cached_irq_mask = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) static DEFINE_SPINLOCK(i8259_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) i8259_update_irq_hw(unsigned int irq, unsigned long mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	int port = 0x21;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	if (irq & 8) mask >>= 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	if (irq & 8) port = 0xA1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 	outb(mask, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) i8259a_enable_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) 	spin_lock(&i8259_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	i8259_update_irq_hw(d->irq, cached_irq_mask &= ~(1 << d->irq));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	spin_unlock(&i8259_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) static inline void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) __i8259a_disable_irq(unsigned int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	i8259_update_irq_hw(irq, cached_irq_mask |= 1 << irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) i8259a_disable_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	spin_lock(&i8259_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	__i8259a_disable_irq(d->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	spin_unlock(&i8259_irq_lock);
^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) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) i8259a_mask_and_ack_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	unsigned int irq = d->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	spin_lock(&i8259_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	__i8259a_disable_irq(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	/* Ack the interrupt making it the lowest priority.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (irq >= 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		outb(0xE0 | (irq - 8), 0xa0);   /* ack the slave */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		irq = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	outb(0xE0 | irq, 0x20);			/* ack the master */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	spin_unlock(&i8259_irq_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) struct irq_chip i8259a_irq_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	.name		= "XT-PIC",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 	.irq_unmask	= i8259a_enable_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 	.irq_mask	= i8259a_disable_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 	.irq_mask_ack	= i8259a_mask_and_ack_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) void __init
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) init_i8259a_irqs(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	long i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	outb(0xff, 0x21);	/* mask all of 8259A-1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	outb(0xff, 0xA1);	/* mask all of 8259A-2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	for (i = 0; i < 16; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 		irq_set_chip_and_handler(i, &i8259a_irq_type, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	if (request_irq(2, no_action, 0, "cascade", NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 		pr_err("Failed to request irq 2 (cascade)\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) }
^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) #if defined(CONFIG_ALPHA_GENERIC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) # define IACK_SC	alpha_mv.iack_sc
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #elif defined(CONFIG_ALPHA_APECS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) # define IACK_SC	APECS_IACK_SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) #elif defined(CONFIG_ALPHA_LCA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) # define IACK_SC	LCA_IACK_SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) #elif defined(CONFIG_ALPHA_CIA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) # define IACK_SC	CIA_IACK_SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) #elif defined(CONFIG_ALPHA_PYXIS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) # define IACK_SC	PYXIS_IACK_SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #elif defined(CONFIG_ALPHA_TITAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) # define IACK_SC	TITAN_IACK_SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) #elif defined(CONFIG_ALPHA_TSUNAMI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) # define IACK_SC	TSUNAMI_IACK_SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) #elif defined(CONFIG_ALPHA_IRONGATE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) # define IACK_SC        IRONGATE_IACK_SC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) /* Note that CONFIG_ALPHA_POLARIS is intentionally left out here, since
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)    sys_rx164 wants to use isa_no_iack_sc_device_interrupt for some reason.  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) #if defined(IACK_SC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) isa_device_interrupt(unsigned long vector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	 * Generate a PCI interrupt acknowledge cycle.  The PIC will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	 * respond with the interrupt vector of the highest priority
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	 * interrupt that is pending.  The PALcode sets up the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	 * interrupts vectors such that irq level L generates vector L.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	int j = *(vuip) IACK_SC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	j &= 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	handle_irq(j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) #if defined(CONFIG_ALPHA_GENERIC) || !defined(IACK_SC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) isa_no_iack_sc_device_interrupt(unsigned long vector)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	unsigned long pic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	 * It seems to me that the probability of two or more *device*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 	 * interrupts occurring at almost exactly the same time is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 	 * pretty low.  So why pay the price of checking for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	 * additional interrupts here if the common case can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 	 * handled so much easier?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	/* 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 	 *  The first read of gives you *all* interrupting lines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	 *  Therefore, read the mask register and and out those lines
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	 *  not enabled.  Note that some documentation has 21 and a1 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 	 *  write only.  This is not true.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	pic = inb(0x20) | (inb(0xA0) << 8);	/* read isr */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	pic &= 0xFFFB;				/* mask out cascade & hibits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	while (pic) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		int j = ffz(~pic);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 		pic &= pic - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		handle_irq(j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #endif