cpuidle-mvebu-v7.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. * Marvell Armada 370, 38x and XP SoC cpuidle driver
  3. *
  4. * Copyright (C) 2014 Marvell
  5. *
  6. * Nadav Haklai <nadavh@marvell.com>
  7. * Gregory CLEMENT <gregory.clement@free-electrons.com>
  8. *
  9. * This file is licensed under the terms of the GNU General Public
  10. * License version 2. This program is licensed "as is" without any
  11. * warranty of any kind, whether express or implied.
  12. *
  13. * Maintainer: Gregory CLEMENT <gregory.clement@free-electrons.com>
  14. */
  15. #include <linux/cpu_pm.h>
  16. #include <linux/cpuidle.h>
  17. #include <linux/module.h>
  18. #include <linux/of.h>
  19. #include <linux/suspend.h>
  20. #include <linux/platform_device.h>
  21. #include <asm/cpuidle.h>
  22. #define MVEBU_V7_FLAG_DEEP_IDLE 0x10000
  23. static int (*mvebu_v7_cpu_suspend)(int);
  24. static int mvebu_v7_enter_idle(struct cpuidle_device *dev,
  25. struct cpuidle_driver *drv,
  26. int index)
  27. {
  28. int ret;
  29. bool deepidle = false;
  30. cpu_pm_enter();
  31. if (drv->states[index].flags & MVEBU_V7_FLAG_DEEP_IDLE)
  32. deepidle = true;
  33. ret = mvebu_v7_cpu_suspend(deepidle);
  34. cpu_pm_exit();
  35. if (ret)
  36. return ret;
  37. return index;
  38. }
  39. static struct cpuidle_driver armadaxp_idle_driver = {
  40. .name = "armada_xp_idle",
  41. .states[0] = ARM_CPUIDLE_WFI_STATE,
  42. .states[1] = {
  43. .enter = mvebu_v7_enter_idle,
  44. .exit_latency = 100,
  45. .power_usage = 50,
  46. .target_residency = 1000,
  47. .name = "MV CPU IDLE",
  48. .desc = "CPU power down",
  49. },
  50. .states[2] = {
  51. .enter = mvebu_v7_enter_idle,
  52. .exit_latency = 1000,
  53. .power_usage = 5,
  54. .target_residency = 10000,
  55. .flags = MVEBU_V7_FLAG_DEEP_IDLE,
  56. .name = "MV CPU DEEP IDLE",
  57. .desc = "CPU and L2 Fabric power down",
  58. },
  59. .state_count = 3,
  60. };
  61. static struct cpuidle_driver armada370_idle_driver = {
  62. .name = "armada_370_idle",
  63. .states[0] = ARM_CPUIDLE_WFI_STATE,
  64. .states[1] = {
  65. .enter = mvebu_v7_enter_idle,
  66. .exit_latency = 100,
  67. .power_usage = 5,
  68. .target_residency = 1000,
  69. .flags = MVEBU_V7_FLAG_DEEP_IDLE,
  70. .name = "Deep Idle",
  71. .desc = "CPU and L2 Fabric power down",
  72. },
  73. .state_count = 2,
  74. };
  75. static struct cpuidle_driver armada38x_idle_driver = {
  76. .name = "armada_38x_idle",
  77. .states[0] = ARM_CPUIDLE_WFI_STATE,
  78. .states[1] = {
  79. .enter = mvebu_v7_enter_idle,
  80. .exit_latency = 10,
  81. .power_usage = 5,
  82. .target_residency = 100,
  83. .name = "Idle",
  84. .desc = "CPU and SCU power down",
  85. },
  86. .state_count = 2,
  87. };
  88. static int mvebu_v7_cpuidle_probe(struct platform_device *pdev)
  89. {
  90. const struct platform_device_id *id = pdev->id_entry;
  91. if (!id)
  92. return -EINVAL;
  93. mvebu_v7_cpu_suspend = pdev->dev.platform_data;
  94. return cpuidle_register((struct cpuidle_driver *)id->driver_data, NULL);
  95. }
  96. static const struct platform_device_id mvebu_cpuidle_ids[] = {
  97. {
  98. .name = "cpuidle-armada-xp",
  99. .driver_data = (unsigned long)&armadaxp_idle_driver,
  100. }, {
  101. .name = "cpuidle-armada-370",
  102. .driver_data = (unsigned long)&armada370_idle_driver,
  103. }, {
  104. .name = "cpuidle-armada-38x",
  105. .driver_data = (unsigned long)&armada38x_idle_driver,
  106. },
  107. {}
  108. };
  109. static struct platform_driver mvebu_cpuidle_driver = {
  110. .probe = mvebu_v7_cpuidle_probe,
  111. .driver = {
  112. .name = "cpuidle-mbevu",
  113. .suppress_bind_attrs = true,
  114. },
  115. .id_table = mvebu_cpuidle_ids,
  116. };
  117. builtin_platform_driver(mvebu_cpuidle_driver);
  118. MODULE_AUTHOR("Gregory CLEMENT <gregory.clement@free-electrons.com>");
  119. MODULE_DESCRIPTION("Marvell EBU v7 cpuidle driver");
  120. MODULE_LICENSE("GPL");