remoteproc.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Remote processor machine-specific module for OMAP4+ SoCs
  3. *
  4. * Copyright (C) 2011-2017 Texas Instruments Incorporated - http://www.ti.com/
  5. * Suman Anna <s-anna@ti.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * version 2 as published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #define pr_fmt(fmt) "%s: " fmt, __func__
  17. #include <linux/kernel.h>
  18. #include <plat/dmtimer.h>
  19. #include "omap_device.h"
  20. #include "remoteproc.h"
  21. /**
  22. * omap_rproc_device_enable - enable the remoteproc device
  23. * @pdev: the rproc platform device
  24. *
  25. * This function performs the necessary low-level functions to enable
  26. * a remoteproc device to start executing. This typically includes
  27. * releasing the reset lines, and enabling the clocks for the device.
  28. * We do not usually expect this function to fail.
  29. *
  30. * Return: 0 on success, or the return code from the failed function
  31. */
  32. int omap_rproc_device_enable(struct platform_device *pdev)
  33. {
  34. int ret = -EINVAL;
  35. /*
  36. * This reset management follows a device name check to differentiate
  37. * DSP and IPU processor subsystems. This check is weak and is ok for
  38. * now because of the dependencies against the pdata-quirks, where
  39. * the devices are given specific device names that satisfy the
  40. * criteria for the check. It can easily be replaced with a stronger
  41. * check like device node compatibility check, if needed.
  42. */
  43. if (strstr(dev_name(&pdev->dev), "dsp")) {
  44. ret = omap_device_deassert_hardreset(pdev, "dsp");
  45. if (ret)
  46. goto out;
  47. } else if (strstr(dev_name(&pdev->dev), "ipu")) {
  48. ret = omap_device_deassert_hardreset(pdev, "cpu0");
  49. if (ret)
  50. goto out;
  51. ret = omap_device_deassert_hardreset(pdev, "cpu1");
  52. if (ret)
  53. goto out;
  54. } else {
  55. pr_err("unsupported remoteproc\n");
  56. goto out;
  57. }
  58. ret = omap_device_enable(pdev);
  59. out:
  60. if (ret)
  61. pr_err("failed for proc %s\n", dev_name(&pdev->dev));
  62. return ret;
  63. }
  64. /**
  65. * omap_rproc_device_shutdown - shutdown the remoteproc device
  66. * @pdev: the rproc platform device
  67. *
  68. * This function performs the necessary low-level functions to shutdown
  69. * a remoteproc device. This typically includes disabling the clocks
  70. * for the device and asserting the associated reset lines. We do not
  71. * usually expect this function to fail.
  72. *
  73. * Return: 0 on success, or the return code from the failed function
  74. */
  75. int omap_rproc_device_shutdown(struct platform_device *pdev)
  76. {
  77. int ret = -EINVAL;
  78. ret = omap_device_idle(pdev);
  79. if (ret)
  80. goto out;
  81. /*
  82. * This reset management follows a device name check to differentiate
  83. * DSP and IPU processor subsystems. This check is weak and is ok for
  84. * now because of the dependencies against the pdata-quirks, where
  85. * the devices are given specific device names that satisfy the
  86. * criteria for the check. It can easily be replaced with a stronger
  87. * check like device node compatibility check, if needed.
  88. */
  89. if (strstr(dev_name(&pdev->dev), "dsp")) {
  90. ret = omap_device_assert_hardreset(pdev, "dsp");
  91. } else if (strstr(dev_name(&pdev->dev), "ipu")) {
  92. ret = omap_device_assert_hardreset(pdev, "cpu1");
  93. if (ret)
  94. goto out;
  95. ret = omap_device_assert_hardreset(pdev, "cpu0");
  96. if (ret)
  97. goto out;
  98. } else {
  99. pr_err("unsupported remoteproc\n");
  100. }
  101. out:
  102. if (ret)
  103. pr_err("failed for proc %s\n", dev_name(&pdev->dev));
  104. return ret;
  105. }
  106. /**
  107. * omap_rproc_request_timer - request a timer for a remoteproc
  108. * @np - device node pointer to the desired timer
  109. *
  110. * This function is used primarily to request a timer associated with
  111. * a remoteproc. The remoteproc driver core needs to store the returned
  112. * handle to invoke other timer specific ops (like starting a timer either
  113. * during device initialization or during a resume operation, or for
  114. * stopping/freeing a timer).
  115. *
  116. * Returns an OMAP timer handle on success, otherwise an equivalent ERR_PTR
  117. */
  118. struct omap_dm_timer *omap_rproc_request_timer(struct device_node *np)
  119. {
  120. struct omap_dm_timer *timer;
  121. int ret = 0;
  122. timer = omap_dm_timer_request_by_node(np);
  123. if (!timer) {
  124. pr_err("request for timer node %p failed\n", np);
  125. return ERR_PTR(-EBUSY);
  126. }
  127. ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_SYS_CLK);
  128. if (ret) {
  129. pr_err("error setting OMAP_TIMER_SRC_SYS_CLK as source for timer node %p\n",
  130. np);
  131. omap_dm_timer_free(timer);
  132. return ERR_PTR(ret);
  133. }
  134. /* clean counter, remoteproc code will set the value */
  135. omap_dm_timer_set_load(timer, 0, 0);
  136. return timer;
  137. }
  138. /**
  139. * omap_rproc_start_timer - start a timer for a remoteproc
  140. * @timer - handle to a OMAP timer
  141. *
  142. * This function is used to start a timer associated with a remoteproc,
  143. * obtained using the request_timer ops. The function needs to be invoked
  144. * by the remoteproc driver core to start the timer (during device
  145. * initialization) or to just resume the timer.
  146. *
  147. * Returns 0 on success, otherwise a failure as returned by DMTimer API
  148. */
  149. int omap_rproc_start_timer(struct omap_dm_timer *timer)
  150. {
  151. return omap_dm_timer_start(timer);
  152. }
  153. /**
  154. * omap_rproc_stop_timer - stop a timer for a remoteproc
  155. * @timer - handle to a struct omap_dm_timer
  156. *
  157. * This function is used to disable a timer associated with a remoteproc,
  158. * and needs to be called either during a device shutdown or suspend
  159. * operation. The separate function allows the remoteproc driver core to
  160. * just stop a timer without having to release the timer during a suspend
  161. * operation.
  162. *
  163. * Returns 0 on success, otherwise a failure as returned by DMTimer API
  164. */
  165. int omap_rproc_stop_timer(struct omap_dm_timer *timer)
  166. {
  167. return omap_dm_timer_stop(timer);
  168. }
  169. /**
  170. * omap_rproc_release_timer - release a timer for a remoteproc
  171. * @timer - handle to a struct omap_dm_timer
  172. *
  173. * This function is used primarily to release a timer associated with
  174. * a remoteproc. The dmtimer will be available for other clients to use
  175. * once released.
  176. *
  177. * Returns 0 on success, otherwise a failure as returned by DMTimer API
  178. */
  179. int omap_rproc_release_timer(struct omap_dm_timer *timer)
  180. {
  181. return omap_dm_timer_free(timer);
  182. }
  183. /**
  184. * omap_rproc_get_timer_irq - get the irq for a timer
  185. * @timer - handle to a OMAP timer
  186. *
  187. * This function is used to get the irq associated with a timer, obtained
  188. * using the request_timer ops. The function is called by the OMAP remoteproc
  189. * driver to register a interrupt handler to handle watchdog events on the
  190. * remote processor.
  191. *
  192. * Returns the irq id on success, otherwise a failure as returned by DMTimer API
  193. */
  194. int omap_rproc_get_timer_irq(struct omap_dm_timer *timer)
  195. {
  196. return omap_dm_timer_get_irq(timer);
  197. }
  198. /**
  199. * omap_rproc_ack_timer_irq - acknowledge a timer irq
  200. * @timer - handle to a OMAP timer
  201. *
  202. * This function is used to clear the irq associated with a timer, obtained
  203. * using the request_timer ops. The function is called by the OMAP remoteproc
  204. * driver upon a watchdog event on the remote processor to clear the interrupt
  205. * status of the watchdog timer.
  206. *
  207. * Returns the irq id on success, otherwise a failure as returned by DMTimer API
  208. */
  209. void omap_rproc_ack_timer_irq(struct omap_dm_timer *timer)
  210. {
  211. omap_dm_timer_write_status(timer, OMAP_TIMER_INT_OVERFLOW);
  212. }