ti_k3_dsp_remoteproc.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * TI K3 DSP Remote Processor(s) driver
  4. *
  5. * Copyright (C) 2018-2022 Texas Instruments Incorporated - https://www.ti.com/
  6. * Suman Anna <s-anna@ti.com>
  7. */
  8. #include <linux/io.h>
  9. #include <linux/mailbox_client.h>
  10. #include <linux/module.h>
  11. #include <linux/of.h>
  12. #include <linux/of_reserved_mem.h>
  13. #include <linux/omap-mailbox.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/remoteproc.h>
  16. #include <linux/reset.h>
  17. #include <linux/slab.h>
  18. #include "omap_remoteproc.h"
  19. #include "remoteproc_internal.h"
  20. #include "ti_sci_proc.h"
  21. #include "ti_k3_common.h"
  22. /*
  23. * Power up the DSP remote processor.
  24. *
  25. * This function will be invoked only after the firmware for this rproc
  26. * was loaded, parsed successfully, and all of its resource requirements
  27. * were met. This callback is invoked only in remoteproc mode.
  28. */
  29. static int k3_dsp_rproc_start(struct rproc *rproc)
  30. {
  31. struct k3_rproc *kproc = rproc->priv;
  32. struct device *dev = kproc->dev;
  33. u32 boot_addr;
  34. int ret;
  35. boot_addr = rproc->bootaddr;
  36. if (boot_addr & (kproc->data->boot_align_addr - 1)) {
  37. dev_err(dev, "invalid boot address 0x%x, must be aligned on a 0x%x boundary\n",
  38. boot_addr, kproc->data->boot_align_addr);
  39. return -EINVAL;
  40. }
  41. dev_dbg(dev, "booting DSP core using boot addr = 0x%x\n", boot_addr);
  42. ret = ti_sci_proc_set_config(kproc->tsp, boot_addr, 0, 0);
  43. if (ret)
  44. return ret;
  45. /* Call the K3 common start function after doing DSP specific stuff */
  46. ret = k3_rproc_start(rproc);
  47. if (ret)
  48. return ret;
  49. return 0;
  50. }
  51. static const struct rproc_ops k3_dsp_rproc_ops = {
  52. .start = k3_dsp_rproc_start,
  53. .stop = k3_rproc_stop,
  54. .attach = k3_rproc_attach,
  55. .detach = k3_rproc_detach,
  56. .kick = k3_rproc_kick,
  57. .da_to_va = k3_rproc_da_to_va,
  58. .get_loaded_rsc_table = k3_get_loaded_rsc_table,
  59. };
  60. static int k3_dsp_rproc_probe(struct platform_device *pdev)
  61. {
  62. struct device *dev = &pdev->dev;
  63. struct device_node *np = dev->of_node;
  64. const struct k3_rproc_dev_data *data;
  65. struct k3_rproc *kproc;
  66. struct rproc *rproc;
  67. const char *fw_name;
  68. bool p_state = false;
  69. int ret = 0;
  70. data = of_device_get_match_data(dev);
  71. if (!data)
  72. return -ENODEV;
  73. ret = rproc_of_parse_firmware(dev, 0, &fw_name);
  74. if (ret)
  75. return dev_err_probe(dev, ret, "failed to parse firmware-name property\n");
  76. rproc = devm_rproc_alloc(dev, dev_name(dev), &k3_dsp_rproc_ops,
  77. fw_name, sizeof(*kproc));
  78. if (!rproc)
  79. return -ENOMEM;
  80. rproc->has_iommu = false;
  81. rproc->recovery_disabled = true;
  82. if (data->uses_lreset) {
  83. rproc->ops->prepare = k3_rproc_prepare;
  84. rproc->ops->unprepare = k3_rproc_unprepare;
  85. }
  86. kproc = rproc->priv;
  87. kproc->rproc = rproc;
  88. kproc->dev = dev;
  89. kproc->data = data;
  90. ret = k3_rproc_request_mbox(rproc);
  91. if (ret)
  92. return ret;
  93. kproc->ti_sci = devm_ti_sci_get_by_phandle(dev, "ti,sci");
  94. if (IS_ERR(kproc->ti_sci))
  95. return dev_err_probe(dev, PTR_ERR(kproc->ti_sci),
  96. "failed to get ti-sci handle\n");
  97. ret = of_property_read_u32(np, "ti,sci-dev-id", &kproc->ti_sci_id);
  98. if (ret)
  99. return dev_err_probe(dev, ret, "missing 'ti,sci-dev-id' property\n");
  100. kproc->reset = devm_reset_control_get_exclusive(dev, NULL);
  101. if (IS_ERR(kproc->reset))
  102. return dev_err_probe(dev, PTR_ERR(kproc->reset),
  103. "failed to get reset\n");
  104. kproc->tsp = ti_sci_proc_of_get_tsp(dev, kproc->ti_sci);
  105. if (IS_ERR(kproc->tsp))
  106. return dev_err_probe(dev, PTR_ERR(kproc->tsp),
  107. "failed to construct ti-sci proc control\n");
  108. ret = ti_sci_proc_request(kproc->tsp);
  109. if (ret < 0) {
  110. dev_err_probe(dev, ret, "ti_sci_proc_request failed\n");
  111. return ret;
  112. }
  113. ret = devm_add_action_or_reset(dev, k3_release_tsp, kproc->tsp);
  114. if (ret)
  115. return ret;
  116. ret = k3_rproc_of_get_memories(pdev, kproc);
  117. if (ret)
  118. return ret;
  119. ret = k3_reserved_mem_init(kproc);
  120. if (ret)
  121. return dev_err_probe(dev, ret, "reserved memory init failed\n");
  122. ret = kproc->ti_sci->ops.dev_ops.is_on(kproc->ti_sci, kproc->ti_sci_id,
  123. NULL, &p_state);
  124. if (ret)
  125. return dev_err_probe(dev, ret, "failed to get initial state, mode cannot be determined\n");
  126. /* configure J721E devices for either remoteproc or IPC-only mode */
  127. if (p_state) {
  128. dev_info(dev, "configured DSP for IPC-only mode\n");
  129. rproc->state = RPROC_DETACHED;
  130. } else {
  131. dev_info(dev, "configured DSP for remoteproc mode\n");
  132. }
  133. ret = devm_rproc_add(dev, rproc);
  134. if (ret)
  135. return dev_err_probe(dev, ret, "failed to add register device with remoteproc core\n");
  136. platform_set_drvdata(pdev, kproc);
  137. return 0;
  138. }
  139. static void k3_dsp_rproc_remove(struct platform_device *pdev)
  140. {
  141. struct k3_rproc *kproc = platform_get_drvdata(pdev);
  142. struct rproc *rproc = kproc->rproc;
  143. struct device *dev = &pdev->dev;
  144. int ret;
  145. if (rproc->state == RPROC_ATTACHED) {
  146. ret = rproc_detach(rproc);
  147. if (ret)
  148. dev_err(dev, "failed to detach proc (%pe)\n", ERR_PTR(ret));
  149. }
  150. }
  151. static const struct k3_rproc_mem_data c66_mems[] = {
  152. { .name = "l2sram", .dev_addr = 0x800000 },
  153. { .name = "l1pram", .dev_addr = 0xe00000 },
  154. { .name = "l1dram", .dev_addr = 0xf00000 },
  155. };
  156. /* C71x cores only have a L1P Cache, there are no L1P SRAMs */
  157. static const struct k3_rproc_mem_data c71_mems[] = {
  158. { .name = "l2sram", .dev_addr = 0x800000 },
  159. { .name = "l1dram", .dev_addr = 0xe00000 },
  160. };
  161. static const struct k3_rproc_mem_data c7xv_mems[] = {
  162. { .name = "l2sram", .dev_addr = 0x800000 },
  163. };
  164. static const struct k3_rproc_dev_data c66_data = {
  165. .mems = c66_mems,
  166. .num_mems = ARRAY_SIZE(c66_mems),
  167. .boot_align_addr = SZ_1K,
  168. .uses_lreset = true,
  169. };
  170. static const struct k3_rproc_dev_data c71_data = {
  171. .mems = c71_mems,
  172. .num_mems = ARRAY_SIZE(c71_mems),
  173. .boot_align_addr = SZ_2M,
  174. .uses_lreset = false,
  175. };
  176. static const struct k3_rproc_dev_data c7xv_data = {
  177. .mems = c7xv_mems,
  178. .num_mems = ARRAY_SIZE(c7xv_mems),
  179. .boot_align_addr = SZ_2M,
  180. .uses_lreset = false,
  181. };
  182. static const struct of_device_id k3_dsp_of_match[] = {
  183. { .compatible = "ti,j721e-c66-dsp", .data = &c66_data, },
  184. { .compatible = "ti,j721e-c71-dsp", .data = &c71_data, },
  185. { .compatible = "ti,j721s2-c71-dsp", .data = &c71_data, },
  186. { .compatible = "ti,am62a-c7xv-dsp", .data = &c7xv_data, },
  187. { /* sentinel */ },
  188. };
  189. MODULE_DEVICE_TABLE(of, k3_dsp_of_match);
  190. static struct platform_driver k3_dsp_rproc_driver = {
  191. .probe = k3_dsp_rproc_probe,
  192. .remove = k3_dsp_rproc_remove,
  193. .driver = {
  194. .name = "k3-dsp-rproc",
  195. .of_match_table = k3_dsp_of_match,
  196. },
  197. };
  198. module_platform_driver(k3_dsp_rproc_driver);
  199. MODULE_AUTHOR("Suman Anna <s-anna@ti.com>");
  200. MODULE_LICENSE("GPL v2");
  201. MODULE_DESCRIPTION("TI K3 DSP Remoteproc driver");