098-3-add-fab-scaling-support-with-cpufreq.patch 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. --- a/drivers/clk/qcom/Makefile
  2. +++ b/drivers/clk/qcom/Makefile
  3. @@ -15,6 +15,7 @@ clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-k
  4. clk-qcom-y += clk-hfpll.o
  5. clk-qcom-y += reset.o
  6. clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
  7. +clk-qcom-y += fab_scaling.o
  8. # Keep alphabetically sorted by config
  9. obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
  10. --- /dev/null
  11. +++ b/drivers/clk/qcom/fab_scaling.c
  12. @@ -0,0 +1,172 @@
  13. +/*
  14. + * Copyright (c) 2015, The Linux Foundation. All rights reserved.
  15. + *
  16. + * Permission to use, copy, modify, and/or distribute this software for any
  17. + * purpose with or without fee is hereby granted, provided that the above
  18. + * copyright notice and this permission notice appear in all copies.
  19. + *
  20. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  21. + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  22. + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  23. + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  24. + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  25. + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  26. + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  27. + */
  28. +
  29. +#include <linux/kernel.h>
  30. +#include <linux/init.h>
  31. +#include <linux/module.h>
  32. +#include <linux/platform_device.h>
  33. +#include <linux/err.h>
  34. +#include <linux/io.h>
  35. +#include <linux/of.h>
  36. +#include <linux/of_device.h>
  37. +#include <linux/clk.h>
  38. +#include <linux/clk-provider.h>
  39. +#include <linux/slab.h>
  40. +#include <linux/fab_scaling.h>
  41. +
  42. +struct qcom_fab_scaling_data {
  43. + u32 fab_freq_high;
  44. + u32 fab_freq_nominal;
  45. + u32 cpu_freq_threshold;
  46. + struct clk *apps_fab_clk;
  47. + struct clk *ddr_fab_clk;
  48. +};
  49. +
  50. +static struct qcom_fab_scaling_data *drv_data;
  51. +
  52. +int scale_fabrics(unsigned long max_cpu_freq)
  53. +{
  54. + struct clk *apps_fab_clk = drv_data->apps_fab_clk,
  55. + *ddr_fab_clk = drv_data->ddr_fab_clk;
  56. + unsigned long target_freq, cur_freq;
  57. + int ret;
  58. +
  59. + /* Skip fab scaling if the driver is not ready */
  60. + if (!apps_fab_clk || !ddr_fab_clk)
  61. + return 0;
  62. +
  63. + if (max_cpu_freq > drv_data->cpu_freq_threshold)
  64. + target_freq = drv_data->fab_freq_high;
  65. + else
  66. + target_freq = drv_data->fab_freq_nominal;
  67. +
  68. + cur_freq = clk_get_rate(ddr_fab_clk);
  69. +
  70. + if (target_freq != cur_freq) {
  71. + ret = clk_set_rate(apps_fab_clk, target_freq);
  72. + if (ret)
  73. + return ret;
  74. + ret = clk_set_rate(ddr_fab_clk, target_freq);
  75. + if (ret)
  76. + return ret;
  77. + }
  78. +
  79. + return 0;
  80. +}
  81. +EXPORT_SYMBOL(scale_fabrics);
  82. +
  83. +static int ipq806x_fab_scaling_probe(struct platform_device *pdev)
  84. +{
  85. + struct device_node *np = pdev->dev.of_node;
  86. + struct clk *apps_fab_clk, *ddr_fab_clk;
  87. + int ret;
  88. +
  89. + if (!np)
  90. + return -ENODEV;
  91. +
  92. + drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
  93. + if (!drv_data)
  94. + return -ENOMEM;
  95. +
  96. + if (of_property_read_u32(np, "fab_freq_high", &drv_data->fab_freq_high)) {
  97. + pr_err("FABRICS turbo freq not found. Using defaults...\n");
  98. + drv_data->fab_freq_high = 533000000;
  99. + }
  100. +
  101. + if (of_property_read_u32(np, "fab_freq_nominal", &drv_data->fab_freq_nominal)) {
  102. + pr_err("FABRICS nominal freq not found. Using defaults...\n");
  103. + drv_data->fab_freq_nominal = 400000000;
  104. + }
  105. +
  106. + if (of_property_read_u32(np, "cpu_freq_threshold", &drv_data->cpu_freq_threshold)) {
  107. + pr_err("FABRICS cpu freq threshold not found. Using defaults...\n");
  108. + drv_data->cpu_freq_threshold = 1000000000;
  109. + }
  110. +
  111. + apps_fab_clk = devm_clk_get(&pdev->dev, "apps-fab-clk");
  112. + ret = PTR_ERR_OR_ZERO(apps_fab_clk);
  113. + if (ret) {
  114. + /*
  115. + * If apps fab clk node is present, but clock is not yet
  116. + * registered, we should try defering probe.
  117. + */
  118. + if (ret != -EPROBE_DEFER) {
  119. + pr_err("Failed to get APPS FABRIC clock: %d\n", ret);
  120. + ret = -ENODEV;
  121. + }
  122. + goto err;
  123. + }
  124. +
  125. + clk_prepare_enable(apps_fab_clk);
  126. + clk_set_rate(apps_fab_clk, drv_data->fab_freq_high);
  127. + drv_data->apps_fab_clk = apps_fab_clk;
  128. +
  129. + ddr_fab_clk = devm_clk_get(&pdev->dev, "ddr-fab-clk");
  130. + ret = PTR_ERR_OR_ZERO(ddr_fab_clk);
  131. + if (ret) {
  132. + /*
  133. + * If ddr fab clk node is present, but clock is not yet
  134. + * registered, we should try defering probe.
  135. + */
  136. + if (ret != -EPROBE_DEFER) {
  137. + pr_err("Failed to get DDR FABRIC clock: %d\n", ret);
  138. + ddr_fab_clk = NULL;
  139. + ret = -ENODEV;
  140. + }
  141. + goto err;
  142. + }
  143. +
  144. + clk_prepare_enable(ddr_fab_clk);
  145. + clk_set_rate(ddr_fab_clk, drv_data->fab_freq_high);
  146. + drv_data->ddr_fab_clk = ddr_fab_clk;
  147. +
  148. + return 0;
  149. +err:
  150. + kfree(drv_data);
  151. + return ret;
  152. +}
  153. +
  154. +static int ipq806x_fab_scaling_remove(struct platform_device *pdev)
  155. +{
  156. + kfree(drv_data);
  157. + return 0;
  158. +}
  159. +
  160. +static const struct of_device_id fab_scaling_ipq806x_match_table[] = {
  161. + { .compatible = "qcom,fab-scaling" },
  162. + { }
  163. +};
  164. +
  165. +static struct platform_driver fab_scaling_ipq806x_driver = {
  166. + .probe = ipq806x_fab_scaling_probe,
  167. + .remove = ipq806x_fab_scaling_remove,
  168. + .driver = {
  169. + .name = "fab-scaling",
  170. + .of_match_table = fab_scaling_ipq806x_match_table,
  171. + },
  172. +};
  173. +
  174. +static int __init fab_scaling_ipq806x_init(void)
  175. +{
  176. + return platform_driver_register(&fab_scaling_ipq806x_driver);
  177. +}
  178. +late_initcall(fab_scaling_ipq806x_init);
  179. +
  180. +static void __exit fab_scaling_ipq806x_exit(void)
  181. +{
  182. + platform_driver_unregister(&fab_scaling_ipq806x_driver);
  183. +}
  184. +module_exit(fab_scaling_ipq806x_exit);
  185. --- /dev/null
  186. +++ b/include/linux/fab_scaling.h
  187. @@ -0,0 +1,31 @@
  188. +/*
  189. + * Copyright (c) 2015, The Linux Foundation. All rights reserved.
  190. + *
  191. + * Permission to use, copy, modify, and/or distribute this software for any
  192. + * purpose with or without fee is hereby granted, provided that the above
  193. + * copyright notice and this permission notice appear in all copies.
  194. + *
  195. + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  196. + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  197. + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  198. + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  199. + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  200. + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  201. + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  202. + */
  203. +
  204. +
  205. +#ifndef __FAB_SCALING_H
  206. +#define __FAB_SCALING_H
  207. +
  208. +/**
  209. + * scale_fabrics - Scale DDR and APPS FABRICS
  210. + *
  211. + * This function monitors all the registered clocks and does APPS
  212. + * and DDR FABRIC scaling based on the idle frequencies with which
  213. + * it was registered.
  214. + *
  215. + */
  216. +int scale_fabrics(unsigned long max_cpu_freq);
  217. +
  218. +#endif
  219. --- a/drivers/cpufreq/qcom-cpufreq-krait.c
  220. +++ b/drivers/cpufreq/qcom-cpufreq-krait.c
  221. @@ -15,6 +15,7 @@
  222. #include <linux/regulator/consumer.h>
  223. #include <linux/slab.h>
  224. #include <linux/thermal.h>
  225. +#include <linux/fab_scaling.h>
  226. #include "cpufreq-dt.h"
  227. @@ -74,6 +75,13 @@ static int set_target(struct cpufreq_pol
  228. goto l2_scale_fail;
  229. }
  230. + /*
  231. + * Scale fabrics with max freq across all cores
  232. + */
  233. + ret = scale_fabrics(target_freq);
  234. + if (ret)
  235. + goto l2_scale_fail;
  236. +
  237. opp = dev_pm_opp_find_level_exact(l2_dev, level);
  238. if (IS_ERR(opp)) {
  239. dev_err(l2_dev,