diff options
Diffstat (limited to 'bsps/sparc/leon3/start/eirq.c')
-rw-r--r-- | bsps/sparc/leon3/start/eirq.c | 179 |
1 files changed, 136 insertions, 43 deletions
diff --git a/bsps/sparc/leon3/start/eirq.c b/bsps/sparc/leon3/start/eirq.c index 2b69b68a13..58ef1828d6 100644 --- a/bsps/sparc/leon3/start/eirq.c +++ b/bsps/sparc/leon3/start/eirq.c @@ -1,31 +1,64 @@ -/* - * GRLIB/LEON3 extended interrupt controller +/* SPDX-License-Identifier: BSD-2-Clause */ + +/** + * @file + * + * @ingroup RTEMSBSPsSPARCLEON3 * - * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de) + * @brief This source file contains the implementation of the interrupt + * controller support. + */ + +/* + * Copyright (C) 2021 embedded brains GmbH & Co. KG * * COPYRIGHT (c) 2011 * Aeroflex Gaisler * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. * */ -#include <leon.h> -#include <bsp/irq.h> #include <bsp/irq-generic.h> +#include <bsp/irqimpl.h> +#include <rtems/score/processormaskimpl.h> +#if !defined(LEON3_IRQAMP_EXTENDED_INTERRUPT) /* GRLIB extended IRQ controller IRQ number */ -int LEON3_IrqCtrl_EIrq = -1; +uint32_t LEON3_IrqCtrl_EIrq; +#endif + +rtems_interrupt_lock LEON3_IrqCtrl_Lock = + RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl"); /* Initialize Extended Interrupt controller */ -void leon3_ext_irq_init(void) +void leon3_ext_irq_init(irqamp *regs) { - if ( (LEON3_IrqCtrl_Regs->mpstat >> 16) & 0xf ) { - /* Extended IRQ controller available */ - LEON3_IrqCtrl_EIrq = (LEON3_IrqCtrl_Regs->mpstat >> 16) & 0xf; - } + grlib_store_32(®s->pimask[LEON3_Cpu_Index], 0); + grlib_store_32(®s->piforce[LEON3_Cpu_Index], 0); + grlib_store_32(®s->iclear, 0xffffffff); +#if !defined(LEON3_IRQAMP_EXTENDED_INTERRUPT) + LEON3_IrqCtrl_EIrq = IRQAMP_MPSTAT_EIRQ_GET(grlib_load_32(®s->mpstat)); +#endif } bool bsp_interrupt_is_valid_vector(rtems_vector_number vector) @@ -34,11 +67,15 @@ bool bsp_interrupt_is_valid_vector(rtems_vector_number vector) return false; } +#if defined(LEON3_IRQAMP_EXTENDED_INTERRUPT) + return vector <= BSP_INTERRUPT_VECTOR_MAX_EXT; +#else if (LEON3_IrqCtrl_EIrq > 0) { return vector <= BSP_INTERRUPT_VECTOR_MAX_EXT; } return vector <= BSP_INTERRUPT_VECTOR_MAX_STD; +#endif } #if defined(RTEMS_SMP) @@ -57,6 +94,8 @@ void bsp_interrupt_facility_initialize(void) leon3_interrupt_affinities[i] = affinity; } #endif + + leon3_ext_irq_init(LEON3_IrqCtrl_Regs); } rtems_status_code bsp_interrupt_get_attributes( @@ -88,14 +127,16 @@ rtems_status_code bsp_interrupt_is_pending( { rtems_interrupt_level level; uint32_t bit; + irqamp *regs; bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); bsp_interrupt_assert(pending != NULL); bit = 1U << vector; + regs = LEON3_IrqCtrl_Regs; rtems_interrupt_local_disable(level); - *pending = (LEON3_IrqCtrl_Regs->ipend & bit) != 0 || - (LEON3_IrqCtrl_Regs->force[rtems_scheduler_get_processor()] & bit) != 0; + *pending = (grlib_load_32(®s->ipend) & bit) != 0 || + (grlib_load_32(®s->piforce[rtems_scheduler_get_processor()]) & bit) != 0; rtems_interrupt_local_enable(level); return RTEMS_SUCCESSFUL; } @@ -103,9 +144,11 @@ rtems_status_code bsp_interrupt_is_pending( rtems_status_code bsp_interrupt_raise(rtems_vector_number vector) { uint32_t bit; + irqamp *regs; bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); bit = 1U << vector; + regs = LEON3_IrqCtrl_Regs; if ( vector <= BSP_INTERRUPT_VECTOR_MAX_STD ) { uint32_t cpu_count; @@ -114,10 +157,11 @@ rtems_status_code bsp_interrupt_raise(rtems_vector_number vector) cpu_count = rtems_scheduler_get_processor_maximum(); for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { - LEON3_IrqCtrl_Regs->force[cpu_index] = bit; + grlib_store_32(®s->piforce[cpu_index], bit); } } else { rtems_interrupt_lock_context lock_context; + uint32_t ipend; /* * This is a very dangerous operation and should only be used for test @@ -125,7 +169,9 @@ rtems_status_code bsp_interrupt_raise(rtems_vector_number vector) * peripherals with this read-modify-write operation. */ LEON3_IRQCTRL_ACQUIRE(&lock_context); - LEON3_IrqCtrl_Regs->ipend |= bit; + ipend = grlib_load_32(®s->ipend); + ipend |= bit; + grlib_store_32(®s->ipend, ipend); LEON3_IRQCTRL_RELEASE(&lock_context); } @@ -138,6 +184,8 @@ rtems_status_code bsp_interrupt_raise_on( uint32_t cpu_index ) { + irqamp *regs; + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); bsp_interrupt_assert(cpu_index < rtems_scheduler_get_processor_maximum()); @@ -145,7 +193,8 @@ rtems_status_code bsp_interrupt_raise_on( return RTEMS_UNSATISFIED; } - LEON3_IrqCtrl_Regs->force[cpu_index] = 1U << vector; + regs = LEON3_IrqCtrl_Regs; + grlib_store_32(®s->piforce[cpu_index], 1U << vector); return RTEMS_SUCCESSFUL; } #endif @@ -153,14 +202,16 @@ rtems_status_code bsp_interrupt_raise_on( rtems_status_code bsp_interrupt_clear(rtems_vector_number vector) { uint32_t bit; + irqamp *regs; bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); bit = 1U << vector; + regs = LEON3_IrqCtrl_Regs; - LEON3_IrqCtrl_Regs->iclear = bit; + grlib_store_32(®s->iclear, bit); if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) { - LEON3_IrqCtrl_Regs->force[rtems_scheduler_get_processor()] = bit << 16; + grlib_store_32(®s->piforce[rtems_scheduler_get_processor()], bit << 16); } return RTEMS_SUCCESSFUL; @@ -171,9 +222,16 @@ rtems_status_code bsp_interrupt_vector_is_enabled( bool *enabled ) { + uint32_t bit; + irqamp *regs; + uint32_t pimask; + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - *enabled = - !BSP_Cpu_Is_interrupt_masked(vector, _LEON3_Get_current_processor()); + + bit = 1U << vector; + regs = LEON3_IrqCtrl_Regs; + pimask = grlib_load_32(®s->pimask[_LEON3_Get_current_processor()]); + *enabled = (pimask & bit) != 0; return RTEMS_SUCCESSFUL; } @@ -185,6 +243,8 @@ static void leon3_interrupt_vector_enable(rtems_vector_number vector) Processor_mask affinity; uint32_t bit; uint32_t unmasked; + uint32_t brdcst; + irqamp *regs; if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) { affinity = leon3_interrupt_affinities[vector]; @@ -194,72 +254,103 @@ static void leon3_interrupt_vector_enable(rtems_vector_number vector) cpu_count = rtems_scheduler_get_processor_maximum(); bit = 1U << vector; + regs = LEON3_IrqCtrl_Regs; unmasked = 0; for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { - uint32_t mask; + uint32_t pimask; - mask = LEON3_IrqCtrl_Regs->mask[cpu_index]; + pimask = grlib_load_32(®s->pimask[cpu_index]); if (_Processor_mask_Is_set(&affinity, cpu_index)) { ++unmasked; - mask |= bit; + pimask |= bit; } else { - mask &= ~bit; + pimask &= ~bit; } - LEON3_IrqCtrl_Regs->mask[cpu_index] = mask; + grlib_store_32(®s->pimask[cpu_index], pimask); } + brdcst = grlib_load_32(®s->brdcst); + if (unmasked > 1) { - LEON3_IrqCtrl_Regs->bcast |= bit; + brdcst |= bit; } else { - LEON3_IrqCtrl_Regs->bcast &= ~bit; + brdcst &= ~bit; } + + grlib_store_32(®s->brdcst, brdcst); } #endif rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector) { -#if defined(RTEMS_SMP) rtems_interrupt_lock_context lock_context; +#if !defined(RTEMS_SMP) + uint32_t bit; + irqamp *regs; + uint32_t pimask; + uint32_t cpu_index; +#endif bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +#if !defined(RTEMS_SMP) + bit = 1U << vector; + regs = LEON3_IrqCtrl_Regs; +#endif + LEON3_IRQCTRL_ACQUIRE(&lock_context); +#if defined(RTEMS_SMP) leon3_interrupt_vector_enable(vector); - LEON3_IRQCTRL_RELEASE(&lock_context); #else - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - BSP_Cpu_Unmask_interrupt(vector, _LEON3_Get_current_processor()); + cpu_index = _LEON3_Get_current_processor(); + pimask = grlib_load_32(®s->pimask[cpu_index]); + pimask |= bit; + grlib_store_32(®s->pimask[cpu_index], pimask); #endif + LEON3_IRQCTRL_RELEASE(&lock_context); return RTEMS_SUCCESSFUL; } rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector) { -#if defined(RTEMS_SMP) rtems_interrupt_lock_context lock_context; uint32_t bit; + irqamp *regs; + uint32_t pimask; uint32_t cpu_index; +#if defined(RTEMS_SMP) uint32_t cpu_count; + uint32_t brdcst; +#endif bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); bit = 1U << vector; - cpu_count = rtems_scheduler_get_processor_maximum(); + regs = LEON3_IrqCtrl_Regs; LEON3_IRQCTRL_ACQUIRE(&lock_context); +#if defined(RTEMS_SMP) + cpu_count = rtems_scheduler_get_processor_maximum(); + for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { - LEON3_IrqCtrl_Regs->mask[cpu_index] &= ~bit; + pimask = grlib_load_32(®s->pimask[cpu_index]); + pimask &= ~bit; + grlib_store_32(®s->pimask[cpu_index], pimask); } - LEON3_IrqCtrl_Regs->bcast &= ~bit; - - LEON3_IRQCTRL_RELEASE(&lock_context); + brdcst = grlib_load_32(®s->brdcst); + brdcst &= ~bit; + grlib_store_32(®s->brdcst, brdcst); #else - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - BSP_Cpu_Mask_interrupt(vector, _LEON3_Get_current_processor()); + cpu_index = _LEON3_Get_current_processor(); + pimask = grlib_load_32(®s->pimask[cpu_index]); + pimask &= ~bit; + grlib_store_32(®s->pimask[cpu_index], pimask); #endif + + LEON3_IRQCTRL_RELEASE(&lock_context); return RTEMS_SUCCESSFUL; } @@ -273,6 +364,7 @@ rtems_status_code bsp_interrupt_set_affinity( uint32_t cpu_count; uint32_t cpu_index; uint32_t bit; + irqamp *regs; if (vector >= RTEMS_ARRAY_SIZE(leon3_interrupt_affinities)) { return RTEMS_UNSATISFIED; @@ -280,6 +372,7 @@ rtems_status_code bsp_interrupt_set_affinity( cpu_count = rtems_scheduler_get_processor_maximum(); bit = 1U << vector; + regs = LEON3_IrqCtrl_Regs; LEON3_IRQCTRL_ACQUIRE(&lock_context); leon3_interrupt_affinities[vector] = *affinity; @@ -289,7 +382,7 @@ rtems_status_code bsp_interrupt_set_affinity( * using the new affinity. */ for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) { - if ((LEON3_IrqCtrl_Regs->mask[cpu_index] & bit) != 0) { + if ((grlib_load_32(®s->pimask[cpu_index]) & bit) != 0) { leon3_interrupt_vector_enable(vector); break; } |