FIQ on xilinx cortex a9 zynq

From: Tim Sander
Date: Fri Feb 28 2014 - 12:03:41 EST


Hi

I am currently trying to get the FIQ interrupt working with linux. I want to
have the FIQ to have an interrupt which is not masked by linux and gives the
lowest irq latencys the hardware can deliver.

In the case of the xilinx zynx i have seen that the ICCICR register enables
the FIQ via the fittingly named config bit FiqEn. Enabling this bit "as is" does
not seem to work as the kernel works in secure mode and thus all interrupts
delivered suddenly are delivered in FIQ context which is obviously not a good
idea.

So i tried to switch all interrupts to the non-secure mode:
Disable the interrupts in ICCICR register, set all interrupt security
registers to 0xffffffff which means non-secure mode.

The register values after that looked like that which is slighly irritating
for the ICDISR0 case:
ICDISR0:f800ffff
ICDISR1:ffffffff
ICDISR2:ffffffff
Set the ICCICR register to 0x17 (SBPR,AckCtl,EnableNS,EnableS).
But still the kernel locks up when doing this.

One cause would be that in driver/irqchips/irq-gic.c the first bit in ICCICR is
used to switch the interrupts off. Now it should be the second bit as they where
shifted to the non-secure mode.

I tried the following patch which should switch both the non-secure and the
secure images but still this locked the kernel up:
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 5e7f810..a05a126 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -467,13 +467,14 @@ static void gic_cpu_init(struct gic_chip_data *gic)
writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4);

writel_relaxed(0xf0, base + GIC_CPU_PRIMASK);
- writel_relaxed(1, base + GIC_CPU_CTRL);
+
+ writel_relaxed(readl(base + GIC_CPU_CTRL)|3, base + GIC_CPU_CTRL);
}

void gic_cpu_if_down(void)
{
void __iomem *cpu_base = gic_data_cpu_base(&gic_data[0]);
- writel_relaxed(0, cpu_base + GIC_CPU_CTRL);
+ writel_relaxed(readl(cpu_base + GIC_CPU_CTRL)&0xfffffffc, cpu_base + GIC_CPU_CTRL);
}

#ifdef CONFIG_CPU_PM
@@ -608,7 +609,7 @@ static void gic_cpu_restore(unsigned int gic_nr)
writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4);

writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK);
- writel_relaxed(1, cpu_base + GIC_CPU_CTRL);
+ writel_relaxed(readl(cpu_base + GIC_CPU_CTRL)|3, cpu_base + GIC_CPU_CTRL);
}

static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v)
----

but still the kernel locks up even if i haven't enabled the fiqen bit in ICCICR register.
So currently i am out of ideas why the kernel locks up but i am sure i have forgotten one thing
or another... :-/

It seems much harder to get the FIQ running than in the "good ol' days" without TrustZone.

Best regards
Tim

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/