Commit | Line | Data |
---|---|---|
39b8d525 RB |
1 | /* |
2 | * Copyright (C) 2007 MIPS Technologies, Inc. | |
3 | * All rights reserved. | |
4 | ||
5 | * This program is free software; you can distribute it and/or modify it | |
6 | * under the terms of the GNU General Public License (Version 2) as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
12 | * for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along | |
15 | * with this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | |
17 | * | |
18 | * Arbitrary Monitor interface | |
19 | */ | |
20 | ||
21 | #include <linux/kernel.h> | |
22 | #include <linux/init.h> | |
23 | #include <linux/smp.h> | |
24 | ||
9e86786a DD |
25 | #include <asm/addrspace.h> |
26 | #include <asm/mips-boards/launch.h> | |
27 | #include <asm/mipsmtregs.h> | |
39b8d525 RB |
28 | |
29 | int amon_cpu_avail(int cpu) | |
30 | { | |
938b2b14 | 31 | struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); |
39b8d525 RB |
32 | |
33 | if (cpu < 0 || cpu >= NCPULAUNCH) { | |
34 | pr_debug("avail: cpu%d is out of range\n", cpu); | |
35 | return 0; | |
36 | } | |
37 | ||
38 | launch += cpu; | |
39 | if (!(launch->flags & LAUNCH_FREADY)) { | |
40 | pr_debug("avail: cpu%d is not ready\n", cpu); | |
41 | return 0; | |
42 | } | |
43 | if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) { | |
44 | pr_debug("avail: too late.. cpu%d is already gone\n", cpu); | |
45 | return 0; | |
46 | } | |
47 | ||
48 | return 1; | |
49 | } | |
50 | ||
51 | void amon_cpu_start(int cpu, | |
52 | unsigned long pc, unsigned long sp, | |
53 | unsigned long gp, unsigned long a0) | |
54 | { | |
55 | volatile struct cpulaunch *launch = | |
938b2b14 | 56 | (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); |
39b8d525 RB |
57 | |
58 | if (!amon_cpu_avail(cpu)) | |
59 | return; | |
60 | if (cpu == smp_processor_id()) { | |
61 | pr_debug("launch: I am cpu%d!\n", cpu); | |
62 | return; | |
63 | } | |
64 | launch += cpu; | |
65 | ||
66 | pr_debug("launch: starting cpu%d\n", cpu); | |
67 | ||
68 | launch->pc = pc; | |
69 | launch->gp = gp; | |
70 | launch->sp = sp; | |
71 | launch->a0 = a0; | |
72 | ||
2ee0a429 | 73 | smp_wmb(); /* Target must see parameters before go */ |
39b8d525 | 74 | launch->flags |= LAUNCH_FGO; |
2ee0a429 CD |
75 | smp_wmb(); /* Target must see go before we poll */ |
76 | ||
39b8d525 RB |
77 | while ((launch->flags & LAUNCH_FGONE) == 0) |
78 | ; | |
2ee0a429 | 79 | smp_rmb(); /* Target will be updating flags soon */ |
39b8d525 RB |
80 | pr_debug("launch: cpu%d gone!\n", cpu); |
81 | } |