spf-core.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
  2. * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 and
  6. * only version 2 as published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/slab.h>
  14. #include <linux/wait.h>
  15. #include <linux/kernel.h>
  16. #include <linux/module.h>
  17. #include <linux/delay.h>
  18. #include <linux/sched.h>
  19. #include <linux/of.h>
  20. #include <linux/of_platform.h>
  21. #include <linux/jiffies.h>
  22. #include <ipc/gpr-lite.h>
  23. #include <dsp/spf-core.h>
  24. #include <dsp/digital-cdc-rsc-mgr.h>
  25. #define Q6_READY_TIMEOUT_MS 1000
  26. #define Q6_CLOSE_ALL_TIMEOUT_MS 5000
  27. #define APM_CMD_GET_SPF_STATE 0x01001021
  28. #define APM_CMD_CLOSE_ALL 0x01001013
  29. #define APM_CMD_RSP_GET_SPF_STATE 0x02001007
  30. #define APM_MODULE_INSTANCE_ID 0x00000001
  31. #define GPR_SVC_ADSP_CORE 0x3
  32. #define ADD_CHILD_DEVICES_APM_TIMEOUT_MS 10000
  33. struct spf_core {
  34. struct gpr_device *adev;
  35. wait_queue_head_t wait;
  36. struct mutex lock;
  37. bool resp_received;
  38. int32_t status;
  39. };
  40. struct spf_core_private {
  41. struct device *dev;
  42. struct mutex lock;
  43. struct spf_core *spf_core_drv;
  44. bool is_initial_boot;
  45. struct work_struct add_chld_dev_work;
  46. };
  47. static struct spf_core_private *spf_core_priv;
  48. /* used to decode basic responses from Gecko */
  49. struct spf_cmd_basic_rsp {
  50. uint32_t opcode;
  51. int32_t status;
  52. };
  53. struct apm_cmd_rsp_get_spf_status_t
  54. {
  55. /* Gecko status
  56. * @values
  57. * 0 -> Not ready
  58. * 1 -> Ready
  59. */
  60. uint32_t status;
  61. };
  62. static int spf_core_callback(struct gpr_device *adev, void *data)
  63. {
  64. struct spf_core *core = dev_get_drvdata(&adev->dev);
  65. struct apm_cmd_rsp_get_spf_status_t *spf_status_rsp;
  66. struct spf_cmd_basic_rsp *basic_rsp;
  67. struct gpr_hdr *hdr = data;
  68. dev_info_ratelimited(&adev->dev, "%s: Payload %x", __func__, hdr->opcode);
  69. switch (hdr->opcode) {
  70. case GPR_IBASIC_RSP_RESULT:
  71. basic_rsp = GPR_PKT_GET_PAYLOAD(
  72. struct spf_cmd_basic_rsp,
  73. data);
  74. dev_info_ratelimited(&adev->dev, "%s: op %x status %d", __func__,
  75. basic_rsp->opcode, basic_rsp->status);
  76. if (basic_rsp->opcode == APM_CMD_CLOSE_ALL) {
  77. core->status = basic_rsp->status;
  78. } else {
  79. dev_err_ratelimited(&adev->dev, "%s: Failed response received",
  80. __func__);
  81. }
  82. core->resp_received = true;
  83. break;
  84. case APM_CMD_RSP_GET_SPF_STATE:
  85. spf_status_rsp =
  86. GPR_PKT_GET_PAYLOAD(
  87. struct apm_cmd_rsp_get_spf_status_t,
  88. data);
  89. dev_info_ratelimited(&adev->dev, "%s: sucess response received", __func__);
  90. core->status = spf_status_rsp->status;
  91. core->resp_received = true;
  92. break;
  93. default:
  94. dev_err_ratelimited(&adev->dev, "Message ID from apm: 0x%x\n",
  95. hdr->opcode);
  96. break;
  97. }
  98. if (core->resp_received)
  99. wake_up(&core->wait);
  100. return 0;
  101. }
  102. static bool __spf_core_is_apm_ready(struct spf_core *core)
  103. {
  104. struct gpr_device *adev = core->adev;
  105. struct gpr_pkt pkt;
  106. int rc;
  107. bool ret = false;
  108. pkt.hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) |
  109. GPR_SET_FIELD(GPR_PKT_HEADER_SIZE, GPR_PKT_HEADER_WORD_SIZE_V) |
  110. GPR_SET_FIELD(GPR_PKT_PACKET_SIZE, GPR_PKT_HEADER_BYTE_SIZE_V);
  111. pkt.hdr.dst_port = APM_MODULE_INSTANCE_ID;
  112. pkt.hdr.src_port = GPR_SVC_ADSP_CORE;
  113. pkt.hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V;
  114. pkt.hdr.src_domain_id = GPR_IDS_DOMAIN_ID_APPS_V;
  115. pkt.hdr.opcode = APM_CMD_GET_SPF_STATE;
  116. dev_err_ratelimited(spf_core_priv->dev, "%s: send_command ret\n", __func__);
  117. rc = gpr_send_pkt(adev, &pkt);
  118. if (rc < 0) {
  119. ret = false;
  120. goto done;
  121. }
  122. rc = wait_event_timeout(core->wait, (core->resp_received),
  123. msecs_to_jiffies(Q6_READY_TIMEOUT_MS));
  124. dev_dbg(spf_core_priv->dev, "%s: wait event unblocked \n", __func__);
  125. if (rc > 0 && core->resp_received) {
  126. ret = core->status;
  127. } else {
  128. dev_err_ratelimited(spf_core_priv->dev, "%s: command timedout, ret\n",
  129. __func__);
  130. }
  131. done:
  132. core->resp_received = false;
  133. return ret;
  134. }
  135. /**
  136. * spf_core_is_apm_ready() - Get status of adsp
  137. *
  138. * Return: Will return true if apm is ready and false if not.
  139. */
  140. bool spf_core_is_apm_ready(int timeout_ms)
  141. {
  142. unsigned long timeout;
  143. bool ret = false;
  144. struct spf_core *core;
  145. if (!spf_core_priv)
  146. return ret;
  147. mutex_lock(&spf_core_priv->lock);
  148. core = spf_core_priv->spf_core_drv;
  149. if (!core)
  150. goto done;
  151. timeout = jiffies + msecs_to_jiffies(timeout_ms);
  152. mutex_lock(&core->lock);
  153. for (;;) {
  154. if (__spf_core_is_apm_ready(core)) {
  155. ret = true;
  156. break;
  157. }
  158. if (!timeout_ms)
  159. break;
  160. usleep_range(50000, 50050);
  161. if (!time_after(timeout, jiffies)) {
  162. ret = false;
  163. break;
  164. }
  165. }
  166. mutex_unlock(&core->lock);
  167. done:
  168. mutex_unlock(&spf_core_priv->lock);
  169. return ret;
  170. }
  171. EXPORT_SYMBOL_GPL(spf_core_is_apm_ready);
  172. /**
  173. * spf_core_apm_close_all() - Get status of adsp
  174. *
  175. * Return: Will be return true if apm is ready and false if not.
  176. */
  177. void spf_core_apm_close_all(void)
  178. {
  179. int rc = 0;
  180. struct spf_core *core;
  181. struct gpr_pkt pkt;
  182. struct gpr_device *adev = NULL;
  183. if (!spf_core_priv)
  184. return;
  185. mutex_lock(&spf_core_priv->lock);
  186. core = spf_core_priv->spf_core_drv;
  187. if (!core) {
  188. mutex_unlock(&spf_core_priv->lock);
  189. return;
  190. }
  191. mutex_lock(&core->lock);
  192. adev = core->adev;
  193. pkt.hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) |
  194. GPR_SET_FIELD(GPR_PKT_HEADER_SIZE,
  195. GPR_PKT_HEADER_WORD_SIZE_V) |
  196. GPR_SET_FIELD(GPR_PKT_PACKET_SIZE,
  197. GPR_PKT_HEADER_BYTE_SIZE_V);
  198. pkt.hdr.dst_port = APM_MODULE_INSTANCE_ID;
  199. pkt.hdr.src_port = GPR_SVC_ADSP_CORE;
  200. pkt.hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V;
  201. pkt.hdr.src_domain_id = GPR_IDS_DOMAIN_ID_APPS_V;
  202. pkt.hdr.opcode = APM_CMD_CLOSE_ALL;
  203. dev_info_ratelimited(spf_core_priv->dev, "%s: send_command \n", __func__);
  204. rc = gpr_send_pkt(adev, &pkt);
  205. if (rc < 0) {
  206. dev_err_ratelimited(spf_core_priv->dev, "%s: send_pkt_failed %d\n",
  207. __func__, rc);
  208. goto done;
  209. }
  210. /* While graph_open is processing by the SPF, apps receives
  211. * userspace(agm/pal) crash which will triggers spf_close_all
  212. * cmd from msm common drivers and immediately calls
  213. * msm_audio_ion_crash_handler() which will un-maps the memory. But
  214. * here SPF is still in processing the graph_open, recieved spf_close_all
  215. * cmd is queued in SPF. Due to un-mapping is done immediately in HLOS
  216. * will resulting in SMMU fault.
  217. * To avoid such scenarios, increased the spf_close_all cmd timeout,
  218. * because the AGM timeout for the graph_open is 4sec, so increase the timeout
  219. * for spf_close_all cmd response until graph open completes or timed out.
  220. */
  221. rc = wait_event_timeout(core->wait, (core->resp_received),
  222. msecs_to_jiffies(Q6_CLOSE_ALL_TIMEOUT_MS));
  223. dev_info_ratelimited(spf_core_priv->dev, "%s: wait event unblocked \n", __func__);
  224. if (rc > 0 && core->resp_received) {
  225. if (core->status != 0)
  226. dev_err_ratelimited(spf_core_priv->dev, "%s, cmd failed status %d",
  227. __func__, core->status);
  228. } else {
  229. dev_err_ratelimited(spf_core_priv->dev, "%s: command timedout, ret\n",
  230. __func__);
  231. }
  232. done:
  233. core->resp_received = false;
  234. mutex_unlock(&core->lock);
  235. mutex_unlock(&spf_core_priv->lock);
  236. return;
  237. }
  238. EXPORT_SYMBOL_GPL(spf_core_apm_close_all);
  239. static int spf_core_probe(struct gpr_device *adev)
  240. {
  241. struct spf_core *core;
  242. pr_err("%s",__func__);
  243. if (!spf_core_priv) {
  244. pr_err("%s: spf_core platform probe not yet done\n", __func__);
  245. return -EPROBE_DEFER;
  246. }
  247. mutex_lock(&spf_core_priv->lock);
  248. core = kzalloc(sizeof(*core), GFP_KERNEL);
  249. if (!core) {
  250. mutex_unlock(&spf_core_priv->lock);
  251. return -ENOMEM;
  252. }
  253. dev_set_drvdata(&adev->dev, core);
  254. mutex_init(&core->lock);
  255. core->adev = adev;
  256. init_waitqueue_head(&core->wait);
  257. spf_core_priv->spf_core_drv = core;
  258. if (spf_core_priv->is_initial_boot)
  259. schedule_work(&spf_core_priv->add_chld_dev_work);
  260. mutex_unlock(&spf_core_priv->lock);
  261. return 0;
  262. }
  263. static int spf_core_exit(struct gpr_device *adev)
  264. {
  265. struct spf_core *core = dev_get_drvdata(&adev->dev);
  266. if (!spf_core_priv) {
  267. pr_err("%s: spf_core platform probe not yet done\n", __func__);
  268. return -1;
  269. }
  270. mutex_lock(&spf_core_priv->lock);
  271. spf_core_priv->spf_core_drv = NULL;
  272. kfree(core);
  273. mutex_unlock(&spf_core_priv->lock);
  274. return 0;
  275. }
  276. static const struct of_device_id spf_core_device_id[] = {
  277. { .compatible = "qcom,spf_core" },
  278. {},
  279. };
  280. MODULE_DEVICE_TABLE(of, spf_core_device_id);
  281. static struct gpr_driver qcom_spf_core_driver = {
  282. .probe = spf_core_probe,
  283. .remove = spf_core_exit,
  284. .callback = spf_core_callback,
  285. .driver = {
  286. .name = "qcom-spf_core",
  287. .of_match_table = of_match_ptr(spf_core_device_id),
  288. },
  289. };
  290. static void spf_core_add_child_devices(struct work_struct *work)
  291. {
  292. int ret;
  293. pr_err("%s:enumarate machine driver\n", __func__);
  294. if (spf_core_is_apm_ready(ADD_CHILD_DEVICES_APM_TIMEOUT_MS)) {
  295. dev_err(spf_core_priv->dev, "%s: apm is up\n",
  296. __func__);
  297. } else {
  298. dev_err(spf_core_priv->dev, "%s: apm is not up\n",
  299. __func__);
  300. return;
  301. }
  302. ret = of_platform_populate(spf_core_priv->dev->of_node,
  303. NULL, NULL, spf_core_priv->dev);
  304. if (ret)
  305. dev_err(spf_core_priv->dev, "%s: failed to add child nodes, ret=%d\n",
  306. __func__, ret);
  307. spf_core_priv->is_initial_boot = false;
  308. }
  309. static int spf_core_platform_driver_probe(struct platform_device *pdev)
  310. {
  311. int ret = 0;
  312. pr_err("%s",__func__);
  313. spf_core_priv = devm_kzalloc(&pdev->dev, sizeof(struct spf_core_private), GFP_KERNEL);
  314. if (!spf_core_priv)
  315. return -ENOMEM;
  316. spf_core_priv->dev = &pdev->dev;
  317. mutex_init(&spf_core_priv->lock);
  318. INIT_WORK(&spf_core_priv->add_chld_dev_work, spf_core_add_child_devices);
  319. spf_core_priv->is_initial_boot = true;
  320. ret = gpr_driver_register(&qcom_spf_core_driver);
  321. if (ret) {
  322. pr_err("%s: gpr driver register failed = %d\n",
  323. __func__, ret);
  324. ret = 0;
  325. }
  326. #if 0
  327. ret = snd_event_client_register(&pdev->dev, &gpr_ssr_ops, NULL);
  328. if (ret) {
  329. pr_err("%s: Registration with SND event fwk failed ret = %d\n",
  330. __func__, ret);
  331. ret = 0;
  332. }
  333. #endif
  334. digital_cdc_rsc_mgr_init();
  335. return ret;
  336. }
  337. static int spf_core_platform_driver_remove(struct platform_device *pdev)
  338. {
  339. //snd_event_client_deregister(&pdev->dev);
  340. gpr_driver_unregister(&qcom_spf_core_driver);
  341. spf_core_priv = NULL;
  342. digital_cdc_rsc_mgr_exit();
  343. return 0;
  344. }
  345. static const struct of_device_id spf_core_of_match[] = {
  346. { .compatible = "qcom,spf-core-platform", },
  347. {},
  348. };
  349. static struct platform_driver spf_core_driver = {
  350. .probe = spf_core_platform_driver_probe,
  351. .remove = spf_core_platform_driver_remove,
  352. .driver = {
  353. .name = "spf-core-platform",
  354. .owner = THIS_MODULE,
  355. .of_match_table = spf_core_of_match,
  356. }
  357. };
  358. module_platform_driver(spf_core_driver);
  359. MODULE_DESCRIPTION("q6 core");
  360. MODULE_LICENSE("GPL v2");