source: rtems/c/src/lib/libbsp/powerpc/qoriq/startup/smp.c @ ca63ae2

4.115
Last change on this file since ca63ae2 was ca63ae2, checked in by Sebastian Huber <sebastian.huber@…>, on 06/13/13 at 13:41:21

smp: Add and use _CPU_SMP_Send_interrupt()

Delete bsp_smp_interrupt_cpu().

  • Property mode set to 100644
File size: 3.9 KB
Line 
1/*
2 * Copyright (c) 2013 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.com/license/LICENSE.
13 */
14
15#include <assert.h>
16
17#include <rtems/bspsmp.h>
18
19#include <libcpu/powerpc-utility.h>
20
21#include <bsp.h>
22#include <bsp/mmu.h>
23#include <bsp/qoriq.h>
24#include <bsp/vectors.h>
25#include <bsp/irq-generic.h>
26#include <bsp/linker-symbols.h>
27
28LINKER_SYMBOL(bsp_exc_vector_base);
29
30void _start_core_1(void);
31
32#define CORE_COUNT 2
33
34#define ONE_CORE(core) (1 << (core))
35
36#define ALL_CORES ((1 << CORE_COUNT) - 1)
37
38#define IPI_INDEX 0
39
40#define TLB_BEGIN 8
41
42#define TLB_END 16
43
44#define TLB_COUNT (TLB_END - TLB_BEGIN)
45
46/*
47 * These values can be obtained with the debugger or a look into the
48 * U-Boot sources (arch/powerpc/cpu/mpc85xx/release.S).
49 */
50#if 1
51  #define BOOT_BEGIN 0x1fff0000
52  #define BOOT_LAST  0x1fffffff
53  #define SPIN_TABLE (BOOT_BEGIN + 0xf2a0)
54#else
55  #define BOOT_BEGIN 0x3fff0000
56  #define BOOT_LAST  0x3fffffff
57  #define SPIN_TABLE (BOOT_BEGIN + 0xf240)
58#endif
59
60#define TLB_BEGIN 8
61
62#define TLB_END 16
63
64#define TLB_COUNT (TLB_END - TLB_BEGIN)
65
66typedef struct {
67  uint32_t addr_upper;
68  uint32_t addr_lower;
69  uint32_t r3_upper;
70  uint32_t r3_lower;
71  uint32_t reserved;
72  uint32_t pir;
73  uint32_t r6_upper;
74  uint32_t r6_lower;
75} uboot_spin_table;
76
77static uint32_t initial_core_1_stack[4096 / sizeof(uint32_t)];
78
79static void mmu_config_undo(void)
80{
81  int i = 0;
82
83  for (i = TLB_BEGIN; i < TLB_END; ++i) {
84    qoriq_tlb1_invalidate(i);
85  }
86}
87
88static void release_core_1(void)
89{
90  uboot_spin_table *spin_table = (uboot_spin_table *) SPIN_TABLE;
91  qoriq_mmu_context mmu_context;
92
93  qoriq_mmu_context_init(&mmu_context);
94  qoriq_mmu_add(&mmu_context, BOOT_BEGIN, BOOT_LAST, 0, 0, FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SW);
95  qoriq_mmu_partition(&mmu_context, TLB_COUNT);
96  qoriq_mmu_write_to_tlb1(&mmu_context, TLB_BEGIN);
97
98  spin_table->pir = 1;
99  spin_table->r3_lower = (uint32_t) _Per_CPU_Information[1].interrupt_stack_high;
100  spin_table->addr_upper = 0;
101  rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table));
102  ppc_synchronize_data();
103  spin_table->addr_lower = (uint32_t) _start_core_1;
104  rtems_cache_flush_multiple_data_lines(spin_table, sizeof(*spin_table));
105
106  mmu_config_undo();
107}
108
109void qoriq_secondary_cpu_initialize(void)
110{
111  /* Disable decrementer */
112  PPC_CLEAR_SPECIAL_PURPOSE_REGISTER_BITS(BOOKE_TCR, BOOKE_TCR_DIE);
113
114  /* Initialize exception handler */
115  ppc_exc_initialize_with_vector_base(
116    PPC_INTERRUPT_DISABLE_MASK_DEFAULT,
117    (uintptr_t) _Per_CPU_Information[1].interrupt_stack_low,
118    rtems_configuration_get_interrupt_stack_size(),
119    bsp_exc_vector_base
120  );
121
122  /* Now it is possible to make the code execute only */
123  qoriq_mmu_change_perm(
124    FSL_EIS_MAS3_SR | FSL_EIS_MAS3_SX,
125    FSL_EIS_MAS3_SX,
126    FSL_EIS_MAS3_SR
127  );
128
129  /* Initialize interrupt support */
130  bsp_interrupt_facility_initialize();
131
132  bsp_interrupt_vector_enable(QORIQ_IRQ_IPI_0);
133
134  rtems_smp_secondary_cpu_initialize();
135}
136
137static void ipi_handler(void *arg)
138{
139  rtems_smp_process_interrupt();
140}
141
142uint32_t bsp_smp_initialize(uint32_t configured_cpu_count)
143{
144  rtems_status_code sc;
145  uint32_t cores = configured_cpu_count < CORE_COUNT ?
146    configured_cpu_count : CORE_COUNT;
147
148  sc = rtems_interrupt_handler_install(
149    QORIQ_IRQ_IPI_0,
150    "IPI",
151    RTEMS_INTERRUPT_UNIQUE,
152    ipi_handler,
153    NULL
154  );
155  assert(sc == RTEMS_SUCCESSFUL);
156
157  if (cores > 1) {
158    release_core_1();
159  }
160
161  return cores;
162}
163
164void bsp_smp_broadcast_interrupt(void)
165{
166  uint32_t self = ppc_processor_id();
167  qoriq.pic.per_cpu [self].ipidr [IPI_INDEX].reg = ALL_CORES;
168}
169
170void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
171{
172  uint32_t self = ppc_processor_id();
173  qoriq.pic.per_cpu [self].ipidr [IPI_INDEX].reg =
174    ONE_CORE(target_processor_index);
175}
Note: See TracBrowser for help on using the repository browser.