2014-01-15 14:31:50 +04:00
/*
* Copyright ( C ) 2013 Imagination Technologies
* Author : Paul Burton < paul . burton @ imgtec . com >
*
* Based on smp - cmp . c :
* Copyright ( C ) 2007 MIPS Technologies , Inc .
* Author : Chris Dearman ( chris @ mips . com )
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*/
2014-10-20 23:03:53 +04:00
# include <linux/irqchip/mips-gic.h>
2014-01-15 14:31:50 +04:00
# include <linux/printk.h>
2014-04-14 19:25:29 +04:00
# include <asm/mips-cpc.h>
2014-01-15 14:31:50 +04:00
# include <asm/smp-ops.h>
void gic_send_ipi_single ( int cpu , unsigned int action )
{
unsigned long flags ;
unsigned int intr ;
2014-04-14 19:25:29 +04:00
unsigned int core = cpu_data [ cpu ] . core ;
2014-01-15 14:31:50 +04:00
pr_debug ( " CPU%d: %s cpu %d action %u status %08x \n " ,
smp_processor_id ( ) , __func__ , cpu , action , read_c0_status ( ) ) ;
local_irq_save ( flags ) ;
switch ( action ) {
case SMP_CALL_FUNCTION :
intr = plat_ipi_call_int_xlate ( cpu ) ;
break ;
case SMP_RESCHEDULE_YOURSELF :
intr = plat_ipi_resched_int_xlate ( cpu ) ;
break ;
default :
BUG ( ) ;
}
gic_send_ipi ( intr ) ;
2014-04-14 19:25:29 +04:00
if ( mips_cpc_present ( ) & & ( core ! = current_cpu_data . core ) ) {
while ( ! cpumask_test_cpu ( cpu , & cpu_coherent_mask ) ) {
2015-09-22 21:12:17 +03:00
mips_cm_lock_other ( core , 0 ) ;
2014-04-14 19:25:29 +04:00
mips_cpc_lock_other ( core ) ;
write_cpc_co_cmd ( CPC_Cx_CMD_PWRUP ) ;
mips_cpc_unlock_other ( ) ;
2015-09-22 21:12:17 +03:00
mips_cm_unlock_other ( ) ;
2014-04-14 19:25:29 +04:00
}
}
2014-01-15 14:31:50 +04:00
local_irq_restore ( flags ) ;
}
void gic_send_ipi_mask ( const struct cpumask * mask , unsigned int action )
{
unsigned int i ;
for_each_cpu ( i , mask )
gic_send_ipi_single ( i , action ) ;
}