exynos-cpufreq.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  3. * http://www.samsung.com
  4. *
  5. * EXYNOS - CPU frequency scaling support for EXYNOS series
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/err.h>
  13. #include <linux/clk.h>
  14. #include <linux/io.h>
  15. #include <linux/slab.h>
  16. #include <linux/regulator/consumer.h>
  17. #include <linux/cpufreq.h>
  18. #include <linux/platform_device.h>
  19. #include <linux/of.h>
  20. #include <linux/cpu_cooling.h>
  21. #include <linux/cpu.h>
  22. #include "exynos-cpufreq.h"
  23. static struct exynos_dvfs_info *exynos_info;
  24. static struct thermal_cooling_device *cdev;
  25. static struct regulator *arm_regulator;
  26. static unsigned int locking_frequency;
  27. static int exynos_cpufreq_get_index(unsigned int freq)
  28. {
  29. struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
  30. struct cpufreq_frequency_table *pos;
  31. cpufreq_for_each_entry(pos, freq_table)
  32. if (pos->frequency == freq)
  33. break;
  34. if (pos->frequency == CPUFREQ_TABLE_END)
  35. return -EINVAL;
  36. return pos - freq_table;
  37. }
  38. static int exynos_cpufreq_scale(unsigned int target_freq)
  39. {
  40. struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
  41. unsigned int *volt_table = exynos_info->volt_table;
  42. struct cpufreq_policy *policy = cpufreq_cpu_get(0);
  43. unsigned int arm_volt, safe_arm_volt = 0;
  44. unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz;
  45. struct device *dev = exynos_info->dev;
  46. unsigned int old_freq;
  47. int index, old_index;
  48. int ret = 0;
  49. old_freq = policy->cur;
  50. /*
  51. * The policy max have been changed so that we cannot get proper
  52. * old_index with cpufreq_frequency_table_target(). Thus, ignore
  53. * policy and get the index from the raw frequency table.
  54. */
  55. old_index = exynos_cpufreq_get_index(old_freq);
  56. if (old_index < 0) {
  57. ret = old_index;
  58. goto out;
  59. }
  60. index = exynos_cpufreq_get_index(target_freq);
  61. if (index < 0) {
  62. ret = index;
  63. goto out;
  64. }
  65. /*
  66. * ARM clock source will be changed APLL to MPLL temporary
  67. * To support this level, need to control regulator for
  68. * required voltage level
  69. */
  70. if (exynos_info->need_apll_change != NULL) {
  71. if (exynos_info->need_apll_change(old_index, index) &&
  72. (freq_table[index].frequency < mpll_freq_khz) &&
  73. (freq_table[old_index].frequency < mpll_freq_khz))
  74. safe_arm_volt = volt_table[exynos_info->pll_safe_idx];
  75. }
  76. arm_volt = volt_table[index];
  77. /* When the new frequency is higher than current frequency */
  78. if ((target_freq > old_freq) && !safe_arm_volt) {
  79. /* Firstly, voltage up to increase frequency */
  80. ret = regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
  81. if (ret) {
  82. dev_err(dev, "failed to set cpu voltage to %d\n",
  83. arm_volt);
  84. return ret;
  85. }
  86. }
  87. if (safe_arm_volt) {
  88. ret = regulator_set_voltage(arm_regulator, safe_arm_volt,
  89. safe_arm_volt);
  90. if (ret) {
  91. dev_err(dev, "failed to set cpu voltage to %d\n",
  92. safe_arm_volt);
  93. return ret;
  94. }
  95. }
  96. exynos_info->set_freq(old_index, index);
  97. /* When the new frequency is lower than current frequency */
  98. if ((target_freq < old_freq) ||
  99. ((target_freq > old_freq) && safe_arm_volt)) {
  100. /* down the voltage after frequency change */
  101. ret = regulator_set_voltage(arm_regulator, arm_volt,
  102. arm_volt);
  103. if (ret) {
  104. dev_err(dev, "failed to set cpu voltage to %d\n",
  105. arm_volt);
  106. goto out;
  107. }
  108. }
  109. out:
  110. cpufreq_cpu_put(policy);
  111. return ret;
  112. }
  113. static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
  114. {
  115. return exynos_cpufreq_scale(exynos_info->freq_table[index].frequency);
  116. }
  117. static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
  118. {
  119. policy->clk = exynos_info->cpu_clk;
  120. policy->suspend_freq = locking_frequency;
  121. return cpufreq_generic_init(policy, exynos_info->freq_table, 100000);
  122. }
  123. static struct cpufreq_driver exynos_driver = {
  124. .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
  125. .verify = cpufreq_generic_frequency_table_verify,
  126. .target_index = exynos_target,
  127. .get = cpufreq_generic_get,
  128. .init = exynos_cpufreq_cpu_init,
  129. .name = "exynos_cpufreq",
  130. .attr = cpufreq_generic_attr,
  131. #ifdef CONFIG_ARM_EXYNOS_CPU_FREQ_BOOST_SW
  132. .boost_supported = true,
  133. #endif
  134. #ifdef CONFIG_PM
  135. .suspend = cpufreq_generic_suspend,
  136. #endif
  137. };
  138. static int exynos_cpufreq_probe(struct platform_device *pdev)
  139. {
  140. struct device_node *cpu0;
  141. int ret = -EINVAL;
  142. exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL);
  143. if (!exynos_info)
  144. return -ENOMEM;
  145. exynos_info->dev = &pdev->dev;
  146. if (of_machine_is_compatible("samsung,exynos4210")) {
  147. exynos_info->type = EXYNOS_SOC_4210;
  148. ret = exynos4210_cpufreq_init(exynos_info);
  149. } else if (of_machine_is_compatible("samsung,exynos4212")) {
  150. exynos_info->type = EXYNOS_SOC_4212;
  151. ret = exynos4x12_cpufreq_init(exynos_info);
  152. } else if (of_machine_is_compatible("samsung,exynos4412")) {
  153. exynos_info->type = EXYNOS_SOC_4412;
  154. ret = exynos4x12_cpufreq_init(exynos_info);
  155. } else if (of_machine_is_compatible("samsung,exynos5250")) {
  156. exynos_info->type = EXYNOS_SOC_5250;
  157. ret = exynos5250_cpufreq_init(exynos_info);
  158. } else {
  159. pr_err("%s: Unknown SoC type\n", __func__);
  160. return -ENODEV;
  161. }
  162. if (ret)
  163. goto err_vdd_arm;
  164. if (exynos_info->set_freq == NULL) {
  165. dev_err(&pdev->dev, "No set_freq function (ERR)\n");
  166. goto err_vdd_arm;
  167. }
  168. arm_regulator = regulator_get(NULL, "vdd_arm");
  169. if (IS_ERR(arm_regulator)) {
  170. dev_err(&pdev->dev, "failed to get resource vdd_arm\n");
  171. goto err_vdd_arm;
  172. }
  173. /* Done here as we want to capture boot frequency */
  174. locking_frequency = clk_get_rate(exynos_info->cpu_clk) / 1000;
  175. ret = cpufreq_register_driver(&exynos_driver);
  176. if (ret)
  177. goto err_cpufreq_reg;
  178. cpu0 = of_get_cpu_node(0, NULL);
  179. if (!cpu0) {
  180. pr_err("failed to find cpu0 node\n");
  181. return 0;
  182. }
  183. if (of_find_property(cpu0, "#cooling-cells", NULL)) {
  184. cdev = of_cpufreq_cooling_register(cpu0,
  185. cpu_present_mask);
  186. if (IS_ERR(cdev))
  187. pr_err("running cpufreq without cooling device: %ld\n",
  188. PTR_ERR(cdev));
  189. }
  190. return 0;
  191. err_cpufreq_reg:
  192. dev_err(&pdev->dev, "failed to register cpufreq driver\n");
  193. regulator_put(arm_regulator);
  194. err_vdd_arm:
  195. kfree(exynos_info);
  196. return -EINVAL;
  197. }
  198. static struct platform_driver exynos_cpufreq_platdrv = {
  199. .driver = {
  200. .name = "exynos-cpufreq",
  201. },
  202. .probe = exynos_cpufreq_probe,
  203. };
  204. module_platform_driver(exynos_cpufreq_platdrv);