sun8i-ss-core.c (23923B)
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 30static 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 43static 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 */ 60int sun8i_ss_get_engine_number(struct sun8i_ss_dev *ss) 61{ 62 return atomic_inc_return(&ss->flow) % MAXFLOW; 63} 64 65int 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 147static 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 165static 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 447static 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 503DEFINE_SHOW_ATTRIBUTE(sun8i_ss_debugfs); 504#endif 505 506static 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 */ 517static 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 goto error_engine; 533 534 for (j = 0; j < MAX_SG; j++) { 535 ss->flows[i].iv[j] = devm_kmalloc(ss->dev, AES_BLOCK_SIZE, 536 GFP_KERNEL | GFP_DMA); 537 if (!ss->flows[i].iv[j]) 538 goto error_engine; 539 } 540 541 /* the padding could be up to two block. */ 542 ss->flows[i].pad = devm_kmalloc(ss->dev, MAX_PAD_SIZE, 543 GFP_KERNEL | GFP_DMA); 544 if (!ss->flows[i].pad) 545 goto error_engine; 546 ss->flows[i].result = devm_kmalloc(ss->dev, SHA256_DIGEST_SIZE, 547 GFP_KERNEL | GFP_DMA); 548 if (!ss->flows[i].result) 549 goto error_engine; 550 551 ss->flows[i].engine = crypto_engine_alloc_init(ss->dev, true); 552 if (!ss->flows[i].engine) { 553 dev_err(ss->dev, "Cannot allocate engine\n"); 554 i--; 555 err = -ENOMEM; 556 goto error_engine; 557 } 558 err = crypto_engine_start(ss->flows[i].engine); 559 if (err) { 560 dev_err(ss->dev, "Cannot start engine\n"); 561 goto error_engine; 562 } 563 } 564 return 0; 565error_engine: 566 sun8i_ss_free_flows(ss, i); 567 return err; 568} 569 570/* 571 * Power management strategy: The device is suspended unless a TFM exists for 572 * one of the algorithms proposed by this driver. 573 */ 574static int sun8i_ss_pm_suspend(struct device *dev) 575{ 576 struct sun8i_ss_dev *ss = dev_get_drvdata(dev); 577 int i; 578 579 reset_control_assert(ss->reset); 580 for (i = 0; i < SS_MAX_CLOCKS; i++) 581 clk_disable_unprepare(ss->ssclks[i]); 582 return 0; 583} 584 585static int sun8i_ss_pm_resume(struct device *dev) 586{ 587 struct sun8i_ss_dev *ss = dev_get_drvdata(dev); 588 int err, i; 589 590 for (i = 0; i < SS_MAX_CLOCKS; i++) { 591 if (!ss->variant->ss_clks[i].name) 592 continue; 593 err = clk_prepare_enable(ss->ssclks[i]); 594 if (err) { 595 dev_err(ss->dev, "Cannot prepare_enable %s\n", 596 ss->variant->ss_clks[i].name); 597 goto error; 598 } 599 } 600 err = reset_control_deassert(ss->reset); 601 if (err) { 602 dev_err(ss->dev, "Cannot deassert reset control\n"); 603 goto error; 604 } 605 /* enable interrupts for all flows */ 606 writel(BIT(0) | BIT(1), ss->base + SS_INT_CTL_REG); 607 608 return 0; 609error: 610 sun8i_ss_pm_suspend(dev); 611 return err; 612} 613 614static const struct dev_pm_ops sun8i_ss_pm_ops = { 615 SET_RUNTIME_PM_OPS(sun8i_ss_pm_suspend, sun8i_ss_pm_resume, NULL) 616}; 617 618static int sun8i_ss_pm_init(struct sun8i_ss_dev *ss) 619{ 620 int err; 621 622 pm_runtime_use_autosuspend(ss->dev); 623 pm_runtime_set_autosuspend_delay(ss->dev, 2000); 624 625 err = pm_runtime_set_suspended(ss->dev); 626 if (err) 627 return err; 628 pm_runtime_enable(ss->dev); 629 return err; 630} 631 632static void sun8i_ss_pm_exit(struct sun8i_ss_dev *ss) 633{ 634 pm_runtime_disable(ss->dev); 635} 636 637static int sun8i_ss_register_algs(struct sun8i_ss_dev *ss) 638{ 639 int ss_method, err, id; 640 unsigned int i; 641 642 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 643 ss_algs[i].ss = ss; 644 switch (ss_algs[i].type) { 645 case CRYPTO_ALG_TYPE_SKCIPHER: 646 id = ss_algs[i].ss_algo_id; 647 ss_method = ss->variant->alg_cipher[id]; 648 if (ss_method == SS_ID_NOTSUPP) { 649 dev_info(ss->dev, 650 "DEBUG: Algo of %s not supported\n", 651 ss_algs[i].alg.skcipher.base.cra_name); 652 ss_algs[i].ss = NULL; 653 break; 654 } 655 id = ss_algs[i].ss_blockmode; 656 ss_method = ss->variant->op_mode[id]; 657 if (ss_method == SS_ID_NOTSUPP) { 658 dev_info(ss->dev, "DEBUG: Blockmode of %s not supported\n", 659 ss_algs[i].alg.skcipher.base.cra_name); 660 ss_algs[i].ss = NULL; 661 break; 662 } 663 dev_info(ss->dev, "DEBUG: Register %s\n", 664 ss_algs[i].alg.skcipher.base.cra_name); 665 err = crypto_register_skcipher(&ss_algs[i].alg.skcipher); 666 if (err) { 667 dev_err(ss->dev, "Fail to register %s\n", 668 ss_algs[i].alg.skcipher.base.cra_name); 669 ss_algs[i].ss = NULL; 670 return err; 671 } 672 break; 673 case CRYPTO_ALG_TYPE_RNG: 674 err = crypto_register_rng(&ss_algs[i].alg.rng); 675 if (err) { 676 dev_err(ss->dev, "Fail to register %s\n", 677 ss_algs[i].alg.rng.base.cra_name); 678 ss_algs[i].ss = NULL; 679 } 680 break; 681 case CRYPTO_ALG_TYPE_AHASH: 682 id = ss_algs[i].ss_algo_id; 683 ss_method = ss->variant->alg_hash[id]; 684 if (ss_method == SS_ID_NOTSUPP) { 685 dev_info(ss->dev, 686 "DEBUG: Algo of %s not supported\n", 687 ss_algs[i].alg.hash.halg.base.cra_name); 688 ss_algs[i].ss = NULL; 689 break; 690 } 691 dev_info(ss->dev, "Register %s\n", 692 ss_algs[i].alg.hash.halg.base.cra_name); 693 err = crypto_register_ahash(&ss_algs[i].alg.hash); 694 if (err) { 695 dev_err(ss->dev, "ERROR: Fail to register %s\n", 696 ss_algs[i].alg.hash.halg.base.cra_name); 697 ss_algs[i].ss = NULL; 698 return err; 699 } 700 break; 701 default: 702 ss_algs[i].ss = NULL; 703 dev_err(ss->dev, "ERROR: tried to register an unknown algo\n"); 704 } 705 } 706 return 0; 707} 708 709static void sun8i_ss_unregister_algs(struct sun8i_ss_dev *ss) 710{ 711 unsigned int i; 712 713 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 714 if (!ss_algs[i].ss) 715 continue; 716 switch (ss_algs[i].type) { 717 case CRYPTO_ALG_TYPE_SKCIPHER: 718 dev_info(ss->dev, "Unregister %d %s\n", i, 719 ss_algs[i].alg.skcipher.base.cra_name); 720 crypto_unregister_skcipher(&ss_algs[i].alg.skcipher); 721 break; 722 case CRYPTO_ALG_TYPE_RNG: 723 dev_info(ss->dev, "Unregister %d %s\n", i, 724 ss_algs[i].alg.rng.base.cra_name); 725 crypto_unregister_rng(&ss_algs[i].alg.rng); 726 break; 727 case CRYPTO_ALG_TYPE_AHASH: 728 dev_info(ss->dev, "Unregister %d %s\n", i, 729 ss_algs[i].alg.hash.halg.base.cra_name); 730 crypto_unregister_ahash(&ss_algs[i].alg.hash); 731 break; 732 } 733 } 734} 735 736static int sun8i_ss_get_clks(struct sun8i_ss_dev *ss) 737{ 738 unsigned long cr; 739 int err, i; 740 741 for (i = 0; i < SS_MAX_CLOCKS; i++) { 742 if (!ss->variant->ss_clks[i].name) 743 continue; 744 ss->ssclks[i] = devm_clk_get(ss->dev, ss->variant->ss_clks[i].name); 745 if (IS_ERR(ss->ssclks[i])) { 746 err = PTR_ERR(ss->ssclks[i]); 747 dev_err(ss->dev, "Cannot get %s SS clock err=%d\n", 748 ss->variant->ss_clks[i].name, err); 749 return err; 750 } 751 cr = clk_get_rate(ss->ssclks[i]); 752 if (!cr) 753 return -EINVAL; 754 if (ss->variant->ss_clks[i].freq > 0 && 755 cr != ss->variant->ss_clks[i].freq) { 756 dev_info(ss->dev, "Set %s clock to %lu (%lu Mhz) from %lu (%lu Mhz)\n", 757 ss->variant->ss_clks[i].name, 758 ss->variant->ss_clks[i].freq, 759 ss->variant->ss_clks[i].freq / 1000000, 760 cr, cr / 1000000); 761 err = clk_set_rate(ss->ssclks[i], ss->variant->ss_clks[i].freq); 762 if (err) 763 dev_err(ss->dev, "Fail to set %s clk speed to %lu hz\n", 764 ss->variant->ss_clks[i].name, 765 ss->variant->ss_clks[i].freq); 766 } 767 if (ss->variant->ss_clks[i].max_freq > 0 && 768 cr > ss->variant->ss_clks[i].max_freq) 769 dev_warn(ss->dev, "Frequency for %s (%lu hz) is higher than datasheet's recommendation (%lu hz)", 770 ss->variant->ss_clks[i].name, cr, 771 ss->variant->ss_clks[i].max_freq); 772 } 773 return 0; 774} 775 776static int sun8i_ss_probe(struct platform_device *pdev) 777{ 778 struct sun8i_ss_dev *ss; 779 int err, irq; 780 u32 v; 781 782 ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL); 783 if (!ss) 784 return -ENOMEM; 785 786 ss->dev = &pdev->dev; 787 platform_set_drvdata(pdev, ss); 788 789 ss->variant = of_device_get_match_data(&pdev->dev); 790 if (!ss->variant) { 791 dev_err(&pdev->dev, "Missing Crypto Engine variant\n"); 792 return -EINVAL; 793 } 794 795 ss->base = devm_platform_ioremap_resource(pdev, 0); 796 if (IS_ERR(ss->base)) 797 return PTR_ERR(ss->base); 798 799 err = sun8i_ss_get_clks(ss); 800 if (err) 801 return err; 802 803 irq = platform_get_irq(pdev, 0); 804 if (irq < 0) 805 return irq; 806 807 ss->reset = devm_reset_control_get(&pdev->dev, NULL); 808 if (IS_ERR(ss->reset)) 809 return dev_err_probe(&pdev->dev, PTR_ERR(ss->reset), 810 "No reset control found\n"); 811 812 mutex_init(&ss->mlock); 813 814 err = allocate_flows(ss); 815 if (err) 816 return err; 817 818 err = sun8i_ss_pm_init(ss); 819 if (err) 820 goto error_pm; 821 822 err = devm_request_irq(&pdev->dev, irq, ss_irq_handler, 0, "sun8i-ss", ss); 823 if (err) { 824 dev_err(ss->dev, "Cannot request SecuritySystem IRQ (err=%d)\n", err); 825 goto error_irq; 826 } 827 828 err = sun8i_ss_register_algs(ss); 829 if (err) 830 goto error_alg; 831 832 err = pm_runtime_resume_and_get(ss->dev); 833 if (err < 0) 834 goto error_alg; 835 836 v = readl(ss->base + SS_CTL_REG); 837 v >>= SS_DIE_ID_SHIFT; 838 v &= SS_DIE_ID_MASK; 839 dev_info(&pdev->dev, "Security System Die ID %x\n", v); 840 841 pm_runtime_put_sync(ss->dev); 842 843#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG 844 /* Ignore error of debugfs */ 845 ss->dbgfs_dir = debugfs_create_dir("sun8i-ss", NULL); 846 ss->dbgfs_stats = debugfs_create_file("stats", 0444, 847 ss->dbgfs_dir, ss, 848 &sun8i_ss_debugfs_fops); 849#endif 850 851 return 0; 852error_alg: 853 sun8i_ss_unregister_algs(ss); 854error_irq: 855 sun8i_ss_pm_exit(ss); 856error_pm: 857 sun8i_ss_free_flows(ss, MAXFLOW - 1); 858 return err; 859} 860 861static int sun8i_ss_remove(struct platform_device *pdev) 862{ 863 struct sun8i_ss_dev *ss = platform_get_drvdata(pdev); 864 865 sun8i_ss_unregister_algs(ss); 866 867#ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG 868 debugfs_remove_recursive(ss->dbgfs_dir); 869#endif 870 871 sun8i_ss_free_flows(ss, MAXFLOW - 1); 872 873 sun8i_ss_pm_exit(ss); 874 875 return 0; 876} 877 878static const struct of_device_id sun8i_ss_crypto_of_match_table[] = { 879 { .compatible = "allwinner,sun8i-a83t-crypto", 880 .data = &ss_a83t_variant }, 881 { .compatible = "allwinner,sun9i-a80-crypto", 882 .data = &ss_a80_variant }, 883 {} 884}; 885MODULE_DEVICE_TABLE(of, sun8i_ss_crypto_of_match_table); 886 887static struct platform_driver sun8i_ss_driver = { 888 .probe = sun8i_ss_probe, 889 .remove = sun8i_ss_remove, 890 .driver = { 891 .name = "sun8i-ss", 892 .pm = &sun8i_ss_pm_ops, 893 .of_match_table = sun8i_ss_crypto_of_match_table, 894 }, 895}; 896 897module_platform_driver(sun8i_ss_driver); 898 899MODULE_DESCRIPTION("Allwinner SecuritySystem cryptographic offloader"); 900MODULE_LICENSE("GPL"); 901MODULE_AUTHOR("Corentin Labbe <clabbe.montjoie@gmail.com>");