From 709e0d5799a57e9904d856fd94a935bd1deb153d Mon Sep 17 00:00:00 2001 From: bigmagic Date: Thu, 16 Apr 2020 18:48:27 +0800 Subject: [PATCH] add bsp/raspi4 gicv2 --- bsp/raspberry-pi/raspi4/driver/board.c | 7 +- bsp/raspberry-pi/raspi4/driver/iomap.h | 1 + bsp/raspberry-pi/raspi4/rtconfig.py | 2 +- libcpu/aarch64/common/gic/gic_pl400.c | 478 ++++++++++--------------- libcpu/aarch64/common/gic/gic_pl400.h | 94 +++-- libcpu/aarch64/cortex-a72/interrupt.c | 50 ++- 6 files changed, 299 insertions(+), 333 deletions(-) diff --git a/bsp/raspberry-pi/raspi4/driver/board.c b/bsp/raspberry-pi/raspi4/driver/board.c index 9716755b7..46d629a35 100644 --- a/bsp/raspberry-pi/raspi4/driver/board.c +++ b/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(); diff --git a/bsp/raspberry-pi/raspi4/driver/iomap.h b/bsp/raspberry-pi/raspi4/driver/iomap.h index 00fc2025d..675cd147e 100644 --- a/bsp/raspberry-pi/raspi4/driver/iomap.h +++ b/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) diff --git a/bsp/raspberry-pi/raspi4/rtconfig.py b/bsp/raspberry-pi/raspi4/rtconfig.py index 9265b016b..a1dd168d3 100644 --- a/bsp/raspberry-pi/raspi4/rtconfig.py +++ b/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' diff --git a/libcpu/aarch64/common/gic/gic_pl400.c b/libcpu/aarch64/common/gic/gic_pl400.c index eb35c5b2a..4d003a9dc 100644 --- a/libcpu/aarch64/common/gic/gic_pl400.c +++ b/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 #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_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); -} diff --git a/libcpu/aarch64/common/gic/gic_pl400.h b/libcpu/aarch64/common/gic/gic_pl400.h index a43583bd7..fa20846ea 100644 --- a/libcpu/aarch64/common/gic/gic_pl400.h +++ b/libcpu/aarch64/common/gic/gic_pl400.h @@ -1,35 +1,61 @@ - -#ifndef __ARCH_MACHINE_GIC_PL400_H -#define __ARCH_MACHINE_GIC_PL400_H - -#include - -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 +#include + +#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 diff --git a/libcpu/aarch64/cortex-a72/interrupt.c b/libcpu/aarch64/cortex-a72/interrupt.c index d770259d6..6fec968dc 100644 --- a/libcpu/aarch64/cortex-a72/interrupt.c +++ b/libcpu/aarch64/cortex-a72/interrupt.c @@ -13,8 +13,10 @@ #include #include #include +#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; -} \ No newline at end of file +} + +/** + * 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); +} -- GitLab