Selaa lähdekoodia

add bsp/raspi4 gicv2

bigmagic 5 vuotta sitten
vanhempi
commit
709e0d5799

+ 3 - 4
bsp/raspberry-pi/raspi4/driver/board.c

@@ -75,10 +75,6 @@ void rt_hw_board_init(void)
     rt_hw_interrupt_init(); // in libcpu/interrupt.c. Set some data structures, no operation on device
     rt_hw_vector_init();    // in libcpu/interrupt.c. == rt_cpu_vector_set_base((rt_ubase_t)&system_vectors);
 
-    /* initialize timer for os tick */
-    rt_hw_timer_init();
-    rt_thread_idle_sethook(idle_wfi);
-
     /* initialize uart */
     rt_hw_uart_init();      // driver/drv_uart.c
 #ifdef RT_USING_CONSOLE
@@ -91,6 +87,9 @@ void rt_hw_board_init(void)
     rt_kprintf("heap: 0x%08x - 0x%08x\n", RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
     rt_system_heap_init(RT_HW_HEAP_BEGIN, RT_HW_HEAP_END);
 #endif
+        /* initialize timer for os tick */
+    rt_hw_timer_init();
+    rt_thread_idle_sethook(idle_wfi);
 
 #ifdef RT_USING_COMPONENTS_INIT
     rt_components_board_init();

+ 1 - 0
bsp/raspberry-pi/raspi4/driver/iomap.h

@@ -1,6 +1,7 @@
 #ifndef __RASPI4_H__
 #define __RASPI4_H__
 
+#define ARM_GIC_NR_IRQS     512
 #define INTC_BASE   0xff800000
 #define GIC_V2_DISTRIBUTOR_BASE     (INTC_BASE + 0x00041000)
 #define GIC_V2_CPU_INTERFACE_BASE   (INTC_BASE + 0x00042000)

+ 1 - 1
bsp/raspberry-pi/raspi4/rtconfig.py

@@ -32,7 +32,7 @@ if PLATFORM == 'gcc':
     OBJDUMP = PREFIX + 'objdump'
     OBJCPY  = PREFIX + 'objcopy'
 
-    DEVICE = ' -march=armv8-a -mtune=cortex-a57'
+    DEVICE = ' -march=armv8-a -mtune=cortex-a72'
     CFLAGS = DEVICE + ' -Wall'
     AFLAGS = ' -c' + ' -x assembler-with-cpp -D__ASSEMBLY__'
     LFLAGS  = DEVICE + ' -nostartfiles -Wl,--gc-sections,-Map=rtthread.map,-cref,-u,system_vectors -T link.lds'

+ 186 - 292
libcpu/aarch64/common/gic/gic_pl400.c

@@ -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);
-}

+ 60 - 34
libcpu/aarch64/common/gic/gic_pl400.h

