1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * sun8i-ss-core.c - hardware cryptographic offloader for 4 * Allwinner A80/A83T SoC 5 * 6 * Copyright (C) 2015-2019 Corentin Labbe <clabbe.montjoie@gmail.com> 7 * 8 * Core file which registers crypto algorithms supported by the SecuritySystem 9 * 10 * You could find a link for the datasheet in Documentation/arm/sunxi.rst 11 */ 12 #include <linux/clk.h> 13 #include <linux/crypto.h> 14 #include <linux/delay.h> 15 #include <linux/dma-mapping.h> 16 #include <linux/interrupt.h> 17 #include <linux/io.h> 18 #include <linux/irq.h> 19 #include <linux/module.h> 20 #include <linux/of.h> 21 #include <linux/of_device.h> 22 #include <linux/platform_device.h> 23 #include <linux/pm_runtime.h> 24 #include <linux/reset.h> 25 #include <crypto/internal/rng.h> 26 #include <crypto/internal/skcipher.h> 27 28 #include "sun8i-ss.h" 29 30 static const struct ss_variant ss_a80_variant = { 31 .alg_cipher = { SS_ALG_AES, SS_ALG_DES, SS_ALG_3DES, 32 }, 33 .alg_hash = { SS_ID_NOTSUPP, SS_ID_NOTSUPP, SS_ID_NOTSUPP, SS_ID_NOTSUPP, 34 }, 35 .op_mode = { SS_OP_ECB, SS_OP_CBC, 36 }, 37 .ss_clks = { 38 { "bus", 0, 300 * 1000 * 1000 }, 39 { "mod", 0, 300 * 1000 * 1000 }, 40 } 41 }; 42 43 static const struct ss_variant ss_a83t_variant = { 44 .alg_cipher = { SS_ALG_AES, SS_ALG_DES, SS_ALG_3DES, 45 }, 46 .alg_hash = { SS_ALG_MD5, SS_ALG_SHA1, SS_ALG_SHA224, SS_ALG_SHA256, 47 }, 48 .op_mode = { SS_OP_ECB, SS_OP_CBC, 49 }, 50 .ss_clks = { 51 { "bus", 0, 300 * 1000 * 1000 }, 52 { "mod", 0, 300 * 1000 * 1000 }, 53 } 54 }; 55 56 /* 57 * sun8i_ss_get_engine_number() get the next channel slot 58 * This is a simple round-robin way of getting the next channel 59 */ 60 int sun8i_ss_get_engine_number(struct sun8i_ss_dev *ss) 61 { 62 return atomic_inc_return(&ss->flow) % MAXFLOW; 63 } 64 65 int sun8i_ss_run_task(struct sun8i_ss_dev *ss, struct sun8i_cipher_req_ctx *rctx, 66 const char *name) 67 { 68 int flow = rctx->flow; 69 unsigned int ivlen = rctx->ivlen; 70 u32 v = SS_START; 71 int i; 72 73 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG 74 ss->flows[flow].stat_req++; 75 #endif 76 77 /* choose between stream0/stream1 */ 78 if (flow) 79 v |= SS_FLOW1; 80 else 81 v |= SS_FLOW0; 82 83 v |= rctx->op_mode; 84 v |= rctx->method; 85 86 if (rctx->op_dir) 87 v |= SS_DECRYPTION; 88 89 switch (rctx->keylen) { 90 case 128 / 8: 91 v |= SS_AES_128BITS << 7; 92 break; 93 case 192 / 8: 94 v |= SS_AES_192BITS << 7; 95 break; 96 case 256 / 8: 97 v |= SS_AES_256BITS << 7; 98 break; 99 } 100 101 for (i = 0; i < MAX_SG; i++) { 102 if (!rctx->t_dst[i].addr) 103 break; 104 105 mutex_lock(&ss->mlock); 106 writel(rctx->p_key, ss->base + SS_KEY_ADR_REG); 107 108 if (ivlen) { 109 if (rctx->op_dir == SS_ENCRYPTION) { 110 if (i == 0) 111 writel(rctx->p_iv[0], ss->base + SS_IV_ADR_REG); 112 else 113 writel(rctx->t_dst[i - 1].addr + rctx->t_dst[i - 1].len * 4 - ivlen, ss->base + SS_IV_ADR_REG); 114 } else { 115 writel(rctx->p_iv[i], ss->base + SS_IV_ADR_REG); 116 } 117 } 118 119 dev_dbg(ss->dev, 120 "Processing SG %d on flow %d %s ctl=%x %d to %d method=%x opmode=%x opdir=%x srclen=%d\n", 121 i, flow, name, v, 122 rctx->t_src[i].len, rctx->t_dst[i].len, 123 rctx->method, rctx->op_mode, 124 rctx->op_dir, rctx->t_src[i].len); 125 126 writel(rctx->t_src[i].addr, ss->base + SS_SRC_ADR_REG); 127 writel(rctx->t_dst[i].addr, ss->base + SS_DST_ADR_REG); 128 writel(rctx->t_src[i].len, ss->base + SS_LEN_ADR_REG); 129 130 reinit_completion(&ss->flows[flow].complete); 131 ss->flows[flow].status = 0; 132 wmb(); 133 134 writel(v, ss->base + SS_CTL_REG); 135 mutex_unlock(&ss->mlock); 136 wait_for_completion_interruptible_timeout(&ss->flows[flow].complete, 137 msecs_to_jiffies(2000)); 138 if (ss->flows[flow].status == 0) { 139 dev_err(ss->dev, "DMA timeout for %s\n", name); 140 return -EFAULT; 141 } 142 } 143 144 return 0; 145 } 146 147 static irqreturn_t ss_irq_handler(int irq, void *data) 148 { 149 struct sun8i_ss_dev *ss = (struct sun8i_ss_dev *)data; 150 int flow = 0; 151 u32 p; 152 153 p = readl(ss->base + SS_INT_STA_REG); 154 for (flow = 0; flow < MAXFLOW; flow++) { 155 if (p & (BIT(flow))) { 156 writel(BIT(flow), ss->base + SS_INT_STA_REG); 157 ss->flows[flow].status = 1; 158 complete(&ss->flows[flow].complete); 159 } 160 } 161 162 return IRQ_HANDLED; 163 } 164 165 static struct sun8i_ss_alg_template ss_algs[] = { 166 { 167 .type = CRYPTO_ALG_TYPE_SKCIPHER, 168 .ss_algo_id = SS_ID_CIPHER_AES, 169 .ss_blockmode = SS_ID_OP_CBC, 170 .alg.skcipher = { 171 .base = { 172 .cra_name = "cbc(aes)", 173 .cra_driver_name = "cbc-aes-sun8i-ss", 174 .cra_priority = 400, 175 .cra_blocksize = AES_BLOCK_SIZE, 176 .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 177 CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | 178 CRYPTO_ALG_NEED_FALLBACK, 179 .cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx), 180 .cra_module = THIS_MODULE, 181 .cra_alignmask = 0xf, 182 .cra_init = sun8i_ss_cipher_init, 183 .cra_exit = sun8i_ss_cipher_exit, 184 }, 185 .min_keysize = AES_MIN_KEY_SIZE, 186 .max_keysize = AES_MAX_KEY_SIZE, 187 .ivsize = AES_BLOCK_SIZE, 188 .setkey = sun8i_ss_aes_setkey, 189 .encrypt = sun8i_ss_skencrypt, 190 .decrypt = sun8i_ss_skdecrypt, 191 } 192 }, 193 { 194 .type = CRYPTO_ALG_TYPE_SKCIPHER, 195 .ss_algo_id = SS_ID_CIPHER_AES, 196 .ss_blockmode = SS_ID_OP_ECB, 197 .alg.skcipher = { 198 .base = { 199 .cra_name = "ecb(aes)", 200 .cra_driver_name = "ecb-aes-sun8i-ss", 201 .cra_priority = 400, 202 .cra_blocksize = AES_BLOCK_SIZE, 203 .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 204 CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | 205 CRYPTO_ALG_NEED_FALLBACK, 206 .cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx), 207 .cra_module = THIS_MODULE, 208 .cra_alignmask = 0xf, 209 .cra_init = sun8i_ss_cipher_init, 210 .cra_exit = sun8i_ss_cipher_exit, 211 }, 212 .min_keysize = AES_MIN_KEY_SIZE, 213 .max_keysize = AES_MAX_KEY_SIZE, 214 .setkey = sun8i_ss_aes_setkey, 215 .encrypt = sun8i_ss_skencrypt, 216 .decrypt = sun8i_ss_skdecrypt, 217 } 218 }, 219 { 220 .type = CRYPTO_ALG_TYPE_SKCIPHER, 221 .ss_algo_id = SS_ID_CIPHER_DES3, 222 .ss_blockmode = SS_ID_OP_CBC, 223 .alg.skcipher = { 224 .base = { 225 .cra_name = "cbc(des3_ede)", 226 .cra_driver_name = "cbc-des3-sun8i-ss", 227 .cra_priority = 400, 228 .cra_blocksize = DES3_EDE_BLOCK_SIZE, 229 .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 230 CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | 231 CRYPTO_ALG_NEED_FALLBACK, 232 .cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx), 233 .cra_module = THIS_MODULE, 234 .cra_alignmask = 0xf, 235 .cra_init = sun8i_ss_cipher_init, 236 .cra_exit = sun8i_ss_cipher_exit, 237 }, 238 .min_keysize = DES3_EDE_KEY_SIZE, 239 .max_keysize = DES3_EDE_KEY_SIZE, 240 .ivsize = DES3_EDE_BLOCK_SIZE, 241 .setkey = sun8i_ss_des3_setkey, 242 .encrypt = sun8i_ss_skencrypt, 243 .decrypt = sun8i_ss_skdecrypt, 244 } 245 }, 246 { 247 .type = CRYPTO_ALG_TYPE_SKCIPHER, 248 .ss_algo_id = SS_ID_CIPHER_DES3, 249 .ss_blockmode = SS_ID_OP_ECB, 250 .alg.skcipher = { 251 .base = { 252 .cra_name = "ecb(des3_ede)", 253 .cra_driver_name = "ecb-des3-sun8i-ss", 254 .cra_priority = 400, 255 .cra_blocksize = DES3_EDE_BLOCK_SIZE, 256 .cra_flags = CRYPTO_ALG_TYPE_SKCIPHER | 257 CRYPTO_ALG_ASYNC | CRYPTO_ALG_ALLOCATES_MEMORY | 258 CRYPTO_ALG_NEED_FALLBACK, 259 .cra_ctxsize = sizeof(struct sun8i_cipher_tfm_ctx), 260 .cra_module = THIS_MODULE, 261 .cra_alignmask = 0xf, 262 .cra_init = sun8i_ss_cipher_init, 263 .cra_exit = sun8i_ss_cipher_exit, 264 }, 265 .min_keysize = DES3_EDE_KEY_SIZE, 266 .max_keysize = DES3_EDE_KEY_SIZE, 267 .setkey = sun8i_ss_des3_setkey, 268 .encrypt = sun8i_ss_skencrypt, 269 .decrypt = sun8i_ss_skdecrypt, 270 } 271 }, 272 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_PRNG 273 { 274 .type = CRYPTO_ALG_TYPE_RNG, 275 .alg.rng = { 276 .base = { 277 .cra_name = "stdrng", 278 .cra_driver_name = "sun8i-ss-prng", 279 .cra_priority = 300, 280 .cra_ctxsize = sizeof(struct sun8i_ss_rng_tfm_ctx), 281 .cra_module = THIS_MODULE, 282 .cra_init = sun8i_ss_prng_init, 283 .cra_exit = sun8i_ss_prng_exit, 284 }, 285 .generate = sun8i_ss_prng_generate, 286 .seed = sun8i_ss_prng_seed, 287 .seedsize = PRNG_SEED_SIZE, 288 } 289 }, 290 #endif 291 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_HASH 292 { .type = CRYPTO_ALG_TYPE_AHASH, 293 .ss_algo_id = SS_ID_HASH_MD5, 294 .alg.hash = { 295 .init = sun8i_ss_hash_init, 296 .update = sun8i_ss_hash_update, 297 .final = sun8i_ss_hash_final, 298 .finup = sun8i_ss_hash_finup, 299 .digest = sun8i_ss_hash_digest, 300 .export = sun8i_ss_hash_export, 301 .import = sun8i_ss_hash_import, 302 .halg = { 303 .digestsize = MD5_DIGEST_SIZE, 304 .statesize = sizeof(struct md5_state), 305 .base = { 306 .cra_name = "md5", 307 .cra_driver_name = "md5-sun8i-ss", 308 .cra_priority = 300, 309 .cra_alignmask = 3, 310 .cra_flags = CRYPTO_ALG_TYPE_AHASH | 311 CRYPTO_ALG_ASYNC | 312 CRYPTO_ALG_NEED_FALLBACK, 313 .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 314 .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), 315 .cra_module = THIS_MODULE, 316 .cra_init = sun8i_ss_hash_crainit, 317 .cra_exit = sun8i_ss_hash_craexit, 318 } 319 } 320 } 321 }, 322 { .type = CRYPTO_ALG_TYPE_AHASH, 323 .ss_algo_id = SS_ID_HASH_SHA1, 324 .alg.hash = { 325 .init = sun8i_ss_hash_init, 326 .update = sun8i_ss_hash_update, 327 .final = sun8i_ss_hash_final, 328 .finup = sun8i_ss_hash_finup, 329 .digest = sun8i_ss_hash_digest, 330 .export = sun8i_ss_hash_export, 331 .import = sun8i_ss_hash_import, 332 .halg = { 333 .digestsize = SHA1_DIGEST_SIZE, 334 .statesize = sizeof(struct sha1_state), 335 .base = { 336 .cra_name = "sha1", 337 .cra_driver_name = "sha1-sun8i-ss", 338 .cra_priority = 300, 339 .cra_alignmask = 3, 340 .cra_flags = CRYPTO_ALG_TYPE_AHASH | 341 CRYPTO_ALG_ASYNC | 342 CRYPTO_ALG_NEED_FALLBACK, 343 .cra_blocksize = SHA1_BLOCK_SIZE, 344 .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), 345 .cra_module = THIS_MODULE, 346 .cra_init = sun8i_ss_hash_crainit, 347 .cra_exit = sun8i_ss_hash_craexit, 348 } 349 } 350 } 351 }, 352 { .type = CRYPTO_ALG_TYPE_AHASH, 353 .ss_algo_id = SS_ID_HASH_SHA224, 354 .alg.hash = { 355 .init = sun8i_ss_hash_init, 356 .update = sun8i_ss_hash_update, 357 .final = sun8i_ss_hash_final, 358 .finup = sun8i_ss_hash_finup, 359 .digest = sun8i_ss_hash_digest, 360 .export = sun8i_ss_hash_export, 361 .import = sun8i_ss_hash_import, 362 .halg = { 363 .digestsize = SHA224_DIGEST_SIZE, 364 .statesize = sizeof(struct sha256_state), 365 .base = { 366 .cra_name = "sha224", 367 .cra_driver_name = "sha224-sun8i-ss", 368 .cra_priority = 300, 369 .cra_alignmask = 3, 370 .cra_flags = CRYPTO_ALG_TYPE_AHASH | 371 CRYPTO_ALG_ASYNC | 372 CRYPTO_ALG_NEED_FALLBACK, 373 .cra_blocksize = SHA224_BLOCK_SIZE, 374 .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), 375 .cra_module = THIS_MODULE, 376 .cra_init = sun8i_ss_hash_crainit, 377 .cra_exit = sun8i_ss_hash_craexit, 378 } 379 } 380 } 381 }, 382 { .type = CRYPTO_ALG_TYPE_AHASH, 383 .ss_algo_id = SS_ID_HASH_SHA256, 384 .alg.hash = { 385 .init = sun8i_ss_hash_init, 386 .update = sun8i_ss_hash_update, 387 .final = sun8i_ss_hash_final, 388 .finup = sun8i_ss_hash_finup, 389 .digest = sun8i_ss_hash_digest, 390 .export = sun8i_ss_hash_export, 391 .import = sun8i_ss_hash_import, 392 .halg = { 393 .digestsize = SHA256_DIGEST_SIZE, 394 .statesize = sizeof(struct sha256_state), 395 .base = { 396 .cra_name = "sha256", 397 .cra_driver_name = "sha256-sun8i-ss", 398 .cra_priority = 300, 399 .cra_alignmask = 3, 400 .cra_flags = CRYPTO_ALG_TYPE_AHASH | 401 CRYPTO_ALG_ASYNC | 402 CRYPTO_ALG_NEED_FALLBACK, 403 .cra_blocksize = SHA256_BLOCK_SIZE, 404 .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), 405 .cra_module = THIS_MODULE, 406 .cra_init = sun8i_ss_hash_crainit, 407 .cra_exit = sun8i_ss_hash_craexit, 408 } 409 } 410 } 411 }, 412 { .type = CRYPTO_ALG_TYPE_AHASH, 413 .ss_algo_id = SS_ID_HASH_SHA1, 414 .alg.hash = { 415 .init = sun8i_ss_hash_init, 416 .update = sun8i_ss_hash_update, 417 .final = sun8i_ss_hash_final, 418 .finup = sun8i_ss_hash_finup, 419 .digest = sun8i_ss_hash_digest, 420 .export = sun8i_ss_hash_export, 421 .import = sun8i_ss_hash_import, 422 .setkey = sun8i_ss_hmac_setkey, 423 .halg = { 424 .digestsize = SHA1_DIGEST_SIZE, 425 .statesize = sizeof(struct sha1_state), 426 .base = { 427 .cra_name = "hmac(sha1)", 428 .cra_driver_name = "hmac-sha1-sun8i-ss", 429 .cra_priority = 300, 430 .cra_alignmask = 3, 431 .cra_flags = CRYPTO_ALG_TYPE_AHASH | 432 CRYPTO_ALG_ASYNC | 433 CRYPTO_ALG_NEED_FALLBACK, 434 .cra_blocksize = SHA1_BLOCK_SIZE, 435 .cra_ctxsize = sizeof(struct sun8i_ss_hash_tfm_ctx), 436 .cra_module = THIS_MODULE, 437 .cra_init = sun8i_ss_hash_crainit, 438 .cra_exit = sun8i_ss_hash_craexit, 439 } 440 } 441 } 442 }, 443 #endif 444 }; 445 446 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG 447 static int sun8i_ss_debugfs_show(struct seq_file *seq, void *v) 448 { 449 struct sun8i_ss_dev *ss = seq->private; 450 unsigned int i; 451 452 for (i = 0; i < MAXFLOW; i++) 453 seq_printf(seq, "Channel %d: nreq %lu\n", i, ss->flows[i].stat_req); 454 455 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 456 if (!ss_algs[i].ss) 457 continue; 458 switch (ss_algs[i].type) { 459 case CRYPTO_ALG_TYPE_SKCIPHER: 460 seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", 461 ss_algs[i].alg.skcipher.base.cra_driver_name, 462 ss_algs[i].alg.skcipher.base.cra_name, 463 ss_algs[i].stat_req, ss_algs[i].stat_fb); 464 465 seq_printf(seq, "\tLast fallback is: %s\n", 466 ss_algs[i].fbname); 467 seq_printf(seq, "\tFallback due to length: %lu\n", 468 ss_algs[i].stat_fb_len); 469 seq_printf(seq, "\tFallback due to SG length: %lu\n", 470 ss_algs[i].stat_fb_sglen); 471 seq_printf(seq, "\tFallback due to alignment: %lu\n", 472 ss_algs[i].stat_fb_align); 473 seq_printf(seq, "\tFallback due to SG numbers: %lu\n", 474 ss_algs[i].stat_fb_sgnum); 475 break; 476 case CRYPTO_ALG_TYPE_RNG: 477 seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n", 478 ss_algs[i].alg.rng.base.cra_driver_name, 479 ss_algs[i].alg.rng.base.cra_name, 480 ss_algs[i].stat_req, ss_algs[i].stat_bytes); 481 break; 482 case CRYPTO_ALG_TYPE_AHASH: 483 seq_printf(seq, "%s %s reqs=%lu fallback=%lu\n", 484 ss_algs[i].alg.hash.halg.base.cra_driver_name, 485 ss_algs[i].alg.hash.halg.base.cra_name, 486 ss_algs[i].stat_req, ss_algs[i].stat_fb); 487 seq_printf(seq, "\tLast fallback is: %s\n", 488 ss_algs[i].fbname); 489 seq_printf(seq, "\tFallback due to length: %lu\n", 490 ss_algs[i].stat_fb_len); 491 seq_printf(seq, "\tFallback due to SG length: %lu\n", 492 ss_algs[i].stat_fb_sglen); 493 seq_printf(seq, "\tFallback due to alignment: %lu\n", 494 ss_algs[i].stat_fb_align); 495 seq_printf(seq, "\tFallback due to SG numbers: %lu\n", 496 ss_algs[i].stat_fb_sgnum); 497 break; 498 } 499 } 500 return 0; 501 } 502 503 DEFINE_SHOW_ATTRIBUTE(sun8i_ss_debugfs); 504 #endif 505 506 static void sun8i_ss_free_flows(struct sun8i_ss_dev *ss, int i) 507 { 508 while (i >= 0) { 509 crypto_engine_exit(ss->flows[i].engine); 510 i--; 511 } 512 } 513 514 /* 515 * Allocate the flow list structure 516 */ 517 static int allocate_flows(struct sun8i_ss_dev *ss) 518 { 519 int i, j, err; 520 521 ss->flows = devm_kcalloc(ss->dev, MAXFLOW, sizeof(struct sun8i_ss_flow), 522 GFP_KERNEL); 523 if (!ss->flows) 524 return -ENOMEM; 525 526 for (i = 0; i < MAXFLOW; i++) { 527 init_completion(&ss->flows[i].complete); 528 529 ss->flows[i].biv = devm_kmalloc(ss->dev, AES_BLOCK_SIZE, 530 GFP_KERNEL | GFP_DMA); 531 if (!ss->flows[i].biv) { 532 err = -ENOMEM; 533 goto error_engine; 534 } 535 536 for (j = 0; j < MAX_SG; j++) { 537 ss->flows[i].iv[j] = devm_kmalloc(ss->dev, AES_BLOCK_SIZE, 538 GFP_KERNEL | GFP_DMA); 539 if (!ss->flows[i].iv[j]) { 540 err = -ENOMEM; 541 goto error_engine; 542 } 543 } 544 545 /* the padding could be up to two block. */ 546 ss->flows[i].pad = devm_kmalloc(ss->dev, MAX_PAD_SIZE, 547 GFP_KERNEL | GFP_DMA); 548 if (!ss->flows[i].pad) { 549 err = -ENOMEM; 550 goto error_engine; 551 } 552 ss->flows[i].result = devm_kmalloc(ss->dev, SHA256_DIGEST_SIZE, 553 GFP_KERNEL | GFP_DMA); 554 if (!ss->flows[i].result) { 555 err = -ENOMEM; 556 goto error_engine; 557 } 558 559 ss->flows[i].engine = crypto_engine_alloc_init(ss->dev, true); 560 if (!ss->flows[i].engine) { 561 dev_err(ss->dev, "Cannot allocate engine\n"); 562 i--; 563 err = -ENOMEM; 564 goto error_engine; 565 } 566 err = crypto_engine_start(ss->flows[i].engine); 567 if (err) { 568 dev_err(ss->dev, "Cannot start engine\n"); 569 goto error_engine; 570 } 571 } 572 return 0; 573 error_engine: 574 sun8i_ss_free_flows(ss, i); 575 return err; 576 } 577 578 /* 579 * Power management strategy: The device is suspended unless a TFM exists for 580 * one of the algorithms proposed by this driver. 581 */ 582 static int sun8i_ss_pm_suspend(struct device *dev) 583 { 584 struct sun8i_ss_dev *ss = dev_get_drvdata(dev); 585 int i; 586 587 reset_control_assert(ss->reset); 588 for (i = 0; i < SS_MAX_CLOCKS; i++) 589 clk_disable_unprepare(ss->ssclks[i]); 590 return 0; 591 } 592 593 static int sun8i_ss_pm_resume(struct device *dev) 594 { 595 struct sun8i_ss_dev *ss = dev_get_drvdata(dev); 596 int err, i; 597 598 for (i = 0; i < SS_MAX_CLOCKS; i++) { 599 if (!ss->variant->ss_clks[i].name) 600 continue; 601 err = clk_prepare_enable(ss->ssclks[i]); 602 if (err) { 603 dev_err(ss->dev, "Cannot prepare_enable %s\n", 604 ss->variant->ss_clks[i].name); 605 goto error; 606 } 607 } 608 err = reset_control_deassert(ss->reset); 609 if (err) { 610 dev_err(ss->dev, "Cannot deassert reset control\n"); 611 goto error; 612 } 613 /* enable interrupts for all flows */ 614 writel(BIT(0) | BIT(1), ss->base + SS_INT_CTL_REG); 615 616 return 0; 617 error: 618 sun8i_ss_pm_suspend(dev); 619 return err; 620 } 621 622 static const struct dev_pm_ops sun8i_ss_pm_ops = { 623 SET_RUNTIME_PM_OPS(sun8i_ss_pm_suspend, sun8i_ss_pm_resume, NULL) 624 }; 625 626 static int sun8i_ss_pm_init(struct sun8i_ss_dev *ss) 627 { 628 int err; 629 630 pm_runtime_use_autosuspend(ss->dev); 631 pm_runtime_set_autosuspend_delay(ss->dev, 2000); 632 633 err = pm_runtime_set_suspended(ss->dev); 634 if (err) 635 return err; 636 pm_runtime_enable(ss->dev); 637 return err; 638 } 639 640 static void sun8i_ss_pm_exit(struct sun8i_ss_dev *ss) 641 { 642 pm_runtime_disable(ss->dev); 643 } 644 645 static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) 646 { 647 int ss_method, err, id; 648 unsigned int i; 649 650 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 651 ss_algs[i].ss = ss; 652 switch (ss_algs[i].type) { 653 case CRYPTO_ALG_TYPE_SKCIPHER: 654 id = ss_algs[i].ss_algo_id; 655 ss_method = ss->variant->alg_cipher[id]; 656 if (ss_method == SS_ID_NOTSUPP) { 657 dev_info(ss->dev, 658 "DEBUG: Algo of %s not supported\n", 659 ss_algs[i].alg.skcipher.base.cra_name); 660 ss_algs[i].ss = NULL; 661 break; 662 } 663 id = ss_algs[i].ss_blockmode; 664 ss_method = ss->variant->op_mode[id]; 665 if (ss_method == SS_ID_NOTSUPP) { 666 dev_info(ss->dev, "DEBUG: Blockmode of %s not supported\n", 667 ss_algs[i].alg.skcipher.base.cra_name); 668 ss_algs[i].ss = NULL; 669 break; 670 } 671 dev_info(ss->dev, "DEBUG: Register %s\n", 672 ss_algs[i].alg.skcipher.base.cra_name); 673 err = crypto_register_skcipher(&ss_algs[i].alg.skcipher); 674 if (err) { 675 dev_err(ss->dev, "Fail to register %s\n", 676 ss_algs[i].alg.skcipher.base.cra_name); 677 ss_algs[i].ss = NULL; 678 return err; 679 } 680 break; 681 case CRYPTO_ALG_TYPE_RNG: 682 err = crypto_register_rng(&ss_algs[i].alg.rng); 683 if (err) { 684 dev_err(ss->dev, "Fail to register %s\n", 685 ss_algs[i].alg.rng.base.cra_name); 686 ss_algs[i].ss = NULL; 687 } 688 break; 689 case CRYPTO_ALG_TYPE_AHASH: 690 id = ss_algs[i].ss_algo_id; 691 ss_method = ss->variant->alg_hash[id]; 692 if (ss_method == SS_ID_NOTSUPP) { 693 dev_info(ss->dev, 694 "DEBUG: Algo of %s not supported\n", 695 ss_algs[i].alg.hash.halg.base.cra_name); 696 ss_algs[i].ss = NULL; 697 break; 698 } 699 dev_info(ss->dev, "Register %s\n", 700 ss_algs[i].alg.hash.halg.base.cra_name); 701 err = crypto_register_ahash(&ss_algs[i].alg.hash); 702 if (err) { 703 dev_err(ss->dev, "ERROR: Fail to register %s\n", 704 ss_algs[i].alg.hash.halg.base.cra_name); 705 ss_algs[i].ss = NULL; 706 return err; 707 } 708 break; 709 default: 710 ss_algs[i].ss = NULL; 711 dev_err(ss->dev, "ERROR: tried to register an unknown algo\n"); 712 } 713 } 714 return 0; 715 } 716 717 static void sun8i_ss_unregister_algs(struct sun8i_ss_dev *ss) 718 { 719 unsigned int i; 720 721 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 722 if (!ss_algs[i].ss) 723 continue; 724 switch (ss_algs[i].type) { 725 case CRYPTO_ALG_TYPE_SKCIPHER: 726 dev_info(ss->dev, "Unregister %d %s\n", i, 727 ss_algs[i].alg.skcipher.base.cra_name); 728 crypto_unregister_skcipher(&ss_algs[i].alg.skcipher); 729 break; 730 case CRYPTO_ALG_TYPE_RNG: 731 dev_info(ss->dev, "Unregister %d %s\n", i, 732 ss_algs[i].alg.rng.base.cra_name); 733 crypto_unregister_rng(&ss_algs[i].alg.rng); 734 break; 735 case CRYPTO_ALG_TYPE_AHASH: 736 dev_info(ss->dev, "Unregister %d %s\n", i, 737 ss_algs[i].alg.hash.halg.base.cra_name); 738 crypto_unregister_ahash(&ss_algs[i].alg.hash); 739 break; 740 } 741 } 742 } 743 744 static int sun8i_ss_get_clks(struct sun8i_ss_dev *ss) 745 { 746 unsigned long cr; 747 int err, i; 748 749 for (i = 0; i < SS_MAX_CLOCKS; i++) { 750 if (!ss->variant->ss_clks[i].name) 751 continue; 752 ss->ssclks[i] = devm_clk_get(ss->dev, ss->variant->ss_clks[i].name); 753 if (IS_ERR(ss->ssclks[i])) { 754 err = PTR_ERR(ss->ssclks[i]); 755 dev_err(ss->dev, "Cannot get %s SS clock err=%d\n", 756 ss->variant->ss_clks[i].name, err); 757 return err; 758 } 759 cr = clk_get_rate(ss->ssclks[i]); 760 if (!cr) 761 return -EINVAL; 762 if (ss->variant->ss_clks[i].freq > 0 && 763 cr != ss->variant->ss_clks[i].freq) { 764 dev_info(ss->dev, "Set %s clock to %lu (%lu Mhz) from %lu (%lu Mhz)\n", 765 ss->variant->ss_clks[i].name, 766 ss->variant->ss_clks[i].freq, 767 ss->variant->ss_clks[i].freq / 1000000, 768 cr, cr / 1000000); 769 err = clk_set_rate(ss->ssclks[i], ss->variant->ss_clks[i].freq); 770 if (err) 771 dev_err(ss->dev, "Fail to set %s clk speed to %lu hz\n", 772 ss->variant->ss_clks[i].name, 773 ss->variant->ss_clks[i].freq); 774 } 775 if (ss->variant->ss_clks[i].max_freq > 0 && 776 cr > ss->variant->ss_clks[i].max_freq) 777 dev_warn(ss->dev, "Frequency for %s (%lu hz) is higher than datasheet's recommendation (%lu hz)", 778 ss->variant->ss_clks[i].name, cr, 779 ss->variant->ss_clks[i].max_freq); 780 } 781 return 0; 782 } 783 784 static int sun8i_ss_probe(struct platform_device *pdev) 785 { 786 struct sun8i_ss_dev *ss; 787 int err, irq; 788 u32 v; 789 790 ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL); 791 if (!ss) 792 return -ENOMEM; 793 794 ss->dev = &pdev->dev; 795 platform_set_drvdata(pdev, ss); 796 797 ss->variant = of_device_get_match_data(&pdev->dev); 798 if (!ss->variant) { 799 dev_err(&pdev->dev, "Missing Crypto Engine variant\n"); 800 return -EINVAL; 801 } 802 803 ss->base = devm_platform_ioremap_resource(pdev, 0); 804 if (IS_ERR(ss->base)) 805 return PTR_ERR(ss->base); 806 807 err = sun8i_ss_get_clks(ss); 808 if (err) 809 return err; 810 811 irq = platform_get_irq(pdev, 0); 812 if (irq < 0) 813 return irq; 814 815 ss->reset = devm_reset_control_get(&pdev->dev, NULL); 816 if (IS_ERR(ss->reset)) 817 return dev_err_probe(&pdev->dev, PTR_ERR(ss->reset), 818 "No reset control found\n"); 819 820 mutex_init(&ss->mlock); 821 822 err = allocate_flows(ss); 823 if (err) 824 return err; 825 826 err = sun8i_ss_pm_init(ss); 827 if (err) 828 goto error_pm; 829 830 err = devm_request_irq(&pdev->dev, irq, ss_irq_handler, 0, "sun8i-ss", ss); 831 if (err) { 832 dev_err(ss->dev, "Cannot request SecuritySystem IRQ (err=%d)\n", err); 833 goto error_irq; 834 } 835 836 err = sun8i_ss_register_algs(ss); 837 if (err) 838 goto error_alg; 839 840 err = pm_runtime_resume_and_get(ss->dev); 841 if (err < 0) 842 goto error_alg; 843 844 v = readl(ss->base + SS_CTL_REG); 845 v >>= SS_DIE_ID_SHIFT; 846 v &= SS_DIE_ID_MASK; 847 dev_info(&pdev->dev, "Security System Die ID %x\n", v); 848 849 pm_runtime_put_sync(ss->dev); 850 851 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG 852 /* Ignore error of debugfs */ 853 ss->dbgfs_dir = debugfs_create_dir("sun8i-ss", NULL); 854 ss->dbgfs_stats = debugfs_create_file("stats", 0444, 855 ss->dbgfs_dir, ss, 856 &sun8i_ss_debugfs_fops); 857 #endif 858 859 return 0; 860 error_alg: 861 sun8i_ss_unregister_algs(ss); 862 error_irq: 863 sun8i_ss_pm_exit(ss); 864 error_pm: 865 sun8i_ss_free_flows(ss, MAXFLOW - 1); 866 return err; 867 } 868 869 static int sun8i_ss_remove(struct platform_device *pdev) 870 { 871 struct sun8i_ss_dev *ss = platform_get_drvdata(pdev); 872 873 sun8i_ss_unregister_algs(ss); 874 875 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG 876 debugfs_remove_recursive(ss->dbgfs_dir); 877 #endif 878 879 sun8i_ss_free_flows(ss, MAXFLOW - 1); 880 881 sun8i_ss_pm_exit(ss); 882 883 return 0; 884 } 885 886 static const struct of_device_id sun8i_ss_crypto_of_match_table[] = { 887 { .compatible = "allwinner,sun8i-a83t-crypto", 888 .data = &ss_a83t_variant }, 889 { .compatible = "allwinner,sun9i-a80-crypto", 890 .data = &ss_a80_variant }, 891 {} 892 }; 893 MODULE_DEVICE_TABLE(of, sun8i_ss_crypto_of_match_table); 894 895 static struct platform_driver sun8i_ss_driver = { 896 .probe = sun8i_ss_probe, 897 .remove = sun8i_ss_remove, 898 .driver = { 899 .name = "sun8i-ss", 900 .pm = &sun8i_ss_pm_ops, 901 .of_match_table = sun8i_ss_crypto_of_match_table, 902 }, 903 }; 904 905 module_platform_driver(sun8i_ss_driver); 906 907 MODULE_DESCRIPTION("Allwinner SecuritySystem cryptographic offloader"); 908 MODULE_LICENSE("GPL"); 909 MODULE_AUTHOR("Corentin Labbe <clabbe.montjoie@gmail.com>"); 910