hotplug.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2002 ARM Ltd.
  4. * All Rights Reserved
  5. *
  6. * This hotplug implementation is _specific_ to the situation found on
  7. * ARM development platforms where there is _no_ possibility of actually
  8. * taking a CPU offline, resetting it, or otherwise. Real platforms must
  9. * NOT copy this code.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/errno.h>
  13. #include <linux/smp.h>
  14. #include <asm/smp_plat.h>
  15. #include <asm/cp15.h>
  16. #include "platsmp.h"
  17. static inline void versatile_immitation_enter_lowpower(unsigned int actrl_mask)
  18. {
  19. unsigned int v;
  20. asm volatile(
  21. "mcr p15, 0, %1, c7, c5, 0\n"
  22. " mcr p15, 0, %1, c7, c10, 4\n"
  23. /*
  24. * Turn off coherency
  25. */
  26. " mrc p15, 0, %0, c1, c0, 1\n"
  27. " bic %0, %0, %3\n"
  28. " mcr p15, 0, %0, c1, c0, 1\n"
  29. " mrc p15, 0, %0, c1, c0, 0\n"
  30. " bic %0, %0, %2\n"
  31. " mcr p15, 0, %0, c1, c0, 0\n"
  32. : "=&r" (v)
  33. : "r" (0), "Ir" (CR_C), "Ir" (actrl_mask)
  34. : "cc");
  35. }
  36. static inline void versatile_immitation_leave_lowpower(unsigned int actrl_mask)
  37. {
  38. unsigned int v;
  39. asm volatile(
  40. "mrc p15, 0, %0, c1, c0, 0\n"
  41. " orr %0, %0, %1\n"
  42. " mcr p15, 0, %0, c1, c0, 0\n"
  43. " mrc p15, 0, %0, c1, c0, 1\n"
  44. " orr %0, %0, %2\n"
  45. " mcr p15, 0, %0, c1, c0, 1\n"
  46. : "=&r" (v)
  47. : "Ir" (CR_C), "Ir" (actrl_mask)
  48. : "cc");
  49. }
  50. static inline void versatile_immitation_do_lowpower(unsigned int cpu, int *spurious)
  51. {
  52. /*
  53. * there is no power-control hardware on this platform, so all
  54. * we can do is put the core into WFI; this is safe as the calling
  55. * code will have already disabled interrupts.
  56. *
  57. * This code should not be used outside Versatile platforms.
  58. */
  59. for (;;) {
  60. wfi();
  61. if (versatile_cpu_release == cpu_logical_map(cpu)) {
  62. /*
  63. * OK, proper wakeup, we're done
  64. */
  65. break;
  66. }
  67. /*
  68. * Getting here, means that we have come out of WFI without
  69. * having been woken up - this shouldn't happen
  70. *
  71. * Just note it happening - when we're woken, we can report
  72. * its occurrence.
  73. */
  74. (*spurious)++;
  75. }
  76. }
  77. /*
  78. * platform-specific code to shutdown a CPU.
  79. * This code supports immitation-style CPU hotplug for Versatile/Realview/
  80. * Versatile Express platforms that are unable to do real CPU hotplug.
  81. */
  82. void versatile_immitation_cpu_die(unsigned int cpu, unsigned int actrl_mask)
  83. {
  84. int spurious = 0;
  85. versatile_immitation_enter_lowpower(actrl_mask);
  86. versatile_immitation_do_lowpower(cpu, &spurious);
  87. versatile_immitation_leave_lowpower(actrl_mask);
  88. if (spurious)
  89. pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
  90. }