|
@@ -1,368 +1,262 @@
|
|
|
/*
|
|
|
- * Copyright 2014, General Dynamics C4 Systems
|
|
|
+ * Copyright (c) 2006-2018, RT-Thread Development Team
|
|
|
*
|
|
|
- * This software may be distributed and modified according to the terms of
|
|
|
- * the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
|
|
- * See "LICENSE_GPLv2.txt" for details.
|
|
|
+ * SPDX-License-Identifier: Apache-2.0
|
|
|
*
|
|
|
- * @TAG(GD_GPL)
|
|
|
+ * Change Logs:
|
|
|
+ * Date Author Notes
|
|
|
+ * 2013-07-20 Bernard first version
|
|
|
+ * 2014-04-03 Grissiom many enhancements
|
|
|
+ * 2018-11-22 Jesven add rt_hw_ipi_send()
|
|
|
+ * add rt_hw_ipi_handler_install()
|
|
|
*/
|
|
|
+#include <rtthread.h>
|
|
|
|
|
|
#include "gic_pl400.h"
|
|
|
+#include "cp15.h"
|
|
|
#include "iomap.h"
|
|
|
|
|
|
-#define BIT(n) (1ul<<(n))
|
|
|
-#define MASK(n) (BIT(n)-1ul)
|
|
|
-
|
|
|
-/* Setters/getters helpers */
|
|
|
-#define IRQ_REG(IRQ) ((IRQ) / 32)
|
|
|
-#define IRQ_BIT(IRQ) BIT((IRQ) % 32)
|
|
|
-#define IRQ_MASK MASK(10)
|
|
|
-#define IS_IRQ_VALID(X) (((X)&IRQ_MASK) < SPECIAL_IRQ_START)
|
|
|
+#define ARM_GIC_MAX_NR 1
|
|
|
+struct arm_gic
|
|
|
+{
|
|
|
+ rt_uint32_t offset; /* the first interrupt index in the vector table */
|
|
|
|
|
|
-#define CPU(X) (1<<(X))
|
|
|
-#define TARGET_CPU_ALLINT(CPU) ( \
|
|
|
- ( ((CPU)&0xff)<<0 ) |\
|
|
|
- ( ((CPU)&0xff)<<8 ) |\
|
|
|
- ( ((CPU)&0xff)<<16 ) |\
|
|
|
- ( ((CPU)&0xff)<<24 ) \
|
|
|
- )
|
|
|
-#define TARGET_CPU0_ALLINT TARGET_CPU_ALLINT(CPU(0))
|
|
|
+ rt_uint32_t dist_hw_base; /* the base address of the gic distributor */
|
|
|
+ rt_uint32_t cpu_hw_base; /* the base addrees of the gic cpu interface */
|
|
|
+};
|
|
|
|
|
|
+/* 'ARM_GIC_MAX_NR' is the number of cores */
|
|
|
+static struct arm_gic _gic_table[ARM_GIC_MAX_NR];
|
|
|
|
|
|
-#define IRQ_SET_ALL 0xffffffff;
|
|
|
+static unsigned int _gic_max_irq;
|
|
|
|
|
|
-/* Special IRQ's */
|
|
|
-#define SPECIAL_IRQ_START 1020
|
|
|
-#define IRQ_NONE 1023
|
|
|
+int arm_gic_get_active_irq(rt_uint32_t index)
|
|
|
+{
|
|
|
+ int irq;
|
|
|
|
|
|
-/* Memory map for GIC distributor */
|
|
|
-struct gic_dist_map {
|
|
|
- uint32_t enable; /* 0x000 */
|
|
|
- uint32_t ic_type; /* 0x004 */
|
|
|
- uint32_t dist_ident; /* 0x008 */
|
|
|
- uint32_t res1[29]; /* [0x00C, 0x080) */
|
|
|
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
|
|
|
|
|
|
- uint32_t group[32]; /* [0x080, 0x100) */
|
|
|
+ irq = GIC_CPU_INTACK(_gic_table[index].cpu_hw_base);
|
|
|
+ irq += _gic_table[index].offset;
|
|
|
+ return irq;
|
|
|
+}
|
|
|
|
|
|
- uint32_t enable_set[32]; /* [0x100, 0x180) */
|
|
|
- uint32_t enable_clr[32]; /* [0x180, 0x200) */
|
|
|
- uint32_t pending_set[32]; /* [0x200, 0x280) */
|
|
|
- uint32_t pending_clr[32]; /* [0x280, 0x300) */
|
|
|
- uint32_t active[32]; /* [0x300, 0x380) */
|
|
|
- uint32_t active_clr[32]; /* [0x380, 0x400) */
|
|
|
+void arm_gic_ack(rt_uint32_t index, int irq)
|
|
|
+{
|
|
|
+ rt_uint32_t mask = 1 << (irq % 32);
|
|
|
|
|
|
- uint32_t priority[255]; /* [0x400, 0x7FC) */
|
|
|
- uint32_t res2; /* 0x7FC */
|
|
|
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
|
|
|
|
|
|
- uint32_t targets[255]; /* [0x800, 0xBFC) */
|
|
|
- uint32_t res3; /* 0xBFC */
|
|
|
+ irq = irq - _gic_table[index].offset;
|
|
|
+ RT_ASSERT(irq >= 0);
|
|
|
|
|
|
- uint32_t config[64]; /* [0xC00, 0xD00) */
|
|
|
+ GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
|
|
+ GIC_CPU_EOI(_gic_table[index].cpu_hw_base) = irq;
|
|
|
+ GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
|
|
|
+}
|
|
|
|
|
|
- uint32_t ppi_status; /* [0xD00, 0xD04) */
|
|
|
- uint32_t spi_status[15]; /* [0xD04, 0xD40) */
|
|
|
- uint32_t res4[112]; /* [0xD40, 0xF00) */
|
|
|
+void arm_gic_mask(rt_uint32_t index, int irq)
|
|
|
+{
|
|
|
+ rt_uint32_t mask = 1 << (irq % 32);
|
|
|
|
|
|
- uint32_t sgi_control; /* 0xF00 */
|
|
|
- uint32_t res5[3]; /* [0xF04, 0xF10) */
|
|
|
- uint32_t sgi_pending_clr[4]; /* [0xF10, 0xF20) */
|
|
|
- uint32_t sgi_pending_set[4]; /* [0xF20, 0xF30) */
|
|
|
- uint32_t res10[40]; /* [0xF30, 0xFD0) */
|
|
|
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
|
|
|
|
|
|
- uint32_t periph_id[8]; /* [0xFD0, 0xFF0) */
|
|
|
- uint32_t component_id[4]; /* [0xFF0, 0xFFF] */
|
|
|
-};
|
|
|
+ irq = irq - _gic_table[index].offset;
|
|
|
+ RT_ASSERT(irq >= 0);
|
|
|
|
|
|
+ GIC_DIST_ENABLE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
|
|
+}
|
|
|
|
|
|
-/* Memory map for GIC cpu interface */
|
|
|
-struct gic_cpu_iface_map {
|
|
|
- uint32_t icontrol; /* 0x000 */
|
|
|
- uint32_t pri_msk_c; /* 0x004 */
|
|
|
- uint32_t bp_c; /* 0x008 */
|
|
|
- uint32_t int_ack; /* 0x00C */
|
|
|
- uint32_t eoi; /* 0x010 */
|
|
|
- uint32_t run_priority; /* 0x014 */
|
|
|
- uint32_t hi_pend; /* 0x018 */
|
|
|
- uint32_t ns_alias_bp_c; /* 0x01C */
|
|
|
- uint32_t ns_alias_ack; /* 0x020 GIC_PL400 only */
|
|
|
- uint32_t ns_alias_eoi; /* 0x024 GIC_PL400 only */
|
|
|
- uint32_t ns_alias_hi_pend; /* 0x028 GIC_PL400 only */
|
|
|
-
|
|
|
- uint32_t res1[41]; /* [0x02C, 0x0D0) */
|
|
|
- uint32_t active_priority[4]; /* [0x0D0, 0xC0] GIC_PL400 only */
|
|
|
- uint32_t ns_active_priority[4]; /* [0xE0,0xF0] GIC_PL400 only */
|
|
|
- uint32_t res4[3]; /* [0xF0, 0xFC] */
|
|
|
-
|
|
|
- uint32_t cpu_if_ident; /* 0x0FC */
|
|
|
- uint32_t deactive; /* [0x1000] */
|
|
|
-};
|
|
|
+void arm_gic_clear_pending(rt_uint32_t index, int irq)
|
|
|
+{
|
|
|
+ rt_uint32_t mask = 1 << (irq % 32);
|
|
|
|
|
|
-volatile struct gic_dist_map *gic_dist =
|
|
|
- (volatile struct gic_dist_map*)(GIC_PL400_DISTRIBUTOR_PPTR);
|
|
|
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
|
|
|
|
|
|
-volatile struct gic_cpu_iface_map *gic_cpuiface =
|
|
|
- (volatile struct gic_cpu_iface_map*)(GIC_PL400_CONTROLLER_PPTR);
|
|
|
+ irq = irq - _gic_table[index].offset;
|
|
|
+ RT_ASSERT(irq >= 0);
|
|
|
|
|
|
-/* Helpers */
|
|
|
-static inline int
|
|
|
-is_irq_pending(irq_t irq)
|
|
|
-{
|
|
|
- int word = irq / 32;
|
|
|
- int bit = irq & 0x1f;
|
|
|
- return !!(gic_dist->pending_set[word] & BIT(bit));
|
|
|
+ GIC_DIST_PENDING_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
|
|
}
|
|
|
|
|
|
-static inline int
|
|
|
-is_irq_active(irq_t irq)
|
|
|
+void arm_gic_clear_active(rt_uint32_t index, int irq)
|
|
|
{
|
|
|
- int word = irq / 32;
|
|
|
- int bit = irq & 0x1f;
|
|
|
- return !!(gic_dist->active[word] & BIT(bit));
|
|
|
-}
|
|
|
+ rt_uint32_t mask = 1 << (irq % 32);
|
|
|
|
|
|
-static inline int
|
|
|
-is_irq_enabled(irq_t irq)
|
|
|
-{
|
|
|
- int word = irq / 32;
|
|
|
- int bit = irq & 0x1f;
|
|
|
- return !!(gic_dist->enable_set[word] & BIT(bit));
|
|
|
-}
|
|
|
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
|
|
|
|
|
|
-static inline int
|
|
|
-is_irq_edge_triggered(irq_t irq)
|
|
|
-{
|
|
|
- int word = irq / 16;
|
|
|
- int bit = ((irq & 0xf) * 2);
|
|
|
- return !!(gic_dist->config[word] & BIT(bit + 1));
|
|
|
-}
|
|
|
+ irq = irq - _gic_table[index].offset;
|
|
|
+ RT_ASSERT(irq >= 0);
|
|
|
|
|
|
-static inline int
|
|
|
-is_irq_1_N(irq_t irq)
|
|
|
-{
|
|
|
- int word = irq / 16;
|
|
|
- int bit = ((irq & 0xf) * 2);
|
|
|
- return !!(gic_dist->config[word] & BIT(bit + 0));
|
|
|
+ GIC_DIST_ACTIVE_CLEAR(_gic_table[index].dist_hw_base, irq) = mask;
|
|
|
}
|
|
|
|
|
|
-static inline int
|
|
|
-is_irq_N_N(irq_t irq)
|
|
|
+/* Set up the cpu mask for the specific interrupt */
|
|
|
+void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask)
|
|
|
{
|
|
|
- return !(is_irq_1_N(irq));
|
|
|
-}
|
|
|
+ rt_uint32_t old_tgt;
|
|
|
|
|
|
-static inline void
|
|
|
-dist_pending_clr(irq_t irq)
|
|
|
-{
|
|
|
- int word = irq / 32;
|
|
|
- int bit = irq & 0x1f;
|
|
|
- /* Using |= here is detrimental to your health */
|
|
|
- gic_dist->pending_clr[word] = BIT(bit);
|
|
|
-}
|
|
|
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
|
|
|
|
|
|
-static inline void
|
|
|
-dist_pending_set(irq_t irq)
|
|
|
-{
|
|
|
- int word = irq / 32;
|
|
|
- int bit = irq & 0x1f;
|
|
|
- gic_dist->pending_set[word] = BIT(bit);
|
|
|
+ irq = irq - _gic_table[index].offset;
|
|
|
+ RT_ASSERT(irq >= 0);
|
|
|
+
|
|
|
+ old_tgt = GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq);
|
|
|
+
|
|
|
+ old_tgt &= ~(0x0FFUL << ((irq % 4)*8));
|
|
|
+ old_tgt |= cpumask << ((irq % 4)*8);
|
|
|
+
|
|
|
+ GIC_DIST_TARGET(_gic_table[index].dist_hw_base, irq) = old_tgt;
|
|
|
}
|
|
|
|
|
|
-static inline void
|
|
|
-dist_enable_clr(irq_t irq)
|
|
|
+void arm_gic_umask(rt_uint32_t index, int irq)
|
|
|
{
|
|
|
- int word = irq / 32;
|
|
|
- int bit = irq & 0x1f;
|
|
|
- /* Using |= here is detrimental to your health */
|
|
|
- gic_dist->enable_clr[word] = BIT(bit);
|
|
|
+ rt_uint32_t mask = 1 << (irq % 32);
|
|
|
+
|
|
|
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
|
|
|
+
|
|
|
+ irq = irq - _gic_table[index].offset;
|
|
|
+ RT_ASSERT(irq >= 0);
|
|
|
+
|
|
|
+ GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base, irq) = mask;
|
|
|
}
|
|
|
|
|
|
-static inline void
|
|
|
-dist_enable_set(irq_t irq)
|
|
|
+void arm_gic_dump_type(rt_uint32_t index)
|
|
|
{
|
|
|
- int word = irq / 32;
|
|
|
- int bit = irq & 0x1f;
|
|
|
- gic_dist->enable_set[word] = BIT(bit);
|
|
|
+ unsigned int gic_type;
|
|
|
+
|
|
|
+ gic_type = GIC_DIST_TYPE(_gic_table[index].dist_hw_base);
|
|
|
+ rt_kprintf("GICv%d on %p, max IRQs: %d, %s security extension(%08x)\n",
|
|
|
+ (GIC_DIST_ICPIDR2(_gic_table[index].dist_hw_base) >> 4) & 0xf,
|
|
|
+ _gic_table[index].dist_hw_base,
|
|
|
+ _gic_max_irq,
|
|
|
+ gic_type & (1 << 10) ? "has" : "no",
|
|
|
+ gic_type);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- DONT_TRANSLATE
|
|
|
- */
|
|
|
-static void dist_init(void)
|
|
|
+void arm_gic_dump(rt_uint32_t index)
|
|
|
{
|
|
|
- int i;
|
|
|
- int nirqs = 32 * ((gic_dist->ic_type & 0x1f) + 1);
|
|
|
- gic_dist->enable = 0;
|
|
|
-
|
|
|
-#if 0
|
|
|
- /* configure to group 0 for security */
|
|
|
- for (i = 0; i < nirqs; i += 32) {
|
|
|
- gic_dist->group[i / 32] = 0xffffffff;
|
|
|
- }
|
|
|
-#endif
|
|
|
-
|
|
|
- for (i = 0; i < nirqs; i += 32) {
|
|
|
- /* disable */
|
|
|
- gic_dist->enable_clr[i / 32] = IRQ_SET_ALL;
|
|
|
- /* clear pending */
|
|
|
- gic_dist->pending_clr[i / 32] = IRQ_SET_ALL;
|
|
|
- }
|
|
|
-
|
|
|
- /* reset interrupts priority */
|
|
|
- for (i = 32; i < nirqs; i += 4) {
|
|
|
- gic_dist->priority[i / 4] = 0x0;
|
|
|
+ unsigned int i, k;
|
|
|
+
|
|
|
+ k = GIC_CPU_HIGHPRI(_gic_table[index].cpu_hw_base);
|
|
|
+ rt_kprintf("--- high pending priority: %d(%08x)\n", k, k);
|
|
|
+ rt_kprintf("--- hw mask ---\n");
|
|
|
+ for (i = 0; i < _gic_max_irq / 32; i++)
|
|
|
+ {
|
|
|
+ rt_kprintf("0x%08x, ",
|
|
|
+ GIC_DIST_ENABLE_SET(_gic_table[index].dist_hw_base,
|
|
|
+ i * 32));
|
|
|
}
|
|
|
-
|
|
|
- /*
|
|
|
- * reset int target to cpu 0
|
|
|
- * (Should really query which processor we're running on and use that)
|
|
|
- */
|
|
|
- for (i = 0; i < nirqs; i += 4) {
|
|
|
- gic_dist->targets[i / 4] = TARGET_CPU0_ALLINT;
|
|
|
+ rt_kprintf("\n--- hw pending ---\n");
|
|
|
+ for (i = 0; i < _gic_max_irq / 32; i++)
|
|
|
+ {
|
|
|
+ rt_kprintf("0x%08x, ",
|
|
|
+ GIC_DIST_PENDING_SET(_gic_table[index].dist_hw_base,
|
|
|
+ i * 32));
|
|
|
}
|
|
|
-
|
|
|
- /* level-triggered, 1-N */
|
|
|
- for (i = 64; i < nirqs; i += 32) {
|
|
|
- gic_dist->config[i / 32] = 0;
|
|
|
- //gic_dist->config[i / 32] = 0x55555555;
|
|
|
+ rt_kprintf("\n--- hw active ---\n");
|
|
|
+ for (i = 0; i < _gic_max_irq / 32; i++)
|
|
|
+ {
|
|
|
+ rt_kprintf("0x%08x, ",
|
|
|
+ GIC_DIST_ACTIVE_SET(_gic_table[index].dist_hw_base,
|
|
|
+ i * 32));
|
|
|
}
|
|
|
- /* enable the int controller */
|
|
|
- gic_dist->enable = 1;
|
|
|
+ rt_kprintf("\n");
|
|
|
}
|
|
|
+#ifdef RT_USING_FINSH
|
|
|
+#include <finsh.h>
|
|
|
+FINSH_FUNCTION_EXPORT_ALIAS(arm_gic_dump, gic, show gic status);
|
|
|
+#endif
|
|
|
|
|
|
-/**
|
|
|
- DONT_TRANSLATE
|
|
|
- */
|
|
|
-static void cpu_iface_init(void)
|
|
|
+int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start)
|
|
|
{
|
|
|
- uint32_t i;
|
|
|
+ unsigned int gic_type, i;
|
|
|
+ rt_uint32_t cpumask = 1 << 0;
|
|
|
|
|
|
- /* For non-Exynos4, the registers are banked per CPU, need to clear them */
|
|
|
- gic_dist->enable_clr[0] = IRQ_SET_ALL;
|
|
|
- gic_dist->pending_clr[0] = IRQ_SET_ALL;
|
|
|
- gic_dist->priority[0] = 0x00;
|
|
|
- /* put everything in group 0 */
|
|
|
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
|
|
|
|
|
|
- /* clear any software generated interrupts */
|
|
|
- for (i = 0; i < 16; i += 4) {
|
|
|
- gic_dist->sgi_pending_clr[i / 4] = IRQ_SET_ALL;
|
|
|
- }
|
|
|
+ _gic_table[index].dist_hw_base = dist_base;
|
|
|
+ _gic_table[index].offset = irq_start;
|
|
|
|
|
|
- gic_cpuiface->icontrol = 0;
|
|
|
- gic_cpuiface->pri_msk_c = 0x000000f0;
|
|
|
- gic_cpuiface->bp_c = 0x00000003;
|
|
|
+ /* Find out how many interrupts are supported. */
|
|
|
+ gic_type = GIC_DIST_TYPE(dist_base);
|
|
|
+ _gic_max_irq = ((gic_type & 0x1f) + 1) * 32;
|
|
|
|
|
|
- while (((i = gic_cpuiface->int_ack) & IRQ_MASK) != IRQ_NONE) {
|
|
|
- gic_cpuiface->eoi = i;
|
|
|
- }
|
|
|
- gic_cpuiface->icontrol = 0x1;
|
|
|
-}
|
|
|
+ /*
|
|
|
+ * The GIC only supports up to 1020 interrupt sources.
|
|
|
+ * Limit this to either the architected maximum, or the
|
|
|
+ * platform maximum.
|
|
|
+ */
|
|
|
+ if (_gic_max_irq > 1020)
|
|
|
+ _gic_max_irq = 1020;
|
|
|
+ if (_gic_max_irq > ARM_GIC_NR_IRQS) /* the platform maximum interrupts */
|
|
|
+ _gic_max_irq = ARM_GIC_NR_IRQS;
|
|
|
|
|
|
-/**
|
|
|
- DONT_TRANSLATE
|
|
|
- */
|
|
|
-void initIRQController(void)
|
|
|
-{
|
|
|
- dist_init();
|
|
|
- cpu_iface_init();
|
|
|
-}
|
|
|
+ cpumask |= cpumask << 8;
|
|
|
+ cpumask |= cpumask << 16;
|
|
|
+ cpumask |= cpumask << 24;
|
|
|
|
|
|
+ GIC_DIST_CTRL(dist_base) = 0x0;
|
|
|
|
|
|
+ /* Set all global interrupts to be level triggered, active low. */
|
|
|
+ for (i = 32; i < _gic_max_irq; i += 16)
|
|
|
+ GIC_DIST_CONFIG(dist_base, i) = 0x0;
|
|
|
|
|
|
-/*
|
|
|
- * The only sane way to get an GIC IRQ number that can be properly
|
|
|
- * ACKED later is through the int_ack register. Unfortunately, reading
|
|
|
- * this register changes the interrupt state to pending so future
|
|
|
- * reads will not return the same value For this reason, we have a
|
|
|
- * global variable to store the IRQ number.
|
|
|
- */
|
|
|
-static uint32_t active_irq = IRQ_NONE;
|
|
|
-
|
|
|
-/**
|
|
|
- DONT_TRANSLATE
|
|
|
- */
|
|
|
-interrupt_t
|
|
|
-getActiveIRQ(void)
|
|
|
-{
|
|
|
- uint32_t irq;
|
|
|
- if (!IS_IRQ_VALID(active_irq)) {
|
|
|
- active_irq = gic_cpuiface->int_ack;
|
|
|
- }
|
|
|
+ /* Set all global interrupts to this CPU only. */
|
|
|
+ for (i = 32; i < _gic_max_irq; i += 4)
|
|
|
+ GIC_DIST_TARGET(dist_base, i) = cpumask;
|
|
|
|
|
|
- if (IS_IRQ_VALID(active_irq)) {
|
|
|
- irq = active_irq & IRQ_MASK;
|
|
|
- } else {
|
|
|
- irq = 1023;
|
|
|
- }
|
|
|
+ /* Set priority on all interrupts. */
|
|
|
+ for (i = 0; i < _gic_max_irq; i += 4)
|
|
|
+ GIC_DIST_PRI(dist_base, i) = 0xa0a0a0a0;
|
|
|
|
|
|
- return irq;
|
|
|
-}
|
|
|
+ /* Disable all interrupts. */
|
|
|
+ for (i = 0; i < _gic_max_irq; i += 32)
|
|
|
+ GIC_DIST_ENABLE_CLEAR(dist_base, i) = 0xffffffff;
|
|
|
|
|
|
-/*
|
|
|
- * GIC has 4 states: pending->active(+pending)->inactive
|
|
|
- * seL4 expects two states: active->inactive.
|
|
|
- * We ignore the active state in GIC to conform
|
|
|
- */
|
|
|
-/**
|
|
|
- DONT_TRANSLATE
|
|
|
- */
|
|
|
-bool_t
|
|
|
-isIRQPending(void)
|
|
|
-{
|
|
|
- return IS_IRQ_VALID(gic_cpuiface->hi_pend);
|
|
|
-}
|
|
|
+#if 0
|
|
|
+ /* All interrupts defaults to IGROUP1(IRQ). */
|
|
|
+ for (i = 0; i < _gic_max_irq; i += 32)
|
|
|
+ GIC_DIST_IGROUP(dist_base, i) = 0xffffffff;
|
|
|
+#endif
|
|
|
+ for (i = 0; i < _gic_max_irq; i += 32)
|
|
|
+ GIC_DIST_IGROUP(dist_base, i) = 0;
|
|
|
|
|
|
+ /* Enable group0 and group1 interrupt forwarding. */
|
|
|
+ GIC_DIST_CTRL(dist_base) = 0x01;
|
|
|
|
|
|
-/**
|
|
|
- DONT_TRANSLATE
|
|
|
- */
|
|
|
-void
|
|
|
-maskInterrupt(bool_t disable, interrupt_t irq)
|
|
|
-{
|
|
|
- if (disable) {
|
|
|
- dist_enable_clr(irq);
|
|
|
- } else {
|
|
|
- dist_enable_set(irq);
|
|
|
- }
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- DONT_TRANSLATE
|
|
|
- */
|
|
|
-void
|
|
|
-ackInterrupt(irq_t irq)
|
|
|
+int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base)
|
|
|
{
|
|
|
- if (!(IS_IRQ_VALID(active_irq) && (active_irq & IRQ_MASK) == irq)) {
|
|
|
- return;
|
|
|
- }
|
|
|
- if (is_irq_edge_triggered(irq)) {
|
|
|
- dist_pending_clr(irq);
|
|
|
- }
|
|
|
- gic_cpuiface->eoi = active_irq;
|
|
|
- active_irq = IRQ_NONE;
|
|
|
-}
|
|
|
+ RT_ASSERT(index < ARM_GIC_MAX_NR);
|
|
|
|
|
|
-void
|
|
|
-handleSpuriousIRQ(void)
|
|
|
-{
|
|
|
-}
|
|
|
+ _gic_table[index].cpu_hw_base = cpu_base;
|
|
|
|
|
|
-void rt_hw_interrupt_mask(int vector)
|
|
|
-{
|
|
|
- maskInterrupt(1, vector);
|
|
|
-}
|
|
|
+ GIC_CPU_PRIMASK(cpu_base) = 0xf0;
|
|
|
+ GIC_CPU_BINPOINT(cpu_base) = 0x7;
|
|
|
+ /* Enable CPU interrupt */
|
|
|
+ GIC_CPU_CTRL(cpu_base) = 0x01;
|
|
|
|
|
|
-void rt_hw_interrupt_umask(int vector)
|
|
|
-{
|
|
|
- maskInterrupt(0, vector);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-int rt_hw_interrupt_get_irq(void)
|
|
|
+void arm_gic_set_group(rt_uint32_t index, int vector, int group)
|
|
|
{
|
|
|
- return getActiveIRQ();
|
|
|
+ /* As for GICv2, there are only group0 and group1. */
|
|
|
+ RT_ASSERT(group <= 1);
|
|
|
+ RT_ASSERT(vector < _gic_max_irq);
|
|
|
+
|
|
|
+ if (group == 0)
|
|
|
+ {
|
|
|
+ GIC_DIST_IGROUP(_gic_table[index].dist_hw_base,
|
|
|
+ vector) &= ~(1 << (vector % 32));
|
|
|
+ }
|
|
|
+ else if (group == 1)
|
|
|
+ {
|
|
|
+ GIC_DIST_IGROUP(_gic_table[index].dist_hw_base,
|
|
|
+ vector) |= (1 << (vector % 32));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void rt_hw_interrupt_ack(int fiq_irq)
|
|
|
-{
|
|
|
- return ackInterrupt(fiq_irq);
|
|
|
-}
|