2011-09-06 10:59:40 +04:00
/*
* Copyright 2011 Freescale Semiconductor , Inc .
* Copyright 2011 Linaro Ltd .
*
* The code contained herein is licensed under the GNU General Public
* License . You may obtain a copy of the GNU General Public License
* Version 2 or later at the following locations :
*
* http : //www.opensource.org/licenses/gpl-license.html
* http : //www.gnu.org/copyleft/gpl.html
*/
# include <linux/init.h>
2014-10-31 12:01:13 +03:00
# include <linux/of_address.h>
# include <linux/of.h>
2011-09-06 10:59:40 +04:00
# include <linux/smp.h>
2014-10-31 12:01:13 +03:00
2013-04-16 18:11:19 +04:00
# include <asm/cacheflush.h>
2011-09-06 10:59:40 +04:00
# include <asm/page.h>
# include <asm/smp_scu.h>
# include <asm/mach/map.h>
2012-09-13 17:01:00 +04:00
# include "common.h"
2012-09-14 10:14:45 +04:00
# include "hardware.h"
2012-09-13 17:01:00 +04:00
2013-04-16 18:11:19 +04:00
u32 g_diag_reg ;
2011-09-06 10:59:40 +04:00
static void __iomem * scu_base ;
static struct map_desc scu_io_desc __initdata = {
/* .virtual and .pfn are run-time assigned */
. length = SZ_4K ,
. type = MT_DEVICE ,
} ;
void __init imx_scu_map_io ( void )
{
unsigned long base ;
/* Get SCU base */
asm ( " mrc p15, 4, %0, c15, c0, 0 " : " =r " ( base ) ) ;
scu_io_desc . virtual = IMX_IO_P2V ( base ) ;
scu_io_desc . pfn = __phys_to_pfn ( base ) ;
iotable_init ( & scu_io_desc , 1 ) ;
scu_base = IMX_IO_ADDRESS ( base ) ;
}
2013-06-17 23:43:14 +04:00
static int imx_boot_secondary ( unsigned int cpu , struct task_struct * idle )
2011-09-06 10:59:40 +04:00
{
imx_set_cpu_jump ( cpu , v7_secondary_startup ) ;
imx_enable_cpu ( cpu , true ) ;
return 0 ;
}
/*
* Initialise the CPU possible map early - this describes the CPUs
* which may be present or become present in the system .
*/
2011-09-08 16:15:22 +04:00
static void __init imx_smp_init_cpus ( void )
2011-09-06 10:59:40 +04:00
{
int i , ncores ;
ncores = scu_get_core_count ( scu_base ) ;
2013-04-02 12:37:21 +04:00
for ( i = ncores ; i < NR_CPUS ; i + + )
set_cpu_possible ( i , false ) ;
2011-09-06 10:59:40 +04:00
}
void imx_smp_prepare ( void )
{
scu_enable ( scu_base ) ;
}
2011-09-08 16:15:22 +04:00
static void __init imx_smp_prepare_cpus ( unsigned int max_cpus )
2011-09-06 10:59:40 +04:00
{
imx_smp_prepare ( ) ;
2013-04-16 18:11:19 +04:00
/*
* The diagnostic register holds the errata bits . Mostly bootloader
* does not bring up secondary cores , so that when errata bits are set
* in bootloader , they are set only for boot cpu . But on a SMP
* configuration , it should be equally done on every single core .
* Read the register from boot cpu here , and will replicate it into
* secondary cores when booting them .
*/
asm ( " mrc p15, 0, %0, c15, c0, 1 " : " =r " ( g_diag_reg ) : : " cc " ) ;
2013-12-05 23:26:16 +04:00
sync_cache_w ( & g_diag_reg ) ;
2011-09-06 10:59:40 +04:00
}
2011-09-08 16:15:22 +04:00
2015-11-15 04:39:53 +03:00
const struct smp_operations imx_smp_ops __initconst = {
2011-09-08 16:15:22 +04:00
. smp_init_cpus = imx_smp_init_cpus ,
. smp_prepare_cpus = imx_smp_prepare_cpus ,
. smp_boot_secondary = imx_boot_secondary ,
# ifdef CONFIG_HOTPLUG_CPU
. cpu_die = imx_cpu_die ,
2013-01-14 10:08:50 +04:00
. cpu_kill = imx_cpu_kill ,
2011-09-08 16:15:22 +04:00
# endif
} ;
2014-10-31 12:01:13 +03:00
# define DCFG_CCSR_SCRATCHRW1 0x200
static int ls1021a_boot_secondary ( unsigned int cpu , struct task_struct * idle )
{
arch_send_wakeup_ipi_mask ( cpumask_of ( cpu ) ) ;
return 0 ;
}
static void __init ls1021a_smp_prepare_cpus ( unsigned int max_cpus )
{
struct device_node * np ;
void __iomem * dcfg_base ;
unsigned long paddr ;
np = of_find_compatible_node ( NULL , NULL , " fsl,ls1021a-dcfg " ) ;
dcfg_base = of_iomap ( np , 0 ) ;
BUG_ON ( ! dcfg_base ) ;
paddr = virt_to_phys ( secondary_startup ) ;
writel_relaxed ( cpu_to_be32 ( paddr ) , dcfg_base + DCFG_CCSR_SCRATCHRW1 ) ;
iounmap ( dcfg_base ) ;
}
2015-11-15 04:39:53 +03:00
const struct smp_operations ls1021a_smp_ops __initconst = {
2014-10-31 12:01:13 +03:00
. smp_prepare_cpus = ls1021a_smp_prepare_cpus ,
. smp_boot_secondary = ls1021a_boot_secondary ,
} ;