cpuidle-arm.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. /*
  2. * ARM/ARM64 generic CPU idle driver.
  3. *
  4. * Copyright (C) 2014 ARM Ltd.
  5. * Author: Lorenzo Pieralisi <[email protected]>
  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. #define pr_fmt(fmt) "CPUidle arm: " fmt
  12. #include <linux/cpuidle.h>
  13. #include <linux/cpumask.h>
  14. #include <linux/cpu_pm.h>
  15. #include <linux/kernel.h>
  16. #include <linux/module.h>
  17. #include <linux/of.h>
  18. #include <linux/slab.h>
  19. #include <linux/topology.h>
  20. #include <asm/cpuidle.h>
  21. #include "dt_idle_states.h"
  22. /*
  23. * arm_enter_idle_state - Programs CPU to enter the specified state
  24. *
  25. * dev: cpuidle device
  26. * drv: cpuidle driver
  27. * idx: state index
  28. *
  29. * Called from the CPUidle framework to program the device to the
  30. * specified target state selected by the governor.
  31. */
  32. static int arm_enter_idle_state(struct cpuidle_device *dev,
  33. struct cpuidle_driver *drv, int idx)
  34. {
  35. /*
  36. * Pass idle state index to arm_cpuidle_suspend which in turn
  37. * will call the CPU ops suspend protocol with idle index as a
  38. * parameter.
  39. */
  40. return CPU_PM_CPU_IDLE_ENTER(arm_cpuidle_suspend, idx);
  41. }
  42. static struct cpuidle_driver arm_idle_driver __initdata = {
  43. .name = "arm_idle",
  44. .owner = THIS_MODULE,
  45. /*
  46. * State at index 0 is standby wfi and considered standard
  47. * on all ARM platforms. If in some platforms simple wfi
  48. * can't be used as "state 0", DT bindings must be implemented
  49. * to work around this issue and allow installing a special
  50. * handler for idle state index 0.
  51. */
  52. .states[0] = {
  53. .enter = arm_enter_idle_state,
  54. .exit_latency = 1,
  55. .target_residency = 1,
  56. .power_usage = UINT_MAX,
  57. .name = "WFI",
  58. .desc = "ARM WFI",
  59. }
  60. };
  61. static const struct of_device_id arm_idle_state_match[] __initconst = {
  62. { .compatible = "arm,idle-state",
  63. .data = arm_enter_idle_state },
  64. { },
  65. };
  66. /*
  67. * arm_idle_init
  68. *
  69. * Registers the arm specific cpuidle driver with the cpuidle
  70. * framework. It relies on core code to parse the idle states
  71. * and initialize them using driver data structures accordingly.
  72. */
  73. static int __init arm_idle_init(void)
  74. {
  75. int cpu, ret;
  76. struct cpuidle_driver *drv;
  77. struct cpuidle_device *dev;
  78. for_each_possible_cpu(cpu) {
  79. drv = kmemdup(&arm_idle_driver, sizeof(*drv), GFP_KERNEL);
  80. if (!drv) {
  81. ret = -ENOMEM;
  82. goto out_fail;
  83. }
  84. drv->cpumask = (struct cpumask *)cpumask_of(cpu);
  85. /*
  86. * Initialize idle states data, starting at index 1. This
  87. * driver is DT only, if no DT idle states are detected (ret
  88. * == 0) let the driver initialization fail accordingly since
  89. * there is no reason to initialize the idle driver if only
  90. * wfi is supported.
  91. */
  92. ret = dt_init_idle_driver(drv, arm_idle_state_match, 1);
  93. if (ret <= 0) {
  94. ret = ret ? : -ENODEV;
  95. goto out_kfree_drv;
  96. }
  97. ret = cpuidle_register_driver(drv);
  98. if (ret) {
  99. pr_err("Failed to register cpuidle driver\n");
  100. goto out_kfree_drv;
  101. }
  102. /*
  103. * Call arch CPU operations in order to initialize
  104. * idle states suspend back-end specific data
  105. */
  106. ret = arm_cpuidle_init(cpu);
  107. /*
  108. * Skip the cpuidle device initialization if the reported
  109. * failure is a HW misconfiguration/breakage (-ENXIO).
  110. */
  111. if (ret == -ENXIO)
  112. continue;
  113. if (ret) {
  114. pr_err("CPU %d failed to init idle CPU ops\n", cpu);
  115. goto out_unregister_drv;
  116. }
  117. dev = kzalloc(sizeof(*dev), GFP_KERNEL);
  118. if (!dev) {
  119. pr_err("Failed to allocate cpuidle device\n");
  120. ret = -ENOMEM;
  121. goto out_unregister_drv;
  122. }
  123. dev->cpu = cpu;
  124. ret = cpuidle_register_device(dev);
  125. if (ret) {
  126. pr_err("Failed to register cpuidle device for CPU %d\n",
  127. cpu);
  128. goto out_kfree_dev;
  129. }
  130. }
  131. return 0;
  132. out_kfree_dev:
  133. kfree(dev);
  134. out_unregister_drv:
  135. cpuidle_unregister_driver(drv);
  136. out_kfree_drv:
  137. kfree(drv);
  138. out_fail:
  139. while (--cpu >= 0) {
  140. dev = per_cpu(cpuidle_devices, cpu);
  141. drv = cpuidle_get_cpu_driver(dev);
  142. cpuidle_unregister_device(dev);
  143. cpuidle_unregister_driver(drv);
  144. kfree(dev);
  145. kfree(drv);
  146. }
  147. return ret;
  148. }
  149. device_initcall(arm_idle_init);