qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC 03/11] arm/arm64: Add initial gic support


From: Alex Bennée
Subject: [Qemu-devel] [RFC 03/11] arm/arm64: Add initial gic support
Date: Fri, 26 Feb 2016 13:15:25 +0000

From: Andrew Jones <address@hidden>

Add some gic(v2) support. This just adds enough support for an IPI
test. It's really just a starting point, and the general functions
(inlines in gic.h) may need some changes as more support is added.

Signed-off-by: Andrew Jones <address@hidden>
---
 lib/arm/asm/gic.h   | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/arm/io.c        |  31 +++++++++++++
 lib/arm64/asm/gic.h |   1 +
 3 files changed, 154 insertions(+)
 create mode 100644 lib/arm/asm/gic.h
 create mode 100644 lib/arm64/asm/gic.h

diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h
new file mode 100644
index 0000000..6f27c91
--- /dev/null
+++ b/lib/arm/asm/gic.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2015, Red Hat Inc, Andrew Jones <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.
+ *
+ * All GIC* defines are lifted from include/linux/irqchip/arm-gic.h
+ */
+#ifndef _ASMARM_GIC_H_
+#define _ASMARM_GIC_H_
+
+#define GIC_CPU_CTRL                   0x00
+#define GIC_CPU_PRIMASK                        0x04
+#define GIC_CPU_BINPOINT               0x08
+#define GIC_CPU_INTACK                 0x0c
+#define GIC_CPU_EOI                    0x10
+#define GIC_CPU_RUNNINGPRI             0x14
+#define GIC_CPU_HIGHPRI                        0x18
+#define GIC_CPU_ALIAS_BINPOINT         0x1c
+#define GIC_CPU_ACTIVEPRIO             0xd0
+#define GIC_CPU_IDENT                  0xfc
+
+#define GICC_ENABLE                    0x1
+#define GICC_INT_PRI_THRESHOLD         0xf0
+#define GICC_IAR_INT_ID_MASK           0x3ff
+#define GICC_INT_SPURIOUS              1023
+#define GICC_DIS_BYPASS_MASK           0x1e0
+
+#define GIC_DIST_CTRL                  0x000
+#define GIC_DIST_CTR                   0x004
+#define GIC_DIST_IGROUP                        0x080
+#define GIC_DIST_ENABLE_SET            0x100
+#define GIC_DIST_ENABLE_CLEAR          0x180
+#define GIC_DIST_PENDING_SET           0x200
+#define GIC_DIST_PENDING_CLEAR         0x280
+#define GIC_DIST_ACTIVE_SET            0x300
+#define GIC_DIST_ACTIVE_CLEAR          0x380
+#define GIC_DIST_PRI                   0x400
+#define GIC_DIST_TARGET                        0x800
+#define GIC_DIST_CONFIG                        0xc00
+#define GIC_DIST_SOFTINT               0xf00
+#define GIC_DIST_SGI_PENDING_CLEAR     0xf10
+#define GIC_DIST_SGI_PENDING_SET       0xf20
+
+#define GICD_ENABLE                    0x1
+#define GICD_DISABLE                   0x0
+#define GICD_INT_ACTLOW_LVLTRIG                0x0
+#define GICD_INT_EN_CLR_X32            0xffffffff
+#define GICD_INT_EN_SET_SGI            0x0000ffff
+#define GICD_INT_EN_CLR_PPI            0xffff0000
+#define GICD_INT_DEF_PRI               0xa0
+#define GICD_INT_DEF_PRI_X4            ((GICD_INT_DEF_PRI << 24) |\
+                                       (GICD_INT_DEF_PRI << 16) |\
+                                       (GICD_INT_DEF_PRI << 8) |\
+                                       GICD_INT_DEF_PRI)
+
+#define GICH_HCR                       0x0
+#define GICH_VTR                       0x4
+#define GICH_VMCR                      0x8
+#define GICH_MISR                      0x10
+#define GICH_EISR0                     0x20
+#define GICH_EISR1                     0x24
+#define GICH_ELRSR0                    0x30
+#define GICH_ELRSR1                    0x34
+#define GICH_APR                       0xf0
+#define GICH_LR0                       0x100
+
+#define GICH_HCR_EN                    (1 << 0)
+#define GICH_HCR_UIE                   (1 << 1)
+
+#define GICH_LR_VIRTUALID              (0x3ff << 0)
+#define GICH_LR_PHYSID_CPUID_SHIFT     (10)
+#define GICH_LR_PHYSID_CPUID           (7 << GICH_LR_PHYSID_CPUID_SHIFT)
+#define GICH_LR_STATE                  (3 << 28)
+#define GICH_LR_PENDING_BIT            (1 << 28)
+#define GICH_LR_ACTIVE_BIT             (1 << 29)
+#define GICH_LR_EOI                    (1 << 19)
+
+#define GICH_VMCR_CTRL_SHIFT           0
+#define GICH_VMCR_CTRL_MASK            (0x21f << GICH_VMCR_CTRL_SHIFT)
+#define GICH_VMCR_PRIMASK_SHIFT                27
+#define GICH_VMCR_PRIMASK_MASK         (0x1f << GICH_VMCR_PRIMASK_SHIFT)
+#define GICH_VMCR_BINPOINT_SHIFT       21
+#define GICH_VMCR_BINPOINT_MASK                (0x7 << 
GICH_VMCR_BINPOINT_SHIFT)
+#define GICH_VMCR_ALIAS_BINPOINT_SHIFT 18
+#define GICH_VMCR_ALIAS_BINPOINT_MASK  (0x7 << GICH_VMCR_ALIAS_BINPOINT_SHIFT)
+
+#define GICH_MISR_EOI                  (1 << 0)
+#define GICH_MISR_U                    (1 << 1)
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+#define GIC_DIST_BASE                  (gicv2_data.dist_base)
+#define GIC_CPU_BASE                   (gicv2_data.cpu_base)
+
+struct gicv2_data {
+       void *dist_base;
+       void *cpu_base;
+};
+
+extern struct gicv2_data gicv2_data;
+
+static inline void gic_enable(void)
+{
+       writel(GICD_ENABLE, GIC_DIST_BASE + GIC_DIST_CTRL);
+       writel(0xff, GIC_CPU_BASE + GIC_CPU_PRIMASK);
+       writel(GICC_ENABLE, GIC_CPU_BASE + GIC_CPU_CTRL);
+}
+
+static inline void gic_irq_ack(void)
+{
+       unsigned int iar = readl(GIC_CPU_BASE + GIC_CPU_INTACK);
+       writel(iar, GIC_CPU_BASE + GIC_CPU_EOI);
+}
+
+static inline void gic_send_sgi(unsigned int cpu, unsigned int irq)
+{
+       writel(((1 << cpu) << 16) | irq, GIC_DIST_BASE + GIC_DIST_SOFTINT);
+}
+
+#endif /* !__ASSEMBLY__ */
+#endif /* _ASMARM_GIC_H_ */
diff --git a/lib/arm/io.c b/lib/arm/io.c
index a08d394..9eae13f 100644
--- a/lib/arm/io.c
+++ b/lib/arm/io.c
@@ -12,6 +12,7 @@
 #include <devicetree.h>
 #include <chr-testdev.h>
 #include <asm/spinlock.h>
