exynos5_bus.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  1. /*
  2. * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  3. * http://www.samsung.com/
  4. *
  5. * EXYNOS5 INT clock frequency scaling support using DEVFREQ framework
  6. * Based on work done by Jonghwan Choi <jhbird.choi@samsung.com>
  7. * Support for only EXYNOS5250 is present.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. *
  13. */
  14. #include <linux/module.h>
  15. #include <linux/devfreq.h>
  16. #include <linux/io.h>
  17. #include <linux/pm_opp.h>
  18. #include <linux/slab.h>
  19. #include <linux/suspend.h>
  20. #include <linux/clk.h>
  21. #include <linux/delay.h>
  22. #include <linux/platform_device.h>
  23. #include <linux/pm_qos.h>
  24. #include <linux/regulator/consumer.h>
  25. #include <linux/of_address.h>
  26. #include <linux/of_platform.h>
  27. #include "exynos_ppmu.h"
  28. #define MAX_SAFEVOLT 1100000 /* 1.10V */
  29. /* Assume that the bus is saturated if the utilization is 25% */
  30. #define INT_BUS_SATURATION_RATIO 25
  31. enum int_level_idx {
  32. LV_0,
  33. LV_1,
  34. LV_2,
  35. LV_3,
  36. LV_4,
  37. _LV_END
  38. };
  39. enum exynos_ppmu_list {
  40. PPMU_RIGHT,
  41. PPMU_END,
  42. };
  43. struct busfreq_data_int {
  44. struct device *dev;
  45. struct devfreq *devfreq;
  46. struct regulator *vdd_int;
  47. struct busfreq_ppmu_data ppmu_data;
  48. unsigned long curr_freq;
  49. bool disabled;
  50. struct notifier_block pm_notifier;
  51. struct mutex lock;
  52. struct pm_qos_request int_req;
  53. struct clk *int_clk;
  54. };
  55. struct int_bus_opp_table {
  56. unsigned int idx;
  57. unsigned long clk;
  58. unsigned long volt;
  59. };
  60. static struct int_bus_opp_table exynos5_int_opp_table[] = {
  61. {LV_0, 266000, 1025000},
  62. {LV_1, 200000, 1025000},
  63. {LV_2, 160000, 1025000},
  64. {LV_3, 133000, 1025000},
  65. {LV_4, 100000, 1025000},
  66. {0, 0, 0},
  67. };
  68. static int exynos5_int_setvolt(struct busfreq_data_int *data,
  69. unsigned long volt)
  70. {
  71. return regulator_set_voltage(data->vdd_int, volt, MAX_SAFEVOLT);
  72. }
  73. static int exynos5_busfreq_int_target(struct device *dev, unsigned long *_freq,
  74. u32 flags)
  75. {
  76. int err = 0;
  77. struct platform_device *pdev = container_of(dev, struct platform_device,
  78. dev);
  79. struct busfreq_data_int *data = platform_get_drvdata(pdev);
  80. struct dev_pm_opp *opp;
  81. unsigned long old_freq, freq;
  82. unsigned long volt;
  83. rcu_read_lock();
  84. opp = devfreq_recommended_opp(dev, _freq, flags);
  85. if (IS_ERR(opp)) {
  86. rcu_read_unlock();
  87. dev_err(dev, "%s: Invalid OPP.\n", __func__);
  88. return PTR_ERR(opp);
  89. }
  90. freq = dev_pm_opp_get_freq(opp);
  91. volt = dev_pm_opp_get_voltage(opp);
  92. rcu_read_unlock();
  93. old_freq = data->curr_freq;
  94. if (old_freq == freq)
  95. return 0;
  96. dev_dbg(dev, "targeting %lukHz %luuV\n", freq, volt);
  97. mutex_lock(&data->lock);
  98. if (data->disabled)
  99. goto out;
  100. if (freq > exynos5_int_opp_table[0].clk)
  101. pm_qos_update_request(&data->int_req, freq * 16 / 1000);
  102. else
  103. pm_qos_update_request(&data->int_req, -1);
  104. if (old_freq < freq)
  105. err = exynos5_int_setvolt(data, volt);
  106. if (err)
  107. goto out;
  108. err = clk_set_rate(data->int_clk, freq * 1000);
  109. if (err)
  110. goto out;
  111. if (old_freq > freq)
  112. err = exynos5_int_setvolt(data, volt);
  113. if (err)
  114. goto out;
  115. data->curr_freq = freq;
  116. out:
  117. mutex_unlock(&data->lock);
  118. return err;
  119. }
  120. static int exynos5_int_get_dev_status(struct device *dev,
  121. struct devfreq_dev_status *stat)
  122. {
  123. struct platform_device *pdev = container_of(dev, struct platform_device,
  124. dev);
  125. struct busfreq_data_int *data = platform_get_drvdata(pdev);
  126. struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
  127. int busier_dmc;
  128. exynos_read_ppmu(ppmu_data);
  129. busier_dmc = exynos_get_busier_ppmu(ppmu_data);
  130. stat->current_frequency = data->curr_freq;
  131. /* Number of cycles spent on memory access */
  132. stat->busy_time = ppmu_data->ppmu[busier_dmc].count[PPMU_PMNCNT3];
  133. stat->busy_time *= 100 / INT_BUS_SATURATION_RATIO;
  134. stat->total_time = ppmu_data->ppmu[busier_dmc].ccnt;
  135. return 0;
  136. }
  137. static struct devfreq_dev_profile exynos5_devfreq_int_profile = {
  138. .initial_freq = 160000,
  139. .polling_ms = 100,
  140. .target = exynos5_busfreq_int_target,
  141. .get_dev_status = exynos5_int_get_dev_status,
  142. };
  143. static int exynos5250_init_int_tables(struct busfreq_data_int *data)
  144. {
  145. int i, err = 0;
  146. for (i = LV_0; i < _LV_END; i++) {
  147. err = dev_pm_opp_add(data->dev, exynos5_int_opp_table[i].clk,
  148. exynos5_int_opp_table[i].volt);
  149. if (err) {
  150. dev_err(data->dev, "Cannot add opp entries.\n");
  151. return err;
  152. }
  153. }
  154. return 0;
  155. }
  156. static int exynos5_busfreq_int_pm_notifier_event(struct notifier_block *this,
  157. unsigned long event, void *ptr)
  158. {
  159. struct busfreq_data_int *data = container_of(this,
  160. struct busfreq_data_int, pm_notifier);
  161. struct dev_pm_opp *opp;
  162. unsigned long maxfreq = ULONG_MAX;
  163. unsigned long freq;
  164. unsigned long volt;
  165. int err = 0;
  166. switch (event) {
  167. case PM_SUSPEND_PREPARE:
  168. /* Set Fastest and Deactivate DVFS */
  169. mutex_lock(&data->lock);
  170. data->disabled = true;
  171. rcu_read_lock();
  172. opp = dev_pm_opp_find_freq_floor(data->dev, &maxfreq);
  173. if (IS_ERR(opp)) {
  174. rcu_read_unlock();
  175. err = PTR_ERR(opp);
  176. goto unlock;
  177. }
  178. freq = dev_pm_opp_get_freq(opp);
  179. volt = dev_pm_opp_get_voltage(opp);
  180. rcu_read_unlock();
  181. err = exynos5_int_setvolt(data, volt);
  182. if (err)
  183. goto unlock;
  184. err = clk_set_rate(data->int_clk, freq * 1000);
  185. if (err)
  186. goto unlock;
  187. data->curr_freq = freq;
  188. unlock:
  189. mutex_unlock(&data->lock);
  190. if (err)
  191. return NOTIFY_BAD;
  192. return NOTIFY_OK;
  193. case PM_POST_RESTORE:
  194. case PM_POST_SUSPEND:
  195. /* Reactivate */
  196. mutex_lock(&data->lock);
  197. data->disabled = false;
  198. mutex_unlock(&data->lock);
  199. return NOTIFY_OK;
  200. }
  201. return NOTIFY_DONE;
  202. }
  203. static int exynos5_busfreq_int_probe(struct platform_device *pdev)
  204. {
  205. struct busfreq_data_int *data;
  206. struct busfreq_ppmu_data *ppmu_data;
  207. struct dev_pm_opp *opp;
  208. struct device *dev = &pdev->dev;
  209. struct device_node *np;
  210. unsigned long initial_freq;
  211. unsigned long initial_volt;
  212. int err = 0;
  213. int i;
  214. data = devm_kzalloc(&pdev->dev, sizeof(struct busfreq_data_int),
  215. GFP_KERNEL);
  216. if (data == NULL) {
  217. dev_err(dev, "Cannot allocate memory.\n");
  218. return -ENOMEM;
  219. }
  220. ppmu_data = &data->ppmu_data;
  221. ppmu_data->ppmu_end = PPMU_END;
  222. ppmu_data->ppmu = devm_kzalloc(dev,
  223. sizeof(struct exynos_ppmu) * PPMU_END,
  224. GFP_KERNEL);
  225. if (!ppmu_data->ppmu) {
  226. dev_err(dev, "Failed to allocate memory for exynos_ppmu\n");
  227. return -ENOMEM;
  228. }
  229. np = of_find_compatible_node(NULL, NULL, "samsung,exynos5250-ppmu");
  230. if (np == NULL) {
  231. pr_err("Unable to find PPMU node\n");
  232. return -ENOENT;
  233. }
  234. for (i = 0; i < ppmu_data->ppmu_end; i++) {
  235. /* map PPMU memory region */
  236. ppmu_data->ppmu[i].hw_base = of_iomap(np, i);
  237. if (ppmu_data->ppmu[i].hw_base == NULL) {
  238. dev_err(&pdev->dev, "failed to map memory region\n");
  239. return -ENOMEM;
  240. }
  241. }
  242. data->pm_notifier.notifier_call = exynos5_busfreq_int_pm_notifier_event;
  243. data->dev = dev;
  244. mutex_init(&data->lock);
  245. err = exynos5250_init_int_tables(data);
  246. if (err)
  247. return err;
  248. data->vdd_int = devm_regulator_get(dev, "vdd_int");
  249. if (IS_ERR(data->vdd_int)) {
  250. dev_err(dev, "Cannot get the regulator \"vdd_int\"\n");
  251. return PTR_ERR(data->vdd_int);
  252. }
  253. data->int_clk = devm_clk_get(dev, "int_clk");
  254. if (IS_ERR(data->int_clk)) {
  255. dev_err(dev, "Cannot get clock \"int_clk\"\n");
  256. return PTR_ERR(data->int_clk);
  257. }
  258. rcu_read_lock();
  259. opp = dev_pm_opp_find_freq_floor(dev,
  260. &exynos5_devfreq_int_profile.initial_freq);
  261. if (IS_ERR(opp)) {
  262. rcu_read_unlock();
  263. dev_err(dev, "Invalid initial frequency %lu kHz.\n",
  264. exynos5_devfreq_int_profile.initial_freq);
  265. return PTR_ERR(opp);
  266. }
  267. initial_freq = dev_pm_opp_get_freq(opp);
  268. initial_volt = dev_pm_opp_get_voltage(opp);
  269. rcu_read_unlock();
  270. data->curr_freq = initial_freq;
  271. err = clk_set_rate(data->int_clk, initial_freq * 1000);
  272. if (err) {
  273. dev_err(dev, "Failed to set initial frequency\n");
  274. return err;
  275. }
  276. err = exynos5_int_setvolt(data, initial_volt);
  277. if (err)
  278. return err;
  279. platform_set_drvdata(pdev, data);
  280. busfreq_mon_reset(ppmu_data);
  281. data->devfreq = devm_devfreq_add_device(dev, &exynos5_devfreq_int_profile,
  282. "simple_ondemand", NULL);
  283. if (IS_ERR(data->devfreq))
  284. return PTR_ERR(data->devfreq);
  285. err = devm_devfreq_register_opp_notifier(dev, data->devfreq);
  286. if (err < 0) {
  287. dev_err(dev, "Failed to register opp notifier\n");
  288. return err;
  289. }
  290. err = register_pm_notifier(&data->pm_notifier);
  291. if (err) {
  292. dev_err(dev, "Failed to setup pm notifier\n");
  293. return err;
  294. }
  295. /* TODO: Add a new QOS class for int/mif bus */
  296. pm_qos_add_request(&data->int_req, PM_QOS_NETWORK_THROUGHPUT, -1);
  297. return 0;
  298. }
  299. static int exynos5_busfreq_int_remove(struct platform_device *pdev)
  300. {
  301. struct busfreq_data_int *data = platform_get_drvdata(pdev);
  302. pm_qos_remove_request(&data->int_req);
  303. unregister_pm_notifier(&data->pm_notifier);
  304. return 0;
  305. }
  306. #ifdef CONFIG_PM_SLEEP
  307. static int exynos5_busfreq_int_resume(struct device *dev)
  308. {
  309. struct platform_device *pdev = container_of(dev, struct platform_device,
  310. dev);
  311. struct busfreq_data_int *data = platform_get_drvdata(pdev);
  312. struct busfreq_ppmu_data *ppmu_data = &data->ppmu_data;
  313. busfreq_mon_reset(ppmu_data);
  314. return 0;
  315. }
  316. static const struct dev_pm_ops exynos5_busfreq_int_pm = {
  317. .resume = exynos5_busfreq_int_resume,
  318. };
  319. #endif
  320. static SIMPLE_DEV_PM_OPS(exynos5_busfreq_int_pm_ops, NULL,
  321. exynos5_busfreq_int_resume);
  322. /* platform device pointer for exynos5 devfreq device. */
  323. static struct platform_device *exynos5_devfreq_pdev;
  324. static struct platform_driver exynos5_busfreq_int_driver = {
  325. .probe = exynos5_busfreq_int_probe,
  326. .remove = exynos5_busfreq_int_remove,
  327. .driver = {
  328. .name = "exynos5-bus-int",
  329. .pm = &exynos5_busfreq_int_pm_ops,
  330. },
  331. };
  332. static int __init exynos5_busfreq_int_init(void)
  333. {
  334. int ret;
  335. ret = platform_driver_register(&exynos5_busfreq_int_driver);
  336. if (ret < 0)
  337. goto out;
  338. exynos5_devfreq_pdev =
  339. platform_device_register_simple("exynos5-bus-int", -1, NULL, 0);
  340. if (IS_ERR(exynos5_devfreq_pdev)) {
  341. ret = PTR_ERR(exynos5_devfreq_pdev);
  342. goto out1;
  343. }
  344. return 0;
  345. out1:
  346. platform_driver_unregister(&exynos5_busfreq_int_driver);
  347. out:
  348. return ret;
  349. }
  350. late_initcall(exynos5_busfreq_int_init);
  351. static void __exit exynos5_busfreq_int_exit(void)
  352. {
  353. platform_device_unregister(exynos5_devfreq_pdev);
  354. platform_driver_unregister(&exynos5_busfreq_int_driver);
  355. }
  356. module_exit(exynos5_busfreq_int_exit);
  357. MODULE_LICENSE("GPL");
  358. MODULE_DESCRIPTION("EXYNOS5 busfreq driver with devfreq framework");