@@ -1,35 +1,61 @@
-
-#ifndef __ARCH_MACHINE_GIC_PL400_H
-#define __ARCH_MACHINE_GIC_PL400_H
-
-#include <stdint.h>
-
-typedef uint16_t interrupt_t;
-typedef uint16_t irq_t;
-typedef uint64_t  bool_t;
-
-/** MODIFIES: [*] */
-interrupt_t getActiveIRQ(void);
-/** MODIFIES: [*] */
-interrupt_t getPendingIRQ(void);
-/** MODIFIES: [*] */
-bool_t isIRQPending(void);
-/** MODIFIES: [*] */
-void maskInterrupt(bool_t disable, interrupt_t irq);
-/** MODIFIES: [*] */
-void ackInterrupt(irq_t irq);
-/** MODIFIES: [*] */
-static inline void setInterruptMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow) { }
-
-/** MODIFIES: [*] */
-void initIRQController(void);
-
-void handleSpuriousIRQ(void);
-
-void rt_hw_interrupt_umask(int vector);
-
-int rt_hw_interrupt_get_irq(void);
-
-void rt_hw_interrupt_ack(int fiq_irq);
-#endif /* !__ARCH_MACHINE_GIC400_H */
+/*
+ * Copyright (c) 2006-2018, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2013-07-20     Bernard      first version
+ */
+
+#ifndef __GIC_PL400_H__
+#define __GIC_PL400_H__
+
+#include <rthw.h>
+#include <board.h>
+
+#define __REG32(x) (*((volatile unsigned int*)((rt_uint64_t)x)))
+
+#define GIC_CPU_CTRL(hw_base)               __REG32((hw_base) + 0x00)
+#define GIC_CPU_PRIMASK(hw_base)            __REG32((hw_base) + 0x04)
+#define GIC_CPU_BINPOINT(hw_base)           __REG32((hw_base) + 0x08)
+#define GIC_CPU_INTACK(hw_base)             __REG32((hw_base) + 0x0c)
+#define GIC_CPU_EOI(hw_base)                __REG32((hw_base) + 0x10)
+#define GIC_CPU_RUNNINGPRI(hw_base)         __REG32((hw_base) + 0x14)
+#define GIC_CPU_HIGHPRI(hw_base)            __REG32((hw_base) + 0x18)
+
+#define GIC_DIST_CTRL(hw_base)              __REG32((hw_base) + 0x000)
+#define GIC_DIST_TYPE(hw_base)              __REG32((hw_base) + 0x004)
+#define GIC_DIST_IGROUP(hw_base, n)         __REG32((hw_base) + 0x080 + ((n)/32) * 4)
+#define GIC_DIST_ENABLE_SET(hw_base, n)     __REG32((hw_base) + 0x100 + ((n)/32) * 4)
+#define GIC_DIST_ENABLE_CLEAR(hw_base, n)   __REG32((hw_base) + 0x180 + ((n)/32) * 4)
+#define GIC_DIST_PENDING_SET(hw_base, n)    __REG32((hw_base) + 0x200 + ((n)/32) * 4)
+#define GIC_DIST_PENDING_CLEAR(hw_base, n)  __REG32((hw_base) + 0x280 + ((n)/32) * 4)
+#define GIC_DIST_ACTIVE_SET(hw_base, n)     __REG32((hw_base) + 0x300 + ((n)/32) * 4)
+#define GIC_DIST_ACTIVE_CLEAR(hw_base, n)   __REG32((hw_base) + 0x380 + ((n)/32) * 4)
+#define GIC_DIST_PRI(hw_base, n)            __REG32((hw_base) + 0x400 +  ((n)/4) * 4)
+#define GIC_DIST_TARGET(hw_base, n)         __REG32((hw_base) + 0x800 +  ((n)/4) * 4)
+#define GIC_DIST_CONFIG(hw_base, n)         __REG32((hw_base) + 0xc00 + ((n)/16) * 4)
+#define GIC_DIST_SOFTINT(hw_base)           __REG32((hw_base) + 0xf00)
+#define GIC_DIST_CPENDSGI(hw_base, n)       __REG32((hw_base) + 0xf10 + ((n)/4) * 4)
+#define GIC_DIST_ICPIDR2(hw_base)           __REG32((hw_base) + 0xfe8)
+
+int arm_gic_dist_init(rt_uint32_t index, rt_uint32_t dist_base, int irq_start);
+int arm_gic_cpu_init(rt_uint32_t index, rt_uint32_t cpu_base);
+
+void arm_gic_mask(rt_uint32_t index, int irq);
+void arm_gic_umask(rt_uint32_t index, int irq);
+void arm_gic_set_cpu(rt_uint32_t index, int irq, unsigned int cpumask);
+void arm_gic_set_group(rt_uint32_t index, int vector, int group);
+
+int arm_gic_get_active_irq(rt_uint32_t index);
+void arm_gic_ack(rt_uint32_t index, int irq);
+
+void arm_gic_clear_active(rt_uint32_t index, int irq);
+void arm_gic_clear_pending(rt_uint32_t index, int irq);
+
+void arm_gic_dump_type(rt_uint32_t index);
+void arm_gic_dump(rt_uint32_t index);
+
+#endif
 

+ 48 - 2
libcpu/aarch64/cortex-a72/interrupt.c

@@ -13,8 +13,10 @@
 #include <gic_pl400.h>
 #include <board.h>
 #include <armv8.h>
+#include "iomap.h"
 
 #define MAX_HANDLERS                256
+#define GIC_ACK_INTID_MASK          0x000003ff
 
 #ifdef RT_USING_SMP
 #define rt_interrupt_nest rt_cpu_self()->irq_nest
@@ -41,7 +43,15 @@ void rt_hw_vector_init(void)
  */
 void rt_hw_interrupt_init(void)
 {
-    initIRQController();
+
+    rt_uint32_t gic_cpu_base = 0;
+    rt_uint32_t gic_dist_base = 0;
+
+    /* initialize ARM GIC */
+    gic_dist_base = GIC_PL400_DISTRIBUTOR_PPTR;
+    gic_cpu_base = GIC_PL400_CONTROLLER_PPTR;
+    arm_gic_dist_init(0, gic_dist_base, 0);
+    arm_gic_cpu_init(0, gic_cpu_base);
 }
 
 /**
@@ -70,4 +80,40 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler,
     }
 
     return old_handler;
-}
+}
+
+/**
+ * This function will mask a interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_mask(int vector)
+{
+    arm_gic_mask(0, vector);
+}
+
+/**
+ * This function will un-mask a interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_umask(int vector)
+{
+    arm_gic_umask(0, vector);
+}
+
+/**
+ * This function returns the active interrupt number.
+ * @param none
+ */
+int rt_hw_interrupt_get_irq(void)
+{
+    return arm_gic_get_active_irq(0) & GIC_ACK_INTID_MASK;
+}
+
+/**
+ * This function acknowledges the interrupt.
+ * @param vector the interrupt number
+ */
+void rt_hw_interrupt_ack(int vector)
+{
+    arm_gic_ack(0, vector);
+}