rk30: fix fiq support when smp
author黄涛 <huangtao@rock-chips.com>
Thu, 15 Mar 2012 08:14:46 +0000 (16:14 +0800)
committer黄涛 <huangtao@rock-chips.com>
Thu, 15 Mar 2012 08:15:52 +0000 (16:15 +0800)
arch/arm/mach-rk30/fiq.c
arch/arm/mach-rk30/platsmp.c

index 48c3b35d8d2d6087e5bab1b0e69b3f73ca8a8385..2c8d176f97815fc6bf51bb947af59a2baa21c317 100644 (file)
@@ -92,29 +92,17 @@ void rk_irq_clearpending(int irq)
 
 void rk30_fiq_init(void)
 {
-       void __iomem *base = RK30_GICD_BASE;
        unsigned int gic_irqs, i;
 
        // read gic info to know how many irqs in our chip
-       gic_irqs = readl_relaxed(base + GIC_DIST_CTR) & 0x1f;
-       //set all the interrupt to non-secure state
+       gic_irqs = readl_relaxed(RK30_GICD_BASE + GIC_DIST_CTR) & 0x1f;
+       // set all the interrupt to non-secure state
        for (i = 0; i < (gic_irqs + 1); i++) {
-               /*
-                * In any system that implements the ARM Security Extensions,
-                * to support a consistent model for message passing between
-                * processors, ARM strongly recommends that all processors reserve:
-                * ID0-ID7 for Non-secure interrupts
-                * ID8-ID15 for Secure interrupts.
-                */
-               if (i == 0) {
-                       writel_relaxed(0xffff00ff, base + GIC_DIST_SECURITY + (i<<2));
-               } else {
-                       writel_relaxed(0xffffffff, base + GIC_DIST_SECURITY + (i<<2));
-               }
+               writel_relaxed(0xffffffff, RK30_GICD_BASE + GIC_DIST_SECURITY + (i<<2));
        }
        dsb();
 
-       writel_relaxed(0x3, base + GIC_DIST_CTRL);
-       writel_relaxed(0x1f, RK30_GICC_BASE + GIC_CPU_CTRL);
+       writel_relaxed(0x3, RK30_GICD_BASE + GIC_DIST_CTRL);
+       writel_relaxed(0xf, RK30_GICC_BASE + GIC_CPU_CTRL);
        dsb();
 }
index 41752d90230007d3eec9d1e873f7111ded766528..c727174f658eec4d96b68f1b7af6b25625c38a57 100644 (file)
 
 #include <mach/pmu.h>
 
+#ifdef CONFIG_FIQ
+static void gic_raise_softirq_non_secure(const struct cpumask *mask, unsigned int irq)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+       unsigned long map = *cpus_addr(*mask);
+#else
+       int cpu;
+       unsigned long map = 0;
+
+       /* Convert our logical CPU mask into a physical one. */
+       for_each_cpu(cpu, mask)
+               map |= 1 << cpu_logical_map(cpu);
+#endif
+
+       /*
+        * Ensure that stores to Normal memory are visible to the
+        * other CPUs before issuing the IPI.
+        */
+       dsb();
+
+       /* this always happens on GIC0 */
+       writel_relaxed(map << 16 | irq | 0x8000, RK30_GICD_BASE + GIC_DIST_SOFTINT);
+}
+
+static void gic_secondary_init_non_secure(void)
+{
+#define GIC_DIST_SECURITY      0x080
+       writel_relaxed(0xffffffff, RK30_GICD_BASE + GIC_DIST_SECURITY);
+       writel_relaxed(0xf, RK30_GICC_BASE + GIC_CPU_CTRL);
+       dsb();
+}
+#endif
+
 void __cpuinit platform_secondary_init(unsigned int cpu)
 {
        /*
@@ -25,6 +58,10 @@ void __cpuinit platform_secondary_init(unsigned int cpu)
         * for us: do so
         */
        gic_secondary_init(0);
+
+#ifdef CONFIG_FIQ
+       gic_secondary_init_non_secure();
+#endif
 }
 
 extern void rk30_sram_secondary_startup(void);
@@ -66,7 +103,11 @@ void __init smp_init_cpus(void)
        for (i = 0; i < ncores; i++)
                set_cpu_possible(i, true);
 
+#ifdef CONFIG_FIQ
+       set_smp_cross_call(gic_raise_softirq_non_secure);
+#else
        set_smp_cross_call(gic_raise_softirq);
+#endif
 }
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)