platsmp.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /*
  2. * arch/arm/mach-mediatek/platsmp.c
  3. *
  4. * Copyright (c) 2014 Mediatek Inc.
  5. * Author: Shunli Wang <shunli.wang@mediatek.com>
  6. * Yingjoe Chen <yingjoe.chen@mediatek.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. */
  18. #include <linux/io.h>
  19. #include <linux/memblock.h>
  20. #include <linux/of.h>
  21. #include <linux/of_address.h>
  22. #include <linux/string.h>
  23. #include <linux/threads.h>
  24. #define MTK_MAX_CPU 8
  25. #define MTK_SMP_REG_SIZE 0x1000
  26. struct mtk_smp_boot_info {
  27. unsigned long smp_base;
  28. unsigned int jump_reg;
  29. unsigned int core_keys[MTK_MAX_CPU - 1];
  30. unsigned int core_regs[MTK_MAX_CPU - 1];
  31. };
  32. static const struct mtk_smp_boot_info mtk_mt8135_tz_boot = {
  33. 0x80002000, 0x3fc,
  34. { 0x534c4131, 0x4c415332, 0x41534c33 },
  35. { 0x3f8, 0x3f8, 0x3f8 },
  36. };
  37. static const struct mtk_smp_boot_info mtk_mt6589_boot = {
  38. 0x10002000, 0x34,
  39. { 0x534c4131, 0x4c415332, 0x41534c33 },
  40. { 0x38, 0x3c, 0x40 },
  41. };
  42. static const struct mtk_smp_boot_info mtk_mt7623_boot = {
  43. 0x10202000, 0x34,
  44. { 0x534c4131, 0x4c415332, 0x41534c33 },
  45. { 0x38, 0x3c, 0x40 },
  46. };
  47. static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
  48. { .compatible = "mediatek,mt8135", .data = &mtk_mt8135_tz_boot },
  49. { .compatible = "mediatek,mt8127", .data = &mtk_mt8135_tz_boot },
  50. { .compatible = "mediatek,mt2701", .data = &mtk_mt8135_tz_boot },
  51. {},
  52. };
  53. static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
  54. { .compatible = "mediatek,mt6589", .data = &mtk_mt6589_boot },
  55. { .compatible = "mediatek,mt7623", .data = &mtk_mt7623_boot },
  56. { .compatible = "mediatek,mt7623a", .data = &mtk_mt7623_boot },
  57. {},
  58. };
  59. static void __iomem *mtk_smp_base;
  60. static const struct mtk_smp_boot_info *mtk_smp_info;
  61. static int mtk_boot_secondary(unsigned int cpu, struct task_struct *idle)
  62. {
  63. if (!mtk_smp_base)
  64. return -EINVAL;
  65. if (!mtk_smp_info->core_keys[cpu-1])
  66. return -EINVAL;
  67. writel_relaxed(mtk_smp_info->core_keys[cpu-1],
  68. mtk_smp_base + mtk_smp_info->core_regs[cpu-1]);
  69. arch_send_wakeup_ipi_mask(cpumask_of(cpu));
  70. return 0;
  71. }
  72. static void __init __mtk_smp_prepare_cpus(unsigned int max_cpus, int trustzone)
  73. {
  74. int i, num;
  75. const struct of_device_id *infos;
  76. if (trustzone) {
  77. num = ARRAY_SIZE(mtk_tz_smp_boot_infos);
  78. infos = mtk_tz_smp_boot_infos;
  79. } else {
  80. num = ARRAY_SIZE(mtk_smp_boot_infos);
  81. infos = mtk_smp_boot_infos;
  82. }
  83. /* Find smp boot info for this SoC */
  84. for (i = 0; i < num; i++) {
  85. if (of_machine_is_compatible(infos[i].compatible)) {
  86. mtk_smp_info = infos[i].data;
  87. break;
  88. }
  89. }
  90. if (!mtk_smp_info) {
  91. pr_err("%s: Device is not supported\n", __func__);
  92. return;
  93. }
  94. if (trustzone) {
  95. /* smp_base(trustzone-bootinfo) is reserved by device tree */
  96. mtk_smp_base = phys_to_virt(mtk_smp_info->smp_base);
  97. } else {
  98. mtk_smp_base = ioremap(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE);
  99. if (!mtk_smp_base) {
  100. pr_err("%s: Can't remap %lx\n", __func__,
  101. mtk_smp_info->smp_base);
  102. return;
  103. }
  104. }
  105. /*
  106. * write the address of slave startup address into the system-wide
  107. * jump register
  108. */
  109. writel_relaxed(__pa_symbol(secondary_startup_arm),
  110. mtk_smp_base + mtk_smp_info->jump_reg);
  111. }
  112. static void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus)
  113. {
  114. __mtk_smp_prepare_cpus(max_cpus, 1);
  115. }
  116. static void __init mtk_smp_prepare_cpus(unsigned int max_cpus)
  117. {
  118. __mtk_smp_prepare_cpus(max_cpus, 0);
  119. }
  120. static const struct smp_operations mt81xx_tz_smp_ops __initconst = {
  121. .smp_prepare_cpus = mtk_tz_smp_prepare_cpus,
  122. .smp_boot_secondary = mtk_boot_secondary,
  123. };
  124. CPU_METHOD_OF_DECLARE(mt81xx_tz_smp, "mediatek,mt81xx-tz-smp", &mt81xx_tz_smp_ops);
  125. static const struct smp_operations mt6589_smp_ops __initconst = {
  126. .smp_prepare_cpus = mtk_smp_prepare_cpus,
  127. .smp_boot_secondary = mtk_boot_secondary,
  128. };
  129. CPU_METHOD_OF_DECLARE(mt6589_smp, "mediatek,mt6589-smp", &mt6589_smp_ops);