ARCv2: IDU-intc: Use build registers for getting numbers of interrupts
authorYuriy Kolerov <yuriy.kolerov@synopsys.com>
Tue, 31 Jan 2017 11:45:23 +0000 (14:45 +0300)
committerVineet Gupta <vgupta@synopsys.com>
Mon, 6 Feb 2017 17:37:57 +0000 (09:37 -0800)
This enhancement is needed to allow masking all available common interrupts
in IDU interrupt controller in boot time since the kernel can
discover a number of them from the build register. Also now there
is no need to specify in device tree a list of used core interrupts
by IDU. E.g. before:

    idu_intc: idu-interrupt-controller {
        compatible = "snps,archs-idu-intc";
        interrupt-controller;
        interrupt-parent = <&core_intc>;
        #interrupt-cells = <2>;
        interrupts = <24 25 26 27 28 29 30 31>;
    };

and after:

    idu_intc: idu-interrupt-controller {
        compatible = "snps,archs-idu-intc";
        interrupt-controller;
        interrupt-parent = <&core_intc>;
        #interrupt-cells = <2>;
    };

Signed-off-by: Yuriy Kolerov <yuriy.kolerov@synopsys.com>
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
arch/arc/kernel/mcip.c
include/soc/arc/mcip.h

index 9f6b68fd4f3bcfc6df3741f5206bf38ebb304ce7..21dc89704113f30f9dc3020a69fe3c0b7cb13426 100644 (file)
@@ -230,14 +230,12 @@ static struct irq_chip idu_irq_chip = {
 
 };
 
-static irq_hw_number_t idu_first_hwirq;
-
 static void idu_cascade_isr(struct irq_desc *desc)
 {
        struct irq_domain *idu_domain = irq_desc_get_handler_data(desc);
        struct irq_chip *core_chip = irq_desc_get_chip(desc);
        irq_hw_number_t core_hwirq = irqd_to_hwirq(irq_desc_get_irq_data(desc));
-       irq_hw_number_t idu_hwirq = core_hwirq - idu_first_hwirq;
+       irq_hw_number_t idu_hwirq = core_hwirq - FIRST_EXT_IRQ;
 
        chained_irq_enter(core_chip, desc);
        generic_handle_irq(irq_find_mapping(idu_domain, idu_hwirq));
@@ -283,17 +281,20 @@ static int __init
 idu_of_init(struct device_node *intc, struct device_node *parent)
 {
        struct irq_domain *domain;
-       /* Read IDU BCR to confirm nr_irqs */
-       int nr_irqs = of_irq_count(intc);
+       int nr_irqs;
        int i, virq;
        struct mcip_bcr mp;
+       struct mcip_idu_bcr idu_bcr;
 
        READ_BCR(ARC_REG_MCIP_BCR, mp);
 
        if (!mp.idu)
                panic("IDU not detected, but DeviceTree using it");
 
-       pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs);
+       READ_BCR(ARC_REG_MCIP_IDU_BCR, idu_bcr);
+       nr_irqs = mcip_idu_bcr_to_nr_irqs(idu_bcr);
+
+       pr_info("MCIP: IDU supports %u common irqs\n", nr_irqs);
 
        domain = irq_domain_add_linear(intc, nr_irqs, &idu_irq_ops, NULL);
 
@@ -306,10 +307,8 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
                 * however we need it to get the parent virq and set IDU handler
                 * as first level isr
                 */
-               virq = irq_of_parse_and_map(intc, i);
-               if (!i)
-                       idu_first_hwirq = irqd_to_hwirq(irq_get_irq_data(virq));
-
+               virq = irq_create_mapping(NULL, i + FIRST_EXT_IRQ);
+               BUG_ON(!virq);
                irq_set_chained_handler_and_data(virq, idu_cascade_isr, domain);
        }
 
index 4b6b489a8d7c2defaf51e9ecb121c91901b9cac8..c2d1b15da136e9aa9273a90471ac8be7a1b6b413 100644 (file)
@@ -14,6 +14,7 @@
 #include <soc/arc/aux.h>
 
 #define ARC_REG_MCIP_BCR       0x0d0
+#define ARC_REG_MCIP_IDU_BCR   0x0D5
 #define ARC_REG_MCIP_CMD       0x600
 #define ARC_REG_MCIP_WDATA     0x601
 #define ARC_REG_MCIP_READBACK  0x602
@@ -69,6 +70,22 @@ struct mcip_bcr {
 #endif
 };
 
+struct mcip_idu_bcr {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:21, cirqnum:3, ver:8;
+#else
+       unsigned int ver:8, cirqnum:3, pad:21;
+#endif
+};
+
+
+/*
+ * Build register for IDU contains not an actual number of supported common
+ * interrupts but an exponent of 2 which must be multiplied by 4 to
+ * get a number of supported common interrupts.
+ */
+#define mcip_idu_bcr_to_nr_irqs(bcr) (4 * (1 << (bcr).cirqnum))
+
 /*
  * MCIP programming model
  *