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