platsmp.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
  53. { .compatible = "mediatek,mt6589", .data = &mtk_mt6589_boot },
  54. { .compatible = "mediatek,mt7623", .data = &mtk_mt7623_boot },
  55. };
  56. static void __iomem *mtk_smp_base;
  57. static const struct mtk_smp_boot_info *mtk_smp_info;
  58. static int mtk_boot_secondary(unsigned int cpu, struct task_struct *idle)
  59. {
  60. if (!mtk_smp_base)
  61. return -EINVAL;
  62. if (!mtk_smp_info->core_keys[cpu-1])
  63. return -EINVAL;
  64. writel_relaxed(mtk_smp_info->core_keys[cpu-1],
  65. mtk_smp_base + mtk_smp_info->core_regs[cpu-1]);
  66. arch_send_wakeup_ipi_mask(cpumask_of(cpu));
  67. return 0;
  68. }
  69. static void __init __mtk_smp_prepare_cpus(unsigned int max_cpus, int trustzone)
  70. {
  71. int i, num;
  72. const struct of_device_id *infos;
  73. if (trustzone) {
  74. num = ARRAY_SIZE(mtk_tz_smp_boot_infos);
  75. infos = mtk_tz_smp_boot_infos;
  76. } else {
  77. num = ARRAY_SIZE(mtk_smp_boot_infos);
  78. infos = mtk_smp_boot_infos;
  79. }
  80. /* Find smp boot info for this SoC */
  81. for (i = 0; i < num; i++) {
  82. if (of_machine_is_compatible(infos[i].compatible)) {
  83. mtk_smp_info = infos[i].data;
  84. break;
  85. }
  86. }
  87. if (!mtk_smp_info) {
  88. pr_err("%s: Device is not supported\n", __func__);
  89. return;
  90. }
  91. if (trustzone) {
  92. /* smp_base(trustzone-bootinfo) is reserved by device tree */
  93. mtk_smp_base = phys_to_virt(mtk_smp_info->smp_base);
  94. } else {
  95. mtk_smp_base = ioremap(mtk_smp_info->smp_base, MTK_SMP_REG_SIZE);
  96. if (!mtk_smp_base) {
  97. pr_err("%s: Can't remap %lx\n", __func__,
  98. mtk_smp_info->smp_base);
  99. return;
  100. }
  101. }
  102. /*
  103. * write the address of slave startup address into the system-wide
  104. * jump register
  105. */
  106. writel_relaxed(virt_to_phys(secondary_startup_arm),
  107. mtk_smp_base + mtk_smp_info->jump_reg);
  108. }
  109. static void __init mtk_tz_smp_prepare_cpus(unsigned int max_cpus)
  110. {
  111. __mtk_smp_prepare_cpus(max_cpus, 1);
  112. }
  113. static void __init mtk_smp_prepare_cpus(unsigned int max_cpus)
  114. {
  115. __mtk_smp_prepare_cpus(max_cpus, 0);
  116. }
  117. static const struct smp_operations mt81xx_tz_smp_ops __initconst = {
  118. .smp_prepare_cpus = mtk_tz_smp_prepare_cpus,
  119. .smp_boot_secondary = mtk_boot_secondary,
  120. };
  121. CPU_METHOD_OF_DECLARE(mt81xx_tz_smp, "mediatek,mt81xx-tz-smp", &mt81xx_tz_smp_ops);
  122. static const struct smp_operations mt6589_smp_ops __initconst = {
  123. .smp_prepare_cpus = mtk_smp_prepare_cpus,
  124. .smp_boot_secondary = mtk_boot_secondary,
  125. };
  126. CPU_METHOD_OF_DECLARE(mt6589_smp, "mediatek,mt6589-smp", &mt6589_smp_ops);