summaryrefslogtreecommitdiffstats
path: root/bsps/sparc/leon3/start
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/sparc/leon3/start')
-rw-r--r--bsps/sparc/leon3/start/amba.c69
-rw-r--r--bsps/sparc/leon3/start/bsp_fatal_halt.c31
-rw-r--r--bsps/sparc/leon3/start/bsp_specs0
-rw-r--r--bsps/sparc/leon3/start/bspclean.c86
-rw-r--r--bsps/sparc/leon3/start/bspdelay.c8
-rw-r--r--bsps/sparc/leon3/start/bspidle.S25
-rw-r--r--bsps/sparc/leon3/start/bspsmp.c44
-rw-r--r--bsps/sparc/leon3/start/bspstart.c46
-rw-r--r--bsps/sparc/leon3/start/cache.c90
-rw-r--r--bsps/sparc/leon3/start/cpucounter.c308
-rw-r--r--bsps/sparc/leon3/start/drvmgr_def_drivers.c25
-rw-r--r--bsps/sparc/leon3/start/eirq.c185
-rw-r--r--bsps/sparc/leon3/start/gettargethash.c71
-rw-r--r--bsps/sparc/leon3/start/setvec.c2
14 files changed, 724 insertions, 266 deletions
diff --git a/bsps/sparc/leon3/start/amba.c b/bsps/sparc/leon3/start/amba.c
index 4801916825..05708e06d0 100644
--- a/bsps/sparc/leon3/start/amba.c
+++ b/bsps/sparc/leon3/start/amba.c
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* AMBA Plug & Play Bus Driver
*
@@ -6,9 +8,26 @@
* 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 <bsp.h>
@@ -20,8 +39,10 @@
#include <string.h>
+#if !defined(LEON3_GPTIMER_BASE)
unsigned int leon3_timer_prescaler __attribute__((weak)) = 0;
int leon3_timer_core_index __attribute__((weak)) = 0;
+#endif
/* AMBA Plug&Play information description.
*
@@ -96,14 +117,15 @@ RTEMS_SYSINIT_ITEM(
);
#endif
-rtems_interrupt_lock LEON3_IrqCtrl_Lock =
- RTEMS_INTERRUPT_LOCK_INITIALIZER("LEON3 IrqCtrl");
-
-/* Pointers to Interrupt Controller configuration registers */
-volatile struct irqmp_regs *LEON3_IrqCtrl_Regs;
+#if !defined(LEON3_IRQAMP_BASE)
+irqamp *LEON3_IrqCtrl_Regs;
struct ambapp_dev *LEON3_IrqCtrl_Adev;
-volatile struct gptimer_regs *LEON3_Timer_Regs;
+#endif
+
+#if !defined(LEON3_GPTIMER_BASE)
+gptimer *LEON3_Timer_Regs;
struct ambapp_dev *LEON3_Timer_Adev;
+#endif
/*
* amba_initialize
@@ -117,12 +139,16 @@ struct ambapp_dev *LEON3_Timer_Adev;
static void amba_initialize(void)
{
- int icsel;
struct ambapp_dev *adev;
struct ambapp_bus *plb;
plb = ambapp_plb();
+#if defined(LEON3_IRQAMP_BASE) && defined(LEON3_GPTIMER_BASE)
+ (void) plb;
+ (void) adev;
+#endif
+#if !defined(LEON3_IRQAMP_BASE)
/* Find LEON3 Interrupt controller */
adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
VENDOR_GAISLER, GAISLER_IRQMP,
@@ -135,38 +161,36 @@ 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;
}
- LEON3_IrqCtrl_Regs->mask[LEON3_Cpu_Index] = 0;
- LEON3_IrqCtrl_Regs->force[LEON3_Cpu_Index] = 0;
- LEON3_IrqCtrl_Regs->iclear = 0xffffffff;
-
- /* Init Extended IRQ controller if available */
- leon3_ext_irq_init();
+#endif
+#if !defined(LEON3_GPTIMER_BASE)
/* find GP Timer */
adev = (void *)ambapp_for_each(plb, (OPTIONS_ALL|OPTIONS_APB_SLVS),
VENDOR_GAISLER, GAISLER_GPTIMER,
ambapp_find_by_idx, &leon3_timer_core_index);
if (adev) {
- LEON3_Timer_Regs = (volatile struct gptimer_regs *)DEV_TO_APB(adev)->start;
+ LEON3_Timer_Regs = (gptimer *)DEV_TO_APB(adev)->start;
LEON3_Timer_Adev = adev;
/* Register AMBA Bus Frequency */
ambapp_freq_init(
plb,
LEON3_Timer_Adev,
- (LEON3_Timer_Regs->scaler_reload + 1)
+ (grlib_load_32(&LEON3_Timer_Regs->sreload) + 1)
* LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER
);
/* Set user prescaler configuration. Use this to increase accuracy of timer
@@ -175,8 +199,9 @@ static void amba_initialize(void)
* GRTIMER/GPTIMER hardware. See HW manual.
*/
if (leon3_timer_prescaler)
- LEON3_Timer_Regs->scaler_reload = leon3_timer_prescaler;
+ grlib_store_32(&LEON3_Timer_Regs->sreload, leon3_timer_prescaler);
}
+#endif
}
RTEMS_SYSINIT_ITEM(
diff --git a/bsps/sparc/leon3/start/bsp_fatal_halt.c b/bsps/sparc/leon3/start/bsp_fatal_halt.c
deleted file mode 100644
index 5a6e3f490e..0000000000
--- a/bsps/sparc/leon3/start/bsp_fatal_halt.c
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * @file
- * @ingroup sparc_leon3
- * @brief LEON3 BSP Fatal_halt handler.
- *
- * COPYRIGHT (c) 2014.
- * Aeroflex Gaisler AB.
- *
- * 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.
- */
-
-#include <bsp.h>
-#include <leon.h>
-#include <rtems/score/cpuimpl.h>
-
-void _CPU_Fatal_halt( uint32_t source, CPU_Uint32ptr error )
-{
-#ifdef BSP_POWER_DOWN_AT_FATAL_HALT
- /* Power down LEON CPU on fatal error exit */
- sparc_disable_interrupts();
- leon3_power_down_loop();
-#else
- /*
- * Return to debugger, simulator, hypervisor or similar by exiting
- * with an error code. g1=1, g2=FATAL_SOURCE, G3=error-code.
- */
- sparc_syscall_exit(source, error);
-#endif
-}
diff --git a/bsps/sparc/leon3/start/bsp_specs b/bsps/sparc/leon3/start/bsp_specs
deleted file mode 100644
index e69de29bb2..0000000000
--- a/bsps/sparc/leon3/start/bsp_specs
+++ /dev/null
diff --git a/bsps/sparc/leon3/start/bspclean.c b/bsps/sparc/leon3/start/bspclean.c
index a818e99631..d624ec74c8 100644
--- a/bsps/sparc/leon3/start/bspclean.c
+++ b/bsps/sparc/leon3/start/bspclean.c
@@ -1,73 +1,62 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/**
* @file
- * @ingroup sparc_leon3
+ * @ingroup RTEMSBSPsSPARCLEON3
* @brief LEON3 BSP fatal extension
*
- * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
- *
- * embedded brains GmbH
- * Dornierstr. 4
- * 82178 Puchheim
- * Germany
- * <rtems@embedded-brains.de>
+ * Copyright (c) 2014 embedded brains GmbH & Co. KG
*
* COPYRIGHT (c) 2014
* 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 <bsp.h>
#include <bsp/bootcard.h>
+#include <bsp/leon3.h>
+#include <rtems/score/cpuimpl.h>
#include <rtems/score/smpimpl.h>
-#include <leon.h>
-
void bsp_fatal_extension(
rtems_fatal_source source,
bool always_set_to_false,
rtems_fatal_code code
)
{
+ rtems_interrupt_level level;
+
+ (void) always_set_to_false;
+ rtems_interrupt_local_disable(level);
+ (void) level;
+
#if defined(RTEMS_SMP)
- /*
- * On SMP we must wait for all other CPUs not requesting a fatal halt, they
- * are responding to another CPU's fatal request. These CPUs goes into
- * power-down. The CPU requesting fatal halt waits for the others and then
- * handles the system shutdown via the normal procedure.
- */
if ((source == RTEMS_FATAL_SOURCE_SMP) &&
(code == SMP_FATAL_SHUTDOWN_RESPONSE)) {
leon3_power_down_loop(); /* CPU didn't start shutdown sequence .. */
- } else {
- volatile struct irqmp_regs *irqmp = LEON3_IrqCtrl_Regs;
-
- if (irqmp != NULL) {
- /*
- * Value was chosen to get something in the magnitude of 1ms on a 200MHz
- * processor.
- */
- uint32_t max_wait = 1234567;
- uint32_t self_cpu = rtems_scheduler_get_processor();
- uint32_t cpu_count = rtems_scheduler_get_processor_maximum();
- uint32_t halt_mask = 0;
- uint32_t i;
-
- for (i = 0; i < cpu_count; ++i) {
- if ( (i != self_cpu) && _SMP_Should_start_processor( i ) ) {
- halt_mask |= UINT32_C(1) << i;
- }
- }
-
- /* Wait some time for secondary processors to halt */
- i = 0;
- while ((irqmp->mpstat & halt_mask) != halt_mask && i < max_wait) {
- ++i;
- }
- }
}
+
+ _SMP_Request_shutdown();
#endif
#if BSP_PRINT_EXCEPTION_CONTEXT
@@ -77,7 +66,10 @@ void bsp_fatal_extension(
#endif
#if BSP_RESET_BOARD_AT_EXIT
- /* If user wants to implement custom reset/reboot it can be done here */
- bsp_reset();
+ /*
+ * Stop the system termination right now. This skips the dynamically
+ * installed fatal error extensions and the generics shutdown procedure.
+ */
+ _CPU_Fatal_halt( source, code );
#endif
}
diff --git a/bsps/sparc/leon3/start/bspdelay.c b/bsps/sparc/leon3/start/bspdelay.c
index c4a880be6d..6695f76929 100644
--- a/bsps/sparc/leon3/start/bspdelay.c
+++ b/bsps/sparc/leon3/start/bspdelay.c
@@ -14,15 +14,17 @@
*/
#include <bsp.h>
-#include <leon.h>
+#include <bsp/leon3.h>
void rtems_bsp_delay(int usecs)
{
uint32_t then;
+ gptimer_timer *regs;
- then =LEON3_Timer_Regs->timer[0].value;
+ regs = &LEON3_Timer_Regs->timer[0];
+ then =grlib_load_32(&regs->tcntval);
then += usecs;
- while (LEON3_Timer_Regs->timer[0].value >= then)
+ while (grlib_load_32(&regs->tcntval) >= then)
;
}
diff --git a/bsps/sparc/leon3/start/bspidle.S b/bsps/sparc/leon3/start/bspidle.S
index 8557ff42a1..82c04a231d 100644
--- a/bsps/sparc/leon3/start/bspidle.S
+++ b/bsps/sparc/leon3/start/bspidle.S
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* Idle Thread Body
*
@@ -6,9 +8,26 @@
* COPYRIGHT (c) 2004.
* Gaisler Research.
*
- * 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.
*/
diff --git a/bsps/sparc/leon3/start/bspsmp.c b/bsps/sparc/leon3/start/bspsmp.c
index 1c72027ebf..82d6e5a163 100644
--- a/bsps/sparc/leon3/start/bspsmp.c
+++ b/bsps/sparc/leon3/start/bspsmp.c
@@ -1,6 +1,6 @@
/**
* @file
- * @ingroup sparc_leon3
+ * @ingroup RTEMSBSPsSPARCLEON3
* @brief LEON3 SMP BSP Support
*/
@@ -16,8 +16,8 @@
#include <bsp.h>
#include <bsp/bootcard.h>
#include <bsp/fatal.h>
-#include <bsp/irq.h>
-#include <leon.h>
+#include <bsp/irq-generic.h>
+#include <bsp/leon3.h>
#include <rtems/bspIo.h>
#include <rtems/sysinit.h>
#include <rtems/score/assert.h>
@@ -39,18 +39,20 @@ static void bsp_inter_processor_interrupt( void *arg )
void bsp_start_on_secondary_processor(Per_CPU_Control *cpu_self)
{
- /*
- * If data cache snooping is not enabled we terminate using BSP_fatal_exit()
- * instead of bsp_fatal(). This is done since the latter function tries to
- * acquire a ticket lock, an operation which requires data cache snooping to
- * be enabled.
- */
- if ( !leon3_data_cache_snooping_enabled() )
- BSP_fatal_exit( LEON3_FATAL_INVALID_CACHE_CONFIG_SECONDARY_PROCESSOR );
+ if ( !leon3_data_cache_snooping_enabled() ) {
+ bsp_fatal( LEON3_FATAL_INVALID_CACHE_CONFIG_SECONDARY_PROCESSOR );
+ }
_SMP_Start_multitasking_on_secondary_processor(cpu_self);
}
+static rtems_interrupt_entry leon3_inter_processor_interrupt_entry =
+ RTEMS_INTERRUPT_ENTRY_INITIALIZER(
+ bsp_inter_processor_interrupt,
+ NULL,
+ "IPI"
+ );
+
static void leon3_install_inter_processor_interrupt( void )
{
rtems_status_code sc;
@@ -60,12 +62,10 @@ static void leon3_install_inter_processor_interrupt( void )
bsp_interrupt_set_affinity( irq, _SMP_Get_online_processors() );
- sc = rtems_interrupt_handler_install(
+ sc = rtems_interrupt_entry_install(
irq,
- "IPI",
RTEMS_INTERRUPT_SHARED,
- bsp_inter_processor_interrupt,
- NULL
+ &leon3_inter_processor_interrupt_entry
);
_Assert_Unused_variable_equals( sc, RTEMS_SUCCESSFUL );
}
@@ -73,7 +73,7 @@ static void leon3_install_inter_processor_interrupt( void )
uint32_t _CPU_SMP_Initialize( void )
{
if ( !leon3_data_cache_snooping_enabled() )
- bsp_fatal( LEON3_FATAL_INVALID_CACHE_CONFIG_MAIN_PROCESSOR );
+ bsp_fatal( LEON3_FATAL_INVALID_CACHE_CONFIG_BOOT_PROCESSOR );
return leon3_get_cpu_count(LEON3_IrqCtrl_Regs);
}
@@ -84,7 +84,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;
}
@@ -100,13 +103,16 @@ void _CPU_SMP_Finalize_initialization( uint32_t cpu_count )
void _CPU_SMP_Prepare_start_multitasking( void )
{
- rtems_cache_invalidate_entire_instruction();
+ /* Do nothing */
}
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/bspstart.c b/bsps/sparc/leon3/start/bspstart.c
index 75042e4c20..2c3844f78d 100644
--- a/bsps/sparc/leon3/start/bspstart.c
+++ b/bsps/sparc/leon3/start/bspstart.c
@@ -1,9 +1,15 @@
-/*
- * This set of routines starts the application. It includes application,
- * board, and monitor specific initialization and configuration.
- * The generic CPU dependent initialization has been performed
- * before any of these are invoked.
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSBSPsSPARCLEON3
*
+ * @brief This source file contains the implementation of bsp_start() and
+ * definitions of BSP-specific objects.
+ */
+
+/*
* COPYRIGHT (c) 2011
* Aeroflex Gaisler
*
@@ -14,14 +20,31 @@
* COPYRIGHT (c) 2004.
* Gaisler Research.
*
- * 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 <bsp.h>
#include <bsp/irq-generic.h>
-#include <leon.h>
+#include <bsp/leon3.h>
#include <bsp/bootcard.h>
#include <rtems/sysinit.h>
@@ -40,11 +63,6 @@ int CPU_SPARC_HAS_SNOOPING;
/* Index of CPU, in an AMP system CPU-index may be non-zero */
uint32_t LEON3_Cpu_Index = 0;
-#if defined(RTEMS_SMP)
-/* Index of the boot CPU. Set by the first CPU at boot to its CPU ID. */
-int LEON3_Boot_Cpu = -1;
-#endif
-
/*
* set_snooping
*
diff --git a/bsps/sparc/leon3/start/cache.c b/bsps/sparc/leon3/start/cache.c
index c428efa119..11af2f4d01 100644
--- a/bsps/sparc/leon3/start/cache.c
+++ b/bsps/sparc/leon3/start/cache.c
@@ -1,19 +1,31 @@
-/*
- * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
+/**
+ * @file
*
- * embedded brains GmbH
- * Dornierstr. 4
- * 82178 Puchheim
- * Germany
- * <rtems@embedded-brains.de>
+ * @ingroup RTEMSBSPsSPARCLEON3
+ *
+ * @brief This source file contains the implementation of the Cache Manager.
+ */
+
+/*
+ * Copyright (c) 2014 embedded brains GmbH & Co. KG
*
* 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.
*/
-#include <amba.h>
-#include <leon.h>
+#include <grlib/l2cache-regs.h>
+#include <grlib/io.h>
+
+#include <bsp/leon3.h>
+
+#if !defined(LEON3_L2CACHE_BASE)
+#include <grlib/ambapp.h>
+#endif
+
+#if !defined(LEON3_L2CACHE_BASE) || LEON3_L2CACHE_BASE != 0
+#define LEON3_MAYBE_HAS_L2CACHE
+#endif
#define CPU_CACHE_SUPPORT_PROVIDES_RANGE_FUNCTIONS
@@ -25,12 +37,12 @@
#define CPU_DATA_CACHE_ALIGNMENT 64
-static inline volatile struct l2c_regs *get_l2c_regs(void)
+#if !defined(LEON3_L2CACHE_BASE)
+static inline l2cache *get_l2c_regs(void)
{
- volatile struct l2c_regs *l2c = NULL;
struct ambapp_dev *adev;
- adev = (void *) ambapp_for_each(
+ adev = (struct ambapp_dev *) ambapp_for_each(
ambapp_plb(),
OPTIONS_ALL | OPTIONS_AHB_SLVS,
VENDOR_GAISLER,
@@ -38,28 +50,14 @@ static inline volatile struct l2c_regs *get_l2c_regs(void)
ambapp_find_by_idx,
NULL
);
- if (adev != NULL) {
- l2c = (volatile struct l2c_regs *) DEV_TO_AHB(adev)->start[1];
- }
-
- return l2c;
-}
-
-static inline size_t get_l2_size(void)
-{
- size_t size = 0;
- volatile struct l2c_regs *l2c = get_l2c_regs();
-
- if (l2c != NULL) {
- unsigned status = l2c->status;
- unsigned ways = (status & 0x3) + 1;
- unsigned set_size = ((status & 0x7ff) >> 2) * 1024;
- size = ways * set_size;
+ if (adev == NULL) {
+ return NULL;
}
- return size;
+ return (l2cache *) DEV_TO_AHB(adev)->start[1];
}
+#endif
static inline size_t get_l1_size(uint32_t l1_cfg)
{
@@ -69,10 +67,36 @@ static inline size_t get_l1_size(uint32_t l1_cfg)
return ways * wsize;
}
+#if defined(LEON3_MAYBE_HAS_L2CACHE)
+static inline size_t get_l2_size(void)
+{
+ l2cache *regs;
+ unsigned status;
+ unsigned ways;
+ unsigned set_size;
+
+#if defined(LEON3_L2CACHE_BASE)
+ regs = (l2cache *) LEON3_L2CACHE_BASE;
+#else
+ regs = get_l2c_regs();
+
+ if (regs == NULL) {
+ return 0;
+ }
+#endif
+
+ status = grlib_load_32(&regs->l2cs);
+ ways = L2CACHE_L2CS_WAY_GET(status) + 1;
+ set_size = L2CACHE_L2CS_WAY_SIZE_GET(status) * 1024;
+
+ return ways * set_size;
+}
+
static inline size_t get_max_size(size_t a, size_t b)
{
return a < b ? b : a;
}
+#endif
static inline size_t get_cache_size(uint32_t level, uint32_t l1_cfg)
{
@@ -80,14 +104,20 @@ static inline size_t get_cache_size(uint32_t level, uint32_t l1_cfg)
switch (level) {
case 0:
+#if defined(LEON3_MAYBE_HAS_L2CACHE)
size = get_max_size(get_l1_size(l1_cfg), get_l2_size());
+#else
+ size = get_l1_size(l1_cfg);
+#endif
break;
case 1:
size = get_l1_size(l1_cfg);
break;
+#if defined(LEON3_MAYBE_HAS_L2CACHE)
case 2:
size = get_l2_size();
break;
+#endif
default:
size = 0;
break;
diff --git a/bsps/sparc/leon3/start/cpucounter.c b/bsps/sparc/leon3/start/cpucounter.c
index 73a306a1eb..8ca1962de9 100644
--- a/bsps/sparc/leon3/start/cpucounter.c
+++ b/bsps/sparc/leon3/start/cpucounter.c
@@ -1,73 +1,295 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSBSPsSPARCLEON3
+ *
+ * @brief This source file contains the implementation of the CPU Counter.
+ */
+
/*
- * Copyright (c) 2014, 2018 embedded brains GmbH. All rights reserved.
+ * Copyright (C) 2014, 2023 embedded brains GmbH & Co. KG
*
- * embedded brains GmbH
- * Dornierstr. 4
- * 82178 Puchheim
- * Germany
- * <rtems@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.
*
- * 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.
+ * 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/leon3.h>
+#include <grlib/irqamp.h>
#include <rtems/counter.h>
#include <rtems/sysinit.h>
-#include <rtems/score/sparcimpl.h>
+#include <rtems/timecounter.h>
+
+#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER) || \
+ defined(LEON3_PROBE_ASR_22_23_UP_COUNTER)
+static uint32_t leon3_timecounter_get_asr_22_23_up_counter(
+ struct timecounter *tc
+)
+{
+ return leon3_up_counter_low();
+}
+
+static void leon3_counter_use_asr_22_23_up_counter(leon3_timecounter *tc)
+{
+#if !defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
+ tc->base.tc_get_timecount = leon3_timecounter_get_asr_22_23_up_counter;
+#endif
+ tc->base.tc_frequency = leon3_up_counter_frequency();
+}
+#endif
-static uint32_t leon3_counter_frequency = 1000000000;
+/*
+ * The following code blocks provide different CPU counter implementations.
+ * The implementation used is defined by build configuration options. For a
+ * particular chip, the best available hardware counter module may be selected
+ * by build configuration options. The default implementation tries to select
+ * the best module at runtime.
+ */
+
+#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
+
+CPU_Counter_ticks _CPU_Counter_read(void)
+{
+ return leon3_up_counter_low();
+}
+
+RTEMS_ALIAS(_CPU_Counter_read) uint32_t _SPARC_Counter_read_ISR_disabled(void);
+
+#define LEON3_GET_TIMECOUNT_INIT leon3_timecounter_get_asr_22_23_up_counter
+
+#elif defined(LEON3_DSU_BASE)
+
+/*
+ * In general, using the Debug Support Unit (DSU) is not recommended. Before
+ * you use it, check that it is available in flight models and that the time
+ * tag register is implemented in radiation hardened flip-flops. For the
+ * GR712RC, this is the case.
+ */
+
+/* This value is specific to the GR712RC */
+#define LEON3_DSU_TIME_TAG_ZERO_BITS 2
+
+static uint32_t leon3_read_dsu_time_tag(void)
+{
+ uint32_t value;
+ volatile uint32_t *reg;
+
+ /* Use a load with a forced cache miss */
+ reg = (uint32_t *) (LEON3_DSU_BASE + 8);
+ __asm__ volatile (
+ "\tlda\t[%1]1, %0"
+ : "=&r"(value)
+ : "r"(reg)
+ );
+ return value << LEON3_DSU_TIME_TAG_ZERO_BITS;
+}
+
+static uint32_t leon3_timecounter_get_dsu_time_tag(
+ struct timecounter *tc
+)
+{
+ (void) tc;
+ return leon3_read_dsu_time_tag();
+}
+
+CPU_Counter_ticks _CPU_Counter_read(void)
+{
+ return leon3_read_dsu_time_tag();
+}
+
+RTEMS_ALIAS(_CPU_Counter_read) uint32_t _SPARC_Counter_read_ISR_disabled(void);
+
+static void leon3_counter_use_dsu_time_tag(leon3_timecounter *tc)
+{
+ tc->base.tc_frequency =
+ leon3_processor_local_bus_frequency() << LEON3_DSU_TIME_TAG_ZERO_BITS;
+}
+
+#define LEON3_GET_TIMECOUNT_INIT leon3_timecounter_get_dsu_time_tag
+
+#else /* !LEON3_HAS_ASR_22_23_UP_COUNTER && !LEON3_DSU_BASE */
+
+/*
+ * This is a workaround for:
+ * https://gcc.gnu.org/bugzilla//show_bug.cgi?id=69027
+ */
+__asm__ (
+ "\t.section\t\".text\"\n"
+ "\t.align\t4\n"
+ "\t.globl\t_CPU_Counter_read\n"
+ "\t.globl\t_SPARC_Counter_read_ISR_disabled\n"
+ "\t.type\t_CPU_Counter_read, #function\n"
+ "\t.type\t_SPARC_Counter_read_ISR_disabled, #function\n"
+ "_CPU_Counter_read:\n"
+ "_SPARC_Counter_read_ISR_disabled:\n"
+ "\tsethi\t%hi(leon3_timecounter_instance), %o0\n"
+ "\tld [%o0 + %lo(leon3_timecounter_instance)], %o1\n"
+ "\tor\t%o0, %lo(leon3_timecounter_instance), %o0\n"
+ "\tor\t%o7, %g0, %g1\n"
+ "\tcall\t%o1, 0\n"
+ "\t or\t%g1, %g0, %o7\n"
+ "\t.previous\n"
+);
+
+static uint32_t leon3_timecounter_get_dummy(struct timecounter *base)
+{
+ leon3_timecounter *tc;
+ uint32_t counter;
+
+ tc = (leon3_timecounter *) base;
+ counter = tc->software_counter + 1;
+ tc->software_counter = counter;
+ return counter;
+}
+
+#define LEON3_GET_TIMECOUNT_INIT leon3_timecounter_get_dummy
+
+static uint32_t leon3_timecounter_get_counter_down(struct timecounter *base)
+{
+ leon3_timecounter *tc;
+
+ tc = (leon3_timecounter *) base;
+ return -(*tc->counter_register);
+}
+
+static void leon3_counter_use_gptimer(
+ leon3_timecounter *tc,
+ gptimer *gpt
+)
+{
+ gptimer_timer *timer;
+
+ timer = &gpt->timer[LEON3_COUNTER_GPTIMER_INDEX];
+
+ /* Make timer free-running */
+ grlib_store_32(&timer->trldval, 0xffffffff);
+ grlib_store_32(&timer->tctrl, GPTIMER_TCTRL_EN | GPTIMER_TCTRL_RS);
+
+ tc->counter_register = &timer->tcntval;
+ tc->base.tc_get_timecount = leon3_timecounter_get_counter_down;
+#if defined(LEON3_PLB_FREQUENCY_DEFINED_BY_GPTIMER)
+ tc->base.tc_frequency = LEON3_GPTIMER_0_FREQUENCY_SET_BY_BOOT_LOADER;
+#else
+ tc->base.tc_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev) /
+ (grlib_load_32(&gpt->sreload) + 1);
+#endif
+}
+
+#if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
+
+static uint32_t leon3_timecounter_get_counter_up(struct timecounter *base)
+{
+ leon3_timecounter *tc;
+
+ tc = (leon3_timecounter *) base;
+ return *tc->counter_register;
+}
+
+static void leon3_counter_use_irqamp_timestamp(
+ leon3_timecounter *tc,
+ irqamp_timestamp *irqmp_ts
+)
+{
+ /* Enable interrupt timestamping for an arbitrary interrupt line */
+ grlib_store_32(&irqmp_ts->itstmpc, IRQAMP_ITSTMPC_TSISEL(1));
+
+ tc->counter_register = &irqmp_ts->itcnt;
+ tc->base.tc_get_timecount = leon3_timecounter_get_counter_up;
+ tc->base.tc_frequency = leon3_processor_local_bus_frequency();
+}
+
+#endif /* LEON3_IRQAMP_PROBE_TIMESTAMP */
+#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER || LEON3_DSU_BASE */
+
+leon3_timecounter leon3_timecounter_instance = {
+ .base = {
+ .tc_get_timecount = LEON3_GET_TIMECOUNT_INIT,
+ .tc_counter_mask = 0xffffffff,
+ .tc_frequency = 1000000000,
+ .tc_quality = RTEMS_TIMECOUNTER_QUALITY_CLOCK_DRIVER
+ }
+};
uint32_t _CPU_Counter_frequency(void)
{
- return leon3_counter_frequency;
+ return leon3_timecounter_instance.base.tc_frequency;
}
static void leon3_counter_initialize(void)
{
- volatile struct irqmp_timestamp_regs *irqmp_ts;
- volatile struct gptimer_regs *gpt;
- SPARC_Counter *counter;
+#if defined(LEON3_HAS_ASR_22_23_UP_COUNTER)
- irqmp_ts = &LEON3_IrqCtrl_Regs->timestamp[0];
- gpt = LEON3_Timer_Regs;
- counter = &_SPARC_Counter_mutable;
+ leon3_up_counter_enable();
+ leon3_counter_use_asr_22_23_up_counter(&leon3_timecounter_instance);
+
+#elif defined(LEON3_DSU_BASE)
+
+ leon3_counter_use_dsu_time_tag(&leon3_timecounter_instance);
+#else /* !LEON3_HAS_ASR_22_23_UP_COUNTER && !LEON3_DSU_BASE */
+
+ /* Try to find the best CPU counter available */
+
+#if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
+ irqamp_timestamp *irqmp_ts;
+#endif
+ gptimer *gpt;
+ leon3_timecounter *tc;
+
+ tc = &leon3_timecounter_instance;
+
+#if defined(LEON3_PROBE_ASR_22_23_UP_COUNTER)
leon3_up_counter_enable();
if (leon3_up_counter_is_available()) {
/* Use the LEON4 up-counter if available */
- counter->read_isr_disabled = _SPARC_Counter_read_asr23;
- counter->read = _SPARC_Counter_read_asr23;
+ leon3_counter_use_asr_22_23_up_counter(tc);
+ return;
+ }
+#endif
- leon3_counter_frequency = leon3_up_counter_frequency();
- } else if (irqmp_has_timestamp(irqmp_ts)) {
+#if defined(LEON3_IRQAMP_PROBE_TIMESTAMP)
+ irqmp_ts = irqamp_get_timestamp_registers(LEON3_IrqCtrl_Regs);
+
+ 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;
+ leon3_counter_use_irqamp_timestamp(tc, irqmp_ts);
+ return;
+ }
+#endif
- /* Enable interrupt timestamping for an arbitrary interrupt line */
- irqmp_ts->control = 0x1;
+ gpt = LEON3_Timer_Regs;
- leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_IrqCtrl_Adev);
- } else if (gpt != NULL) {
+#if defined(LEON3_GPTIMER_BASE)
+ leon3_counter_use_gptimer(tc, gpt);
+#else
+ if (gpt != NULL) {
/* Fall back to the first GPTIMER if available */
- counter->read_isr_disabled = _SPARC_Counter_read_down;
- counter->read = _SPARC_Counter_read_down;
- counter->counter_register = &gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].value;
-
- /* Enable timer just in case no clock driver is configured */
- gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].reload = 0xffffffff;
- gpt->timer[LEON3_COUNTER_GPTIMER_INDEX].ctrl |= GPTIMER_TIMER_CTRL_EN |
- GPTIMER_TIMER_CTRL_RS |
- GPTIMER_TIMER_CTRL_LD;
-
- leon3_counter_frequency = ambapp_freq_get(ambapp_plb(), LEON3_Timer_Adev) /
- (gpt->scaler_reload + 1);
+ leon3_counter_use_gptimer(tc, gpt);
}
+#endif
+
+#endif /* LEON3_HAS_ASR_22_23_UP_COUNTER || LEON3_DSU_BASE */
}
RTEMS_SYSINIT_ITEM(
@@ -75,5 +297,3 @@ RTEMS_SYSINIT_ITEM(
RTEMS_SYSINIT_CPU_COUNTER,
RTEMS_SYSINIT_ORDER_FIRST
);
-
-SPARC_COUNTER_DEFINITION;
diff --git a/bsps/sparc/leon3/start/drvmgr_def_drivers.c b/bsps/sparc/leon3/start/drvmgr_def_drivers.c
index 688b37bab9..2eeed6ec46 100644
--- a/bsps/sparc/leon3/start/drvmgr_def_drivers.c
+++ b/bsps/sparc/leon3/start/drvmgr_def_drivers.c
@@ -1,12 +1,31 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
/*
* Default BSP drivers when Driver Manager enabled
*
* COPYRIGHT (c) 2019.
* Cobham 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 <bsp.h>
diff --git a/bsps/sparc/leon3/start/eirq.c b/bsps/sparc/leon3/start/eirq.c
index b94a674f64..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
*
- * Copyright (C) 2021 embedded brains GmbH (http://www.embedded-brains.de)
+ * @ingroup RTEMSBSPsSPARCLEON3
+ *
+ * @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(
@@ -86,32 +125,30 @@ 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;
+ *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;
-#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;
+ 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;
@@ -120,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
@@ -131,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);
}
@@ -144,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());
@@ -151,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
@@ -159,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;
@@ -177,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;
}
@@ -191,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];
@@ -200,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;
}
@@ -279,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;
@@ -286,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;
@@ -295,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;
}
diff --git a/bsps/sparc/leon3/start/gettargethash.c b/bsps/sparc/leon3/start/gettargethash.c
new file mode 100644
index 0000000000..c51031dc4f
--- /dev/null
+++ b/bsps/sparc/leon3/start/gettargethash.c
@@ -0,0 +1,71 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @ingroup RTEMSBSPsSPARCLEON3
+ *
+ * @brief This source file contains the sparc/leon3 implementation of
+ * rtems_get_target_hash().
+ */
+
+/*
+ * Copyright (C) 2021, 2022 embedded brains GmbH & Co. KG
+ *
+ * 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 <rtems/config.h>
+#include <rtems/counter.h>
+#include <rtems/sysinit.h>
+#include <rtems/score/hash.h>
+
+#include <bsp/leon3.h>
+
+static Hash_Control bsp_target_hash;
+
+static void bsp_target_hash_initialize( void )
+{
+ Hash_Context context;
+ uint32_t frequency;
+
+ _Hash_Initialize( &context );
+
+ frequency = rtems_counter_frequency();
+ _Hash_Add_data( &context, &frequency, sizeof( frequency ) );
+
+ frequency = leon3_processor_local_bus_frequency();
+ _Hash_Add_data( &context, &frequency, sizeof( frequency ) );
+
+ _Hash_Finalize( &context, &bsp_target_hash );
+}
+
+const char *rtems_get_target_hash( void )
+{
+ return _Hash_Get_string( &bsp_target_hash );
+}
+
+RTEMS_SYSINIT_ITEM(
+ bsp_target_hash_initialize,
+ RTEMS_SYSINIT_TARGET_HASH,
+ RTEMS_SYSINIT_ORDER_SECOND
+);
diff --git a/bsps/sparc/leon3/start/setvec.c b/bsps/sparc/leon3/start/setvec.c
index 31461893ff..b60796f3c4 100644
--- a/bsps/sparc/leon3/start/setvec.c
+++ b/bsps/sparc/leon3/start/setvec.c
@@ -1,6 +1,6 @@
/**
* @file
- * @ingroup sparc_leon3
+ * @ingroup RTEMSBSPsSPARCLEON3
* @brief Install an interrupt vector on SPARC
*/