blob: 917df6d643ce502da2a03bea66e0e913d497b141 [file] [log] [blame]
Ralf Baechle39b8d522008-04-28 17:14:26 +01001/*
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
David Daney9e867862008-09-20 10:16:36 -070025#include <asm/addrspace.h>
26#include <asm/mips-boards/launch.h>
27#include <asm/mipsmtregs.h>
Deng-Cheng Zhu13361132013-10-30 15:52:10 -050028#include <asm/vpe.h>
Ralf Baechle39b8d522008-04-28 17:14:26 +010029
30int amon_cpu_avail(int cpu)
31{
Thomas Bogendoerfer938b2b12008-05-29 22:05:07 +020032 struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
Ralf Baechle39b8d522008-04-28 17:14:26 +010033
34 if (cpu < 0 || cpu >= NCPULAUNCH) {
35 pr_debug("avail: cpu%d is out of range\n", cpu);
36 return 0;
37 }
38
39 launch += cpu;
40 if (!(launch->flags & LAUNCH_FREADY)) {
41 pr_debug("avail: cpu%d is not ready\n", cpu);
42 return 0;
43 }
44 if (launch->flags & (LAUNCH_FGO|LAUNCH_FGONE)) {
45 pr_debug("avail: too late.. cpu%d is already gone\n", cpu);
46 return 0;
47 }
48
49 return 1;
50}
51
Deng-Cheng Zhu13361132013-10-30 15:52:10 -050052int amon_cpu_start(int cpu,
Ralf Baechle39b8d522008-04-28 17:14:26 +010053 unsigned long pc, unsigned long sp,
54 unsigned long gp, unsigned long a0)
55{
56 volatile struct cpulaunch *launch =
Thomas Bogendoerfer938b2b12008-05-29 22:05:07 +020057 (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH);
Ralf Baechle39b8d522008-04-28 17:14:26 +010058
59 if (!amon_cpu_avail(cpu))
Deng-Cheng Zhu13361132013-10-30 15:52:10 -050060 return -1;
Ralf Baechle39b8d522008-04-28 17:14:26 +010061 if (cpu == smp_processor_id()) {
62 pr_debug("launch: I am cpu%d!\n", cpu);
Deng-Cheng Zhu13361132013-10-30 15:52:10 -050063 return -1;
Ralf Baechle39b8d522008-04-28 17:14:26 +010064 }
65 launch += cpu;
66
67 pr_debug("launch: starting cpu%d\n", cpu);
68
69 launch->pc = pc;
70 launch->gp = gp;
71 launch->sp = sp;
72 launch->a0 = a0;
73
Ralf Baechle70342282013-01-22 12:59:30 +010074 smp_wmb(); /* Target must see parameters before go */
Ralf Baechle39b8d522008-04-28 17:14:26 +010075 launch->flags |= LAUNCH_FGO;
Ralf Baechle70342282013-01-22 12:59:30 +010076 smp_wmb(); /* Target must see go before we poll */
Chris Dearman2ee0a422009-07-10 02:06:38 -070077
Ralf Baechle39b8d522008-04-28 17:14:26 +010078 while ((launch->flags & LAUNCH_FGONE) == 0)
79 ;
Ralf Baechle70342282013-01-22 12:59:30 +010080 smp_rmb(); /* Target will be updating flags soon */
Ralf Baechle39b8d522008-04-28 17:14:26 +010081 pr_debug("launch: cpu%d gone!\n", cpu);
Deng-Cheng Zhu13361132013-10-30 15:52:10 -050082
83 return 0;
Ralf Baechle39b8d522008-04-28 17:14:26 +010084}
Deng-Cheng Zhu13361132013-10-30 15:52:10 -050085
86#ifdef CONFIG_MIPS_VPE_LOADER
87int vpe_run(struct vpe *v)
88{
89 struct vpe_notifications *n;
90
91 if (amon_cpu_start(aprp_cpu_index(), v->__start, 0, 0, 0) < 0)
92 return -1;
93
94 list_for_each_entry(n, &v->notify, list)
95 n->start(VPE_MODULE_MINOR);
96
97 return 0;
98}
99#endif