new file mode 100644
@@ -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_ */
@@ -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, ®) == 0);
+
+ gicv2_data.dist_base = ioremap(reg.addr, reg.size);
+
+ assert(dt_pbus_translate_node(node, 1, ®) == 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)
new file mode 100644
@@ -0,0 +1 @@
+#include "../../arm/asm/gic.h"