jr.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * Copyright 2008-2014 Freescale Semiconductor, Inc.
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. *
  6. * Based on CAAM driver in drivers/crypto/caam in Linux
  7. */
  8. #include <common.h>
  9. #include <malloc.h>
  10. #include "fsl_sec.h"
  11. #include "jr.h"
  12. #define CIRC_CNT(head, tail, size) (((head) - (tail)) & (size - 1))
  13. #define CIRC_SPACE(head, tail, size) CIRC_CNT((tail), (head) + 1, (size))
  14. struct jobring jr;
  15. static inline void start_jr0(void)
  16. {
  17. ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
  18. u32 ctpr_ms = sec_in32(&sec->ctpr_ms);
  19. u32 scfgr = sec_in32(&sec->scfgr);
  20. if (ctpr_ms & SEC_CTPR_MS_VIRT_EN_INCL) {
  21. /* VIRT_EN_INCL = 1 & VIRT_EN_POR = 1 or
  22. * VIRT_EN_INCL = 1 & VIRT_EN_POR = 0 & SEC_SCFGR_VIRT_EN = 1
  23. */
  24. if ((ctpr_ms & SEC_CTPR_MS_VIRT_EN_POR) ||
  25. (!(ctpr_ms & SEC_CTPR_MS_VIRT_EN_POR) &&
  26. (scfgr & SEC_SCFGR_VIRT_EN)))
  27. sec_out32(&sec->jrstartr, CONFIG_JRSTARTR_JR0);
  28. } else {
  29. /* VIRT_EN_INCL = 0 && VIRT_EN_POR_VALUE = 1 */
  30. if (ctpr_ms & SEC_CTPR_MS_VIRT_EN_POR)
  31. sec_out32(&sec->jrstartr, CONFIG_JRSTARTR_JR0);
  32. }
  33. }
  34. static inline void jr_reset_liodn(void)
  35. {
  36. ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
  37. sec_out32(&sec->jrliodnr[0].ls, 0);
  38. }
  39. static inline void jr_disable_irq(void)
  40. {
  41. struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
  42. uint32_t jrcfg = sec_in32(&regs->jrcfg1);
  43. jrcfg = jrcfg | JR_INTMASK;
  44. sec_out32(&regs->jrcfg1, jrcfg);
  45. }
  46. static void jr_initregs(void)
  47. {
  48. struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
  49. phys_addr_t ip_base = virt_to_phys((void *)jr.input_ring);
  50. phys_addr_t op_base = virt_to_phys((void *)jr.output_ring);
  51. #ifdef CONFIG_PHYS_64BIT
  52. sec_out32(&regs->irba_h, ip_base >> 32);
  53. #else
  54. sec_out32(&regs->irba_h, 0x0);
  55. #endif
  56. sec_out32(&regs->irba_l, (uint32_t)ip_base);
  57. #ifdef CONFIG_PHYS_64BIT
  58. sec_out32(&regs->orba_h, op_base >> 32);
  59. #else
  60. sec_out32(&regs->orba_h, 0x0);
  61. #endif
  62. sec_out32(&regs->orba_l, (uint32_t)op_base);
  63. sec_out32(&regs->ors, JR_SIZE);
  64. sec_out32(&regs->irs, JR_SIZE);
  65. if (!jr.irq)
  66. jr_disable_irq();
  67. }
  68. static int jr_init(void)
  69. {
  70. memset(&jr, 0, sizeof(struct jobring));
  71. jr.jq_id = DEFAULT_JR_ID;
  72. jr.irq = DEFAULT_IRQ;
  73. #ifdef CONFIG_FSL_CORENET
  74. jr.liodn = DEFAULT_JR_LIODN;
  75. #endif
  76. jr.size = JR_SIZE;
  77. jr.input_ring = (dma_addr_t *)malloc(JR_SIZE * sizeof(dma_addr_t));
  78. if (!jr.input_ring)
  79. return -1;
  80. jr.output_ring =
  81. (struct op_ring *)malloc(JR_SIZE * sizeof(struct op_ring));
  82. if (!jr.output_ring)
  83. return -1;
  84. memset(jr.input_ring, 0, JR_SIZE * sizeof(dma_addr_t));
  85. memset(jr.output_ring, 0, JR_SIZE * sizeof(struct op_ring));
  86. start_jr0();
  87. jr_initregs();
  88. return 0;
  89. }
  90. static int jr_sw_cleanup(void)
  91. {
  92. jr.head = 0;
  93. jr.tail = 0;
  94. jr.read_idx = 0;
  95. jr.write_idx = 0;
  96. memset(jr.info, 0, sizeof(jr.info));
  97. memset(jr.input_ring, 0, jr.size * sizeof(dma_addr_t));
  98. memset(jr.output_ring, 0, jr.size * sizeof(struct op_ring));
  99. return 0;
  100. }
  101. static int jr_hw_reset(void)
  102. {
  103. struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
  104. uint32_t timeout = 100000;
  105. uint32_t jrint, jrcr;
  106. sec_out32(&regs->jrcr, JRCR_RESET);
  107. do {
  108. jrint = sec_in32(&regs->jrint);
  109. } while (((jrint & JRINT_ERR_HALT_MASK) ==
  110. JRINT_ERR_HALT_INPROGRESS) && --timeout);
  111. jrint = sec_in32(&regs->jrint);
  112. if (((jrint & JRINT_ERR_HALT_MASK) !=
  113. JRINT_ERR_HALT_INPROGRESS) && timeout == 0)
  114. return -1;
  115. timeout = 100000;
  116. sec_out32(&regs->jrcr, JRCR_RESET);
  117. do {
  118. jrcr = sec_in32(&regs->jrcr);
  119. } while ((jrcr & JRCR_RESET) && --timeout);
  120. if (timeout == 0)
  121. return -1;
  122. return 0;
  123. }
  124. /* -1 --- error, can't enqueue -- no space available */
  125. static int jr_enqueue(uint32_t *desc_addr,
  126. void (*callback)(uint32_t desc, uint32_t status, void *arg),
  127. void *arg)
  128. {
  129. struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
  130. int head = jr.head;
  131. dma_addr_t desc_phys_addr = virt_to_phys(desc_addr);
  132. if (sec_in32(&regs->irsa) == 0 ||
  133. CIRC_SPACE(jr.head, jr.tail, jr.size) <= 0)
  134. return -1;
  135. jr.input_ring[head] = desc_phys_addr;
  136. jr.info[head].desc_phys_addr = desc_phys_addr;
  137. jr.info[head].desc_addr = (uint32_t)desc_addr;
  138. jr.info[head].callback = (void *)callback;
  139. jr.info[head].arg = arg;
  140. jr.info[head].op_done = 0;
  141. jr.head = (head + 1) & (jr.size - 1);
  142. sec_out32(&regs->irja, 1);
  143. return 0;
  144. }
  145. static int jr_dequeue(void)
  146. {
  147. struct jr_regs *regs = (struct jr_regs *)CONFIG_SYS_FSL_JR0_ADDR;
  148. int head = jr.head;
  149. int tail = jr.tail;
  150. int idx, i, found;
  151. void (*callback)(uint32_t desc, uint32_t status, void *arg);
  152. void *arg = NULL;
  153. while (sec_in32(&regs->orsf) && CIRC_CNT(jr.head, jr.tail, jr.size)) {
  154. found = 0;
  155. dma_addr_t op_desc = jr.output_ring[jr.tail].desc;
  156. uint32_t status = jr.output_ring[jr.tail].status;
  157. uint32_t desc_virt;
  158. for (i = 0; CIRC_CNT(head, tail + i, jr.size) >= 1; i++) {
  159. idx = (tail + i) & (jr.size - 1);
  160. if (op_desc == jr.info[idx].desc_phys_addr) {
  161. desc_virt = jr.info[idx].desc_addr;
  162. found = 1;
  163. break;
  164. }
  165. }
  166. /* Error condition if match not found */
  167. if (!found)
  168. return -1;
  169. jr.info[idx].op_done = 1;
  170. callback = (void *)jr.info[idx].callback;
  171. arg = jr.info[idx].arg;
  172. /* When the job on tail idx gets done, increment
  173. * tail till the point where job completed out of oredr has
  174. * been taken into account
  175. */
  176. if (idx == tail)
  177. do {
  178. tail = (tail + 1) & (jr.size - 1);
  179. } while (jr.info[tail].op_done);
  180. jr.tail = tail;
  181. jr.read_idx = (jr.read_idx + 1) & (jr.size - 1);
  182. sec_out32(&regs->orjr, 1);
  183. jr.info[idx].op_done = 0;
  184. callback(desc_virt, status, arg);
  185. }
  186. return 0;
  187. }
  188. static void desc_done(uint32_t desc, uint32_t status, void *arg)
  189. {
  190. struct result *x = arg;
  191. x->status = status;
  192. caam_jr_strstatus(status);
  193. x->done = 1;
  194. }
  195. int run_descriptor_jr(uint32_t *desc)
  196. {
  197. unsigned long long timeval = get_ticks();
  198. unsigned long long timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
  199. struct result op;
  200. int ret = 0;
  201. memset(&op, sizeof(op), 0);
  202. ret = jr_enqueue(desc, desc_done, &op);
  203. if (ret) {
  204. debug("Error in SEC enq\n");
  205. ret = JQ_ENQ_ERR;
  206. goto out;
  207. }
  208. timeval = get_ticks();
  209. timeout = usec2ticks(CONFIG_SEC_DEQ_TIMEOUT);
  210. while (op.done != 1) {
  211. ret = jr_dequeue();
  212. if (ret) {
  213. debug("Error in SEC deq\n");
  214. ret = JQ_DEQ_ERR;
  215. goto out;
  216. }
  217. if ((get_ticks() - timeval) > timeout) {
  218. debug("SEC Dequeue timed out\n");
  219. ret = JQ_DEQ_TO_ERR;
  220. goto out;
  221. }
  222. }
  223. if (!op.status) {
  224. debug("Error %x\n", op.status);
  225. ret = op.status;
  226. }
  227. out:
  228. return ret;
  229. }
  230. int jr_reset(void)
  231. {
  232. if (jr_hw_reset() < 0)
  233. return -1;
  234. /* Clean up the jobring structure maintained by software */
  235. jr_sw_cleanup();
  236. return 0;
  237. }
  238. int sec_reset(void)
  239. {
  240. ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
  241. uint32_t mcfgr = sec_in32(&sec->mcfgr);
  242. uint32_t timeout = 100000;
  243. mcfgr |= MCFGR_SWRST;
  244. sec_out32(&sec->mcfgr, mcfgr);
  245. mcfgr |= MCFGR_DMA_RST;
  246. sec_out32(&sec->mcfgr, mcfgr);
  247. do {
  248. mcfgr = sec_in32(&sec->mcfgr);
  249. } while ((mcfgr & MCFGR_DMA_RST) == MCFGR_DMA_RST && --timeout);
  250. if (timeout == 0)
  251. return -1;
  252. timeout = 100000;
  253. do {
  254. mcfgr = sec_in32(&sec->mcfgr);
  255. } while ((mcfgr & MCFGR_SWRST) == MCFGR_SWRST && --timeout);
  256. if (timeout == 0)
  257. return -1;
  258. return 0;
  259. }
  260. int sec_init(void)
  261. {
  262. int ret = 0;
  263. #ifdef CONFIG_PHYS_64BIT
  264. ccsr_sec_t *sec = (void *)CONFIG_SYS_FSL_SEC_ADDR;
  265. uint32_t mcr = sec_in32(&sec->mcfgr);
  266. sec_out32(&sec->mcfgr, mcr | 1 << MCFGR_PS_SHIFT);
  267. #endif
  268. ret = jr_init();
  269. if (ret < 0)
  270. return -1;
  271. return ret;
  272. }