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