aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Auger <eric.auger@redhat.com>2020-04-03 09:13:25 +0200
committerAndrew Jones <drjones@redhat.com>2020-04-03 10:03:45 +0200
commitcb573c2fe0841f5ad1d215f0a693b589292b46da (patch)
tree2a97cf02f91fa5d83db6be20a4853db30d1af80f
parentca42f29a12344d3be60dfd0c4f6aba09b2dbc016 (diff)
downloadkvm-unit-tests-cb573c2fe0841f5ad1d215f0a693b589292b46da.tar.gz
arm: gic: Introduce gic_irq_set_clr_enable() helper
Allows to set or clear the enable state of a PPI/SGI/SPI. Signed-off-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Andrew Jones <drjones@redhat.com>
-rw-r--r--lib/arm/asm/gic.h4
-rw-r--r--lib/arm/gic.c31
2 files changed, 35 insertions, 0 deletions
diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
index 922cbe9..afb3309 100644
--- a/lib/arm/asm/gic.h
+++ b/lib/arm/asm/gic.h
@@ -82,5 +82,9 @@ extern void gic_ipi_send_single(int irq, int cpu);
extern void gic_ipi_send_mask(int irq, const cpumask_t *dest);
extern enum gic_irq_state gic_irq_state(int irq);
+void gic_irq_set_clr_enable(int irq, bool enable);
+#define gic_enable_irq(irq) gic_irq_set_clr_enable(irq, true)
+#define gic_disable_irq(irq) gic_irq_set_clr_enable(irq, false)
+
#endif /* !__ASSEMBLY__ */
#endif /* _ASMARM_GIC_H_ */
diff --git a/lib/arm/gic.c b/lib/arm/gic.c
index c3c5f6b..8a1a8c8 100644
--- a/lib/arm/gic.c
+++ b/lib/arm/gic.c
@@ -147,6 +147,36 @@ void gic_ipi_send_mask(int irq, const cpumask_t *dest)
gic_common_ops->ipi_send_mask(irq, dest);
}
+void gic_irq_set_clr_enable(int irq, bool enable)
+{
+ u32 offset, split = 32, shift = (irq % 32);
+ u32 reg, mask = BIT(shift);
+ void *base;
+
+ assert(irq < 1020);
+
+ switch (gic_version()) {
+ case 2:
+ offset = enable ? GICD_ISENABLER : GICD_ICENABLER;
+ base = gicv2_dist_base();
+ break;
+ case 3:
+ if (irq < 32) {
+ offset = enable ? GICR_ISENABLER0 : GICR_ICENABLER0;
+ base = gicv3_sgi_base();
+ } else {
+ offset = enable ? GICD_ISENABLER : GICD_ICENABLER;
+ base = gicv3_dist_base();
+ }
+ break;
+ default:
+ assert(0);
+ }
+ base += offset + (irq / split) * 4;
+ reg = readl(base);
+ writel(reg | mask, base);
+}
+
enum gic_irq_state gic_irq_state(int irq)
{
enum gic_irq_state state;
@@ -191,3 +221,4 @@ enum gic_irq_state gic_irq_state(int irq)
return state;
}
+