2008-04-28 20:14:26 +04:00
/*
2014-01-01 19:35:32 +04:00
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
2008-04-28 20:14:26 +04:00
*
2014-01-01 19:35:32 +04:00
* Copyright ( C ) 2007 MIPS Technologies , Inc . All rights reserved .
* Copyright ( C ) 2013 Imagination Technologies Ltd .
2008-04-28 20:14:26 +04:00
*
2014-01-01 19:35:32 +04:00
* Arbitrary Monitor Interface
2008-04-28 20:14:26 +04:00
*/
# include <linux/kernel.h>
# include <linux/smp.h>
2008-09-20 21:16:36 +04:00
# include <asm/addrspace.h>
# include <asm/mipsmtregs.h>
2014-01-01 19:35:32 +04:00
# include <asm/mips-boards/launch.h>
2013-10-31 00:52:10 +04:00
# include <asm/vpe.h>
2008-04-28 20:14:26 +04:00
int amon_cpu_avail ( int cpu )
{
2008-05-30 00:05:07 +04:00
struct cpulaunch * launch = ( struct cpulaunch * ) CKSEG0ADDR ( CPULAUNCH ) ;
2008-04-28 20:14:26 +04: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 ;
}
2013-10-31 00:52:10 +04:00
int amon_cpu_start ( int cpu ,
2008-04-28 20:14:26 +04:00
unsigned long pc , unsigned long sp ,
unsigned long gp , unsigned long a0 )
{
volatile struct cpulaunch * launch =
2008-05-30 00:05:07 +04:00
( struct cpulaunch * ) CKSEG0ADDR ( CPULAUNCH ) ;
2008-04-28 20:14:26 +04:00
if ( ! amon_cpu_avail ( cpu ) )
2013-10-31 00:52:10 +04:00
return - 1 ;
2008-04-28 20:14:26 +04:00
if ( cpu = = smp_processor_id ( ) ) {
pr_debug ( " launch: I am cpu%d! \n " , cpu ) ;
2013-10-31 00:52:10 +04:00
return - 1 ;
2008-04-28 20:14:26 +04:00
}
launch + = cpu ;
pr_debug ( " launch: starting cpu%d \n " , cpu ) ;
launch - > pc = pc ;
launch - > gp = gp ;
launch - > sp = sp ;
launch - > a0 = a0 ;
2013-01-22 15:59:30 +04:00
smp_wmb ( ) ; /* Target must see parameters before go */
2008-04-28 20:14:26 +04:00
launch - > flags | = LAUNCH_FGO ;
2013-01-22 15:59:30 +04:00
smp_wmb ( ) ; /* Target must see go before we poll */
2009-07-10 13:06:38 +04:00
2008-04-28 20:14:26 +04:00
while ( ( launch - > flags & LAUNCH_FGONE ) = = 0 )
;
2013-01-22 15:59:30 +04:00
smp_rmb ( ) ; /* Target will be updating flags soon */
2008-04-28 20:14:26 +04:00
pr_debug ( " launch: cpu%d gone! \n " , cpu ) ;
2013-10-31 00:52:10 +04:00
return 0 ;
}
2014-02-28 22:23:03 +04:00
# ifdef CONFIG_MIPS_VPE_LOADER_CMP
2013-10-31 00:52:10 +04:00
int vpe_run ( struct vpe * v )
{
struct vpe_notifications * n ;
if ( amon_cpu_start ( aprp_cpu_index ( ) , v - > __start , 0 , 0 , 0 ) < 0 )
return - 1 ;
list_for_each_entry ( n , & v - > notify , list )
n - > start ( VPE_MODULE_MINOR ) ;
return 0 ;
2008-04-28 20:14:26 +04:00
}
2013-10-31 00:52:10 +04:00
# endif