xref: /openbmc/linux/arch/arm/mach-rpc/irq.c (revision c1fe8d05)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds #include <linux/init.h>
31da177e4SLinus Torvalds #include <linux/list.h>
4fced80c7SRussell King #include <linux/io.h>
51da177e4SLinus Torvalds 
61da177e4SLinus Torvalds #include <asm/mach/irq.h>
71da177e4SLinus Torvalds #include <asm/hardware/iomd.h>
81da177e4SLinus Torvalds #include <asm/irq.h>
978cbaacaSRob Herring #include <asm/fiq.h>
101da177e4SLinus Torvalds 
1105002cf1SRussell King // These are offsets from the stat register for each IRQ bank
1205002cf1SRussell King #define STAT	0x00
1305002cf1SRussell King #define REQ	0x04
1405002cf1SRussell King #define CLR	0x04
1505002cf1SRussell King #define MASK	0x08
161da177e4SLinus Torvalds 
17*c1fe8d05SArnd Bergmann static const u8 irq_prio_h[256] = {
18*c1fe8d05SArnd Bergmann 	 0, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
19*c1fe8d05SArnd Bergmann 	12, 8, 9, 8,10,10,10,10,11,11,11,11,10,10,10,10,
20*c1fe8d05SArnd Bergmann 	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
21*c1fe8d05SArnd Bergmann 	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
22*c1fe8d05SArnd Bergmann 	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
23*c1fe8d05SArnd Bergmann 	14,14,14,14,10,10,10,10,11,11,11,11,10,10,10,10,
24*c1fe8d05SArnd Bergmann 	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
25*c1fe8d05SArnd Bergmann 	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
26*c1fe8d05SArnd Bergmann 	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
27*c1fe8d05SArnd Bergmann 	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
28*c1fe8d05SArnd Bergmann 	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
29*c1fe8d05SArnd Bergmann 	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
30*c1fe8d05SArnd Bergmann 	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
31*c1fe8d05SArnd Bergmann 	15,15,15,15,10,10,10,10,11,11,11,11,10,10,10,10,
32*c1fe8d05SArnd Bergmann 	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
33*c1fe8d05SArnd Bergmann 	13,13,13,13,10,10,10,10,11,11,11,11,10,10,10,10,
34*c1fe8d05SArnd Bergmann };
35*c1fe8d05SArnd Bergmann 
36*c1fe8d05SArnd Bergmann static const u8 irq_prio_d[256] = {
37*c1fe8d05SArnd Bergmann 	 0,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
38*c1fe8d05SArnd Bergmann 	20,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
39*c1fe8d05SArnd Bergmann 	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
40*c1fe8d05SArnd Bergmann 	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
41*c1fe8d05SArnd Bergmann 	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
42*c1fe8d05SArnd Bergmann 	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
43*c1fe8d05SArnd Bergmann 	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
44*c1fe8d05SArnd Bergmann 	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
45*c1fe8d05SArnd Bergmann 	23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
46*c1fe8d05SArnd Bergmann 	23,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
47*c1fe8d05SArnd Bergmann 	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
48*c1fe8d05SArnd Bergmann 	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
49*c1fe8d05SArnd Bergmann 	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
50*c1fe8d05SArnd Bergmann 	22,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
51*c1fe8d05SArnd Bergmann 	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
52*c1fe8d05SArnd Bergmann 	21,16,17,16,18,16,17,16,19,16,17,16,18,16,17,16,
53*c1fe8d05SArnd Bergmann };
54*c1fe8d05SArnd Bergmann 
55*c1fe8d05SArnd Bergmann static const u8 irq_prio_l[256] = {
56*c1fe8d05SArnd Bergmann 	 0, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
57*c1fe8d05SArnd Bergmann 	 4, 0, 1, 0, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
58*c1fe8d05SArnd Bergmann 	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
59*c1fe8d05SArnd Bergmann 	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
60*c1fe8d05SArnd Bergmann 	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
61*c1fe8d05SArnd Bergmann 	 6, 6, 6, 6, 6, 6, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3,
62*c1fe8d05SArnd Bergmann 	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
63*c1fe8d05SArnd Bergmann 	 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
64*c1fe8d05SArnd Bergmann 	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
65*c1fe8d05SArnd Bergmann 	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
66*c1fe8d05SArnd Bergmann 	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
67*c1fe8d05SArnd Bergmann 	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
68*c1fe8d05SArnd Bergmann 	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
69*c1fe8d05SArnd Bergmann 	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
70*c1fe8d05SArnd Bergmann 	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
71*c1fe8d05SArnd Bergmann 	 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
72*c1fe8d05SArnd Bergmann };
73*c1fe8d05SArnd Bergmann 
iomd_get_irq_nr(void)74*c1fe8d05SArnd Bergmann static int iomd_get_irq_nr(void)
75*c1fe8d05SArnd Bergmann {
76*c1fe8d05SArnd Bergmann 	int irq;
77*c1fe8d05SArnd Bergmann 	u8 reg;
78*c1fe8d05SArnd Bergmann 
79*c1fe8d05SArnd Bergmann 	/* get highest priority first */
80*c1fe8d05SArnd Bergmann 	reg = readb(IOC_BASE + IOMD_IRQREQB);
81*c1fe8d05SArnd Bergmann 	irq = irq_prio_h[reg];
82*c1fe8d05SArnd Bergmann 	if (irq)
83*c1fe8d05SArnd Bergmann 		return irq;
84*c1fe8d05SArnd Bergmann 
85*c1fe8d05SArnd Bergmann 	/* get DMA  */
86*c1fe8d05SArnd Bergmann 	reg = readb(IOC_BASE + IOMD_DMAREQ);
87*c1fe8d05SArnd Bergmann 	irq = irq_prio_d[reg];
88*c1fe8d05SArnd Bergmann 	if (irq)
89*c1fe8d05SArnd Bergmann 		return irq;
90*c1fe8d05SArnd Bergmann 
91*c1fe8d05SArnd Bergmann 	/* get low priority */
92*c1fe8d05SArnd Bergmann 	reg = readb(IOC_BASE + IOMD_IRQREQA);
93*c1fe8d05SArnd Bergmann 	irq = irq_prio_l[reg];
94*c1fe8d05SArnd Bergmann 	if (irq)
95*c1fe8d05SArnd Bergmann 		return irq;
96*c1fe8d05SArnd Bergmann 	return 0;
97*c1fe8d05SArnd Bergmann }
98*c1fe8d05SArnd Bergmann 
iomd_handle_irq(struct pt_regs * regs)99*c1fe8d05SArnd Bergmann static void iomd_handle_irq(struct pt_regs *regs)
100*c1fe8d05SArnd Bergmann {
101*c1fe8d05SArnd Bergmann 	int irq;
102*c1fe8d05SArnd Bergmann 
103*c1fe8d05SArnd Bergmann 	do {
104*c1fe8d05SArnd Bergmann 		irq = iomd_get_irq_nr();
105*c1fe8d05SArnd Bergmann 		if (irq)
106*c1fe8d05SArnd Bergmann 			generic_handle_irq(irq);
107*c1fe8d05SArnd Bergmann 	} while (irq);
108*c1fe8d05SArnd Bergmann }
109*c1fe8d05SArnd Bergmann 
iomd_get_base(struct irq_data * d)11005002cf1SRussell King static void __iomem *iomd_get_base(struct irq_data *d)
11105002cf1SRussell King {
11205002cf1SRussell King 	void *cd = irq_data_get_irq_chip_data(d);
11305002cf1SRussell King 
11405002cf1SRussell King 	return (void __iomem *)(unsigned long)cd;
1151da177e4SLinus Torvalds }
1161da177e4SLinus Torvalds 
iomd_set_base_mask(unsigned int irq,void __iomem * base,u32 mask)11705002cf1SRussell King static void iomd_set_base_mask(unsigned int irq, void __iomem *base, u32 mask)
1181da177e4SLinus Torvalds {
11905002cf1SRussell King 	struct irq_data *d = irq_get_irq_data(irq);
1201da177e4SLinus Torvalds 
12105002cf1SRussell King 	d->mask = mask;
12205002cf1SRussell King 	irq_set_chip_data(irq, (void *)(unsigned long)base);
1231da177e4SLinus Torvalds }
1241da177e4SLinus Torvalds 
iomd_irq_mask_ack(struct irq_data * d)12505002cf1SRussell King static void iomd_irq_mask_ack(struct irq_data *d)
1261da177e4SLinus Torvalds {
12705002cf1SRussell King 	void __iomem *base = iomd_get_base(d);
12805002cf1SRussell King 	unsigned int val, mask = d->mask;
1291da177e4SLinus Torvalds 
13005002cf1SRussell King 	val = readb(base + MASK);
13105002cf1SRussell King 	writeb(val & ~mask, base + MASK);
13205002cf1SRussell King 	writeb(mask, base + CLR);
1331da177e4SLinus Torvalds }
1341da177e4SLinus Torvalds 
iomd_irq_mask(struct irq_data * d)13505002cf1SRussell King static void iomd_irq_mask(struct irq_data *d)
13605002cf1SRussell King {
13705002cf1SRussell King 	void __iomem *base = iomd_get_base(d);
13805002cf1SRussell King 	unsigned int val, mask = d->mask;
13905002cf1SRussell King 
14005002cf1SRussell King 	val = readb(base + MASK);
14105002cf1SRussell King 	writeb(val & ~mask, base + MASK);
14205002cf1SRussell King }
14305002cf1SRussell King 
iomd_irq_unmask(struct irq_data * d)14405002cf1SRussell King static void iomd_irq_unmask(struct irq_data *d)
14505002cf1SRussell King {
14605002cf1SRussell King 	void __iomem *base = iomd_get_base(d);
14705002cf1SRussell King 	unsigned int val, mask = d->mask;
14805002cf1SRussell King 
14905002cf1SRussell King 	val = readb(base + MASK);
15005002cf1SRussell King 	writeb(val | mask, base + MASK);
15105002cf1SRussell King }
15205002cf1SRussell King 
15305002cf1SRussell King static struct irq_chip iomd_chip_clr = {
15405002cf1SRussell King 	.irq_mask_ack	= iomd_irq_mask_ack,
15505002cf1SRussell King 	.irq_mask	= iomd_irq_mask,
15605002cf1SRussell King 	.irq_unmask	= iomd_irq_unmask,
1571da177e4SLinus Torvalds };
1581da177e4SLinus Torvalds 
15905002cf1SRussell King static struct irq_chip iomd_chip_noclr = {
16005002cf1SRussell King 	.irq_mask	= iomd_irq_mask,
16105002cf1SRussell King 	.irq_unmask	= iomd_irq_unmask,
1621da177e4SLinus Torvalds };
1631da177e4SLinus Torvalds 
16478cbaacaSRob Herring extern unsigned char rpc_default_fiq_start, rpc_default_fiq_end;
16578cbaacaSRob Herring 
rpc_init_irq(void)1661da177e4SLinus Torvalds void __init rpc_init_irq(void)
1671da177e4SLinus Torvalds {
16863a0666bSRussell King 	unsigned int irq, clr, set;
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds 	iomd_writeb(0, IOMD_IRQMASKA);
1711da177e4SLinus Torvalds 	iomd_writeb(0, IOMD_IRQMASKB);
1721da177e4SLinus Torvalds 	iomd_writeb(0, IOMD_FIQMASK);
1731da177e4SLinus Torvalds 	iomd_writeb(0, IOMD_DMAMASK);
1741da177e4SLinus Torvalds 
17578cbaacaSRob Herring 	set_fiq_handler(&rpc_default_fiq_start,
17678cbaacaSRob Herring 		&rpc_default_fiq_end - &rpc_default_fiq_start);
17778cbaacaSRob Herring 
178*c1fe8d05SArnd Bergmann 	set_handle_irq(iomd_handle_irq);
179*c1fe8d05SArnd Bergmann 
1801da177e4SLinus Torvalds 	for (irq = 0; irq < NR_IRQS; irq++) {
181e8d36d5dSRob Herring 		clr = IRQ_NOREQUEST;
18263a0666bSRussell King 		set = 0;
1831da177e4SLinus Torvalds 
1841da177e4SLinus Torvalds 		if (irq <= 6 || (irq >= 9 && irq <= 15))
185e8d36d5dSRob Herring 			clr |= IRQ_NOPROBE;
1861da177e4SLinus Torvalds 
1871da177e4SLinus Torvalds 		if (irq == 21 || (irq >= 16 && irq <= 19) ||
1881da177e4SLinus Torvalds 		    irq == IRQ_KEYBOARDTX)
189e8d36d5dSRob Herring 			set |= IRQ_NOAUTOEN;
1901da177e4SLinus Torvalds 
1911da177e4SLinus Torvalds 		switch (irq) {
1921da177e4SLinus Torvalds 		case 0 ... 7:
19305002cf1SRussell King 			irq_set_chip_and_handler(irq, &iomd_chip_clr,
194f38c02f3SThomas Gleixner 						 handle_level_irq);
195e8d36d5dSRob Herring 			irq_modify_status(irq, clr, set);
19605002cf1SRussell King 			iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATA,
19705002cf1SRussell King 					   BIT(irq));
1981da177e4SLinus Torvalds 			break;
1991da177e4SLinus Torvalds 
2001da177e4SLinus Torvalds 		case 8 ... 15:
20105002cf1SRussell King 			irq_set_chip_and_handler(irq, &iomd_chip_noclr,
202f38c02f3SThomas Gleixner 						 handle_level_irq);
203e8d36d5dSRob Herring 			irq_modify_status(irq, clr, set);
20405002cf1SRussell King 			iomd_set_base_mask(irq, IOMD_BASE + IOMD_IRQSTATB,
20505002cf1SRussell King 					   BIT(irq - 8));
2061da177e4SLinus Torvalds 			break;
2071da177e4SLinus Torvalds 
2081da177e4SLinus Torvalds 		case 16 ... 21:
20905002cf1SRussell King 			irq_set_chip_and_handler(irq, &iomd_chip_noclr,
210f38c02f3SThomas Gleixner 						 handle_level_irq);
211e8d36d5dSRob Herring 			irq_modify_status(irq, clr, set);
21205002cf1SRussell King 			iomd_set_base_mask(irq, IOMD_BASE + IOMD_DMASTAT,
21305002cf1SRussell King 					   BIT(irq - 16));
2141da177e4SLinus Torvalds 			break;
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds 		case 64 ... 71:
21705002cf1SRussell King 			irq_set_chip(irq, &iomd_chip_noclr);
218e8d36d5dSRob Herring 			irq_modify_status(irq, clr, set);
21905002cf1SRussell King 			iomd_set_base_mask(irq, IOMD_BASE + IOMD_FIQSTAT,
22005002cf1SRussell King 					   BIT(irq - 64));
2211da177e4SLinus Torvalds 			break;
2221da177e4SLinus Torvalds 		}
2231da177e4SLinus Torvalds 	}
2241da177e4SLinus Torvalds 
225bc89663aSShawn Guo 	init_FIQ(FIQ_START);
2261da177e4SLinus Torvalds }
227