1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Crypto acceleration support for Rockchip crypto engine
4 *
5 * Copyright (c) 2025 Rockchip Electronics Co., Ltd.
6 *
7 * Author: Lin Jinhan <troy.lin@rock-chips.com>
8 *
9 */
10
11 #include <linux/bug.h>
12 #include <linux/delay.h>
13 #include <linux/string.h>
14
15 #include "rockchip/rkce_core.h"
16 #include "rockchip/rkce_debug.h"
17 #include "rockchip/rkce_error.h"
18 #include "rockchip/rkce_reg.h"
19
20 struct rkce_chn_info {
21 void *td_virt;
22 uint32_t int_st;
23 uint32_t td_id;
24 int result;
25
26 request_cb_func cb_func;
27 };
28
29 struct rkce_hardware {
30 struct RKCE_REG *rkce_reg;
31
32 struct rkce_chn_info chn[RKCE_TD_TYPE_MAX];
33 };
34
35 #define RST_TIMEOUT_MS 100
36 #define TD_PUSH_TIMEOUT_MS 3000
37
38 #define IP_VERSION_MASK (0xfU >> 28)
39 #define IP_VERSION_RKCE (0x1U >> 28)
40 #define GET_IP_VERSION(ver) ((ver) & IP_VERSION_MASK)
41
42 #define IS_SYMM_TD(td_type) ((td_type) == RKCE_TD_TYPE_SYMM || \
43 (td_type) == RKCE_TD_TYPE_SYMM_HASH_IN || \
44 (td_type) == RKCE_TD_TYPE_SYMM_HASH_OUT)
45
46 #define IS_HASH_TD(td_type) ((td_type) == RKCE_TD_TYPE_HASH)
47
48 #define GET_RKCE_REG(hardware) (((struct rkce_hardware *)(hardware))->rkce_reg)
49 #define CHECK_RKCE_INITED(hardware) WARN_ON_ONCE(!(hardware) || \
50 !(((struct rkce_hardware *)(hardware))->rkce_reg))
51 #define POLL_TIMEOUT(condition, timeout_ms) ({ \
52 int timeout = timeout_ms; \
53 while ((condition) && timeout--) { \
54 udelay(1000); \
55 } \
56 if (timeout < 0) \
57 rk_err("%s timeout!\n", #condition); \
58 (timeout < 0) ? -RKCE_TIMEOUT : 0; \
59 })
60
61 static const uint32_t cipher_mode2bit_mask[] = {
62 [RKCE_SYMM_MODE_ECB] = RKCE_AES_VER_ECB_FLAG_MASK,
63 [RKCE_SYMM_MODE_CBC] = RKCE_AES_VER_CBC_FLAG_MASK,
64 [RKCE_SYMM_MODE_CFB] = RKCE_AES_VER_CFB_FLAG_MASK,
65 [RKCE_SYMM_MODE_OFB] = RKCE_AES_VER_OFB_FLAG_MASK,
66 [RKCE_SYMM_MODE_CTR] = RKCE_AES_VER_CTR_FLAG_MASK,
67 [RKCE_SYMM_MODE_XTS] = RKCE_AES_VER_XTS_FLAG_MASK,
68 [RKCE_SYMM_MODE_CTS] = RKCE_AES_VER_CTS_FLAG_MASK,
69 [RKCE_SYMM_MODE_CCM] = RKCE_AES_VER_CCM_FLAG_MASK,
70 [RKCE_SYMM_MODE_GCM] = RKCE_AES_VER_GCM_FLAG_MASK,
71 [RKCE_SYMM_MODE_CMAC] = RKCE_AES_VER_CMAC_FLAG_MASK,
72 [RKCE_SYMM_MODE_CBC_MAC] = RKCE_AES_VER_CBC_MAC_FLAG_MASK,
73 };
74
75 static const uint32_t hash_algo2bit_mask[] = {
76 [RKCE_HASH_ALGO_SHA1] = RKCE_HASH_VER_SHA1_FLAG_MASK,
77 [RKCE_HASH_ALGO_SHA224] = RKCE_HASH_VER_SHA224_FLAG_MASK,
78 [RKCE_HASH_ALGO_SHA256] = RKCE_HASH_VER_SHA256_FLAG_MASK,
79 [RKCE_HASH_ALGO_SHA384] = RKCE_HASH_VER_SHA384_FLAG_MASK,
80 [RKCE_HASH_ALGO_SHA512] = RKCE_HASH_VER_SHA512_FLAG_MASK,
81 [RKCE_HASH_ALGO_SHA512_224] = RKCE_HASH_VER_SHA512_224_FLAG_MASK,
82 [RKCE_HASH_ALGO_SHA512_256] = RKCE_HASH_VER_SHA512_256_FLAG_MASK,
83 [RKCE_HASH_ALGO_MD5] = RKCE_HASH_VER_MD5_FLAG_MASK,
84 [RKCE_HASH_ALGO_SM3] = RKCE_HASH_VER_SM3_FLAG_MASK,
85 };
86
87 static const uint32_t hmac_algo2bit_mask[] = {
88 [RKCE_HASH_ALGO_SHA1] = RKCE_HMAC_VER_SHA1_FLAG_MASK,
89 [RKCE_HASH_ALGO_SHA256] = RKCE_HMAC_VER_SHA256_FLAG_MASK,
90 [RKCE_HASH_ALGO_SHA512] = RKCE_HMAC_VER_SHA512_FLAG_MASK,
91 [RKCE_HASH_ALGO_MD5] = RKCE_HMAC_VER_MD5_FLAG_MASK,
92 [RKCE_HASH_ALGO_SM3] = RKCE_HMAC_VER_SM3_FLAG_MASK,
93 };
94
rk_is_cipher_support(struct RKCE_REG * rkce_reg,uint32_t algo,uint32_t mode,uint32_t key_len)95 static bool rk_is_cipher_support(struct RKCE_REG *rkce_reg,
96 uint32_t algo, uint32_t mode, uint32_t key_len)
97 {
98 uint32_t version = 0;
99 uint32_t mask = 0;
100 bool key_len_valid = true;
101
102 switch (algo) {
103 case RKCE_SYMM_ALGO_DES:
104 case RKCE_SYMM_ALGO_TDES:
105 version = rkce_reg->DES_VER;
106
107 if (key_len == RKCE_DES_BLOCK_SIZE)
108 key_len_valid = true;
109 else if (key_len == 2 * RKCE_DES_BLOCK_SIZE ||
110 key_len == 3 * RKCE_DES_BLOCK_SIZE)
111 key_len_valid = version & RKCE_DES_VER_TDES_FLAG_MASK;
112 else
113 key_len_valid = false;
114 break;
115 case RKCE_SYMM_ALGO_AES:
116 version = rkce_reg->AES_VER;
117
118 if (key_len == RKCE_AES_KEYSIZE_128)
119 key_len_valid = version & RKCE_AES_VER_AES128_FLAG_MASK;
120 else if (key_len == RKCE_AES_KEYSIZE_192)
121 key_len_valid = version & RKCE_AES_VER_AES192_FLAG_MASK;
122 else if (key_len == RKCE_KEY_AES_256)
123 key_len_valid = version & RKCE_AES_VER_AES256_FLAG_MASK;
124 else
125 key_len_valid = false;
126 break;
127 case RKCE_SYMM_ALGO_SM4:
128 version = rkce_reg->SM4_VER;
129
130 key_len_valid = (key_len == RKCE_SM4_KEYSIZE) ? true : false;
131 break;
132 default:
133 return false;
134 }
135
136 mask = cipher_mode2bit_mask[mode];
137
138 if (key_len == 0)
139 key_len_valid = true;
140
141 return (version & mask) && key_len_valid;
142 }
143
rk_is_hash_support(struct RKCE_REG * rkce_reg,uint32_t algo,uint32_t type)144 static bool rk_is_hash_support(struct RKCE_REG *rkce_reg, uint32_t algo, uint32_t type)
145 {
146 uint32_t version = 0;
147 uint32_t mask = 0;
148
149 if (type == RKCE_ALGO_TYPE_HMAC) {
150 version = rkce_reg->HMAC_VER;
151 mask = hmac_algo2bit_mask[algo];
152 } else if (type == RKCE_ALGO_TYPE_HASH) {
153 version = rkce_reg->HASH_VER;
154 mask = hash_algo2bit_mask[algo];
155 } else {
156 return false;
157 }
158
159 return version & mask;
160 }
161
rk_is_asym_support(struct RKCE_REG * rkce_reg,uint32_t algo)162 static bool rk_is_asym_support(struct RKCE_REG *rkce_reg, uint32_t algo)
163 {
164 switch (algo) {
165 case RKCE_ASYM_ALGO_RSA:
166 return !!rkce_reg->PKA_VER;
167 case RKCE_ASYM_ALGO_ECC_P192:
168 case RKCE_ASYM_ALGO_ECC_P224:
169 case RKCE_ASYM_ALGO_ECC_P256:
170 case RKCE_ASYM_ALGO_SM2:
171 return !!rkce_reg->ECC_MAX_CURVE_WIDE;
172 default:
173 return false;
174 }
175 }
176
rkce_hw_algo_valid(void * rkce_hw,uint32_t type,uint32_t algo,uint32_t mode)177 bool rkce_hw_algo_valid(void *rkce_hw, uint32_t type, uint32_t algo, uint32_t mode)
178 {
179 struct RKCE_REG *rkce_reg;
180
181 CHECK_RKCE_INITED(rkce_hw);
182
183 rkce_reg = GET_RKCE_REG(rkce_hw);
184
185 if (type == RKCE_ALGO_TYPE_CIPHER || type == RKCE_ALGO_TYPE_AEAD) {
186 rk_debug("CIPHER");
187 return rk_is_cipher_support(rkce_reg, algo, mode, 0);
188 } else if (type == RKCE_ALGO_TYPE_HASH || type == RKCE_ALGO_TYPE_HMAC) {
189 rk_debug("HASH/HMAC");
190 return rk_is_hash_support(rkce_reg, algo, type);
191 } else if (type == RKCE_ALGO_TYPE_ASYM) {
192 rk_debug("ASYM");
193 return rk_is_asym_support(rkce_reg, algo);
194 } else {
195 return false;
196 }
197 }
198
rkce_get_td_type(void * td)199 uint32_t rkce_get_td_type(void *td)
200 {
201 if (!td)
202 return ~((uint32_t)0);
203
204 return ((struct rkce_symm_td *)td)->ctrl.td_type;
205 }
206
rkce_soft_reset(void * rkce_hw,uint32_t reset_sel)207 int rkce_soft_reset(void *rkce_hw, uint32_t reset_sel)
208 {
209 struct RKCE_REG *rkce_reg;
210 uint32_t value = 0;
211
212 CHECK_RKCE_INITED(rkce_hw);
213
214 rkce_reg = GET_RKCE_REG(rkce_hw);
215
216 if (reset_sel & RKCE_RESET_SYMM)
217 value |= RKCE_RST_CTL_SW_SYMM_RESET_SHIFT;
218
219 if (reset_sel & RKCE_RESET_HASH)
220 value |= RKCE_RST_CTL_SW_HASH_RESET_SHIFT;
221
222 if (reset_sel & RKCE_RESET_PKA)
223 value |= RKCE_RST_CTL_SW_PKA_RESET_SHIFT;
224
225 rkce_reg->RST_CTL = value | RKCE_WRITE_MASK_ALL;
226
227 return POLL_TIMEOUT(rkce_reg->RST_CTL, RST_TIMEOUT_MS);
228 }
229
rkce_check_version(struct RKCE_REG * rkce_reg)230 static int rkce_check_version(struct RKCE_REG *rkce_reg)
231 {
232 rk_debug("rkce_reg->CE_VER = %08x\n", rkce_reg->CE_VER);
233
234 if (GET_IP_VERSION(rkce_reg->CE_VER) != IP_VERSION_RKCE) {
235 rk_err("IP version is %08x not a RKCE module.\n", rkce_reg->CE_VER);
236 return -RKCE_FAULT;
237 }
238
239 return RKCE_SUCCESS;
240 }
241
rkce_init(void * rkce_hw)242 static int rkce_init(void *rkce_hw)
243 {
244 struct RKCE_REG *rkce_reg = GET_RKCE_REG(rkce_hw);
245 uint32_t value = 0;
246 int ret;
247
248 ret = rkce_check_version(rkce_reg);
249 if (ret)
250 goto exit;
251
252 rkce_soft_reset(rkce_hw, RKCE_RESET_SYMM | RKCE_RESET_HASH | RKCE_RESET_PKA);
253
254 /* clear symm interrupt register */
255 rkce_reg->SYMM_INT_EN = 0;
256 value = rkce_reg->SYMM_INT_ST;
257 rkce_reg->SYMM_INT_ST = value;
258
259 ret = POLL_TIMEOUT(rkce_reg->SYMM_INT_ST, RST_TIMEOUT_MS);
260 if (ret)
261 goto exit;
262
263 /* clear hash interrupt register */
264 rkce_reg->HASH_INT_EN = 0;
265 value = rkce_reg->HASH_INT_ST;
266 rkce_reg->HASH_INT_ST = value;
267
268 ret = POLL_TIMEOUT(rkce_reg->HASH_INT_ST, RST_TIMEOUT_MS);
269 if (ret)
270 goto exit;
271
272 if (rkce_reg->SYMM_CONTEXT_SIZE != RKCE_TD_SYMM_CTX_SIZE) {
273 rk_err("rkce symm context size (%u) != %u\n",
274 rkce_reg->SYMM_CONTEXT_SIZE, RKCE_TD_SYMM_CTX_SIZE);
275 return -RKCE_INVAL;
276 }
277
278 if (rkce_reg->HASH_CONTEXT_SIZE != RKCE_TD_HASH_CTX_SIZE) {
279 rk_err("rkce hash context size (%u) != %u\n",
280 rkce_reg->HASH_CONTEXT_SIZE, RKCE_TD_HASH_CTX_SIZE);
281 return -RKCE_INVAL;
282 }
283
284 exit:
285 return ret;
286 }
287
rkce_hardware_alloc(void __iomem * reg_base)288 void *rkce_hardware_alloc(void __iomem *reg_base)
289 {
290 struct rkce_hardware *hardware;
291
292 rk_debug("reg_base = %p", reg_base);
293
294 if (!reg_base)
295 return NULL;
296
297 hardware = malloc(sizeof(*hardware));
298 if (!hardware)
299 return NULL;
300
301 hardware->rkce_reg = reg_base;
302
303 if (rkce_init(hardware) != 0) {
304 free(hardware);
305 return NULL;
306 }
307
308 rk_debug("hardware = %p", hardware);
309
310 return hardware;
311 }
312
rkce_hardware_free(void * rkce_hw)313 void rkce_hardware_free(void *rkce_hw)
314 {
315 if (!rkce_hw)
316 return;
317
318 free(rkce_hw);
319 }
320
rkce_dump_reginfo(void * rkce_hw)321 void rkce_dump_reginfo(void *rkce_hw)
322 {
323 struct RKCE_REG *rkce_reg;
324
325 CHECK_RKCE_INITED(rkce_hw);
326
327 rkce_reg = GET_RKCE_REG(rkce_hw);
328
329 rk_info("\n============================== reg info ===========================\n");
330 rk_info("FIFO_ST = %08x\n", rkce_reg->FIFO_ST);
331 rk_info("\n");
332 rk_info("SYMM_INT_EN = %08x\n", rkce_reg->SYMM_INT_EN);
333 rk_info("SYMM_INT_ST = %08x\n", rkce_reg->SYMM_INT_ST);
334 rk_info("SYMM_TD_ST = %08x\n", rkce_reg->SYMM_TD_ST);
335 rk_info("SYMM_TD_ID = %08x\n", rkce_reg->SYMM_TD_ID);
336 rk_info("SYMM_ST_DBG = %08x\n", rkce_reg->SYMM_ST_DBG);
337 rk_info("SYMM_TD_ADDR_DBG = %08x\n", rkce_reg->SYMM_TD_ADDR_DBG);
338 rk_info("SYMM_TD_GRANT_DBG = %08x\n", rkce_reg->SYMM_TD_GRANT_DBG);
339 rk_info("\n");
340 rk_info("HASH_INT_EN = %08x\n", rkce_reg->HASH_INT_EN);
341 rk_info("HASH_INT_ST = %08x\n", rkce_reg->HASH_INT_ST);
342 rk_info("HASH_TD_ST = %08x\n", rkce_reg->HASH_TD_ST);
343 rk_info("HASH_TD_ID = %08x\n", rkce_reg->HASH_TD_ID);
344 rk_info("HASH_ST_DBG = %08x\n", rkce_reg->HASH_ST_DBG);
345 rk_info("HASH_TD_ADDR_DBG = %08x\n", rkce_reg->HASH_TD_ADDR_DBG);
346 rk_info("HASH_TD_GRANT_DBG = %08x\n", rkce_reg->HASH_TD_GRANT_DBG);
347 rk_info("===================================================================\n");
348 }
349
rkce_push_td(void * rkce_hw,void * td)350 int rkce_push_td(void *rkce_hw, void *td)
351 {
352 int ret = RKCE_SUCCESS;
353 struct RKCE_REG *rkce_reg;
354 uint32_t td_type;
355 struct rkce_hardware *hardware = rkce_hw;
356
357 CHECK_RKCE_INITED(rkce_hw);
358
359 if (!td)
360 return -RKCE_INVAL;
361
362 td_type = rkce_get_td_type(td);
363 rkce_reg = GET_RKCE_REG(rkce_hw);
364
365 rkce_dump_td(td);
366
367 if (IS_SYMM_TD(td_type)) {
368 rk_debug("rkce symm push td virt(%p), phys(%lx)\n",
369 td, rkce_cma_virt2phys(td));
370
371 WRITE_ONCE(rkce_reg->SYMM_INT_EN, 0x3f);
372
373 /* wait symm fifo valid */
374 ret = POLL_TIMEOUT(rkce_reg->TD_LOAD_CTRL & RKCE_TD_LOAD_CTRL_SYMM_TLR_MASK,
375 TD_PUSH_TIMEOUT_MS);
376 if (ret)
377 goto exit;
378
379 /* set task desc address */
380 rkce_reg->TD_ADDR = rkce_cma_virt2phys(td);
381 hardware->chn[RKCE_TD_TYPE_SYMM].td_virt = td;
382
383 /* tell rkce to load task desc address as symm td */
384 rkce_reg->TD_LOAD_CTRL = 0xffff0000 | RKCE_TD_LOAD_CTRL_SYMM_TLR_MASK;
385 } else if (IS_HASH_TD(td_type)) {
386 rk_debug("rkce hash push td virt(%p), phys(%lx)\n",
387 td, rkce_cma_virt2phys(td));
388
389 WRITE_ONCE(rkce_reg->HASH_INT_EN, 0x3f);
390
391 /* wait hash fifo valid */
392 ret = POLL_TIMEOUT(rkce_reg->TD_LOAD_CTRL & RKCE_TD_LOAD_CTRL_HASH_TLR_MASK,
393 TD_PUSH_TIMEOUT_MS);
394 if (ret)
395 goto exit;
396
397 /* set task desc address */
398 rkce_reg->TD_ADDR = rkce_cma_virt2phys(td);
399 hardware->chn[RKCE_TD_TYPE_HASH].td_virt = td;
400
401 /* tell rkce to load task desc address as hash td */
402 rkce_reg->TD_LOAD_CTRL = 0xffff0000 | RKCE_TD_LOAD_CTRL_HASH_TLR_MASK;
403 } else {
404 return -RKCE_INVAL;
405 }
406
407 exit:
408 return ret;
409 }
410
rkce_push_td_sync(void * rkce_hw,void * td,uint32_t timeout_ms)411 int rkce_push_td_sync(void *rkce_hw, void *td, uint32_t timeout_ms)
412 {
413 int ret = RKCE_SUCCESS;
414 struct RKCE_REG *rkce_reg;
415 uint32_t td_type;
416 uint32_t value, mask;
417
418 CHECK_RKCE_INITED(rkce_hw);
419
420 if (!td)
421 return -RKCE_INVAL;
422
423 td_type = rkce_get_td_type(td);
424 rkce_reg = GET_RKCE_REG(rkce_hw);
425
426 rkce_dump_td(td);
427
428 if (IS_SYMM_TD(td_type)) {
429 rk_debug("rkce symm push td virt(%p), phys(%lx)\n",
430 td, rkce_cma_virt2phys(td));
431
432 WRITE_ONCE(rkce_reg->SYMM_INT_EN, 0x00);
433
434 /* wait symm fifo valid */
435 ret = POLL_TIMEOUT(rkce_reg->TD_LOAD_CTRL & RKCE_TD_LOAD_CTRL_SYMM_TLR_MASK,
436 timeout_ms);
437 if (ret)
438 goto exit;
439
440 /* set task desc address */
441 rkce_reg->TD_ADDR = rkce_cma_virt2phys(td);
442
443 /* tell rkce to load task desc address as symm td */
444 rkce_reg->TD_LOAD_CTRL = 0xffff0000 | RKCE_TD_LOAD_CTRL_SYMM_TLR_MASK;
445
446 /* wait symm done */
447 ret = POLL_TIMEOUT(!(rkce_reg->SYMM_INT_ST), timeout_ms);
448 mask = RKCE_SYMM_INT_ST_TD_DONE_MASK;
449 value = READ_ONCE(rkce_reg->SYMM_INT_ST);
450 WRITE_ONCE(rkce_reg->SYMM_INT_ST, value);
451 rk_debug("symm ret = %d, value = %08x, IN_ST = %08x\n",
452 ret, value, READ_ONCE(rkce_reg->SYMM_INT_ST));
453 } else if (IS_HASH_TD(td_type)) {
454 rk_debug("rkce hash push td virt(%p), phys(%lx)\n",
455 td, rkce_cma_virt2phys(td));
456
457 WRITE_ONCE(rkce_reg->HASH_INT_EN, 0x00);
458
459 /* wait hash fifo valid */
460 ret = POLL_TIMEOUT(rkce_reg->TD_LOAD_CTRL & RKCE_TD_LOAD_CTRL_HASH_TLR_MASK,
461 timeout_ms);
462 if (ret)
463 goto exit;
464
465 /* set task desc address */
466 rkce_reg->TD_ADDR = rkce_cma_virt2phys(td);
467
468 /* tell rkce to load task desc address as hash td */
469 rkce_reg->TD_LOAD_CTRL = 0xffff0000 | RKCE_TD_LOAD_CTRL_HASH_TLR_MASK;
470
471 /* wait hash done */
472 ret = POLL_TIMEOUT(!(rkce_reg->HASH_INT_ST), timeout_ms);
473 mask = RKCE_HASH_INT_ST_TD_DONE_MASK;
474 value = READ_ONCE(rkce_reg->HASH_INT_ST);
475 WRITE_ONCE(rkce_reg->HASH_INT_ST, value);
476 rk_debug("hash ret = %d, value = %08x, INT_ST = %08x\n",
477 ret, value, READ_ONCE(rkce_reg->HASH_INT_ST));
478 } else {
479 rk_debug("unknown td_type = %u\n", td_type);
480 return -RKCE_INVAL;
481 }
482
483 if (ret)
484 goto exit;
485
486 ret = (value == mask) ? 0 : -RKCE_FAULT;
487 exit:
488 return ret;
489 }
490
rkce_init_symm_td(struct rkce_symm_td * td,struct rkce_symm_td_buf * buf)491 int rkce_init_symm_td(struct rkce_symm_td *td, struct rkce_symm_td_buf *buf)
492 {
493 if (!td ||
494 !buf ||
495 !rkce_cma_virt2phys(td) ||
496 !rkce_cma_virt2phys(buf)) {
497 rk_debug("td = %p buf = %p", td, buf);
498 return -RKCE_INVAL;
499 }
500
501 memset(td, 0x00, sizeof(*td));
502
503 td->ctrl.td_type = RKCE_TD_TYPE_SYMM;
504 td->task_id = rkce_cma_virt2phys(buf);
505 td->key_addr = rkce_cma_virt2phys(buf->key1);
506 td->iv_addr = rkce_cma_virt2phys(buf->iv);
507 td->gcm_len_addr = rkce_cma_virt2phys(&buf->gcm_len);
508 td->tag_addr = rkce_cma_virt2phys(buf->tag);
509 td->symm_ctx_addr = rkce_cma_virt2phys(buf->ctx);
510
511 return RKCE_SUCCESS;
512 }
513
rkce_init_hash_td(struct rkce_hash_td * td,struct rkce_hash_td_buf * buf)514 int rkce_init_hash_td(struct rkce_hash_td *td, struct rkce_hash_td_buf *buf)
515 {
516 if (!td ||
517 !buf ||
518 !rkce_cma_virt2phys(td) ||
519 !rkce_cma_virt2phys(buf)) {
520 rk_debug("td = %p buf = %p", td, buf);
521 return -RKCE_INVAL;
522 }
523
524 memset(td, 0x00, sizeof(*td));
525
526 td->ctrl.td_type = RKCE_TD_TYPE_HASH;
527 td->task_id = rkce_cma_virt2phys(buf);
528 td->key_addr = rkce_cma_virt2phys(buf->key);
529 td->hash_addr = rkce_cma_virt2phys(buf->hash);
530 td->hash_ctx_addr = rkce_cma_virt2phys(buf->ctx);
531
532 return RKCE_SUCCESS;
533 }
534
rkce_irq_callback_set(void * rkce_hw,enum rkce_td_type td_type,request_cb_func cb_func)535 int rkce_irq_callback_set(void *rkce_hw, enum rkce_td_type td_type, request_cb_func cb_func)
536 {
537 struct rkce_hardware *hardware = rkce_hw;
538
539 CHECK_RKCE_INITED(rkce_hw);
540
541 if (!cb_func)
542 return -RKCE_INVAL;
543
544 if (td_type == RKCE_TD_TYPE_SYMM)
545 hardware->chn[RKCE_TD_TYPE_SYMM].cb_func = cb_func;
546 else if (td_type == RKCE_TD_TYPE_HASH)
547 hardware->chn[RKCE_TD_TYPE_HASH].cb_func = cb_func;
548 else
549 return -RKCE_INVAL;
550
551 return RKCE_SUCCESS;
552 }
553
rkce_irq_handler(void * rkce_hw)554 void rkce_irq_handler(void *rkce_hw)
555 {
556 struct rkce_chn_info *cur_chn;
557 struct RKCE_REG *rkce_reg;
558 struct rkce_hardware *hardware = rkce_hw;
559
560 CHECK_RKCE_INITED(rkce_hw);
561
562 rkce_reg = GET_RKCE_REG(rkce_hw);
563
564 if (rkce_reg->SYMM_INT_ST) {
565 cur_chn = &hardware->chn[RKCE_TD_TYPE_SYMM];
566 cur_chn->int_st = READ_ONCE(rkce_reg->SYMM_INT_ST);
567 cur_chn->td_id = rkce_reg->SYMM_TD_ID;
568
569 /* clear symm int */
570 WRITE_ONCE(rkce_reg->SYMM_INT_ST, cur_chn->int_st);
571
572 cur_chn->result = (cur_chn->int_st == RKCE_SYMM_INT_ST_TD_DONE_MASK) ?
573 RKCE_SUCCESS : cur_chn->int_st;
574 }
575
576 if (rkce_reg->HASH_INT_ST) {
577 cur_chn = &hardware->chn[RKCE_TD_TYPE_HASH];
578 cur_chn->int_st = READ_ONCE(rkce_reg->HASH_INT_ST);
579 cur_chn->td_id = rkce_reg->HASH_TD_ID;
580
581 /* clear hash int */
582 WRITE_ONCE(rkce_reg->HASH_INT_ST, cur_chn->int_st);
583
584 cur_chn->result = (cur_chn->int_st == RKCE_HASH_INT_ST_TD_DONE_MASK) ?
585 RKCE_SUCCESS : cur_chn->int_st;
586 }
587 }
588
rkce_irq_thread(void * rkce_hw)589 void rkce_irq_thread(void *rkce_hw)
590 {
591 uint32_t i;
592 bool is_fault = false;
593 struct rkce_hardware *hardware = rkce_hw;
594
595 CHECK_RKCE_INITED(rkce_hw);
596
597 for (i = 0; i < ARRAY_SIZE(hardware->chn); i++) {
598 struct rkce_chn_info *cur_chn = &hardware->chn[i];
599
600 if (cur_chn->result) {
601 is_fault = true;
602 rk_err("td_type = %u, wrong SISR = %08x, td_id = %08x, td_virt = %p\n",
603 i, cur_chn->int_st, cur_chn->td_id, cur_chn->td_virt);
604 }
605
606 if (cur_chn->int_st == 0 || !(cur_chn->cb_func))
607 continue;
608
609 rk_debug("##################### finalize td %p, result = %d\n",
610 cur_chn->td_virt, cur_chn->result);
611
612 if (cur_chn->cb_func && cur_chn->td_virt)
613 cur_chn->cb_func(cur_chn->result, cur_chn->td_id, cur_chn->td_virt);
614
615 cur_chn->result = 0;
616 cur_chn->int_st = 0;
617 cur_chn->td_id = 0;
618 cur_chn->td_virt = NULL;
619 }
620
621 if (is_fault)
622 rkce_dump_reginfo(hardware);
623 }
624
rkce_get_keytable_addr(void * rkce_hw)625 uint32_t rkce_get_keytable_addr(void *rkce_hw)
626 {
627 struct RKCE_REG *rkce_reg;
628
629 CHECK_RKCE_INITED(rkce_hw);
630
631 rkce_reg = GET_RKCE_REG(rkce_hw);
632
633 return rkce_reg->KL_TO_CE_PADDR + CRYPTO_CH0_KEY_0;
634 }
635