···42094209S: Maintained42104210T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core42114211F: kernel/irq/42124212+F: drivers/irqchip/4212421342134214IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)42144215M: Benjamin Herrenschmidt <benh@kernel.crashing.org>
-23
arch/arm/common/Kconfig
···11-config ARM_GIC22- bool33- select IRQ_DOMAIN44- select MULTI_IRQ_HANDLER55-66-config GIC_NON_BANKED77- bool88-99-config ARM_VIC1010- bool1111- select IRQ_DOMAIN1212- select MULTI_IRQ_HANDLER1313-1414-config ARM_VIC_NR1515- int1616- default 4 if ARCH_S5PV2101717- default 3 if ARCH_S5PC1001818- default 21919- depends on ARM_VIC2020- help2121- The maximum number of VICs available in the system, for2222- power management.2323-241config ICST252 bool263
-2
arch/arm/common/Makefile
···22# Makefile for the linux kernel.33#4455-obj-$(CONFIG_ARM_GIC) += gic.o66-obj-$(CONFIG_ARM_VIC) += vic.o75obj-$(CONFIG_ICST) += icst.o86obj-$(CONFIG_SA1111) += sa1111.o97obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
+36-23
arch/arm/common/gic.c
drivers/irqchip/irq-gic.c
···3838#include <linux/interrupt.h>3939#include <linux/percpu.h>4040#include <linux/slab.h>4141+#include <linux/irqchip/arm-gic.h>41424243#include <asm/irq.h>4344#include <asm/exception.h>4445#include <asm/smp_plat.h>4546#include <asm/mach/irq.h>4646-#include <asm/hardware/gic.h>4747+4848+#include "irqchip.h"47494850union gic_base {4951 void __iomem *common_base;···278276#define gic_set_wake NULL279277#endif280278281281-asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)279279+static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)282280{283281 u32 irqstat, irqnr;284282 struct gic_chip_data *gic = &gic_data[0];···619617}620618#endif621619620620+#ifdef CONFIG_SMP621621+void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)622622+{623623+ int cpu;624624+ unsigned long map = 0;625625+626626+ /* Convert our logical CPU mask into a physical one. */627627+ for_each_cpu(cpu, mask)628628+ map |= 1 << cpu_logical_map(cpu);629629+630630+ /*631631+ * Ensure that stores to Normal memory are visible to the632632+ * other CPUs before issuing the IPI.633633+ */634634+ dsb();635635+636636+ /* this always happens on GIC0 */637637+ writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);638638+}639639+#endif640640+622641static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,623642 irq_hw_number_t hw)624643{···766743 if (WARN_ON(!gic->domain))767744 return;768745746746+#ifdef CONFIG_SMP747747+ set_smp_cross_call(gic_raise_softirq);748748+#endif749749+750750+ set_handle_irq(gic_handle_irq);751751+769752 gic_chip.flags |= gic_arch_extn.flags;770753 gic_dist_init(gic);771754 gic_cpu_init(gic);···784755785756 gic_cpu_init(&gic_data[gic_nr]);786757}787787-788788-#ifdef CONFIG_SMP789789-void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)790790-{791791- int cpu;792792- unsigned long map = 0;793793-794794- /* Convert our logical CPU mask into a physical one. */795795- for_each_cpu(cpu, mask)796796- map |= gic_cpu_map[cpu];797797-798798- /*799799- * Ensure that stores to Normal memory are visible to the800800- * other CPUs before issuing the IPI.801801- */802802- dsb();803803-804804- /* this always happens on GIC0 */805805- writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);806806-}807807-#endif808758809759#ifdef CONFIG_OF810760static int gic_cnt __initdata = 0;···816808 gic_cnt++;817809 return 0;818810}811811+IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);812812+IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);813813+IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);814814+IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);815815+819816#endif
+60-35
arch/arm/common/vic.c
drivers/irqchip/irq-vic.c
···3030#include <linux/syscore_ops.h>3131#include <linux/device.h>3232#include <linux/amba/bus.h>3333+#include <linux/irqchip/arm-vic.h>33343435#include <asm/exception.h>3536#include <asm/mach/irq.h>3636-#include <asm/hardware/vic.h>3737+3838+#include "irqchip.h"3939+4040+#define VIC_IRQ_STATUS 0x004141+#define VIC_FIQ_STATUS 0x044242+#define VIC_INT_SELECT 0x0c /* 1 = FIQ, 0 = IRQ */4343+#define VIC_INT_SOFT 0x184444+#define VIC_INT_SOFT_CLEAR 0x1c4545+#define VIC_PROTECT 0x204646+#define VIC_PL190_VECT_ADDR 0x30 /* PL190 only */4747+#define VIC_PL190_DEF_VECT_ADDR 0x34 /* PL190 only */4848+4949+#define VIC_VECT_ADDR0 0x100 /* 0 to 15 (0..31 PL192) */5050+#define VIC_VECT_CNTL0 0x200 /* 0 to 15 (0..31 PL192) */5151+#define VIC_ITCR 0x300 /* VIC test control register */5252+5353+#define VIC_VECT_CNTL_ENABLE (1 << 5)5454+5555+#define VIC_PL192_VECT_ADDR 0xF0037563857/**3958 * struct vic_device - VIC PM device···8465static struct vic_device vic_devices[CONFIG_ARM_VIC_NR];85668667static int vic_id;6868+6969+static void vic_handle_irq(struct pt_regs *regs);87708871/**8972 * vic_init2 - common initialisation code···203182 return 0;204183}205184185185+/*186186+ * Handle each interrupt in a single VIC. Returns non-zero if we've187187+ * handled at least one interrupt. This reads the status register188188+ * before handling each interrupt, which is necessary given that189189+ * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.190190+ */191191+static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)192192+{193193+ u32 stat, irq;194194+ int handled = 0;195195+196196+ while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {197197+ irq = ffs(stat) - 1;198198+ handle_IRQ(irq_find_mapping(vic->domain, irq), regs);199199+ handled = 1;200200+ }201201+202202+ return handled;203203+}204204+205205+/*206206+ * Keep iterating over all registered VIC's until there are no pending207207+ * interrupts.208208+ */209209+static asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)210210+{211211+ int i, handled;212212+213213+ do {214214+ for (i = 0, handled = 0; i < vic_id; ++i)215215+ handled |= handle_one_vic(&vic_devices[i], regs);216216+ } while (handled);217217+}218218+206219static struct irq_domain_ops vic_irqdomain_ops = {207220 .map = vic_irqdomain_map,208221 .xlate = irq_domain_xlate_onetwocell,···273218 v->valid_sources = valid_sources;274219 v->resume_sources = resume_sources;275220 v->irq = irq;221221+ set_handle_irq(vic_handle_irq);276222 vic_id++;277223 v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,278224 &vic_irqdomain_ops, v);···483427484428 return 0;485429}430430+IRQCHIP_DECLARE(arm_pl190_vic, "arm,pl190-vic", vic_of_init);431431+IRQCHIP_DECLARE(arm_pl192_vic, "arm,pl192-vic", vic_of_init);432432+IRQCHIP_DECLARE(arm_versatile_vic, "arm,versatile-vic", vic_of_init);486433#endif /* CONFIG OF */487487-488488-/*489489- * Handle each interrupt in a single VIC. Returns non-zero if we've490490- * handled at least one interrupt. This reads the status register491491- * before handling each interrupt, which is necessary given that492492- * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.493493- */494494-static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)495495-{496496- u32 stat, irq;497497- int handled = 0;498498-499499- while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {500500- irq = ffs(stat) - 1;501501- handle_IRQ(irq_find_mapping(vic->domain, irq), regs);502502- handled = 1;503503- }504504-505505- return handled;506506-}507507-508508-/*509509- * Keep iterating over all registered VIC's until there are no pending510510- * interrupts.511511- */512512-asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)513513-{514514- int i, handled;515515-516516- do {517517- for (i = 0, handled = 0; i < vic_id; ++i)518518- handled |= handle_one_vic(&vic_devices[i], regs);519519- } while (handled);520520-}
···24242525#include <asm/smp_twd.h>2626#include <asm/localtimer.h>2727-#include <asm/hardware/gic.h>28272928/* set up by the platform code */3029static void __iomem *twd_base;
···1515#include <linux/jiffies.h>1616#include <linux/smp.h>1717#include <linux/io.h>1818+#include <linux/irqchip/arm-gic.h>18191919-#include <asm/hardware/gic.h>2020#include <asm/cacheflush.h>2121#include <asm/cputype.h>2222#include <asm/mach-types.h>···115115 * the boot monitor to read the system wide flags register,116116 * and branch to the address found there.117117 */118118- gic_raise_softirq(cpumask_of(cpu), 0);118118+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));119119120120 timeout = jiffies + (1 * HZ);121121 while (time_before(jiffies, timeout)) {···153153154154 for (i = 0; i < ncores; i++)155155 set_cpu_possible(i, true);156156-157157- set_smp_cross_call(gic_raise_softirq);158156}159157160158static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
···1919#include <linux/device.h>2020#include <linux/smp.h>2121#include <linux/io.h>2222+#include <linux/irqchip/arm-gic.h>22232324#include <asm/cacheflush.h>2424-#include <asm/hardware/gic.h>2525#include <asm/smp_scu.h>26262727#include "omap-secure.h"···157157 booted = true;158158 }159159160160- gic_raise_softirq(cpumask_of(cpu), 0);160160+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));161161162162 /*163163 * Now the secondary core is starting up let it run its···231231232232 for (i = 0; i < ncores; i++)233233 set_cpu_possible(i, true);234234-235235- set_smp_cross_call(gic_raise_softirq);236234}237235238236static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
···1515#ifndef __ASM_ARCH_TICK_H1616#define __ASM_ARCH_TICK_H __FILE__17171818+#include <linux/irqchip/arm-vic.h>1919+1820/* note, the timer interrutps turn up in 2 places, the vic and then1921 * the timer block. We take the VIC as the base at the moment.2022 */
···11-/* linux/arch/arm/mach-s5p64x0/include/mach/tick.h22- *33- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.44- * http://www.samsung.com55- *66- * Copyright 2008 Openmoko, Inc.77- * Copyright 2008 Simtec Electronics88- * http://armlinux.simtec.co.uk/99- * Ben Dooks <ben@simtec.co.uk>1010- *1111- * S5P64X0 - Timer tick support definitions1212- *1313- * This program is free software; you can redistribute it and/or modify1414- * it under the terms of the GNU General Public License version 2 as1515- * published by the Free Software Foundation.1616-*/1717-1818-#ifndef __ASM_ARCH_TICK_H1919-#define __ASM_ARCH_TICK_H __FILE__2020-2121-static inline u32 s3c24xx_ostimer_pending(void)2222-{2323- u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);2424- return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));2525-}2626-2727-#define TICK_MAX (0xffffffff)2828-2929-#endif /* __ASM_ARCH_TICK_H */
···1515#ifndef __ASM_ARCH_TICK_H1616#define __ASM_ARCH_TICK_H __FILE__17171818+#include <linux/irqchip/arm-vic.h>1919+1820/* note, the timer interrutps turn up in 2 places, the vic and then1921 * the timer block. We take the VIC as the base at the moment.2022 */
···11-/* linux/arch/arm/mach-s5pv210/include/mach/tick.h22- *33- * Copyright (c) 2009 Samsung Electronics Co., Ltd.44- * http://www.samsung.com/55- *66- * Based on arch/arm/mach-s3c6400/include/mach/tick.h77- *88- * S5PV210 - Timer tick support definitions99- *1010- * This program is free software; you can redistribute it and/or modify1111- * it under the terms of the GNU General Public License version 2 as1212- * published by the Free Software Foundation.1313-*/1414-1515-#ifndef __ASM_ARCH_TICK_H1616-#define __ASM_ARCH_TICK_H __FILE__1717-1818-static inline u32 s3c24xx_ostimer_pending(void)1919-{2020- u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);2121- return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));2222-}2323-2424-#define TICK_MAX (0xffffffff)2525-2626-#endif /* __ASM_ARCH_TICK_H */
···1212 */1313#include <linux/init.h>1414#include <linux/smp.h>1515-#include <asm/hardware/gic.h>16151716void __init shmobile_smp_init_cpus(unsigned int ncores)1817{···25262627 for (i = 0; i < ncores; i++)2728 set_cpu_possible(i, true);2828-2929- set_smp_cross_call(gic_raise_softirq);3029}
···1414#include <linux/device.h>1515#include <linux/jiffies.h>1616#include <linux/smp.h>1717+#include <linux/irqchip/arm-gic.h>17181819#include <asm/cacheflush.h>1920#include <asm/smp_plat.h>2020-#include <asm/hardware/gic.h>21212222/*2323 * Write pen_release in a way that is guaranteed to be visible to all···7979 * the boot monitor to read the system wide flags register,8080 * and branch to the address found there.8181 */8282- gic_raise_softirq(cpumask_of(cpu), 0);8282+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));83838484 timeout = jiffies + (1 * HZ);8585 while (time_before(jiffies, timeout)) {
+27
drivers/irqchip/Kconfig
···11+config IRQCHIP22+ def_bool y33+ depends on OF_IRQ44+55+config ARM_GIC66+ bool77+ select IRQ_DOMAIN88+ select MULTI_IRQ_HANDLER99+1010+config GIC_NON_BANKED1111+ bool1212+1313+config ARM_VIC1414+ bool1515+ select IRQ_DOMAIN1616+ select MULTI_IRQ_HANDLER1717+1818+config ARM_VIC_NR1919+ int2020+ default 4 if ARCH_S5PV2102121+ default 3 if ARCH_S5PC1002222+ default 22323+ depends on ARM_VIC2424+ help2525+ The maximum number of VICs available in the system, for2626+ power management.2727+128config VERSATILE_FPGA_IRQ229 bool330 select IRQ_DOMAIN
···11+/*22+ * Copyright (C) 2012 Thomas Petazzoni33+ *44+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>55+ *66+ * This file is licensed under the terms of the GNU General Public77+ * License version 2. This program is licensed "as is" without any88+ * warranty of any kind, whether express or implied.99+ */1010+1111+#include <linux/init.h>1212+#include <linux/of_irq.h>1313+1414+#include "irqchip.h"1515+1616+/*1717+ * This special of_device_id is the sentinel at the end of the1818+ * of_device_id[] array of all irqchips. It is automatically placed at1919+ * the end of the array by the linker, thanks to being part of a2020+ * special section.2121+ */2222+static const struct of_device_id2323+irqchip_of_match_end __used __section(__irqchip_of_end);2424+2525+extern struct of_device_id __irqchip_begin[];2626+2727+void __init irqchip_init(void)2828+{2929+ of_irq_init(__irqchip_begin);3030+}
+29
drivers/irqchip/irqchip.h
···11+/*22+ * Copyright (C) 2012 Thomas Petazzoni33+ *44+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>55+ *66+ * This file is licensed under the terms of the GNU General Public77+ * License version 2. This program is licensed "as is" without any88+ * warranty of any kind, whether express or implied.99+ */1010+1111+#ifndef _IRQCHIP_H1212+#define _IRQCHIP_H1313+1414+/*1515+ * This macro must be used by the different irqchip drivers to declare1616+ * the association between their DT compatible string and their1717+ * initialization function.1818+ *1919+ * @name: name that must be unique accross all IRQCHIP_DECLARE of the2020+ * same file.2121+ * @compstr: compatible string of the irqchip driver2222+ * @fn: initialization function2323+ */2424+#define IRQCHIP_DECLARE(name,compstr,fn) \2525+ static const struct of_device_id irqchip_of_match_##name \2626+ __used __section(__irqchip_of_table) \2727+ = { .compatible = compstr, .data = fn }2828+2929+#endif
···11+/*22+ * Copyright (C) 2012 Thomas Petazzoni33+ *44+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>55+ *66+ * This file is licensed under the terms of the GNU General Public77+ * License version 2. This program is licensed "as is" without any88+ * warranty of any kind, whether express or implied.99+ */1010+1111+#ifndef _LINUX_IRQCHIP_H1212+#define _LINUX_IRQCHIP_H1313+1414+void irqchip_init(void);1515+1616+#endif