Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsPowerPCQorIQ
0007  *
0008  * @brief BSP restart.
0009  */
0010 
0011 /*
0012  * Copyright (C) 2016, 2018 embedded brains GmbH & Co. KG
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #include <bsp.h>
0037 #include <bsp/irq.h>
0038 #include <bsp/fatal.h>
0039 #include <bsp/fdt.h>
0040 #include <bsp/linker-symbols.h>
0041 #include <bsp/qoriq.h>
0042 
0043 #include <libcpu/powerpc-utility.h>
0044 
0045 #include <string.h>
0046 
0047 static char fdt_copy[BSP_FDT_BLOB_SIZE_MAX];
0048 
0049 static RTEMS_NO_RETURN void do_restart(void *addr)
0050 {
0051   void (*restart)(uintptr_t);
0052 
0053   qoriq_reset_qman_and_bman();
0054 
0055   memcpy(fdt_copy, bsp_fdt_get(), sizeof(fdt_copy));
0056   rtems_cache_flush_multiple_data_lines(fdt_copy, sizeof(fdt_copy));
0057 
0058   restart = addr;
0059   (*restart)((uintptr_t) fdt_copy);
0060   bsp_fatal(QORIQ_FATAL_RESTART_FAILED);
0061 }
0062 
0063 #if defined(RTEMS_SMP) && !defined(QORIQ_IS_HYPERVISOR_GUEST)
0064 
0065 #include <rtems/score/smpimpl.h>
0066 #include <rtems/score/smpbarrier.h>
0067 
0068 #define RESTART_IPI_INDEX 1
0069 
0070 static SMP_barrier_Control restart_barrier = SMP_BARRIER_CONTROL_INITIALIZER;
0071 
0072 static void restart_interrupt(void *arg)
0073 {
0074   uint32_t cpu_self_index;
0075   uint32_t thread_index;
0076   rtems_interrupt_level level;
0077   SMP_barrier_State bs;
0078 
0079   rtems_interrupt_local_disable(level);
0080   (void) level;
0081 
0082   _SMP_barrier_State_initialize(&bs);
0083   _SMP_barrier_Wait(&restart_barrier, &bs, _SMP_Get_processor_maximum());
0084 
0085   cpu_self_index = rtems_scheduler_get_processor();
0086   thread_index = cpu_self_index % QORIQ_THREAD_COUNT;
0087 
0088   if (cpu_self_index == 0) {
0089     do_restart(arg);
0090   } else if (thread_index == 0) {
0091     uint32_t real_processor_index;
0092     const qoriq_start_spin_table *spin_table;
0093 
0094     real_processor_index = cpu_self_index / QORIQ_THREAD_COUNT;
0095     spin_table = qoriq_start_spin_table_addr[real_processor_index];
0096 
0097     qoriq_restart_secondary_processor(spin_table);
0098   } else {
0099     uint32_t pir_reset_value;
0100 
0101     /* Restore reset PIR value */
0102     pir_reset_value = (cpu_self_index & ~0x1U) << 2;
0103     PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR, pir_reset_value);
0104 
0105     /* Thread Enable Clear (TENC) */
0106     PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_TENC, 1U << thread_index);
0107 
0108     RTEMS_UNREACHABLE();
0109   }
0110 }
0111 
0112 static void raise_restart_interrupt(void)
0113 {
0114   qoriq.pic.ipidr[RESTART_IPI_INDEX].reg =
0115     _Processor_mask_To_uint32_t(_SMP_Get_online_processors(), 0);
0116   ppc_synchronize_data();
0117   ppc_synchronize_instructions();
0118 }
0119 
0120 static rtems_interrupt_entry restart_entry;
0121 
0122 void bsp_restart(void *addr)
0123 {
0124   rtems_status_code sc;
0125   size_t i;
0126 
0127   for (i = 0; i < RTEMS_ARRAY_SIZE(qoriq_start_spin_table_addr); ++i) {
0128     qoriq_start_spin_table *spin_table;
0129 
0130     spin_table = qoriq_start_spin_table_addr[i];
0131     memset(spin_table, 0, sizeof(*spin_table));
0132     rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table));
0133   }
0134 
0135   rtems_interrupt_entry_initialize(
0136     &restart_entry,
0137     restart_interrupt,
0138     addr,
0139     "Restart"
0140   );
0141   sc = rtems_interrupt_entry_install(
0142     QORIQ_IRQ_IPI_0 + RESTART_IPI_INDEX,
0143     RTEMS_INTERRUPT_UNIQUE,
0144     &restart_entry
0145   );
0146   if (sc != RTEMS_SUCCESSFUL) {
0147     bsp_fatal(QORIQ_FATAL_RESTART_INSTALL_INTERRUPT);
0148   }
0149 
0150   raise_restart_interrupt();
0151   bsp_fatal(QORIQ_FATAL_RESTART_INTERRUPT_FAILED);
0152 }
0153 
0154 #else /* !RTEMS_SMP || QORIQ_IS_HYPERVISOR_GUEST */
0155 
0156 void bsp_restart(void *addr)
0157 {
0158   rtems_interrupt_level level;
0159 
0160   rtems_interrupt_local_disable(level);
0161   (void) level;
0162   do_restart(addr);
0163 }
0164 
0165 #endif /* RTEMS_SMP && !QORIQ_IS_HYPERVISOR_GUEST */