diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 4176617eb851..47e8e447b29c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -16,4 +16,24 @@ config ARM64 bool select 64BIT +config ARM_CUSTOM_INTERRUPT_CONTROLLER + bool + depends on !CPU_CORTEX_M + help + This option indicates that the ARM CPU is connected to a custom (i.e. + non-GIC) interrupt controller. + + A number of Cortex-A and Cortex-R cores (Cortex-A5, Cortex-R4/5, ...) + allow interfacing to a custom external interrupt controller and this + option must be selected when such cores are connected to an interrupt + controller that is not the ARM Generic Interrupt Controller (GIC). + + When this option is selected, the architecture interrupt control + functions are mapped to the SoC interrupt control interface, which is + implemented at the SoC level. + + N.B. This option is only applicable to the Cortex-A and Cortex-R + family cores. The Cortex-M family cores are always equipped with + the ARM Nested Vectored Interrupt Controller (NVIC). + endmenu diff --git a/arch/arm/core/aarch32/cortex_r/CMakeLists.txt b/arch/arm/core/aarch32/cortex_r/CMakeLists.txt index a1154a3efb94..52b6d71804e9 100644 --- a/arch/arm/core/aarch32/cortex_r/CMakeLists.txt +++ b/arch/arm/core/aarch32/cortex_r/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library_sources( vector_table.S reset.S fault.c + irq_init.c reboot.c stacks.c ) diff --git a/arch/arm/core/aarch32/cortex_r/irq_init.c b/arch/arm/core/aarch32/cortex_r/irq_init.c new file mode 100644 index 000000000000..e6a96bf39579 --- /dev/null +++ b/arch/arm/core/aarch32/cortex_r/irq_init.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020 Stephanos Ioannidis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief ARM Cortex-R interrupt initialization + */ + +#include +#include + +/** + * + * @brief Initialize interrupts + * + * @return N/A + */ +void z_arm_interrupt_init(void) +{ + /* + * Initialise interrupt controller. + */ +#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/aarch32/irq_manage.c b/arch/arm/core/aarch32/irq_manage.c index 6d1cf304b4ad..0130bdd5a1f5 100644 --- a/arch/arm/core/aarch32/irq_manage.c +++ b/arch/arm/core/aarch32/irq_manage.c @@ -18,9 +18,8 @@ #include #if defined(CONFIG_CPU_CORTEX_M) #include -#elif defined(CONFIG_CPU_CORTEX_R) -#include -#include +#elif defined(CONFIG_CPU_CORTEX_A) || defined(CONFIG_CPU_CORTEX_R) +#include #endif #include #include @@ -96,26 +95,32 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, u32_t flags) NVIC_SetPriority((IRQn_Type)irq, prio); } -#elif defined(CONFIG_CPU_CORTEX_R) +#elif defined(CONFIG_CPU_CORTEX_A) || defined(CONFIG_CPU_CORTEX_R) +/* + * For Cortex-A and Cortex-R cores, the default interrupt controller 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/aarch32/irq.h`. + */ + +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) 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); } /** @@ -132,15 +137,11 @@ int arch_irq_is_enabled(unsigned int irq) */ void z_arm_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 */ -#endif +#endif /* CONFIG_CPU_CORTEX_M */ void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); diff --git a/arch/arm/core/aarch32/isr_wrapper.S b/arch/arm/core/aarch32/isr_wrapper.S index 4aa3049c725a..0d350fc7394f 100644 --- a/arch/arm/core/aarch32/isr_wrapper.S +++ b/arch/arm/core/aarch32/isr_wrapper.S @@ -126,7 +126,6 @@ _idle_state_cleared: #if defined(CONFIG_CPU_CORTEX_M) mrs r0, IPSR /* get exception number */ -#endif #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) ldr r1, =16 subs r0, r1 /* get IRQ number */ @@ -134,15 +133,19 @@ _idle_state_cleared: #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) sub r0, r0, #16 /* get IRQ number */ lsl r0, r0, #3 /* table is 8-byte wide */ -#elif defined(CONFIG_ARMV7_R) - /* - * Cortex-R only has one IRQ line so the main handler will be at - * offset 0 of the table. - */ - mov r0, #0 +#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ +#elif defined(CONFIG_CPU_CORTEX_R) + /* 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 */ + push {r0, r1} + lsl r0, r0, #3 /* table is 8-byte wide */ #else #error Unknown ARM architecture -#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ +#endif /* CONFIG_CPU_CORTEX_M */ ldr r1, =_sw_isr_table add r1, r1, r0 /* table entry: ISRs must have their MSB set to stay * in thumb mode */ @@ -162,6 +165,16 @@ _idle_state_cleared: #endif /* CONFIG_EXECUTION_BENCHMARKING */ blx r3 /* call ISR */ +#if defined(CONFIG_CPU_CORTEX_R) + /* Signal end-of-interrupt */ + pop {r0, r1} +#if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) + bl arm_gic_eoi +#else + bl z_soc_irq_eoi +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ +#endif /* CONFIG_CPU_CORTEX_R */ + #ifdef CONFIG_TRACING_ISR bl sys_trace_isr_exit #endif diff --git a/arch/arm/core/aarch64/CMakeLists.txt b/arch/arm/core/aarch64/CMakeLists.txt index 8b49457d3a5f..f29703e81237 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 000000000000..2f2b8306a08f --- /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 edd27c1a0651..ce5aaae7f5b9 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 b0dc7f561da6..e36e1000b6eb 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 01c3a1492ea1..e1f149eb3d32 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/drivers/interrupt_controller/intc_gic.c b/drivers/interrupt_controller/intc_gic.c index 9aff07d006cf..241531acd24a 100644 --- a/drivers/interrupt_controller/intc_gic.c +++ b/drivers/interrupt_controller/intc_gic.c @@ -11,9 +11,7 @@ * GICv3 interface is not supported. */ -#include #include -#include #include #include @@ -21,9 +19,74 @@ #error "GICv3 and above are not supported" #endif -struct gic_ictl_config { - u32_t isr_table_offset; -}; +void arm_gic_irq_enable(unsigned int irq) +{ + int int_grp, int_off; + + int_grp = irq / 32; + int_off = irq % 32; + + sys_write32((1 << int_off), (GICD_ISENABLERn + int_grp * 4)); +} + +void arm_gic_irq_disable(unsigned int irq) +{ + int int_grp, int_off; + + int_grp = irq / 32; + int_off = irq % 32; + + sys_write32((1 << int_off), (GICD_ICENABLERn + int_grp * 4)); +} + +bool arm_gic_irq_is_enabled(unsigned int irq) +{ + int int_grp, int_off; + unsigned int enabler; + + int_grp = irq / 32; + int_off = irq % 32; + + enabler = sys_read32(GICD_ISENABLERn + int_grp * 4); + + return (enabler & (1 << int_off)) != 0; +} + +void arm_gic_irq_set_priority( + unsigned int irq, unsigned int prio, u32_t flags) +{ + int int_grp, int_off; + u8_t val; + + /* Set priority */ + sys_write8(prio & 0xff, GICD_IPRIORITYRn + irq); + + /* Set interrupt type */ + int_grp = irq / 4; + int_off = (irq % 16) * 2; + + val = sys_read8(GICD_ICFGRn + int_grp); + val &= ~(GICC_ICFGR_MASK << int_off); + if (flags & IRQ_TYPE_EDGE) { + val |= (GICC_ICFGR_TYPE << int_off); + } + + sys_write8(val, GICD_ICFGRn + int_grp); +} + +unsigned int arm_gic_get_active(void) +{ + int irq; + + irq = sys_read32(GICC_IAR) & 0x3ff; + return irq; +} + +void arm_gic_eoi(unsigned int irq) +{ + /* set to inactive */ + sys_write32(irq, GICC_EOIR); +} static void gic_dist_init(void) { @@ -31,8 +94,9 @@ static void gic_dist_init(void) gic_irqs = sys_read32(GICD_TYPER) & 0x1f; gic_irqs = (gic_irqs + 1) * 32; - if (gic_irqs > 1020) + if (gic_irqs > 1020) { gic_irqs = 1020; + } /* * Disable the forwarding of pending interrupts @@ -43,22 +107,26 @@ static void gic_dist_init(void) /* * Set all global interrupts to this CPU only. */ - for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 4) + for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 4) { sys_write32(0x01010101, GICD_ITARGETSRn + i); + } /* * Set all global interrupts to be level triggered, active low. */ - for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 16) + for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 16) { sys_write32(0, GICD_ICFGRn + i / 4); + } /* Set priority on all global interrupts. */ - for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 4) + for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 4) { sys_write32(0, GICD_IPRIORITYRn + i); + } /* Set all interrupts to group 0 */ - for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 32) + for (i = GIC_SPI_INT_BASE; i < gic_irqs; i += 32) { sys_write32(0, GICD_IGROUPRn + i / 8); + } /* * Disable all interrupts. Leave the PPI and SGIs alone @@ -96,8 +164,9 @@ static void gic_cpu_init(void) /* * Set priority on PPI and SGI interrupts */ - for (i = 0; i < 32; i += 4) + for (i = 0; i < 32; i += 4) { sys_write32(0xa0a0a0a0, GICD_IPRIORITYRn + i); + } sys_write32(0xf0, GICC_PMR); @@ -112,94 +181,6 @@ static void gic_cpu_init(void) sys_write32(val, GICC_CTLR); } -static void gic_irq_enable(struct device *dev, unsigned int irq) -{ - int int_grp, int_off; - - int_grp = irq / 32; - int_off = irq % 32; - - sys_write32((1 << int_off), (GICD_ISENABLERn + int_grp * 4)); -} - -static void gic_irq_disable(struct device *dev, unsigned int irq) -{ - int int_grp, int_off; - - int_grp = irq / 32; - int_off = irq % 32; - - sys_write32((1 << int_off), (GICD_ICENABLERn + int_grp * 4)); -} - -static unsigned int gic_irq_get_state(struct device *dev) -{ - return 1; -} - -static void gic_irq_set_priority(struct device *dev, - unsigned int irq, unsigned int prio, u32_t flags) -{ - int int_grp, int_off; - u8_t val; - - /* Set priority */ - sys_write8(prio & 0xff, GICD_IPRIORITYRn + irq); - - /* Set interrupt type */ - int_grp = irq / 4; - int_off = (irq % 16) * 2; - - val = sys_read8(GICD_ICFGRn + int_grp); - val &= ~(GICC_ICFGR_MASK << int_off); - if (flags & IRQ_TYPE_EDGE) - val |= (GICC_ICFGR_TYPE << int_off); - sys_write8(val, GICD_ICFGRn + int_grp); -} - -static void gic_isr(void *arg) -{ - struct device *dev = arg; - const struct gic_ictl_config *cfg = dev->config->config_info; - void (*gic_isr_handle)(void *); - int irq, isr_offset; - - irq = sys_read32(GICC_IAR); - irq &= 0x3ff; - - if (irq == GICC_IAR_SPURIOUS) { - printk("gic: Invalid interrupt\n"); - return; - } - - isr_offset = cfg->isr_table_offset + irq; - - gic_isr_handle = _sw_isr_table[isr_offset].isr; - if (gic_isr_handle) - gic_isr_handle(_sw_isr_table[isr_offset].arg); - else - printk("gic: no handler found for int %d\n", irq); - - /* set to inactive */ - sys_write32(irq, GICC_EOIR); -} - -static int gic_init(struct device *unused); -static const struct irq_next_level_api gic_apis = { - .intr_enable = gic_irq_enable, - .intr_disable = gic_irq_disable, - .intr_get_state = gic_irq_get_state, - .intr_set_priority = gic_irq_set_priority, -}; - -static const struct gic_ictl_config gic_config = { - .isr_table_offset = CONFIG_2ND_LVL_ISR_TBL_OFFSET, -}; - -DEVICE_AND_API_INIT(arm_gic, DT_INST_0_ARM_GIC_LABEL, - gic_init, NULL, &gic_config, - PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &gic_apis); - /** * * @brief Initialize the GIC device driver @@ -210,11 +191,8 @@ DEVICE_AND_API_INIT(arm_gic, DT_INST_0_ARM_GIC_LABEL, #define GIC_PARENT_IRQ 0 #define GIC_PARENT_IRQ_PRI 0 #define GIC_PARENT_IRQ_FLAGS 0 -static int gic_init(struct device *unused) +int arm_gic_init(void) { - IRQ_CONNECT(GIC_PARENT_IRQ, GIC_PARENT_IRQ_PRI, gic_isr, - DEVICE_GET(arm_gic), GIC_PARENT_IRQ_FLAGS); - /* Init of Distributor interface registers */ gic_dist_init(); diff --git a/include/arch/arm/aarch32/arch.h b/include/arch/arm/aarch32/arch.h index c008b06ab9e2..71ba6045c4bf 100644 --- a/include/arch/arm/aarch32/arch.h +++ b/include/arch/arm/aarch32/arch.h @@ -6,9 +6,9 @@ /** * @file - * @brief ARM specific kernel interface header + * @brief ARM AArch32 specific kernel interface header * - * This header contains the ARM specific kernel interface. It is + * This header contains the ARM AArch32 specific kernel interface. It is * included by the kernel interface architecture-abstraction header * (include/arm/cpu.h) */ diff --git a/include/arch/arm/aarch32/asm_inline.h b/include/arch/arm/aarch32/asm_inline.h index db045ca83bb4..0b759ec43f16 100644 --- a/include/arch/arm/aarch32/asm_inline.h +++ b/include/arch/arm/aarch32/asm_inline.h @@ -1,4 +1,4 @@ -/* Intel ARM inline assembler functions and macros for public functions */ +/* ARM AArch32 inline assembler functions and macros for public functions */ /* * Copyright (c) 2015, Wind River Systems, Inc. diff --git a/include/arch/arm/aarch32/asm_inline_gcc.h b/include/arch/arm/aarch32/asm_inline_gcc.h index 2ff8e45c0d33..e7c96a701687 100644 --- a/include/arch/arm/aarch32/asm_inline_gcc.h +++ b/include/arch/arm/aarch32/asm_inline_gcc.h @@ -1,4 +1,4 @@ -/* ARM Cortex-M GCC specific public inline assembler functions and macros */ +/* ARM AArch32 GCC specific public inline assembler functions and macros */ /* * Copyright (c) 2015, Wind River Systems, Inc. diff --git a/include/arch/arm/aarch32/error.h b/include/arch/arm/aarch32/error.h index 8d7e2a09716e..2c584cdf97ce 100644 --- a/include/arch/arm/aarch32/error.h +++ b/include/arch/arm/aarch32/error.h @@ -6,9 +6,10 @@ /** * @file - * @brief Cortex-M public error handling + * @brief ARM AArch32 public error handling * - * ARM-specific kernel error handling interface. Included by arm/arch.h. + * ARM AArch32-specific kernel error handling interface. Included by + * arm/arch.h. */ #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_ERROR_H_ diff --git a/include/arch/arm/aarch32/exc.h b/include/arch/arm/aarch32/exc.h index a633fe0ce77a..729afba37c7a 100644 --- a/include/arch/arm/aarch32/exc.h +++ b/include/arch/arm/aarch32/exc.h @@ -8,7 +8,8 @@ * @file * @brief ARM AArch32 public exception handling * - * ARM-specific kernel exception handling interface. Included by arm/arch.h. + * ARM AArch32-specific kernel exception handling interface. Included by + * arm/arch.h. */ #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_EXC_H_ diff --git a/include/arch/arm/aarch32/irq.h b/include/arch/arm/aarch32/irq.h index 5ecd94db4978..1a9f59842cc3 100644 --- a/include/arch/arm/aarch32/irq.h +++ b/include/arch/arm/aarch32/irq.h @@ -7,9 +7,10 @@ /** * @file - * @brief Cortex-M public interrupt handling + * @brief ARM AArch32 public interrupt handling * - * ARM-specific kernel interrupt handling interface. Included by arm/arch.h. + * ARM AArch32-specific kernel interrupt handling interface. Included by + * arm/arch.h. */ #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_IRQ_H_ @@ -28,20 +29,52 @@ GTEXT(z_arm_int_exit); 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); -extern void z_arm_int_exit(void); +/* internal routine documented in C file, needed by IRQ_CONNECT() macro */ +extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, + u32_t flags); -#if defined(CONFIG_ARMV7_R) -static ALWAYS_INLINE void z_arm_interrupt_init(void) -{ -} #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_arm_irq_priority_set(irq, prio, flags) \ + z_soc_irq_priority_set(irq, prio, flags) + +#endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + +extern void z_arm_int_exit(void); + extern void z_arm_interrupt_init(void); -#endif /* macros convert value of it's argument to a string */ #define DO_TOSTR(s) #s @@ -51,11 +84,6 @@ extern void z_arm_interrupt_init(void); #define DO_CONCAT(x, y) x ## y #define CONCAT(x, y) DO_CONCAT(x, y) -/* internal routine documented in C file, needed by IRQ_CONNECT() macro */ -extern void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, - u32_t flags); - - /* Flags for use with IRQ_CONNECT() */ #ifdef CONFIG_ZERO_LATENCY_IRQS /** diff --git a/include/arch/arm/aarch32/misc.h b/include/arch/arm/aarch32/misc.h index d085308cf4cb..b7fac9662acf 100644 --- a/include/arch/arm/aarch32/misc.h +++ b/include/arch/arm/aarch32/misc.h @@ -6,9 +6,9 @@ /** * @file - * @brief Cortex-M public kernel miscellaneous + * @brief ARM AArch32 public kernel miscellaneous * - * ARM-specific kernel miscellaneous interface. Included by arm/arch.h. + * ARM AArch32-specific kernel miscellaneous interface. Included by arm/arch.h. */ #ifndef ZEPHYR_INCLUDE_ARCH_ARM_AARCH32_MISC_H_ diff --git a/include/arch/arm/aarch32/nmi.h b/include/arch/arm/aarch32/nmi.h index 9d4459fe4172..4e7417e7a0f6 100644 --- a/include/arch/arm/aarch32/nmi.h +++ b/include/arch/arm/aarch32/nmi.h @@ -1,7 +1,7 @@ /** * @file * - * @brief NMI routines for ARM Cortex M series + * @brief ARM AArch32 NMI routines */ /* diff --git a/include/arch/arm/aarch32/syscall.h b/include/arch/arm/aarch32/syscall.h index b4c63ea9c99d..4301990b7947 100644 --- a/include/arch/arm/aarch32/syscall.h +++ b/include/arch/arm/aarch32/syscall.h @@ -6,9 +6,9 @@ /** * @file - * @brief ARM specific syscall header + * @brief ARM AArch32 specific syscall header * - * This header contains the ARM specific syscall interface. It is + * This header contains the ARM AArch32 specific syscall interface. It is * included by the syscall interface architecture-abstraction header * (include/arch/syscall.h) */ diff --git a/include/arch/arm/aarch64/irq.h b/include/arch/arm/aarch64/irq.h index 47002d9754d9..3fa4534d9e4d 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 6964eb581009..384b7e29e0c7 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) diff --git a/include/drivers/interrupt_controller/gic.h b/include/drivers/interrupt_controller/gic.h index 8cedd88a9528..7d6387514e73 100644 --- a/include/drivers/interrupt_controller/gic.h +++ b/include/drivers/interrupt_controller/gic.h @@ -4,10 +4,20 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief Driver for ARM Generic Interrupt Controller + * + * The Generic Interrupt Controller (GIC) is the default interrupt controller + * for the ARM A and R profile cores. This driver is used by the ARM arch + * implementation to handle interrupts. + */ + #ifndef ZEPHYR_INCLUDE_DRIVERS_GIC_H_ #define ZEPHYR_INCLUDE_DRIVERS_GIC_H_ -#include +#include +#include /* * GIC Register Interface Base Addresses @@ -196,4 +206,65 @@ #endif /* CONFIG_GIC_VER <= 2 */ +#ifndef _ASMLANGUAGE + +/* + * GIC Driver Interface Functions + */ + +/** + * @brief Initialise ARM GIC driver + * + * @return 0 if successful + */ +int arm_gic_init(void); + +/** + * @brief Enable interrupt + * + * @param irq interrupt ID + */ +void arm_gic_irq_enable(unsigned int irq); + +/** + * @brief Disable interrupt + * + * @param irq interrupt ID + */ +void arm_gic_irq_disable(unsigned int irq); + +/** + * @brief Check if an interrupt is enabled + * + * @param irq interrupt ID + * @return Returns true if interrupt is enabled, false otherwise + */ +bool arm_gic_irq_is_enabled(unsigned int irq); + +/** + * @brief Set interrupt priority + * + * @param irq interrupt ID + * @param prio interrupt priority + * @param flags interrupt flags + */ +void arm_gic_irq_set_priority( + unsigned int irq, unsigned int prio, unsigned int flags); + +/** + * @brief Get active interrupt ID + * + * @return Returns the ID of an active interrupt + */ +unsigned int arm_gic_get_active(void); + +/** + * @brief Signal end-of-interrupt + * + * @param irq interrupt ID + */ +void arm_gic_eoi(unsigned int irq); + +#endif /* !_ASMLANGUAGE */ + #endif /* ZEPHYR_INCLUDE_DRIVERS_GIC_H_ */ diff --git a/soc/arm/qemu_cortex_a53/Kconfig.defconfig b/soc/arm/qemu_cortex_a53/Kconfig.defconfig index d9990fa6c193..3c5ce0822c83 100644 --- a/soc/arm/qemu_cortex_a53/Kconfig.defconfig +++ b/soc/arm/qemu_cortex_a53/Kconfig.defconfig @@ -11,15 +11,6 @@ config NUM_IRQS # - include the UART interrupts default 220 -config 2ND_LVL_ISR_TBL_OFFSET - default 1 - -config MAX_IRQ_PER_AGGREGATOR - default 219 - -config NUM_2ND_LEVEL_AGGREGATORS - default 1 - config SYS_CLOCK_HW_CYCLES_PER_SEC default 62500000 diff --git a/soc/arm/qemu_cortex_a53/Kconfig.soc b/soc/arm/qemu_cortex_a53/Kconfig.soc index b69baec261cd..0a0305cc4953 100644 --- a/soc/arm/qemu_cortex_a53/Kconfig.soc +++ b/soc/arm/qemu_cortex_a53/Kconfig.soc @@ -6,5 +6,3 @@ config SOC_QEMU_CORTEX_A53 select ARM select CPU_CORTEX_A53 select GIC_V2 - select MULTI_LEVEL_INTERRUPTS - select 2ND_LEVEL_INTERRUPTS diff --git a/soc/arm/qemu_cortex_a53/dts_fixup.h b/soc/arm/qemu_cortex_a53/dts_fixup.h index 390c8a1455ee..e65598a797f0 100644 --- a/soc/arm/qemu_cortex_a53/dts_fixup.h +++ b/soc/arm/qemu_cortex_a53/dts_fixup.h @@ -5,6 +5,3 @@ */ #define DT_INST_0_SHARED_IRQ_IRQ_0_SENSE DT_INST_0_SHARED_IRQ_IRQ_0_FLAGS - -#undef DT_INST_0_SHARED_IRQ_IRQ_0 -#define DT_INST_0_SHARED_IRQ_IRQ_0 ((DT_SHARED_IRQ_SHAREDIRQ0_IRQ_0 + 1) << 8) diff --git a/soc/arm/xilinx_zynqmp/Kconfig.defconfig b/soc/arm/xilinx_zynqmp/Kconfig.defconfig index 75c0ff5c8799..25b189edc3de 100644 --- a/soc/arm/xilinx_zynqmp/Kconfig.defconfig +++ b/soc/arm/xilinx_zynqmp/Kconfig.defconfig @@ -14,15 +14,6 @@ config NUM_IRQS # - include the UART interrupts default 220 -config 2ND_LVL_ISR_TBL_OFFSET - default 1 - -config MAX_IRQ_PER_AGGREGATOR - default 219 - -config NUM_2ND_LEVEL_AGGREGATORS - default 1 - config SYS_CLOCK_HW_CYCLES_PER_SEC default 12000000 diff --git a/soc/arm/xilinx_zynqmp/Kconfig.soc b/soc/arm/xilinx_zynqmp/Kconfig.soc index e3a0597facf5..58c4eee9f157 100644 --- a/soc/arm/xilinx_zynqmp/Kconfig.soc +++ b/soc/arm/xilinx_zynqmp/Kconfig.soc @@ -8,6 +8,4 @@ config SOC_XILINX_ZYNQMP_RPU select CPU_CORTEX_R5 select SOC_XILINX_ZYNQMP select GIC_V1 - select MULTI_LEVEL_INTERRUPTS - select 2ND_LEVEL_INTERRUPTS select PLATFORM_SPECIFIC_INIT diff --git a/soc/arm/xilinx_zynqmp/dts_fixup.h b/soc/arm/xilinx_zynqmp/dts_fixup.h index 70b231a114d6..e8def7f63d65 100644 --- a/soc/arm/xilinx_zynqmp/dts_fixup.h +++ b/soc/arm/xilinx_zynqmp/dts_fixup.h @@ -5,12 +5,4 @@ * */ -#undef DT_INST_0_XLNX_XUARTPS_IRQ_0 -#define DT_INST_0_XLNX_XUARTPS_IRQ_0 ((DT_INST_0_XLNX_XUARTPS_IRQ_IRQ_0 + 1) << 8) - -#undef DT_INST_0_CDNS_TTC_IRQ_0 -#define DT_INST_0_CDNS_TTC_IRQ_0 ((DT_INST_0_CDNS_TTC_IRQ_IRQ_0 + 1) << 8) -#undef DT_INST_0_CDNS_TTC_IRQ_1 -#define DT_INST_0_CDNS_TTC_IRQ_1 ((DT_INST_0_CDNS_TTC_IRQ_IRQ_1 + 1) << 8) -#undef DT_INST_0_CDNS_TTC_IRQ_2 -#define DT_INST_0_CDNS_TTC_IRQ_2 ((DT_INST_0_CDNS_TTC_IRQ_IRQ_2 + 1) << 8) +/* Nothing for now */