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