// SPDX-License-Identifier: GPL-2.0-only1/*2* Copyright (C) 2011-12 Synopsys, Inc. (www.synopsys.com)3*/45#include <linux/interrupt.h>6#include <linux/module.h>7#include <linux/of.h>8#include <linux/irqdomain.h>9#include <linux/irqchip.h>10#include <asm/irq.h>1112#define NR_CPU_IRQS 32 /* number of irq lines coming in */13#define TIMER0_IRQ 3 /* Fixed by ISA */1415/*16* Early Hardware specific Interrupt setup17* -Platform independent, needed for each CPU (not foldable into init_IRQ)18* -Called very early (start_kernel -> setup_arch -> setup_processor)19*20* what it does ?21* -Optionally, setup the High priority Interrupts as Level 2 IRQs22*/23void arc_init_IRQ(void)24{25unsigned int level_mask = 0, i;2627/* Is timer high priority Interrupt (Level2 in ARCompact jargon) */28level_mask |= IS_ENABLED(CONFIG_ARC_COMPACT_IRQ_LEVELS) << TIMER0_IRQ;2930/*31* Write to register, even if no LV2 IRQs configured to reset it32* in case bootloader had mucked with it33*/34write_aux_reg(AUX_IRQ_LEV, level_mask);3536if (level_mask)37pr_info("Level-2 interrupts bitset %x\n", level_mask);3839/*40* Disable all IRQ lines so faulty external hardware won't41* trigger interrupt that kernel is not ready to handle.42*/43for (i = TIMER0_IRQ; i < NR_CPU_IRQS; i++) {44unsigned int ienb;4546ienb = read_aux_reg(AUX_IENABLE);47ienb &= ~(1 << i);48write_aux_reg(AUX_IENABLE, ienb);49}50}5152/*53* ARC700 core includes a simple on-chip intc supporting54* -per IRQ enable/disable55* -2 levels of interrupts (high/low)56* -all interrupts being level triggered57*58* To reduce platform code, we assume all IRQs directly hooked-up into intc.59* Platforms with external intc, hence cascaded IRQs, are free to over-ride60* below, per IRQ.61*/6263static void arc_irq_mask(struct irq_data *data)64{65unsigned int ienb;6667ienb = read_aux_reg(AUX_IENABLE);68ienb &= ~(1 << data->hwirq);69write_aux_reg(AUX_IENABLE, ienb);70}7172static void arc_irq_unmask(struct irq_data *data)73{74unsigned int ienb;7576ienb = read_aux_reg(AUX_IENABLE);77ienb |= (1 << data->hwirq);78write_aux_reg(AUX_IENABLE, ienb);79}8081static struct irq_chip onchip_intc = {82.name = "ARC In-core Intc",83.irq_mask = arc_irq_mask,84.irq_unmask = arc_irq_unmask,85};8687static int arc_intc_domain_map(struct irq_domain *d, unsigned int irq,88irq_hw_number_t hw)89{90switch (hw) {91case TIMER0_IRQ:92irq_set_percpu_devid(irq);93irq_set_chip_and_handler(irq, &onchip_intc, handle_percpu_irq);94break;95default:96irq_set_chip_and_handler(irq, &onchip_intc, handle_level_irq);97}98return 0;99}100101static const struct irq_domain_ops arc_intc_domain_ops = {102.xlate = irq_domain_xlate_onecell,103.map = arc_intc_domain_map,104};105106static int __init107init_onchip_IRQ(struct device_node *intc, struct device_node *parent)108{109struct irq_domain *root_domain;110111if (parent)112panic("DeviceTree incore intc not a root irq controller\n");113114root_domain = irq_domain_create_linear(of_fwnode_handle(intc),115NR_CPU_IRQS,116&arc_intc_domain_ops, NULL);117if (!root_domain)118panic("root irq domain not avail\n");119120/*121* Needed for primary domain lookup to succeed122* This is a primary irqchip, and can never have a parent123*/124irq_set_default_domain(root_domain);125126return 0;127}128129IRQCHIP_DECLARE(arc_intc, "snps,arc700-intc", init_onchip_IRQ);130131/*132* arch_local_irq_enable - Enable interrupts.133*134* 1. Explicitly called to re-enable interrupts135* 2. Implicitly called from spin_unlock_irq, write_unlock_irq etc136* which maybe in hard ISR itself137*138* Semantics of this function change depending on where it is called from:139*140* -If called from hard-ISR, it must not invert interrupt priorities141* e.g. suppose TIMER is high priority (Level 2) IRQ142* Time hard-ISR, timer_interrupt( ) calls spin_unlock_irq several times.143* Here local_irq_enable( ) shd not re-enable lower priority interrupts144* -If called from soft-ISR, it must re-enable all interrupts145* soft ISR are low priority jobs which can be very slow, thus all IRQs146* must be enabled while they run.147* Now hardware context wise we may still be in L2 ISR (not done rtie)148* still we must re-enable both L1 and L2 IRQs149* Another twist is prev scenario with flow being150* L1 ISR ==> interrupted by L2 ISR ==> L2 soft ISR151* here we must not re-enable Ll as prev Ll Interrupt's h/w context will get152* over-written (this is deficiency in ARC700 Interrupt mechanism)153*/154155#ifdef CONFIG_ARC_COMPACT_IRQ_LEVELS /* Complex version for 2 IRQ levels */156157void arch_local_irq_enable(void)158{159unsigned long flags = arch_local_save_flags();160161if (flags & STATUS_A2_MASK)162flags |= STATUS_E2_MASK;163else if (flags & STATUS_A1_MASK)164flags |= STATUS_E1_MASK;165166arch_local_irq_restore(flags);167}168169EXPORT_SYMBOL(arch_local_irq_enable);170#endif171172173