platsmp-scu.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * SMP support for SoCs with SCU covered by mach-shmobile
  4. *
  5. * Copyright (C) 2013 Magnus Damm
  6. */
  7. #include <linux/cpu.h>
  8. #include <linux/delay.h>
  9. #include <linux/init.h>
  10. #include <linux/io.h>
  11. #include <linux/smp.h>
  12. #include <asm/cacheflush.h>
  13. #include <asm/smp_plat.h>
  14. #include <asm/smp_scu.h>
  15. #include "common.h"
  16. static phys_addr_t shmobile_scu_base_phys;
  17. static void __iomem *shmobile_scu_base;
  18. static int shmobile_scu_cpu_prepare(unsigned int cpu)
  19. {
  20. /* For this particular CPU register SCU SMP boot vector */
  21. shmobile_smp_hook(cpu, __pa_symbol(shmobile_boot_scu),
  22. shmobile_scu_base_phys);
  23. return 0;
  24. }
  25. void __init shmobile_smp_scu_prepare_cpus(phys_addr_t scu_base_phys,
  26. unsigned int max_cpus)
  27. {
  28. /* install boot code shared by all CPUs */
  29. shmobile_boot_fn = __pa_symbol(shmobile_smp_boot);
  30. /* enable SCU and cache coherency on booting CPU */
  31. shmobile_scu_base_phys = scu_base_phys;
  32. shmobile_scu_base = ioremap(scu_base_phys, PAGE_SIZE);
  33. scu_enable(shmobile_scu_base);
  34. scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
  35. /* Use CPU notifier for reset vector control */
  36. cpuhp_setup_state_nocalls(CPUHP_ARM_SHMOBILE_SCU_PREPARE,
  37. "arm/shmobile-scu:prepare",
  38. shmobile_scu_cpu_prepare, NULL);
  39. }
  40. #ifdef CONFIG_HOTPLUG_CPU
  41. void shmobile_smp_scu_cpu_die(unsigned int cpu)
  42. {
  43. /* For this particular CPU deregister boot vector */
  44. shmobile_smp_hook(cpu, 0, 0);
  45. dsb();
  46. flush_cache_all();
  47. /* disable cache coherency */
  48. scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
  49. /* jump to shared mach-shmobile sleep / reset code */
  50. shmobile_smp_sleep();
  51. }
  52. static int shmobile_smp_scu_psr_core_disabled(int cpu)
  53. {
  54. unsigned long mask = SCU_PM_POWEROFF << (cpu * 8);
  55. if ((readl(shmobile_scu_base + 8) & mask) == mask)
  56. return 1;
  57. return 0;
  58. }
  59. int shmobile_smp_scu_cpu_kill(unsigned int cpu)
  60. {
  61. int k;
  62. /* this function is running on another CPU than the offline target,
  63. * here we need wait for shutdown code in platform_cpu_die() to
  64. * finish before asking SoC-specific code to power off the CPU core.
  65. */
  66. for (k = 0; k < 1000; k++) {
  67. if (shmobile_smp_scu_psr_core_disabled(cpu))
  68. return 1;
  69. mdelay(1);
  70. }
  71. return 0;
  72. }
  73. #endif