Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Jan 2018 00:47:21 +0000 (16:47 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Jan 2018 00:47:21 +0000 (16:47 -0800)
Pull irq updates from Thomas Gleixner:
 "A rather small set of irq updates this time:

   - removal of the old and now obsolete irq domain debugging code

   - the new Goldfish PIC driver

   - the usual pile of small fixes and updates"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  irqdomain: Kill CONFIG_IRQ_DOMAIN_DEBUG
  irq/work: Improve the flag definitions
  irqchip/gic-v3: Fix the driver probe() fail due to disabled GICC entry
  irqchip/irq-goldfish-pic: Add Goldfish PIC driver
  dt-bindings/goldfish-pic: Add device tree binding for Goldfish PIC driver
  irqchip/ompic: fix return value check in ompic_of_init()
  dt-bindings/bcm283x: Define polarity of per-cpu interrupts
  irqchip/irq-bcm2836: Add support for DT interrupt polarity
  dt-bindings/bcm2836-l1-intc: Add interrupt polarity support

35 files changed:
Documentation/IRQ-domain.txt
Documentation/devicetree/bindings/interrupt-controller/brcm,bcm2836-l1-intc.txt
Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt [new file with mode: 0644]
MAINTAINERS
arch/arm/boot/dts/bcm2836.dtsi
arch/arm/boot/dts/bcm2837.dtsi
arch/arm/boot/dts/bcm283x.dtsi
arch/arm/configs/aspeed_g4_defconfig
arch/arm/configs/aspeed_g5_defconfig
arch/arm/configs/hisi_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/mvebu_v7_defconfig
arch/arm/configs/pxa_defconfig
arch/arm/configs/sama5_defconfig
arch/arm/configs/tegra_defconfig
arch/arm/configs/vt8500_v6_v7_defconfig
arch/powerpc/configs/fsl-emb-nonhw.config
arch/powerpc/configs/powernv_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/pseries_defconfig
arch/xtensa/configs/audio_kc705_defconfig
arch/xtensa/configs/cadence_csp_defconfig
arch/xtensa/configs/generic_kc705_defconfig
arch/xtensa/configs/nommu_kc705_defconfig
arch/xtensa/configs/smp_lx200_defconfig
drivers/irqchip/Kconfig
drivers/irqchip/Makefile
drivers/irqchip/irq-bcm2836.c
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-goldfish-pic.c [new file with mode: 0644]
drivers/irqchip/irq-ompic.c
include/linux/irq_work.h
kernel/irq/Kconfig
kernel/irq/irqdomain.c
kernel/irq_work.c

index 4a1cd76..507775c 100644 (file)
@@ -265,37 +265,5 @@ support other architectures, such as ARM, ARM64 etc.
 
 === Debugging ===
 
-If you switch on CONFIG_IRQ_DOMAIN_DEBUG (which depends on
-CONFIG_IRQ_DOMAIN and CONFIG_DEBUG_FS), you will find a new file in
-your debugfs mount point, called irq_domain_mapping. This file
-contains a live snapshot of all the IRQ domains in the system:
-
- name              mapped  linear-max  direct-max  devtree-node
- pl061                  8           8           0  /smb/gpio@e0080000
- pl061                  8           8           0  /smb/gpio@e1050000
- pMSI                   0           0           0  /interrupt-controller@e1101000/v2m@e0080000
- MSI                   37           0           0  /interrupt-controller@e1101000/v2m@e0080000
- GICv2m                37           0           0  /interrupt-controller@e1101000/v2m@e0080000
- GICv2                448         448           0  /interrupt-controller@e1101000
-
-it also iterates over the interrupts to display their mapping in the
-domains, and makes the domain stacking visible:
-
-
-irq    hwirq    chip name        chip data           active  type            domain
-    1  0x00019  GICv2            0xffff00000916bfd8     *    LINEAR          GICv2
-    2  0x0001d  GICv2            0xffff00000916bfd8          LINEAR          GICv2
-    3  0x0001e  GICv2            0xffff00000916bfd8     *    LINEAR          GICv2
-    4  0x0001b  GICv2            0xffff00000916bfd8     *    LINEAR          GICv2
-    5  0x0001a  GICv2            0xffff00000916bfd8          LINEAR          GICv2
-[...]
-   96  0x81808  MSI              0x          (null)           RADIX          MSI
-   96+ 0x00063  GICv2m           0xffff8003ee116980           RADIX          GICv2m
-   96+ 0x00063  GICv2            0xffff00000916bfd8          LINEAR          GICv2
-   97  0x08800  MSI              0x          (null)     *     RADIX          MSI
-   97+ 0x00064  GICv2m           0xffff8003ee116980     *     RADIX          GICv2m
-   97+ 0x00064  GICv2            0xffff00000916bfd8     *    LINEAR          GICv2
-
-Here, interrupts 1-5 are only using a single domain, while 96 and 97
-are build out of a stack of three domain, each level performing a
-particular function.
+Most of the internals of the IRQ subsystem are exposed in debugfs by
+turning CONFIG_GENERIC_IRQ_DEBUGFS on.
index f320dcd..8ced169 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
                          registers
 - interrupt-controller:        Identifies the node as an interrupt controller
 - #interrupt-cells:    Specifies the number of cells needed to encode an
-                         interrupt source. The value shall be 1
+                         interrupt source. The value shall be 2
 
 Please refer to interrupts.txt in this directory for details of the common
 Interrupt Controllers bindings used by client devices.
@@ -32,6 +32,6 @@ local_intc: local_intc {
        compatible = "brcm,bcm2836-l1-intc";
        reg = <0x40000000 0x100>;
        interrupt-controller;
-       #interrupt-cells = <1>;
+       #interrupt-cells = <2>;
        interrupt-parent = <&local_intc>;
 };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt b/Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt
new file mode 100644 (file)
index 0000000..35f7527
--- /dev/null
@@ -0,0 +1,30 @@
+Android Goldfish PIC
+
+Android Goldfish programmable interrupt device used by Android
+emulator.
+
+Required properties:
+
+- compatible : should contain "google,goldfish-pic"
+- reg        : <registers mapping>
+- interrupts : <interrupt mapping>
+
+Example for mips when used in cascade mode:
+
+        cpuintc {
+                #interrupt-cells = <0x1>;
+                #address-cells = <0>;
+                interrupt-controller;
+                compatible = "mti,cpu-interrupt-controller";
+        };
+
+        interrupt-controller@1f000000 {
+                compatible = "google,goldfish-pic";
+                reg = <0x1f000000 0x1000>;
+
+                interrupt-controller;
+                #interrupt-cells = <0x1>;
+
+                interrupt-parent = <&cpuintc>;
+                interrupts = <0x2>;
+        };
index 9e8de56..4ad9d6a 100644 (file)
@@ -875,6 +875,12 @@ S: Supported
 F:     drivers/android/
 F:     drivers/staging/android/
 
+ANDROID GOLDFISH PIC DRIVER
+M:     Miodrag Dinic <miodrag.dinic@mips.com>
+S:     Supported
+F:     Documentation/devicetree/bindings/interrupt-controller/google,goldfish-pic.txt
+F:     drivers/irqchip/irq-goldfish-pic.c
+
 ANDROID GOLDFISH RTC DRIVER
 M:     Miodrag Dinic <miodrag.dinic@mips.com>
 S:     Supported
index 61e1580..1dfd764 100644 (file)
                        compatible = "brcm,bcm2836-l1-intc";
                        reg = <0x40000000 0x100>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                        interrupt-parent = <&local_intc>;
                };
 
                arm-pmu {
                        compatible = "arm,cortex-a7-pmu";
                        interrupt-parent = <&local_intc>;
-                       interrupts = <9>;
+                       interrupts = <9 IRQ_TYPE_LEVEL_HIGH>;
                };
        };
 
        timer {
                compatible = "arm,armv7-timer";
                interrupt-parent = <&local_intc>;
-               interrupts = <0>, // PHYS_SECURE_PPI
-                            <1>, // PHYS_NONSECURE_PPI
-                            <3>, // VIRT_PPI
-                            <2>; // HYP_PPI
+               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, // PHYS_SECURE_PPI
+                            <1 IRQ_TYPE_LEVEL_HIGH>, // PHYS_NONSECURE_PPI
+                            <3 IRQ_TYPE_LEVEL_HIGH>, // VIRT_PPI
+                            <2 IRQ_TYPE_LEVEL_HIGH>; // HYP_PPI
                always-on;
        };
 
