cpuidle-cps.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * Copyright (C) 2014 Imagination Technologies
  3. * Author: Paul Burton <paul.burton@imgtec.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. */
  10. #include <linux/cpu_pm.h>
  11. #include <linux/cpuidle.h>
  12. #include <linux/init.h>
  13. #include <asm/idle.h>
  14. #include <asm/pm-cps.h>
  15. /* Enumeration of the various idle states this driver may enter */
  16. enum cps_idle_state {
  17. STATE_WAIT = 0, /* MIPS wait instruction, coherent */
  18. STATE_NC_WAIT, /* MIPS wait instruction, non-coherent */
  19. STATE_CLOCK_GATED, /* Core clock gated */
  20. STATE_POWER_GATED, /* Core power gated */
  21. STATE_COUNT
  22. };
  23. static int cps_nc_enter(struct cpuidle_device *dev,
  24. struct cpuidle_driver *drv, int index)
  25. {
  26. enum cps_pm_state pm_state;
  27. int err;
  28. /*
  29. * At least one core must remain powered up & clocked in order for the
  30. * system to have any hope of functioning.
  31. *
  32. * TODO: don't treat core 0 specially, just prevent the final core
  33. * TODO: remap interrupt affinity temporarily
  34. */
  35. if (!cpu_data[dev->cpu].core && (index > STATE_NC_WAIT))
  36. index = STATE_NC_WAIT;
  37. /* Select the appropriate cps_pm_state */
  38. switch (index) {
  39. case STATE_NC_WAIT:
  40. pm_state = CPS_PM_NC_WAIT;
  41. break;
  42. case STATE_CLOCK_GATED:
  43. pm_state = CPS_PM_CLOCK_GATED;
  44. break;
  45. case STATE_POWER_GATED:
  46. pm_state = CPS_PM_POWER_GATED;
  47. break;
  48. default:
  49. BUG();
  50. return -EINVAL;
  51. }
  52. /* Notify listeners the CPU is about to power down */
  53. if ((pm_state == CPS_PM_POWER_GATED) && cpu_pm_enter())
  54. return -EINTR;
  55. /* Enter that state */
  56. err = cps_pm_enter_state(pm_state);
  57. /* Notify listeners the CPU is back up */
  58. if (pm_state == CPS_PM_POWER_GATED)
  59. cpu_pm_exit();
  60. return err ?: index;
  61. }
  62. static struct cpuidle_driver cps_driver = {
  63. .name = "cpc_cpuidle",
  64. .owner = THIS_MODULE,
  65. .states = {
  66. [STATE_WAIT] = MIPS_CPUIDLE_WAIT_STATE,
  67. [STATE_NC_WAIT] = {
  68. .enter = cps_nc_enter,
  69. .exit_latency = 200,
  70. .target_residency = 450,
  71. .flags = CPUIDLE_FLAG_TIME_VALID,
  72. .name = "nc-wait",
  73. .desc = "non-coherent MIPS wait",
  74. },
  75. [STATE_CLOCK_GATED] = {
  76. .enter = cps_nc_enter,
  77. .exit_latency = 300,
  78. .target_residency = 700,
  79. .flags = CPUIDLE_FLAG_TIME_VALID |
  80. CPUIDLE_FLAG_TIMER_STOP,
  81. .name = "clock-gated",
  82. .desc = "core clock gated",
  83. },
  84. [STATE_POWER_GATED] = {
  85. .enter = cps_nc_enter,
  86. .exit_latency = 600,
  87. .target_residency = 1000,
  88. .flags = CPUIDLE_FLAG_TIME_VALID |
  89. CPUIDLE_FLAG_TIMER_STOP,
  90. .name = "power-gated",
  91. .desc = "core power gated",
  92. },
  93. },
  94. .state_count = STATE_COUNT,
  95. .safe_state_index = 0,
  96. };
  97. static void __init cps_cpuidle_unregister(void)
  98. {
  99. int cpu;
  100. struct cpuidle_device *device;
  101. for_each_possible_cpu(cpu) {
  102. device = &per_cpu(cpuidle_dev, cpu);
  103. cpuidle_unregister_device(device);
  104. }
  105. cpuidle_unregister_driver(&cps_driver);
  106. }
  107. static int __init cps_cpuidle_init(void)
  108. {
  109. int err, cpu, core, i;
  110. struct cpuidle_device *device;
  111. /* Detect supported states */
  112. if (!cps_pm_support_state(CPS_PM_POWER_GATED))
  113. cps_driver.state_count = STATE_CLOCK_GATED + 1;
  114. if (!cps_pm_support_state(CPS_PM_CLOCK_GATED))
  115. cps_driver.state_count = STATE_NC_WAIT + 1;
  116. if (!cps_pm_support_state(CPS_PM_NC_WAIT))
  117. cps_driver.state_count = STATE_WAIT + 1;
  118. /* Inform the user if some states are unavailable */
  119. if (cps_driver.state_count < STATE_COUNT) {
  120. pr_info("cpuidle-cps: limited to ");
  121. switch (cps_driver.state_count - 1) {
  122. case STATE_WAIT:
  123. pr_cont("coherent wait\n");
  124. break;
  125. case STATE_NC_WAIT:
  126. pr_cont("non-coherent wait\n");
  127. break;
  128. case STATE_CLOCK_GATED:
  129. pr_cont("clock gating\n");
  130. break;
  131. }
  132. }
  133. /*
  134. * Set the coupled flag on the appropriate states if this system
  135. * requires it.
  136. */
  137. if (coupled_coherence)
  138. for (i = STATE_NC_WAIT; i < cps_driver.state_count; i++)
  139. cps_driver.states[i].flags |= CPUIDLE_FLAG_COUPLED;
  140. err = cpuidle_register_driver(&cps_driver);
  141. if (err) {
  142. pr_err("Failed to register CPS cpuidle driver\n");
  143. return err;
  144. }
  145. for_each_possible_cpu(cpu) {
  146. core = cpu_data[cpu].core;
  147. device = &per_cpu(cpuidle_dev, cpu);
  148. device->cpu = cpu;
  149. #ifdef CONFIG_MIPS_MT
  150. cpumask_copy(&device->coupled_cpus, &cpu_sibling_map[cpu]);
  151. #endif
  152. err = cpuidle_register_device(device);
  153. if (err) {
  154. pr_err("Failed to register CPU%d cpuidle device\n",
  155. cpu);
  156. goto err_out;
  157. }
  158. }
  159. return 0;
  160. err_out:
  161. cps_cpuidle_unregister();
  162. return err;
  163. }
  164. device_initcall(cps_cpuidle_init);