cpuidle.c 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /* linux/arch/arm/mach-exynos4/cpuidle.c
  2. *
  3. * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  4. * http://www.samsung.com
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/init.h>
  12. #include <linux/cpuidle.h>
  13. #include <linux/io.h>
  14. #include <linux/export.h>
  15. #include <linux/time.h>
  16. #include <asm/proc-fns.h>
  17. static int exynos4_enter_idle(struct cpuidle_device *dev,
  18. struct cpuidle_driver *drv,
  19. int index);
  20. static struct cpuidle_state exynos4_cpuidle_set[] = {
  21. [0] = {
  22. .enter = exynos4_enter_idle,
  23. .exit_latency = 1,
  24. .target_residency = 100000,
  25. .flags = CPUIDLE_FLAG_TIME_VALID,
  26. .name = "IDLE",
  27. .desc = "ARM clock gating(WFI)",
  28. },
  29. };
  30. static DEFINE_PER_CPU(struct cpuidle_device, exynos4_cpuidle_device);
  31. static struct cpuidle_driver exynos4_idle_driver = {
  32. .name = "exynos4_idle",
  33. .owner = THIS_MODULE,
  34. };
  35. static int exynos4_enter_idle(struct cpuidle_device *dev,
  36. struct cpuidle_driver *drv,
  37. int index)
  38. {
  39. struct timeval before, after;
  40. int idle_time;
  41. local_irq_disable();
  42. do_gettimeofday(&before);
  43. cpu_do_idle();
  44. do_gettimeofday(&after);
  45. local_irq_enable();
  46. idle_time = (after.tv_sec - before.tv_sec) * USEC_PER_SEC +
  47. (after.tv_usec - before.tv_usec);
  48. dev->last_residency = idle_time;
  49. return index;
  50. }
  51. static int __init exynos4_init_cpuidle(void)
  52. {
  53. int i, max_cpuidle_state, cpu_id;
  54. struct cpuidle_device *device;
  55. struct cpuidle_driver *drv = &exynos4_idle_driver;
  56. /* Setup cpuidle driver */
  57. drv->state_count = (sizeof(exynos4_cpuidle_set) /
  58. sizeof(struct cpuidle_state));
  59. max_cpuidle_state = drv->state_count;
  60. for (i = 0; i < max_cpuidle_state; i++) {
  61. memcpy(&drv->states[i], &exynos4_cpuidle_set[i],
  62. sizeof(struct cpuidle_state));
  63. }
  64. cpuidle_register_driver(&exynos4_idle_driver);
  65. for_each_cpu(cpu_id, cpu_online_mask) {
  66. device = &per_cpu(exynos4_cpuidle_device, cpu_id);
  67. device->cpu = cpu_id;
  68. device->state_count = drv->state_count;
  69. if (cpuidle_register_device(device)) {
  70. printk(KERN_ERR "CPUidle register device failed\n,");
  71. return -EIO;
  72. }
  73. }
  74. return 0;
  75. }
  76. device_initcall(exynos4_init_cpuidle);