@@ -76,7 +76,7 @@
        compatible = "brcm,bcm2836-armctrl-ic";
        reg = <0x7e00b200 0x200>;
        interrupt-parent = <&local_intc>;
-       interrupts = <8>;
+       interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
 };
 
 &cpu_thermal {
index bc1cca5..efa7d33 100644 (file)
@@ -12,7 +12,7 @@
                        compatible = "brcm,bcm2836-l1-intc";
                        reg = <0x40000000 0x100>;
                        interrupt-controller;
-                       #interrupt-cells = <1>;
+                       #interrupt-cells = <2>;
                        interrupt-parent = <&local_intc>;
                };
        };
        timer {
                compatible = "arm,armv7-timer";
                interrupt-parent = <&local_intc>;
-               interrupts = <0>, // PHYS_SECURE_PPI
-                            <1>, // PHYS_NONSECURE_PPI
-                            <3>, // VIRT_PPI
-                            <2>; // HYP_PPI
+               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>, // PHYS_SECURE_PPI
+                            <1 IRQ_TYPE_LEVEL_HIGH>, // PHYS_NONSECURE_PPI
+                            <3 IRQ_TYPE_LEVEL_HIGH>, // VIRT_PPI
+                            <2 IRQ_TYPE_LEVEL_HIGH>; // HYP_PPI
                always-on;
        };
 
