summaryrefslogtreecommitdiffstats
path: root/bsps/sparc/leon3/start/eirq.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/sparc/leon3/start/eirq.c')
-rw-r--r--bsps/sparc/leon3/start/eirq.c179
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(&regs->pimask[LEON3_Cpu_Index], 0);
+ grlib_store_32(&regs->piforce[LEON3_Cpu_Index], 0);
+ grlib_store_32(&regs->iclear, 0xffffffff);
+#if !defined(LEON3_IRQAMP_EXTENDED_INTERRUPT)
+ LEON3_IrqCtrl_EIrq = IRQAMP_MPSTAT_EIRQ_GET(grlib_load_32(&regs->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(&regs->ipend) & bit) != 0 ||
+ (grlib_load_32(&regs->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(&regs->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(&regs->ipend);
+ ipend |= bit;
+ grlib_store_32(&regs->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(&regs->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(&regs->iclear, bit);
if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) {
- LEON3_IrqCtrl_Regs->force[rtems_scheduler_get_processor()] = bit << 16;
+ grlib_store_32(&regs->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(&regs->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(&regs->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(&regs->pimask[cpu_index], pimask);
}
+ brdcst = grlib_load_32(&regs->brdcst);
+
if (unmasked > 1) {
- LEON3_IrqCtrl_Regs->bcast |= bit;
+ brdcst |= bit;
} else {
- LEON3_IrqCtrl_Regs->bcast &= ~bit;
+ brdcst &= ~bit;
}
+
+ grlib_store_32(&regs->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(&regs->pimask[cpu_index]);
+ pimask |= bit;
+ grlib_store_32(&regs->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(&regs->pimask[cpu_index]);
+ pimask &= ~bit;
+ grlib_store_32(&regs->pimask[cpu_index], pimask);
}
- LEON3_IrqCtrl_Regs->bcast &= ~bit;
-
- LEON3_IRQCTRL_RELEASE(&lock_context);
+ brdcst = grlib_load_32(&regs->brdcst);
+ brdcst &= ~bit;
+ grlib_store_32(&regs->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(&regs->pimask[cpu_index]);
+ pimask &= ~bit;
+ grlib_store_32(&regs->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(&regs->pimask[cpu_index]) & bit) != 0) {
leon3_interrupt_vector_enable(vector);
break;
}