1 /*
2  * Copyright 2021 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <assert.h>
9 #include <errno.h>
10 #include <stdbool.h>
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 
15 #include <arch_helpers.h>
16 #include "caam.h"
17 #include <common/debug.h>
18 #include "jobdesc.h"
19 #include "sec_hw_specific.h"
20 
21 
22 /* Job rings used for communication with SEC HW */
23 extern struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS];
24 
25 /* The current state of SEC user space driver */
26 extern volatile sec_driver_state_t g_driver_state;
27 
28 /* The number of job rings used by SEC user space driver */
29 extern int g_job_rings_no;
30 
31 /* LOCAL FUNCTIONS */
hw_set_input_ring_start_addr(struct jobring_regs * regs,phys_addr_t * start_addr)32 static inline void hw_set_input_ring_start_addr(struct jobring_regs *regs,
33 						phys_addr_t *start_addr)
34 {
35 #if defined(CONFIG_PHYS_64BIT)
36 	sec_out32(&regs->irba_h, PHYS_ADDR_HI(start_addr));
37 #else
38 	sec_out32(&regs->irba_h, 0);
39 #endif
40 	sec_out32(&regs->irba_l, PHYS_ADDR_LO(start_addr));
41 }
42 
hw_set_output_ring_start_addr(struct jobring_regs * regs,phys_addr_t * start_addr)43 static inline void hw_set_output_ring_start_addr(struct jobring_regs *regs,
44 						 phys_addr_t *start_addr)
45 {
46 #if defined(CONFIG_PHYS_64BIT)
47 	sec_out32(&regs->orba_h, PHYS_ADDR_HI(start_addr));
48 #else
49 	sec_out32(&regs->orba_h, 0);
50 #endif
51 	sec_out32(&regs->orba_l, PHYS_ADDR_LO(start_addr));
52 }
53 
54 /* ORJR - Output Ring Jobs Removed Register shows how many jobs were
55  * removed from the Output Ring for processing by software. This is done after
56  * the software has processed the entries.
57  */
hw_remove_entries(sec_job_ring_t * jr,int num)58 static inline void hw_remove_entries(sec_job_ring_t *jr, int num)
59 {
60 	struct jobring_regs *regs =
61 	    (struct jobring_regs *)jr->register_base_addr;
62 
63 	sec_out32(&regs->orjr, num);
64 }
65 
66 /* IRSA - Input Ring Slots Available register holds the number of entries in
67  * the Job Ring's input ring. Once a job is enqueued, the value returned is
68  * decremented by the hardware by the number of jobs enqueued.
69  */
hw_get_available_slots(sec_job_ring_t * jr)70 static inline int hw_get_available_slots(sec_job_ring_t *jr)
71 {
72 	struct jobring_regs *regs =
73 	    (struct jobring_regs *)jr->register_base_addr;
74 
75 	return sec_in32(&regs->irsa);
76 }
77 
78 /* ORSFR - Output Ring Slots Full register holds the number of jobs which were
79  * processed by the SEC and can be retrieved by the software. Once a job has
80  * been processed by software, the user will call hw_remove_one_entry in order
81  * to notify the SEC that the entry was processed
82  */
hw_get_no_finished_jobs(sec_job_ring_t * jr)83 static inline int hw_get_no_finished_jobs(sec_job_ring_t *jr)
84 {
85 	struct jobring_regs *regs =
86 	    (struct jobring_regs *)jr->register_base_addr;
87 
88 	return sec_in32(&regs->orsf);
89 }
90 
91 /* @brief Process Jump Halt Condition related errors
92  * @param [in]  error_code The error code in the descriptor status word
93  */
hw_handle_jmp_halt_cond_err(union hw_error_code error_code)94 static inline void hw_handle_jmp_halt_cond_err(union hw_error_code error_code)
95 {
96 	ERROR("JMP %x\n", error_code.error_desc.jmp_halt_cond_src.jmp);
97 	ERROR("Descriptor Index: %d\n",
98 	      error_code.error_desc.jmp_halt_cond_src.desc_idx);
99 	ERROR(" Condition %x\n", error_code.error_desc.jmp_halt_cond_src.cond);
100 }
101 
102 /* @brief Process DECO related errors
103  * @param [in]  error_code      The error code in the descriptor status word
104  */
hw_handle_deco_err(union hw_error_code error_code)105 static inline void hw_handle_deco_err(union hw_error_code error_code)
106 {
107 	ERROR("JMP %x\n", error_code.error_desc.deco_src.jmp);
108 	ERROR("Descriptor Index: 0x%x",
109 	      error_code.error_desc.deco_src.desc_idx);
110 
111 	switch (error_code.error_desc.deco_src.desc_err) {
112 	case SEC_HW_ERR_DECO_HFN_THRESHOLD:
113 		WARN(" Descriptor completed but exceeds the Threshold");
114 		break;
115 	default:
116 		ERROR("Error 0x%04x not implemented",
117 		      error_code.error_desc.deco_src.desc_err);
118 		break;
119 	}
120 }
121 
122 /* @brief Process  Jump Halt User Status related errors
123  * @param [in]  error_code      The error code in the descriptor status word
124  */
hw_handle_jmp_halt_user_err(union hw_error_code error_code)125 static inline void hw_handle_jmp_halt_user_err(union hw_error_code error_code)
126 {
127 	WARN(" Not implemented");
128 }
129 
130 /* @brief Process CCB related errors
131  * @param [in]  error_code      The error code in the descriptor status word
132  */
hw_handle_ccb_err(union hw_error_code hw_error_code)133 static inline void hw_handle_ccb_err(union hw_error_code hw_error_code)
134 {
135 	WARN(" Not implemented");
136 }
137 
138 /* @brief Process Job Ring related errors
139  * @param [in]  error_code      The error code in the descriptor status word
140  */
hw_handle_jr_err(union hw_error_code hw_error_code)141 static inline void hw_handle_jr_err(union hw_error_code hw_error_code)
142 {
143 	WARN(" Not implemented");
144 }
145 
146 /* GLOBAL FUNCTIONS */
147 
hw_reset_job_ring(sec_job_ring_t * job_ring)148 int hw_reset_job_ring(sec_job_ring_t *job_ring)
149 {
150 	int ret = 0;
151 	struct jobring_regs *regs =
152 	    (struct jobring_regs *)job_ring->register_base_addr;
153 
154 	/* First reset the job ring in hw */
155 	ret = hw_shutdown_job_ring(job_ring);
156 	if (ret != 0) {
157 		ERROR("Failed resetting job ring in hardware");
158 		return ret;
159 	}
160 	/* In order to have the HW JR in a workable state
161 	 *after a reset, I need to re-write the input
162 	 * queue size, input start address, output queue
163 	 * size and output start address
164 	 * Write the JR input queue size to the HW register
165 	 */
166 	sec_out32(&regs->irs, SEC_JOB_RING_SIZE);
167 
168 	/* Write the JR output queue size to the HW register */
169 	sec_out32(&regs->ors, SEC_JOB_RING_SIZE);
170 
171 	/* Write the JR input queue start address */
172 	hw_set_input_ring_start_addr(regs, vtop(job_ring->input_ring));
173 
174 	/* Write the JR output queue start address */
175 	hw_set_output_ring_start_addr(regs, vtop(job_ring->output_ring));
176 
177 	return 0;
178 }
179 
hw_shutdown_job_ring(sec_job_ring_t * job_ring)180 int hw_shutdown_job_ring(sec_job_ring_t *job_ring)
181 {
182 	struct jobring_regs *regs =
183 	    (struct jobring_regs *)job_ring->register_base_addr;
184 	unsigned int timeout = SEC_TIMEOUT;
185 	uint32_t tmp = 0U;
186 
187 	VERBOSE("Resetting Job ring\n");
188 
189 	/*
190 	 * Mask interrupts since we are going to poll
191 	 * for reset completion status
192 	 * Also, at POR, interrupts are ENABLED on a JR, thus
193 	 * this is the point where I can disable them without
194 	 * changing the code logic too much
195 	 */
196 
197 	jr_disable_irqs(job_ring);
198 
199 	/* initiate flush (required prior to reset) */
200 	sec_out32(&regs->jrcr, JR_REG_JRCR_VAL_RESET);
201 
202 	/* dummy read */
203 	tmp = sec_in32(&regs->jrcr);
204 
205 	do {
206 		tmp = sec_in32(&regs->jrint);
207 	} while (((tmp & JRINT_ERR_HALT_MASK) ==
208 		  JRINT_ERR_HALT_INPROGRESS) && ((--timeout) != 0U));
209 
210 	if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE ||
211 	    timeout == 0U) {
212 		ERROR("Failed to flush hw job ring %x\n %u", tmp, timeout);
213 		/* unmask interrupts */
214 		if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
215 			jr_enable_irqs(job_ring);
216 		}
217 		return -1;
218 	}
219 	/* Initiate reset */
220 	timeout = SEC_TIMEOUT;
221 	sec_out32(&regs->jrcr, JR_REG_JRCR_VAL_RESET);
222 
223 	do {
224 		tmp = sec_in32(&regs->jrcr);
225 	} while (((tmp & JR_REG_JRCR_VAL_RESET) != 0U) &&
226 		 ((--timeout) != 0U));
227 
228 	if (timeout == 0U) {
229 		ERROR("Failed to reset hw job ring\n");
230 		/* unmask interrupts */
231 		if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
232 			jr_enable_irqs(job_ring);
233 		}
234 		return -1;
235 	}
236 	/* unmask interrupts */
237 	if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
238 		jr_enable_irqs(job_ring);
239 	}
240 	return 0;
241 
242 }
243 
hw_handle_job_ring_error(sec_job_ring_t * job_ring,uint32_t error_code)244 void hw_handle_job_ring_error(sec_job_ring_t *job_ring, uint32_t error_code)
245 {
246 	union hw_error_code hw_err_code;
247 
248 	hw_err_code.error = error_code;
249 
250 	switch (hw_err_code.error_desc.value.ssrc) {
251 	case SEC_HW_ERR_SSRC_NO_SRC:
252 		INFO("No Status Source ");
253 		break;
254 	case SEC_HW_ERR_SSRC_CCB_ERR:
255 		INFO("CCB Status Source");
256 		hw_handle_ccb_err(hw_err_code);
257 		break;
258 	case SEC_HW_ERR_SSRC_JMP_HALT_U:
259 		INFO("Jump Halt User Status Source");
260 		hw_handle_jmp_halt_user_err(hw_err_code);
261 		break;
262 	case SEC_HW_ERR_SSRC_DECO:
263 		INFO("DECO Status Source");
264 		hw_handle_deco_err(hw_err_code);
265 		break;
266 	case SEC_HW_ERR_SSRC_JR:
267 		INFO("Job Ring Status Source");
268 		hw_handle_jr_err(hw_err_code);
269 		break;
270 	case SEC_HW_ERR_SSRC_JMP_HALT_COND:
271 		INFO("Jump Halt Condition Codes");
272 		hw_handle_jmp_halt_cond_err(hw_err_code);
273 		break;
274 	default:
275 		INFO("Unknown SSRC");
276 		break;
277 	}
278 }
279 
hw_job_ring_error(sec_job_ring_t * job_ring)280 int hw_job_ring_error(sec_job_ring_t *job_ring)
281 {
282 	uint32_t jrint_error_code;
283 	struct jobring_regs *regs =
284 	    (struct jobring_regs *)job_ring->register_base_addr;
285 
286 	if (JR_REG_JRINT_JRE_EXTRACT(sec_in32(&regs->jrint)) == 0) {
287 		return 0;
288 	}
289 
290 	jrint_error_code =
291 	    JR_REG_JRINT_ERR_TYPE_EXTRACT(sec_in32(&regs->jrint));
292 	switch (jrint_error_code) {
293 	case JRINT_ERR_WRITE_STATUS:
294 		ERROR("Error writing status to Output Ring ");
295 		break;
296 	case JRINT_ERR_BAD_INPUT_BASE:
297 		ERROR("Bad Input Ring Base (not on a 4-byte boundary)\n");
298 		break;
299 	case JRINT_ERR_BAD_OUTPUT_BASE:
300 		ERROR("Bad Output Ring Base (not on a 4-byte boundary)\n");
301 		break;
302 	case JRINT_ERR_WRITE_2_IRBA:
303 		ERROR("Invalid write to Input Ring Base Address Register\n");
304 		break;
305 	case JRINT_ERR_WRITE_2_ORBA:
306 		ERROR("Invalid write to Output Ring Base Address Register\n");
307 		break;
308 	case JRINT_ERR_RES_B4_HALT:
309 		ERROR("Job Ring released before Job Ring is halted\n");
310 		break;
311 	case JRINT_ERR_REM_TOO_MANY:
312 		ERROR("Removed too many jobs from job ring\n");
313 		break;
314 	case JRINT_ERR_ADD_TOO_MANY:
315 		ERROR("Added too many jobs on job ring\n");
316 		break;
317 	default:
318 		ERROR("Unknown SEC JR Error :%d\n", jrint_error_code);
319 		break;
320 	}
321 	return jrint_error_code;
322 }
323 
hw_job_ring_set_coalescing_param(sec_job_ring_t * job_ring,uint16_t irq_coalescing_timer,uint8_t irq_coalescing_count)324 int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring,
325 				     uint16_t irq_coalescing_timer,
326 				     uint8_t irq_coalescing_count)
327 {
328 	uint32_t reg_val = 0U;
329 	struct jobring_regs *regs =
330 	    (struct jobring_regs *)job_ring->register_base_addr;
331 
332 	/* Set descriptor count coalescing */
333 	reg_val |= (irq_coalescing_count << JR_REG_JRCFG_LO_ICDCT_SHIFT);
334 
335 	/* Set coalescing timer value */
336 	reg_val |= (irq_coalescing_timer << JR_REG_JRCFG_LO_ICTT_SHIFT);
337 
338 	/* Update parameters in HW */
339 	sec_out32(&regs->jrcfg1, reg_val);
340 
341 	VERBOSE("Set coalescing params on jr\n");
342 
343 	return 0;
344 }
345 
hw_job_ring_enable_coalescing(sec_job_ring_t * job_ring)346 int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring)
347 {
348 	uint32_t reg_val = 0U;
349 	struct jobring_regs *regs =
350 	    (struct jobring_regs *)job_ring->register_base_addr;
351 
352 	/* Get the current value of the register */
353 	reg_val = sec_in32(&regs->jrcfg1);
354 
355 	/* Enable coalescing */
356 	reg_val |= JR_REG_JRCFG_LO_ICEN_EN;
357 
358 	/* Write in hw */
359 	sec_out32(&regs->jrcfg1, reg_val);
360 
361 	VERBOSE("Enabled coalescing on jr\n");
362 
363 	return 0;
364 }
365 
hw_job_ring_disable_coalescing(sec_job_ring_t * job_ring)366 int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring)
367 {
368 	uint32_t reg_val = 0U;
369 	struct jobring_regs *regs =
370 	    (struct jobring_regs *)job_ring->register_base_addr;
371 
372 	/* Get the current value of the register */
373 	reg_val = sec_in32(&regs->jrcfg1);
374 
375 	/* Disable coalescing */
376 	reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN;
377 
378 	/* Write in hw */
379 	sec_out32(&regs->jrcfg1, reg_val);
380 
381 	VERBOSE("Disabled coalescing on jr");
382 
383 	return 0;
384 
385 }
386 
hw_flush_job_ring(struct sec_job_ring_t * job_ring,uint32_t do_notify,uint32_t error_code,uint32_t * notified_descs)387 void hw_flush_job_ring(struct sec_job_ring_t *job_ring,
388 		       uint32_t do_notify,
389 		       uint32_t error_code, uint32_t *notified_descs)
390 {
391 	int32_t jobs_no_to_discard = 0;
392 	int32_t discarded_descs_no = 0;
393 	int32_t number_of_jobs_available = 0;
394 
395 	VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx);
396 	VERBOSE("error code %x\n", error_code);
397 	VERBOSE("Notify_desc = %d\n", do_notify);
398 
399 	number_of_jobs_available = hw_get_no_finished_jobs(job_ring);
400 
401 	/* Discard all jobs */
402 	jobs_no_to_discard = number_of_jobs_available;
403 
404 	VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx);
405 	VERBOSE("Discarding desc = %d\n", jobs_no_to_discard);
406 
407 	while (jobs_no_to_discard > discarded_descs_no) {
408 		discarded_descs_no++;
409 		/* Now increment the consumer index for the current job ring,
410 		 * AFTER saving job in temporary location!
411 		 * Increment the consumer index for the current job ring
412 		 */
413 
414 		job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx,
415 						      SEC_JOB_RING_SIZE);
416 
417 		hw_remove_entries(job_ring, 1);
418 	}
419 
420 	if (do_notify == true) {
421 		if (notified_descs == NULL) {
422 			return;
423 		}
424 		*notified_descs = discarded_descs_no;
425 	}
426 }
427 
428 /* return >0 in case of success
429  *  -1 in case of error from SEC block
430  *  0 in case job not yet processed by SEC
431  *   or  Descriptor returned is NULL after dequeue
432  */
hw_poll_job_ring(struct sec_job_ring_t * job_ring,int32_t limit)433 int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit)
434 {
435 	int32_t jobs_no_to_notify = 0;
436 	int32_t number_of_jobs_available = 0;
437 	int32_t notified_descs_no = 0;
438 	uint32_t error_descs_no = 0U;
439 	uint32_t sec_error_code = 0U;
440 	uint32_t do_driver_shutdown = false;
441 	phys_addr_t *fnptr, *arg_addr;
442 	user_callback usercall = NULL;
443 	uint8_t *current_desc;
444 	void *arg;
445 	uintptr_t current_desc_addr;
446 	phys_addr_t current_desc_loc;
447 
448 #if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
449 	inv_dcache_range((uintptr_t)job_ring->register_base_addr, sizeof(struct jobring_regs));
450 	dmbsy();
451 #endif
452 
453 	/* check here if any JR error that cannot be written
454 	 * in the output status word has occurred
455 	 */
456 	sec_error_code = hw_job_ring_error(job_ring);
457 	if (unlikely(sec_error_code) != 0) {
458 		ERROR("Error here itself %x\n", sec_error_code);
459 		return -1;
460 	}
461 	/* Compute the number of notifications that need to be raised to UA
462 	 * If limit < 0 -> notify all done jobs
463 	 * If limit > total number of done jobs -> notify all done jobs
464 	 * If limit = 0 -> error
465 	 * If limit > 0 && limit < total number of done jobs -> notify a number
466 	 * of done jobs equal with limit
467 	 */
468 
469 	/*compute the number of jobs available in the job ring based on the
470 	 * producer and consumer index values.
471 	 */
472 
473 	number_of_jobs_available = hw_get_no_finished_jobs(job_ring);
474 	jobs_no_to_notify = (limit < 0 || limit > number_of_jobs_available) ?
475 	    number_of_jobs_available : limit;
476 	VERBOSE("JR - pi %d, ci %d, ", job_ring->pidx, job_ring->cidx);
477 	VERBOSE("Jobs submitted %d", number_of_jobs_available);
478 	VERBOSE("Jobs to notify %d\n", jobs_no_to_notify);
479 
480 	while (jobs_no_to_notify > notified_descs_no) {
481 
482 #if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
483 		inv_dcache_range(
484 			(uintptr_t)(&job_ring->output_ring[job_ring->cidx]),
485 			sizeof(struct sec_outring_entry));
486 		dmbsy();
487 #endif
488 
489 		/* Get job status here */
490 		sec_error_code =
491 		    sec_in32(&(job_ring->output_ring[job_ring->cidx].status));
492 
493 		/* Get completed descriptor
494 		 */
495 		current_desc_loc = (uintptr_t)
496 		    &job_ring->output_ring[job_ring->cidx].desc;
497 		current_desc_addr = sec_read_addr(current_desc_loc);
498 
499 		current_desc = ptov((phys_addr_t *) current_desc_addr);
500 		if (current_desc == 0) {
501 			ERROR("No descriptor returned from SEC");
502 			assert(current_desc);
503 			return 0;
504 		}
505 		/* now increment the consumer index for the current job ring,
506 		 * AFTER saving job in temporary location!
507 		 */
508 		job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx,
509 						      SEC_JOB_RING_SIZE);
510 
511 		if (sec_error_code != 0) {
512 			ERROR("desc at cidx %d\n ", job_ring->cidx);
513 			ERROR("generated error %x\n", sec_error_code);
514 
515 			sec_handle_desc_error(job_ring,
516 					      sec_error_code,
517 					      &error_descs_no,
518 					      &do_driver_shutdown);
519 			hw_remove_entries(job_ring, 1);
520 
521 			return -1;
522 		}
523 		/* Signal that the job has been processed & the slot is free */
524 		hw_remove_entries(job_ring, 1);
525 		notified_descs_no++;
526 
527 		arg_addr = (phys_addr_t *) (current_desc +
528 				(MAX_DESC_SIZE_WORDS * sizeof(uint32_t)));
529 
530 		fnptr = (phys_addr_t *) (current_desc +
531 					(MAX_DESC_SIZE_WORDS * sizeof(uint32_t)
532 					+  sizeof(void *)));
533 
534 		arg = (void *)*(arg_addr);
535 		if (*fnptr != 0) {
536 			VERBOSE("Callback Function called\n");
537 			usercall = (user_callback) *(fnptr);
538 			(*usercall) ((uint32_t *) current_desc,
539 				     sec_error_code, arg, job_ring);
540 		}
541 	}
542 
543 	return notified_descs_no;
544 }
545 
sec_handle_desc_error(sec_job_ring_t * job_ring,uint32_t sec_error_code,uint32_t * notified_descs,uint32_t * do_driver_shutdown)546 void sec_handle_desc_error(sec_job_ring_t *job_ring,
547 			   uint32_t sec_error_code,
548 			   uint32_t *notified_descs,
549 			   uint32_t *do_driver_shutdown)
550 {
551 	/* Analyze the SEC error on this job ring */
552 	hw_handle_job_ring_error(job_ring, sec_error_code);
553 }
554 
flush_job_rings(void)555 void flush_job_rings(void)
556 {
557 	struct sec_job_ring_t *job_ring = NULL;
558 	int i = 0;
559 
560 	for (i = 0; i < g_job_rings_no; i++) {
561 		job_ring = &g_job_rings[i];
562 		/* Producer index is frozen. If consumer index is not equal
563 		 * with producer index, then we have descs to flush.
564 		 */
565 		while (job_ring->pidx != job_ring->cidx) {
566 			hw_flush_job_ring(job_ring, false, 0,	/* no error */
567 					  NULL);
568 		}
569 	}
570 }
571 
shutdown_job_ring(struct sec_job_ring_t * job_ring)572 int shutdown_job_ring(struct sec_job_ring_t *job_ring)
573 {
574 	int ret = 0;
575 
576 	ret = hw_shutdown_job_ring(job_ring);
577 	if (ret != 0) {
578 		ERROR("Failed to shutdown hardware job ring\n");
579 		return ret;
580 	}
581 
582 	if (job_ring->coalescing_en != 0) {
583 		hw_job_ring_disable_coalescing(job_ring);
584 	}
585 
586 	if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
587 		ret = jr_disable_irqs(job_ring);
588 		if (ret != 0) {
589 			ERROR("Failed to disable irqs for job ring");
590 			return ret;
591 		}
592 	}
593 
594 	return 0;
595 }
596 
jr_enable_irqs(struct sec_job_ring_t * job_ring)597 int jr_enable_irqs(struct sec_job_ring_t *job_ring)
598 {
599 	uint32_t reg_val = 0U;
600 	struct jobring_regs *regs =
601 	    (struct jobring_regs *)job_ring->register_base_addr;
602 
603 	/* Get the current value of the register */
604 	reg_val = sec_in32(&regs->jrcfg1);
605 
606 	/* Enable interrupts by disabling interrupt masking*/
607 	reg_val &= ~JR_REG_JRCFG_LO_IMSK_EN;
608 
609 	/* Update parameters in HW */
610 	sec_out32(&regs->jrcfg1, reg_val);
611 
612 	VERBOSE("Enable interrupts on JR\n");
613 
614 	return 0;
615 }
616 
jr_disable_irqs(struct sec_job_ring_t * job_ring)617 int jr_disable_irqs(struct sec_job_ring_t *job_ring)
618 {
619 	uint32_t reg_val = 0U;
620 	struct jobring_regs *regs =
621 	    (struct jobring_regs *)job_ring->register_base_addr;
622 
623 	/* Get the current value of the register */
624 	reg_val = sec_in32(&regs->jrcfg1);
625 
626 	/* Disable interrupts by enabling interrupt masking*/
627 	reg_val |= JR_REG_JRCFG_LO_IMSK_EN;
628 
629 	/* Update parameters in HW */
630 	sec_out32(&regs->jrcfg1, reg_val);
631 
632 	VERBOSE("Disable interrupts on JR\n");
633 
634 	return 0;
635 }
636