diff --git a/arch/arm/core/aarch64/CMakeLists.txt b/arch/arm/core/aarch64/CMakeLists.txt index 8b49457d3a5..f29703e8123 100644 --- a/arch/arm/core/aarch64/CMakeLists.txt +++ b/arch/arm/core/aarch64/CMakeLists.txt @@ -9,6 +9,7 @@ endif () zephyr_library_sources( cpu_idle.S fatal.c + irq_init.c irq_manage.c prep_c.c reset.S diff --git a/arch/arm/core/aarch64/irq_init.c b/arch/arm/core/aarch64/irq_init.c new file mode 100644 index 00000000000..2f2b8306a08 --- /dev/null +++ b/arch/arm/core/aarch64/irq_init.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM64 Cortex-A interrupt initialisation + */ + +#include +#include + +/** + * @brief Initialise interrupts + * + * This function invokes the ARM Generic Interrupt Controller (GIC) driver to + * initialise the interrupt system on the SoCs that use the GIC as the primary + * interrupt controller. + * + * When a custom interrupt controller is used, however, the SoC layer function + * is invoked for SoC-specific interrupt system initialisation. + */ +void z_arm64_interrupt_init(void) +{ +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + /* Initialise the Generic Interrupt Controller (GIC) driver */ + arm_gic_init(); +#else + /* Invoke SoC-specific interrupt controller initialisation */ + z_soc_irq_init(); +#endif +} diff --git a/arch/arm/core/aarch64/irq_manage.c b/arch/arm/core/aarch64/irq_manage.c index edd27c1a065..ce5aaae7f5b 100644 --- a/arch/arm/core/aarch64/irq_manage.c +++ b/arch/arm/core/aarch64/irq_manage.c @@ -11,46 +11,47 @@ #include #include -#include #include #include -#include #include #include #include +#include void z_arm64_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) +/* + * The default interrupt controller for AArch64 is the ARM Generic Interrupt + * Controller (GIC) and therefore the architecture interrupt control functions + * are mapped to the GIC driver interface. + * + * When a custom interrupt controller is used (i.e. + * CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER is enabled), the architecture + * interrupt control functions are mapped to the SoC layer in + * `include/arch/arm/aarch64/irq.h`. + */ + void arch_irq_enable(unsigned int irq) { - struct device *dev = _sw_isr_table[0].arg; - - irq_enable_next_level(dev, (irq >> 8) - 1); + arm_gic_irq_enable(irq); } void arch_irq_disable(unsigned int irq) { - struct device *dev = _sw_isr_table[0].arg; - - irq_disable_next_level(dev, (irq >> 8) - 1); + arm_gic_irq_disable(irq); } int arch_irq_is_enabled(unsigned int irq) { - struct device *dev = _sw_isr_table[0].arg; - - return irq_is_enabled_next_level(dev); + return arm_gic_irq_is_enabled(irq); } void z_arm64_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags) { - struct device *dev = _sw_isr_table[0].arg; - - if (irq == 0) - return; - - irq_set_priority_next_level(dev, (irq >> 8) - 1, prio, flags); + arm_gic_irq_set_priority(irq, prio, flags); } +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ void z_irq_spurious(void *unused) { diff --git a/arch/arm/core/aarch64/isr_wrapper.S b/arch/arm/core/aarch64/isr_wrapper.S index b0dc7f561da..e36e1000b6e 100644 --- a/arch/arm/core/aarch64/isr_wrapper.S +++ b/arch/arm/core/aarch64/isr_wrapper.S @@ -64,11 +64,29 @@ SECTION_FUNC(TEXT, _isr_wrapper) bl sys_trace_isr_enter #endif - /* Cortex-A has one IRQ line so the main handler will be at offset 0 */ + /* Get active IRQ number from the interrupt controller */ +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + bl arm_gic_get_active +#else + bl z_soc_irq_get_active +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + stp x0, x1, [sp, #-16]! + lsl x0, x0, #4 /* table is 16-byte wide */ + + /* Call interrupt service routine */ ldr x1, =_sw_isr_table + add x1, x1, x0 ldp x0, x3, [x1] /* arg in x0, ISR in x3 */ blr x3 + /* Signal end-of-interrupt */ + ldp x0, x1, [sp], #16 +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + bl arm_gic_eoi +#else + bl z_soc_irq_eoi +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + #ifdef CONFIG_TRACING bl sys_trace_isr_exit #endif diff --git a/arch/arm/core/aarch64/prep_c.c b/arch/arm/core/aarch64/prep_c.c index 01c3a1492ea..e1f149eb3d3 100644 --- a/arch/arm/core/aarch64/prep_c.c +++ b/arch/arm/core/aarch64/prep_c.c @@ -28,6 +28,7 @@ extern FUNC_NORETURN void z_cstart(void); void z_arm64_prep_c(void) { z_bss_zero(); + z_arm64_interrupt_init(); z_cstart(); CODE_UNREACHABLE; diff --git a/include/arch/arm/aarch64/irq.h b/include/arch/arm/aarch64/irq.h index 47002d9754d..3fa4534d9e4 100644 --- a/include/arch/arm/aarch64/irq.h +++ b/include/arch/arm/aarch64/irq.h @@ -27,7 +27,14 @@ extern "C" { GTEXT(arch_irq_enable) GTEXT(arch_irq_disable) GTEXT(arch_irq_is_enabled) +#if defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) +GTEXT(z_soc_irq_get_active) +GTEXT(z_soc_irq_eoi) +#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ #else + +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + extern void arch_irq_enable(unsigned int irq); extern void arch_irq_disable(unsigned int irq); extern int arch_irq_is_enabled(unsigned int irq); @@ -36,6 +43,35 @@ extern int arch_irq_is_enabled(unsigned int irq); extern void z_arm64_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags); +#else + +/* + * When a custom interrupt controller is specified, map the architecture + * interrupt control functions to the SoC layer interrupt control functions. + */ + +void z_soc_irq_init(void); +void z_soc_irq_enable(unsigned int irq); +void z_soc_irq_disable(unsigned int irq); +int z_soc_irq_is_enabled(unsigned int irq); + +void z_soc_irq_priority_set( + unsigned int irq, unsigned int prio, unsigned int flags); + +unsigned int z_soc_irq_get_active(void); +void z_soc_irq_eoi(unsigned int irq); + +#define arch_irq_enable(irq) z_soc_irq_enable(irq) +#define arch_irq_disable(irq) z_soc_irq_disable(irq) +#define arch_irq_is_enabled(irq) z_soc_irq_is_enabled(irq) + +#define z_arm64_irq_priority_set(irq, prio, flags) \ + z_soc_irq_priority_set(irq, prio, flags) + +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + +extern void z_arm64_interrupt_init(void); + /* All arguments must be computable by the compiler at build time. * * Z_ISR_DECLARE will populate the .intList section with the interrupt's diff --git a/include/arch/arm/aarch64/timer.h b/include/arch/arm/aarch64/timer.h index 6964eb58100..384b7e29e0c 100644 --- a/include/arch/arm/aarch64/timer.h +++ b/include/arch/arm/aarch64/timer.h @@ -16,7 +16,7 @@ extern "C" { #endif -#define ARM_ARCH_TIMER_IRQ ((ARM_TIMER_VIRTUAL_IRQ + 1) << 8) +#define ARM_ARCH_TIMER_IRQ ARM_TIMER_VIRTUAL_IRQ #define CNTV_CTL_ENABLE ((1) << 0)