~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to arch/mips/netlogic/xlr/smp.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2003-2011 NetLogic Microsystems, Inc. (NetLogic). All rights
 
3
 * reserved.
 
4
 *
 
5
 * This software is available to you under a choice of one of two
 
6
 * licenses.  You may choose to be licensed under the terms of the GNU
 
7
 * General Public License (GPL) Version 2, available from the file
 
8
 * COPYING in the main directory of this source tree, or the NetLogic
 
9
 * license below:
 
10
 *
 
11
 * Redistribution and use in source and binary forms, with or without
 
12
 * modification, are permitted provided that the following conditions
 
13
 * are met:
 
14
 *
 
15
 * 1. Redistributions of source code must retain the above copyright
 
16
 *    notice, this list of conditions and the following disclaimer.
 
17
 * 2. Redistributions in binary form must reproduce the above copyright
 
18
 *    notice, this list of conditions and the following disclaimer in
 
19
 *    the documentation and/or other materials provided with the
 
20
 *    distribution.
 
21
 *
 
22
 * THIS SOFTWARE IS PROVIDED BY NETLOGIC ``AS IS'' AND ANY EXPRESS OR
 
23
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
24
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
25
 * ARE DISCLAIMED. IN NO EVENT SHALL NETLOGIC OR CONTRIBUTORS BE LIABLE
 
26
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
27
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
28
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 
29
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
30
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 
31
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 
32
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
33
 */
 
34
 
 
35
#include <linux/kernel.h>
 
36
#include <linux/delay.h>
 
37
#include <linux/init.h>
 
38
#include <linux/smp.h>
 
39
#include <linux/irq.h>
 
40
 
 
41
#include <asm/mmu_context.h>
 
42
 
 
43
#include <asm/netlogic/interrupt.h>
 
44
#include <asm/netlogic/mips-extns.h>
 
45
 
 
46
#include <asm/netlogic/xlr/iomap.h>
 
47
#include <asm/netlogic/xlr/pic.h>
 
48
#include <asm/netlogic/xlr/xlr.h>
 
49
 
 
50
void core_send_ipi(int logical_cpu, unsigned int action)
 
51
{
 
52
        int cpu = cpu_logical_map(logical_cpu);
 
53
        u32 tid = cpu & 0x3;
 
54
        u32 pid = (cpu >> 2) & 0x07;
 
55
        u32 ipi = (tid << 16) | (pid << 20);
 
56
 
 
57
        if (action & SMP_CALL_FUNCTION)
 
58
                ipi |= IRQ_IPI_SMP_FUNCTION;
 
59
        else if (action & SMP_RESCHEDULE_YOURSELF)
 
60
                ipi |= IRQ_IPI_SMP_RESCHEDULE;
 
61
        else
 
62
                return;
 
63
 
 
64
        pic_send_ipi(ipi);
 
65
}
 
66
 
 
67
void nlm_send_ipi_single(int cpu, unsigned int action)
 
68
{
 
69
        core_send_ipi(cpu, action);
 
70
}
 
71
 
 
72
void nlm_send_ipi_mask(const struct cpumask *mask, unsigned int action)
 
73
{
 
74
        int cpu;
 
75
 
 
76
        for_each_cpu(cpu, mask) {
 
77
                core_send_ipi(cpu, action);
 
78
        }
 
79
}
 
80
 
 
81
/* IRQ_IPI_SMP_FUNCTION Handler */
 
82
void nlm_smp_function_ipi_handler(unsigned int irq, struct irq_desc *desc)
 
83
{
 
84
        smp_call_function_interrupt();
 
85
}
 
86
 
 
87
/* IRQ_IPI_SMP_RESCHEDULE  handler */
 
88
void nlm_smp_resched_ipi_handler(unsigned int irq, struct irq_desc *desc)
 
89
{
 
90
        set_need_resched();
 
91
}
 
92
 
 
93
void nlm_common_ipi_handler(int irq, struct pt_regs *regs)
 
94
{
 
95
        if (irq == IRQ_IPI_SMP_FUNCTION) {
 
96
                smp_call_function_interrupt();
 
97
        } else {
 
98
                /* Announce that we are for reschduling */
 
99
                set_need_resched();
 
100
        }
 
101
}
 
102
 
 
103
/*
 
104
 * Called before going into mips code, early cpu init
 
105
 */
 
106
void nlm_early_init_secondary(void)
 
107
{
 
108
        write_c0_ebase((uint32_t)nlm_common_ebase);
 
109
        /* TLB partition here later */
 
110
}
 
111
 
 
112
/*
 
113
 * Code to run on secondary just after probing the CPU
 
114
 */
 
115
static void __cpuinit nlm_init_secondary(void)
 
