ARCv2: intc: untangle SMP, MCIP and IDU
authorVineet Gupta <vgupta@synopsys.com>
Thu, 29 Sep 2016 17:00:14 +0000 (10:00 -0700)
committerVineet Gupta <vgupta@synopsys.com>
Sun, 16 Oct 2016 22:49:07 +0000 (15:49 -0700)
The IDU intc is technically part of MCIP (Multi-core IP) hence
historically was only available in a SMP hardware build (and thus only
in a SMP kernel build). Now that hardware restriction has been lifted,
so a UP kernel needs to support it.

This requires breaking mcip.c into parts which are strictly SMP
(inter-core interrupts) and IDU which in reality is just another
intc and thus has no bearing on SMP.

This change allows IDU in UP builds and with a suitable device tree, we
can have the cascaded intc system

    ARCv2 core intc <---> ARCv2 IDU intc <---> periperals

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
arch/arc/Kconfig
arch/arc/include/asm/mcip.h
arch/arc/kernel/mcip.c

index ecd12379e2cdb55bf29626ce0590742875574f3a..6f67895cd9c481709f5c71f412a389854ec04142 100644 (file)
@@ -186,14 +186,6 @@ if SMP
 config ARC_HAS_COH_CACHES
        def_bool n
 
-config ARC_MCIP
-       bool "ARConnect Multicore IP (MCIP) Support "
-       depends on ISA_ARCV2
-       help
-         This IP block enables SMP in ARC-HS38 cores.
-         It provides for cross-core interrupts, multi-core debug
-         hardware semaphores, shared memory,....
-
 config NR_CPUS
        int "Maximum number of CPUs (2-4096)"
        range 2 4096
@@ -211,6 +203,15 @@ config ARC_SMP_HALT_ON_RESET
 
 endif  #SMP
 
+config ARC_MCIP
+       bool "ARConnect Multicore IP (MCIP) Support "
+       depends on ISA_ARCV2
+       default y if SMP
+       help
+         This IP block enables SMP in ARC-HS38 cores.
+         It provides for cross-core interrupts, multi-core debug
+         hardware semaphores, shared memory,....
+
 menuconfig ARC_CACHE
        bool "Enable Cache Support"
        default y
index 847e3bbe387fc92f9b4433bf7e08fc0b11e3ec70..c8fbe4114badd972a18b37de313f91ab7cffd482 100644 (file)
@@ -55,6 +55,22 @@ struct mcip_cmd {
 #define IDU_M_DISTRI_DEST              0x2
 };
 
+struct mcip_bcr {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+               unsigned int pad3:8,
+                            idu:1, llm:1, num_cores:6,
+                            iocoh:1,  gfrc:1, dbg:1, pad2:1,
+                            msg:1, sem:1, ipi:1, pad:1,
+                            ver:8;
+#else
+               unsigned int ver:8,
+                            pad:1, ipi:1, sem:1, msg:1,
+                            pad2:1, dbg:1, gfrc:1, iocoh:1,
+                            num_cores:6, llm:1, idu:1,
+                            pad3:8;
+#endif
+};
+
 /*
  * MCIP programming model
  *
index 72f9179b1a24663b582b73d0bdc1972ec46befa9..c424d5abc318a220f07d4724b8796a35280f4e7e 100644 (file)
 #include <asm/mcip.h>
 #include <asm/setup.h>
 
-static char smp_cpuinfo_buf[128];
-static int idu_detected;
-
 static DEFINE_RAW_SPINLOCK(mcip_lock);
 
+#ifdef CONFIG_SMP
+
+static char smp_cpuinfo_buf[128];
+
 static void mcip_setup_per_cpu(int cpu)
 {
        smp_ipi_irq_setup(cpu, IPI_IRQ);
@@ -86,21 +87,7 @@ static void mcip_ipi_clear(int irq)
 
 static void mcip_probe_n_setup(void)
 {
-       struct mcip_bcr {
-#ifdef CONFIG_CPU_BIG_ENDIAN
-               unsigned int pad3:8,
-                            idu:1, llm:1, num_cores:6,
-                            iocoh:1,  gfrc:1, dbg:1, pad2:1,
-                            msg:1, sem:1, ipi:1, pad:1,
-                            ver:8;
-#else
-               unsigned int ver:8,
-                            pad:1, ipi:1, sem:1, msg:1,
-                            pad2:1, dbg:1, gfrc:1, iocoh:1,
-                            num_cores:6, llm:1, idu:1,
-                            pad3:8;
-#endif
-       } mp;
+       struct mcip_bcr mp;
 
        READ_BCR(ARC_REG_MCIP_BCR, mp);
 
@@ -114,7 +101,6 @@ static void mcip_probe_n_setup(void)
                IS_AVAIL1(mp.gfrc, "GFRC"));
 
        cpuinfo_arc700[0].extn.gfrc = mp.gfrc;
-       idu_detected = mp.idu;
 
        if (mp.dbg) {
                __mcip_cmd_data(CMD_DEBUG_SET_SELECT, 0, 0xf);
@@ -130,6 +116,8 @@ struct plat_smp_ops plat_smp_ops = {
        .ipi_clear      = mcip_ipi_clear,
 };
 
+#endif
+
 /***************************************************************************
  * ARCv2 Interrupt Distribution Unit (IDU)
  *
@@ -295,8 +283,11 @@ idu_of_init(struct device_node *intc, struct device_node *parent)
        /* Read IDU BCR to confirm nr_irqs */
        int nr_irqs = of_irq_count(intc);
        int i, irq;
+       struct mcip_bcr mp;
+
+       READ_BCR(ARC_REG_MCIP_BCR, mp);
 
-       if (!idu_detected)
+       if (!mp.idu)
                panic("IDU not detected, but DeviceTree using it");
 
        pr_info("MCIP: IDU referenced from Devicetree %d irqs\n", nr_irqs);