mmrm_vm_fe_main.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #include <linux/types.h>
  6. #include <linux/kthread.h>
  7. #include <linux/module.h>
  8. #include <linux/of.h>
  9. #include "mmrm_vm_fe.h"
  10. #include "mmrm_vm_msgq.h"
  11. #include "mmrm_vm_interface.h"
  12. #include "mmrm_vm_debug.h"
  13. struct mmrm_vm_driver_data *drv_vm_fe = (void *) -EPROBE_DEFER;
  14. static ssize_t dump_clk_info_show(struct device *dev,
  15. struct device_attribute *attr, char *buf)
  16. {
  17. int rc;
  18. struct mmrm_vm_fe_priv *fe_data = drv_vm_fe->vm_pvt_data;
  19. rc = mmrm_vm_fe_clk_print_info(&fe_data->clk_src_set, buf, MMRM_SYSFS_ENTRY_MAX_LEN);
  20. if (rc == 0)
  21. d_mpr_e("%s: failed to dump clk info\n", __func__);
  22. return rc;
  23. }
  24. ssize_t msgq_send_trigger_store(struct device *dev, struct device_attribute *attr,
  25. const char *buf, size_t count)
  26. {
  27. struct mmrm_vm_driver_data *priv = dev->driver_data;
  28. char send_buf[64] = "test msg";
  29. int ret;
  30. bool flag;
  31. ret = strtobool(buf, &flag);
  32. if (ret) {
  33. dev_err(dev, "invalid user input\n");
  34. return -1;
  35. }
  36. if (flag) {
  37. ret = mmrm_vm_msgq_send(priv, send_buf, sizeof(send_buf));
  38. if (ret)
  39. d_mpr_e("%s:send msgq failed\n", __func__);
  40. else
  41. d_mpr_e("%s:send msgq success\n", __func__);
  42. }
  43. return ret ? ret : count;
  44. }
  45. extern int mmrm_client_msgq_roundtrip_measure(u32 val);
  46. ssize_t msgq_rt_test_store(struct device *dev, struct device_attribute *attr,
  47. const char *buf, size_t count)
  48. {
  49. int ret;
  50. long sz, n;
  51. struct mmrm_vm_fe_priv *fe_data;
  52. struct mmrm_vm_fe_msgq_rt_stats *trip_time;
  53. if (IS_ERR_OR_NULL(drv_vm_fe)) {
  54. return -1;
  55. }
  56. ret = kstrtol(buf, 10, &sz);
  57. if (ret) {
  58. dev_err(dev, "invalid user input\n");
  59. return -1;
  60. }
  61. if (sz) {
  62. d_mpr_w("%s: loop count:%d\n", __func__, sz);
  63. fe_data = drv_vm_fe->vm_pvt_data;
  64. trip_time = &fe_data->msgq_rt_stats;
  65. trip_time->looptest_total_us = 0;
  66. n = sz;
  67. while (n-- > 0) {
  68. ret = mmrm_client_msgq_roundtrip_measure(0);
  69. if (ret) {
  70. d_mpr_e("%s:send msgq failed\n", __func__);
  71. break;
  72. };
  73. }
  74. if (n <= 0)
  75. d_mpr_w("%s: aver: %d\n", __func__, trip_time->looptest_total_us / sz);
  76. }
  77. return ret ? ret : count;
  78. }
  79. static DEVICE_ATTR_RO(dump_clk_info);
  80. static DEVICE_ATTR_WO(msgq_send_trigger);
  81. static DEVICE_ATTR_WO(msgq_rt_test);
  82. static struct attribute *mmrm_vm_fe_fs_attrs[] = {
  83. &dev_attr_dump_clk_info.attr,
  84. &dev_attr_msgq_send_trigger.attr,
  85. &dev_attr_msgq_rt_test.attr,
  86. NULL,
  87. };
  88. static struct attribute_group mmrm_vm_fe_fs_attrs_group = {
  89. .attrs = mmrm_vm_fe_fs_attrs,
  90. };
  91. static int mmrm_vm_fe_driver_probe(struct platform_device *pdev)
  92. {
  93. struct device *dev = &pdev->dev;
  94. struct mmrm_vm_fe_priv *fe_priv_data;
  95. int rc = 0;
  96. u32 clk_clients = 0;
  97. drv_vm_fe = devm_kzalloc(dev, sizeof(*drv_vm_fe), GFP_KERNEL);
  98. if (!drv_vm_fe)
  99. return -ENOMEM;
  100. fe_priv_data = devm_kzalloc(dev, sizeof(*fe_priv_data), GFP_KERNEL);
  101. if (!fe_priv_data) {
  102. rc = -ENOMEM;
  103. goto err_priv_data;
  104. }
  105. drv_vm_fe->vm_pvt_data = fe_priv_data;
  106. fe_priv_data->seq_no = 0;
  107. fe_priv_data->dev = dev;
  108. /* check for clk clients needing admission control */
  109. clk_clients = mmrm_vm_fe_count_clk_clients_frm_dt(pdev);
  110. if (clk_clients) {
  111. d_mpr_h("%s: %d clk clients managed for admission control\n",
  112. __func__, clk_clients);
  113. fe_priv_data->is_clk_scaling_supported = true;
  114. } else {
  115. d_mpr_h("%s: no clk clients managed for admission control\n",
  116. __func__);
  117. fe_priv_data->is_clk_scaling_supported = false;
  118. goto skip_mmrm;
  119. }
  120. mutex_init(&fe_priv_data->msg_send_lock);
  121. dev_set_drvdata(&pdev->dev, drv_vm_fe);
  122. INIT_LIST_HEAD(&fe_priv_data->resp_works);
  123. mutex_init(&fe_priv_data->resp_works_lock);
  124. mmrm_vm_fe_load_clk_rsrc(drv_vm_fe);
  125. rc = mmrm_vm_msgq_init(drv_vm_fe);
  126. if (rc != 0) {
  127. d_mpr_e("%s: failed to msgq init\n",
  128. __func__);
  129. goto err_msgq_init;
  130. }
  131. rc = mmrm_vm_fe_init_lookup_table(drv_vm_fe);
  132. if (rc == -1) {
  133. d_mpr_e("%s: failed to lookup table init\n",
  134. __func__);
  135. goto err_lookup_table;
  136. }
  137. if (sysfs_create_group(&pdev->dev.kobj, &mmrm_vm_fe_fs_attrs_group)) {
  138. d_mpr_e("%s: failed to create sysfs\n",
  139. __func__);
  140. }
  141. d_mpr_w("msgq probe success");
  142. return rc;
  143. err_lookup_table:
  144. mmrm_vm_msgq_deinit(drv_vm_fe);
  145. err_msgq_init:
  146. err_priv_data:
  147. d_mpr_e("%s: failed to probe\n", __func__);
  148. skip_mmrm:
  149. return rc;
  150. }
  151. static int mmrm_vm_fe_driver_remove(struct platform_device *pdev)
  152. {
  153. struct mmrm_vm_driver_data *mmrm_vm = dev_get_drvdata(&pdev->dev);
  154. mmrm_vm_msgq_deinit(mmrm_vm);
  155. return 0;
  156. }
  157. static const struct of_device_id mmrm_vm_fe_match[] = {
  158. { .compatible = "qcom,mmrm-vm-fe" },
  159. {},
  160. };
  161. MODULE_DEVICE_TABLE(of, mmrm_vm_fe_match);
  162. static struct platform_driver mmrm_vm_fe_driver = {
  163. .probe = mmrm_vm_fe_driver_probe,
  164. .driver = {
  165. .name = "mmrm-vm-fe",
  166. .of_match_table = mmrm_vm_fe_match,
  167. },
  168. .remove = mmrm_vm_fe_driver_remove,
  169. };
  170. static int __init mmrm_vm_fe_module_init(void)
  171. {
  172. d_mpr_e("%s: init start\n", __func__);
  173. return platform_driver_register(&mmrm_vm_fe_driver);
  174. }
  175. subsys_initcall(mmrm_vm_fe_module_init);
  176. static void __exit mmrm_vm_fe_module_exit(void)
  177. {
  178. platform_driver_unregister(&mmrm_vm_fe_driver);
  179. }
  180. module_exit(mmrm_vm_fe_module_exit);
  181. MODULE_SOFTDEP("pre: gunyah_transport");
  182. MODULE_DESCRIPTION("Qualcomm Technologies, Inc. Test MSGQ Driver");
  183. MODULE_LICENSE("GPL v2");