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/arch/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_debugfs_show(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 DEFINE_SHOW_ATTRIBUTE(sun4i_ss_debugfs); 270 271 /* 272 * Power management strategy: The device is suspended unless a TFM exists for 273 * one of the algorithms proposed by this driver. 274 */ 275 static int sun4i_ss_pm_suspend(struct device *dev) 276 { 277 struct sun4i_ss_ctx *ss = dev_get_drvdata(dev); 278 279 reset_control_assert(ss->reset); 280 281 clk_disable_unprepare(ss->ssclk); 282 clk_disable_unprepare(ss->busclk); 283 return 0; 284 } 285 286 static int sun4i_ss_pm_resume(struct device *dev) 287 { 288 struct sun4i_ss_ctx *ss = dev_get_drvdata(dev); 289 290 int err; 291 292 err = clk_prepare_enable(ss->busclk); 293 if (err) { 294 dev_err(ss->dev, "Cannot prepare_enable busclk\n"); 295 goto err_enable; 296 } 297 298 err = clk_prepare_enable(ss->ssclk); 299 if (err) { 300 dev_err(ss->dev, "Cannot prepare_enable ssclk\n"); 301 goto err_enable; 302 } 303 304 err = reset_control_deassert(ss->reset); 305 if (err) { 306 dev_err(ss->dev, "Cannot deassert reset control\n"); 307 goto err_enable; 308 } 309 310 return err; 311 err_enable: 312 sun4i_ss_pm_suspend(dev); 313 return err; 314 } 315 316 static const struct dev_pm_ops sun4i_ss_pm_ops = { 317 SET_RUNTIME_PM_OPS(sun4i_ss_pm_suspend, sun4i_ss_pm_resume, NULL) 318 }; 319 320 /* 321 * When power management is enabled, this function enables the PM and set the 322 * device as suspended 323 * When power management is disabled, this function just enables the device 324 */ 325 static int sun4i_ss_pm_init(struct sun4i_ss_ctx *ss) 326 { 327 int err; 328 329 pm_runtime_use_autosuspend(ss->dev); 330 pm_runtime_set_autosuspend_delay(ss->dev, 2000); 331 332 err = pm_runtime_set_suspended(ss->dev); 333 if (err) 334 return err; 335 pm_runtime_enable(ss->dev); 336 return err; 337 } 338 339 static void sun4i_ss_pm_exit(struct sun4i_ss_ctx *ss) 340 { 341 pm_runtime_disable(ss->dev); 342 } 343 344 static int sun4i_ss_probe(struct platform_device *pdev) 345 { 346 u32 v; 347 int err, i; 348 unsigned long cr; 349 const unsigned long cr_ahb = 24 * 1000 * 1000; 350 const unsigned long cr_mod = 150 * 1000 * 1000; 351 struct sun4i_ss_ctx *ss; 352 353 if (!pdev->dev.of_node) 354 return -ENODEV; 355 356 ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL); 357 if (!ss) 358 return -ENOMEM; 359 360 ss->base = devm_platform_ioremap_resource(pdev, 0); 361 if (IS_ERR(ss->base)) { 362 dev_err(&pdev->dev, "Cannot request MMIO\n"); 363 return PTR_ERR(ss->base); 364 } 365 366 ss->variant = of_device_get_match_data(&pdev->dev); 367 if (!ss->variant) { 368 dev_err(&pdev->dev, "Missing Security System variant\n"); 369 return -EINVAL; 370 } 371 372 ss->ssclk = devm_clk_get(&pdev->dev, "mod"); 373 if (IS_ERR(ss->ssclk)) { 374 err = PTR_ERR(ss->ssclk); 375 dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err); 376 return err; 377 } 378 dev_dbg(&pdev->dev, "clock ss acquired\n"); 379 380 ss->busclk = devm_clk_get(&pdev->dev, "ahb"); 381 if (IS_ERR(ss->busclk)) { 382 err = PTR_ERR(ss->busclk); 383 dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err); 384 return err; 385 } 386 dev_dbg(&pdev->dev, "clock ahb_ss acquired\n"); 387 388 ss->reset = devm_reset_control_get_optional(&pdev->dev, "ahb"); 389 if (IS_ERR(ss->reset)) 390 return PTR_ERR(ss->reset); 391 if (!ss->reset) 392 dev_info(&pdev->dev, "no reset control found\n"); 393 394 /* 395 * Check that clock have the correct rates given in the datasheet 396 * Try to set the clock to the maximum allowed 397 */ 398 err = clk_set_rate(ss->ssclk, cr_mod); 399 if (err) { 400 dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n"); 401 return err; 402 } 403 404 /* 405 * The only impact on clocks below requirement are bad performance, 406 * so do not print "errors" 407 * warn on Overclocked clocks 408 */ 409 cr = clk_get_rate(ss->busclk); 410 if (cr >= cr_ahb) 411 dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n", 412 cr, cr / 1000000, cr_ahb); 413 else 414 dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n", 415 cr, cr / 1000000, cr_ahb); 416 417 cr = clk_get_rate(ss->ssclk); 418 if (cr <= cr_mod) 419 if (cr < cr_mod) 420 dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n", 421 cr, cr / 1000000, cr_mod); 422 else 423 dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n", 424 cr, cr / 1000000, cr_mod); 425 else 426 dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n", 427 cr, cr / 1000000, cr_mod); 428 429 ss->dev = &pdev->dev; 430 platform_set_drvdata(pdev, ss); 431 432 spin_lock_init(&ss->slock); 433 434 err = sun4i_ss_pm_init(ss); 435 if (err) 436 return err; 437 438 /* 439 * Datasheet named it "Die Bonding ID" 440 * I expect to be a sort of Security System Revision number. 441 * Since the A80 seems to have an other version of SS 442 * this info could be useful 443 */ 444 445 err = pm_runtime_resume_and_get(ss->dev); 446 if (err < 0) 447 goto error_pm; 448 449 writel(SS_ENABLED, ss->base + SS_CTL); 450 v = readl(ss->base + SS_CTL); 451 v >>= 16; 452 v &= 0x07; 453 dev_info(&pdev->dev, "Die ID %d\n", v); 454 writel(0, ss->base + SS_CTL); 455 456 pm_runtime_put_sync(ss->dev); 457 458 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 459 ss_algs[i].ss = ss; 460 switch (ss_algs[i].type) { 461 case CRYPTO_ALG_TYPE_SKCIPHER: 462 err = crypto_register_skcipher(&ss_algs[i].alg.crypto); 463 if (err) { 464 dev_err(ss->dev, "Fail to register %s\n", 465 ss_algs[i].alg.crypto.base.cra_name); 466 goto error_alg; 467 } 468 break; 469 case CRYPTO_ALG_TYPE_AHASH: 470 err = crypto_register_ahash(&ss_algs[i].alg.hash); 471 if (err) { 472 dev_err(ss->dev, "Fail to register %s\n", 473 ss_algs[i].alg.hash.halg.base.cra_name); 474 goto error_alg; 475 } 476 break; 477 case CRYPTO_ALG_TYPE_RNG: 478 err = crypto_register_rng(&ss_algs[i].alg.rng); 479 if (err) { 480 dev_err(ss->dev, "Fail to register %s\n", 481 ss_algs[i].alg.rng.base.cra_name); 482 } 483 break; 484 } 485 } 486 487 /* Ignore error of debugfs */ 488 ss->dbgfs_dir = debugfs_create_dir("sun4i-ss", NULL); 489 ss->dbgfs_stats = debugfs_create_file("stats", 0444, ss->dbgfs_dir, ss, 490 &sun4i_ss_debugfs_fops); 491 492 return 0; 493 error_alg: 494 i--; 495 for (; i >= 0; i--) { 496 switch (ss_algs[i].type) { 497 case CRYPTO_ALG_TYPE_SKCIPHER: 498 crypto_unregister_skcipher(&ss_algs[i].alg.crypto); 499 break; 500 case CRYPTO_ALG_TYPE_AHASH: 501 crypto_unregister_ahash(&ss_algs[i].alg.hash); 502 break; 503 case CRYPTO_ALG_TYPE_RNG: 504 crypto_unregister_rng(&ss_algs[i].alg.rng); 505 break; 506 } 507 } 508 error_pm: 509 sun4i_ss_pm_exit(ss); 510 return err; 511 } 512 513 static int sun4i_ss_remove(struct platform_device *pdev) 514 { 515 int i; 516 struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev); 517 518 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) { 519 switch (ss_algs[i].type) { 520 case CRYPTO_ALG_TYPE_SKCIPHER: 521 crypto_unregister_skcipher(&ss_algs[i].alg.crypto); 522 break; 523 case CRYPTO_ALG_TYPE_AHASH: 524 crypto_unregister_ahash(&ss_algs[i].alg.hash); 525 break; 526 case CRYPTO_ALG_TYPE_RNG: 527 crypto_unregister_rng(&ss_algs[i].alg.rng); 528 break; 529 } 530 } 531 532 sun4i_ss_pm_exit(ss); 533 return 0; 534 } 535 536 static const struct of_device_id a20ss_crypto_of_match_table[] = { 537 { .compatible = "allwinner,sun4i-a10-crypto", 538 .data = &ss_a10_variant 539 }, 540 { .compatible = "allwinner,sun8i-a33-crypto", 541 .data = &ss_a33_variant 542 }, 543 {} 544 }; 545 MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table); 546 547 static struct platform_driver sun4i_ss_driver = { 548 .probe = sun4i_ss_probe, 549 .remove = sun4i_ss_remove, 550 .driver = { 551 .name = "sun4i-ss", 552 .pm = &sun4i_ss_pm_ops, 553 .of_match_table = a20ss_crypto_of_match_table, 554 }, 555 }; 556 557 module_platform_driver(sun4i_ss_driver); 558 559 MODULE_ALIAS("platform:sun4i-ss"); 560 MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator"); 561 MODULE_LICENSE("GPL"); 562 MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>"); 563