diff mbox

[RFC,03/11] arm/arm64: Add initial gic support

Message ID 1456492533-17171-4-git-send-email-alex.bennee@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Alex Bennée Feb. 26, 2016, 1:15 p.m. UTC
From: Andrew Jones <drjones@redhat.com>

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 <drjones@redhat.com>
---
 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 mbox

Patch

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 <drjones@redhat.com>
+ *
+ * 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"