18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * linux/arch/arm/kernel/irq.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1992 Linus Torvalds 68c2ecf20Sopenharmony_ci * Modifications for ARM processor Copyright (C) 1995-2000 Russell King. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Support for Dynamic Tick Timer Copyright (C) 2004-2005 Nokia Corporation. 98c2ecf20Sopenharmony_ci * Dynamic Tick Timer written by Tony Lindgren <tony@atomide.com> and 108c2ecf20Sopenharmony_ci * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>. 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * This file contains the code used by various IRQ handling routines: 138c2ecf20Sopenharmony_ci * asking for different IRQ's should be done through these routines 148c2ecf20Sopenharmony_ci * instead of just grabbing them. Thus setups with different IRQ numbers 158c2ecf20Sopenharmony_ci * shouldn't result in any weird surprises, and installing new handlers 168c2ecf20Sopenharmony_ci * should be easier. 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * IRQ's are in fact implemented a bit like signal handlers for the kernel. 198c2ecf20Sopenharmony_ci * Naturally it's not a 1:1 relation, but there are similarities. 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_ci#include <linux/signal.h> 228c2ecf20Sopenharmony_ci#include <linux/ioport.h> 238c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 248c2ecf20Sopenharmony_ci#include <linux/irq.h> 258c2ecf20Sopenharmony_ci#include <linux/irqchip.h> 268c2ecf20Sopenharmony_ci#include <linux/random.h> 278c2ecf20Sopenharmony_ci#include <linux/smp.h> 288c2ecf20Sopenharmony_ci#include <linux/init.h> 298c2ecf20Sopenharmony_ci#include <linux/seq_file.h> 308c2ecf20Sopenharmony_ci#include <linux/errno.h> 318c2ecf20Sopenharmony_ci#include <linux/list.h> 328c2ecf20Sopenharmony_ci#include <linux/kallsyms.h> 338c2ecf20Sopenharmony_ci#include <linux/proc_fs.h> 348c2ecf20Sopenharmony_ci#include <linux/export.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include <asm/hardware/cache-l2x0.h> 378c2ecf20Sopenharmony_ci#include <asm/hardware/cache-uniphier.h> 388c2ecf20Sopenharmony_ci#include <asm/outercache.h> 398c2ecf20Sopenharmony_ci#include <asm/exception.h> 408c2ecf20Sopenharmony_ci#include <asm/mach/arch.h> 418c2ecf20Sopenharmony_ci#include <asm/mach/irq.h> 428c2ecf20Sopenharmony_ci#include <asm/mach/time.h> 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ciunsigned long irq_err_count; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ciint arch_show_interrupts(struct seq_file *p, int prec) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci#ifdef CONFIG_FIQ 498c2ecf20Sopenharmony_ci show_fiq_list(p, prec); 508c2ecf20Sopenharmony_ci#endif 518c2ecf20Sopenharmony_ci#ifdef CONFIG_SMP 528c2ecf20Sopenharmony_ci show_ipi_list(p, prec); 538c2ecf20Sopenharmony_ci#endif 548c2ecf20Sopenharmony_ci seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count); 558c2ecf20Sopenharmony_ci return 0; 568c2ecf20Sopenharmony_ci} 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/* 598c2ecf20Sopenharmony_ci * handle_IRQ handles all hardware IRQ's. Decoded IRQs should 608c2ecf20Sopenharmony_ci * not come via this function. Instead, they should provide their 618c2ecf20Sopenharmony_ci * own 'handler'. Used by platform code implementing C-based 1st 628c2ecf20Sopenharmony_ci * level decoding. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_civoid handle_IRQ(unsigned int irq, struct pt_regs *regs) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci __handle_domain_irq(NULL, irq, false, regs); 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci/* 708c2ecf20Sopenharmony_ci * asm_do_IRQ is the interface to be used from assembly code. 718c2ecf20Sopenharmony_ci */ 728c2ecf20Sopenharmony_ciasmlinkage void __exception_irq_entry 738c2ecf20Sopenharmony_ciasm_do_IRQ(unsigned int irq, struct pt_regs *regs) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci handle_IRQ(irq, regs); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_civoid __init init_IRQ(void) 798c2ecf20Sopenharmony_ci{ 808c2ecf20Sopenharmony_ci int ret; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_OF) && !machine_desc->init_irq) 838c2ecf20Sopenharmony_ci irqchip_init(); 848c2ecf20Sopenharmony_ci else 858c2ecf20Sopenharmony_ci machine_desc->init_irq(); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_OF) && IS_ENABLED(CONFIG_CACHE_L2X0) && 888c2ecf20Sopenharmony_ci (machine_desc->l2c_aux_mask || machine_desc->l2c_aux_val)) { 898c2ecf20Sopenharmony_ci if (!outer_cache.write_sec) 908c2ecf20Sopenharmony_ci outer_cache.write_sec = machine_desc->l2c_write_sec; 918c2ecf20Sopenharmony_ci ret = l2x0_of_init(machine_desc->l2c_aux_val, 928c2ecf20Sopenharmony_ci machine_desc->l2c_aux_mask); 938c2ecf20Sopenharmony_ci if (ret && ret != -ENODEV) 948c2ecf20Sopenharmony_ci pr_err("L2C: failed to init: %d\n", ret); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci uniphier_cache_init(); 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci#ifdef CONFIG_SPARSE_IRQ 1018c2ecf20Sopenharmony_ciint __init arch_probe_nr_irqs(void) 1028c2ecf20Sopenharmony_ci{ 1038c2ecf20Sopenharmony_ci nr_irqs = machine_desc->nr_irqs ? machine_desc->nr_irqs : NR_IRQS; 1048c2ecf20Sopenharmony_ci return nr_irqs; 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci#endif 107