Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: IRQ handling

This patch adds the support for IRQ handling. The actual interrupt
controller will be part of a separate patch (going into
drivers/irqchip/).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Tony Lindgren <tony@atomide.com>
Acked-by: Nicolas Pitre <nico@linaro.org>
Acked-by: Olof Johansson <olof@lixom.net>
Acked-by: Santosh Shilimkar <santosh.shilimkar@ti.com>

authored by

Marc Zyngier and committed by
Catalin Marinas
fb9bd7d6 58d0ba57

+230
+47
arch/arm64/include/asm/hardirq.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 + */ 16 + #ifndef __ASM_HARDIRQ_H 17 + #define __ASM_HARDIRQ_H 18 + 19 + #include <linux/cache.h> 20 + #include <linux/threads.h> 21 + #include <asm/irq.h> 22 + 23 + typedef struct { 24 + unsigned int __softirq_pending; 25 + } ____cacheline_aligned irq_cpustat_t; 26 + 27 + #include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */ 28 + 29 + #define __inc_irq_stat(cpu, member) __IRQ_STAT(cpu, member)++ 30 + #define __get_irq_stat(cpu, member) __IRQ_STAT(cpu, member) 31 + 32 + #ifdef CONFIG_SMP 33 + u64 smp_irq_stat_cpu(unsigned int cpu); 34 + #define arch_irq_stat_cpu smp_irq_stat_cpu 35 + #endif 36 + 37 + #define __ARCH_IRQ_EXIT_IRQS_DISABLED 1 38 + 39 + static inline void ack_bad_irq(unsigned int irq) 40 + { 41 + extern unsigned long irq_err_count; 42 + irq_err_count++; 43 + } 44 + 45 + extern void handle_IRQ(unsigned int, struct pt_regs *); 46 + 47 + #endif /* __ASM_HARDIRQ_H */
+8
arch/arm64/include/asm/irq.h
··· 1 + #ifndef __ASM_IRQ_H 2 + #define __ASM_IRQ_H 3 + 4 + #include <asm-generic/irq.h> 5 + 6 + extern void (*handle_arch_irq)(struct pt_regs *); 7 + 8 + #endif
+91
arch/arm64/include/asm/irqflags.h
··· 1 + /* 2 + * Copyright (C) 2012 ARM Ltd. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + * 13 + * You should have received a copy of the GNU General Public License 14 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 + */ 16 + #ifndef __ASM_IRQFLAGS_H 17 + #define __ASM_IRQFLAGS_H 18 + 19 + #ifdef __KERNEL__ 20 + 21 + #include <asm/ptrace.h> 22 + 23 + /* 24 + * CPU interrupt mask handling. 25 + */ 26 + static inline unsigned long arch_local_irq_save(void) 27 + { 28 + unsigned long flags; 29 + asm volatile( 30 + "mrs %0, daif // arch_local_irq_save\n" 31 + "msr daifset, #2" 32 + : "=r" (flags) 33 + : 34 + : "memory"); 35 + return flags; 36 + } 37 + 38 + static inline void arch_local_irq_enable(void) 39 + { 40 + asm volatile( 41 + "msr daifclr, #2 // arch_local_irq_enable" 42 + : 43 + : 44 + : "memory"); 45 + } 46 + 47 + static inline void arch_local_irq_disable(void) 48 + { 49 + asm volatile( 50 + "msr daifset, #2 // arch_local_irq_disable" 51 + : 52 + : 53 + : "memory"); 54 + } 55 + 56 + #define local_fiq_enable() asm("msr daifclr, #1" : : : "memory") 57 + #define local_fiq_disable() asm("msr daifset, #1" : : : "memory") 58 + 59 + /* 60 + * Save the current interrupt enable state. 61 + */ 62 + static inline unsigned long arch_local_save_flags(void) 63 + { 64 + unsigned long flags; 65 + asm volatile( 66 + "mrs %0, daif // arch_local_save_flags" 67 + : "=r" (flags) 68 + : 69 + : "memory"); 70 + return flags; 71 + } 72 + 73 + /* 74 + * restore saved IRQ state 75 + */ 76 + static inline void arch_local_irq_restore(unsigned long flags) 77 + { 78 + asm volatile( 79 + "msr daif, %0 // arch_local_irq_restore" 80 + : 81 + : "r" (flags) 82 + : "memory"); 83 + } 84 + 85 + static inline int arch_irqs_disabled_flags(unsigned long flags) 86 + { 87 + return flags & PSR_I_BIT; 88 + } 89 + 90 + #endif 91 + #endif
+84
arch/arm64/kernel/irq.c
··· 1 + /* 2 + * Based on arch/arm/kernel/irq.c 3 + * 4 + * Copyright (C) 1992 Linus Torvalds 5 + * Modifications for ARM processor Copyright (C) 1995-2000 Russell King. 6 + * Support for Dynamic Tick Timer Copyright (C) 2004-2005 Nokia Corporation. 7 + * Dynamic Tick Timer written by Tony Lindgren <tony@atomide.com> and 8 + * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>. 9 + * Copyright (C) 2012 ARM Ltd. 10 + * 11 + * This program is free software; you can redistribute it and/or modify 12 + * it under the terms of the GNU General Public License version 2 as 13 + * published by the Free Software Foundation. 14 + * 15 + * This program is distributed in the hope that it will be useful, 16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 + * GNU General Public License for more details. 19 + * 20 + * You should have received a copy of the GNU General Public License 21 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 22 + */ 23 + 24 + #include <linux/kernel_stat.h> 25 + #include <linux/irq.h> 26 + #include <linux/smp.h> 27 + #include <linux/init.h> 28 + #include <linux/of_irq.h> 29 + #include <linux/seq_file.h> 30 + #include <linux/ratelimit.h> 31 + 32 + unsigned long irq_err_count; 33 + 34 + int arch_show_interrupts(struct seq_file *p, int prec) 35 + { 36 + #ifdef CONFIG_SMP 37 + show_ipi_list(p, prec); 38 + #endif 39 + seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); 40 + return 0; 41 + } 42 + 43 + /* 44 + * handle_IRQ handles all hardware IRQ's. Decoded IRQs should 45 + * not come via this function. Instead, they should provide their 46 + * own 'handler'. Used by platform code implementing C-based 1st 47 + * level decoding. 48 + */ 49 + void handle_IRQ(unsigned int irq, struct pt_regs *regs) 50 + { 51 + struct pt_regs *old_regs = set_irq_regs(regs); 52 + 53 + irq_enter(); 54 + 55 + /* 56 + * Some hardware gives randomly wrong interrupts. Rather 57 + * than crashing, do something sensible. 58 + */ 59 + if (unlikely(irq >= nr_irqs)) { 60 + pr_warn_ratelimited("Bad IRQ%u\n", irq); 61 + ack_bad_irq(irq); 62 + } else { 63 + generic_handle_irq(irq); 64 + } 65 + 66 + irq_exit(); 67 + set_irq_regs(old_regs); 68 + } 69 + 70 + /* 71 + * Interrupt controllers supported by the kernel. 72 + */ 73 + static const struct of_device_id intctrl_of_match[] __initconst = { 74 + /* IRQ controllers { .compatible, .data } info to go here */ 75 + {} 76 + }; 77 + 78 + void __init init_IRQ(void) 79 + { 80 + of_irq_init(intctrl_of_match); 81 + 82 + if (!handle_arch_irq) 83 + panic("No interrupt controller found."); 84 + }