psci_smp.c 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /*
  2. * This program is free software; you can redistribute it and/or modify
  3. * it under the terms of the GNU General Public License version 2 as
  4. * published by the Free Software Foundation.
  5. *
  6. * This program is distributed in the hope that it will be useful,
  7. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. * GNU General Public License for more details.
  10. *
  11. * Copyright (C) 2012 ARM Limited
  12. *
  13. * Author: Will Deacon <will.deacon@arm.com>
  14. */
  15. #include <linux/init.h>
  16. #include <linux/smp.h>
  17. #include <linux/of.h>
  18. #include <asm/psci.h>
  19. #include <asm/smp_plat.h>
  20. /*
  21. * psci_smp assumes that the following is true about PSCI:
  22. *
  23. * cpu_suspend Suspend the execution on a CPU
  24. * @state we don't currently describe affinity levels, so just pass 0.
  25. * @entry_point the first instruction to be executed on return
  26. * returns 0 success, < 0 on failure
  27. *
  28. * cpu_off Power down a CPU
  29. * @state we don't currently describe affinity levels, so just pass 0.
  30. * no return on successful call
  31. *
  32. * cpu_on Power up a CPU
  33. * @cpuid cpuid of target CPU, as from MPIDR
  34. * @entry_point the first instruction to be executed on return
  35. * returns 0 success, < 0 on failure
  36. *
  37. * migrate Migrate the context to a different CPU
  38. * @cpuid cpuid of target CPU, as from MPIDR
  39. * returns 0 success, < 0 on failure
  40. *
  41. */
  42. extern void secondary_startup(void);
  43. static int psci_boot_secondary(unsigned int cpu, struct task_struct *idle)
  44. {
  45. if (psci_ops.cpu_on)
  46. return psci_ops.cpu_on(cpu_logical_map(cpu),
  47. __pa(secondary_startup));
  48. return -ENODEV;
  49. }
  50. #ifdef CONFIG_HOTPLUG_CPU
  51. void __ref psci_cpu_die(unsigned int cpu)
  52. {
  53. const struct psci_power_state ps = {
  54. .type = PSCI_POWER_STATE_TYPE_POWER_DOWN,
  55. };
  56. if (psci_ops.cpu_off)
  57. psci_ops.cpu_off(ps);
  58. /* We should never return */
  59. panic("psci: cpu %d failed to shutdown\n", cpu);
  60. }
  61. #endif
  62. bool __init psci_smp_available(void)
  63. {
  64. /* is cpu_on available at least? */
  65. return (psci_ops.cpu_on != NULL);
  66. }
  67. struct smp_operations __initdata psci_smp_ops = {
  68. .smp_boot_secondary = psci_boot_secondary,
  69. #ifdef CONFIG_HOTPLUG_CPU
  70. .cpu_die = psci_cpu_die,
  71. #endif
  72. };