0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/clk.h>
0012 #include <linux/crypto.h>
0013 #include <linux/debugfs.h>
0014 #include <linux/io.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/of_device.h>
0018 #include <linux/platform_device.h>
0019 #include <crypto/scatterwalk.h>
0020 #include <linux/scatterlist.h>
0021 #include <linux/interrupt.h>
0022 #include <linux/delay.h>
0023 #include <linux/reset.h>
0024
0025 #include "sun4i-ss.h"
0026
0027 static const struct ss_variant ss_a10_variant = {
0028 .sha1_in_be = false,
0029 };
0030
0031 static const struct ss_variant ss_a33_variant = {
0032 .sha1_in_be = true,
0033 };
0034
0035 static struct sun4i_ss_alg_template ss_algs[] = {
0036 { .type = CRYPTO_ALG_TYPE_AHASH,
0037 .mode = SS_OP_MD5,
0038 .alg.hash = {
0039 .init = sun4i_hash_init,
0040 .update = sun4i_hash_update,
0041 .final = sun4i_hash_final,
0042 .finup = sun4i_hash_finup,
0043 .digest = sun4i_hash_digest,
0044 .export = sun4i_hash_export_md5,
0045 .import = sun4i_hash_import_md5,
0046 .halg = {
0047 .digestsize = MD5_DIGEST_SIZE,
0048 .statesize = sizeof(struct md5_state),
0049 .base = {
0050 .cra_name = "md5",
0051 .cra_driver_name = "md5-sun4i-ss",
0052 .cra_priority = 300,
0053 .cra_alignmask = 3,
0054 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
0055 .cra_ctxsize = sizeof(struct sun4i_req_ctx),
0056 .cra_module = THIS_MODULE,
0057 .cra_init = sun4i_hash_crainit,
0058 .cra_exit = sun4i_hash_craexit,
0059 }
0060 }
0061 }
0062 },
0063 { .type = CRYPTO_ALG_TYPE_AHASH,
0064 .mode = SS_OP_SHA1,
0065 .alg.hash = {
0066 .init = sun4i_hash_init,
0067 .update = sun4i_hash_update,
0068 .final = sun4i_hash_final,
0069 .finup = sun4i_hash_finup,
0070 .digest = sun4i_hash_digest,
0071 .export = sun4i_hash_export_sha1,
0072 .import = sun4i_hash_import_sha1,
0073 .halg = {
0074 .digestsize = SHA1_DIGEST_SIZE,
0075 .statesize = sizeof(struct sha1_state),
0076 .base = {
0077 .cra_name = "sha1",
0078 .cra_driver_name = "sha1-sun4i-ss",
0079 .cra_priority = 300,
0080 .cra_alignmask = 3,
0081 .cra_blocksize = SHA1_BLOCK_SIZE,
0082 .cra_ctxsize = sizeof(struct sun4i_req_ctx),
0083 .cra_module = THIS_MODULE,
0084 .cra_init = sun4i_hash_crainit,
0085 .cra_exit = sun4i_hash_craexit,
0086 }
0087 }
0088 }
0089 },
0090 { .type = CRYPTO_ALG_TYPE_SKCIPHER,
0091 .alg.crypto = {
0092 .setkey = sun4i_ss_aes_setkey,
0093 .encrypt = sun4i_ss_cbc_aes_encrypt,
0094 .decrypt = sun4i_ss_cbc_aes_decrypt,
0095 .min_keysize = AES_MIN_KEY_SIZE,
0096 .max_keysize = AES_MAX_KEY_SIZE,
0097 .ivsize = AES_BLOCK_SIZE,
0098 .base = {
0099 .cra_name = "cbc(aes)",
0100 .cra_driver_name = "cbc-aes-sun4i-ss",
0101 .cra_priority = 300,
0102 .cra_blocksize = AES_BLOCK_SIZE,
0103 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK,
0104 .cra_ctxsize = sizeof(struct sun4i_tfm_ctx),
0105 .cra_module = THIS_MODULE,
0106 .cra_alignmask = 3,
0107 .cra_init = sun4i_ss_cipher_init,
0108 .cra_exit = sun4i_ss_cipher_exit,
0109 }
0110 }
0111 },
0112 { .type = CRYPTO_ALG_TYPE_SKCIPHER,
0113 .alg.crypto = {
0114 .setkey = sun4i_ss_aes_setkey,
0115 .encrypt = sun4i_ss_ecb_aes_encrypt,
0116 .decrypt = sun4i_ss_ecb_aes_decrypt,
0117 .min_keysize = AES_MIN_KEY_SIZE,
0118 .max_keysize = AES_MAX_KEY_SIZE,
0119 .base = {
0120 .cra_name = "ecb(aes)",
0121 .cra_driver_name = "ecb-aes-sun4i-ss",
0122 .cra_priority = 300,
0123 .cra_blocksize = AES_BLOCK_SIZE,
0124 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK,
0125 .cra_ctxsize = sizeof(struct sun4i_tfm_ctx),
0126 .cra_module = THIS_MODULE,
0127 .cra_alignmask = 3,
0128 .cra_init = sun4i_ss_cipher_init,
0129 .cra_exit = sun4i_ss_cipher_exit,
0130 }
0131 }
0132 },
0133 { .type = CRYPTO_ALG_TYPE_SKCIPHER,
0134 .alg.crypto = {
0135 .setkey = sun4i_ss_des_setkey,
0136 .encrypt = sun4i_ss_cbc_des_encrypt,
0137 .decrypt = sun4i_ss_cbc_des_decrypt,
0138 .min_keysize = DES_KEY_SIZE,
0139 .max_keysize = DES_KEY_SIZE,
0140 .ivsize = DES_BLOCK_SIZE,
0141 .base = {
0142 .cra_name = "cbc(des)",
0143 .cra_driver_name = "cbc-des-sun4i-ss",
0144 .cra_priority = 300,
0145 .cra_blocksize = DES_BLOCK_SIZE,
0146 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK,
0147 .cra_ctxsize = sizeof(struct sun4i_req_ctx),
0148 .cra_module = THIS_MODULE,
0149 .cra_alignmask = 3,
0150 .cra_init = sun4i_ss_cipher_init,
0151 .cra_exit = sun4i_ss_cipher_exit,
0152 }
0153 }
0154 },
0155 { .type = CRYPTO_ALG_TYPE_SKCIPHER,
0156 .alg.crypto = {
0157 .setkey = sun4i_ss_des_setkey,
0158 .encrypt = sun4i_ss_ecb_des_encrypt,
0159 .decrypt = sun4i_ss_ecb_des_decrypt,
0160 .min_keysize = DES_KEY_SIZE,
0161 .max_keysize = DES_KEY_SIZE,
0162 .base = {
0163 .cra_name = "ecb(des)",
0164 .cra_driver_name = "ecb-des-sun4i-ss",
0165 .cra_priority = 300,
0166 .cra_blocksize = DES_BLOCK_SIZE,
0167 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK,
0168 .cra_ctxsize = sizeof(struct sun4i_req_ctx),
0169 .cra_module = THIS_MODULE,
0170 .cra_alignmask = 3,
0171 .cra_init = sun4i_ss_cipher_init,
0172 .cra_exit = sun4i_ss_cipher_exit,
0173 }
0174 }
0175 },
0176 { .type = CRYPTO_ALG_TYPE_SKCIPHER,
0177 .alg.crypto = {
0178 .setkey = sun4i_ss_des3_setkey,
0179 .encrypt = sun4i_ss_cbc_des3_encrypt,
0180 .decrypt = sun4i_ss_cbc_des3_decrypt,
0181 .min_keysize = DES3_EDE_KEY_SIZE,
0182 .max_keysize = DES3_EDE_KEY_SIZE,
0183 .ivsize = DES3_EDE_BLOCK_SIZE,
0184 .base = {
0185 .cra_name = "cbc(des3_ede)",
0186 .cra_driver_name = "cbc-des3-sun4i-ss",
0187 .cra_priority = 300,
0188 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
0189 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK,
0190 .cra_ctxsize = sizeof(struct sun4i_req_ctx),
0191 .cra_module = THIS_MODULE,
0192 .cra_alignmask = 3,
0193 .cra_init = sun4i_ss_cipher_init,
0194 .cra_exit = sun4i_ss_cipher_exit,
0195 }
0196 }
0197 },
0198 { .type = CRYPTO_ALG_TYPE_SKCIPHER,
0199 .alg.crypto = {
0200 .setkey = sun4i_ss_des3_setkey,
0201 .encrypt = sun4i_ss_ecb_des3_encrypt,
0202 .decrypt = sun4i_ss_ecb_des3_decrypt,
0203 .min_keysize = DES3_EDE_KEY_SIZE,
0204 .max_keysize = DES3_EDE_KEY_SIZE,
0205 .base = {
0206 .cra_name = "ecb(des3_ede)",
0207 .cra_driver_name = "ecb-des3-sun4i-ss",
0208 .cra_priority = 300,
0209 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
0210 .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY | CRYPTO_ALG_NEED_FALLBACK,
0211 .cra_ctxsize = sizeof(struct sun4i_req_ctx),
0212 .cra_module = THIS_MODULE,
0213 .cra_alignmask = 3,
0214 .cra_init = sun4i_ss_cipher_init,
0215 .cra_exit = sun4i_ss_cipher_exit,
0216 }
0217 }
0218 },
0219 #ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
0220 {
0221 .type = CRYPTO_ALG_TYPE_RNG,
0222 .alg.rng = {
0223 .base = {
0224 .cra_name = "stdrng",
0225 .cra_driver_name = "sun4i_ss_rng",
0226 .cra_priority = 300,
0227 .cra_ctxsize = 0,
0228 .cra_module = THIS_MODULE,
0229 },
0230 .generate = sun4i_ss_prng_generate,
0231 .seed = sun4i_ss_prng_seed,
0232 .seedsize = SS_SEED_LEN / BITS_PER_BYTE,
0233 }
0234 },
0235 #endif
0236 };
0237
0238 static int sun4i_ss_dbgfs_read(struct seq_file *seq, void *v)
0239 {
0240 unsigned int i;
0241
0242 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
0243 if (!ss_algs[i].ss)
0244 continue;
0245 switch (ss_algs[i].type) {
0246 case CRYPTO_ALG_TYPE_SKCIPHER:
0247 seq_printf(seq, "%s %s reqs=%lu opti=%lu fallback=%lu tsize=%lu\n",
0248 ss_algs[i].alg.crypto.base.cra_driver_name,
0249 ss_algs[i].alg.crypto.base.cra_name,
0250 ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb,
0251 ss_algs[i].stat_bytes);
0252 break;
0253 case CRYPTO_ALG_TYPE_RNG:
0254 seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n",
0255 ss_algs[i].alg.rng.base.cra_driver_name,
0256 ss_algs[i].alg.rng.base.cra_name,
0257 ss_algs[i].stat_req, ss_algs[i].stat_bytes);
0258 break;
0259 case CRYPTO_ALG_TYPE_AHASH:
0260 seq_printf(seq, "%s %s reqs=%lu\n",
0261 ss_algs[i].alg.hash.halg.base.cra_driver_name,
0262 ss_algs[i].alg.hash.halg.base.cra_name,
0263 ss_algs[i].stat_req);
0264 break;
0265 }
0266 }
0267 return 0;
0268 }
0269
0270 static int sun4i_ss_dbgfs_open(struct inode *inode, struct file *file)
0271 {
0272 return single_open(file, sun4i_ss_dbgfs_read, inode->i_private);
0273 }
0274
0275 static const struct file_operations sun4i_ss_debugfs_fops = {
0276 .owner = THIS_MODULE,
0277 .open = sun4i_ss_dbgfs_open,
0278 .read = seq_read,
0279 .llseek = seq_lseek,
0280 .release = single_release,
0281 };
0282
0283
0284
0285
0286
0287 static int sun4i_ss_pm_suspend(struct device *dev)
0288 {
0289 struct sun4i_ss_ctx *ss = dev_get_drvdata(dev);
0290
0291 reset_control_assert(ss->reset);
0292
0293 clk_disable_unprepare(ss->ssclk);
0294 clk_disable_unprepare(ss->busclk);
0295 return 0;
0296 }
0297
0298 static int sun4i_ss_pm_resume(struct device *dev)
0299 {
0300 struct sun4i_ss_ctx *ss = dev_get_drvdata(dev);
0301
0302 int err;
0303
0304 err = clk_prepare_enable(ss->busclk);
0305 if (err) {
0306 dev_err(ss->dev, "Cannot prepare_enable busclk\n");
0307 goto err_enable;
0308 }
0309
0310 err = clk_prepare_enable(ss->ssclk);
0311 if (err) {
0312 dev_err(ss->dev, "Cannot prepare_enable ssclk\n");
0313 goto err_enable;
0314 }
0315
0316 err = reset_control_deassert(ss->reset);
0317 if (err) {
0318 dev_err(ss->dev, "Cannot deassert reset control\n");
0319 goto err_enable;
0320 }
0321
0322 return err;
0323 err_enable:
0324 sun4i_ss_pm_suspend(dev);
0325 return err;
0326 }
0327
0328 static const struct dev_pm_ops sun4i_ss_pm_ops = {
0329 SET_RUNTIME_PM_OPS(sun4i_ss_pm_suspend, sun4i_ss_pm_resume, NULL)
0330 };
0331
0332
0333
0334
0335
0336
0337 static int sun4i_ss_pm_init(struct sun4i_ss_ctx *ss)
0338 {
0339 int err;
0340
0341 pm_runtime_use_autosuspend(ss->dev);
0342 pm_runtime_set_autosuspend_delay(ss->dev, 2000);
0343
0344 err = pm_runtime_set_suspended(ss->dev);
0345 if (err)
0346 return err;
0347 pm_runtime_enable(ss->dev);
0348 return err;
0349 }
0350
0351 static void sun4i_ss_pm_exit(struct sun4i_ss_ctx *ss)
0352 {
0353 pm_runtime_disable(ss->dev);
0354 }
0355
0356 static int sun4i_ss_probe(struct platform_device *pdev)
0357 {
0358 u32 v;
0359 int err, i;
0360 unsigned long cr;
0361 const unsigned long cr_ahb = 24 * 1000 * 1000;
0362 const unsigned long cr_mod = 150 * 1000 * 1000;
0363 struct sun4i_ss_ctx *ss;
0364
0365 if (!pdev->dev.of_node)
0366 return -ENODEV;
0367
0368 ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL);
0369 if (!ss)
0370 return -ENOMEM;
0371
0372 ss->base = devm_platform_ioremap_resource(pdev, 0);
0373 if (IS_ERR(ss->base)) {
0374 dev_err(&pdev->dev, "Cannot request MMIO\n");
0375 return PTR_ERR(ss->base);
0376 }
0377
0378 ss->variant = of_device_get_match_data(&pdev->dev);
0379 if (!ss->variant) {
0380 dev_err(&pdev->dev, "Missing Security System variant\n");
0381 return -EINVAL;
0382 }
0383
0384 ss->ssclk = devm_clk_get(&pdev->dev, "mod");
0385 if (IS_ERR(ss->ssclk)) {
0386 err = PTR_ERR(ss->ssclk);
0387 dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err);
0388 return err;
0389 }
0390 dev_dbg(&pdev->dev, "clock ss acquired\n");
0391
0392 ss->busclk = devm_clk_get(&pdev->dev, "ahb");
0393 if (IS_ERR(ss->busclk)) {
0394 err = PTR_ERR(ss->busclk);
0395 dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err);
0396 return err;
0397 }
0398 dev_dbg(&pdev->dev, "clock ahb_ss acquired\n");
0399
0400 ss->reset = devm_reset_control_get_optional(&pdev->dev, "ahb");
0401 if (IS_ERR(ss->reset))
0402 return PTR_ERR(ss->reset);
0403 if (!ss->reset)
0404 dev_info(&pdev->dev, "no reset control found\n");
0405
0406
0407
0408
0409
0410 err = clk_set_rate(ss->ssclk, cr_mod);
0411 if (err) {
0412 dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n");
0413 return err;
0414 }
0415
0416
0417
0418
0419
0420
0421 cr = clk_get_rate(ss->busclk);
0422 if (cr >= cr_ahb)
0423 dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
0424 cr, cr / 1000000, cr_ahb);
0425 else
0426 dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
0427 cr, cr / 1000000, cr_ahb);
0428
0429 cr = clk_get_rate(ss->ssclk);
0430 if (cr <= cr_mod)
0431 if (cr < cr_mod)
0432 dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
0433 cr, cr / 1000000, cr_mod);
0434 else
0435 dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
0436 cr, cr / 1000000, cr_mod);
0437 else
0438 dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n",
0439 cr, cr / 1000000, cr_mod);
0440
0441 ss->dev = &pdev->dev;
0442 platform_set_drvdata(pdev, ss);
0443
0444 spin_lock_init(&ss->slock);
0445
0446 err = sun4i_ss_pm_init(ss);
0447 if (err)
0448 return err;
0449
0450
0451
0452
0453
0454
0455
0456
0457 err = pm_runtime_resume_and_get(ss->dev);
0458 if (err < 0)
0459 goto error_pm;
0460
0461 writel(SS_ENABLED, ss->base + SS_CTL);
0462 v = readl(ss->base + SS_CTL);
0463 v >>= 16;
0464 v &= 0x07;
0465 dev_info(&pdev->dev, "Die ID %d\n", v);
0466 writel(0, ss->base + SS_CTL);
0467
0468 pm_runtime_put_sync(ss->dev);
0469
0470 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
0471 ss_algs[i].ss = ss;
0472 switch (ss_algs[i].type) {
0473 case CRYPTO_ALG_TYPE_SKCIPHER:
0474 err = crypto_register_skcipher(&ss_algs[i].alg.crypto);
0475 if (err) {
0476 dev_err(ss->dev, "Fail to register %s\n",
0477 ss_algs[i].alg.crypto.base.cra_name);
0478 goto error_alg;
0479 }
0480 break;
0481 case CRYPTO_ALG_TYPE_AHASH:
0482 err = crypto_register_ahash(&ss_algs[i].alg.hash);
0483 if (err) {
0484 dev_err(ss->dev, "Fail to register %s\n",
0485 ss_algs[i].alg.hash.halg.base.cra_name);
0486 goto error_alg;
0487 }
0488 break;
0489 case CRYPTO_ALG_TYPE_RNG:
0490 err = crypto_register_rng(&ss_algs[i].alg.rng);
0491 if (err) {
0492 dev_err(ss->dev, "Fail to register %s\n",
0493 ss_algs[i].alg.rng.base.cra_name);
0494 }
0495 break;
0496 }
0497 }
0498
0499
0500 ss->dbgfs_dir = debugfs_create_dir("sun4i-ss", NULL);
0501 ss->dbgfs_stats = debugfs_create_file("stats", 0444, ss->dbgfs_dir, ss,
0502 &sun4i_ss_debugfs_fops);
0503
0504 return 0;
0505 error_alg:
0506 i--;
0507 for (; i >= 0; i--) {
0508 switch (ss_algs[i].type) {
0509 case CRYPTO_ALG_TYPE_SKCIPHER:
0510 crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
0511 break;
0512 case CRYPTO_ALG_TYPE_AHASH:
0513 crypto_unregister_ahash(&ss_algs[i].alg.hash);
0514 break;
0515 case CRYPTO_ALG_TYPE_RNG:
0516 crypto_unregister_rng(&ss_algs[i].alg.rng);
0517 break;
0518 }
0519 }
0520 error_pm:
0521 sun4i_ss_pm_exit(ss);
0522 return err;
0523 }
0524
0525 static int sun4i_ss_remove(struct platform_device *pdev)
0526 {
0527 int i;
0528 struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev);
0529
0530 for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
0531 switch (ss_algs[i].type) {
0532 case CRYPTO_ALG_TYPE_SKCIPHER:
0533 crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
0534 break;
0535 case CRYPTO_ALG_TYPE_AHASH:
0536 crypto_unregister_ahash(&ss_algs[i].alg.hash);
0537 break;
0538 case CRYPTO_ALG_TYPE_RNG:
0539 crypto_unregister_rng(&ss_algs[i].alg.rng);
0540 break;
0541 }
0542 }
0543
0544 sun4i_ss_pm_exit(ss);
0545 return 0;
0546 }
0547
0548 static const struct of_device_id a20ss_crypto_of_match_table[] = {
0549 { .compatible = "allwinner,sun4i-a10-crypto",
0550 .data = &ss_a10_variant
0551 },
0552 { .compatible = "allwinner,sun8i-a33-crypto",
0553 .data = &ss_a33_variant
0554 },
0555 {}
0556 };
0557 MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table);
0558
0559 static struct platform_driver sun4i_ss_driver = {
0560 .probe = sun4i_ss_probe,
0561 .remove = sun4i_ss_remove,
0562 .driver = {
0563 .name = "sun4i-ss",
0564 .pm = &sun4i_ss_pm_ops,
0565 .of_match_table = a20ss_crypto_of_match_table,
0566 },
0567 };
0568
0569 module_platform_driver(sun4i_ss_driver);
0570
0571 MODULE_ALIAS("platform:sun4i-ss");
0572 MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator");
0573 MODULE_LICENSE("GPL");
0574 MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>");