2008-11-19 09:35:56 -06:00
/*
* Author : Andy Fleming < afleming @ freescale . com >
* Kumar Gala < galak @ kernel . crashing . org >
*
* Copyright 2006 - 2008 Freescale Semiconductor Inc .
*
* 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 .
*/
# include <linux/stddef.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/of.h>
# include <asm/machdep.h>
# include <asm/pgtable.h>
# include <asm/page.h>
# include <asm/mpic.h>
# include <asm/cacheflush.h>
2009-02-11 22:50:42 -06:00
# include <asm/dbell.h>
2008-11-19 09:35:56 -06:00
# include <sysdev/fsl_soc.h>
extern void __early_start ( void ) ;
# define BOOT_ENTRY_ADDR_UPPER 0
# define BOOT_ENTRY_ADDR_LOWER 1
# define BOOT_ENTRY_R3_UPPER 2
# define BOOT_ENTRY_R3_LOWER 3
# define BOOT_ENTRY_RESV 4
# define BOOT_ENTRY_PIR 5
# define BOOT_ENTRY_R6_UPPER 6
# define BOOT_ENTRY_R6_LOWER 7
# define NUM_BOOT_ENTRY 8
# define SIZE_BOOT_ENTRY (NUM_BOOT_ENTRY * sizeof(u32))
static void __init
smp_85xx_kick_cpu ( int nr )
{
unsigned long flags ;
const u64 * cpu_rel_addr ;
__iomem u32 * bptr_vaddr ;
struct device_node * np ;
int n = 0 ;
WARN_ON ( nr < 0 | | nr > = NR_CPUS ) ;
pr_debug ( " smp_85xx_kick_cpu: kick CPU #%d \n " , nr ) ;
np = of_get_cpu_node ( nr , NULL ) ;
cpu_rel_addr = of_get_property ( np , " cpu-release-addr " , NULL ) ;
if ( cpu_rel_addr = = NULL ) {
printk ( KERN_ERR " No cpu-release-addr for cpu %d \n " , nr ) ;
return ;
}
/* Map the spin table */
bptr_vaddr = ioremap ( * cpu_rel_addr , SIZE_BOOT_ENTRY ) ;
2009-06-19 03:30:42 -05:00
local_irq_save ( flags ) ;
2008-11-19 09:35:56 -06:00
out_be32 ( bptr_vaddr + BOOT_ENTRY_PIR , nr ) ;
out_be32 ( bptr_vaddr + BOOT_ENTRY_ADDR_LOWER , __pa ( __early_start ) ) ;
/* Wait a bit for the CPU to ack. */
while ( ( __secondary_hold_acknowledge ! = nr ) & & ( + + n < 1000 ) )
mdelay ( 1 ) ;
local_irq_restore ( flags ) ;
2009-06-19 03:30:42 -05:00
iounmap ( bptr_vaddr ) ;
2008-11-19 09:35:56 -06:00
pr_debug ( " waited %d msecs for CPU #%d. \n " , n , nr ) ;
}
2009-02-11 22:50:42 -06:00
static void __init
smp_85xx_setup_cpu ( int cpu_nr )
{
mpic_setup_this_cpu ( ) ;
}
2008-11-19 09:35:56 -06:00
struct smp_ops_t smp_85xx_ops = {
. kick_cpu = smp_85xx_kick_cpu ,
} ;
2009-02-11 22:50:42 -06:00
void __init mpc85xx_smp_init ( void )
{
struct device_node * np ;
np = of_find_node_by_type ( NULL , " open-pic " ) ;
if ( np ) {
smp_85xx_ops . probe = smp_mpic_probe ;
smp_85xx_ops . setup_cpu = smp_85xx_setup_cpu ;
smp_85xx_ops . message_pass = smp_mpic_message_pass ;
}
if ( cpu_has_feature ( CPU_FTR_DBELL ) )
smp_85xx_ops . message_pass = smp_dbell_message_pass ;
BUG_ON ( ! smp_85xx_ops . message_pass ) ;
2008-11-19 09:35:56 -06:00
smp_ops = & smp_85xx_ops ;
}