1 /*
2  * Copyright 2021 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #include <errno.h>
9 #include <stdbool.h>
10 #include <stdint.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include <arch_helpers.h>
16 #include "caam.h"
17 #include <common/debug.h>
18 #include "jobdesc.h"
19 #include "nxp_timer.h"
20 #include "sec_hw_specific.h"
21 #include "sec_jr_driver.h"
22 
23 
24 /* Job rings used for communication with SEC HW  */
25 struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS];
26 
27 /* The current state of SEC user space driver */
28 volatile sec_driver_state_t g_driver_state = SEC_DRIVER_STATE_IDLE;
29 
30 int g_job_rings_no;
31 
32 uint8_t ip_ring[SEC_DMA_MEM_INPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE);
33 uint8_t op_ring[SEC_DMA_MEM_OUTPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE);
34 
init_job_ring(uint8_t jr_mode,uint16_t irq_coalescing_timer,uint8_t irq_coalescing_count,void * reg_base_addr,uint32_t irq_id)35 void *init_job_ring(uint8_t jr_mode,
36 		    uint16_t irq_coalescing_timer,
37 		    uint8_t irq_coalescing_count,
38 		    void *reg_base_addr, uint32_t irq_id)
39 {
40 	struct sec_job_ring_t *job_ring = &g_job_rings[g_job_rings_no++];
41 	int ret = 0;
42 
43 	job_ring->register_base_addr = reg_base_addr;
44 	job_ring->jr_mode = jr_mode;
45 	job_ring->irq_fd = irq_id;
46 
47 	job_ring->input_ring = vtop(ip_ring);
48 	memset(job_ring->input_ring, 0, SEC_DMA_MEM_INPUT_RING_SIZE);
49 
50 	job_ring->output_ring = (struct sec_outring_entry *)vtop(op_ring);
51 	memset(job_ring->output_ring, 0, SEC_DMA_MEM_OUTPUT_RING_SIZE);
52 
53 	dsb();
54 
55 #if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
56 	flush_dcache_range((uintptr_t)(job_ring->input_ring),
57 				       SEC_DMA_MEM_INPUT_RING_SIZE),
58 	flush_dcache_range((uintptr_t)(job_ring->output_ring),
59 				       SEC_DMA_MEM_OUTPUT_RING_SIZE),
60 
61 	dmbsy();
62 #endif
63 	/* Reset job ring in SEC hw and configure job ring registers */
64 	ret = hw_reset_job_ring(job_ring);
65 	if (ret != 0) {
66 		ERROR("Failed to reset hardware job ring\n");
67 		return NULL;
68 	}
69 
70 	if (jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
71 		/* Enable IRQ if driver work sin interrupt mode */
72 		ERROR("Enabling DONE IRQ generation on job ring\n");
73 		ret = jr_enable_irqs(job_ring);
74 		if (ret != 0) {
75 			ERROR("Failed to enable irqs for job ring\n");
76 			return NULL;
77 		}
78 	}
79 	if ((irq_coalescing_timer != 0) || (irq_coalescing_count != 0)) {
80 		hw_job_ring_set_coalescing_param(job_ring,
81 						 irq_coalescing_timer,
82 						 irq_coalescing_count);
83 
84 		hw_job_ring_enable_coalescing(job_ring);
85 		job_ring->coalescing_en = 1;
86 	}
87 
88 	job_ring->jr_state = SEC_JOB_RING_STATE_STARTED;
89 
90 	return job_ring;
91 }
92 
sec_release(void)93 int sec_release(void)
94 {
95 	int i;
96 
97 	/* Validate driver state */
98 	if (g_driver_state == SEC_DRIVER_STATE_RELEASE) {
99 		ERROR("Driver release is already in progress");
100 		return SEC_DRIVER_RELEASE_IN_PROGRESS;
101 	}
102 	/* Update driver state */
103 	g_driver_state = SEC_DRIVER_STATE_RELEASE;
104 
105 	/* If any descriptors in flight , poll and wait
106 	 * until all descriptors are received and silently discarded.
107 	 */
108 
109 	flush_job_rings();
110 
111 	for (i = 0; i < g_job_rings_no; i++) {
112 		shutdown_job_ring(&g_job_rings[i]);
113 	}
114 	g_job_rings_no = 0;
115 	g_driver_state = SEC_DRIVER_STATE_IDLE;
116 
117 	return SEC_SUCCESS;
118 }
119 
sec_jr_lib_init(void)120 int sec_jr_lib_init(void)
121 {
122 	/* Validate driver state */
123 	if (g_driver_state != SEC_DRIVER_STATE_IDLE) {
124 		ERROR("Driver already initialized\n");
125 		return 0;
126 	}
127 
128 	memset(g_job_rings, 0, sizeof(g_job_rings));
129 	g_job_rings_no = 0;
130 
131 	/* Update driver state */
132 	g_driver_state = SEC_DRIVER_STATE_STARTED;
133 	return 0;
134 }
135 
dequeue_jr(void * job_ring_handle,int32_t limit)136 int dequeue_jr(void *job_ring_handle, int32_t limit)
137 {
138 	int ret = 0;
139 	int notified_descs_no = 0;
140 	struct sec_job_ring_t *job_ring = (sec_job_ring_t *) job_ring_handle;
141 	uint64_t start_time;
142 
143 	/* Validate driver state */
144 	if (g_driver_state != SEC_DRIVER_STATE_STARTED) {
145 		ERROR("Driver release in progress or driver not initialized\n");
146 		return -1;
147 	}
148 
149 	/* Validate input arguments */
150 	if (job_ring == NULL) {
151 		ERROR("job_ring_handle is NULL\n");
152 		return -1;
153 	}
154 	if (((limit == 0) || (limit > SEC_JOB_RING_SIZE))) {
155 		ERROR("Invalid limit parameter configuration\n");
156 		return -1;
157 	}
158 
159 	VERBOSE("JR Polling limit[%d]\n", limit);
160 
161 	/* Poll job ring
162 	 * If limit < 0 -> poll JR until no more notifications are available.
163 	 * If limit > 0 -> poll JR until limit is reached.
164 	 */
165 
166 	start_time = get_timer_val(0);
167 
168 	while (notified_descs_no == 0) {
169 		/* Run hw poll job ring */
170 		notified_descs_no = hw_poll_job_ring(job_ring, limit);
171 		if (notified_descs_no < 0) {
172 			ERROR("Error polling SEC engine job ring ");
173 			return notified_descs_no;
174 		}
175 		VERBOSE("Jobs notified[%d]. ", notified_descs_no);
176 
177 		if (get_timer_val(start_time) >= CAAM_TIMEOUT) {
178 			break;
179 		}
180 	}
181 
182 	if (job_ring->jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
183 
184 		/* Always enable IRQ generation when in pure IRQ mode */
185 		ret = jr_enable_irqs(job_ring);
186 		if (ret != 0) {
187 			ERROR("Failed to enable irqs for job ring");
188 			return ret;
189 		}
190 	}
191 	return notified_descs_no;
192 }
193 
enq_jr_desc(void * job_ring_handle,struct job_descriptor * jobdescr)194 int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr)
195 {
196 	struct sec_job_ring_t *job_ring;
197 
198 	job_ring = (struct sec_job_ring_t *)job_ring_handle;
199 
200 	/* Validate driver state */
201 	if (g_driver_state != SEC_DRIVER_STATE_STARTED) {
202 		ERROR("Driver release in progress or driver not initialized\n");
203 		return -1;
204 	}
205 
206 	/* Check job ring state */
207 	if (job_ring->jr_state != SEC_JOB_RING_STATE_STARTED) {
208 		ERROR("Job ring is currently resetting\n");
209 		return -1;
210 	}
211 
212 	if (SEC_JOB_RING_IS_FULL(job_ring->pidx, job_ring->cidx,
213 				 SEC_JOB_RING_SIZE, SEC_JOB_RING_SIZE)) {
214 		ERROR("Job ring is full\n");
215 		return -1;
216 	}
217 
218 	/* Set ptr in input ring to current descriptor  */
219 	sec_write_addr(&job_ring->input_ring[job_ring->pidx],
220 		       (phys_addr_t) vtop(jobdescr->desc));
221 
222 	dsb();
223 
224 #if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
225 	flush_dcache_range((uintptr_t)(&job_ring->input_ring[job_ring->pidx]),
226 			   sizeof(phys_addr_t));
227 
228 	inv_dcache_range((uintptr_t)(&job_ring->output_ring[job_ring->cidx]),
229 			   sizeof(struct sec_outring_entry));
230 	dmbsy();
231 #endif
232 	/* Notify HW that a new job is enqueued  */
233 	hw_enqueue_desc_on_job_ring(
234 			(struct jobring_regs *)job_ring->register_base_addr, 1);
235 
236 	/* increment the producer index for the current job ring */
237 	job_ring->pidx = SEC_CIRCULAR_COUNTER(job_ring->pidx,
238 					      SEC_JOB_RING_SIZE);
239 
240 	return 0;
241 }
242