msm_mmrm.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/module.h>
  6. #include <linux/of_platform.h>
  7. #include <linux/platform_device.h>
  8. #include <linux/slab.h>
  9. #include <linux/soc/qcom/msm_mmrm.h>
  10. #include <linux/fs.h>
  11. #include "mmrm_internal.h"
  12. #include "mmrm_debug.h"
  13. #include "mmrm_clk_rsrc_mgr.h"
  14. #define VERIFY_PDEV(pdev) \
  15. { \
  16. if (!pdev) { \
  17. d_mpr_e("%s: null platform dev\n", __func__);\
  18. rc = -EINVAL; \
  19. goto err_exit; \
  20. } \
  21. }
  22. #define RESET_DRV_DATA(drv_data) \
  23. { \
  24. kfree(drv_data); \
  25. drv_data = (void *) -EPROBE_DEFER; \
  26. }
  27. #define CHECK_SKIP_MMRM_CLK_RSRC(drv_data) \
  28. { \
  29. if (!drv_data->is_clk_scaling_supported) { \
  30. d_mpr_h("%s: mmrm clk rsrc not supported\n", __func__);\
  31. goto skip_mmrm; \
  32. } \
  33. }
  34. #define MMRM_SYSFS_ENTRY_MAX_LEN PAGE_SIZE
  35. extern int msm_mmrm_debug;
  36. extern u8 msm_mmrm_enable_throttle_feature;
  37. extern u8 msm_mmrm_allow_multiple_register;
  38. struct mmrm_driver_data *drv_data = (void *) -EPROBE_DEFER;
  39. bool mmrm_client_check_scaling_supported(enum mmrm_client_type client_type, u32 client_domain)
  40. {
  41. if (drv_data == (void *)-EPROBE_DEFER) {
  42. d_mpr_e("%s: mmrm probe_init not done\n", __func__);
  43. goto err_exit;
  44. }
  45. if (client_type == MMRM_CLIENT_CLOCK) {
  46. CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
  47. /* TODO: Check for individual domain */
  48. }
  49. return true;
  50. err_exit:
  51. d_mpr_e("%s: error exit\n", __func__);
  52. skip_mmrm:
  53. return false;
  54. }
  55. EXPORT_SYMBOL(mmrm_client_check_scaling_supported);
  56. struct mmrm_client *mmrm_client_register(struct mmrm_client_desc *client_desc)
  57. {
  58. struct mmrm_client *client = NULL;
  59. /* check for null input */
  60. if (!client_desc) {
  61. d_mpr_e("%s: null input descriptor\n", __func__);
  62. goto err_exit;
  63. }
  64. if (drv_data == (void *) -EPROBE_DEFER) {
  65. d_mpr_e("%s: mmrm probe_init not done\n", __func__);
  66. goto err_exit;
  67. }
  68. /* check for client type, then register */
  69. if (client_desc->client_type == MMRM_CLIENT_CLOCK) {
  70. /* check for skip mmrm */
  71. CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
  72. client = mmrm_clk_client_register(
  73. drv_data->clk_mgr, client_desc);
  74. if (!client) {
  75. d_mpr_e("%s: failed to register client\n", __func__);
  76. goto err_exit;
  77. }
  78. } else {
  79. d_mpr_e("%s: unknown client_type %d\n",
  80. __func__, client_desc->client_type);
  81. goto err_exit;
  82. }
  83. skip_mmrm:
  84. return client;
  85. err_exit:
  86. d_mpr_e("%s: error exit\n", __func__);
  87. return client;
  88. }
  89. EXPORT_SYMBOL(mmrm_client_register);
  90. int mmrm_client_deregister(struct mmrm_client *client)
  91. {
  92. int rc = 0;
  93. /* check for null input */
  94. if (!client) {
  95. d_mpr_e("%s: invalid input client\n", __func__);
  96. rc = -EINVAL;
  97. goto err_exit;
  98. }
  99. if (drv_data == (void *) -EPROBE_DEFER) {
  100. d_mpr_e("%s: mmrm probe_init not done\n", __func__);
  101. goto err_exit;
  102. }
  103. /* check for client type, then deregister */
  104. if (client->client_type == MMRM_CLIENT_CLOCK) {
  105. /* check for skip mmrm */
  106. CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
  107. rc = mmrm_clk_client_deregister(drv_data->clk_mgr, client);
  108. if (rc != 0) {
  109. d_mpr_e("%s: failed to deregister client\n", __func__);
  110. goto err_exit;
  111. }
  112. } else {
  113. d_mpr_e("%s: unknown client_type %d\n",
  114. __func__, client->client_type);
  115. }
  116. skip_mmrm:
  117. return rc;
  118. err_exit:
  119. d_mpr_e("%s: error = %d\n", __func__, rc);
  120. return rc;
  121. }
  122. EXPORT_SYMBOL(mmrm_client_deregister);
  123. int mmrm_client_set_value(struct mmrm_client *client,
  124. struct mmrm_client_data *client_data, unsigned long val)
  125. {
  126. int rc = 0;
  127. /* check for null input */
  128. if (!client || !client_data) {
  129. d_mpr_e("%s: invalid input client(%pK) client_data(%pK)\n",
  130. __func__, client, client_data);
  131. rc = -EINVAL;
  132. goto err_exit;
  133. }
  134. if (drv_data == (void *) -EPROBE_DEFER) {
  135. d_mpr_e("%s: mmrm probe_init not done\n", __func__);
  136. goto err_exit;
  137. }
  138. /* check for client type, then set value */
  139. if (client->client_type == MMRM_CLIENT_CLOCK) {
  140. /* check for skip mmrm */
  141. CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
  142. rc = mmrm_clk_client_setval(drv_data->clk_mgr, client,
  143. client_data, val);
  144. if (rc != 0) {
  145. d_mpr_e("%s: failed to set value for client\n", __func__);
  146. goto err_exit;
  147. }
  148. } else {
  149. d_mpr_e("%s: unknown client_type %d\n",
  150. __func__, client->client_type);
  151. }
  152. skip_mmrm:
  153. return rc;
  154. err_exit:
  155. d_mpr_e("%s: error = %d\n", __func__, rc);
  156. return rc;
  157. }
  158. EXPORT_SYMBOL(mmrm_client_set_value);
  159. int mmrm_client_set_value_in_range(struct mmrm_client *client,
  160. struct mmrm_client_data *client_data,
  161. struct mmrm_client_res_value *val)
  162. {
  163. int rc = 0;
  164. /* check for null input */
  165. if (!client || !client_data || !val) {
  166. d_mpr_e(
  167. "%s: invalid input client(%pK) client_data(%pK) val(%pK)\n",
  168. __func__, client, client_data, val);
  169. rc = -EINVAL;
  170. goto err_exit;
  171. }
  172. if (drv_data == (void *) -EPROBE_DEFER) {
  173. d_mpr_e("%s: mmrm probe_init not done\n", __func__);
  174. goto err_exit;
  175. }
  176. /* check for client type, then set value */
  177. if (client->client_type == MMRM_CLIENT_CLOCK) {
  178. /* check for skip mmrm */
  179. CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
  180. rc = mmrm_clk_client_setval_inrange(drv_data->clk_mgr,
  181. client, client_data, val);
  182. if (rc != 0) {
  183. d_mpr_e("%s: failed to set value for client\n", __func__);
  184. goto err_exit;
  185. }
  186. } else {
  187. d_mpr_e("%s: unknown client_type %d\n",
  188. __func__, client->client_type);
  189. }
  190. skip_mmrm:
  191. return rc;
  192. err_exit:
  193. d_mpr_e("%s: error = %d\n", __func__, rc);
  194. return rc;
  195. }
  196. EXPORT_SYMBOL(mmrm_client_set_value_in_range);
  197. int mmrm_client_get_value(struct mmrm_client *client,
  198. struct mmrm_client_res_value *val)
  199. {
  200. int rc = 0;
  201. /* check for null input */
  202. if (!client || !val) {
  203. d_mpr_e("%s: invalid input client(%pK) val(%pK)\n",
  204. __func__, client, val);
  205. rc = -EINVAL;
  206. goto err_exit;
  207. }
  208. if (drv_data == (void *) -EPROBE_DEFER) {
  209. d_mpr_e("%s: mmrm probe_init not done\n", __func__);
  210. goto err_exit;
  211. }
  212. /* check for client type, then get value */
  213. if (client->client_type == MMRM_CLIENT_CLOCK) {
  214. /* check for skip mmrm */
  215. CHECK_SKIP_MMRM_CLK_RSRC(drv_data);
  216. rc = mmrm_clk_client_getval(drv_data->clk_mgr,
  217. client, val);
  218. if (rc != 0) {
  219. d_mpr_e("%s: failed to get value for client\n", __func__);
  220. goto err_exit;
  221. }
  222. } else {
  223. d_mpr_e("%s: unknown client_type %d\n",
  224. __func__, client->client_type);
  225. }
  226. skip_mmrm:
  227. return rc;
  228. err_exit:
  229. d_mpr_e("%s: error = %d\n", __func__, rc);
  230. return rc;
  231. }
  232. EXPORT_SYMBOL(mmrm_client_get_value);
  233. int mmrm_client_get_clk_count(void)
  234. {
  235. struct mmrm_sw_clk_mgr_info *sinfo;
  236. if (drv_data == (void *) -EPROBE_DEFER)
  237. return 0;
  238. sinfo = &(drv_data->clk_mgr->data.sw_info);
  239. return sinfo->tot_clk_clients;
  240. }
  241. EXPORT_SYMBOL(mmrm_client_get_clk_count);
  242. static int sysfs_get_param(const char *buf, u32 *param)
  243. {
  244. int base;
  245. if (buf) {
  246. if ((buf[1] == 'x') || (buf[1] == 'X'))
  247. base = 16;
  248. else
  249. base = 10;
  250. if (kstrtou32(buf, base, param) != 0)
  251. return -EINVAL;
  252. }
  253. return 0;
  254. }
  255. static ssize_t mmrm_sysfs_debug_get(struct device *dev,
  256. struct device_attribute *attr, char *buf)
  257. {
  258. int ret;
  259. ret = scnprintf(buf, MMRM_SYSFS_ENTRY_MAX_LEN, "0x%x\n", msm_mmrm_debug);
  260. pr_info("%s: 0x%04X\n", __func__, msm_mmrm_debug);
  261. return ret;
  262. }
  263. static ssize_t mmrm_sysfs_debug_set(struct device *dev,
  264. struct device_attribute *attr, const char *buf, size_t count)
  265. {
  266. int ret;
  267. u32 reg_addr;
  268. ret = sysfs_get_param(buf, &reg_addr);
  269. if (ret == 0)
  270. msm_mmrm_debug = reg_addr;
  271. return count;
  272. }
  273. static ssize_t mmrm_sysfs_enable_throttle_get(struct device *dev,
  274. struct device_attribute *attr, char *buf)
  275. {
  276. int ret;
  277. ret = scnprintf(buf, MMRM_SYSFS_ENTRY_MAX_LEN, "0x%x\n", msm_mmrm_enable_throttle_feature);
  278. pr_info("%s: 0x%04X\n", __func__, msm_mmrm_enable_throttle_feature);
  279. return ret;
  280. }
  281. static ssize_t mmrm_sysfs_enable_throttle_set(struct device *dev,
  282. struct device_attribute *attr, const char *buf, size_t count)
  283. {
  284. u32 reg_addr;
  285. int ret;
  286. ret = sysfs_get_param(buf, &reg_addr);
  287. if (ret == 0)
  288. msm_mmrm_enable_throttle_feature = (u8)reg_addr;
  289. return count;
  290. }
  291. static ssize_t mmrm_sysfs_allow_multiple_get(struct device *dev,
  292. struct device_attribute *attr, char *buf)
  293. {
  294. int ret;
  295. ret = scnprintf(buf, MMRM_SYSFS_ENTRY_MAX_LEN, "0x%x\n", msm_mmrm_allow_multiple_register);
  296. pr_info("%s: 0x%04X\n", __func__, msm_mmrm_allow_multiple_register);
  297. return ret;
  298. }
  299. static ssize_t mmrm_sysfs_allow_multiple_set(struct device *dev,
  300. struct device_attribute *attr, const char *buf, size_t count)
  301. {
  302. u32 reg_addr;
  303. int ret;
  304. ret = sysfs_get_param(buf, &reg_addr);
  305. if (ret == 0)
  306. msm_mmrm_allow_multiple_register = (u8)reg_addr;
  307. return count;
  308. }
  309. static ssize_t dump_enabled_client_info_show(struct device *dev,
  310. struct device_attribute *attr, char *buf)
  311. {
  312. int rc;
  313. rc = mmrm_clk_print_enabled_client_info(drv_data->clk_mgr, buf, MMRM_SYSFS_ENTRY_MAX_LEN);
  314. if (rc == 0)
  315. d_mpr_e("%s: failed to dump client info\n", __func__);
  316. return rc;
  317. }
  318. static ssize_t dump_clk_res_info_show(struct device *dev,
  319. struct device_attribute *attr, char *buf)
  320. {
  321. int i, len;
  322. struct mmrm_clk_platform_resources *cres = &drv_data->clk_res;
  323. struct nom_clk_src_set *clk_set = &cres->nom_clk_set;
  324. struct nom_clk_src_info *pclk;
  325. int left_spaces = MMRM_SYSFS_ENTRY_MAX_LEN;
  326. len = scnprintf(buf, left_spaces, "threshold: %d\n",
  327. cres->peak_threshold);
  328. left_spaces -= len;
  329. buf += len;
  330. for (i = 0, pclk = clk_set->clk_src_tbl; i < clk_set->count && left_spaces > 1; i++, pclk++) {
  331. len = scnprintf(buf, left_spaces, "%d\t%d\t% 8d\t%d\t%d\n",
  332. pclk->domain,
  333. pclk->clk_src_id,
  334. pclk->nom_dyn_pwr,
  335. pclk->nom_leak_pwr,
  336. pclk->num_hw_block);
  337. left_spaces -= len;
  338. buf += len;
  339. }
  340. return MMRM_SYSFS_ENTRY_MAX_LEN - left_spaces;
  341. }
  342. static DEVICE_ATTR(debug, 0644,
  343. mmrm_sysfs_debug_get,
  344. mmrm_sysfs_debug_set);
  345. static DEVICE_ATTR(enable_throttle_feature, 0644,
  346. mmrm_sysfs_enable_throttle_get,
  347. mmrm_sysfs_enable_throttle_set);
  348. static DEVICE_ATTR(allow_multiple_register, 0644,
  349. mmrm_sysfs_allow_multiple_get,
  350. mmrm_sysfs_allow_multiple_set);
  351. static DEVICE_ATTR_RO(dump_enabled_client_info);
  352. static DEVICE_ATTR_RO(dump_clk_res_info);
  353. static struct attribute *mmrm_fs_attrs[] = {
  354. &dev_attr_debug.attr,
  355. &dev_attr_enable_throttle_feature.attr,
  356. &dev_attr_allow_multiple_register.attr,
  357. &dev_attr_dump_enabled_client_info.attr,
  358. &dev_attr_dump_clk_res_info.attr,
  359. NULL,
  360. };
  361. static struct attribute_group mmrm_fs_attrs_group = {
  362. .attrs = mmrm_fs_attrs,
  363. };
  364. static int msm_mmrm_probe_init(struct platform_device *pdev)
  365. {
  366. int rc = 0;
  367. u32 clk_clients = 0;
  368. drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
  369. if (!drv_data) {
  370. d_mpr_e("%s: unable to allocate memory for mmrm driver\n",
  371. __func__);
  372. rc = -ENOMEM;
  373. goto err_no_mem;
  374. }
  375. /* check for clk clients needing admission control */
  376. clk_clients = mmrm_count_clk_clients_frm_dt(pdev);
  377. if (clk_clients) {
  378. d_mpr_h("%s: %d clk clients managed for admission control\n",
  379. __func__, clk_clients);
  380. drv_data->is_clk_scaling_supported = true;
  381. } else {
  382. d_mpr_h("%s: no clk clients managed for admission control\n",
  383. __func__);
  384. drv_data->is_clk_scaling_supported = false;
  385. goto skip_mmrm;
  386. }
  387. drv_data->platform_data = mmrm_get_platform_data(&pdev->dev);
  388. if (!drv_data->platform_data) {
  389. d_mpr_e("%s: unable to get platform data\n",
  390. __func__);
  391. rc = -EINVAL;
  392. goto err_get_drv_data;
  393. }
  394. drv_data->debugfs_root = msm_mmrm_debugfs_init();
  395. if (!drv_data->debugfs_root)
  396. d_mpr_e("%s: failed to create debugfs for mmrm\n", __func__);
  397. dev_set_drvdata(&pdev->dev, drv_data);
  398. rc = mmrm_read_platform_resources(pdev, drv_data);
  399. if (rc) {
  400. d_mpr_e("%s: unable to read platform resources for mmrm\n",
  401. __func__);
  402. goto err_read_pltfrm_rsc;
  403. }
  404. rc = mmrm_init(drv_data);
  405. if (rc) {
  406. d_mpr_e("%s: failed to init mmrm\n",
  407. __func__);
  408. goto err_mmrm_init;
  409. }
  410. if (sysfs_create_group(&pdev->dev.kobj, &mmrm_fs_attrs_group)) {
  411. d_mpr_e("%s: failed to create sysfs\n",
  412. __func__);
  413. }
  414. skip_mmrm:
  415. return rc;
  416. err_mmrm_init:
  417. msm_mmrm_debugfs_deinit(drv_data->debugfs_root);
  418. err_read_pltfrm_rsc:
  419. mmrm_free_platform_resources(drv_data);
  420. err_get_drv_data:
  421. RESET_DRV_DATA(drv_data);
  422. err_no_mem:
  423. d_mpr_e("%s: error = %d\n", __func__, rc);
  424. return rc;
  425. }
  426. static int msm_mmrm_probe(struct platform_device *pdev)
  427. {
  428. int rc = -EINVAL;
  429. d_mpr_h("%s\n", __func__);
  430. VERIFY_PDEV(pdev)
  431. if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-mmrm"))
  432. return msm_mmrm_probe_init(pdev);
  433. d_mpr_e("%s: no compatible device node\n", __func__);
  434. return rc;
  435. err_exit:
  436. d_mpr_e("%s: error = %d\n", __func__, rc);
  437. return rc;
  438. }
  439. static int msm_mmrm_remove(struct platform_device *pdev)
  440. {
  441. int rc = 0;
  442. VERIFY_PDEV(pdev);
  443. drv_data = dev_get_drvdata(&pdev->dev);
  444. if (!drv_data) {
  445. d_mpr_e("%s: null driver data\n", __func__);
  446. return -EINVAL;
  447. }
  448. if (drv_data->is_clk_scaling_supported) {
  449. sysfs_remove_group(&pdev->dev.kobj, &mmrm_fs_attrs_group);
  450. msm_mmrm_debugfs_deinit(drv_data->debugfs_root);
  451. mmrm_deinit(drv_data);
  452. mmrm_free_platform_resources(drv_data);
  453. }
  454. dev_set_drvdata(&pdev->dev, NULL);
  455. RESET_DRV_DATA(drv_data);
  456. return rc;
  457. err_exit:
  458. d_mpr_e("%s: error = %d\n", __func__, rc);
  459. return rc;
  460. }
  461. static const struct of_device_id msm_mmrm_dt_match[] = {
  462. {.compatible = "qcom,msm-mmrm"},
  463. {}
  464. };
  465. MODULE_DEVICE_TABLE(of, msm_mmrm_dt_match);
  466. static struct platform_driver msm_mmrm_driver = {
  467. .probe = msm_mmrm_probe,
  468. .remove = msm_mmrm_remove,
  469. .driver = {
  470. .name = "msm-mmrm",
  471. .of_match_table = msm_mmrm_dt_match,
  472. },
  473. };
  474. static int __init msm_mmrm_init(void)
  475. {
  476. int rc = 0;
  477. rc = platform_driver_register(&msm_mmrm_driver);
  478. if (rc) {
  479. d_mpr_e("%s: failed to register platform driver\n",
  480. __func__);
  481. goto err_platform_drv_reg;
  482. }
  483. d_mpr_h("%s: success\n", __func__);
  484. return rc;
  485. err_platform_drv_reg:
  486. d_mpr_e("%s: error = %d\n", __func__, rc);
  487. return rc;
  488. }
  489. static void __exit msm_mmrm_exit(void)
  490. {
  491. platform_driver_unregister(&msm_mmrm_driver);
  492. }
  493. module_init(msm_mmrm_init);
  494. module_exit(msm_mmrm_exit);
  495. MODULE_DESCRIPTION("QTI MMRM Driver");
  496. MODULE_LICENSE("GPL v2");