source: rtems/c/src/lib/libbsp/sparc/leon3/smp/smp_leon3.c @ 3d77001

4.115
Last change on this file since 3d77001 was 3d77001, checked in by Sebastian Huber <sebastian.huber@…>, on 02/05/14 at 14:15:51

bsp/leon3: Fix SMP initialization

Avoid usage of the same stack area by multiple secondary processors at
the same time.

Avoid magic delay loops.

  • Property mode set to 100644
File size: 2.9 KB
Line 
1/**
2 * @file
3 * @ingroup sparc_leon3
4 * @brief 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 <bsp.h>
17#include <leon.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
36static rtems_isr bsp_ap_ipi_isr(
37  rtems_vector_number vector
38)
39{
40  rtems_smp_process_interrupt();
41}
42
43void leon3_secondary_cpu_initialize(uint32_t cpu)
44{
45  sparc_leon3_set_cctrl( 0x80000F );
46  LEON_Unmask_interrupt(LEON3_MP_IRQ);
47  LEON3_IrqCtrl_Regs->mask[cpu] |= 1 << LEON3_MP_IRQ;
48
49  rtems_smp_secondary_cpu_initialize();
50}
51
52static void bsp_smp_delay( int );
53
54uint32_t bsp_smp_initialize( uint32_t configured_cpu_count )
55{
56  uint32_t cpu;
57  uint32_t found_cpus = 0;
58
59  sparc_leon3_set_cctrl( 0x80000F );
60  found_cpus =
61    ((LEON3_IrqCtrl_Regs->mpstat >> LEON3_IRQMPSTATUS_CPUNR) & 0xf)  + 1;
62
63  #if defined(RTEMS_DEBUG)
64    printk( "Found %d CPUs\n", found_cpus );
65
66    if ( found_cpus > configured_cpu_count ) {
67      printk(
68        "%d CPUs IS MORE THAN CONFIGURED -- ONLY USING %d\n",
69        found_cpus,
70        configured_cpu_count
71      );
72      found_cpus = configured_cpu_count;
73    }
74  #endif
75
76  if ( found_cpus > 1 ) {
77    LEON_Unmask_interrupt(LEON3_MP_IRQ);
78    set_vector(bsp_ap_ipi_isr, LEON_TRAP_TYPE(LEON3_MP_IRQ), 1);
79  }
80
81  for ( cpu = 1 ; cpu < found_cpus ; ++cpu ) {
82    #if defined(RTEMS_DEBUG)
83      printk( "Waking CPU %d\n", cpu );
84    #endif
85
86    LEON3_IrqCtrl_Regs->mpstat = 1 << cpu;
87  }
88
89  return found_cpus;
90}
91
92void _CPU_SMP_Send_interrupt(uint32_t target_processor_index)
93{
94  /* send interrupt to destination CPU */
95  LEON3_IrqCtrl_Regs->force[target_processor_index] = 1 << LEON3_MP_IRQ;
96}
97
98void bsp_smp_broadcast_interrupt(void)
99{
100  uint32_t dest_cpu;
101  uint32_t cpu;
102  uint32_t max_cpus;
103
104  cpu = rtems_smp_get_current_processor();
105  max_cpus = rtems_smp_get_processor_count();
106
107  for ( dest_cpu=0 ; dest_cpu < max_cpus ; dest_cpu++ ) {
108    if ( cpu == dest_cpu )
109      continue;
110    _CPU_SMP_Send_interrupt( dest_cpu );
111    /* this is likely needed due to the ISR code not being SMP aware yet */
112    bsp_smp_delay( 100000 );
113  }
114}
115
116static __inline__ void __delay(unsigned long loops)
117{
118   __asm__ __volatile__("cmp %0, 0\n\t"
119     "1: bne 1b\n\t"
120     "subcc %0, 1, %0\n" :
121     "=&r" (loops) :
122     "0" (loops) :
123     "cc"
124  );
125}
126
127/*
128 *  Kill time without depending on the timer being present or programmed.
129 *
130 *  This is not very sophisticated.
131 */
132void bsp_smp_delay( int max )
133{
134   __delay( max );
135}
Note: See TracBrowser for help on using the repository browser.