2019-05-27 09:55:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2015-10-02 18:19:39 +03:00
/*
* arch / arm / mach - mediatek / platsmp . c
*
* Copyright ( c ) 2014 Mediatek Inc .
* Author : Shunli Wang < shunli . wang @ mediatek . com >
* Yingjoe Chen < yingjoe . chen @ mediatek . com >
*/
# include <linux/io.h>
# include <linux/memblock.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include <linux/string.h>
# include <linux/threads.h>
# define MTK_MAX_CPU 8
# define MTK_SMP_REG_SIZE 0x1000
struct mtk_smp_boot_info {
unsigned long smp_base ;
unsigned int jump_reg ;
unsigned int core_keys [ MTK_MAX_CPU - 1 ] ;
unsigned int core_regs [ MTK_MAX_CPU - 1 ] ;
} ;
static const struct mtk_smp_boot_info mtk_mt8135_tz_boot = {
0x80002000 , 0x3fc ,
{ 0x534c4131 , 0x4c415332 , 0x41534c33 } ,
{ 0x3f8 , 0x3f8 , 0x3f8 } ,
} ;
static const struct mtk_smp_boot_info mtk_mt6589_boot = {
0x10002000 , 0x34 ,
{ 0x534c4131 , 0x4c415332 , 0x41534c33 } ,
{ 0x38 , 0x3c , 0x40 } ,
} ;
2016-01-05 19:24:28 +03:00
static const struct mtk_smp_boot_info mtk_mt7623_boot = {
0x10202000 , 0x34 ,
{ 0x534c4131 , 0x4c415332 , 0x41534c33 } ,
{ 0x38 , 0x3c , 0x40 } ,
} ;
2015-10-02 18:19:39 +03:00
static const struct of_device_id mtk_tz_smp_boot_infos [ ] __initconst = {
{ . compatible = " mediatek,mt8135 " , . data = & mtk_mt8135_tz_boot } ,
{ . compatible = " mediatek,mt8127 " , . data = & mtk_mt8135_tz_boot } ,
2016-01-07 15:09:43 +03:00
{ . compatible = " mediatek,mt2701 " , . data = & mtk_mt8135_tz_boot } ,
2017-09-21 09:24:27 +03:00
{ } ,
2015-10-02 18:19:39 +03:00
} ;
static const struct of_device_id mtk_smp_boot_infos [ ] __initconst = {
{ . compatible = " mediatek,mt6589 " , . data = & mtk_mt6589_boot } ,
2016-01-05 19:24:28 +03:00
{ . compatible = " mediatek,mt7623 " , . data = & mtk_mt7623_boot } ,
2019-01-29 07:31:18 +03:00
{ . compatible = " mediatek,mt7629 " , . data = & mtk_mt7623_boot } ,
2017-09-21 09:24:27 +03:00
{ } ,
2015-10-02 18:19:39 +03:00
} ;
static void __iomem * mtk_smp_base ;
static const struct mtk_smp_boot_info * mtk_smp_info ;
static int mtk_boot_secondary ( unsigned int cpu , struct task_struct * idle )
{
if ( ! mtk_smp_base )
return - EINVAL ;
if ( ! mtk_smp_info - > core_keys [ cpu - 1 ] )
return - EINVAL ;
writel_relaxed ( mtk_smp_info - > core_keys [ cpu - 1 ] ,
mtk_smp_base + mtk_smp_info - > core_regs [ cpu - 1 ] ) ;
arch_send_wakeup_ipi_mask ( cpumask_of ( cpu ) ) ;
return 0 ;
}
static void __init __mtk_smp_prepare_cpus ( unsigned int max_cpus , int trustzone )
{
int i , num ;
const struct of_device_id * infos ;
if ( trustzone ) {
num = ARRAY_SIZE ( mtk_tz_smp_boot_infos ) ;
infos = mtk_tz_smp_boot_infos ;
} else {
num = ARRAY_SIZE ( mtk_smp_boot_infos ) ;
infos = mtk_smp_boot_infos ;
}
/* Find smp boot info for this SoC */
for ( i = 0 ; i < num ; i + + ) {
if ( of_machine_is_compatible ( infos [ i ] . compatible ) ) {
mtk_smp_info = infos [ i ] . data ;
break ;
}
}
if ( ! mtk_smp_info ) {
pr_err ( " %s: Device is not supported \n " , __func__ ) ;
return ;
}
if ( trustzone ) {
/* smp_base(trustzone-bootinfo) is reserved by device tree */
mtk_smp_base = phys_to_virt ( mtk_smp_info - > smp_base ) ;
} else {
mtk_smp_base = ioremap ( mtk_smp_info - > smp_base , MTK_SMP_REG_SIZE ) ;
if ( ! mtk_smp_base ) {
pr_err ( " %s: Can't remap %lx \n " , __func__ ,
mtk_smp_info - > smp_base ) ;
return ;
}
}
/*
* write the address of slave startup address into the system - wide
* jump register
*/
2017-01-15 05:59:29 +03:00
writel_relaxed ( __pa_symbol ( secondary_startup_arm ) ,
2015-10-02 18:19:39 +03:00
mtk_smp_base + mtk_smp_info - > jump_reg ) ;
}
static void __init mtk_tz_smp_prepare_cpus ( unsigned int max_cpus )
{
__mtk_smp_prepare_cpus ( max_cpus , 1 ) ;
}
static void __init mtk_smp_prepare_cpus ( unsigned int max_cpus )
{
__mtk_smp_prepare_cpus ( max_cpus , 0 ) ;
}
2015-11-15 04:39:53 +03:00
static const struct smp_operations mt81xx_tz_smp_ops __initconst = {
2015-10-02 18:19:39 +03:00
. smp_prepare_cpus = mtk_tz_smp_prepare_cpus ,
. smp_boot_secondary = mtk_boot_secondary ,
} ;
CPU_METHOD_OF_DECLARE ( mt81xx_tz_smp , " mediatek,mt81xx-tz-smp " , & mt81xx_tz_smp_ops ) ;
2015-11-15 04:39:53 +03:00
static const struct smp_operations mt6589_smp_ops __initconst = {
2015-10-02 18:19:39 +03:00
. smp_prepare_cpus = mtk_smp_prepare_cpus ,
. smp_boot_secondary = mtk_boot_secondary ,
} ;
CPU_METHOD_OF_DECLARE ( mt6589_smp , " mediatek,mt6589-smp " , & mt6589_smp_ops ) ;