cpuidle.c 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. * arch/arm/mach-kirkwood/cpuidle.c
  3. *
  4. * CPU idle Marvell Kirkwood SoCs
  5. *
  6. * This file is licensed under the terms of the GNU General Public
  7. * License version 2. This program is licensed "as is" without any
  8. * warranty of any kind, whether express or implied.
  9. *
  10. * The cpu idle uses wait-for-interrupt and DDR self refresh in order
  11. * to implement two idle states -
  12. * #1 wait-for-interrupt
  13. * #2 wait-for-interrupt and DDR self refresh
  14. */
  15. #include <linux/kernel.h>
  16. #include <linux/init.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/cpuidle.h>
  19. #include <linux/io.h>
  20. #include <linux/export.h>
  21. #include <asm/proc-fns.h>
  22. #include <mach/kirkwood.h>
  23. #define KIRKWOOD_MAX_STATES 2
  24. static struct cpuidle_driver kirkwood_idle_driver = {
  25. .name = "kirkwood_idle",
  26. .owner = THIS_MODULE,
  27. };
  28. static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
  29. /* Actual code that puts the SoC in different idle states */
  30. static int kirkwood_enter_idle(struct cpuidle_device *dev,
  31. struct cpuidle_state *state)
  32. {
  33. struct timeval before, after;
  34. int idle_time;
  35. local_irq_disable();
  36. do_gettimeofday(&before);
  37. if (state == &dev->states[0])
  38. /* Wait for interrupt state */
  39. cpu_do_idle();
  40. else if (state == &dev->states[1]) {
  41. /*
  42. * Following write will put DDR in self refresh.
  43. * Note that we have 256 cycles before DDR puts it
  44. * self in self-refresh, so the wait-for-interrupt
  45. * call afterwards won't get the DDR from self refresh
  46. * mode.
  47. */
  48. writel(0x7, DDR_OPERATION_BASE);
  49. cpu_do_idle();
  50. }
  51. do_gettimeofday(&after);
  52. local_irq_enable();
  53. idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
  54. (after.tv_usec - before.tv_usec);
  55. return idle_time;
  56. }
  57. /* Initialize CPU idle by registering the idle states */
  58. static int kirkwood_init_cpuidle(void)
  59. {
  60. struct cpuidle_device *device;
  61. cpuidle_register_driver(&kirkwood_idle_driver);
  62. device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
  63. device->state_count = KIRKWOOD_MAX_STATES;
  64. /* Wait for interrupt state */
  65. device->states[0].enter = kirkwood_enter_idle;
  66. device->states[0].exit_latency = 1;
  67. device->states[0].target_residency = 10000;
  68. device->states[0].flags = CPUIDLE_FLAG_TIME_VALID;
  69. strcpy(device->states[0].name, "WFI");
  70. strcpy(device->states[0].desc, "Wait for interrupt");
  71. /* Wait for interrupt and DDR self refresh state */
  72. device->states[1].enter = kirkwood_enter_idle;
  73. device->states[1].exit_latency = 10;
  74. device->states[1].target_residency = 10000;
  75. device->states[1].flags = CPUIDLE_FLAG_TIME_VALID;
  76. strcpy(device->states[1].name, "DDR SR");
  77. strcpy(device->states[1].desc, "WFI and DDR Self Refresh");
  78. if (cpuidle_register_device(device)) {
  79. printk(KERN_ERR "kirkwood_init_cpuidle: Failed registering\n");
  80. return -EIO;
  81. }
  82. return 0;
  83. }
  84. device_initcall(kirkwood_init_cpuidle);