mcpm_platsmp.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * linux/arch/arm/mach-vexpress/mcpm_platsmp.c
  3. *
  4. * Created by: Nicolas Pitre, November 2012
  5. * Copyright: (C) 2012-2013 Linaro Limited
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * Code to handle secondary CPU bringup and hotplug for the cluster power API.
  12. */
  13. #include <linux/init.h>
  14. #include <linux/smp.h>
  15. #include <linux/spinlock.h>
  16. #include <asm/mcpm.h>
  17. #include <asm/smp.h>
  18. #include <asm/smp_plat.h>
  19. static int mcpm_boot_secondary(unsigned int cpu, struct task_struct *idle)
  20. {
  21. unsigned int mpidr, pcpu, pcluster, ret;
  22. extern void secondary_startup(void);
  23. mpidr = cpu_logical_map(cpu);
  24. pcpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
  25. pcluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
  26. pr_debug("%s: logical CPU %d is physical CPU %d cluster %d\n",
  27. __func__, cpu, pcpu, pcluster);
  28. mcpm_set_entry_vector(pcpu, pcluster, NULL);
  29. ret = mcpm_cpu_power_up(pcpu, pcluster);
  30. if (ret)
  31. return ret;
  32. mcpm_set_entry_vector(pcpu, pcluster, secondary_startup);
  33. arch_send_wakeup_ipi_mask(cpumask_of(cpu));
  34. dsb_sev();
  35. return 0;
  36. }
  37. static void mcpm_secondary_init(unsigned int cpu)
  38. {
  39. mcpm_cpu_powered_up();
  40. }
  41. #ifdef CONFIG_HOTPLUG_CPU
  42. static int mcpm_cpu_disable(unsigned int cpu)
  43. {
  44. /*
  45. * We assume all CPUs may be shut down.
  46. * This would be the hook to use for eventual Secure
  47. * OS migration requests as described in the PSCI spec.
  48. */
  49. return 0;
  50. }
  51. static void mcpm_cpu_die(unsigned int cpu)
  52. {
  53. unsigned int mpidr, pcpu, pcluster;
  54. mpidr = read_cpuid_mpidr();
  55. pcpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
  56. pcluster = MPIDR_AFFINITY_LEVEL(mpidr, 1);
  57. mcpm_set_entry_vector(pcpu, pcluster, NULL);
  58. mcpm_cpu_power_down();
  59. }
  60. #endif
  61. static struct smp_operations __initdata mcpm_smp_ops = {
  62. .smp_boot_secondary = mcpm_boot_secondary,
  63. .smp_secondary_init = mcpm_secondary_init,
  64. #ifdef CONFIG_HOTPLUG_CPU
  65. .cpu_disable = mcpm_cpu_disable,
  66. .cpu_die = mcpm_cpu_die,
  67. #endif
  68. };
  69. void __init mcpm_smp_set_ops(void)
  70. {
  71. smp_set_ops(&mcpm_smp_ops);
  72. }