forked from Imagelibrary/rtems
bsp/leon3: Use new IRQ(A)MP register block API
This commit is contained in:
@@ -45,6 +45,7 @@
|
|||||||
#include <leon.h>
|
#include <leon.h>
|
||||||
#include <rtems/rtems/intr.h>
|
#include <rtems/rtems/intr.h>
|
||||||
#include <grlib/ambapp.h>
|
#include <grlib/ambapp.h>
|
||||||
|
#include <grlib/irqamp.h>
|
||||||
#include <rtems/score/profiling.h>
|
#include <rtems/score/profiling.h>
|
||||||
#include <rtems/score/sparcimpl.h>
|
#include <rtems/score/sparcimpl.h>
|
||||||
#include <rtems/timecounter.h>
|
#include <rtems/timecounter.h>
|
||||||
@@ -69,12 +70,14 @@ static struct timecounter leon3_tc;
|
|||||||
|
|
||||||
static void leon3_tc_tick_irqmp_timestamp(void)
|
static void leon3_tc_tick_irqmp_timestamp(void)
|
||||||
{
|
{
|
||||||
volatile struct irqmp_timestamp_regs *irqmp_ts =
|
irqamp_timestamp *irqmp_ts =
|
||||||
&LEON3_IrqCtrl_Regs->timestamp[0];
|
irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
|
||||||
unsigned int first = irqmp_ts->assertion;
|
uint32_t first = grlib_load_32(&irqmp_ts->itstmpas);
|
||||||
unsigned int second = irqmp_ts->counter;
|
uint32_t second = grlib_load_32(&irqmp_ts->itcnt);
|
||||||
|
uint32_t control = grlib_load_32(&irqmp_ts->itstmpc);
|
||||||
|
|
||||||
irqmp_ts->control |= IRQMP_TIMESTAMP_S1_S2;
|
control |= IRQMP_TIMESTAMP_S1_S2;
|
||||||
|
grlib_store_32(&irqmp_ts->itstmpc, control);
|
||||||
|
|
||||||
_Profiling_Update_max_interrupt_delay(_Per_CPU_Get(), second - first);
|
_Profiling_Update_max_interrupt_delay(_Per_CPU_Get(), second - first);
|
||||||
|
|
||||||
@@ -100,11 +103,13 @@ static void leon3_tc_tick_irqmp_timestamp_init(void)
|
|||||||
bool done = true;
|
bool done = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
volatile struct irqmp_timestamp_regs *irqmp_ts =
|
irqamp_timestamp *irqmp_ts =
|
||||||
&LEON3_IrqCtrl_Regs->timestamp[0];
|
irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
|
||||||
unsigned int ks = 1U << 5;
|
uint32_t ks = 1U << 5;
|
||||||
|
uint32_t control = grlib_load_32(&irqmp_ts->itstmpc);
|
||||||
|
|
||||||
irqmp_ts->control = ks | IRQMP_TIMESTAMP_S1_S2 | (unsigned int) clkirq;
|
control = ks | IRQMP_TIMESTAMP_S1_S2 | (unsigned int) clkirq;
|
||||||
|
grlib_store_32(&irqmp_ts->itstmpc, control);
|
||||||
|
|
||||||
if (done) {
|
if (done) {
|
||||||
leon3_tc_tick = leon3_tc_tick_irqmp_timestamp;
|
leon3_tc_tick = leon3_tc_tick_irqmp_timestamp;
|
||||||
@@ -116,14 +121,14 @@ static void leon3_tc_tick_irqmp_timestamp_init(void)
|
|||||||
|
|
||||||
static void leon3_tc_tick_default(void)
|
static void leon3_tc_tick_default(void)
|
||||||
{
|
{
|
||||||
#ifndef RTEMS_SMP
|
#if !defined(RTEMS_SMP)
|
||||||
SPARC_Counter *counter;
|
SPARC_Counter *counter;
|
||||||
rtems_interrupt_level level;
|
rtems_interrupt_level level;
|
||||||
|
|
||||||
counter = &_SPARC_Counter_mutable;
|
counter = &_SPARC_Counter_mutable;
|
||||||
rtems_interrupt_local_disable(level);
|
rtems_interrupt_local_disable(level);
|
||||||
|
|
||||||
LEON3_IrqCtrl_Regs->iclear = counter->pending_mask;
|
grlib_store_32(&LEON3_IrqCtrl_Regs->iclear, counter->pending_mask);
|
||||||
counter->accumulated += counter->interval;
|
counter->accumulated += counter->interval;
|
||||||
|
|
||||||
rtems_interrupt_local_enable(level);
|
rtems_interrupt_local_enable(level);
|
||||||
@@ -179,11 +184,11 @@ static void bsp_clock_handler_install(rtems_interrupt_handler isr)
|
|||||||
|
|
||||||
static void leon3_clock_initialize(void)
|
static void leon3_clock_initialize(void)
|
||||||
{
|
{
|
||||||
volatile struct irqmp_timestamp_regs *irqmp_ts;
|
irqamp_timestamp *irqmp_ts;
|
||||||
volatile struct gptimer_regs *gpt;
|
volatile struct gptimer_regs *gpt;
|
||||||
struct timecounter *tc;
|
struct timecounter *tc;
|
||||||
|
|
||||||
irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
|
irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
|
||||||
gpt = LEON3_Timer_Regs;
|
gpt = LEON3_Timer_Regs;
|
||||||
tc = &leon3_tc;
|
tc = &leon3_tc;
|
||||||
|
|
||||||
@@ -201,13 +206,13 @@ static void leon3_clock_initialize(void)
|
|||||||
tc->tc_frequency = leon3_up_counter_frequency();
|
tc->tc_frequency = leon3_up_counter_frequency();
|
||||||
|
|
||||||
#ifdef RTEMS_PROFILING
|
#ifdef RTEMS_PROFILING
|
||||||
if (!irqmp_has_timestamp(irqmp_ts)) {
|
if (irqmp_ts == NULL) {
|
||||||
bsp_fatal(LEON3_FATAL_CLOCK_NO_IRQMP_TIMESTAMP_SUPPORT);
|
bsp_fatal(LEON3_FATAL_CLOCK_NO_IRQMP_TIMESTAMP_SUPPORT);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
leon3_tc_tick = leon3_tc_tick_irqmp_timestamp_init;
|
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 */
|
/* Use the interrupt controller timestamp counter if available */
|
||||||
tc->tc_get_timecount = _SPARC_Get_timecount_up;
|
tc->tc_get_timecount = _SPARC_Get_timecount_up;
|
||||||
tc->tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev);
|
tc->tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev);
|
||||||
@@ -218,7 +223,7 @@ static void leon3_clock_initialize(void)
|
|||||||
* At least one TSISEL field must be non-zero to enable the timestamp
|
* At least one TSISEL field must be non-zero to enable the timestamp
|
||||||
* counter. Use an arbitrary interrupt source.
|
* counter. Use an arbitrary interrupt source.
|
||||||
*/
|
*/
|
||||||
irqmp_ts->control = 0x1;
|
grlib_store_32(&irqmp_ts->itstmpc, IRQAMP_ITSTMPC_TSISEL(1));
|
||||||
} else {
|
} else {
|
||||||
#ifdef RTEMS_SMP
|
#ifdef RTEMS_SMP
|
||||||
/*
|
/*
|
||||||
@@ -237,7 +242,7 @@ static void leon3_clock_initialize(void)
|
|||||||
counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled;
|
counter->read_isr_disabled = _SPARC_Counter_read_clock_isr_disabled;
|
||||||
counter->read = _SPARC_Counter_read_clock;
|
counter->read = _SPARC_Counter_read_clock;
|
||||||
counter->counter_register = &gpt->timer[LEON3_CLOCK_INDEX].value;
|
counter->counter_register = &gpt->timer[LEON3_CLOCK_INDEX].value;
|
||||||
counter->pending_register = &LEON3_IrqCtrl_Regs->ipend;
|
counter->pending_register = grlib_load_32(&LEON3_IrqCtrl_Regs->ipend);
|
||||||
counter->pending_mask = UINT32_C(1) << clkirq;
|
counter->pending_mask = UINT32_C(1) << clkirq;
|
||||||
counter->accumulated = rtems_configuration_get_microseconds_per_tick();
|
counter->accumulated = rtems_configuration_get_microseconds_per_tick();
|
||||||
counter->interval = rtems_configuration_get_microseconds_per_tick();
|
counter->interval = rtems_configuration_get_microseconds_per_tick();
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#ifndef LIBBSP_LEON3_IRQ_CONFIG_H
|
#ifndef LIBBSP_LEON3_IRQ_CONFIG_H
|
||||||
#define LIBBSP_LEON3_IRQ_CONFIG_H
|
#define LIBBSP_LEON3_IRQ_CONFIG_H
|
||||||
|
|
||||||
|
#include <rtems.h>
|
||||||
#include <rtems/score/processormask.h>
|
#include <rtems/score/processormask.h>
|
||||||
|
|
||||||
#define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */
|
#define BSP_INTERRUPT_VECTOR_MAX_STD 15 /* Standard IRQ controller */
|
||||||
|
|||||||
@@ -38,7 +38,8 @@
|
|||||||
#define LIBBSP_SPARC_LEON3_BSP_IRQIMPL_H
|
#define LIBBSP_SPARC_LEON3_BSP_IRQIMPL_H
|
||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
#include <grlib/grlib.h>
|
#include <grlib/irqamp-regs.h>
|
||||||
|
#include <grlib/io.h>
|
||||||
|
|
||||||
struct ambapp_dev;
|
struct ambapp_dev;
|
||||||
|
|
||||||
@@ -52,15 +53,38 @@ 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.
|
* @brief This lock serializes the interrupt controller access.
|
||||||
*/
|
*/
|
||||||
extern rtems_interrupt_lock LEON3_IrqCtrl_Lock;
|
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.
|
* @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.
|
* @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.
|
* @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
|
* @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 )
|
static inline uint32_t bsp_irq_fixup( uint32_t irq )
|
||||||
{
|
{
|
||||||
uint32_t eirq;
|
uint32_t eirq;
|
||||||
|
uint32_t cpu_self;
|
||||||
|
|
||||||
if ( irq != LEON3_IrqCtrl_EIrq ) {
|
if ( irq != LEON3_IrqCtrl_EIrq ) {
|
||||||
return irq;
|
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 ) {
|
if ( eirq < 16 ) {
|
||||||
return irq;
|
return irq;
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
|
|
||||||
#include <rtems.h>
|
#include <rtems.h>
|
||||||
#include <amba.h>
|
#include <amba.h>
|
||||||
|
#include <grlib/io.h>
|
||||||
#include <bsp/irqimpl.h>
|
#include <bsp/irqimpl.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@@ -151,9 +152,6 @@ extern "C" {
|
|||||||
extern volatile struct gptimer_regs *LEON3_Timer_Regs;
|
extern volatile struct gptimer_regs *LEON3_Timer_Regs;
|
||||||
extern struct ambapp_dev *LEON3_Timer_Adev;
|
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 */
|
/* Macros used for manipulating bits in LEON3 GP Timer Control Register */
|
||||||
|
|
||||||
#define LEON3_IRQMPSTATUS_CPUNR 28
|
#define LEON3_IRQMPSTATUS_CPUNR 28
|
||||||
@@ -172,28 +170,21 @@ extern uint32_t LEON3_Cpu_Index;
|
|||||||
* store the result back are vulnerable.
|
* 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 ) \
|
#define LEON_Clear_interrupt( _source ) \
|
||||||
do { \
|
grlib_store_32(&LEON3_IrqCtrl_Regs->iclear, 1U << (_source))
|
||||||
LEON3_IrqCtrl_Regs->iclear = (1U << (_source)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define LEON_Force_interrupt( _source ) \
|
#define LEON_Force_interrupt( _source ) \
|
||||||
do { \
|
grlib_store_32(&LEON3_IrqCtrl_Regs->iforce0, 1U << (_source))
|
||||||
LEON3_IrqCtrl_Regs->iforce = (1U << (_source)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
#define LEON_Enable_interrupt_broadcast( _source ) \
|
#define LEON_Enable_interrupt_broadcast( _source ) \
|
||||||
do { \
|
do { \
|
||||||
rtems_interrupt_lock_context _lock_context; \
|
rtems_interrupt_lock_context _lock_context; \
|
||||||
uint32_t _mask = 1U << ( _source ); \
|
uint32_t _mask = 1U << ( _source ); \
|
||||||
|
uint32_t _brdcst; \
|
||||||
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
||||||
LEON3_IrqCtrl_Regs->bcast |= _mask; \
|
_brdcst = grlib_load_32(&LEON3_IrqCtrl_Regs->brdcst); \
|
||||||
|
_brdcst |= _mask; \
|
||||||
|
grlib_store_32(&LEON3_IrqCtrl_Regs->brdcst, _brdcst); \
|
||||||
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -201,30 +192,39 @@ extern uint32_t LEON3_Cpu_Index;
|
|||||||
do { \
|
do { \
|
||||||
rtems_interrupt_lock_context _lock_context; \
|
rtems_interrupt_lock_context _lock_context; \
|
||||||
uint32_t _mask = 1U << ( _source ); \
|
uint32_t _mask = 1U << ( _source ); \
|
||||||
|
uint32_t _brdcst; \
|
||||||
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
||||||
LEON3_IrqCtrl_Regs->bcast &= ~_mask; \
|
_brdcst = grlib_load_32(&LEON3_IrqCtrl_Regs->brdcst); \
|
||||||
|
_brdcst &= ~_mask; \
|
||||||
|
grlib_store_32(&LEON3_IrqCtrl_Regs->brdcst, _brdcst); \
|
||||||
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LEON_Is_interrupt_pending( _source ) \
|
#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 ) \
|
#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 ) \
|
#define LEON_Cpu_Mask_interrupt( _source, _cpu ) \
|
||||||
do { \
|
do { \
|
||||||
rtems_interrupt_lock_context _lock_context; \
|
rtems_interrupt_lock_context _lock_context; \
|
||||||
|
uint32_t _pimask; \
|
||||||
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
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 ); \
|
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define LEON_Cpu_Unmask_interrupt( _source, _cpu ) \
|
#define LEON_Cpu_Unmask_interrupt( _source, _cpu ) \
|
||||||
do { \
|
do { \
|
||||||
rtems_interrupt_lock_context _lock_context; \
|
rtems_interrupt_lock_context _lock_context; \
|
||||||
|
uint32_t _pimask; \
|
||||||
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
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 ); \
|
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -233,8 +233,8 @@ extern uint32_t LEON3_Cpu_Index;
|
|||||||
rtems_interrupt_lock_context _lock_context; \
|
rtems_interrupt_lock_context _lock_context; \
|
||||||
uint32_t _mask = 1U << (_source); \
|
uint32_t _mask = 1U << (_source); \
|
||||||
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
||||||
(_previous) = LEON3_IrqCtrl_Regs->mask[_cpu]; \
|
(_previous) = grlib_load_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ]); \
|
||||||
LEON3_IrqCtrl_Regs->mask[_cpu] = _previous & ~_mask; \
|
grlib_store_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ], (_previous) & ~_mask); \
|
||||||
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
||||||
(_previous) &= _mask; \
|
(_previous) &= _mask; \
|
||||||
} while (0)
|
} while (0)
|
||||||
@@ -242,10 +242,12 @@ extern uint32_t LEON3_Cpu_Index;
|
|||||||
#define LEON_Cpu_Restore_interrupt( _source, _previous, _cpu ) \
|
#define LEON_Cpu_Restore_interrupt( _source, _previous, _cpu ) \
|
||||||
do { \
|
do { \
|
||||||
rtems_interrupt_lock_context _lock_context; \
|
rtems_interrupt_lock_context _lock_context; \
|
||||||
uint32_t _mask = 1U << (_source); \
|
uint32_t _pimask; \
|
||||||
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
LEON3_IRQCTRL_ACQUIRE( &_lock_context ); \
|
||||||
LEON3_IrqCtrl_Regs->mask[_cpu] = \
|
_pimask = grlib_load_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ]); \
|
||||||
(LEON3_IrqCtrl_Regs->mask[_cpu] & ~_mask) | (_previous); \
|
_pimask &= ~(1U << (_source)); \
|
||||||
|
_pimask |= _previous; \
|
||||||
|
grlib_store_32(&LEON3_IrqCtrl_Regs->pimask[_cpu ], _pimask); \
|
||||||
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
LEON3_IRQCTRL_RELEASE( &_lock_context ); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -389,15 +391,6 @@ extern unsigned int leon3_timer_prescaler;
|
|||||||
|
|
||||||
RTEMS_NO_RETURN void leon3_power_down_loop(void);
|
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)
|
static inline void leon3_set_system_register(uint32_t addr, uint32_t val)
|
||||||
{
|
{
|
||||||
__asm__ volatile(
|
__asm__ volatile(
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ RTEMS_SYSINIT_ITEM(
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Pointers to Interrupt Controller configuration registers */
|
/* Pointers to Interrupt Controller configuration registers */
|
||||||
volatile struct irqmp_regs *LEON3_IrqCtrl_Regs;
|
irqamp *LEON3_IrqCtrl_Regs;
|
||||||
struct ambapp_dev *LEON3_IrqCtrl_Adev;
|
struct ambapp_dev *LEON3_IrqCtrl_Adev;
|
||||||
volatile struct gptimer_regs *LEON3_Timer_Regs;
|
volatile struct gptimer_regs *LEON3_Timer_Regs;
|
||||||
struct ambapp_dev *LEON3_Timer_Adev;
|
struct ambapp_dev *LEON3_Timer_Adev;
|
||||||
@@ -133,7 +133,6 @@ struct ambapp_dev *LEON3_Timer_Adev;
|
|||||||
|
|
||||||
static void amba_initialize(void)
|
static void amba_initialize(void)
|
||||||
{
|
{
|
||||||
int icsel;
|
|
||||||
struct ambapp_dev *adev;
|
struct ambapp_dev *adev;
|
||||||
struct ambapp_bus *plb;
|
struct ambapp_bus *plb;
|
||||||
|
|
||||||
@@ -151,15 +150,17 @@ static void amba_initialize(void)
|
|||||||
bsp_fatal(LEON3_FATAL_NO_IRQMP_CONTROLLER);
|
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;
|
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
|
/* IRQ Controller has support for multiple IRQ Controllers, each
|
||||||
* CPU can be routed to different Controllers, we find out which
|
* CPU can be routed to different Controllers, we find out which
|
||||||
* controller by looking at the IRQCTRL Select Register for this CPU.
|
* controller by looking at the IRQCTRL Select Register for this CPU.
|
||||||
* Each Controller is located at a 4KByte offset.
|
* 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;
|
icsel = (icsel >> ((7 - (LEON3_Cpu_Index & 0x7)) * 4)) & 0xf;
|
||||||
LEON3_IrqCtrl_Regs += icsel;
|
LEON3_IrqCtrl_Regs += icsel;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ void bsp_fatal_extension(
|
|||||||
(code == SMP_FATAL_SHUTDOWN_RESPONSE)) {
|
(code == SMP_FATAL_SHUTDOWN_RESPONSE)) {
|
||||||
leon3_power_down_loop(); /* CPU didn't start shutdown sequence .. */
|
leon3_power_down_loop(); /* CPU didn't start shutdown sequence .. */
|
||||||
} else {
|
} 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
|
* Value was chosen to get something in the magnitude of 1ms on a 200MHz
|
||||||
* processor.
|
* processor.
|
||||||
@@ -76,7 +76,10 @@ void bsp_fatal_extension(
|
|||||||
|
|
||||||
/* Wait some time for secondary processors to halt */
|
/* Wait some time for secondary processors to halt */
|
||||||
i = 0;
|
i = 0;
|
||||||
while ((irqmp->mpstat & halt_mask) != halt_mask && i < max_wait) {
|
while (
|
||||||
|
(grlib_load_32(®s->mpstat) & halt_mask) != halt_mask &&
|
||||||
|
i < max_wait
|
||||||
|
) {
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <bsp/bootcard.h>
|
#include <bsp/bootcard.h>
|
||||||
#include <bsp/fatal.h>
|
#include <bsp/fatal.h>
|
||||||
#include <bsp/irq.h>
|
#include <bsp/irq.h>
|
||||||
|
#include <bsp/leon3.h>
|
||||||
#include <leon.h>
|
#include <leon.h>
|
||||||
#include <rtems/bspIo.h>
|
#include <rtems/bspIo.h>
|
||||||
#include <rtems/sysinit.h>
|
#include <rtems/sysinit.h>
|
||||||
@@ -75,6 +76,11 @@ static void leon3_install_inter_processor_interrupt( void )
|
|||||||
_Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL );
|
_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( ®s->mpstat ) ) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t _CPU_SMP_Initialize( void )
|
uint32_t _CPU_SMP_Initialize( void )
|
||||||
{
|
{
|
||||||
if ( !leon3_data_cache_snooping_enabled() )
|
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 );
|
printk( "Waking CPU %d\n", cpu_index );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LEON3_IrqCtrl_Regs->mpstat = 1U << cpu_index;
|
grlib_store_32(
|
||||||
|
&LEON3_IrqCtrl_Regs->mpstat,
|
||||||
|
IRQAMP_MPSTAT_STATUS(1U << cpu_index)
|
||||||
|
);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -111,7 +120,10 @@ void _CPU_SMP_Prepare_start_multitasking( void )
|
|||||||
void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
|
void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
|
||||||
{
|
{
|
||||||
/* send interrupt to destination CPU */
|
/* 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)
|
#if defined(RTEMS_DRVMGR_STARTUP)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <leon.h>
|
#include <leon.h>
|
||||||
|
#include <grlib/irqamp.h>
|
||||||
|
|
||||||
#include <rtems/counter.h>
|
#include <rtems/counter.h>
|
||||||
#include <rtems/sysinit.h>
|
#include <rtems/sysinit.h>
|
||||||
@@ -40,11 +41,11 @@ uint32_t _CPU_Counter_frequency(void)
|
|||||||
|
|
||||||
static void leon3_counter_initialize(void)
|
static void leon3_counter_initialize(void)
|
||||||
{
|
{
|
||||||
volatile struct irqmp_timestamp_regs *irqmp_ts;
|
irqamp_timestamp *irqmp_ts;
|
||||||
volatile struct gptimer_regs *gpt;
|
volatile struct gptimer_regs *gpt;
|
||||||
SPARC_Counter *counter;
|
SPARC_Counter *counter;
|
||||||
|
|
||||||
irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
|
irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
|
||||||
gpt = LEON3_Timer_Regs;
|
gpt = LEON3_Timer_Regs;
|
||||||
counter = &_SPARC_Counter_mutable;
|
counter = &_SPARC_Counter_mutable;
|
||||||
|
|
||||||
@@ -56,14 +57,14 @@ static void leon3_counter_initialize(void)
|
|||||||
counter->read = _SPARC_Counter_read_asr23;
|
counter->read = _SPARC_Counter_read_asr23;
|
||||||
|
|
||||||
leon3_counter_frequency = leon3_up_counter_frequency();
|
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 */
|
/* Use the interrupt controller timestamp counter if available */
|
||||||
counter->read_isr_disabled = _SPARC_Counter_read_up;
|
counter->read_isr_disabled = _SPARC_Counter_read_up;
|
||||||
counter->read = _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 */
|
/* 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);
|
leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_IrqCtrl_Adev);
|
||||||
} else if (gpt != NULL) {
|
} else if (gpt != NULL) {
|
||||||
|
|||||||
@@ -31,9 +31,9 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <leon.h>
|
|
||||||
#include <bsp/irq.h>
|
#include <bsp/irq.h>
|
||||||
#include <bsp/irq-generic.h>
|
#include <bsp/irq-generic.h>
|
||||||
|
#include <bsp/irqimpl.h>
|
||||||
|
|
||||||
/* GRLIB extended IRQ controller IRQ number */
|
/* GRLIB extended IRQ controller IRQ number */
|
||||||
uint32_t LEON3_IrqCtrl_EIrq;
|
uint32_t LEON3_IrqCtrl_EIrq;
|
||||||
@@ -42,12 +42,12 @@ rtems_interrupt_lock LEON3_IrqCtrl_Lock =
|
|||||||
RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl");
|
RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl");
|
||||||
|
|
||||||
/* Initialize Extended Interrupt controller */
|
/* 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;
|
grlib_store_32(®s->pimask[LEON3_Cpu_Index], 0);
|
||||||
regs->force[LEON3_Cpu_Index] = 0;
|
grlib_store_32(®s->piforce[LEON3_Cpu_Index], 0);
|
||||||
regs->iclear = 0xffffffff;
|
grlib_store_32(®s->iclear, 0xffffffff);
|
||||||
LEON3_IrqCtrl_EIrq = (regs->mpstat >> 16) & 0xf;
|
LEON3_IrqCtrl_EIrq = IRQAMP_MPSTAT_EIRQ_GET(grlib_load_32(®s->mpstat));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
|
bool bsp_interrupt_is_valid_vector(rtems_vector_number vector)
|
||||||
@@ -112,14 +112,16 @@ rtems_status_code bsp_interrupt_is_pending(
|
|||||||
{
|
{
|
||||||
rtems_interrupt_level level;
|
rtems_interrupt_level level;
|
||||||
uint32_t bit;
|
uint32_t bit;
|
||||||
|
irqamp *regs;
|
||||||
|
|
||||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||||
bsp_interrupt_assert(pending != NULL);
|
bsp_interrupt_assert(pending != NULL);
|
||||||
bit = 1U << vector;
|
bit = 1U << vector;
|
||||||
|
regs = LEON3_IrqCtrl_Regs;
|
||||||
|
|
||||||
rtems_interrupt_local_disable(level);
|
rtems_interrupt_local_disable(level);
|
||||||
*pending = (LEON3_IrqCtrl_Regs->ipend & bit) != 0 ||
|
*pending = (grlib_load_32(®s->ipend) & bit) != 0 ||
|
||||||
(LEON3_IrqCtrl_Regs->force[rtems_scheduler_get_processor()] & bit) != 0;
|
(grlib_load_32(®s->piforce[rtems_scheduler_get_processor()]) & bit) != 0;
|
||||||
rtems_interrupt_local_enable(level);
|
rtems_interrupt_local_enable(level);
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
@@ -127,9 +129,11 @@ rtems_status_code bsp_interrupt_is_pending(
|
|||||||
rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
|
rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
|
||||||
{
|
{
|
||||||
uint32_t bit;
|
uint32_t bit;
|
||||||
|
irqamp *regs;
|
||||||
|
|
||||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||||
bit = 1U << vector;
|
bit = 1U << vector;
|
||||||
|
regs = LEON3_IrqCtrl_Regs;
|
||||||
|
|
||||||
if ( vector <= BSP_INTERRUPT_VECTOR_MAX_STD ) {
|
if ( vector <= BSP_INTERRUPT_VECTOR_MAX_STD ) {
|
||||||
uint32_t cpu_count;
|
uint32_t cpu_count;
|
||||||
@@ -138,10 +142,11 @@ rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
|
|||||||
cpu_count = rtems_scheduler_get_processor_maximum();
|
cpu_count = rtems_scheduler_get_processor_maximum();
|
||||||
|
|
||||||
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
|
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 {
|
} else {
|
||||||
rtems_interrupt_lock_context lock_context;
|
rtems_interrupt_lock_context lock_context;
|
||||||
|
uint32_t ipend;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is a very dangerous operation and should only be used for test
|
* This is a very dangerous operation and should only be used for test
|
||||||
@@ -149,7 +154,9 @@ rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
|
|||||||
* peripherals with this read-modify-write operation.
|
* peripherals with this read-modify-write operation.
|
||||||
*/
|
*/
|
||||||
LEON3_IRQCTRL_ACQUIRE(&lock_context);
|
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);
|
LEON3_IRQCTRL_RELEASE(&lock_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,6 +169,8 @@ rtems_status_code bsp_interrupt_raise_on(
|
|||||||
uint32_t cpu_index
|
uint32_t cpu_index
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
irqamp *regs;
|
||||||
|
|
||||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||||
bsp_interrupt_assert(cpu_index < rtems_scheduler_get_processor_maximum());
|
bsp_interrupt_assert(cpu_index < rtems_scheduler_get_processor_maximum());
|
||||||
|
|
||||||
@@ -169,7 +178,8 @@ rtems_status_code bsp_interrupt_raise_on(
|
|||||||
return RTEMS_UNSATISFIED;
|
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;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -177,14 +187,16 @@ rtems_status_code bsp_interrupt_raise_on(
|
|||||||
rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
|
rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
|
||||||
{
|
{
|
||||||
uint32_t bit;
|
uint32_t bit;
|
||||||
|
irqamp *regs;
|
||||||
|
|
||||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||||
bit = 1U << 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) {
|
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;
|
return RTEMS_SUCCESSFUL;
|
||||||
@@ -195,9 +207,16 @@ rtems_status_code bsp_interrupt_vector_is_enabled(
|
|||||||
bool *enabled
|
bool *enabled
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
uint32_t bit;
|
||||||
|
irqamp *regs;
|
||||||
|
uint32_t pimask;
|
||||||
|
|
||||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
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;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,6 +228,8 @@ static void leon3_interrupt_vector_enable(rtems_vector_number vector)
|
|||||||
Processor_mask affinity;
|
Processor_mask affinity;
|
||||||
uint32_t bit;
|
uint32_t bit;
|
||||||
uint32_t unmasked;
|
uint32_t unmasked;
|
||||||
|
uint32_t brdcst;
|
||||||
|
irqamp *regs;
|
||||||
|
|
||||||
if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) {
|
if (vector <= BSP_INTERRUPT_VECTOR_MAX_STD) {
|
||||||
affinity = leon3_interrupt_affinities[vector];
|
affinity = leon3_interrupt_affinities[vector];
|
||||||
@@ -218,72 +239,103 @@ static void leon3_interrupt_vector_enable(rtems_vector_number vector)
|
|||||||
|
|
||||||
cpu_count = rtems_scheduler_get_processor_maximum();
|
cpu_count = rtems_scheduler_get_processor_maximum();
|
||||||
bit = 1U << vector;
|
bit = 1U << vector;
|
||||||
|
regs = LEON3_IrqCtrl_Regs;
|
||||||
unmasked = 0;
|
unmasked = 0;
|
||||||
|
|
||||||
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
|
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)) {
|
if (_Processor_mask_Is_set(&affinity, cpu_index)) {
|
||||||
++unmasked;
|
++unmasked;
|
||||||
mask |= bit;
|
pimask |= bit;
|
||||||
} else {
|
} 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) {
|
if (unmasked > 1) {
|
||||||
LEON3_IrqCtrl_Regs->bcast |= bit;
|
brdcst |= bit;
|
||||||
} else {
|
} else {
|
||||||
LEON3_IrqCtrl_Regs->bcast &= ~bit;
|
brdcst &= ~bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grlib_store_32(®s->brdcst, brdcst);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
|
rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
|
||||||
{
|
{
|
||||||
#if defined(RTEMS_SMP)
|
|
||||||
rtems_interrupt_lock_context lock_context;
|
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));
|
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||||
LEON3_IRQCTRL_ACQUIRE(&lock_context);
|
#if !defined(RTEMS_SMP)
|
||||||
leon3_interrupt_vector_enable(vector);
|
bit = 1U << vector;
|
||||||
LEON3_IRQCTRL_RELEASE(&lock_context);
|
regs = LEON3_IrqCtrl_Regs;
|
||||||
#else
|
|
||||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
|
||||||
BSP_Cpu_Unmask_interrupt(vector, _LEON3_Get_current_processor());
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
LEON3_IRQCTRL_ACQUIRE(&lock_context);
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
|
leon3_interrupt_vector_enable(vector);
|
||||||
|
#else
|
||||||
|
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;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
|
rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
|
||||||
{
|
{
|
||||||
#if defined(RTEMS_SMP)
|
|
||||||
rtems_interrupt_lock_context lock_context;
|
rtems_interrupt_lock_context lock_context;
|
||||||
uint32_t bit;
|
uint32_t bit;
|
||||||
|
irqamp *regs;
|
||||||
|
uint32_t pimask;
|
||||||
uint32_t cpu_index;
|
uint32_t cpu_index;
|
||||||
|
#if defined(RTEMS_SMP)
|
||||||
uint32_t cpu_count;
|
uint32_t cpu_count;
|
||||||
|
uint32_t brdcst;
|
||||||
|
#endif
|
||||||
|
|
||||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
||||||
bit = 1U << vector;
|
bit = 1U << vector;
|
||||||
cpu_count = rtems_scheduler_get_processor_maximum();
|
regs = LEON3_IrqCtrl_Regs;
|
||||||
|
|
||||||
LEON3_IRQCTRL_ACQUIRE(&lock_context);
|
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) {
|
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;
|
brdcst = grlib_load_32(®s->brdcst);
|
||||||
|
brdcst &= ~bit;
|
||||||
|
grlib_store_32(®s->brdcst, brdcst);
|
||||||
|
#else
|
||||||
|
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);
|
LEON3_IRQCTRL_RELEASE(&lock_context);
|
||||||
#else
|
|
||||||
bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
|
|
||||||
BSP_Cpu_Mask_interrupt(vector, _LEON3_Get_current_processor());
|
|
||||||
#endif
|
|
||||||
return RTEMS_SUCCESSFUL;
|
return RTEMS_SUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,6 +349,7 @@ rtems_status_code bsp_interrupt_set_affinity(
|
|||||||
uint32_t cpu_count;
|
uint32_t cpu_count;
|
||||||
uint32_t cpu_index;
|
uint32_t cpu_index;
|
||||||
uint32_t bit;
|
uint32_t bit;
|
||||||
|
irqamp *regs;
|
||||||
|
|
||||||
if (vector >= RTEMS_ARRAY_SIZE(leon3_interrupt_affinities)) {
|
if (vector >= RTEMS_ARRAY_SIZE(leon3_interrupt_affinities)) {
|
||||||
return RTEMS_UNSATISFIED;
|
return RTEMS_UNSATISFIED;
|
||||||
@@ -304,6 +357,7 @@ rtems_status_code bsp_interrupt_set_affinity(
|
|||||||
|
|
||||||
cpu_count = rtems_scheduler_get_processor_maximum();
|
cpu_count = rtems_scheduler_get_processor_maximum();
|
||||||
bit = 1U << vector;
|
bit = 1U << vector;
|
||||||
|
regs = LEON3_IrqCtrl_Regs;
|
||||||
|
|
||||||
LEON3_IRQCTRL_ACQUIRE(&lock_context);
|
LEON3_IRQCTRL_ACQUIRE(&lock_context);
|
||||||
leon3_interrupt_affinities[vector] = *affinity;
|
leon3_interrupt_affinities[vector] = *affinity;
|
||||||
@@ -313,7 +367,7 @@ rtems_status_code bsp_interrupt_set_affinity(
|
|||||||
* using the new affinity.
|
* using the new affinity.
|
||||||
*/
|
*/
|
||||||
for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
|
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);
|
leon3_interrupt_vector_enable(vector);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user