+#include <asm/gic.h>
 #include <asm/io.h>
 
 extern void halt(int code);
@@ -62,10 +63,40 @@ static void uart0_init(void)
        }
 }
 
+struct gicv2_data gicv2_data;
+static int gicv2_init(void)
+{
+       const char *compatible = "arm,cortex-a15-gic";
+       struct dt_pbus_reg reg;
+       struct dt_device gic;
+       struct dt_bus bus;
+       int node;
+
+       dt_bus_init_defaults(&bus);
+       dt_device_init(&gic, &bus, NULL);
+
+       node = dt_device_find_compatible(&gic, compatible);
+       assert(node >= 0 || node == -FDT_ERR_NOTFOUND);
+
+       if (node == -FDT_ERR_NOTFOUND)
+               return node;
+
+       assert(dt_pbus_translate_node(node, 0, &reg) == 0);
+
+       gicv2_data.dist_base = ioremap(reg.addr, reg.size);
+
+       assert(dt_pbus_translate_node(node, 1, &reg) == 0);
+
+       gicv2_data.cpu_base = ioremap(reg.addr, reg.size);
+
+       return 0;
+}
+
 void io_init(void)
 {
        uart0_init();
        chr_testdev_init();
+       assert(gicv2_init() == 0);
 }
 
 void puts(const char *s)
diff --git a/lib/arm64/asm/gic.h b/lib/arm64/asm/gic.h
new file mode 100644
index 0000000..e5eb302
--- /dev/null
+++ b/lib/arm64/asm/gic.h
@@ -0,0 +1 @@
+#include "../../arm/asm/gic.h"
-- 
2.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]