diff options
Diffstat (limited to 'bsps/sparc/leon3/start/bspclean.c')
-rw-r--r-- | bsps/sparc/leon3/start/bspclean.c | 89 |
1 files changed, 62 insertions, 27 deletions
diff --git a/bsps/sparc/leon3/start/bspclean.c b/bsps/sparc/leon3/start/bspclean.c index 55bcf4474c..a49e5ffb42 100644 --- a/bsps/sparc/leon3/start/bspclean.c +++ b/bsps/sparc/leon3/start/bspclean.c @@ -35,14 +35,62 @@ #include <bsp.h> #include <bsp/bootcard.h> #include <bsp/leon3.h> +#include <rtems/score/cpuimpl.h> #include <rtems/score/smpimpl.h> +#if defined(RTEMS_SMP) +static void leon3_wait_for_power_down(irqamp *regs) +{ + uint32_t max_wait; + uint32_t cpu_self; + uint32_t cpu_count; + uint32_t halt_mask; + uint32_t i; + + cpu_count = leon3_get_cpu_count(regs); + + if (cpu_count > rtems_configuration_get_maximum_processors()) { + cpu_count = rtems_configuration_get_maximum_processors(); + } + + cpu_self = rtems_scheduler_get_processor(); + halt_mask = 0; + + for (i = 0; i < cpu_count; ++i) { + if (i != cpu_self && _SMP_Should_start_processor(i)) { + halt_mask |= UINT32_C(1) << i; + } + } + + /* + * Wait some time for secondary processors to halt. + * + * The value was chosen to get something in the magnitude of 1ms on a 200MHz + * processor. + */ + + max_wait = 1234567; + i = 0; + + while ( + (grlib_load_32(®s->mpstat) & halt_mask) != halt_mask && i < max_wait + ) { + ++i; + } +} +#endif + void bsp_fatal_extension( rtems_fatal_source source, bool always_set_to_false, rtems_fatal_code code ) { + rtems_interrupt_level level; + + 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 @@ -54,34 +102,18 @@ void bsp_fatal_extension( (code == SMP_FATAL_SHUTDOWN_RESPONSE)) { leon3_power_down_loop(); /* CPU didn't start shutdown sequence .. */ } else { - irqamp *regs = LEON3_IrqCtrl_Regs; + irqamp *regs; + + _SMP_Request_shutdown(); + regs = LEON3_IrqCtrl_Regs; +#if defined(LEON3_IRQAMP_BASE) + leon3_wait_for_power_down(regs); +#else if (regs != 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 ( - (grlib_load_32(®s->mpstat) & halt_mask) != halt_mask && - i < max_wait - ) { - ++i; - } + leon3_wait_for_power_down(regs); } +#endif } #endif @@ -92,7 +124,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 } |