@@ -73,7 +73,7 @@
        compatible = "brcm,bcm2836-armctrl-ic";
        reg = <0x7e00b200 0x200>;
        interrupt-parent = <&local_intc>;
-       interrupts = <8>;
+       interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
 };
 
 &cpu_thermal {
index dcde93c..18db25a 100644 (file)
@@ -2,6 +2,7 @@
 #include <dt-bindings/clock/bcm2835.h>
 #include <dt-bindings/clock/bcm2835-aux.h>
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/irq.h>
 
 /* firmware-provided startup stubs live here, where the secondary CPUs are
  * spinning.
index d23b9d5..95946de 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_KERNEL_XZ=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
index c0ad7b8..8c7ea03 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_KERNEL_XZ=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
index b2e340b..74d611e 100644 (file)
@@ -1,4 +1,3 @@
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
index 61509c4..b659244 100644 (file)
@@ -1,6 +1,5 @@
 CONFIG_SYSVIPC=y
 CONFIG_FHANDLE=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_CGROUPS=y
index 4b6e4fd..ddaeda4 100644 (file)
@@ -1,6 +1,5 @@
 CONFIG_SYSVIPC=y
 CONFIG_FHANDLE=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
index 830e817..837d0c9 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_FHANDLE=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
index 6529cb4..2080025 100644 (file)
@@ -2,7 +2,6 @@
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_FHANDLE=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
index 6678f29..c819be0 100644 (file)
@@ -1,5 +1,4 @@
 CONFIG_SYSVIPC=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
index 1bfaa7b..9b85326 100644 (file)
@@ -1,4 +1,3 @@
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BLK_DEV_INITRD=y
index cc49c95..e0567dc 100644 (file)
@@ -71,7 +71,6 @@ CONFIG_IP_ROUTE_MULTIPATH=y
 CONFIG_IP_ROUTE_VERBOSE=y
 CONFIG_IP_SCTP=m
 CONFIG_IPV6=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_ISO9660_FS=m
 CONFIG_JFFS2_FS_DEBUG=1
 CONFIG_JFFS2_FS=y
index 4891bbe..73dab7a 100644 (file)
@@ -4,7 +4,6 @@ CONFIG_CPU_LITTLE_ENDIAN=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_AUDIT=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_TASKSTATS=y
index 6ddca80..5033e63 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_PPC64=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_TASKSTATS=y
index bde2cd1..0dd5cf7 100644 (file)
@@ -3,7 +3,6 @@ CONFIG_NR_CPUS=2048
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_AUDIT=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_TASKSTATS=y
index 8d16925..2bf964d 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_FHANDLE=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IRQ_TIME_ACCOUNTING=y
index f2d3094..3221b70 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_USELIB=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IRQ_TIME_ACCOUNTING=y
index 744adea..985fa85 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_FHANDLE=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IRQ_TIME_ACCOUNTING=y
index 78c2529..624f9b3 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_FHANDLE=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IRQ_TIME_ACCOUNTING=y
index 14e3ca3..11fed6c 100644 (file)
@@ -1,7 +1,6 @@
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_FHANDLE=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IRQ_TIME_ACCOUNTING=y
index c70476b..d913aec 100644 (file)
@@ -343,4 +343,12 @@ config MESON_IRQ_GPIO
        help
          Support Meson SoC Family GPIO Interrupt Multiplexer
 
+config GOLDFISH_PIC
+       bool "Goldfish programmable interrupt controller"
+       depends on MIPS && (GOLDFISH || COMPILE_TEST)
+       select IRQ_DOMAIN
+       help
+         Say yes here to enable Goldfish interrupt controller driver used
+         for Goldfish based virtual platforms.
+
 endmenu
index d2df34a..d27e3e3 100644 (file)
@@ -84,3 +84,4 @@ obj-$(CONFIG_QCOM_IRQ_COMBINER)               += qcom-irq-combiner.o
 obj-$(CONFIG_IRQ_UNIPHIER_AIDET)       += irq-uniphier-aidet.o
 obj-$(CONFIG_ARCH_SYNQUACER)           += irq-sni-exiu.o
 obj-$(CONFIG_MESON_IRQ_GPIO)           += irq-meson-gpio.o
+obj-$(CONFIG_GOLDFISH_PIC)             += irq-goldfish-pic.o
index 667b9e1..dfe4a46 100644 (file)
@@ -98,13 +98,35 @@ static struct irq_chip bcm2836_arm_irqchip_gpu = {
        .irq_unmask     = bcm2836_arm_irqchip_unmask_gpu_irq,
 };
 
-static void bcm2836_arm_irqchip_register_irq(int hwirq, struct irq_chip *chip)
-{
-       int irq = irq_create_mapping(intc.domain, hwirq);
+static int bcm2836_map(struct irq_domain *d, unsigned int irq,
+                      irq_hw_number_t hw)
+{
+       struct irq_chip *chip;
+
+       switch (hw) {
+       case LOCAL_IRQ_CNTPSIRQ:
+       case LOCAL_IRQ_CNTPNSIRQ:
+       case LOCAL_IRQ_CNTHPIRQ:
+       case LOCAL_IRQ_CNTVIRQ:
+               chip = &bcm2836_arm_irqchip_timer;
+               break;
+       case LOCAL_IRQ_GPU_FAST:
+               chip = &bcm2836_arm_irqchip_gpu;
+               break;
+       case LOCAL_IRQ_PMU_FAST:
+               chip = &bcm2836_arm_irqchip_pmu;
+               break;
+       default:
+               pr_warn_once("Unexpected hw irq: %lu\n", hw);
+               return -EINVAL;
+       }
 
        irq_set_percpu_devid(irq);
-       irq_set_chip_and_handler(irq, chip, handle_percpu_devid_irq);
+       irq_domain_set_info(d, irq, hw, chip, d->host_data,
+                           handle_percpu_devid_irq, NULL, NULL);
        irq_set_status_flags(irq, IRQ_NOAUTOEN);
+
+       return 0;
 }
 
 static void
@@ -165,7 +187,8 @@ static int bcm2836_cpu_dying(unsigned int cpu)
 #endif
 
 static const struct irq_domain_ops bcm2836_arm_irqchip_intc_ops = {
-       .xlate = irq_domain_xlate_onecell
+       .xlate = irq_domain_xlate_onetwocell,
+       .map = bcm2836_map,
 };
 
 static void
@@ -218,19 +241,6 @@ static int __init bcm2836_arm_irqchip_l1_intc_of_init(struct device_node *node,
        if (!intc.domain)
                panic("%pOF: unable to create IRQ domain\n", node);
 
-       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPSIRQ,
-                                        &bcm2836_arm_irqchip_timer);
-       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTPNSIRQ,
-                                        &bcm2836_arm_irqchip_timer);
-       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTHPIRQ,
-                                        &bcm2836_arm_irqchip_timer);
-       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_CNTVIRQ,
-                                        &bcm2836_arm_irqchip_timer);
-       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_GPU_FAST,
-                                        &bcm2836_arm_irqchip_gpu);
-       bcm2836_arm_irqchip_register_irq(LOCAL_IRQ_PMU_FAST,
-                                        &bcm2836_arm_irqchip_pmu);
-
        bcm2836_arm_irqchip_smp_init();
 
        set_handle_irq(bcm2836_arm_irqchip_handle_irq);
index b56c3e2..a874777 100644 (file)
@@ -1331,6 +1331,10 @@ gic_acpi_parse_madt_gicc(struct acpi_subtable_header *header,
        u32 size = reg == GIC_PIDR2_ARCH_GICv4 ? SZ_64K * 4 : SZ_64K * 2;
        void __iomem *redist_base;
 
+       /* GICC entry which has !ACPI_MADT_ENABLED is not unusable so skip */
+       if (!(gicc->flags & ACPI_MADT_ENABLED))
+               return 0;
+
        redist_base = ioremap(gicc->gicr_base_address, size);
        if (!redist_base)
                return -ENOMEM;
@@ -1380,6 +1384,13 @@ static int __init gic_acpi_match_gicc(struct acpi_subtable_header *header,
        if ((gicc->flags & ACPI_MADT_ENABLED) && gicc->gicr_base_address)
                return 0;
 
+       /*
+        * It's perfectly valid firmware can pass disabled GICC entry, driver
+        * should not treat as errors, skip the entry instead of probe fail.
+        */
+       if (!(gicc->flags & ACPI_MADT_ENABLED))
+               return 0;
+
        return -ENODEV;
 }
 
diff --git a/drivers/irqchip/irq-goldfish-pic.c b/drivers/irqchip/irq-goldfish-pic.c
new file mode 100644 (file)
index 0000000..2a92f03
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Driver for MIPS Goldfish Programmable Interrupt Controller.
+ *
+ * Author: Miodrag Dinic <miodrag.dinic@mips.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#define GFPIC_NR_IRQS                  32
+
+/* 8..39 Cascaded Goldfish PIC interrupts */
+#define GFPIC_IRQ_BASE                 8
+
+#define GFPIC_REG_IRQ_PENDING          0x04
+#define GFPIC_REG_IRQ_DISABLE_ALL      0x08
+#define GFPIC_REG_IRQ_DISABLE          0x0c
+#define GFPIC_REG_IRQ_ENABLE           0x10
+
+struct goldfish_pic_data {
+       void __iomem *base;
+       struct irq_domain *irq_domain;
+};
+
+static void goldfish_pic_cascade(struct irq_desc *desc)
+{
+       struct goldfish_pic_data *gfpic = irq_desc_get_handler_data(desc);
+       struct irq_chip *host_chip = irq_desc_get_chip(desc);
+       u32 pending, hwirq, virq;
+
+       chained_irq_enter(host_chip, desc);
+
+       pending = readl(gfpic->base + GFPIC_REG_IRQ_PENDING);
+       while (pending) {
+               hwirq = __fls(pending);
+               virq = irq_linear_revmap(gfpic->irq_domain, hwirq);
+               generic_handle_irq(virq);
+               pending &= ~(1 << hwirq);
+       }
+
+       chained_irq_exit(host_chip, desc);
+}
+
+static const struct irq_domain_ops goldfish_irq_domain_ops = {
+       .xlate = irq_domain_xlate_onecell,
+};
+
+static int __init goldfish_pic_of_init(struct device_node *of_node,
+                                      struct device_node *parent)
+{
+       struct goldfish_pic_data *gfpic;
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
+       unsigned int parent_irq;
+       int ret = 0;
+
+       gfpic = kzalloc(sizeof(*gfpic), GFP_KERNEL);
+       if (!gfpic) {
+               ret = -ENOMEM;
+               goto out_err;
+       }
+
+       parent_irq = irq_of_parse_and_map(of_node, 0);
+       if (!parent_irq) {
+               pr_err("Failed to map parent IRQ!\n");
+               ret = -EINVAL;
+               goto out_free;
+       }
+
+       gfpic->base = of_iomap(of_node, 0);
+       if (!gfpic->base) {
+               pr_err("Failed to map base address!\n");
+               ret = -ENOMEM;
+               goto out_unmap_irq;
+       }
+
+       /* Mask interrupts. */
+       writel(1, gfpic->base + GFPIC_REG_IRQ_DISABLE_ALL);
+
+       gc = irq_alloc_generic_chip("GFPIC", 1, GFPIC_IRQ_BASE, gfpic->base,
+                                   handle_level_irq);
+       if (!gc) {
+               pr_err("Failed to allocate chip structures!\n");
+               ret = -ENOMEM;
+               goto out_iounmap;
+       }
+
+       ct = gc->chip_types;
+       ct->regs.enable = GFPIC_REG_IRQ_ENABLE;
+       ct->regs.disable = GFPIC_REG_IRQ_DISABLE;
+       ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
+       ct->chip.irq_mask = irq_gc_mask_disable_reg;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(GFPIC_NR_IRQS), 0,
+                              IRQ_NOPROBE | IRQ_LEVEL, 0);
+
+       gfpic->irq_domain = irq_domain_add_legacy(of_node, GFPIC_NR_IRQS,
+                                                 GFPIC_IRQ_BASE, 0,
+                                                 &goldfish_irq_domain_ops,
+                                                 NULL);
+       if (!gfpic->irq_domain) {
+               pr_err("Failed to add irqdomain!\n");
+               ret = -ENOMEM;
+               goto out_destroy_generic_chip;
+       }
+
+       irq_set_chained_handler_and_data(parent_irq,
+                                        goldfish_pic_cascade, gfpic);
+
+       pr_info("Successfully registered.\n");
+       return 0;
+
+out_destroy_generic_chip:
+       irq_destroy_generic_chip(gc, IRQ_MSK(GFPIC_NR_IRQS),
+                                IRQ_NOPROBE | IRQ_LEVEL, 0);
+out_iounmap:
+       iounmap(gfpic->base);
+out_unmap_irq:
+       irq_dispose_mapping(parent_irq);
+out_free:
+       kfree(gfpic);
+out_err:
+       pr_err("Failed to initialize! (errno = %d)\n", ret);
+       return ret;
+}
+
+IRQCHIP_DECLARE(google_gf_pic, "google,goldfish-pic", goldfish_pic_of_init);
index cf6d0c4..e66ef43 100644 (file)
@@ -171,9 +171,9 @@ static int __init ompic_of_init(struct device_node *node,
 
        /* Setup the device */
        ompic_base = ioremap(res.start, resource_size(&res));
-       if (IS_ERR(ompic_base)) {
+       if (!ompic_base) {
                pr_err("ompic: unable to map registers");
-               return PTR_ERR(ompic_base);
+               return -ENOMEM;
        }
 
        irq = irq_of_parse_and_map(node, 0);
index 0e81035..b11fcdf 100644 (file)
  * busy      NULL, 2 -> {free, claimed} : callback in progress, can be claimed
  */
 
-#define IRQ_WORK_PENDING       1UL
-#define IRQ_WORK_BUSY          2UL
-#define IRQ_WORK_FLAGS         3UL
-#define IRQ_WORK_LAZY          4UL /* Doesn't want IPI, wait for tick */
+#define IRQ_WORK_PENDING       BIT(0)
+#define IRQ_WORK_BUSY          BIT(1)
+
+/* Doesn't want IPI, wait for tick: */
+#define IRQ_WORK_LAZY          BIT(2)
+
+#define IRQ_WORK_CLAIMED       (IRQ_WORK_PENDING | IRQ_WORK_BUSY)
 
 struct irq_work {
        unsigned long flags;
index 89e3558..6fc87cc 100644 (file)
@@ -103,16 +103,6 @@ config GENERIC_IRQ_MATRIX_ALLOCATOR
 config GENERIC_IRQ_RESERVATION_MODE
        bool
 
-config IRQ_DOMAIN_DEBUG
-       bool "Expose hardware/virtual IRQ mapping via debugfs"
-       depends on IRQ_DOMAIN && DEBUG_FS
-       help
-         This option will show the mapping relationship between hardware irq
-         numbers and Linux irq numbers. The mapping is exposed via debugfs
-         in the file "irq_domain_mapping".
-
-         If you don't know what this means you don't need it.
-
 # Support forced irq threading
 config IRQ_FORCED_THREADING
        bool
index 62068ad..e6a9c36 100644 (file)
@@ -897,124 +897,6 @@ unsigned int irq_find_mapping(struct irq_domain *domain,
 }
 EXPORT_SYMBOL_GPL(irq_find_mapping);
 
-#ifdef CONFIG_IRQ_DOMAIN_DEBUG
-static void virq_debug_show_one(struct seq_file *m, struct irq_desc *desc)
-{
-       struct irq_domain *domain;
-       struct irq_data *data;
-
-       domain = desc->irq_data.domain;
-       data = &desc->irq_data;
-
-       while (domain) {
-               unsigned int irq = data->irq;
-               unsigned long hwirq = data->hwirq;
-               struct irq_chip *chip;
-               bool direct;
-
-               if (data == &desc->irq_data)
-                       seq_printf(m, "%5d  ", irq);
-               else
-                       seq_printf(m, "%5d+ ", irq);
-               seq_printf(m, "0x%05lx  ", hwirq);
-
-               chip = irq_data_get_irq_chip(data);
-               seq_printf(m, "%-15s  ", (chip && chip->name) ? chip->name : "none");
-
-               seq_printf(m, "0x%p  ", irq_data_get_irq_chip_data(data));
-
-               seq_printf(m, "   %c    ", (desc->action && desc->action->handler) ? '*' : ' ');
-               direct = (irq == hwirq) && (irq < domain->revmap_direct_max_irq);
-               seq_printf(m, "%6s%-8s  ",
-                          (hwirq < domain->revmap_size) ? "LINEAR" : "RADIX",
-                          direct ? "(DIRECT)" : "");
-               seq_printf(m, "%s\n", domain->name);
-#ifdef CONFIG_IRQ_DOMAIN_HIERARCHY
-               domain = domain->parent;
-               data = data->parent_data;
-#else
-               domain = NULL;
-#endif
-       }
-}
-
-static int virq_debug_show(struct seq_file *m, void *private)
-{
-       unsigned long flags;
-       struct irq_desc *desc;
-       struct irq_domain *domain;
-       struct radix_tree_iter iter;
-       void __rcu **slot;
-       int i;
-
-       seq_printf(m, " %-16s  %-6s  %-10s  %-10s  %s\n",
-                  "name", "mapped", "linear-max", "direct-max", "devtree-node");
-       mutex_lock(&irq_domain_mutex);
-       list_for_each_entry(domain, &irq_domain_list, link) {
-               struct device_node *of_node;
-               const char *name;
-
-               int count = 0;
-
-               of_node = irq_domain_get_of_node(domain);
-               if (of_node)
-                       name = of_node_full_name(of_node);
-               else if (is_fwnode_irqchip(domain->fwnode))
-                       name = container_of(domain->fwnode, struct irqchip_fwid,
-                                           fwnode)->name;
-               else
-                       name = "";
-
-               radix_tree_for_each_slot(slot, &domain->revmap_tree, &iter, 0)
-                       count++;
-               seq_printf(m, "%c%-16s  %6u  %10u  %10u  %s\n",
-                          domain == irq_default_domain ? '*' : ' ', domain->name,
-                          domain->revmap_size + count, domain->revmap_size,
-                          domain->revmap_direct_max_irq,
-                          name);
-       }
-       mutex_unlock(&irq_domain_mutex);
-
-       seq_printf(m, "%-5s  %-7s  %-15s  %-*s  %6s  %-14s  %s\n", "irq", "hwirq",
-                     "chip name", (int)(2 * sizeof(void *) + 2), "chip data",
-                     "active", "type", "domain");
-
-       for (i = 1; i < nr_irqs; i++) {
-               desc = irq_to_desc(i);
-               if (!desc)
-                       continue;
-
-               raw_spin_lock_irqsave(&desc->lock, flags);
-               virq_debug_show_one(m, desc);
-               raw_spin_unlock_irqrestore(&desc->lock, flags);
-       }
-
-       return 0;
-}
-
-static int virq_debug_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, virq_debug_show, inode->i_private);
-}
-
-static const struct file_operations virq_debug_fops = {
-       .open = virq_debug_open,
-       .read = seq_read,
-       .llseek = seq_lseek,
-       .release = single_release,
-};
-
-static int __init irq_debugfs_init(void)
-{
-       if (debugfs_create_file("irq_domain_mapping", S_IRUGO, NULL,
-                                NULL, &virq_debug_fops) == NULL)
-               return -ENOMEM;
-
-       return 0;
-}
-__initcall(irq_debugfs_init);
-#endif /* CONFIG_IRQ_DOMAIN_DEBUG */
-
 /**
  * irq_domain_xlate_onecell() - Generic xlate for direct one cell bindings
  *
index 40e9d73..6b7cdf1 100644 (file)
@@ -36,7 +36,7 @@ static bool irq_work_claim(struct irq_work *work)
         */
        flags = work->flags & ~IRQ_WORK_PENDING;
        for (;;) {
-               nflags = flags | IRQ_WORK_FLAGS;
+               nflags = flags | IRQ_WORK_CLAIMED;
                oflags = cmpxchg(&work->flags, flags, nflags);
                if (oflags == flags)
                        break;