MLK-16804-04 driver: irqchip: Add IPI SW workaround for imx8mq
authorBai Ping <ping.bai@nxp.com>
Wed, 8 Nov 2017 09:48:47 +0000 (17:48 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:46:54 +0000 (15:46 -0500)
On i.MX8MQ, when the CPU core is in power down state,
the IPI can NOT wakeup the core anymore(ERR011171), so using the
external IRQ32 to wakeup the core in power down idle
state successfully.

Signed-off-by: Bai Ping <ping.bai@nxp.com>
Reviewed-by: Anson Huang <anson.huang@nxp.com>
arch/arm64/boot/dts/freescale/fsl-imx8mq.dtsi
drivers/irqchip/irq-gic-v3.c

index 2c00a5e..24f5516 100644 (file)
@@ -70,7 +70,8 @@
        gic: interrupt-controller@38800000 {
                compatible = "arm,gic-v3";
                reg = <0x0 0x38800000 0 0x10000>, /* GIC Dist */
-                     <0x0 0x38880000 0 0xC0000>; /* GICR (RD_base + SGI_base) */
+                     <0x0 0x38880000 0 0xC0000>, /* GICR (RD_base + SGI_base) */
+                     <0x0 0x30340000 0x0 0x10000>; /* IOMUXC_GPR */
                #interrupt-cells = <3>;
                interrupt-controller;
                interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
index fd4a782..8889d69 100644 (file)
@@ -62,6 +62,8 @@ struct gic_chip_data {
 static struct gic_chip_data gic_data __read_mostly;
 static struct static_key supports_deactivate = STATIC_KEY_INIT_TRUE;
 
+static void __iomem *iomuxc_gpr_base;
+
 static struct gic_kvm_info gic_v3_kvm_info;
 
 #define gic_data_rdist()               (this_cpu_ptr(gic_data.rdists.rdist))
@@ -608,6 +610,7 @@ static void gic_send_sgi(u64 cluster_id, u16 tlist, unsigned int irq)
 static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 {
        int cpu;
+       u32 val;
 
        if (WARN_ON(irq >= 16))
                return;
@@ -624,8 +627,18 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 
                tlist = gic_compute_target_list(&cpu, mask, cluster_id);
                gic_send_sgi(cluster_id, tlist, irq);
-       }
 
+               if (iomuxc_gpr_base) {
+                       /* pending the IRQ32 to wakeup the core */
+                       val = readl_relaxed(iomuxc_gpr_base + 0x4);
+                       val |= (1 << 12);
+                       writel_relaxed(val, iomuxc_gpr_base + 0x4);
+                       /* delay for a while to make sure cores wakeup done */
+                       udelay(50);
+                       val &= ~(1 << 12);
+                       writel_relaxed(val, iomuxc_gpr_base + 0x4);
+               }
+       }
        /* Force the above writes to ICC_SGI1R_EL1 to be executed */
        isb();
 }
@@ -1175,6 +1188,9 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
                rdist_regs[i].phys_base = res.start;
        }
 
+       /* sw workaround for IPI can't wakeup CORE ERRATA(ERR011171) on i.MX8MQ */
+       iomuxc_gpr_base = of_iomap(node, 2);
+
        if (of_property_read_u64(node, "redistributor-stride", &redist_stride))
                redist_stride = 0;