cpufreq_gov_msm.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/kernel.h>
  14. #include <linux/init.h>
  15. #include <linux/module.h>
  16. #include <linux/mutex.h>
  17. #include <linux/kobject.h>
  18. #include <linux/cpufreq.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/cpu_pm.h>
  21. #include <linux/pm_qos.h>
  22. #include <linux/hrtimer.h>
  23. #include <linux/tick.h>
  24. #include <mach/msm_dcvs.h>
  25. struct cpu_idle_info {
  26. int enabled;
  27. int dcvs_core_id;
  28. struct pm_qos_request pm_qos_req;
  29. };
  30. static DEFINE_PER_CPU_SHARED_ALIGNED(struct cpu_idle_info, cpu_idle_info);
  31. static DEFINE_PER_CPU_SHARED_ALIGNED(u64, iowait_on_cpu);
  32. static uint32_t latency;
  33. static int msm_dcvs_idle_notifier(int core_num,
  34. enum msm_core_control_event event)
  35. {
  36. struct cpu_idle_info *info = &per_cpu(cpu_idle_info, core_num);
  37. switch (event) {
  38. case MSM_DCVS_ENABLE_IDLE_PULSE:
  39. info->enabled = true;
  40. break;
  41. case MSM_DCVS_DISABLE_IDLE_PULSE:
  42. info->enabled = false;
  43. break;
  44. case MSM_DCVS_ENABLE_HIGH_LATENCY_MODES:
  45. pm_qos_update_request(&info->pm_qos_req, PM_QOS_DEFAULT_VALUE);
  46. break;
  47. case MSM_DCVS_DISABLE_HIGH_LATENCY_MODES:
  48. pm_qos_update_request(&info->pm_qos_req, latency);
  49. break;
  50. }
  51. return 0;
  52. }
  53. static int msm_cpuidle_notifier(struct notifier_block *self, unsigned long cmd,
  54. void *v)
  55. {
  56. struct cpu_idle_info *info =
  57. &per_cpu(cpu_idle_info, smp_processor_id());
  58. u64 io_wait_us = 0;
  59. u64 prev_io_wait_us = 0;
  60. u64 last_update_time = 0;
  61. u64 val = 0;
  62. uint32_t iowaited = 0;
  63. if (!info->enabled)
  64. return NOTIFY_OK;
  65. switch (cmd) {
  66. case CPU_PM_ENTER:
  67. val = get_cpu_iowait_time_us(smp_processor_id(),
  68. &last_update_time);
  69. /* val could be -1 when NOHZ is not enabled */
  70. if (val == (u64)-1)
  71. val = 0;
  72. per_cpu(iowait_on_cpu, smp_processor_id()) = val;
  73. msm_dcvs_idle(info->dcvs_core_id, MSM_DCVS_IDLE_ENTER, 0);
  74. break;
  75. case CPU_PM_EXIT:
  76. prev_io_wait_us = per_cpu(iowait_on_cpu, smp_processor_id());
  77. val = get_cpu_iowait_time_us(smp_processor_id(),
  78. &last_update_time);
  79. if (val == (u64)-1)
  80. val = 0;
  81. io_wait_us = val;
  82. iowaited = (io_wait_us - prev_io_wait_us);
  83. msm_dcvs_idle(info->dcvs_core_id, MSM_DCVS_IDLE_EXIT, iowaited);
  84. break;
  85. }
  86. return NOTIFY_OK;
  87. }
  88. static struct notifier_block idle_nb = {
  89. .notifier_call = msm_cpuidle_notifier,
  90. };
  91. static void msm_gov_idle_source_init(int cpu, int dcvs_core_id)
  92. {
  93. struct cpu_idle_info *info = NULL;
  94. info = &per_cpu(cpu_idle_info, cpu);
  95. info->dcvs_core_id = dcvs_core_id;
  96. pm_qos_add_request(&info->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
  97. PM_QOS_DEFAULT_VALUE);
  98. }
  99. struct msm_gov {
  100. int cpu;
  101. unsigned int cur_freq;
  102. unsigned int min_freq;
  103. unsigned int max_freq;
  104. struct cpufreq_policy *policy;
  105. int dcvs_core_id;
  106. };
  107. static DEFINE_PER_CPU_SHARED_ALIGNED(struct mutex, gov_mutex);
  108. static DEFINE_PER_CPU_SHARED_ALIGNED(struct msm_gov, msm_gov_info);
  109. static void msm_gov_check_limits(struct cpufreq_policy *policy)
  110. {
  111. struct msm_gov *gov = &per_cpu(msm_gov_info, policy->cpu);
  112. if (policy->max < gov->cur_freq)
  113. __cpufreq_driver_target(policy, policy->max,
  114. CPUFREQ_RELATION_H);
  115. else if (policy->min > gov->cur_freq)
  116. __cpufreq_driver_target(policy, policy->min,
  117. CPUFREQ_RELATION_L);
  118. else
  119. __cpufreq_driver_target(policy, gov->cur_freq,
  120. CPUFREQ_RELATION_L);
  121. gov->cur_freq = policy->cur;
  122. gov->min_freq = policy->min;
  123. gov->max_freq = policy->max;
  124. msm_dcvs_update_limits(gov->dcvs_core_id);
  125. }
  126. static int msm_dcvs_freq_set(int core_num,
  127. unsigned int freq)
  128. {
  129. int ret = -EINVAL;
  130. struct msm_gov *gov = &per_cpu(msm_gov_info, core_num);
  131. mutex_lock(&per_cpu(gov_mutex, gov->cpu));
  132. if (freq < gov->min_freq)
  133. freq = gov->min_freq;
  134. if (freq > gov->max_freq)
  135. freq = gov->max_freq;
  136. mutex_unlock(&per_cpu(gov_mutex, gov->cpu));
  137. ret = cpufreq_driver_target(gov->policy, freq, CPUFREQ_RELATION_L);
  138. if (!ret) {
  139. gov->cur_freq = cpufreq_quick_get(gov->cpu);
  140. if (freq != gov->cur_freq)
  141. pr_err("cpu %d freq %u gov->cur_freq %u didn't match",
  142. gov->cpu, freq, gov->cur_freq);
  143. }
  144. ret = gov->cur_freq;
  145. return ret;
  146. }
  147. static unsigned int msm_dcvs_freq_get(int core_num)
  148. {
  149. struct msm_gov *gov = &per_cpu(msm_gov_info, core_num);
  150. /*
  151. * the rw_sem in cpufreq is always held when this is called.
  152. * The policy->cur won't be updated in this case - so it is safe to
  153. * access policy->cur
  154. */
  155. return gov->policy->cur;
  156. }
  157. static int cpufreq_governor_msm(struct cpufreq_policy *policy,
  158. unsigned int event)
  159. {
  160. unsigned int cpu = policy->cpu;
  161. int ret = 0;
  162. int handle = 0;
  163. struct msm_gov *gov = &per_cpu(msm_gov_info, policy->cpu);
  164. switch (event) {
  165. case CPUFREQ_GOV_START:
  166. if (!cpu_online(cpu))
  167. return -EINVAL;
  168. BUG_ON(!policy->cur);
  169. mutex_lock(&per_cpu(gov_mutex, cpu));
  170. per_cpu(msm_gov_info, cpu).cpu = cpu;
  171. gov->policy = policy;
  172. handle = msm_dcvs_freq_sink_start(gov->dcvs_core_id);
  173. BUG_ON(handle < 0);
  174. msm_gov_check_limits(policy);
  175. mutex_unlock(&per_cpu(gov_mutex, cpu));
  176. break;
  177. case CPUFREQ_GOV_STOP:
  178. msm_dcvs_freq_sink_stop(gov->dcvs_core_id);
  179. break;
  180. case CPUFREQ_GOV_LIMITS:
  181. mutex_lock(&per_cpu(gov_mutex, cpu));
  182. msm_gov_check_limits(policy);
  183. mutex_unlock(&per_cpu(gov_mutex, cpu));
  184. break;
  185. };
  186. return ret;
  187. }
  188. struct cpufreq_governor cpufreq_gov_msm = {
  189. .name = "msm-dcvs",
  190. .governor = cpufreq_governor_msm,
  191. .owner = THIS_MODULE,
  192. };
  193. static int __devinit msm_gov_probe(struct platform_device *pdev)
  194. {
  195. int cpu;
  196. struct msm_dcvs_core_info *core = NULL;
  197. struct msm_dcvs_core_info *core_info = NULL;
  198. struct msm_gov_platform_data *pdata = pdev->dev.platform_data;
  199. int sensor = 0;
  200. core = pdev->dev.platform_data;
  201. core_info = pdata->info;
  202. latency = pdata->latency;
  203. for_each_possible_cpu(cpu) {
  204. struct msm_gov *gov = &per_cpu(msm_gov_info, cpu);
  205. mutex_init(&per_cpu(gov_mutex, cpu));
  206. if (cpu < core->num_cores)
  207. sensor = core_info->sensors[cpu];
  208. gov->dcvs_core_id = msm_dcvs_register_core(
  209. MSM_DCVS_CORE_TYPE_CPU,
  210. cpu,
  211. core_info,
  212. msm_dcvs_freq_set,
  213. msm_dcvs_freq_get,
  214. msm_dcvs_idle_notifier,
  215. NULL,
  216. sensor);
  217. if (gov->dcvs_core_id < 0) {
  218. pr_err("Unable to register core for %d\n", cpu);
  219. return -EINVAL;
  220. }
  221. msm_gov_idle_source_init(cpu, gov->dcvs_core_id);
  222. }
  223. cpu_pm_register_notifier(&idle_nb);
  224. return cpufreq_register_governor(&cpufreq_gov_msm);
  225. }
  226. static int __devexit msm_gov_remove(struct platform_device *pdev)
  227. {
  228. platform_set_drvdata(pdev, NULL);
  229. return 0;
  230. }
  231. static struct platform_driver msm_gov_driver = {
  232. .probe = msm_gov_probe,
  233. .remove = __devexit_p(msm_gov_remove),
  234. .driver = {
  235. .name = "msm_dcvs_gov",
  236. .owner = THIS_MODULE,
  237. },
  238. };
  239. static int __init cpufreq_gov_msm_init(void)
  240. {
  241. return platform_driver_register(&msm_gov_driver);
  242. }
  243. late_initcall(cpufreq_gov_msm_init);