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 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 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 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 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 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 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 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 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 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 313 void rkce_hardware_free(void *rkce_hw) 314 { 315 if (!rkce_hw) 316 return; 317 318 free(rkce_hw); 319 } 320 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 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 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 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 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 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 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 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 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