source: rtems/c/src/lib/libbsp/powerpc/qoriq/startup/bsprestart.c @ d8f4689

5
Last change on this file since d8f4689 was d8f4689, checked in by Sebastian Huber <sebastian.huber@…>, on 04/22/16 at 12:03:43

bsp/qoriq: Add bsp_restart()

  • Property mode set to 100644
File size: 3.2 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup QorIQ
5 *
6 * @brief BSP restart.
7 */
8
9/*
10 * Copyright (c) 2016 embedded brains GmbH.  All rights reserved.
11 *
12 *  embedded brains GmbH
13 *  Dornierstr. 4
14 *  82178 Puchheim
15 *  Germany
16 *  <rtems@embedded-brains.de>
17 *
18 * The license and distribution terms for this file may be
19 * found in the file LICENSE in this distribution or at
20 * http://www.rtems.org/license/LICENSE.
21 */
22
23#include <bsp.h>
24#include <bsp/irq.h>
25#include <bsp/fatal.h>
26#include <bsp/fdt.h>
27#include <bsp/linker-symbols.h>
28#include <bsp/qoriq.h>
29
30#include <libcpu/powerpc-utility.h>
31
32static RTEMS_NO_RETURN void do_restart(void *addr)
33{
34  void (*restart)(uintptr_t);
35  uintptr_t fdt;
36
37  restart = addr;
38
39  fdt = (uintptr_t) bsp_fdt_get();
40#ifdef BSP_FDT_BLOB_READ_ONLY
41  fdt -= (uintptr_t) bsp_section_rodata_begin;
42  fdt += (uintptr_t) bsp_section_rodata_load_begin;
43#endif
44
45  (*restart)(fdt);
46  bsp_fatal(QORIQ_FATAL_RESTART_FAILED);
47}
48
49#ifdef RTEMS_SMP
50
51#include <rtems/score/smpimpl.h>
52#include <rtems/score/smpbarrier.h>
53
54#define RESTART_IPI_INDEX 1
55
56static SMP_barrier_Control restart_barrier = SMP_BARRIER_CONTROL_INITIALIZER;
57
58static void restart_interrupt(void *arg)
59{
60  uint32_t cpu_self_index;
61  uint32_t thread_index;
62  rtems_interrupt_level level;
63  SMP_barrier_State bs;
64
65  rtems_interrupt_local_disable(level);
66  (void) level;
67
68  _SMP_barrier_State_initialize(&bs);
69  _SMP_barrier_Wait(&restart_barrier, &bs, _SMP_Processor_count);
70
71  cpu_self_index = rtems_get_current_processor();
72  thread_index = cpu_self_index % QORIQ_THREAD_COUNT;
73
74  if (cpu_self_index == 0) {
75    do_restart(arg);
76  } else if (thread_index == 0) {
77    uint32_t real_processor_index;
78    const qoriq_start_spin_table *spin_table;
79
80    real_processor_index = cpu_self_index / QORIQ_THREAD_COUNT;
81    spin_table = qoriq_start_spin_table_addr[real_processor_index];
82
83    qoriq_restart_secondary_processor(spin_table);
84  } else {
85    uint32_t pir_reset_value;
86
87    /* Restore reset PIR value */
88    pir_reset_value = (cpu_self_index & ~0x1U) << 2;
89    PPC_SET_SPECIAL_PURPOSE_REGISTER(BOOKE_PIR, pir_reset_value);
90
91    /* Thread Enable Clear (TENC) */
92    PPC_SET_SPECIAL_PURPOSE_REGISTER(FSL_EIS_TENC, 1U << thread_index);
93
94    RTEMS_UNREACHABLE();
95  }
96}
97
98static void raise_restart_interrupt(void)
99{
100  qoriq.pic.ipidr[RESTART_IPI_INDEX].reg = _SMP_Online_processors[0];
101  ppc_synchronize_data();
102  ppc_synchronize_instructions();
103}
104
105void bsp_restart(void *addr)
106{
107  rtems_status_code sc;
108  size_t i;
109
110  for (i = 0; i < RTEMS_ARRAY_SIZE(qoriq_start_spin_table_addr); ++i) {
111    qoriq_start_spin_table *spin_table;
112
113    spin_table = qoriq_start_spin_table_addr[i];
114    memset(spin_table, 0, sizeof(*spin_table));
115    rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table));
116  }
117
118  sc = rtems_interrupt_handler_install(
119    QORIQ_IRQ_IPI_0 + RESTART_IPI_INDEX,
120    "Restart",
121    RTEMS_INTERRUPT_UNIQUE,
122    restart_interrupt,
123    addr
124  );
125  if (sc != RTEMS_SUCCESSFUL) {
126    bsp_fatal(QORIQ_FATAL_RESTART_INSTALL_INTERRUPT);
127  }
128
129  raise_restart_interrupt();
130  bsp_fatal(QORIQ_FATAL_RESTART_INTERRUPT_FAILED);
131}
132
133#else /* RTEMS_SMP */
134
135void bsp_restart(void *addr)
136{
137  rtems_interrupt_level level;
138
139  rtems_interrupt_local_disable(level);
140  (void) level;
141  do_restart(addr);
142}
143
144#endif /* !RTEMS_SMP */
Note: See TracBrowser for help on using the repository browser.