xref: /optee_os/core/drivers/crypto/caam/caam_jr.c (revision 12fc37711783247b0d05fdc271ef007f4930767b)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright 2018-2019 NXP
4  *
5  * Brief   CAAM Job Rings manager.
6  *         Implementation of functions to enqueue/dequeue CAAM Job Descriptor
7  */
8 #include <caam_hal_clk.h>
9 #include <caam_common.h>
10 #include <caam_desc_helper.h>
11 #include <caam_hal_clk.h>
12 #include <caam_hal_jr.h>
13 #include <caam_io.h>
14 #include <caam_jr.h>
15 #include <caam_rng.h>
16 #include <caam_utils_delay.h>
17 #include <caam_utils_mem.h>
18 #include <kernel/interrupt.h>
19 #include <kernel/panic.h>
20 #include <kernel/pm.h>
21 #include <kernel/spinlock.h>
22 #include <mm/core_memprot.h>
23 #include <tee/cache.h>
24 
25 /*
26  * Job Free define
27  */
28 #define JR_JOB_FREE	0
29 
30 /*
31  * Caller information context object
32  */
33 struct caller_info {
34 	struct caam_jobctx *jobctx; /* Caller job context object */
35 	uint32_t job_id;            /* Current Job ID */
36 	paddr_t pdesc;              /* Physical address of the descriptor */
37 };
38 
39 /*
40  * Job Ring module private data
41  */
42 struct jr_privdata {
43 	vaddr_t baseaddr;        /* Job Ring base address */
44 
45 	vaddr_t ctrladdr;        /* CAAM virtual base address */
46 	paddr_t jroffset;        /* Job Ring address offset */
47 	uint64_t paddr_inrings;  /* CAAM physical addr of input queue */
48 	uint64_t paddr_outrings; /* CAAM physical addr of output queue */
49 
50 	uint8_t nb_jobs;         /* Number of Job ring entries managed */
51 
52 	/* Input Job Ring Variables */
53 	struct caam_inring_entry *inrings; /* Input JR HW queue */
54 	unsigned int inlock;          /* Input JR spin lock */
55 	uint16_t inwrite_index;       /* SW Index - next JR entry free */
56 
57 	/* Output Job Ring Variables */
58 	struct caam_outring_entry *outrings; /* Output JR HW queue */
59 	unsigned int outlock;           /* Output JR spin lock */
60 	uint16_t outread_index;         /* SW Index - next JR output done */
61 
62 	/* Caller Information Variables */
63 	struct caller_info *callers;    /* Job Ring Caller information */
64 	unsigned int callers_lock;      /* Job Ring Caller spin lock */
65 
66 	struct itr_handler it_handler;  /* Interrupt handler */
67 };
68 
69 /*
70  * Job Ring module private data reference
71  */
72 static struct jr_privdata *jr_privdata;
73 
74 /*
75  * Free module resources
76  *
77  * @jr_priv   Reference to the module private data
78  */
79 static void do_jr_free(struct jr_privdata *jr_priv)
80 {
81 	if (jr_priv) {
82 		caam_free(jr_priv->inrings);
83 		caam_free(jr_priv->outrings);
84 		caam_free(jr_priv->callers);
85 		caam_free(jr_priv);
86 	}
87 }
88 
89 /*
90  * Allocate module resources
91  *
92  * @privdata  [out] Allocated Job Ring private data
93  * @nb_jobs   Number of jobs to manage in the queue
94  */
95 static enum caam_status do_jr_alloc(struct jr_privdata **privdata,
96 				    uint8_t nb_jobs)
97 {
98 	enum caam_status retstatus = CAAM_OUT_MEMORY;
99 	struct jr_privdata *jr_priv = NULL;
100 
101 	/* Allocate the Job Ring private data */
102 	jr_priv = caam_calloc(sizeof(*jr_priv));
103 
104 	if (!jr_priv) {
105 		JR_TRACE("Private Data allocation error");
106 		goto end_alloc;
107 	}
108 
109 	/* Setup the number of jobs */
110 	jr_priv->nb_jobs = nb_jobs;
111 
112 	/* Allocate the input and output job ring queues */
113 	jr_priv->inrings =
114 		caam_calloc_align(nb_jobs * sizeof(struct caam_inring_entry));
115 	jr_priv->outrings =
116 		caam_calloc_align(nb_jobs * sizeof(struct caam_outring_entry));
117 
118 	/* Allocate the callers information */
119 	jr_priv->callers = caam_calloc(nb_jobs * sizeof(struct caller_info));
120 
121 	if (!jr_priv->inrings || !jr_priv->outrings || !jr_priv->callers) {
122 		JR_TRACE("JR resources allocation error");
123 		goto end_alloc;
124 	}
125 
126 	/* Initialize the spin locks */
127 	jr_priv->inlock = SPINLOCK_UNLOCK;
128 	jr_priv->outlock = SPINLOCK_UNLOCK;
129 	jr_priv->callers_lock = SPINLOCK_UNLOCK;
130 
131 	/* Initialize the queue counter */
132 	jr_priv->inwrite_index = 0;
133 	jr_priv->outread_index = 0;
134 
135 	/*
136 	 * Ensure that allocated queue initialization is pushed to the physical
137 	 * memory
138 	 */
139 	cache_operation(TEE_CACHEFLUSH, jr_priv->inrings,
140 			nb_jobs * sizeof(struct caam_inring_entry));
141 	cache_operation(TEE_CACHEFLUSH, jr_priv->outrings,
142 			nb_jobs * sizeof(struct caam_outring_entry));
143 
144 	retstatus = CAAM_NO_ERROR;
145 end_alloc:
146 	if (retstatus != CAAM_NO_ERROR)
147 		do_jr_free(jr_priv);
148 	else
149 		*privdata = jr_priv;
150 
151 	return retstatus;
152 }
153 
154 /*
155  * Job Ring Interrupt handler
156  *
157  * @handler  Interrupt Handler structure
158  */
159 static enum itr_return caam_jr_irqhandler(struct itr_handler *handler)
160 {
161 	JR_TRACE("Disable the interrupt");
162 	itr_disable(handler->it);
163 
164 	/* Send a signal to exit WFE loop */
165 	sev();
166 
167 	return ITRR_HANDLED;
168 }
169 
170 /*
171  * Returns all jobs completed depending on the input @wait_job_ids mask.
172  *
173  * Dequeues all Jobs completed. Call the job context callback
174  * function. Function returns the bit mask of the expected completed job
175  * (@wait_job_ids parameter)
176  *
177  * @wait_job_ids  Expected Jobs to be complete
178  */
179 static uint32_t do_jr_dequeue(uint32_t wait_job_ids)
180 {
181 	uint32_t ret_job_id = 0;
182 	struct caller_info *caller = NULL;
183 	struct caam_outring_entry *jr_out = NULL;
184 	struct caam_jobctx *jobctx = NULL;
185 	uint32_t exceptions = 0;
186 	bool found = false;
187 	uint16_t idx_jr = 0;
188 	uint32_t nb_jobs_done = 0;
189 	size_t nb_jobs_inv = 0;
190 
191 	exceptions = cpu_spin_lock_xsave(&jr_privdata->outlock);
192 
193 	nb_jobs_done = caam_hal_jr_get_nbjob_done(jr_privdata->baseaddr);
194 
195 	if (nb_jobs_done == 0) {
196 		cpu_spin_unlock_xrestore(&jr_privdata->outlock, exceptions);
197 		return ret_job_id;
198 	}
199 
200 	/* Ensure that output ring descriptor entries are not in cache */
201 	if ((jr_privdata->outread_index + nb_jobs_done) >
202 	    jr_privdata->nb_jobs) {
203 		/*
204 		 * Invalidate the whole circular job buffer because some
205 		 * completed job rings are at the beginning of the buffer
206 		 */
207 		jr_out = jr_privdata->outrings;
208 		nb_jobs_inv = jr_privdata->nb_jobs;
209 	} else {
210 		/* Invalidate only the completed job */
211 		jr_out = &jr_privdata->outrings[jr_privdata->outread_index];
212 		nb_jobs_inv = nb_jobs_done;
213 	}
214 
215 	cache_operation(TEE_CACHEINVALIDATE, jr_out,
216 			sizeof(struct caam_outring_entry) * nb_jobs_inv);
217 
218 	for (; nb_jobs_done; nb_jobs_done--) {
219 		jr_out = &jr_privdata->outrings[jr_privdata->outread_index];
220 
221 		/*
222 		 * Lock the caller information array because enqueue is
223 		 * also touching it
224 		 */
225 		cpu_spin_lock(&jr_privdata->callers_lock);
226 		for (idx_jr = 0, found = false; idx_jr < jr_privdata->nb_jobs;
227 		     idx_jr++) {
228 			/*
229 			 * Search for the caller information corresponding to
230 			 * the completed JR.
231 			 * Don't use the outread_index or inwrite_index because
232 			 * completion can be out of order compared to input
233 			 * buffer
234 			 */
235 			caller = &jr_privdata->callers[idx_jr];
236 			if (caam_desc_pop(jr_out) == caller->pdesc) {
237 				jobctx = caller->jobctx;
238 				jobctx->status = caam_read_jobstatus(jr_out);
239 
240 				/* Update return Job IDs mask */
241 				if (caller->job_id & wait_job_ids)
242 					ret_job_id |= caller->job_id;
243 
244 				JR_TRACE("JR id=%" PRId32
245 					 ", context @0x%08" PRIxVA,
246 					 caller->job_id, (vaddr_t)jobctx);
247 				/* Clear the Entry Descriptor DMA */
248 				caller->pdesc = 0;
249 				caller->jobctx = NULL;
250 				caller->job_id = JR_JOB_FREE;
251 				found = true;
252 				JR_TRACE("Free space #%" PRId16
253 					 " in the callers array",
254 					 idx_jr);
255 				break;
256 			}
257 		}
258 		cpu_spin_unlock(&jr_privdata->callers_lock);
259 
260 		/*
261 		 * Remove the JR from the output list even if no
262 		 * JR caller found
263 		 */
264 		caam_hal_jr_del_job(jr_privdata->baseaddr);
265 
266 		/*
267 		 * Increment index to next JR output entry taking care that
268 		 * it is a circular buffer of nb_jobs size.
269 		 */
270 		jr_privdata->outread_index++;
271 		jr_privdata->outread_index %= jr_privdata->nb_jobs;
272 
273 		if (found && jobctx->callback) {
274 			/* Finally, execute user's callback */
275 			jobctx->callback(jobctx);
276 		}
277 	}
278 
279 	cpu_spin_unlock_xrestore(&jr_privdata->outlock, exceptions);
280 
281 	return ret_job_id;
282 }
283 
284 /*
285  * Enqueues a new job in the Job Ring input queue. Keep the caller's
286  * job context in private array.
287  *
288  * @jobctx   Caller's job context
289  * @job_id   [out] Job ID enqueued
290  */
291 static enum caam_status do_jr_enqueue(struct caam_jobctx *jobctx,
292 				      uint32_t *job_id)
293 {
294 	enum caam_status retstatus = CAAM_BUSY;
295 	struct caam_inring_entry *cur_inrings = NULL;
296 	struct caller_info *caller = NULL;
297 	uint32_t exceptions = 0;
298 	uint32_t job_mask = 0;
299 	uint8_t idx_jr = 0;
300 	bool found = false;
301 
302 	exceptions = cpu_spin_lock_xsave(&jr_privdata->inlock);
303 
304 	caam_hal_clk_enable(true);
305 
306 	/*
307 	 * Stay locked until a job is available
308 	 * Check if there is an available JR index in the HW
309 	 */
310 	while (caam_hal_jr_read_nbslot_available(jr_privdata->baseaddr) == 0) {
311 		/*
312 		 * WFE will return thanks to a SEV generated by the
313 		 * interrupt handler or by a spin_unlock
314 		 */
315 		wfe();
316 	};
317 
318 	/*
319 	 * There is a space free in the input ring but it doesn't mean
320 	 * that the job pushed is completed.
321 	 * Completion is out of order. Look for a free space in the
322 	 * caller data to push them and get a job ID for the completion
323 	 *
324 	 * Lock the caller information array because dequeue is
325 	 * also touching it
326 	 */
327 	cpu_spin_lock(&jr_privdata->callers_lock);
328 	for (idx_jr = 0; idx_jr < jr_privdata->nb_jobs; idx_jr++) {
329 		if (jr_privdata->callers[idx_jr].job_id == JR_JOB_FREE) {
330 			JR_TRACE("Found a space #%" PRId8
331 				 " free in the callers array",
332 				 idx_jr);
333 			job_mask = 1 << idx_jr;
334 
335 			/* Store the caller information for the JR completion */
336 			caller = &jr_privdata->callers[idx_jr];
337 			caller->job_id = job_mask;
338 			caller->jobctx = jobctx;
339 			caller->pdesc = virt_to_phys((void *)jobctx->desc);
340 
341 			found = true;
342 			break;
343 		}
344 	}
345 	cpu_spin_unlock(&jr_privdata->callers_lock);
346 
347 	if (!found) {
348 		JR_TRACE("Error didn't find a free space in the callers array");
349 		goto end_enqueue;
350 	}
351 
352 	JR_TRACE("Push id=%" PRId16 ", job (0x%08" PRIx32
353 		 ") context @0x%08" PRIxVA,
354 		 jr_privdata->inwrite_index, job_mask, (vaddr_t)jobctx);
355 
356 	cur_inrings = &jr_privdata->inrings[jr_privdata->inwrite_index];
357 
358 	/* Push the descriptor into the JR HW list */
359 	caam_desc_push(cur_inrings, caller->pdesc);
360 
361 	/* Ensure that physical memory is up to date */
362 	cache_operation(TEE_CACHECLEAN, cur_inrings,
363 			sizeof(struct caam_inring_entry));
364 
365 	/*
366 	 * Increment index to next JR input entry taking care that
367 	 * it is a circular buffer of nb_jobs size.
368 	 */
369 	jr_privdata->inwrite_index++;
370 	jr_privdata->inwrite_index %= jr_privdata->nb_jobs;
371 
372 	/* Ensure that input descriptor is pushed in physical memory */
373 	cache_operation(TEE_CACHECLEAN, jobctx->desc,
374 			DESC_SZBYTES(caam_desc_get_len(jobctx->desc)));
375 
376 	/* Inform HW that a new JR is available */
377 	caam_hal_jr_add_newjob(jr_privdata->baseaddr);
378 
379 	*job_id = job_mask;
380 	retstatus = CAAM_NO_ERROR;
381 
382 end_enqueue:
383 	cpu_spin_unlock_xrestore(&jr_privdata->inlock, exceptions);
384 
385 	return retstatus;
386 }
387 
388 /*
389  * Synchronous job completion callback
390  *
391  * @jobctx   Job context
392  */
393 static void job_done(struct caam_jobctx *jobctx)
394 {
395 	jobctx->completion = true;
396 }
397 
398 void caam_jr_cancel(uint32_t job_id)
399 {
400 	unsigned int idx = 0;
401 
402 	cpu_spin_lock(&jr_privdata->callers_lock);
403 
404 	JR_TRACE("Job cancel 0x%" PRIx32, job_id);
405 	for (idx = 0; idx < jr_privdata->nb_jobs; idx++) {
406 		/*
407 		 * Search for the caller information corresponding to
408 		 * the job_id mask.
409 		 */
410 		if (jr_privdata->callers[idx].job_id == job_id) {
411 			/* Clear the Entry Descriptor */
412 			jr_privdata->callers[idx].pdesc = 0;
413 			jr_privdata->callers[idx].jobctx = NULL;
414 			jr_privdata->callers[idx].job_id = JR_JOB_FREE;
415 			return;
416 		}
417 	}
418 
419 	cpu_spin_unlock(&jr_privdata->callers_lock);
420 }
421 
422 enum caam_status caam_jr_dequeue(uint32_t job_ids, unsigned int timeout_ms)
423 {
424 	uint32_t job_complete = 0;
425 	uint32_t nb_loop = 0;
426 	bool infinite = false;
427 	bool it_active = false;
428 
429 	if (timeout_ms == UINT_MAX)
430 		infinite = true;
431 	else
432 		nb_loop = timeout_ms * 100;
433 
434 	do {
435 		/* Call the do_jr_dequeue function to dequeue the jobs */
436 		job_complete = do_jr_dequeue(job_ids);
437 
438 		/* Check if new job has been submitted and acknowledge it */
439 		it_active = caam_hal_jr_check_ack_itr(jr_privdata->baseaddr);
440 
441 		if (job_complete & job_ids)
442 			return CAAM_NO_ERROR;
443 
444 		/* Check if JR interrupt otherwise wait a bit */
445 		if (!it_active)
446 			caam_udelay(10);
447 	} while (infinite || (nb_loop--));
448 
449 	return CAAM_TIMEOUT;
450 }
451 
452 enum caam_status caam_jr_enqueue(struct caam_jobctx *jobctx, uint32_t *job_id)
453 {
454 	enum caam_status retstatus = CAAM_FAILURE;
455 	__maybe_unused int timeout  = 10; /* Nb loops to pool job completion */
456 
457 	if (!jobctx)
458 		return CAAM_BAD_PARAM;
459 
460 	JR_DUMPDESC(jobctx->desc);
461 
462 	if (!jobctx->callback && job_id) {
463 		JR_TRACE("Job Callback not defined whereas asynchronous");
464 		return CAAM_BAD_PARAM;
465 	}
466 
467 	if (jobctx->callback && !job_id) {
468 		JR_TRACE("Job Id not defined whereas asynchronous");
469 		return CAAM_BAD_PARAM;
470 	}
471 
472 	jobctx->completion = false;
473 	jobctx->status = 0;
474 
475 	/*
476 	 * If parameter job_id is NULL, the job is synchronous, hence use
477 	 * the local job_done callback function
478 	 */
479 	if (!jobctx->callback && !job_id) {
480 		jobctx->callback = job_done;
481 		jobctx->context = jobctx;
482 	}
483 
484 	retstatus = do_jr_enqueue(jobctx, &jobctx->id);
485 
486 	if (retstatus != CAAM_NO_ERROR) {
487 		JR_TRACE("enqueue job error 0x%08x", retstatus);
488 		return retstatus;
489 	}
490 
491 	/*
492 	 * If parameter job_id is defined, the job is asynchronous, so
493 	 * returns with setting the job_id value
494 	 */
495 	if (job_id) {
496 		*job_id = jobctx->id;
497 		return CAAM_PENDING;
498 	}
499 
500 #ifdef TIMEOUT_COMPLETION
501 	/*
502 	 * Job is synchronous wait until job completion or timeout
503 	 */
504 	while (!jobctx->completion && timeout--)
505 		caam_jr_dequeue(jobctx->id, 100);
506 
507 	if (timeout <= 0) {
508 		/* Job timeout, cancel it and return in error */
509 		caam_jr_cancel(jobctx->id);
510 		retstatus = CAAM_TIMEOUT;
511 	} else {
512 		if (JRSTA_SRC_GET(jobctx->status) != JRSTA_SRC(NONE))
513 			retstatus = CAAM_JOB_STATUS;
514 		else
515 			retstatus = CAAM_NO_ERROR;
516 	}
517 #else
518 	/*
519 	 * Job is synchronous wait until job complete
520 	 * Don't use a timeout because there is no HW timer and
521 	 * so the timeout is not precise
522 	 */
523 	while (!jobctx->completion)
524 		caam_jr_dequeue(jobctx->id, 100);
525 
526 	if (JRSTA_SRC_GET(jobctx->status) != JRSTA_SRC(NONE))
527 		retstatus = CAAM_JOB_STATUS;
528 	else
529 		retstatus = CAAM_NO_ERROR;
530 #endif
531 
532 	/* Erase local callback function */
533 	jobctx->callback = NULL;
534 
535 	return retstatus;
536 }
537 
538 enum caam_status caam_jr_init(struct caam_jrcfg *jrcfg)
539 {
540 	enum caam_status retstatus = CAAM_FAILURE;
541 
542 	JR_TRACE("Initialization");
543 
544 	/* Allocate the Job Ring resources */
545 	retstatus = do_jr_alloc(&jr_privdata, jrcfg->nb_jobs);
546 	if (retstatus != CAAM_NO_ERROR)
547 		goto end_init;
548 
549 	jr_privdata->ctrladdr = jrcfg->base;
550 	jr_privdata->jroffset = jrcfg->offset;
551 
552 	retstatus =
553 		caam_hal_jr_setowner(jrcfg->base, jrcfg->offset, JROWN_ARM_S);
554 	JR_TRACE("JR setowner returned 0x%x", retstatus);
555 
556 	if (retstatus != CAAM_NO_ERROR)
557 		goto end_init;
558 
559 	jr_privdata->baseaddr = jrcfg->base + jrcfg->offset;
560 	retstatus = caam_hal_jr_reset(jr_privdata->baseaddr);
561 	if (retstatus != CAAM_NO_ERROR)
562 		goto end_init;
563 
564 	/*
565 	 * Get the physical address of the Input/Output queue
566 	 * The HW configuration is 64 bits registers regardless
567 	 * the CAAM or CPU addressing mode.
568 	 */
569 	jr_privdata->paddr_inrings = virt_to_phys(jr_privdata->inrings);
570 	jr_privdata->paddr_outrings = virt_to_phys(jr_privdata->outrings);
571 	if (!jr_privdata->paddr_inrings || !jr_privdata->paddr_outrings) {
572 		JR_TRACE("JR bad queue pointers");
573 		retstatus = CAAM_FAILURE;
574 		goto end_init;
575 	}
576 
577 	caam_hal_jr_config(jr_privdata->baseaddr, jr_privdata->nb_jobs,
578 			   jr_privdata->paddr_inrings,
579 			   jr_privdata->paddr_outrings);
580 
581 	/*
582 	 * Prepare the interrupt handler to secure the interrupt even
583 	 * if the interrupt is not used
584 	 */
585 	jr_privdata->it_handler.it = jrcfg->it_num;
586 	jr_privdata->it_handler.flags = ITRF_TRIGGER_LEVEL;
587 	jr_privdata->it_handler.handler = caam_jr_irqhandler;
588 	jr_privdata->it_handler.data = jr_privdata;
589 
590 #if defined(CFG_NXP_CAAM_RUNTIME_JR) && defined(CFG_CAAM_ITR)
591 	itr_add(&jr_privdata->it_handler);
592 #endif
593 	caam_hal_jr_enable_itr(jr_privdata->baseaddr);
594 
595 	retstatus = CAAM_NO_ERROR;
596 
597 end_init:
598 	if (retstatus != CAAM_NO_ERROR)
599 		do_jr_free(jr_privdata);
600 
601 	return retstatus;
602 }
603 
604 enum caam_status caam_jr_halt(void)
605 {
606 	enum caam_status retstatus = CAAM_FAILURE;
607 	__maybe_unused uint32_t job_complete = 0;
608 
609 	retstatus = caam_hal_jr_halt(jr_privdata->baseaddr);
610 
611 	/*
612 	 * All jobs in the input queue have been done, call the
613 	 * dequeue function to complete them.
614 	 */
615 	job_complete = do_jr_dequeue(UINT32_MAX);
616 	JR_TRACE("Completion of jobs mask 0x%" PRIx32, job_complete);
617 
618 	return retstatus;
619 }
620 
621 enum caam_status caam_jr_flush(void)
622 {
623 	enum caam_status retstatus = CAAM_FAILURE;
624 	__maybe_unused uint32_t job_complete = 0;
625 
626 	retstatus = caam_hal_jr_flush(jr_privdata->baseaddr);
627 
628 	/*
629 	 * All jobs in the input queue have been done, call the
630 	 * dequeue function to complete them.
631 	 */
632 	job_complete = do_jr_dequeue(UINT32_MAX);
633 	JR_TRACE("Completion of jobs mask 0x%" PRIx32, job_complete);
634 
635 	return retstatus;
636 }
637 
638 void caam_jr_resume(uint32_t pm_hint)
639 {
640 	if (pm_hint == PM_HINT_CONTEXT_STATE) {
641 #ifndef CFG_NXP_CAAM_RUNTIME_JR
642 		/*
643 		 * In case the CAAM is not used the JR used to
644 		 * instantiate the RNG has been released to Non-Secure
645 		 * hence, need reconfigure the Secure JR and release
646 		 * it after RNG instantiation
647 		 */
648 		caam_hal_jr_setowner(jr_privdata->ctrladdr,
649 				     jr_privdata->jroffset, JROWN_ARM_S);
650 
651 		caam_hal_jr_config(jr_privdata->baseaddr, jr_privdata->nb_jobs,
652 				   jr_privdata->paddr_inrings,
653 				   jr_privdata->paddr_outrings);
654 #endif /* CFG_NXP_CAAM_RUNTIME_JR */
655 
656 		/* Read the current job ring index */
657 		jr_privdata->inwrite_index =
658 			caam_hal_jr_input_index(jr_privdata->baseaddr);
659 		/* Read the current output ring index */
660 		jr_privdata->outread_index =
661 			caam_hal_jr_output_index(jr_privdata->baseaddr);
662 
663 		if (caam_rng_instantiation() != CAAM_NO_ERROR)
664 			panic();
665 
666 #ifndef CFG_NXP_CAAM_RUNTIME_JR
667 		caam_hal_jr_setowner(jr_privdata->ctrladdr,
668 				     jr_privdata->jroffset, JROWN_ARM_NS);
669 #endif /* CFG_NXP_CAAM_RUNTIME_JR */
670 	} else {
671 		caam_hal_jr_resume(jr_privdata->baseaddr);
672 	}
673 }
674 
675 enum caam_status caam_jr_complete(void)
676 {
677 	enum caam_status ret = CAAM_BUSY;
678 
679 	ret = caam_hal_jr_flush(jr_privdata->baseaddr);
680 	if (ret == CAAM_NO_ERROR)
681 		caam_hal_jr_resume(jr_privdata->baseaddr);
682 
683 	return ret;
684 }
685