2005-04-16 15:20:36 -07:00
/*
* Smp support for CHRP machines .
*
* Written by Cort Dougan ( cort @ cs . nmt . edu ) borrowing a great
* deal of code from the sparc and intel versions .
*
* Copyright ( C ) 1999 Cort Dougan < cort @ cs . nmt . edu >
*
*/
# include <linux/config.h>
# include <linux/kernel.h>
# include <linux/sched.h>
# include <linux/smp.h>
# include <linux/smp_lock.h>
# include <linux/interrupt.h>
# include <linux/kernel_stat.h>
# include <linux/delay.h>
# include <linux/init.h>
# include <linux/spinlock.h>
# include <asm/ptrace.h>
# include <asm/atomic.h>
# include <asm/irq.h>
# include <asm/page.h>
# include <asm/pgtable.h>
# include <asm/sections.h>
# include <asm/io.h>
# include <asm/prom.h>
# include <asm/smp.h>
# include <asm/residual.h>
# include <asm/time.h>
# include <asm/open_pic.h>
2005-10-11 22:08:12 +10:00
# include <asm/machdep.h>
2005-04-16 15:20:36 -07:00
extern unsigned long smp_chrp_cpu_nr ;
static int __init
smp_chrp_probe ( void )
{
if ( smp_chrp_cpu_nr > 1 )
openpic_request_IPIs ( ) ;
return smp_chrp_cpu_nr ;
}
static void __devinit
smp_chrp_kick_cpu ( int nr )
{
* ( unsigned long * ) KERNELBASE = nr ;
asm volatile ( " dcbf 0,%0 " : : " r " ( KERNELBASE ) : " memory " ) ;
}
static void __devinit
smp_chrp_setup_cpu ( int cpu_nr )
{
if ( OpenPIC_Addr )
do_openpic_setup_cpu ( ) ;
}
static DEFINE_SPINLOCK ( timebase_lock ) ;
static unsigned int timebase_upper = 0 , timebase_lower = 0 ;
void __devinit
smp_chrp_give_timebase ( void )
{
spin_lock ( & timebase_lock ) ;
call_rtas ( " freeze-time-base " , 0 , 1 , NULL ) ;
timebase_upper = get_tbu ( ) ;
timebase_lower = get_tbl ( ) ;
spin_unlock ( & timebase_lock ) ;
while ( timebase_upper | | timebase_lower )
barrier ( ) ;
call_rtas ( " thaw-time-base " , 0 , 1 , NULL ) ;
}
void __devinit
smp_chrp_take_timebase ( void )
{
while ( ! ( timebase_upper | | timebase_lower ) )
barrier ( ) ;
spin_lock ( & timebase_lock ) ;
set_tb ( timebase_upper , timebase_lower ) ;
timebase_upper = 0 ;
timebase_lower = 0 ;
spin_unlock ( & timebase_lock ) ;
printk ( " CPU %i taken timebase \n " , smp_processor_id ( ) ) ;
}
/* CHRP with openpic */
2005-09-17 10:35:08 -05:00
struct smp_ops_t chrp_smp_ops = {
2005-04-16 15:20:36 -07:00
. message_pass = smp_openpic_message_pass ,
. probe = smp_chrp_probe ,
. kick_cpu = smp_chrp_kick_cpu ,
. setup_cpu = smp_chrp_setup_cpu ,
. give_timebase = smp_chrp_give_timebase ,
. take_timebase = smp_chrp_take_timebase ,
} ;