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