source: rtems/c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c @ 42eee51

4.115
Last change on this file since 42eee51 was baf8f4d, checked in by Sebastian Huber <sebastian.huber@…>, on 05/14/13 at 08:12:52

smp: Simplify main CPU initialization

Call _SMP_Handler_initialize() later and move bsp_smp_initialize() into
_SMP_Handler_initialize(). Change bsp_smp_initialize() prototype to
match integer types of calling context.

  • Property mode set to 100644
File size: 3.7 KB
Line 
1/**
2 *  @file
3 *
4 *  LEON3 SMP BSP Support
5 */
6
7/*
8 *  COPYRIGHT (c) 1989-2011.
9 *  On-Line Applications Research Corporation (OAR).
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.rtems.com/license/LICENSE.
14 */
15
16#include <rtems.h>
17#include <bsp.h>
18#include <rtems/bspIo.h>
19#include <rtems/bspsmp.h>
20#include <stdlib.h>
21
22#define RTEMS_DEBUG
23
24static inline void sparc_leon3_set_cctrl( unsigned int val )
25{
26  __asm__ volatile( "sta %0, [%%g0] 2" : : "r" (val) );
27}
28
29static inline unsigned int sparc_leon3_get_cctrl( void )
30{
31  unsigned int v = 0;
32  __asm__ volatile( "lda [%%g0] 2, %0" : "=r" (v) : "0" (v) );
33  return v;
34}
35
36rtems_isr bsp_ap_ipi_isr(
37  rtems_vector_number vector
38)
39{
40  LEON_Clear_interrupt(LEON3_MP_IRQ);
41  rtems_smp_process_interrupt();
42}
43
44void bsp_smp_secondary_cpu_initialize(int cpu)
45{
46  sparc_leon3_set_cctrl( 0x80000F );
47  LEON_Unmask_interrupt(LEON3_MP_IRQ);
48  LEON3_IrqCtrl_Regs->mask[cpu] |= 1 << LEON3_MP_IRQ;
49}
50
51/*
52 *  Used to pass information to start.S when bringing secondary CPUs
53 *  out of reset.
54 */
55void *bsp_ap_stack;
56void *bsp_ap_entry;
57
58static void bsp_smp_delay( int );
59
60uint32_t bsp_smp_initialize( uint32_t configured_cpu_count )
61{
62  uint32_t cpu;
63  uint32_t found_cpus = 0;
64
65  sparc_leon3_set_cctrl( 0x80000F );
66  found_cpus =
67    ((LEON3_IrqCtrl_Regs->mpstat >> LEON3_IRQMPSTATUS_CPUNR) & 0xf)  + 1;
68  #if defined(RTEMS_DEBUG)
69    printk( "Found %d CPUs\n", found_cpus );
70  #endif
71
72  if ( found_cpus > configured_cpu_count ) {
73    printk(
74      "%d CPUs IS MORE THAN CONFIGURED -- ONLY USING %d\n",
75      found_cpus,
76      configured_cpu_count
77    );
78    found_cpus = configured_cpu_count;
79  }
80
81  if ( found_cpus == 1 )
82    return 1;
83
84  for ( cpu=1 ; cpu < found_cpus ; cpu++ ) {
85   
86    #if defined(RTEMS_DEBUG)
87      printk( "Waking CPU %d\n", cpu );
88    #endif
89
90    bsp_ap_stack = _Per_CPU_Information[cpu].interrupt_stack_high -
91                      CPU_MINIMUM_STACK_FRAME_SIZE;
92    bsp_ap_entry = rtems_smp_secondary_cpu_initialize;
93
94    LEON3_IrqCtrl_Regs->mpstat = 1 << cpu;
95    bsp_smp_delay( 1000000 );
96    #if defined(RTEMS_DEBUG)
97      printk(
98        "CPU %d is %s\n",
99        cpu,
100        ((_Per_CPU_Information[cpu].state == RTEMS_BSP_SMP_CPU_INITIALIZED) ?
101           "online" : "offline")
102      );
103    #endif
104  }
105
106  if ( found_cpus > 1 ) {
107    LEON_Unmask_interrupt(LEON3_MP_IRQ);
108    set_vector(bsp_ap_ipi_isr, LEON_TRAP_TYPE(LEON3_MP_IRQ), 1);
109  }
110  return found_cpus;
111}
112
113void bsp_smp_interrupt_cpu(
114  int cpu
115)
116{
117  /* send interrupt to destination CPU */
118  LEON3_IrqCtrl_Regs->force[cpu] = 1 << LEON3_MP_IRQ;
119}
120
121void bsp_smp_broadcast_interrupt(void)
122{
123  int dest_cpu;
124  int cpu;
125  int max_cpus;
126
127  cpu = bsp_smp_processor_id();
128  max_cpus = rtems_smp_get_number_of_processors();
129
130  for ( dest_cpu=0 ; dest_cpu < max_cpus ; dest_cpu++ ) {
131    if ( cpu == dest_cpu )
132      continue;
133    bsp_smp_interrupt_cpu( dest_cpu );
134    /* this is likely needed due to the ISR code not being SMP aware yet */
135    bsp_smp_delay( 100000 );
136  }
137}
138
139extern __inline__ void __delay(unsigned long loops)
140{
141   __asm__ __volatile__("cmp %0, 0\n\t"
142     "1: bne 1b\n\t"
143     "subcc %0, 1, %0\n" :
144     "=&r" (loops) :
145     "0" (loops) :
146     "cc"
147  );
148}
149
150/*
151 *  Kill time without depending on the timer being present or programmed.
152 *
153 *  This is not very sophisticated.
154 */
155void bsp_smp_delay( int max )
156{
157   __delay( max );
158}
159
160void bsp_smp_wait_for(
161  volatile unsigned int *address,
162  unsigned int           desired,
163  int                    maximum_usecs
164)
165{
166  int iterations;
167  volatile unsigned int *p = address;
168
169  for (iterations=0 ;  iterations < maximum_usecs ; iterations++ ) {
170    if ( *p == desired )
171      break;
172    bsp_smp_delay( 5000 );
173  }
174}
175
176
Note: See TracBrowser for help on using the repository browser.