162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * arch/arm/mach-mediatek/platsmp.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2014 Mediatek Inc. 662306a36Sopenharmony_ci * Author: Shunli Wang <shunli.wang@mediatek.com> 762306a36Sopenharmony_ci * Yingjoe Chen <yingjoe.chen@mediatek.com> 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci#include <linux/io.h> 1062306a36Sopenharmony_ci#include <linux/memblock.h> 1162306a36Sopenharmony_ci#include <linux/of.h> 1262306a36Sopenharmony_ci#include <linux/of_address.h> 1362306a36Sopenharmony_ci#include <linux/string.h> 1462306a36Sopenharmony_ci#include <linux/threads.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define MTK_MAX_CPU 8 1762306a36Sopenharmony_ci#define MTK_SMP_REG_SIZE 0x1000 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistruct mtk_smp_boot_info { 2062306a36Sopenharmony_ci unsigned long smp_base; 2162306a36Sopenharmony_ci unsigned int jump_reg; 2262306a36Sopenharmony_ci unsigned int core_keys[MTK_MAX_CPU - 1]; 2362306a36Sopenharmony_ci unsigned int core_regs[MTK_MAX_CPU - 1]; 2462306a36Sopenharmony_ci}; 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic const struct mtk_smp_boot_info mtk_mt8135_tz_boot = { 2762306a36Sopenharmony_ci 0x80002000, 0x3fc, 2862306a36Sopenharmony_ci { 0x534c4131, 0x4c415332, 0x41534c33 }, 2962306a36Sopenharmony_ci { 0x3f8, 0x3f8, 0x3f8 }, 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic const struct mtk_smp_boot_info mtk_mt6589_boot = { 3362306a36Sopenharmony_ci 0x10002000, 0x34, 3462306a36Sopenharmony_ci { 0x534c4131, 0x4c415332, 0x41534c33 }, 3562306a36Sopenharmony_ci { 0x38, 0x3c, 0x40 }, 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic const struct mtk_smp_boot_info mtk_mt7623_boot = { 3962306a36Sopenharmony_ci 0x10202000, 0x34, 4062306a36Sopenharmony_ci { 0x534c4131, 0x4c415332, 0x41534c33 }, 4162306a36Sopenharmony_ci { 0x38, 0x3c, 0x40 }, 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_cistatic const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = { 4562306a36Sopenharmony_ci { .compatible = "mediatek,mt8135", .data = &mtk_mt8135_tz_boot }, 4662306a36Sopenharmony_ci { .compatible = "mediatek,mt8127", .data = &mtk_mt8135_tz_boot }, 4762306a36Sopenharmony_ci { .compatible = "mediatek,mt2701", .data = &mtk_mt8135_tz_boot }, 4862306a36Sopenharmony_ci {}, 4962306a36Sopenharmony_ci}; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic const struct of_device_id mtk_smp_boot_infos[] __initconst = { 5262306a36Sopenharmony_ci { .compatible = "mediatek,mt6589", .data = &mtk_mt6589_boot }, 5362306a36Sopenharmony_ci { .compatible = "mediatek,mt7623", .data = &mtk_mt7623_boot }, 5462306a36Sopenharmony_ci { .compatible = "mediatek,mt7629", .data = &mtk_mt7623_boot }, 5562306a36Sopenharmony_ci {}, 5662306a36Sopenharmony_ci}; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic void __iomem *mtk_smp_base; 5962306a36Sopenharmony_cistatic const struct mtk_smp_boot_info *mtk_smp_info; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic int mtk_boot_secondary(unsigned int cpu, struct task_struct *idle) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci if (!mtk_smp_base) 6462306a36Sopenharmony_ci return -EINVAL; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci if (!mtk_smp_info->core_keys[cpu-1]) 6762306a36Sopenharmony_ci return -EINVAL; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci writel_relaxed(mtk_smp_info->core_keys[cpu-1], 7062306a36Sopenharmony_ci mtk_smp_base + mtk_smp_info->core_regs[cpu-1]); 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci arch_send_wakeup_ipi_mask(cpumask_of(cpu)); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci return 0; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic void __init __mtk_smp_prepare_cpus(unsigned int max_cpus, int trustzone) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci int i, num; 8062306a36Sopenharmony_ci const struct of_device_id *infos; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (trustzone) { 8362306a36Sopenharmony_ci num = ARRAY_SIZE(mtk_tz_smp_boot_infos); 8462306a36Sopenharmony_ci infos = mtk_tz_smp_boot_infos; 8562306a36Sopenharmony_ci } else { 8662306a36Sopenharmony_ci num = ARRAY_SIZE(mtk_smp_boot_infos); 8762306a36Sopenharmony_ci infos = mtk_smp_boot_infos; 8862306a36Sopenharmony_ci } 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* Find smp boot info for this SoC */ 9162306a36Sopenharmony_ci for (i = 0; i < num; i++) { 9262306a36Sopenharmony_ci if (of_machine_is_compatible(infos[i].compatible)) { 9362306a36Sopenharmony_ci mtk_smp_info = infos[i].data; 9462306a36Sopenharmony_ci break; 9562306a36Sopenharmony_ci } 9662306a36Sopenharmony_ci } 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (!mtk_smp_info) { 9962306a36Sopenharmony_ci pr_err("%s: Device is not supported\n", __func__); 10062306a36Sopenharmony_ci return; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci if (trustzone) { 10462306a36Sopenharmony_ci /* smp_base(trustzone-bootinfo) is reserved by device tree */ 10562306a36Sopenharmony_ci mtk_smp_base = phys_to_virt(mtk_smp_info->smp_base); 10662306a36Sopenharmony_ci } else { 10762306a36Sopenharmony_ci mtk_smp_base = ioremap(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE); 10862306a36Sopenharmony_ci if (!mtk_smp_base) { 10962306a36Sopenharmony_ci pr_err("%s: Can't remap %lx\n", __func__, 11062306a36Sopenharmony_ci mtk_smp_info->smp_base); 11162306a36Sopenharmony_ci return; 11262306a36Sopenharmony_ci } 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci /* 11662306a36Sopenharmony_ci * write the address of slave startup address into the system-wide 11762306a36Sopenharmony_ci * jump register 11862306a36Sopenharmony_ci */ 11962306a36Sopenharmony_ci writel_relaxed(__pa_symbol(secondary_startup_arm), 12062306a36Sopenharmony_ci mtk_smp_base + mtk_smp_info->jump_reg); 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci __mtk_smp_prepare_cpus(max_cpus, 1); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic void __init mtk_smp_prepare_cpus(unsigned int max_cpus) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci __mtk_smp_prepare_cpus(max_cpus, 0); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic const struct smp_operations mt81xx_tz_smp_ops __initconst = { 13462306a36Sopenharmony_ci .smp_prepare_cpus = mtk_tz_smp_prepare_cpus, 13562306a36Sopenharmony_ci .smp_boot_secondary = mtk_boot_secondary, 13662306a36Sopenharmony_ci}; 13762306a36Sopenharmony_ciCPU_METHOD_OF_DECLARE(mt81xx_tz_smp, "mediatek,mt81xx-tz-smp", &mt81xx_tz_smp_ops); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistatic const struct smp_operations mt6589_smp_ops __initconst = { 14062306a36Sopenharmony_ci .smp_prepare_cpus = mtk_smp_prepare_cpus, 14162306a36Sopenharmony_ci .smp_boot_secondary = mtk_boot_secondary, 14262306a36Sopenharmony_ci}; 14362306a36Sopenharmony_ciCPU_METHOD_OF_DECLARE(mt6589_smp, "mediatek,mt6589-smp", &mt6589_smp_ops); 144