2019-06-04 10:11:33 +02:00
// SPDX-License-Identifier: GPL-2.0-only
2014-05-23 11:08:35 +02:00
/*
* linux / arch / arm / mach - axxia / platsmp . c
*
* Copyright ( C ) 2012 LSI Corporation
*/
# include <linux/init.h>
# include <linux/io.h>
# include <linux/smp.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include <asm/cacheflush.h>
/* Syscon register offsets for releasing cores from reset */
# define SC_CRIT_WRITE_KEY 0x1000
# define SC_RST_CPU_HOLD 0x1010
/*
* Write the kernel entry point for secondary CPUs to the specified address
*/
static void write_release_addr ( u32 release_phys )
{
u32 * virt = ( u32 * ) phys_to_virt ( release_phys ) ;
2017-01-15 03:59:29 +01:00
writel_relaxed ( __pa_symbol ( secondary_startup ) , virt ) ;
2014-05-23 11:08:35 +02:00
/* Make sure this store is visible to other CPUs */
smp_wmb ( ) ;
__cpuc_flush_dcache_area ( virt , sizeof ( u32 ) ) ;
}
static int axxia_boot_secondary ( unsigned int cpu , struct task_struct * idle )
{
struct device_node * syscon_np ;
void __iomem * syscon ;
u32 tmp ;
syscon_np = of_find_compatible_node ( NULL , NULL , " lsi,axxia-syscon " ) ;
if ( ! syscon_np )
return - ENOENT ;
syscon = of_iomap ( syscon_np , 0 ) ;
if ( ! syscon )
return - ENOMEM ;
tmp = readl ( syscon + SC_RST_CPU_HOLD ) ;
writel ( 0xab , syscon + SC_CRIT_WRITE_KEY ) ;
tmp & = ~ ( 1 < < cpu ) ;
writel ( tmp , syscon + SC_RST_CPU_HOLD ) ;
return 0 ;
}
static void __init axxia_smp_prepare_cpus ( unsigned int max_cpus )
{
int cpu_count = 0 ;
int cpu ;
/*
* Initialise the present map , which describes the set of CPUs actually
* populated at the present time .
*/
for_each_possible_cpu ( cpu ) {
struct device_node * np ;
u32 release_phys ;
np = of_get_cpu_node ( cpu , NULL ) ;
if ( ! np )
continue ;
if ( of_property_read_u32 ( np , " cpu-release-addr " , & release_phys ) )
continue ;
if ( cpu_count < max_cpus ) {
set_cpu_present ( cpu , true ) ;
cpu_count + + ;
}
if ( release_phys ! = 0 )
write_release_addr ( release_phys ) ;
}
}
2015-11-15 10:39:53 +09:00
static const struct smp_operations axxia_smp_ops __initconst = {
2014-05-23 11:08:35 +02:00
. smp_prepare_cpus = axxia_smp_prepare_cpus ,
. smp_boot_secondary = axxia_boot_secondary ,
} ;
CPU_METHOD_OF_DECLARE ( axxia_smp , " lsi,syscon-release " , & axxia_smp_ops ) ;