2008-04-28 17:14:26 +01:00
/*
* Copyright ( C ) 2007 MIPS Technologies , Inc .
* All rights reserved .
* This program is free software ; you can distribute it and / or modify it
* under the terms of the GNU General Public License ( Version 2 ) as
* published by the Free Software Foundation .
*
* This program is distributed in the hope it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* for more details .
*
* You should have received a copy of the GNU General Public License along
* with this program ; if not , write to the Free Software Foundation , Inc . ,
* 59 Temple Place - Suite 330 , Boston MA 02111 - 1307 , USA .
*
* Arbitrary Monitor interface
*/
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/smp.h>
2008-09-20 10:16:36 -07:00
# include <asm/addrspace.h>
# include <asm/mips-boards/launch.h>
# include <asm/mipsmtregs.h>
2008-04-28 17:14:26 +01:00
int amon_cpu_avail ( int cpu )
{
2008-05-29 22:05:07 +02:00
struct cpulaunch * launch = ( struct cpulaunch * ) CKSEG0ADDR ( CPULAUNCH ) ;
2008-04-28 17:14:26 +01:00
if ( cpu < 0 | | cpu > = NCPULAUNCH ) {
pr_debug ( " avail: cpu%d is out of range \n " , cpu ) ;
return 0 ;
}
launch + = cpu ;
if ( ! ( launch - > flags & LAUNCH_FREADY ) ) {
pr_debug ( " avail: cpu%d is not ready \n " , cpu ) ;
return 0 ;
}
if ( launch - > flags & ( LAUNCH_FGO | LAUNCH_FGONE ) ) {
pr_debug ( " avail: too late.. cpu%d is already gone \n " , cpu ) ;
return 0 ;
}
return 1 ;
}
void amon_cpu_start ( int cpu ,
unsigned long pc , unsigned long sp ,
unsigned long gp , unsigned long a0 )
{
volatile struct cpulaunch * launch =
2008-05-29 22:05:07 +02:00
( struct cpulaunch * ) CKSEG0ADDR ( CPULAUNCH ) ;
2008-04-28 17:14:26 +01:00
if ( ! amon_cpu_avail ( cpu ) )
return ;
if ( cpu = = smp_processor_id ( ) ) {
pr_debug ( " launch: I am cpu%d! \n " , cpu ) ;
return ;
}
launch + = cpu ;
pr_debug ( " launch: starting cpu%d \n " , cpu ) ;
launch - > pc = pc ;
launch - > gp = gp ;
launch - > sp = sp ;
launch - > a0 = a0 ;
2009-07-10 02:06:38 -07:00
smp_wmb ( ) ; /* Target must see parameters before go */
2008-04-28 17:14:26 +01:00
launch - > flags | = LAUNCH_FGO ;
2009-07-10 02:06:38 -07:00
smp_wmb ( ) ; /* Target must see go before we poll */
2008-04-28 17:14:26 +01:00
while ( ( launch - > flags & LAUNCH_FGONE ) = = 0 )
;
2009-07-10 02:06:38 -07:00
smp_rmb ( ) ; /* Target will be updating flags soon */
2008-04-28 17:14:26 +01:00
pr_debug ( " launch: cpu%d gone! \n " , cpu ) ;
}