platsmp.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2014 Marvell Technology Group Ltd.
  4. *
  5. * Antoine Ténart <[email protected]>
  6. */
  7. #include <linux/io.h>
  8. #include <linux/delay.h>
  9. #include <linux/of.h>
  10. #include <linux/of_address.h>
  11. #include <asm/cacheflush.h>
  12. #include <asm/cp15.h>
  13. #include <asm/memory.h>
  14. #include <asm/smp_plat.h>
  15. #include <asm/smp_scu.h>
  16. /*
  17. * There are two reset registers, one with self-clearing (SC)
  18. * reset and one with non-self-clearing reset (NON_SC).
  19. */
  20. #define CPU_RESET_SC 0x00
  21. #define CPU_RESET_NON_SC 0x20
  22. #define RESET_VECT 0x00
  23. #define SW_RESET_ADDR 0x94
  24. extern u32 boot_inst;
  25. static void __iomem *cpu_ctrl;
  26. static inline void berlin_perform_reset_cpu(unsigned int cpu)
  27. {
  28. u32 val;
  29. val = readl(cpu_ctrl + CPU_RESET_NON_SC);
  30. val &= ~BIT(cpu_logical_map(cpu));
  31. writel(val, cpu_ctrl + CPU_RESET_NON_SC);
  32. val |= BIT(cpu_logical_map(cpu));
  33. writel(val, cpu_ctrl + CPU_RESET_NON_SC);
  34. }
  35. static int berlin_boot_secondary(unsigned int cpu, struct task_struct *idle)
  36. {
  37. if (!cpu_ctrl)
  38. return -EFAULT;
  39. /*
  40. * Reset the CPU, making it to execute the instruction in the reset
  41. * exception vector.
  42. */
  43. berlin_perform_reset_cpu(cpu);
  44. return 0;
  45. }
  46. static void __init berlin_smp_prepare_cpus(unsigned int max_cpus)
  47. {
  48. struct device_node *np;
  49. void __iomem *scu_base;
  50. void __iomem *vectors_base;
  51. np = of_find_compatible_node(NULL, NULL, "arm,cortex-a9-scu");
  52. scu_base = of_iomap(np, 0);
  53. of_node_put(np);
  54. if (!scu_base)
  55. return;
  56. np = of_find_compatible_node(NULL, NULL, "marvell,berlin-cpu-ctrl");
  57. cpu_ctrl = of_iomap(np, 0);
  58. of_node_put(np);
  59. if (!cpu_ctrl)
  60. goto unmap_scu;
  61. vectors_base = ioremap(VECTORS_BASE, SZ_32K);
  62. if (!vectors_base)
  63. goto unmap_scu;
  64. scu_enable(scu_base);
  65. /*
  66. * Write the first instruction the CPU will execute after being reset
  67. * in the reset exception vector.
  68. */
  69. writel(boot_inst, vectors_base + RESET_VECT);
  70. /*
  71. * Write the secondary startup address into the SW reset address
  72. * vector. This is used by boot_inst.
  73. */
  74. writel(__pa_symbol(secondary_startup), vectors_base + SW_RESET_ADDR);
  75. iounmap(vectors_base);
  76. unmap_scu:
  77. iounmap(scu_base);
  78. }
  79. #ifdef CONFIG_HOTPLUG_CPU
  80. static void berlin_cpu_die(unsigned int cpu)
  81. {
  82. v7_exit_coherency_flush(louis);
  83. while (1)
  84. cpu_do_idle();
  85. }
  86. static int berlin_cpu_kill(unsigned int cpu)
  87. {
  88. u32 val;
  89. val = readl(cpu_ctrl + CPU_RESET_NON_SC);
  90. val &= ~BIT(cpu_logical_map(cpu));
  91. writel(val, cpu_ctrl + CPU_RESET_NON_SC);
  92. return 1;
  93. }
  94. #endif
  95. static const struct smp_operations berlin_smp_ops __initconst = {
  96. .smp_prepare_cpus = berlin_smp_prepare_cpus,
  97. .smp_boot_secondary = berlin_boot_secondary,
  98. #ifdef CONFIG_HOTPLUG_CPU
  99. .cpu_die = berlin_cpu_die,
  100. .cpu_kill = berlin_cpu_kill,
  101. #endif
  102. };
  103. CPU_METHOD_OF_DECLARE(berlin_smp, "marvell,berlin-smp", &berlin_smp_ops);