msgqueue_0148cdec.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. /*
  2. * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  17. * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18. * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19. * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. * OTHER DEALINGS IN THE SOFTWARE.
  21. *
  22. */
  23. #include "msgqueue.h"
  24. #include <engine/falcon.h>
  25. #include <subdev/secboot.h>
  26. /*
  27. * This firmware runs on the SEC falcon. It only has one command and one
  28. * message queue, and uses a different command line and init message.
  29. */
  30. enum {
  31. MSGQUEUE_0148CDEC_COMMAND_QUEUE = 0,
  32. MSGQUEUE_0148CDEC_MESSAGE_QUEUE = 1,
  33. MSGQUEUE_0148CDEC_NUM_QUEUES,
  34. };
  35. struct msgqueue_0148cdec {
  36. struct nvkm_msgqueue base;
  37. struct nvkm_msgqueue_queue queue[MSGQUEUE_0148CDEC_NUM_QUEUES];
  38. };
  39. #define msgqueue_0148cdec(q) \
  40. container_of(q, struct msgqueue_0148cdec, base)
  41. static struct nvkm_msgqueue_queue *
  42. msgqueue_0148cdec_cmd_queue(struct nvkm_msgqueue *queue,
  43. enum msgqueue_msg_priority priority)
  44. {
  45. struct msgqueue_0148cdec *priv = msgqueue_0148cdec(queue);
  46. return &priv->queue[MSGQUEUE_0148CDEC_COMMAND_QUEUE];
  47. }
  48. static void
  49. msgqueue_0148cdec_process_msgs(struct nvkm_msgqueue *queue)
  50. {
  51. struct msgqueue_0148cdec *priv = msgqueue_0148cdec(queue);
  52. struct nvkm_msgqueue_queue *q_queue =
  53. &priv->queue[MSGQUEUE_0148CDEC_MESSAGE_QUEUE];
  54. nvkm_msgqueue_process_msgs(&priv->base, q_queue);
  55. }
  56. /* Init unit */
  57. #define MSGQUEUE_0148CDEC_UNIT_INIT 0x01
  58. enum {
  59. INIT_MSG_INIT = 0x0,
  60. };
  61. static void
  62. init_gen_cmdline(struct nvkm_msgqueue *queue, void *buf)
  63. {
  64. struct {
  65. u32 freq_hz;
  66. u32 falc_trace_size;
  67. u32 falc_trace_dma_base;
  68. u32 falc_trace_dma_idx;
  69. bool secure_mode;
  70. } *args = buf;
  71. args->secure_mode = false;
  72. }
  73. static int
  74. init_callback(struct nvkm_msgqueue *_queue, struct nvkm_msgqueue_hdr *hdr)
  75. {
  76. struct msgqueue_0148cdec *priv = msgqueue_0148cdec(_queue);
  77. struct {
  78. struct nvkm_msgqueue_msg base;
  79. u8 num_queues;
  80. u16 os_debug_entry_point;
  81. struct {
  82. u32 offset;
  83. u16 size;
  84. u8 index;
  85. u8 id;
  86. } queue_info[MSGQUEUE_0148CDEC_NUM_QUEUES];
  87. u16 sw_managed_area_offset;
  88. u16 sw_managed_area_size;
  89. } *init = (void *)hdr;
  90. const struct nvkm_subdev *subdev = _queue->falcon->owner;
  91. int i;
  92. if (init->base.hdr.unit_id != MSGQUEUE_0148CDEC_UNIT_INIT) {
  93. nvkm_error(subdev, "expected message from init unit\n");
  94. return -EINVAL;
  95. }
  96. if (init->base.msg_type != INIT_MSG_INIT) {
  97. nvkm_error(subdev, "expected SEC init msg\n");
  98. return -EINVAL;
  99. }
  100. for (i = 0; i < MSGQUEUE_0148CDEC_NUM_QUEUES; i++) {
  101. u8 id = init->queue_info[i].id;
  102. struct nvkm_msgqueue_queue *queue = &priv->queue[id];
  103. mutex_init(&queue->mutex);
  104. queue->index = init->queue_info[i].index;
  105. queue->offset = init->queue_info[i].offset;
  106. queue->size = init->queue_info[i].size;
  107. if (id == MSGQUEUE_0148CDEC_MESSAGE_QUEUE) {
  108. queue->head_reg = 0xa30 + (queue->index * 8);
  109. queue->tail_reg = 0xa34 + (queue->index * 8);
  110. } else {
  111. queue->head_reg = 0xa00 + (queue->index * 8);
  112. queue->tail_reg = 0xa04 + (queue->index * 8);
  113. }
  114. nvkm_debug(subdev,
  115. "queue %d: index %d, offset 0x%08x, size 0x%08x\n",
  116. id, queue->index, queue->offset, queue->size);
  117. }
  118. complete_all(&_queue->init_done);
  119. return 0;
  120. }
  121. static const struct nvkm_msgqueue_init_func
  122. msgqueue_0148cdec_init_func = {
  123. .gen_cmdline = init_gen_cmdline,
  124. .init_callback = init_callback,
  125. };
  126. /* ACR unit */
  127. #define MSGQUEUE_0148CDEC_UNIT_ACR 0x08
  128. enum {
  129. ACR_CMD_BOOTSTRAP_FALCON = 0x00,
  130. };
  131. static void
  132. acr_boot_falcon_callback(struct nvkm_msgqueue *priv,
  133. struct nvkm_msgqueue_hdr *hdr)
  134. {
  135. struct acr_bootstrap_falcon_msg {
  136. struct nvkm_msgqueue_msg base;
  137. u32 error_code;
  138. u32 falcon_id;
  139. } *msg = (void *)hdr;
  140. const struct nvkm_subdev *subdev = priv->falcon->owner;
  141. u32 falcon_id = msg->falcon_id;
  142. if (msg->error_code) {
  143. nvkm_error(subdev, "in bootstrap falcon callback:\n");
  144. nvkm_error(subdev, "expected error code 0x%x\n",
  145. msg->error_code);
  146. return;
  147. }
  148. if (falcon_id >= NVKM_SECBOOT_FALCON_END) {
  149. nvkm_error(subdev, "in bootstrap falcon callback:\n");
  150. nvkm_error(subdev, "invalid falcon ID 0x%x\n", falcon_id);
  151. return;
  152. }
  153. nvkm_debug(subdev, "%s booted\n", nvkm_secboot_falcon_name[falcon_id]);
  154. }
  155. enum {
  156. ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES = 0,
  157. ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_NO = 1,
  158. };
  159. static int
  160. acr_boot_falcon(struct nvkm_msgqueue *priv, enum nvkm_secboot_falcon falcon)
  161. {
  162. DECLARE_COMPLETION_ONSTACK(completed);
  163. /*
  164. * flags - Flag specifying RESET or no RESET.
  165. * falcon id - Falcon id specifying falcon to bootstrap.
  166. */
  167. struct {
  168. struct nvkm_msgqueue_hdr hdr;
  169. u8 cmd_type;
  170. u32 flags;
  171. u32 falcon_id;
  172. } cmd;
  173. memset(&cmd, 0, sizeof(cmd));
  174. cmd.hdr.unit_id = MSGQUEUE_0148CDEC_UNIT_ACR;
  175. cmd.hdr.size = sizeof(cmd);
  176. cmd.cmd_type = ACR_CMD_BOOTSTRAP_FALCON;
  177. cmd.flags = ACR_CMD_BOOTSTRAP_FALCON_FLAGS_RESET_YES;
  178. cmd.falcon_id = falcon;
  179. nvkm_msgqueue_post(priv, MSGQUEUE_MSG_PRIORITY_HIGH, &cmd.hdr,
  180. acr_boot_falcon_callback, &completed, true);
  181. if (!wait_for_completion_timeout(&completed, msecs_to_jiffies(1000)))
  182. return -ETIMEDOUT;
  183. return 0;
  184. }
  185. const struct nvkm_msgqueue_acr_func
  186. msgqueue_0148cdec_acr_func = {
  187. .boot_falcon = acr_boot_falcon,
  188. };
  189. static void
  190. msgqueue_0148cdec_dtor(struct nvkm_msgqueue *queue)
  191. {
  192. kfree(msgqueue_0148cdec(queue));
  193. }
  194. const struct nvkm_msgqueue_func
  195. msgqueue_0148cdec_func = {
  196. .init_func = &msgqueue_0148cdec_init_func,
  197. .acr_func = &msgqueue_0148cdec_acr_func,
  198. .cmd_queue = msgqueue_0148cdec_cmd_queue,
  199. .recv = msgqueue_0148cdec_process_msgs,
  200. .dtor = msgqueue_0148cdec_dtor,
  201. };
  202. int
  203. msgqueue_0148cdec_new(struct nvkm_falcon *falcon, const struct nvkm_secboot *sb,
  204. struct nvkm_msgqueue **queue)
  205. {
  206. struct msgqueue_0148cdec *ret;
  207. ret = kzalloc(sizeof(*ret), GFP_KERNEL);
  208. if (!ret)
  209. return -ENOMEM;
  210. *queue = &ret->base;
  211. nvkm_msgqueue_ctor(&msgqueue_0148cdec_func, falcon, &ret->base);
  212. return 0;
  213. }