1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * sun4i-ss-core.c - hardware cryptographic accelerator for Allwinner A20 SoC 4 * 5 * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com> 6 * 7 * Core file which registers crypto algorithms supported by the SS. 8 * 9 * You could find a link for the datasheet in Documentation/arm/sunxi.rst 10 */ 11 #include <linux/clk.h> 12 #include <linux/crypto.h> 13 #include <linux/debugfs.h> 14 #include <linux/io.h> 15 #include <linux/module.h> 16 #include <linux/of.h> 17 #include <linux/of_device.h> 18 #include <linux/platform_device.h> 19 #include <crypto/scatterwalk.h> 20 #include <linux/scatterlist.h> 21 #include <linux/interrupt.h> 22 #include <linux/delay.h> 23 #include <linux/reset.h> 24 25 #include "sun4i-ss.h" 26 27 static const struct ss_variant ss_a10_variant = { 28 .sha1_in_be = false, 29 }; 30 31 static const struct ss_variant ss_a33_variant = { 32 .sha1_in_be = true, 33 }; 34 35 static struct sun4i_ss_alg_template ss_algs[] = { 36 { .type = CRYPTO_ALG_TYPE_AHASH, 37 .mode = SS_OP_MD5, 38 .alg.hash = { 39 .init = sun4i_hash_init, 40 .update = sun4i_hash_update, 41 .final = sun4i_hash_final, 42 .finup = sun4i_hash_finup, 43 .digest = sun4i_hash_digest, 44 .export = sun4i_hash_export_md5, 45 .import = sun4i_hash_import_md5, 46 .halg = { 47 .digestsize = MD5_DIGEST_SIZE, 48 .statesize = sizeof(struct md5_state), 49 .base = { 50 .cra_name = "md5", 51 .cra_driver_name = "md5-sun4i-ss", 52 .cra_priority = 300, 53 .cra_alignmask = 3, 54 .cra_blocksize = MD5_HMAC_BLOCK_SIZE, 55 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 56 .cra_module = THIS_MODULE, 57 .cra_init = sun4i_hash_crainit, 58 .cra_exit = sun4i_hash_craexit, 59 } 60 } 61 } 62 }, 63 { .type = CRYPTO_ALG_TYPE_AHASH, 64 .mode = SS_OP_SHA1, 65 .alg.hash = { 66 .init = sun4i_hash_init, 67 .update = sun4i_hash_update, 68 .final = sun4i_hash_final, 69 .finup = sun4i_hash_finup, 70 .digest = sun4i_hash_digest, 71 .export = sun4i_hash_export_sha1, 72 .import = sun4i_hash_import_sha1, 73 .halg = { 74 .digestsize = SHA1_DIGEST_SIZE, 75 .statesize = sizeof(struct sha1_state), 76 .base = { 77 .cra_name = "sha1", 78 .cra_driver_name = "sha1-sun4i-ss", 79 .cra_priority = 300, 80 .cra_alignmask = 3, 81 .cra_blocksize = SHA1_BLOCK_SIZE, 82 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 83 .cra_module = THIS_MODULE, 84 .cra_init = sun4i_hash_crainit, 85 .cra_exit = sun4i_hash_craexit, 86 } 87 } 88 } 89 }, 90 { .type = CRYPTO_ALG_TYPE_SKCIPHER, 91 .alg.crypto = { 92 .setkey = sun4i_ss_aes_setkey, 93 .encrypt = sun4i_ss_cbc_aes_encrypt, 94 .decrypt = sun4i_ss_cbc_aes_decrypt, 95 .min_keysize = AES_MIN_KEY_SIZE, 96 .max_keysize = AES_MAX_KEY_SIZE, 97 .ivsize = AES_BLOCK_SIZE, 98 .base = { 99 .cra_name = "cbc(aes)", 100 .cra_driver_name = "cbc-aes-sun4i-ss", 101 .cra_priority = 300, 102 .cra_blocksize = AES_BLOCK_SIZE, 103 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, 104 .cra_ctxsize = sizeof(struct sun4i_tfm_ctx), 105 .cra_module = THIS_MODULE, 106 .cra_alignmask = 3, 107 .cra_init = sun4i_ss_cipher_init, 108 .cra_exit = sun4i_ss_cipher_exit, 109 } 110 } 111 }, 112 { .type = CRYPTO_ALG_TYPE_SKCIPHER, 113 .alg.crypto = { 114 .setkey = sun4i_ss_aes_setkey, 115 .encrypt = sun4i_ss_ecb_aes_encrypt, 116 .decrypt = sun4i_ss_ecb_aes_decrypt, 117 .min_keysize = AES_MIN_KEY_SIZE, 118 .max_keysize = AES_MAX_KEY_SIZE, 119 .base = { 120 .cra_name = "ecb(aes)", 121 .cra_driver_name = "ecb-aes-sun4i-ss", 122 .cra_priority = 300, 123 .cra_blocksize = AES_BLOCK_SIZE, 124 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, 125 .cra_ctxsize = sizeof(struct sun4i_tfm_ctx), 126 .cra_module = THIS_MODULE, 127 .cra_alignmask = 3, 128 .cra_init = sun4i_ss_cipher_init, 129 .cra_exit = sun4i_ss_cipher_exit, 130 } 131 } 132 }, 133 { .type = CRYPTO_ALG_TYPE_SKCIPHER, 134 .alg.crypto = { 135 .setkey = sun4i_ss_des_setkey, 136 .encrypt = sun4i_ss_cbc_des_encrypt, 137 .decrypt = sun4i_ss_cbc_des_decrypt, 138 .min_keysize = DES_KEY_SIZE, 139 .max_keysize = DES_KEY_SIZE, 140 .ivsize = DES_BLOCK_SIZE, 141 .base = { 142 .cra_name = "cbc(des)", 143 .cra_driver_name = "cbc-des-sun4i-ss", 144 .cra_priority = 300, 145 .cra_blocksize = DES_BLOCK_SIZE, 146 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, 147 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 148 .cra_module = THIS_MODULE, 149 .cra_alignmask = 3, 150 .cra_init = sun4i_ss_cipher_init, 151 .cra_exit = sun4i_ss_cipher_exit, 152 } 153 } 154 }, 155 { .type = CRYPTO_ALG_TYPE_SKCIPHER, 156 .alg.crypto = { 157 .setkey = sun4i_ss_des_setkey, 158 .encrypt = sun4i_ss_ecb_des_encrypt, 159 .decrypt = sun4i_ss_ecb_des_decrypt, 160 .min_keysize = DES_KEY_SIZE, 161 .max_keysize = DES_KEY_SIZE, 162 .base = { 163 .cra_name = "ecb(des)", 164 .cra_driver_name = "ecb-des-sun4i-ss", 165 .cra_priority = 300, 166 .cra_blocksize = DES_BLOCK_SIZE, 167 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, 168 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 169 .cra_module = THIS_MODULE, 170 .cra_alignmask = 3, 171 .cra_init = sun4i_ss_cipher_init, 172 .cra_exit = sun4i_ss_cipher_exit, 173 } 174 } 175 }, 176 { .type = CRYPTO_ALG_TYPE_SKCIPHER, 177 .alg.crypto = { 178 .setkey = sun4i_ss_des3_setkey, 179 .encrypt = sun4i_ss_cbc_des3_encrypt, 180 .decrypt = sun4i_ss_cbc_des3_decrypt, 181 .min_keysize = DES3_EDE_KEY_SIZE, 182 .max_keysize = DES3_EDE_KEY_SIZE, 183 .ivsize = DES3_EDE_BLOCK_SIZE, 184 .base = { 185 .cra_name = "cbc(des3_ede)", 186 .cra_driver_name = "cbc-des3-sun4i-ss", 187 .cra_priority = 300, 188 .cra_blocksize = DES3_EDE_BLOCK_SIZE, 189 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, 190 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 191 .cra_module = THIS_MODULE, 192 .cra_alignmask = 3, 193 .cra_init = sun4i_ss_cipher_init, 194 .cra_exit = sun4i_ss_cipher_exit, 195 } 196 } 197 }, 198 { .type = CRYPTO_ALG_TYPE_SKCIPHER, 199 .alg.crypto = { 200 .setkey = sun4i_ss_des3_setkey, 201 .encrypt = sun4i_ss_ecb_des3_encrypt, 202 .decrypt = sun4i_ss_ecb_des3_decrypt, 203 .min_keysize = DES3_EDE_KEY_SIZE, 204 .max_keysize = DES3_EDE_KEY_SIZE, 205 .base = { 206 .cra_name = "ecb(des3_ede)", 207 .cra_driver_name = "ecb-des3-sun4i-ss", 208 .cra_priority = 300, 209 .cra_blocksize = DES3_EDE_BLOCK_SIZE, 210 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK, 211 .cra_ctxsize = sizeof(struct sun4i_req_ctx), 212 .cra_module = THIS_MODULE, 213 .cra_alignmask = 3, 214 .cra_init = sun4i_ss_cipher_init, 215 .cra_exit = sun4i_ss_cipher_exit, 216 } 217 } 218 }, 219 #ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG 220 { 221 .type = CRYPTO_ALG_TYPE_RNG, 222 .alg.rng = { 223 .base = { 224 .cra_name = "stdrng", 225 .cra_driver_name = "sun4i_ss_rng", 226 .cra_priority = 300, 227 .cra_ctxsize = 0, 228 .cra_module = THIS_MODULE, 229 }, 230 .generate = sun4i_ss_prng_generate, 231 .seed = sun4i_ss_prng_seed, 232 .seedsize = SS_SEED_LEN / BITS_PER_BYTE, 233 } 234 }, 235 #endif 236 }; 237 238 static int sun4i_ss_dbgfs_read(struct seq_file *seq, void *v) 239 { 240 unsigned int i; 241 242 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 243 if (!ss_algs[i].ss) 244 continue; 245 switch (ss_algs[i].type) { 246 case CRYPTO_ALG_TYPE_SKCIPHER: 247 seq_printf(seq, "%s %s reqs=%lu opti=%lu fallback=%lu tsize=%lu\n", 248 ss_algs[i].alg.crypto.base.cra_driver_name, 249 ss_algs[i].alg.crypto.base.cra_name, 250 ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb, 251 ss_algs[i].stat_bytes); 252 break; 253 case CRYPTO_ALG_TYPE_RNG: 254 seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n", 255 ss_algs[i].alg.rng.base.cra_driver_name, 256 ss_algs[i].alg.rng.base.cra_name, 257 ss_algs[i].stat_req, ss_algs[i].stat_bytes); 258 break; 259 case CRYPTO_ALG_TYPE_AHASH: 260 seq_printf(seq, "%s %s reqs=%lu\n", 261 ss_algs[i].alg.hash.halg.base.cra_driver_name, 262 ss_algs[i].alg.hash.halg.base.cra_name, 263 ss_algs[i].stat_req); 264 break; 265 } 266 } 267 return 0; 268 } 269 270 static int sun4i_ss_dbgfs_open(struct inode *inode, struct file *file) 271 { 272 return single_open(file, sun4i_ss_dbgfs_read, inode->i_private); 273 } 274 275 static const struct file_operations sun4i_ss_debugfs_fops = { 276 .owner = THIS_MODULE, 277 .open = sun4i_ss_dbgfs_open, 278 .read = seq_read, 279 .llseek = seq_lseek, 280 .release = single_release, 281 }; 282 283 /* 284 * Power management strategy: The device is suspended unless a TFM exists for 285 * one of the algorithms proposed by this driver. 286 */ 287 static int sun4i_ss_pm_suspend(struct device *dev) 288 { 289 struct sun4i_ss_ctx *ss = dev_get_drvdata(dev); 290 291 if (ss->reset) 292 reset_control_assert(ss->reset); 293 294 clk_disable_unprepare(ss->ssclk); 295 clk_disable_unprepare(ss->busclk); 296 return 0; 297 } 298 299 static int sun4i_ss_pm_resume(struct device *dev) 300 { 301 struct sun4i_ss_ctx *ss = dev_get_drvdata(dev); 302 303 int err; 304 305 err = clk_prepare_enable(ss->busclk); 306 if (err) { 307 dev_err(ss->dev, "Cannot prepare_enable busclk\n"); 308 goto err_enable; 309 } 310 311 err = clk_prepare_enable(ss->ssclk); 312 if (err) { 313 dev_err(ss->dev, "Cannot prepare_enable ssclk\n"); 314 goto err_enable; 315 } 316 317 if (ss->reset) { 318 err = reset_control_deassert(ss->reset); 319 if (err) { 320 dev_err(ss->dev, "Cannot deassert reset control\n"); 321 goto err_enable; 322 } 323 } 324 325 return err; 326 err_enable: 327 sun4i_ss_pm_suspend(dev); 328 return err; 329 } 330 331 static const struct dev_pm_ops sun4i_ss_pm_ops = { 332 SET_RUNTIME_PM_OPS(sun4i_ss_pm_suspend, sun4i_ss_pm_resume, NULL) 333 }; 334 335 /* 336 * When power management is enabled, this function enables the PM and set the 337 * device as suspended 338 * When power management is disabled, this function just enables the device 339 */ 340 static int sun4i_ss_pm_init(struct sun4i_ss_ctx *ss) 341 { 342 int err; 343 344 pm_runtime_use_autosuspend(ss->dev); 345 pm_runtime_set_autosuspend_delay(ss->dev, 2000); 346 347 err = pm_runtime_set_suspended(ss->dev); 348 if (err) 349 return err; 350 pm_runtime_enable(ss->dev); 351 return err; 352 } 353 354 static void sun4i_ss_pm_exit(struct sun4i_ss_ctx *ss) 355 { 356 pm_runtime_disable(ss->dev); 357 } 358 359 static int sun4i_ss_probe(struct platform_device *pdev) 360 { 361 u32 v; 362 int err, i; 363 unsigned long cr; 364 const unsigned long cr_ahb = 24 * 1000 * 1000; 365 const unsigned long cr_mod = 150 * 1000 * 1000; 366 struct sun4i_ss_ctx *ss; 367 368 if (!pdev->dev.of_node) 369 return -ENODEV; 370 371 ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL); 372 if (!ss) 373 return -ENOMEM; 374 375 ss->base = devm_platform_ioremap_resource(pdev, 0); 376 if (IS_ERR(ss->base)) { 377 dev_err(&pdev->dev, "Cannot request MMIO\n"); 378 return PTR_ERR(ss->base); 379 } 380 381 ss->variant = of_device_get_match_data(&pdev->dev); 382 if (!ss->variant) { 383 dev_err(&pdev->dev, "Missing Security System variant\n"); 384 return -EINVAL; 385 } 386 387 ss->ssclk = devm_clk_get(&pdev->dev, "mod"); 388 if (IS_ERR(ss->ssclk)) { 389 err = PTR_ERR(ss->ssclk); 390 dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err); 391 return err; 392 } 393 dev_dbg(&pdev->dev, "clock ss acquired\n"); 394 395 ss->busclk = devm_clk_get(&pdev->dev, "ahb"); 396 if (IS_ERR(ss->busclk)) { 397 err = PTR_ERR(ss->busclk); 398 dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err); 399 return err; 400 } 401 dev_dbg(&pdev->dev, "clock ahb_ss acquired\n"); 402 403 ss->reset = devm_reset_control_get_optional(&pdev->dev, "ahb"); 404 if (IS_ERR(ss->reset)) { 405 if (PTR_ERR(ss->reset) == -EPROBE_DEFER) 406 return PTR_ERR(ss->reset); 407 dev_info(&pdev->dev, "no reset control found\n"); 408 ss->reset = NULL; 409 } 410 411 /* 412 * Check that clock have the correct rates given in the datasheet 413 * Try to set the clock to the maximum allowed 414 */ 415 err = clk_set_rate(ss->ssclk, cr_mod); 416 if (err) { 417 dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n"); 418 return err; 419 } 420 421 /* 422 * The only impact on clocks below requirement are bad performance, 423 * so do not print "errors" 424 * warn on Overclocked clocks 425 */ 426 cr = clk_get_rate(ss->busclk); 427 if (cr >= cr_ahb) 428 dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n", 429 cr, cr / 1000000, cr_ahb); 430 else 431 dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n", 432 cr, cr / 1000000, cr_ahb); 433 434 cr = clk_get_rate(ss->ssclk); 435 if (cr <= cr_mod) 436 if (cr < cr_mod) 437 dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n", 438 cr, cr / 1000000, cr_mod); 439 else 440 dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n", 441 cr, cr / 1000000, cr_mod); 442 else 443 dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n", 444 cr, cr / 1000000, cr_mod); 445 446 ss->dev = &pdev->dev; 447 platform_set_drvdata(pdev, ss); 448 449 spin_lock_init(&ss->slock); 450 451 err = sun4i_ss_pm_init(ss); 452 if (err) 453 return err; 454 455 /* 456 * Datasheet named it "Die Bonding ID" 457 * I expect to be a sort of Security System Revision number. 458 * Since the A80 seems to have an other version of SS 459 * this info could be useful 460 */ 461 462 err = pm_runtime_get_sync(ss->dev); 463 if (err < 0) 464 goto error_pm; 465 466 writel(SS_ENABLED, ss->base + SS_CTL); 467 v = readl(ss->base + SS_CTL); 468 v >>= 16; 469 v &= 0x07; 470 dev_info(&pdev->dev, "Die ID %d\n", v); 471 writel(0, ss->base + SS_CTL); 472 473 pm_runtime_put_sync(ss->dev); 474 475 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 476 ss_algs[i].ss = ss; 477 switch (ss_algs[i].type) { 478 case CRYPTO_ALG_TYPE_SKCIPHER: 479 err = crypto_register_skcipher(&ss_algs[i].alg.crypto); 480 if (err) { 481 dev_err(ss->dev, "Fail to register %s\n", 482 ss_algs[i].alg.crypto.base.cra_name); 483 goto error_alg; 484 } 485 break; 486 case CRYPTO_ALG_TYPE_AHASH: 487 err = crypto_register_ahash(&ss_algs[i].alg.hash); 488 if (err) { 489 dev_err(ss->dev, "Fail to register %s\n", 490 ss_algs[i].alg.hash.halg.base.cra_name); 491 goto error_alg; 492 } 493 break; 494 case CRYPTO_ALG_TYPE_RNG: 495 err = crypto_register_rng(&ss_algs[i].alg.rng); 496 if (err) { 497 dev_err(ss->dev, "Fail to register %s\n", 498 ss_algs[i].alg.rng.base.cra_name); 499 } 500 break; 501 } 502 } 503 504 /* Ignore error of debugfs */ 505 ss->dbgfs_dir = debugfs_create_dir("sun4i-ss", NULL); 506 ss->dbgfs_stats = debugfs_create_file("stats", 0444, ss->dbgfs_dir, ss, 507 &sun4i_ss_debugfs_fops); 508 509 return 0; 510 error_alg: 511 i--; 512 for (; i >= 0; i--) { 513 switch (ss_algs[i].type) { 514 case CRYPTO_ALG_TYPE_SKCIPHER: 515 crypto_unregister_skcipher(&ss_algs[i].alg.crypto); 516 break; 517 case CRYPTO_ALG_TYPE_AHASH: 518 crypto_unregister_ahash(&ss_algs[i].alg.hash); 519 break; 520 case CRYPTO_ALG_TYPE_RNG: 521 crypto_unregister_rng(&ss_algs[i].alg.rng); 522 break; 523 } 524 } 525 error_pm: 526 sun4i_ss_pm_exit(ss); 527 return err; 528 } 529 530 static int sun4i_ss_remove(struct platform_device *pdev) 531 { 532 int i; 533 struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev); 534 535 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 536 switch (ss_algs[i].type) { 537 case CRYPTO_ALG_TYPE_SKCIPHER: 538 crypto_unregister_skcipher(&ss_algs[i].alg.crypto); 539 break; 540 case CRYPTO_ALG_TYPE_AHASH: 541 crypto_unregister_ahash(&ss_algs[i].alg.hash); 542 break; 543 case CRYPTO_ALG_TYPE_RNG: 544 crypto_unregister_rng(&ss_algs[i].alg.rng); 545 break; 546 } 547 } 548 549 sun4i_ss_pm_exit(ss); 550 return 0; 551 } 552 553 static const struct of_device_id a20ss_crypto_of_match_table[] = { 554 { .compatible = "allwinner,sun4i-a10-crypto", 555 .data = &ss_a10_variant 556 }, 557 { .compatible = "allwinner,sun8i-a33-crypto", 558 .data = &ss_a33_variant 559 }, 560 {} 561 }; 562 MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table); 563 564 static struct platform_driver sun4i_ss_driver = { 565 .probe = sun4i_ss_probe, 566 .remove = sun4i_ss_remove, 567 .driver = { 568 .name = "sun4i-ss", 569 .pm = &sun4i_ss_pm_ops, 570 .of_match_table = a20ss_crypto_of_match_table, 571 }, 572 }; 573 574 module_platform_driver(sun4i_ss_driver); 575 576 MODULE_ALIAS("platform:sun4i-ss"); 577 MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator"); 578 MODULE_LICENSE("GPL"); 579 MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>"); 580