crypto/caam_jr: add routines to configure HW
[dpdk.git] / drivers / crypto / caam_jr / caam_jr_hw.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright 2017-2018 NXP
3  */
4
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <inttypes.h>
8 #include <rte_common.h>
9 #include <rte_memory.h>
10 #include <rte_malloc.h>
11 #include <rte_crypto.h>
12 #include <rte_security.h>
13
14 #include <caam_jr_config.h>
15 #include <caam_jr_hw_specific.h>
16 #include <caam_jr_pvt.h>
17 #include <caam_jr_log.h>
18
19 /* RTA header files */
20 #include <hw/desc/common.h>
21 #include <hw/desc/algo.h>
22 #include <hw/desc/ipsec.h>
23
24 /* Used to retry resetting a job ring in SEC hardware. */
25 #define SEC_TIMEOUT 100000
26
27 /* @brief Process Jump Halt Condition related errors
28  *
29  * @param [in]  error_code        The error code in the descriptor status word
30  */
31 static inline void
32 hw_handle_jmp_halt_cond_err(union hw_error_code error_code)
33 {
34         CAAM_JR_DEBUG("JMP: %d, Descriptor Index: 0x%x, Condition: 0x%x",
35                         error_code.error_desc.jmp_halt_cond_src.jmp,
36                         error_code.error_desc.jmp_halt_cond_src.desc_idx,
37                         error_code.error_desc.jmp_halt_cond_src.cond);
38         (void)error_code;
39 }
40
41 /* @brief Process DECO related errors
42  *
43  * @param [in]  error_code        The error code in the descriptor status word
44  */
45 static inline void
46 hw_handle_deco_err(union hw_error_code error_code)
47 {
48         CAAM_JR_DEBUG("JMP: %d, Descriptor Index: 0x%x",
49                         error_code.error_desc.deco_src.jmp,
50                         error_code.error_desc.deco_src.desc_idx);
51
52         switch (error_code.error_desc.deco_src.desc_err) {
53         case SEC_HW_ERR_DECO_HFN_THRESHOLD:
54                 CAAM_JR_DEBUG(" Warning: Descriptor completed normally,"
55                         "but 3GPP HFN matches or exceeds the Threshold ");
56                 break;
57         default:
58                 CAAM_JR_DEBUG("Error 0x%04x not implemented",
59                                 error_code.error_desc.deco_src.desc_err);
60                 break;
61         }
62 }
63
64 /* @brief Process  Jump Halt User Status related errors
65  *
66  * @param [in]  error_code        The error code in the descriptor status word
67  */
68 static inline void
69 hw_handle_jmp_halt_user_err(union hw_error_code error_code __rte_unused)
70 {
71         CAAM_JR_DEBUG(" Not implemented");
72 }
73
74 /* @brief Process CCB related errors
75  *
76  * @param [in]  error_code        The error code in the descriptor status word
77  */
78 static inline void
79 hw_handle_ccb_err(union hw_error_code hw_error_code __rte_unused)
80 {
81         CAAM_JR_DEBUG(" Not implemented");
82 }
83
84 /* @brief Process Job Ring related errors
85  *
86  * @param [in]  error_code        The error code in the descriptor status word
87  */
88 static inline void
89 hw_handle_jr_err(union hw_error_code hw_error_code __rte_unused)
90 {
91         CAAM_JR_DEBUG(" Not implemented");
92 }
93
94 uint32_t
95 caam_jr_enable_irqs(uint32_t uio_fd __rte_unused)
96 {
97         return 0;
98 }
99
100 uint32_t
101 caam_jr_disable_irqs(uint32_t uio_fd __rte_unused)
102 {
103         return 0;
104 }
105
106 int
107 hw_reset_job_ring(struct sec_job_ring_t *job_ring)
108 {
109         int ret = 0;
110
111         ASSERT(job_ring->register_base_addr != NULL);
112
113         /* First reset the job ring in hw */
114         ret = hw_shutdown_job_ring(job_ring);
115         SEC_ASSERT(ret == 0, ret, "Failed resetting job ring in hardware");
116
117         /* In order to have the HW JR in a workable state
118          * after a reset, I need to re-write the input
119          * queue size, input start address, output queue
120          * size and output start address
121          */
122         /* Write the JR input queue size to the HW register */
123         hw_set_input_ring_size(job_ring, SEC_JOB_RING_SIZE);
124
125         /* Write the JR output queue size to the HW register */
126         hw_set_output_ring_size(job_ring, SEC_JOB_RING_SIZE);
127
128         /* Write the JR input queue start address */
129         hw_set_input_ring_start_addr(job_ring,
130                         caam_jr_dma_vtop(job_ring->input_ring));
131         CAAM_JR_DEBUG(" Set input ring base address to : Virtual: 0x%" PRIx64
132                       ",Physical: 0x%" PRIx64 ", Read from HW: 0x%" PRIx64,
133                       (uint64_t)(uintptr_t)job_ring->input_ring,
134                       caam_jr_dma_vtop(job_ring->input_ring),
135                       hw_get_inp_queue_base(job_ring));
136
137         /* Write the JR output queue start address */
138         hw_set_output_ring_start_addr(job_ring,
139                         caam_jr_dma_vtop(job_ring->output_ring));
140         CAAM_JR_DEBUG(" Set output ring base address to: Virtual: 0x%" PRIx64
141                       ",Physical: 0x%" PRIx64 ", Read from HW: 0x%" PRIx64,
142                       (uint64_t)(uintptr_t)job_ring->output_ring,
143                       caam_jr_dma_vtop(job_ring->output_ring),
144                       hw_get_out_queue_base(job_ring));
145         return ret;
146 }
147
148 int
149 hw_shutdown_job_ring(struct sec_job_ring_t *job_ring)
150 {
151         unsigned int timeout = SEC_TIMEOUT;
152         uint32_t tmp = 0;
153         int usleep_interval = 10;
154
155         if (job_ring->register_base_addr == NULL) {
156                 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
157                         job_ring);
158                 return 0;
159         }
160
161         CAAM_JR_INFO("Resetting Job ring %p", job_ring);
162
163         /*
164          * Mask interrupts since we are going to poll
165          * for reset completion status
166          * Also, at POR, interrupts are ENABLED on a JR, thus
167          * this is the point where I can disable them without
168          * changing the code logic too much
169          */
170         caam_jr_disable_irqs(job_ring->irq_fd);
171
172         /* initiate flush (required prior to reset) */
173         SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
174
175         /* dummy read */
176         tmp = GET_JR_REG(JRCR, job_ring);
177
178         do {
179                 tmp = GET_JR_REG(JRINT, job_ring);
180                 usleep(usleep_interval);
181         } while (((tmp & JRINT_ERR_HALT_MASK) ==
182                         JRINT_ERR_HALT_INPROGRESS) && --timeout);
183
184         CAAM_JR_INFO("JRINT is %x", tmp);
185         if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE ||
186                 timeout == 0) {
187                 CAAM_JR_ERR("0x%x, %d", tmp, timeout);
188                 /* unmask interrupts */
189                 if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
190                         caam_jr_enable_irqs(job_ring->irq_fd);
191                 return -1;
192         }
193
194         /* Initiate reset */
195         timeout = SEC_TIMEOUT;
196         SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
197
198         do {
199                 tmp = GET_JR_REG(JRCR, job_ring);
200                 usleep(usleep_interval);
201         } while ((tmp & JR_REG_JRCR_VAL_RESET) && --timeout);
202
203         CAAM_JR_DEBUG("JRCR is %x", tmp);
204         if (timeout == 0) {
205                 CAAM_JR_ERR("Failed to reset hw job ring %p", job_ring);
206                 /* unmask interrupts */
207                 if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
208                         caam_jr_enable_irqs(job_ring->irq_fd);
209                 return -1;
210         }
211         /* unmask interrupts */
212         if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
213                 caam_jr_enable_irqs(job_ring->irq_fd);
214         return 0;
215
216 }
217
218 void
219 hw_handle_job_ring_error(struct sec_job_ring_t *job_ring __rte_unused,
220                          uint32_t error_code)
221 {
222         union hw_error_code hw_err_code;
223
224         hw_err_code.error = error_code;
225         switch (hw_err_code.error_desc.value.ssrc) {
226         case SEC_HW_ERR_SSRC_NO_SRC:
227                 ASSERT(hw_err_code.error_desc.no_status_src.res == 0);
228                 CAAM_JR_ERR("No Status Source ");
229                 break;
230         case SEC_HW_ERR_SSRC_CCB_ERR:
231                 CAAM_JR_ERR("CCB Status Source");
232                 hw_handle_ccb_err(hw_err_code);
233                 break;
234         case SEC_HW_ERR_SSRC_JMP_HALT_U:
235                 CAAM_JR_ERR("Jump Halt User Status Source");
236                 hw_handle_jmp_halt_user_err(hw_err_code);
237                 break;
238         case SEC_HW_ERR_SSRC_DECO:
239                 CAAM_JR_ERR("DECO Status Source");
240                 hw_handle_deco_err(hw_err_code);
241                 break;
242         case SEC_HW_ERR_SSRC_JR:
243                 CAAM_JR_ERR("Job Ring Status Source");
244                 hw_handle_jr_err(hw_err_code);
245                 break;
246         case SEC_HW_ERR_SSRC_JMP_HALT_COND:
247                 CAAM_JR_ERR("Jump Halt Condition Codes");
248                 hw_handle_jmp_halt_cond_err(hw_err_code);
249                 break;
250         default:
251                 ASSERT(0);
252                 CAAM_JR_ERR("Unknown SSRC");
253                 break;
254         }
255 }
256
257 void
258 hw_job_ring_error_print(struct sec_job_ring_t *job_ring, int code)
259 {
260         switch (code) {
261         case JRINT_ERR_WRITE_STATUS:
262                 CAAM_JR_ERR("Error writing status to Output Ring ");
263                 break;
264         case JRINT_ERR_BAD_INPUT_BASE:
265                 CAAM_JR_ERR(
266                 "Bad Input Ring Base (%p) (not on a 4-byte boundary) ",
267                 (void *)job_ring);
268                 break;
269         case JRINT_ERR_BAD_OUTPUT_BASE:
270                 CAAM_JR_ERR(
271                 "Bad Output Ring Base (%p) (not on a 4-byte boundary) ",
272                 (void *)job_ring);
273                 break;
274         case JRINT_ERR_WRITE_2_IRBA:
275                 CAAM_JR_ERR(
276                 "Invalid write to Input Ring Base Address Register ");
277                 break;
278         case JRINT_ERR_WRITE_2_ORBA:
279                 CAAM_JR_ERR(
280                 "Invalid write to Output Ring Base Address Register ");
281                 break;
282         case JRINT_ERR_RES_B4_HALT:
283                 CAAM_JR_ERR(
284                 "Job Ring [%p] released before Job Ring is halted",
285                 (void *)job_ring);
286                 break;
287         case JRINT_ERR_REM_TOO_MANY:
288                 CAAM_JR_ERR("Removed too many jobs from job ring [%p]",
289                         (void *)job_ring);
290                 break;
291         case JRINT_ERR_ADD_TOO_MANY:
292                 CAAM_JR_ERR("Added too many jobs on job ring [%p]", job_ring);
293                 break;
294         default:
295                 CAAM_JR_ERR(" Unknown SEC JR Error :%d",
296                                 code);
297                 break;
298         }
299 }
300
301 int
302 hw_job_ring_set_coalescing_param(struct sec_job_ring_t *job_ring,
303                                  uint16_t irq_coalescing_timer,
304                                  uint8_t irq_coalescing_count)
305 {
306         uint32_t reg_val = 0;
307
308         ASSERT(job_ring != NULL);
309         if (job_ring->register_base_addr == NULL) {
310                 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
311                         job_ring);
312                 return -1;
313         }
314         /* Set descriptor count coalescing */
315         reg_val |= (irq_coalescing_count << JR_REG_JRCFG_LO_ICDCT_SHIFT);
316
317         /* Set coalescing timer value */
318         reg_val |= (irq_coalescing_timer << JR_REG_JRCFG_LO_ICTT_SHIFT);
319
320         /* Update parameters in HW */
321         SET_JR_REG_LO(JRCFG, job_ring, reg_val);
322         CAAM_JR_DEBUG("Set coalescing params on jr %p timer:%d, desc count: %d",
323                         job_ring, irq_coalescing_timer, irq_coalescing_timer);
324
325         return 0;
326 }
327
328 int
329 hw_job_ring_enable_coalescing(struct sec_job_ring_t *job_ring)
330 {
331         uint32_t reg_val = 0;
332
333         ASSERT(job_ring != NULL);
334         if (job_ring->register_base_addr == NULL) {
335                 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
336                         job_ring);
337                 return -1;
338         }
339
340         /* Get the current value of the register */
341         reg_val = GET_JR_REG_LO(JRCFG, job_ring);
342
343         /* Enable coalescing */
344         reg_val |= JR_REG_JRCFG_LO_ICEN_EN;
345
346         /* Write in hw */
347         SET_JR_REG_LO(JRCFG, job_ring, reg_val);
348
349         CAAM_JR_DEBUG("Enabled coalescing on jr %p ",
350                         job_ring);
351
352         return 0;
353 }
354
355 int
356 hw_job_ring_disable_coalescing(struct sec_job_ring_t *job_ring)
357 {
358         uint32_t reg_val = 0;
359
360         ASSERT(job_ring != NULL);
361
362         if (job_ring->register_base_addr == NULL) {
363                 CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
364                         job_ring);
365                 return -1;
366         }
367
368         /* Get the current value of the register */
369         reg_val = GET_JR_REG_LO(JRCFG, job_ring);
370
371         /* Disable coalescing */
372         reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN;
373
374         /* Write in hw */
375         SET_JR_REG_LO(JRCFG, job_ring, reg_val);
376         CAAM_JR_DEBUG("Disabled coalescing on jr %p ", job_ring);
377
378         return 0;
379 }