116
{
 
117
        nlm_smp_irq_init();
 
118
}
 
119
 
 
120
void nlm_smp_finish(void)
 
121
{
 
122
#ifdef notyet
 
123
        nlm_common_msgring_cpu_init();
 
124
#endif
 
125
}
 
126
 
 
127
void nlm_cpus_done(void)
 
128
{
 
129
}
 
130
 
 
131
/*
 
132
 * Boot all other cpus in the system, initialize them, and bring them into
 
133
 * the boot function
 
134
 */
 
135
int nlm_cpu_unblock[NR_CPUS];
 
136
int nlm_cpu_ready[NR_CPUS];
 
137
unsigned long nlm_next_gp;
 
138
unsigned long nlm_next_sp;
 
139
cpumask_t phys_cpu_present_map;
 
140
 
 
141
void nlm_boot_secondary(int logical_cpu, struct task_struct *idle)
 
142
{
 
143
        unsigned long gp = (unsigned long)task_thread_info(idle);
 
144
        unsigned long sp = (unsigned long)__KSTK_TOS(idle);
 
145
        int cpu = cpu_logical_map(logical_cpu);
 
146
 
 
147
        nlm_next_sp = sp;
 
148
        nlm_next_gp = gp;
 
149
 
 
150
        /* barrier */
 
151
        __sync();
 
152
        nlm_cpu_unblock[cpu] = 1;
 
153
}
 
154
 
 
155
void __init nlm_smp_setup(void)
 
156
{
 
157
        unsigned int boot_cpu;
 
158
        int num_cpus, i;
 
159
 
 
160
        boot_cpu = hard_smp_processor_id();
 
161
        cpus_clear(phys_cpu_present_map);
 
162
 
 
163
        cpu_set(boot_cpu, phys_cpu_present_map);
 
164
        __cpu_number_map[boot_cpu] = 0;
 
165
        __cpu_logical_map[0] = boot_cpu;
 
166
        cpu_set(0, cpu_possible_map);
 
167
 
 
168
        num_cpus = 1;
 
169
        for (i = 0; i < NR_CPUS; i++) {
 
170
                if (nlm_cpu_ready[i]) {
 
171
                        cpu_set(i, phys_cpu_present_map);
 
172
                        __cpu_number_map[i] = num_cpus;
 
173
                        __cpu_logical_map[num_cpus] = i;
 
174
                        cpu_set(num_cpus, cpu_possible_map);
 
175
                        ++num_cpus;
 
176
                }
 
177
        }
 
178
 
 
179
        pr_info("Phys CPU present map: %lx, possible map %lx\n",
 
180
                (unsigned long)phys_cpu_present_map.bits[0],
 
181
                (unsigned long)cpu_possible_map.bits[0]);
 
182
 
 
183
        pr_info("Detected %i Slave CPU(s)\n", num_cpus);
 
184
}
 
185
 
 
186
void nlm_prepare_cpus(unsigned int max_cpus)
 
187
{
 
188
}
 
189
 
 
190
struct plat_smp_ops nlm_smp_ops = {
 
191
        .send_ipi_single        = nlm_send_ipi_single,
 
192
        .send_ipi_mask          = nlm_send_ipi_mask,
 
193
        .init_secondary         = nlm_init_secondary,
 
194
        .smp_finish             = nlm_smp_finish,
 
195
        .cpus_done              = nlm_cpus_done,
 
196
        .boot_secondary         = nlm_boot_secondary,
 
197
        .smp_setup              = nlm_smp_setup,
 
198
        .prepare_cpus           = nlm_prepare_cpus,
 
199
};
 
200
 
 
201
unsigned long secondary_entry_point;
 
202
 
 
203
int nlm_wakeup_secondary_cpus(u32 wakeup_mask)
 
204
{
 
205
        unsigned int tid, pid, ipi, i, boot_cpu;
 
206
        void *reset_vec;
 
207
 
 
208
        secondary_entry_point = (unsigned long)prom_pre_boot_secondary_cpus;
 
209
        reset_vec = (void *)CKSEG1ADDR(0x1fc00000);
 
210
        memcpy(reset_vec, nlm_boot_smp_nmi, 0x80);
 
211
        boot_cpu = hard_smp_processor_id();
 
212
 
 
213
        for (i = 0; i < NR_CPUS; i++) {
 
214
                if (i == boot_cpu)
 
215
                        continue;
 
216
                if (wakeup_mask & (1u << i)) {
 
217
                        tid = i & 0x3;
 
218
                        pid = (i >> 2) & 0x7;
 
219
                        ipi = (tid << 16) | (pid << 20) | (1 << 8);
 
220
                        pic_send_ipi(ipi);
 
221
                }
 
222
        }
 
223
 
 
224
        return 0;
 
225
}