xref: /rk3399_rockchip-uboot/drivers/crypto/rockchip/rkce_core.c (revision 8f7f431fc3314b4d44fc6ab0ecd2b6ae4ecaa9b9)
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