summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2021-07-16 16:07:23 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2021-07-23 16:31:12 +0200
commit38818d768c3b6a7379522907ae49dbc227aea51e (patch)
treeb492cb73c8cb9914ab8ec59ca37daee34d738300
parent24a3c50b95bc0e2f723300e9e55c4ca0331952ed (diff)
bsp/leon3: Use new IRQ(A)MP register block API
-rw-r--r--bsps/include/grlib/irqamp.h99
-rw-r--r--bsps/sparc/leon3/clock/ckinit.c11
-rw-r--r--bsps/sparc/leon3/include/bsp/irq.h1
-rw-r--r--bsps/sparc/leon3/include/bsp/leon3.h35
-rw-r--r--bsps/sparc/leon3/include/leon.h53
-rw-r--r--bsps/sparc/leon3/start/amba.c11
-rw-r--r--bsps/sparc/leon3/start/bspclean.c9
-rw-r--r--bsps/sparc/leon3/start/bspsmp.c16
-rw-r--r--bsps/sparc/leon3/start/cpucounter.c11
-rw-r--r--bsps/sparc/leon3/start/eirq.c130
10 files changed, 280 insertions, 96 deletions
diff --git a/bsps/include/grlib/irqamp.h b/bsps/include/grlib/irqamp.h
new file mode 100644
index 0000000000..7819583e1b
--- /dev/null
+++ b/bsps/include/grlib/irqamp.h
@@ -0,0 +1,99 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSDeviceGRLIBIRQAMP
+ *
+ * @brief This header file defines the IRQ(A)MP interface.
+ */
+
+/*
+ * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * 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.
+ */
+
+/*
+ * This file is part of the RTEMS quality process and was automatically
+ * generated. If you find something that needs to be fixed or
+ * worded better please post a report or patch to an RTEMS mailing list
+ * or raise a bug report:
+ *
+ * https://www.rtems.org/bugs.html
+ *
+ * For information on updating and regenerating please refer to the How-To
+ * section in the Software Requirements Engineering chapter of the
+ * RTEMS Software Engineering manual. The manual is provided as a part of
+ * a release. For development sources please refer to the online
+ * documentation at:
+ *
+ * https://docs.rtems.org
+ */
+
+/* Generated from spec:/dev/grlib/if/irqamp-header-2 */
+
+#ifndef _GRLIB_IRQAMP_H
+#define _GRLIB_IRQAMP_H
+
+#include <grlib/irqamp-regs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Generated from spec:/dev/grlib/if/irqamp-get-timestamp */
+
+/**
+ * @ingroup RTEMSDeviceGRLIBIRQAMP
+ *
+ * @brief Gets the interrupt timestamping register bock.
+ *
+ * @param irqamp_regs is the IRQ(A)MP register block.
+ *
+ * @retval NULL The IRQ(A)MP does not support the interrupt timestamping
+ * feature.
+ *
+ * @return Returns the interrupt timestamping register block.
+ */
+static inline irqamp_timestamp *irqamp_get_timestamp_registers(
+ irqamp *irqamp_regs
+)
+{
+ irqamp_timestamp *timestamp_regs;
+ uint32_t itstmpc;
+
+ timestamp_regs = &irqamp_regs->itstmp[ 0 ];
+ itstmpc = grlib_load_32( &timestamp_regs->itstmpc );
+
+ if ( IRQAMP_ITSTMPC_TSTAMP_GET( itstmpc ) == 0 ) {
+ return NULL;
+ }
+
+ return timestamp_regs;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _GRLIB_IRQAMP_H */
diff --git a/bsps/sparc/leon3/clock/ckinit.c b/bsps/sparc/leon3/clock/ckinit.c
index 1146c77bd5..4fce12e74e 100644
--- a/bsps/sparc/leon3/clock/ckinit.c
+++ b/bsps/sparc/leon3/clock/ckinit.c
@@ -26,6 +26,7 @@
#include <leon.h>
#include <rtems/rtems/intr.h>
#include <grlib/ambapp.h>
+#include <grlib/irqamp.h>
#include <rtems/score/profiling.h>
#include <rtems/score/sparcimpl.h>
#include <rtems/timecounter.h>
@@ -160,11 +161,11 @@ static void bsp_clock_handler_install(rtems_interrupt_handler isr)
static void leon3_clock_initialize(void)
{
- volatile struct irqmp_timestamp_regs *irqmp_ts;
+ irqamp_timestamp *irqmp_ts;
volatile struct gptimer_regs *gpt;
struct timecounter *tc;
- irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
+ irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
gpt = LEON3_Timer_Regs;
tc = &leon3_tc;
@@ -182,13 +183,13 @@ static void leon3_clock_initialize(void)
tc->tc_frequency = leon3_up_counter_frequency();
#ifdef RTEMS_PROFILING
- if (!irqmp_has_timestamp(irqmp_ts)) {
+ if (irqmp_ts == NULL) {
bsp_fatal(LEON3_FATAL_CLOCK_NO_IRQMP_TIMESTAMP_SUPPORT);
}
#endif
leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init;
- } else if (irqmp_has_timestamp(irqmp_ts)) {
+ } else if (irqmp_ts != NULL) {
/* Use the interrupt controller timestamp counter if available */
tc->tc_get_timecount = _SPARC_Get_timecount_up;
tc->tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev);
@@ -199,7 +200,7 @@ static void leon3_clock_initialize(void)
* At least one TSISEL field must be non-zero to enable the timestamp
* counter. Use an arbitrary interrupt source.
*/
- irqmp_ts->control = 0x1;
+ grlib_store_32(&irqmp_ts->itstmpc, IRQAMP_ITSTMPC_TSISEL(1));
} else {
#ifdef RTEMS_SMP
/*
diff --git a/bsps/sparc/leon3/include/bsp/irq.h b/bsps/sparc/leon3/include/bsp/irq.h
index 30b28e4b96..d5cff2e1a4 100644
--- a/bsps/sparc/leon3/include/bsp/irq.h
+++ b/bsps/sparc/leon3/include/bsp/irq.h
@@ -18,6 +18,7 @@
#ifndef LIBBSP_LEON3_IRQ_CONFIG_H
#define LIBBSP_LEON3_IRQ_CONFIG_H
+#include <rtems.h>
#include <rtems/score/processormask.h>
#define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */
diff --git a/bsps/sparc/leon3/include/bsp/leon3.h b/bsps/sparc/leon3/include/bsp/leon3.h
index c0359937f9..623cbe5912 100644
--- a/bsps/sparc/leon3/include/bsp/leon3.h
+++ b/bsps/sparc/leon3/include/bsp/leon3.h
@@ -37,8 +37,9 @@
#define _BSP_LEON3_H
#include <rtems.h>
-#include <grlib/grlib.h>
#include <grlib/apbuart-regs.h>
+#include <grlib/irqamp-regs.h>
+#include <grlib/io.h>
struct ambapp_dev;
@@ -53,14 +54,37 @@ extern "C" {
*/
/**
+ * @brief This object provides the index of the boot processor.
+ *
+ * This object should be read-only after initialization.
+ */
+extern uint32_t LEON3_Cpu_Index;
+
+/**
* @brief This lock serializes the interrupt controller access.
*/
extern rtems_interrupt_lock LEON3_IrqCtrl_Lock;
/**
+ * @brief Acquires the interrupt controller lock.
+ *
+ * @param[out] _lock_context is the lock context.
+ */
+#define LEON3_IRQCTRL_ACQUIRE( _lock_context ) \
+ rtems_interrupt_lock_acquire( &LEON3_IrqCtrl_Lock, _lock_context )
+
+/**
+ * @brief Releases the interrupt controller lock.
+ *
+ * @param[in, out] _lock_context is the lock context.
+ */
+#define LEON3_IRQCTRL_RELEASE( _lock_context ) \
+ rtems_interrupt_lock_release( &LEON3_IrqCtrl_Lock, _lock_context )
+
+/**
* @brief This pointer provides the IRQ(A)MP register block address.
*/
-extern volatile struct irqmp_regs *LEON3_IrqCtrl_Regs;
+extern irqamp *LEON3_IrqCtrl_Regs;
/**
* @brief This pointer provides the IRQ(A)MP device information block.
@@ -80,7 +104,7 @@ extern uint32_t LEON3_IrqCtrl_EIrq;
*
* @param[in, out] regs is the IRQ(A)MP register block address.
*/
-void leon3_ext_irq_init( volatile struct irqmp_regs *regs );
+void leon3_ext_irq_init( irqamp *regs );
/**
* @brief Acknowledges and maps extended interrupts if this feature is
@@ -91,12 +115,15 @@ void leon3_ext_irq_init( volatile struct irqmp_regs *regs );
static inline uint32_t bsp_irq_fixup( uint32_t irq )
{
uint32_t eirq;
+ uint32_t cpu_self;
if ( irq != LEON3_IrqCtrl_EIrq ) {
return irq;
}
- eirq = LEON3_IrqCtrl_Regs->intid[ _LEON3_Get_current_processor() ] & 0x1f;
+ cpu_self = _LEON3_Get_current_processor();
+ eirq = grlib_load_32( &LEON3_IrqCtrl_Regs->pextack[ cpu_self ] );
+ eirq = IRQAMP_PEXTACK_EID_4_0_GET( eirq );
if ( eirq < 16 ) {
return irq;
diff --git a/bsps/sparc/leon3/include/leon.h b/bsps/sparc/leon3/include/leon.h
index c42b377170..848039f514 100644
--- a/bsps/sparc/leon3/include/leon.h
+++ b/bsps/sparc/leon3/include/leon.h
@@ -25,6 +25,7 @@
#include <rtems.h>
#include <amba.h>
+#include <grlib/io.h>
#include <bsp/leon3.h>
#ifdef __cplusplus
@@ -132,9 +133,6 @@ extern "C" {
extern volatile struct gptimer_regs *LEON3_Timer_Regs;
extern struct ambapp_dev *LEON3_Timer_Adev;
-/* LEON3 CPU Index of boot CPU */
-extern uint32_t LEON3_Cpu_Index;
-
/* Macros used for manipulating bits in LEON3 GP Timer Control Register */
#define LEON3_IRQMPSTATUS_CPUNR 28
@@ -153,21 +151,11 @@ extern uint32_t LEON3_Cpu_Index;
* store the result back are vulnerable.
*/
-#define LEON3_IRQCTRL_ACQUIRE( _lock_context ) \
- rtems_interrupt_lock_acquire( &LEON3_IrqCtrl_Lock, _lock_context )
-
-#define LEON3_IRQCTRL_RELEASE( _lock_context ) \
- rtems_interrupt_lock_release( &LEON3_IrqCtrl_Lock, _lock_context )
-
#define LEON_Clear_interrupt( _source ) \
- do { \
- LEON3_IrqCtrl_Regs->iclear = (1U << (_source)); \
- } while (0)
+ grlib_store_32(&LEON3_IrqCtrl_Regs->iclear, 1U << (_source))
#define LEON_Force_interrupt( _source ) \
- do { \
- LEON3_IrqCtrl_Regs->iforce = (1U << (_source)); \
- } while (0)
+ grlib_store_32(&LEON3_IrqCtrl_Regs->iforce0, 1U << (_source))
#define LEON_Enable_interrupt_broadcast( _source ) \
do { \
@@ -188,24 +176,30 @@ extern uint32_t LEON3_Cpu_Index;
} while (0)
#define LEON_Is_interrupt_pending( _source ) \
- (LEON3_IrqCtrl_Regs->ipend & (1U << (_source)))
+ (grlib_load_32(&LEON3_IrqCtrl_Regs->ipend) & (1U << (_source)))
#define LEON_Cpu_Is_interrupt_masked( _source, _cpu ) \
- (!(LEON3_IrqCtrl_Regs->mask[_cpu] & (1U << (_source))))
+ (!(grlib_load_32(&LEON3_IrqCtrl_Regs->pimask[_cpu]) & (1U << (_source))))
#define LEON_Cpu_Mask_interrupt( _source, _cpu ) \
do { \
rtems_interrupt_lock_context _lock_context; \
+ uint32_t _pimask; \
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
- LEON3_IrqCtrl_Regs->mask[_cpu] &= ~(1U << (_source)); \
+ _pimask = grlib_load_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ]); \
+ _pimask &= ~(1U << (_source)); \
+ grlib_store_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ], _pimask); \
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
} while (0)
#define LEON_Cpu_Unmask_interrupt( _source, _cpu ) \
do { \
rtems_interrupt_lock_context _lock_context; \
+ uint32_t _pimask; \
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
- LEON3_IrqCtrl_Regs->mask[_cpu] |= (1U << (_source)); \
+ _pimask = grlib_load_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ]); \
+ _pimask |= 1U << (_source); \
+ grlib_store_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ], _pimask); \
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
} while (0)
@@ -214,8 +208,8 @@ extern uint32_t LEON3_Cpu_Index;
rtems_interrupt_lock_context _lock_context; \
uint32_t _mask = 1U << (_source); \
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
- (_previous) = LEON3_IrqCtrl_Regs->mask[_cpu]; \
- LEON3_IrqCtrl_Regs->mask[_cpu] = _previous & ~_mask; \
+ (_previous) = grlib_load_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ]); \
+ grlib_store_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ], (_previous) & ~_mask); \
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
(_previous) &= _mask; \
} while (0)
@@ -223,10 +217,12 @@ extern uint32_t LEON3_Cpu_Index;
#define LEON_Cpu_Restore_interrupt( _source, _previous, _cpu ) \
do { \
rtems_interrupt_lock_context _lock_context; \
- uint32_t _mask = 1U << (_source); \
+ uint32_t _pimask; \
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
- LEON3_IrqCtrl_Regs->mask[_cpu] = \
- (LEON3_IrqCtrl_Regs->mask[_cpu] & ~_mask) | (_previous); \
+ _pimask = grlib_load_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ]); \
+ _pimask &= ~(1U << (_source)); \
+ _pimask |= _previous; \
+ grlib_store_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ], _pimask); \
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
} while (0)
@@ -370,15 +366,6 @@ extern unsigned int leon3_timer_prescaler;
RTEMS_NO_RETURN void leon3_power_down_loop(void);
-static inline uint32_t leon3_get_cpu_count(
- volatile struct irqmp_regs *irqmp
-)
-{
- uint32_t mpstat = irqmp->mpstat;
-
- return ((mpstat >> LEON3_IRQMPSTATUS_CPUNR) & 0xf) + 1;
-}
-
static inline void leon3_set_system_register(uint32_t addr, uint32_t val)
{
__asm__ volatile(
diff --git a/bsps/sparc/leon3/start/amba.c b/bsps/sparc/leon3/start/amba.c
index e13d07e85d..7cbe8f08a7 100644
--- a/bsps/sparc/leon3/start/amba.c
+++ b/bsps/sparc/leon3/start/amba.c
@@ -97,7 +97,7 @@ RTEMS_SYSINIT_ITEM(
#endif
/* Pointers to Interrupt Controller configuration registers */
-volatile struct irqmp_regs *LEON3_IrqCtrl_Regs;
+irqamp *LEON3_IrqCtrl_Regs;
struct ambapp_dev *LEON3_IrqCtrl_Adev;
volatile struct gptimer_regs *LEON3_Timer_Regs;
struct ambapp_dev *LEON3_Timer_Adev;
@@ -114,7 +114,6 @@ struct ambapp_dev *LEON3_Timer_Adev;
static void amba_initialize(void)
{
- int icsel;
struct ambapp_dev *adev;
struct ambapp_bus *plb;
@@ -132,15 +131,17 @@ static void amba_initialize(void)
bsp_fatal(LEON3_FATAL_NO_IRQMP_CONTROLLER);
}
- LEON3_IrqCtrl_Regs = (volatile struct irqmp_regs *)DEV_TO_APB(adev)->start;
+ LEON3_IrqCtrl_Regs = (irqamp *)DEV_TO_APB(adev)->start;
LEON3_IrqCtrl_Adev = adev;
- if ((LEON3_IrqCtrl_Regs->ampctrl >> 28) > 0) {
+ if ((grlib_load_32(&LEON3_IrqCtrl_Regs->asmpctrl) >> 28) > 0) {
+ uint32_t icsel;
+
/* IRQ Controller has support for multiple IRQ Controllers, each
* CPU can be routed to different Controllers, we find out which
* controller by looking at the IRQCTRL Select Register for this CPU.
* Each Controller is located at a 4KByte offset.
*/
- icsel = LEON3_IrqCtrl_Regs->icsel[LEON3_Cpu_Index/8];
+ icsel = grlib_load_32(&LEON3_IrqCtrl_Regs->icselr[LEON3_Cpu_Index/8]);
icsel = (icsel >> ((7 - (LEON3_Cpu_Index & 0x7)) * 4)) & 0xf;
LEON3_IrqCtrl_Regs += icsel;
}
diff --git a/bsps/sparc/leon3/start/bspclean.c b/bsps/sparc/leon3/start/bspclean.c
index a818e99631..0e109140df 100644
--- a/bsps/sparc/leon3/start/bspclean.c
+++ b/bsps/sparc/leon3/start/bspclean.c
@@ -42,9 +42,9 @@ void bsp_fatal_extension(
(code == SMP_FATAL_SHUTDOWN_RESPONSE)) {
leon3_power_down_loop(); /* CPU didn't start shutdown sequence .. */
} else {
- volatile struct irqmp_regs *irqmp = LEON3_IrqCtrl_Regs;
+ irqamp *regs = LEON3_IrqCtrl_Regs;
- if (irqmp != NULL) {
+ if (regs != NULL) {
/*
* Value was chosen to get something in the magnitude of 1ms on a 200MHz
* processor.
@@ -63,7 +63,10 @@ void bsp_fatal_extension(
/* Wait some time for secondary processors to halt */
i = 0;
- while ((irqmp->mpstat & halt_mask) != halt_mask && i < max_wait) {
+ while (
+ (grlib_load_32(&regs->mpstat) & halt_mask) != halt_mask &&
+ i < max_wait
+ ) {
++i;
}
}
diff --git a/bsps/sparc/leon3/start/bspsmp.c b/bsps/sparc/leon3/start/bspsmp.c
index abc3e61e2c..0f75e89fa1 100644
--- a/bsps/sparc/leon3/start/bspsmp.c
+++ b/bsps/sparc/leon3/start/bspsmp.c
@@ -17,6 +17,7 @@
#include <bsp/bootcard.h>
#include <bsp/fatal.h>
#include <bsp/irq.h>
+#include <bsp/leon3.h>
#include <leon.h>
#include <rtems/bspIo.h>
#include <rtems/sysinit.h>
@@ -75,6 +76,11 @@ static void leon3_install_inter_processor_interrupt( void )
_Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL );
}
+static uint32_t leon3_get_cpu_count( const irqamp *regs )
+{
+ return IRQAMP_MPSTAT_NCPU_GET( grlib_load_32( &regs->mpstat ) ) + 1;
+}
+
uint32_t _CPU_SMP_Initialize( void )
{
if ( !leon3_data_cache_snooping_enabled() )
@@ -89,7 +95,10 @@ bool _CPU_SMP_Start_processor( uint32_t cpu_index )
printk( "Waking CPU %d\n", cpu_index );
#endif
- LEON3_IrqCtrl_Regs->mpstat = 1U << cpu_index;
+ grlib_store_32(
+ &LEON3_IrqCtrl_Regs->mpstat,
+ IRQAMP_MPSTAT_STATUS(1U << cpu_index)
+ );
return true;
}
@@ -111,7 +120,10 @@ void _CPU_SMP_Prepare_start_multitasking( void )
void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
{
/* send interrupt to destination CPU */
- LEON3_IrqCtrl_Regs->force[target_processor_index] = 1 << LEON3_mp_irq;
+ grlib_store_32(
+ &LEON3_IrqCtrl_Regs->piforce[target_processor_index],
+ 1U << LEON3_mp_irq
+ );
}
#if defined(RTEMS_DRVMGR_STARTUP)
diff --git a/bsps/sparc/leon3/start/cpucounter.c b/bsps/sparc/leon3/start/cpucounter.c
index 73a306a1eb..d636c41632 100644
--- a/bsps/sparc/leon3/start/cpucounter.c
+++ b/bsps/sparc/leon3/start/cpucounter.c
@@ -13,6 +13,7 @@
*/
#include <leon.h>
+#include <grlib/irqamp.h>
#include <rtems/counter.h>
#include <rtems/sysinit.h>
@@ -27,11 +28,11 @@ uint32_t _CPU_Counter_frequency(void)
static void leon3_counter_initialize(void)
{
- volatile struct irqmp_timestamp_regs *irqmp_ts;
+ irqamp_timestamp *irqmp_ts;
volatile struct gptimer_regs *gpt;
SPARC_Counter *counter;
- irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
+ irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
gpt = LEON3_Timer_Regs;
counter = &_SPARC_Counter_mutable;
@@ -43,14 +44,14 @@ static void leon3_counter_initialize(void)
counter->read = _SPARC_Counter_read_asr23;
leon3_counter_frequency = leon3_up_counter_frequency();
- } else if (irqmp_has_timestamp(irqmp_ts)) {
+ } else if (irqmp_ts != NULL) {
/* Use the interrupt controller timestamp counter if available */
counter->read_isr_disabled = _SPARC_Counter_read_up;
counter->read = _SPARC_Counter_read_up;
- counter->counter_register = &LEON3_IrqCtrl_Regs->timestamp[0].counter;
+ counter->counter_register = &irqmp_ts->itcnt;
/* Enable interrupt timestamping for an arbitrary interrupt line */
- irqmp_ts->control = 0x1;
+ grlib_store_32(&irqmp_ts->itstmpc, IRQAMP_ITSTMPC_TSISEL(1));
leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_IrqCtrl_Adev);
} else if (gpt != NULL) {
diff --git a/bsps/sparc/leon3/start/eirq.c b/bsps/sparc/leon3/start/eirq.c
index 2545e4ed6b..b0b42902df 100644
--- a/bsps/sparc/leon3/start/eirq.c
+++ b/bsps/sparc/leon3/start/eirq.c
@@ -12,9 +12,9 @@
*
*/
-#include <leon.h>
#include <bsp/irq.h>
#include <bsp/irq-generic.h>
+#include <bsp/leon3.h>
/* GRLIB extended IRQ controller IRQ number */
uint32_t LEON3_IrqCtrl_EIrq;
@@ -23,12 +23,12 @@ rtems_interrupt_lock LEON3_IrqCtrl_Lock =
RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl");
/* Initialize Extended Interrupt controller */
-void leon3_ext_irq_init(volatile struct irqmp_regs *regs)
+void leon3_ext_irq_init(irqamp *regs)
{
- regs->mask[LEON3_Cpu_Index] = 0;
- regs->force[LEON3_Cpu_Index] = 0;
- regs->iclear = 0xffffffff;
- LEON3_IrqCtrl_EIrq = (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);
+ LEON3_IrqCtrl_EIrq = IRQAMP_MPSTAT_EIRQ_GET(grlib_load_32(&regs->mpstat));
}
bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
@@ -92,32 +92,34 @@ rtems_status_code bsp_interrupt_is_pending(
bool *pending
)
{
-#if defined(RTEMS_SMP)
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;
- rtems_interrupt_local_enable(level);
- return RTEMS_SUCCESSFUL;
+#if defined(RTEMS_SMP)
+ *pending = (grlib_load_32(&regs->ipend) & bit) != 0 ||
+ (grlib_load_32(&regs->piforce[rtems_scheduler_get_processor()]) & bit) != 0;
#else
- bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
- *pending = !BSP_Is_interrupt_pending(vector);
- return RTEMS_SUCCESSFUL;
+ *pending = (grlib_load_32(&regs->ipend) & bit) != 0;
#endif
+ rtems_interrupt_local_enable(level);
+ return RTEMS_SUCCESSFUL;
}
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;
@@ -126,10 +128,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
@@ -137,7 +140,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);
}
@@ -150,6 +155,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());
@@ -157,7 +164,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
@@ -165,14 +173,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;
@@ -183,9 +193,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;
}
@@ -197,75 +214,108 @@ static void leon3_interrupt_vector_enable(rtems_vector_number vector)
Processor_mask affinity;
uint32_t bit;
uint32_t unmasked;
+ uint32_t brdcst;
+ irqamp *regs;
cpu_count = rtems_scheduler_get_processor_maximum();
affinity = leon3_interrupt_affinities[vector];
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;
+ brdcst = grlib_load_32(&regs->brdcst);
+ brdcst &= ~bit;
+ grlib_store_32(&regs->brdcst, brdcst);
LEON3_IRQCTRL_RELEASE(&lock_context);
#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
return RTEMS_SUCCESSFUL;
}
@@ -280,9 +330,11 @@ rtems_status_code bsp_interrupt_set_affinity(
uint32_t cpu_count;
uint32_t cpu_index;
uint32_t bit;
+ irqamp *regs;
cpu_count = rtems_scheduler_get_processor_maximum();
bit = 1U << vector;
+ regs = LEON3_IrqCtrl_Regs;
LEON3_IRQCTRL_ACQUIRE(&lock_context);
leon3_interrupt_affinities[vector] = *affinity;
@@ -292,7 +344,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;
}