xref: /openbmc/linux/arch/arm/mach-mv78xx0/irq.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1*0fdebc5eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2794d15b2SStanislav Samsonov /*
3794d15b2SStanislav Samsonov  * arch/arm/mach-mv78xx0/irq.c
4794d15b2SStanislav Samsonov  *
5794d15b2SStanislav Samsonov  * MV78xx0 IRQ handling.
6794d15b2SStanislav Samsonov  */
72f8163baSRussell King #include <linux/gpio.h>
8794d15b2SStanislav Samsonov #include <linux/kernel.h>
9b95a13d7SLennert Buytenhek #include <linux/irq.h>
10383b9961SThomas Petazzoni #include <linux/io.h>
11b8cd337cSArnd Bergmann #include <asm/exception.h>
12ce91574cSRob Herring #include <plat/orion-gpio.h>
136f088f1dSLennert Buytenhek #include <plat/irq.h>
144c811b99SArnd Bergmann #include "bridge-regs.h"
15794d15b2SStanislav Samsonov #include "common.h"
16794d15b2SStanislav Samsonov 
17278b45b0SAndrew Lunn static int __initdata gpio0_irqs[4] = {
18278b45b0SAndrew Lunn 	IRQ_MV78XX0_GPIO_0_7,
19278b45b0SAndrew Lunn 	IRQ_MV78XX0_GPIO_8_15,
20278b45b0SAndrew Lunn 	IRQ_MV78XX0_GPIO_16_23,
21278b45b0SAndrew Lunn 	IRQ_MV78XX0_GPIO_24_31,
22278b45b0SAndrew Lunn };
23b95a13d7SLennert Buytenhek 
24b8cd337cSArnd Bergmann static void __iomem *mv78xx0_irq_base = IRQ_VIRT_BASE;
25b8cd337cSArnd Bergmann 
26b8cd337cSArnd Bergmann static asmlinkage void
mv78xx0_legacy_handle_irq(struct pt_regs * regs)27b8cd337cSArnd Bergmann __exception_irq_entry mv78xx0_legacy_handle_irq(struct pt_regs *regs)
28b8cd337cSArnd Bergmann {
29b8cd337cSArnd Bergmann 	u32 stat;
30b8cd337cSArnd Bergmann 
31b8cd337cSArnd Bergmann 	stat = readl_relaxed(mv78xx0_irq_base + IRQ_CAUSE_LOW_OFF);
32b8cd337cSArnd Bergmann 	stat &= readl_relaxed(mv78xx0_irq_base + IRQ_MASK_LOW_OFF);
33b8cd337cSArnd Bergmann 	if (stat) {
34b8cd337cSArnd Bergmann 		unsigned int hwirq = __fls(stat);
35b8cd337cSArnd Bergmann 		handle_IRQ(hwirq, regs);
36b8cd337cSArnd Bergmann 		return;
37b8cd337cSArnd Bergmann 	}
38b8cd337cSArnd Bergmann 	stat = readl_relaxed(mv78xx0_irq_base + IRQ_CAUSE_HIGH_OFF);
39b8cd337cSArnd Bergmann 	stat &= readl_relaxed(mv78xx0_irq_base + IRQ_MASK_HIGH_OFF);
40b8cd337cSArnd Bergmann 	if (stat) {
41b8cd337cSArnd Bergmann 		unsigned int hwirq = 32 + __fls(stat);
42b8cd337cSArnd Bergmann 		handle_IRQ(hwirq, regs);
43b8cd337cSArnd Bergmann 		return;
44b8cd337cSArnd Bergmann 	}
45b8cd337cSArnd Bergmann 	stat = readl_relaxed(mv78xx0_irq_base + IRQ_CAUSE_ERR_OFF);
46b8cd337cSArnd Bergmann 	stat &= readl_relaxed(mv78xx0_irq_base + IRQ_MASK_ERR_OFF);
47b8cd337cSArnd Bergmann 	if (stat) {
48b8cd337cSArnd Bergmann 		unsigned int hwirq = 64 + __fls(stat);
49b8cd337cSArnd Bergmann 		handle_IRQ(hwirq, regs);
50b8cd337cSArnd Bergmann 		return;
51b8cd337cSArnd Bergmann 	}
52b8cd337cSArnd Bergmann }
53b8cd337cSArnd Bergmann 
mv78xx0_init_irq(void)54794d15b2SStanislav Samsonov void __init mv78xx0_init_irq(void)
55794d15b2SStanislav Samsonov {
56383b9961SThomas Petazzoni 	orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
57383b9961SThomas Petazzoni 	orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
58383b9961SThomas Petazzoni 	orion_irq_init(64, IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF);
59b95a13d7SLennert Buytenhek 
60b8cd337cSArnd Bergmann 	set_handle_irq(mv78xx0_legacy_handle_irq);
61b8cd337cSArnd Bergmann 
62b95a13d7SLennert Buytenhek 	/*
639eac6d0aSLennert Buytenhek 	 * Initialize gpiolib for GPIOs 0-31.  (The GPIO interrupt mask
649eac6d0aSLennert Buytenhek 	 * registers for core #1 are at an offset of 0x18 from those of
659eac6d0aSLennert Buytenhek 	 * core #0.)
66b95a13d7SLennert Buytenhek 	 */
67bba14b32SAndy Shevchenko 	orion_gpio_init(0, 32, GPIO_VIRT_BASE, mv78xx0_core_index() ? 0x18 : 0,
68278b45b0SAndrew Lunn 			IRQ_MV78XX0_GPIO_START, gpio0_irqs);
69794d15b2SStanislav Samsonov }
70