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