On Fri, Jul 23, 2021 at 7:58 AM Sebastian Huber <sebastian.hu...@embedded-brains.de> wrote: > > Update #3269. > --- > bsps/sparc/erc32/include/bsp/irq.h | 3 +- > bsps/sparc/erc32/include/erc32.h | 12 ++++- > bsps/sparc/leon2/include/bsp/irq.h | 3 +- > bsps/sparc/leon2/include/leon.h | 16 +++++- > bsps/sparc/leon3/start/eirq.c | 87 +++++++++++++++++++++++++++--- > bsps/sparc/shared/irq/irq-shared.c | 48 ++++++++++++++--- > 6 files changed, 148 insertions(+), 21 deletions(-) > > diff --git a/bsps/sparc/erc32/include/bsp/irq.h > b/bsps/sparc/erc32/include/bsp/irq.h > index a61f51d6b6..83b383ba7a 100644 > --- a/bsps/sparc/erc32/include/bsp/irq.h > +++ b/bsps/sparc/erc32/include/bsp/irq.h > @@ -23,8 +23,7 @@ > #define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */ > #define BSP_INTERRUPT_VECTOR_COUNT (BSP_INTERRUPT_VECTOR_MAX_STD + 1) > > -/* No extra check is needed */ > -#undef BSP_INTERRUPT_CUSTOM_VALID_VECTOR > +#define BSP_INTERRUPT_CUSTOM_VALID_VECTOR > > RTEMS_INLINE_ROUTINE rtems_status_code bsp_interrupt_set_affinity( > rtems_vector_number vector, > diff --git a/bsps/sparc/erc32/include/erc32.h > b/bsps/sparc/erc32/include/erc32.h > index a677b13d25..f9cdbc960a 100644 > --- a/bsps/sparc/erc32/include/erc32.h > +++ b/bsps/sparc/erc32/include/erc32.h > @@ -352,7 +352,7 @@ static __inline__ int bsp_irq_fixup(int irq) > \ > _level = sparc_disable_interrupts(); \ > ERC32_MEC.Test_Control = ERC32_MEC.Test_Control | 0x80000; \ > - ERC32_MEC.Interrupt_Force = (1 << (_source)); \ > + ERC32_MEC.Interrupt_Force |= (1 << (_source)); \ > sparc_enable_interrupts( _level ); \ > } while (0) > > @@ -406,7 +406,17 @@ static __inline__ int bsp_irq_fixup(int irq) > /* Make all SPARC BSPs have common macros for interrupt handling on local > CPU */ > #define BSP_Clear_interrupt(_source) ERC32_Clear_interrupt(_source) > #define BSP_Force_interrupt(_source) ERC32_Force_interrupt(_source) > +#define BSP_Clear_forced_interrupt( _source ) \ > + do { \ > + uint32_t _level; \ > + \ > + _level = sparc_disable_interrupts(); \ > + ERC32_MEC.Interrupt_Force &= ~(1 << (_source)); \ > + sparc_enable_interrupts( _level ); \ > + } while (0) > #define BSP_Is_interrupt_pending(_source) ERC32_Is_interrupt_pending(_source) > +#define BSP_Is_interrupt_forced(_source) \ > + (ERC32_MEC.Interrupt_Force & (1 << (_source))) > #define BSP_Is_interrupt_masked(_source) ERC32_Is_interrupt_masked(_source) > #define BSP_Unmask_interrupt(_source) ERC32_Unmask_interrupt(_source) > #define BSP_Mask_interrupt(_source) ERC32_Mask_interrupt(_source) > diff --git a/bsps/sparc/leon2/include/bsp/irq.h > b/bsps/sparc/leon2/include/bsp/irq.h > index 5f2359014a..a4ce3c55ff 100644 > --- a/bsps/sparc/leon2/include/bsp/irq.h > +++ b/bsps/sparc/leon2/include/bsp/irq.h > @@ -21,7 +21,6 @@ > #define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */ > #define BSP_INTERRUPT_VECTOR_COUNT (BSP_INTERRUPT_VECTOR_MAX_STD + 1) > > -/* No extra check is needed */ > -#undef BSP_INTERRUPT_CUSTOM_VALID_VECTOR > +#define BSP_INTERRUPT_CUSTOM_VALID_VECTOR > > #endif /* LIBBSP_LEON2_IRQ_CONFIG_H */ > diff --git a/bsps/sparc/leon2/include/leon.h b/bsps/sparc/leon2/include/leon.h > index fc90e1f7e6..11196aee6d 100644 > --- a/bsps/sparc/leon2/include/leon.h > +++ b/bsps/sparc/leon2/include/leon.h > @@ -295,7 +295,11 @@ static __inline__ int bsp_irq_fixup(int irq) > > #define LEON_Force_interrupt( _source ) \ > do { \ > - LEON_REG.Interrupt_Force = (1 << (_source)); \ > + uint32_t _level; \ > + \ > + _level = sparc_disable_interrupts(); \ > + LEON_REG.Interrupt_Force |= (1 << (_source)); \ > + sparc_enable_interrupts( _level ); \ > } while (0) > > #define LEON_Is_interrupt_pending( _source ) \ > @@ -348,7 +352,17 @@ static __inline__ int bsp_irq_fixup(int irq) > /* Make all SPARC BSPs have common macros for interrupt handling */ > #define BSP_Clear_interrupt(_source) LEON_Clear_interrupt(_source) > #define BSP_Force_interrupt(_source) LEON_Force_interrupt(_source) > +#define BSP_Clear_forced_interrupt( _source ) \ > + do { \ > + uint32_t _level; \ > + \ > + _level = sparc_disable_interrupts(); \ > + LEON_REG.Interrupt_Force &= ~(1 << (_source)); \ > + sparc_enable_interrupts( _level ); \ > + } while (0) > #define BSP_Is_interrupt_pending(_source) LEON_Is_interrupt_pending(_source) > +#define BSP_Is_interrupt_forced(_source) \ > + (LEON_REG.Interrupt_Force & (1 << (_source))) > #define BSP_Is_interrupt_masked(_source) LEON_Is_interrupt_masked(_source) > #define BSP_Unmask_interrupt(_source) LEON_Unmask_interrupt(_source) > #define BSP_Mask_interrupt(_source) LEON_Mask_interrupt(_source) > diff --git a/bsps/sparc/leon3/start/eirq.c b/bsps/sparc/leon3/start/eirq.c > index 5519d6efe7..80c0efd3fa 100644 > --- a/bsps/sparc/leon3/start/eirq.c > +++ b/bsps/sparc/leon3/start/eirq.c > @@ -66,6 +66,20 @@ rtems_status_code bsp_interrupt_get_attributes( > rtems_interrupt_attributes *attributes > ) > { > + bool is_standard_interrupt; > + > + is_standard_interrupt = (vector <= BSP_INTERRUPT_VECTOR_MAX_STD); > + attributes->is_maskable = (vector != 15); 15? BSP_INTERRUPT_VECTOR_MAX_STD?
> + attributes->can_enable = true; > + attributes->maybe_enable = true; > + attributes->can_disable = true; > + attributes->maybe_disable = true; > + attributes->can_raise = true; > + attributes->can_raise_on = is_standard_interrupt; > + attributes->can_clear = true; > + attributes->cleared_by_acknowledge = true; > + attributes->can_get_affinity = is_standard_interrupt; > + attributes->can_set_affinity = is_standard_interrupt; > return RTEMS_SUCCESSFUL; > } > > @@ -74,16 +88,56 @@ rtems_status_code bsp_interrupt_is_pending( > bool *pending > ) > { > +#if defined(RTEMS_SMP) > + rtems_interrupt_level level; > + uint32_t bit; > + > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > bsp_interrupt_assert(pending != NULL); > - *pending = false; > - return RTEMS_UNSATISFIED; > + bit = 1U << vector; > + > + rtems_interrupt_local_disable(level); > + *pending = (LEON3_IrqCtrl_Regs->ipend & bit) != 0 || > + (LEON3_IrqCtrl_Regs->force[rtems_scheduler_get_processor()] & bit) != 0; > + rtems_interrupt_local_enable(level); > + return RTEMS_SUCCESSFUL; > +#else > + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > + *pending = !BSP_Is_interrupt_pending(vector); > + return RTEMS_SUCCESSFUL; > +#endif > } > > rtems_status_code bsp_interrupt_raise(rtems_vector_number vector) > { > + uint32_t bit; > + > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > - return RTEMS_UNSATISFIED; > + bit = 1U << vector; > + > + if ( vector <= BSP_INTERRUPT_VECTOR_MAX_STD ) { > + uint32_t cpu_count; > + uint32_t cpu_index; > + > + cpu_count = rtems_scheduler_get_processor_maximum(); > + > + for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { > + LEON3_IrqCtrl_Regs->force[cpu_index] = bit; > + } > + } else { > + rtems_interrupt_lock_context lock_context; > + > + /* > + * This is a very dangerous operation and should only be used for test > + * software. We may accidentally clear the pending state set by > + * peripherals with this read-modify-write operation. > + */ > + LEON3_IRQCTRL_ACQUIRE(&lock_context); > + LEON3_IrqCtrl_Regs->ipend |= bit; > + LEON3_IRQCTRL_RELEASE(&lock_context); > + } > + > + return RTEMS_SUCCESSFUL; > } > > #if defined(RTEMS_SMP) > @@ -93,14 +147,31 @@ rtems_status_code bsp_interrupt_raise_on( > ) > { > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > - return RTEMS_UNSATISFIED; > + bsp_interrupt_assert(cpu_index < rtems_scheduler_get_processor_maximum()); > + > + if ( vector > BSP_INTERRUPT_VECTOR_MAX_STD ) { > + return RTEMS_UNSATISFIED; > + } > + > + LEON3_IrqCtrl_Regs->force[cpu_index] = 1U << vector; > + return RTEMS_SUCCESSFUL; > } > #endif > > rtems_status_code bsp_interrupt_clear(rtems_vector_number vector) > { > + uint32_t bit; > + > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > - return RTEMS_UNSATISFIED; > + bit = 1U << vector; > + > + LEON3_IrqCtrl_Regs->iclear = bit; > + > + if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) { > + LEON3_IrqCtrl_Regs->force[rtems_scheduler_get_processor()] = bit << 16; > + } > + > + return RTEMS_SUCCESSFUL; > } > > rtems_status_code bsp_interrupt_vector_is_enabled( > @@ -109,9 +180,9 @@ rtems_status_code bsp_interrupt_vector_is_enabled( > ) > { > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > - bsp_interrupt_assert(enabled != NULL); > - *enabled = false; > - return RTEMS_UNSATISFIED; > + *enabled = > + !BSP_Cpu_Is_interrupt_masked(vector, _LEON3_Get_current_processor()); > + return RTEMS_SUCCESSFUL; > } > > #if defined(RTEMS_SMP) > diff --git a/bsps/sparc/shared/irq/irq-shared.c > b/bsps/sparc/shared/irq/irq-shared.c > index 68ad57d723..8896aca761 100644 > --- a/bsps/sparc/shared/irq/irq-shared.c > +++ b/bsps/sparc/shared/irq/irq-shared.c > @@ -26,17 +26,41 @@ static inline int bsp_irq_cpu(int irq) > } > > #if !defined(LEON3) > +bool bsp_interrupt_is_valid_vector(rtems_vector_number vector) > +{ > + if (vector == 0) { > + return false; > + } > + > + return vector <= BSP_INTERRUPT_VECTOR_MAX_STD; > +} > + > rtems_status_code bsp_interrupt_facility_initialize(void) > { > /* Nothing to do */ > return RTEMS_SUCCESSFUL; > } > > +static bool is_maskable(rtems_vector_number vector) > +{ > + return vector != 15; 15? > +} > + > rtems_status_code bsp_interrupt_get_attributes( > rtems_vector_number vector, > rtems_interrupt_attributes *attributes > ) > { > + attributes->is_maskable = is_maskable(vector); > + attributes->can_enable = true; > + attributes->maybe_enable = true; > + attributes->can_disable = is_maskable(vector); > + attributes->maybe_disable = is_maskable(vector); > + attributes->can_raise = true; > + attributes->can_raise_on = true; > + attributes->can_clear = true; > + attributes->cleared_by_acknowledge = true; > + attributes->can_set_affinity = true; > return RTEMS_SUCCESSFUL; > } > > @@ -47,14 +71,16 @@ rtems_status_code bsp_interrupt_is_pending( > { > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > bsp_interrupt_assert(pending != NULL); > - *pending = false; > - return RTEMS_UNSATISFIED; > + *pending = BSP_Is_interrupt_pending(vector) || > + BSP_Is_interrupt_forced(vector); > + return RTEMS_SUCCESSFUL; > } > > rtems_status_code bsp_interrupt_raise(rtems_vector_number vector) > { > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > - return RTEMS_UNSATISFIED; > + BSP_Force_interrupt(vector); > + return RTEMS_SUCCESSFUL; > } > > #if defined(RTEMS_SMP) > @@ -64,14 +90,17 @@ rtems_status_code bsp_interrupt_raise_on( > ) > { > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > - return RTEMS_UNSATISFIED; > + BSP_Force_interrupt(vector); > + return RTEMS_SUCCESSFUL; > } > #endif > > rtems_status_code bsp_interrupt_clear(rtems_vector_number vector) > { > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > - return RTEMS_UNSATISFIED; > + BSP_Clear_forced_interrupt(vector); > + BSP_Clear_interrupt(vector); > + return RTEMS_SUCCESSFUL; > } > > rtems_status_code bsp_interrupt_vector_is_enabled( > @@ -81,8 +110,8 @@ rtems_status_code bsp_interrupt_vector_is_enabled( > { > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > bsp_interrupt_assert(enabled != NULL); > - *enabled = false; > - return RTEMS_UNSATISFIED; > + *enabled = !BSP_Cpu_Is_interrupt_masked(vector, bsp_irq_cpu(vector)); > + return RTEMS_SUCCESSFUL; > } > > rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector) > @@ -95,6 +124,11 @@ rtems_status_code > bsp_interrupt_vector_enable(rtems_vector_number vector) > rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector) > { > bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); > + > + if (!is_maskable(vector)) { > + return RTEMS_UNSATISFIED; > + } > + > BSP_Cpu_Mask_interrupt(vector, 0); > return RTEMS_SUCCESSFUL; > } > -- > 2.26.2 > > _______________________________________________ > devel mailing list > devel@rtems.org > http://lists.rtems.org/mailman/listinfo/devel _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel