OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [mips/] [pmc-sierra/] [yosemite/] [smp.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
#include <linux/linkage.h>
2
#include <linux/sched.h>
3
 
4
#include <asm/pmon.h>
5
#include <asm/titan_dep.h>
6
#include <asm/time.h>
7
 
8
#define LAUNCHSTACK_SIZE 256
9
 
10
static __initdata DEFINE_SPINLOCK(launch_lock);
11
 
12
static unsigned long secondary_sp __initdata;
13
static unsigned long secondary_gp __initdata;
14
 
15
static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata
16
        __attribute__((aligned(2 * sizeof(long))));
17
 
18
static void __init prom_smp_bootstrap(void)
19
{
20
        local_irq_disable();
21
 
22
        while (spin_is_locked(&launch_lock));
23
 
24
        __asm__ __volatile__(
25
        "       move    $sp, %0         \n"
26
        "       move    $gp, %1         \n"
27
        "       j       smp_bootstrap   \n"
28
        :
29
        : "r" (secondary_sp), "r" (secondary_gp));
30
}
31
 
32
/*
33
 * PMON is a fragile beast.  It'll blow up once the mappings it's littering
34
 * right into the middle of KSEG3 are blown away so we have to grab the slave
35
 * core early and keep it in a waiting loop.
36
 */
37
void __init prom_grab_secondary(void)
38
{
39
        spin_lock(&launch_lock);
40
 
41
        pmon_cpustart(1, &prom_smp_bootstrap,
42
                      launchstack + LAUNCHSTACK_SIZE, 0);
43
}
44
 
45
/*
46
 * Detect available CPUs, populate phys_cpu_present_map before smp_init
47
 *
48
 * We don't want to start the secondary CPU yet nor do we have a nice probing
49
 * feature in PMON so we just assume presence of the secondary core.
50
 */
51
void __init plat_smp_setup(void)
52
{
53
        int i;
54
 
55
        cpus_clear(phys_cpu_present_map);
56
 
57
        for (i = 0; i < 2; i++) {
58
                cpu_set(i, phys_cpu_present_map);
59
                __cpu_number_map[i]     = i;
60
                __cpu_logical_map[i]    = i;
61
        }
62
}
63
 
64
void __init plat_prepare_cpus(unsigned int max_cpus)
65
{
66
        /*
67
         * Be paranoid.  Enable the IPI only if we're really about to go SMP.
68
         */
69
        if (cpus_weight(cpu_possible_map))
70
                set_c0_status(STATUSF_IP5);
71
}
72
 
73
/*
74
 * Firmware CPU startup hook
75
 * Complicated by PMON's weird interface which tries to minimic the UNIX fork.
76
 * It launches the next * available CPU and copies some information on the
77
 * stack so the first thing we do is throw away that stuff and load useful
78
 * values into the registers ...
79
 */
80
void __cpuinit prom_boot_secondary(int cpu, struct task_struct *idle)
81
{
82
        unsigned long gp = (unsigned long) task_thread_info(idle);
83
        unsigned long sp = __KSTK_TOS(idle);
84
 
85
        secondary_sp = sp;
86
        secondary_gp = gp;
87
 
88
        spin_unlock(&launch_lock);
89
}
90
 
91
/* Hook for after all CPUs are online */
92
void prom_cpus_done(void)
93
{
94
}
95
 
96
/*
97
 *  After we've done initial boot, this function is called to allow the
98
 *  board code to clean up state, if needed
99
 */
100
void __cpuinit prom_init_secondary(void)
101
{
102
        set_c0_status(ST0_CO | ST0_IE | ST0_IM);
103
}
104
 
105
void __cpuinit prom_smp_finish(void)
106
{
107
}
108
 
109
void titan_mailbox_irq(void)
110
{
111
        int cpu = smp_processor_id();
112
        unsigned long status;
113
 
114
        switch (cpu) {
115
        case 0:
116
                status = OCD_READ(RM9000x2_OCD_INTP0STATUS3);
117
                OCD_WRITE(RM9000x2_OCD_INTP0CLEAR3, status);
118
 
119
                if (status & 0x2)
120
                        smp_call_function_interrupt();
121
                break;
122
 
123
        case 1:
124
                status = OCD_READ(RM9000x2_OCD_INTP1STATUS3);
125
                OCD_WRITE(RM9000x2_OCD_INTP1CLEAR3, status);
126
 
127
                if (status & 0x2)
128
                        smp_call_function_interrupt();
129
                break;
130
        }
131
}
132
 
133
/*
134
 * Send inter-processor interrupt
135
 */
136
void core_send_ipi(int cpu, unsigned int action)
137
{
138
        /*
139
         * Generate an INTMSG so that it can be sent over to the
140
         * destination CPU. The INTMSG will put the STATUS bits
141
         * based on the action desired. An alternative strategy
142
         * is to write to the Interrupt Set register, read the
143
         * Interrupt Status register and clear the Interrupt
144
         * Clear register. The latter is preffered.
145
         */
146
        switch (action) {
147
        case SMP_RESCHEDULE_YOURSELF:
148
                if (cpu == 1)
149
                        OCD_WRITE(RM9000x2_OCD_INTP1SET3, 4);
150
                else
151
                        OCD_WRITE(RM9000x2_OCD_INTP0SET3, 4);
152
                break;
153
 
154
        case SMP_CALL_FUNCTION:
155
                if (cpu == 1)
156
                        OCD_WRITE(RM9000x2_OCD_INTP1SET3, 2);
157
                else
158
                        OCD_WRITE(RM9000x2_OCD_INTP0SET3, 2);
159
                break;
160
        }
161
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.