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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Platform information definitions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * Copied from arch/ppc/syslib/cpm2_pic.c with minor subsequent updates
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * to make in work in arch/powerpc/. Original (c) belongs to Dan Malek.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * Author:  Vitaly Bordug <vbordug@ru.mvista.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * 1999-2001 (c) Dan Malek <dan@embeddedalley.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * 2006 (c) MontaVista Software, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * This file is licensed under the terms of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  * version 2. This program is licensed "as is" without any warranty of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * kind, whether express or implied.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) /* The CPM2 internal interrupt controller.  It is usually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * the only interrupt controller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * There are two 32-bit registers (high/low) for up to 64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * possible interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * Now, the fun starts.....Interrupt Numbers DO NOT MAP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * in a simple arithmetic fashion to mask or pending registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  * That is, interrupt 4 does not map to bit position 4.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25)  * We create two tables, indexed by vector number, to indicate
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)  * which register to use and which bit in the register to use.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <linux/stddef.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) #include <asm/immap_cpm2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) #include <asm/mpc8260.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) #include <asm/prom.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #include <asm/fs_pd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #include "cpm2_pic.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) /* External IRQS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) #define CPM2_IRQ_EXT1		19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) #define CPM2_IRQ_EXT7		25
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) /* Port C IRQS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) #define CPM2_IRQ_PORTC15	48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) #define CPM2_IRQ_PORTC0		63
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) static intctl_cpm2_t __iomem *cpm2_intctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) static struct irq_domain *cpm2_pic_host;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) static unsigned long ppc_cached_irq_mask[2]; /* 2 32-bit registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static const u_char irq_to_siureg[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 	0, 0, 0, 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	0, 0, 0, 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 	1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 	1, 1, 1, 1, 1, 1, 1, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 	0, 0, 0, 0, 0, 0, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 	0, 0, 0, 0, 0, 0, 0, 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) /* bit numbers do not match the docs, these are precomputed so the bit for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67)  * a given irq is (1 << irq_to_siubit[irq]) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) static const u_char irq_to_siubit[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	 0, 15, 14, 13, 12, 11, 10,  9,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	 8,  7,  6,  5,  4,  3,  2,  1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	 2,  1,  0, 14, 13, 12, 11, 10,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	 9,  8,  7,  6,  5,  4,  3,  0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	31, 30, 29, 28, 27, 26, 25, 24,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 	23, 22, 21, 20, 19, 18, 17, 16,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 	16, 17, 18, 19, 20, 21, 22, 23,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 	24, 25, 26, 27, 28, 29, 30, 31,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) static void cpm2_mask_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	int	bit, word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	unsigned int irq_nr = irqd_to_hwirq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	bit = irq_to_siubit[irq_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	word = irq_to_siureg[irq_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	ppc_cached_irq_mask[word] &= ~(1 << bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) static void cpm2_unmask_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 	int	bit, word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 	unsigned int irq_nr = irqd_to_hwirq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	bit = irq_to_siubit[irq_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	word = irq_to_siureg[irq_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	ppc_cached_irq_mask[word] |= 1 << bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) static void cpm2_ack(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 	int	bit, word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	unsigned int irq_nr = irqd_to_hwirq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	bit = irq_to_siubit[irq_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	word = irq_to_siureg[irq_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 	out_be32(&cpm2_intctl->ic_sipnrh + word, 1 << bit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) static void cpm2_end_irq(struct irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	int	bit, word;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	unsigned int irq_nr = irqd_to_hwirq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	bit = irq_to_siubit[irq_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	word = irq_to_siureg[irq_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	ppc_cached_irq_mask[word] |= 1 << bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	 * Work around large numbers of spurious IRQs on PowerPC 82xx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	 * systems.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 	mb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 	unsigned int src = irqd_to_hwirq(d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	unsigned int vold, vnew, edibit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	/* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	 * IRQ_TYPE_EDGE_BOTH (default).  All others are IRQ_TYPE_EDGE_FALLING
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	 * or IRQ_TYPE_LEVEL_LOW (default)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		if (flow_type == IRQ_TYPE_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 			flow_type = IRQ_TYPE_EDGE_BOTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 		if (flow_type != IRQ_TYPE_EDGE_BOTH &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 		    flow_type != IRQ_TYPE_EDGE_FALLING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 			goto err_sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 		if (flow_type == IRQ_TYPE_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			flow_type = IRQ_TYPE_LEVEL_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_LEVEL_HIGH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 			goto err_sense;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	irqd_set_trigger_type(d, flow_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	if (flow_type & IRQ_TYPE_LEVEL_LOW)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 		irq_set_handler_locked(d, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		irq_set_handler_locked(d, handle_edge_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	/* internal IRQ senses are LEVEL_LOW
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	 * EXT IRQ and Port C IRQ senses are programmable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	if (src >= CPM2_IRQ_EXT1 && src <= CPM2_IRQ_EXT7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 			edibit = (14 - (src - CPM2_IRQ_EXT1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 			edibit = (31 - (CPM2_IRQ_PORTC0 - src));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			return (flow_type & IRQ_TYPE_LEVEL_LOW) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 				IRQ_SET_MASK_OK_NOCOPY : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	vold = in_be32(&cpm2_intctl->ic_siexr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if ((flow_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_FALLING)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		vnew = vold | (1 << edibit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		vnew = vold & ~(1 << edibit);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	if (vold != vnew)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		out_be32(&cpm2_intctl->ic_siexr, vnew);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 	return IRQ_SET_MASK_OK_NOCOPY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) err_sense:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 	pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static struct irq_chip cpm2_pic = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	.name = "CPM2 SIU",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	.irq_mask = cpm2_mask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 	.irq_unmask = cpm2_unmask_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	.irq_ack = cpm2_ack,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	.irq_eoi = cpm2_end_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	.irq_set_type = cpm2_set_irq_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	.flags = IRQCHIP_EOI_IF_HANDLED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) unsigned int cpm2_get_irq(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	int irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	unsigned long bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)        /* For CPM2, read the SIVEC register and shift the bits down
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)          * to get the irq number.         */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)         bits = in_be32(&cpm2_intctl->ic_sivec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)         irq = bits >> 26;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 	if (irq == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		return(-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 	return irq_linear_revmap(cpm2_pic_host, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) static int cpm2_pic_host_map(struct irq_domain *h, unsigned int virq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			  irq_hw_number_t hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	irq_set_status_flags(virq, IRQ_LEVEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 	irq_set_chip_and_handler(virq, &cpm2_pic, handle_level_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) static const struct irq_domain_ops cpm2_pic_host_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	.map = cpm2_pic_host_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	.xlate = irq_domain_xlate_onetwocell,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) void cpm2_pic_init(struct device_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 	cpm2_intctl = cpm2_map(im_intctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 	/* Clear the CPM IRQ controller, in case it has any bits set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	 * from the bootloader
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 	/* Mask out everything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 	out_be32(&cpm2_intctl->ic_simrh, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	out_be32(&cpm2_intctl->ic_simrl, 0x00000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 	wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	/* Ack everything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 	out_be32(&cpm2_intctl->ic_sipnrh, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 	out_be32(&cpm2_intctl->ic_sipnrl, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 	wmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 	/* Dummy read of the vector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 	i = in_be32(&cpm2_intctl->ic_sivec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 	rmb();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 	/* Initialize the default interrupt mapping priorities,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 	 * in case the boot rom changed something on us.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	out_be16(&cpm2_intctl->ic_sicr, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	out_be32(&cpm2_intctl->ic_scprrh, 0x05309770);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	out_be32(&cpm2_intctl->ic_scprrl, 0x05309770);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 	/* create a legacy host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 	cpm2_pic_host = irq_domain_add_linear(node, 64, &cpm2_pic_host_ops, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 	if (cpm2_pic_host == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		printk(KERN_ERR "CPM2 PIC: failed to allocate irq host!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }