18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * arch/arm/mach-mv78xx0/irq.c
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * MV78xx0 IRQ handling.
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * This file is licensed under the terms of the GNU General Public
78c2ecf20Sopenharmony_ci * License version 2.  This program is licensed "as is" without any
88c2ecf20Sopenharmony_ci * warranty of any kind, whether express or implied.
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci#include <linux/gpio.h>
118c2ecf20Sopenharmony_ci#include <linux/kernel.h>
128c2ecf20Sopenharmony_ci#include <linux/irq.h>
138c2ecf20Sopenharmony_ci#include <linux/io.h>
148c2ecf20Sopenharmony_ci#include <asm/exception.h>
158c2ecf20Sopenharmony_ci#include <plat/orion-gpio.h>
168c2ecf20Sopenharmony_ci#include <plat/irq.h>
178c2ecf20Sopenharmony_ci#include "bridge-regs.h"
188c2ecf20Sopenharmony_ci#include "common.h"
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_cistatic int __initdata gpio0_irqs[4] = {
218c2ecf20Sopenharmony_ci	IRQ_MV78XX0_GPIO_0_7,
228c2ecf20Sopenharmony_ci	IRQ_MV78XX0_GPIO_8_15,
238c2ecf20Sopenharmony_ci	IRQ_MV78XX0_GPIO_16_23,
248c2ecf20Sopenharmony_ci	IRQ_MV78XX0_GPIO_24_31,
258c2ecf20Sopenharmony_ci};
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic void __iomem *mv78xx0_irq_base = IRQ_VIRT_BASE;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cistatic asmlinkage void
308c2ecf20Sopenharmony_ci__exception_irq_entry mv78xx0_legacy_handle_irq(struct pt_regs *regs)
318c2ecf20Sopenharmony_ci{
328c2ecf20Sopenharmony_ci	u32 stat;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	stat = readl_relaxed(mv78xx0_irq_base + IRQ_CAUSE_LOW_OFF);
358c2ecf20Sopenharmony_ci	stat &= readl_relaxed(mv78xx0_irq_base + IRQ_MASK_LOW_OFF);
368c2ecf20Sopenharmony_ci	if (stat) {
378c2ecf20Sopenharmony_ci		unsigned int hwirq = __fls(stat);
388c2ecf20Sopenharmony_ci		handle_IRQ(hwirq, regs);
398c2ecf20Sopenharmony_ci		return;
408c2ecf20Sopenharmony_ci	}
418c2ecf20Sopenharmony_ci	stat = readl_relaxed(mv78xx0_irq_base + IRQ_CAUSE_HIGH_OFF);
428c2ecf20Sopenharmony_ci	stat &= readl_relaxed(mv78xx0_irq_base + IRQ_MASK_HIGH_OFF);
438c2ecf20Sopenharmony_ci	if (stat) {
448c2ecf20Sopenharmony_ci		unsigned int hwirq = 32 + __fls(stat);
458c2ecf20Sopenharmony_ci		handle_IRQ(hwirq, regs);
468c2ecf20Sopenharmony_ci		return;
478c2ecf20Sopenharmony_ci	}
488c2ecf20Sopenharmony_ci	stat = readl_relaxed(mv78xx0_irq_base + IRQ_CAUSE_ERR_OFF);
498c2ecf20Sopenharmony_ci	stat &= readl_relaxed(mv78xx0_irq_base + IRQ_MASK_ERR_OFF);
508c2ecf20Sopenharmony_ci	if (stat) {
518c2ecf20Sopenharmony_ci		unsigned int hwirq = 64 + __fls(stat);
528c2ecf20Sopenharmony_ci		handle_IRQ(hwirq, regs);
538c2ecf20Sopenharmony_ci		return;
548c2ecf20Sopenharmony_ci	}
558c2ecf20Sopenharmony_ci}
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_civoid __init mv78xx0_init_irq(void)
588c2ecf20Sopenharmony_ci{
598c2ecf20Sopenharmony_ci	orion_irq_init(0, IRQ_VIRT_BASE + IRQ_MASK_LOW_OFF);
608c2ecf20Sopenharmony_ci	orion_irq_init(32, IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF);
618c2ecf20Sopenharmony_ci	orion_irq_init(64, IRQ_VIRT_BASE + IRQ_MASK_ERR_OFF);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	set_handle_irq(mv78xx0_legacy_handle_irq);
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	/*
668c2ecf20Sopenharmony_ci	 * Initialize gpiolib for GPIOs 0-31.  (The GPIO interrupt mask
678c2ecf20Sopenharmony_ci	 * registers for core #1 are at an offset of 0x18 from those of
688c2ecf20Sopenharmony_ci	 * core #0.)
698c2ecf20Sopenharmony_ci	 */
708c2ecf20Sopenharmony_ci	orion_gpio_init(NULL, 0, 32, GPIO_VIRT_BASE,
718c2ecf20Sopenharmony_ci			mv78xx0_core_index() ? 0x18 : 0,
728c2ecf20Sopenharmony_ci			IRQ_MV78XX0_GPIO_START, gpio0_irqs);
738c2ecf20Sopenharmony_ci}
74