2009-04-28 20:51:52 +05:30
/*
* OMAP4 SMP source file . It contains platform specific fucntions
* needed for the linux smp kernel .
*
* Copyright ( C ) 2009 Texas Instruments , Inc .
*
* Author :
* Santosh Shilimkar < santosh . shilimkar @ ti . com >
*
* Platform file needed for the OMAP4 SMP . This file is based on arm
* realview smp platform .
* * Copyright ( c ) 2002 ARM Limited .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# include <linux/init.h>
# include <linux/device.h>
# include <linux/smp.h>
# include <linux/io.h>
2009-12-11 16:16:35 -08:00
# include <asm/cacheflush.h>
2011-04-03 13:01:30 +01:00
# include <asm/hardware/gic.h>
2009-04-28 20:51:52 +05:30
# include <asm/smp_scu.h>
# include <mach/hardware.h>
2010-05-14 12:05:26 -07:00
# include <mach/omap4-common.h>
2009-04-28 20:51:52 +05:30
/* SCU base address */
2009-10-19 15:25:26 -07:00
static void __iomem * scu_base ;
2009-04-28 20:51:52 +05:30
static DEFINE_SPINLOCK ( boot_lock ) ;
void __cpuinit platform_secondary_init ( unsigned int cpu )
{
/*
* If any interrupts are already enabled for the primary
* core ( e . g . timer irq ) , then they will not have been enabled
* for us : do so
*/
2010-12-04 16:01:03 +00:00
gic_secondary_init ( 0 ) ;
2009-04-28 20:51:52 +05:30
/*
* Synchronise with the boot thread .
*/
spin_lock ( & boot_lock ) ;
spin_unlock ( & boot_lock ) ;
}
int __cpuinit boot_secondary ( unsigned int cpu , struct task_struct * idle )
{
/*
* Set synchronisation state between this boot processor
* and the secondary one
*/
spin_lock ( & boot_lock ) ;
/*
2009-12-11 16:16:35 -08:00
* Update the AuxCoreBoot0 with boot state for secondary core .
2009-04-28 20:51:52 +05:30
* omap_secondary_startup ( ) routine will hold the secondary core till
* the AuxCoreBoot1 register is updated with cpu state
* A barrier is added to ensure that write buffer is drained
*/
2010-08-02 13:18:19 +03:00
omap_modify_auxcoreboot0 ( 0x200 , 0xfffffdff ) ;
2009-12-11 16:16:35 -08:00
flush_cache_all ( ) ;
2009-04-28 20:51:52 +05:30
smp_wmb ( ) ;
2011-04-03 13:01:30 +01:00
gic_raise_softirq ( cpumask_of ( cpu ) , 1 ) ;
2009-04-28 20:51:52 +05:30
/*
* Now the secondary core is starting up let it run its
* calibrations , then wait for it to finish
*/
spin_unlock ( & boot_lock ) ;
return 0 ;
}
static void __init wakeup_secondary ( void )
{
/*
* Write the address of secondary startup routine into the
2009-12-11 16:16:35 -08:00
* AuxCoreBoot1 where ROM code will jump and start executing
2009-04-28 20:51:52 +05:30
* on secondary core once out of WFE
* A barrier is added to ensure that write buffer is drained
*/
2009-12-11 16:16:35 -08:00
omap_auxcoreboot_addr ( virt_to_phys ( omap_secondary_startup ) ) ;
2009-04-28 20:51:52 +05:30
smp_wmb ( ) ;
/*
* Send a ' sev ' to wake the secondary core from WFE .
2009-12-11 16:16:35 -08:00
* Drain the outstanding writes to memory
2009-04-28 20:51:52 +05:30
*/
2010-08-16 09:21:20 +03:00
dsb_sev ( ) ;
2009-04-28 20:51:52 +05:30
mb ( ) ;
}
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system .
*/
void __init smp_init_cpus ( void )
{
2009-10-19 15:25:26 -07:00
unsigned int i , ncores ;
2011-10-04 18:17:41 -07:00
/*
* Currently we can ' t call ioremap here because
* SoC detection won ' t work until after init_early .
*/
scu_base = OMAP2_L4_IO_ADDRESS ( OMAP44XX_SCU_BASE ) ;
2009-10-19 15:25:26 -07:00
BUG_ON ( ! scu_base ) ;
2010-12-02 18:09:37 +00:00
ncores = scu_get_core_count ( scu_base ) ;
2009-04-28 20:51:52 +05:30
/* sanity check */
2011-10-20 22:04:18 +01:00
if ( ncores > nr_cpu_ids ) {
pr_warn ( " SMP: %u cores greater than maximum (%u), clipping \n " ,
ncores , nr_cpu_ids ) ;
ncores = nr_cpu_ids ;
2009-04-28 20:51:52 +05:30
}
2010-12-03 10:42:58 +00:00
for ( i = 0 ; i < ncores ; i + + )
set_cpu_possible ( i , true ) ;
2011-04-03 13:01:30 +01:00
set_smp_cross_call ( gic_raise_softirq ) ;
2010-12-03 10:42:58 +00:00
}
2010-12-03 11:09:48 +00:00
void __init platform_smp_prepare_cpus ( unsigned int max_cpus )
2010-12-03 10:42:58 +00:00
{
2009-04-28 20:51:52 +05:30
2010-12-03 11:09:48 +00:00
/*
* Initialise the SCU and wake up the secondary core using
* wakeup_secondary ( ) .
*/
scu_enable ( scu_base ) ;
wakeup_secondary ( ) ;
2009-04-28 20:51:52 +05:30
}