0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/io.h>
0010 #include <linux/memblock.h>
0011 #include <linux/of.h>
0012 #include <linux/of_address.h>
0013 #include <linux/string.h>
0014 #include <linux/threads.h>
0015
0016 #define MTK_MAX_CPU 8
0017 #define MTK_SMP_REG_SIZE 0x1000
0018
0019 struct mtk_smp_boot_info {
0020 unsigned long smp_base;
0021 unsigned int jump_reg;
0022 unsigned int core_keys[MTK_MAX_CPU - 1];
0023 unsigned int core_regs[MTK_MAX_CPU - 1];
0024 };
0025
0026 static const struct mtk_smp_boot_info mtk_mt8135_tz_boot = {
0027 0x80002000, 0x3fc,
0028 { 0x534c4131, 0x4c415332, 0x41534c33 },
0029 { 0x3f8, 0x3f8, 0x3f8 },
0030 };
0031
0032 static const struct mtk_smp_boot_info mtk_mt6589_boot = {
0033 0x10002000, 0x34,
0034 { 0x534c4131, 0x4c415332, 0x41534c33 },
0035 { 0x38, 0x3c, 0x40 },
0036 };
0037
0038 static const struct mtk_smp_boot_info mtk_mt7623_boot = {
0039 0x10202000, 0x34,
0040 { 0x534c4131, 0x4c415332, 0x41534c33 },
0041 { 0x38, 0x3c, 0x40 },
0042 };
0043
0044 static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
0045 { .compatible = "mediatek,mt8135", .data = &mtk_mt8135_tz_boot },
0046 { .compatible = "mediatek,mt8127", .data = &mtk_mt8135_tz_boot },
0047 { .compatible = "mediatek,mt2701", .data = &mtk_mt8135_tz_boot },
0048 {},
0049 };
0050
0051 static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
0052 { .compatible = "mediatek,mt6589", .data = &mtk_mt6589_boot },
0053 { .compatible = "mediatek,mt7623", .data = &mtk_mt7623_boot },
0054 { .compatible = "mediatek,mt7629", .data = &mtk_mt7623_boot },
0055 {},
0056 };
0057
0058 static void __iomem *mtk_smp_base;
0059 static const struct mtk_smp_boot_info *mtk_smp_info;
0060
0061 static int mtk_boot_secondary(unsigned int cpu, struct task_struct *idle)
0062 {
0063 if (!mtk_smp_base)
0064 return -EINVAL;
0065
0066 if (!mtk_smp_info->core_keys[cpu-1])
0067 return -EINVAL;
0068
0069 writel_relaxed(mtk_smp_info->core_keys[cpu-1],
0070 mtk_smp_base + mtk_smp_info->core_regs[cpu-1]);
0071
0072 arch_send_wakeup_ipi_mask(cpumask_of(cpu));
0073
0074 return 0;
0075 }
0076
0077 static void __init __mtk_smp_prepare_cpus(unsigned int max_cpus, int trustzone)
0078 {
0079 int i, num;
0080 const struct of_device_id *infos;
0081
0082 if (trustzone) {
0083 num = ARRAY_SIZE(mtk_tz_smp_boot_infos);
0084 infos = mtk_tz_smp_boot_infos;
0085 } else {
0086 num = ARRAY_SIZE(mtk_smp_boot_infos);
0087 infos = mtk_smp_boot_infos;
0088 }
0089
0090
0091 for (i = 0; i < num; i++) {
0092 if (of_machine_is_compatible(infos[i].compatible)) {
0093 mtk_smp_info = infos[i].data;
0094 break;
0095 }
0096 }
0097
0098 if (!mtk_smp_info) {
0099 pr_err("%s: Device is not supported\n", __func__);
0100 return;
0101 }
0102
0103 if (trustzone) {
0104
0105 mtk_smp_base = phys_to_virt(mtk_smp_info->smp_base);
0106 } else {
0107 mtk_smp_base = ioremap(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE);
0108 if (!mtk_smp_base) {
0109 pr_err("%s: Can't remap %lx\n", __func__,
0110 mtk_smp_info->smp_base);
0111 return;
0112 }
0113 }
0114
0115
0116
0117
0118
0119 writel_relaxed(__pa_symbol(secondary_startup_arm),
0120 mtk_smp_base + mtk_smp_info->jump_reg);
0121 }
0122
0123 static void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus)
0124 {
0125 __mtk_smp_prepare_cpus(max_cpus, 1);
0126 }
0127
0128 static void __init mtk_smp_prepare_cpus(unsigned int max_cpus)
0129 {
0130 __mtk_smp_prepare_cpus(max_cpus, 0);
0131 }
0132
0133 static const struct smp_operations mt81xx_tz_smp_ops __initconst = {
0134 .smp_prepare_cpus = mtk_tz_smp_prepare_cpus,
0135 .smp_boot_secondary = mtk_boot_secondary,
0136 };
0137 CPU_METHOD_OF_DECLARE(mt81xx_tz_smp, "mediatek,mt81xx-tz-smp", &mt81xx_tz_smp_ops);
0138
0139 static const struct smp_operations mt6589_smp_ops __initconst = {
0140 .smp_prepare_cpus = mtk_smp_prepare_cpus,
0141 .smp_boot_secondary = mtk_boot_secondary,
0142 };
0143 CPU_METHOD_OF_DECLARE(mt6589_smp, "mediatek,mt6589-smp", &mt6589_smp_ops);