Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * sun4i-ss-core.c - hardware cryptographic accelerator for Allwinner A20 SoC
0004  *
0005  * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
0006  *
0007  * Core file which registers crypto algorithms supported by the SS.
0008  *
0009  * You could find a link for the datasheet in Documentation/arm/sunxi.rst
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  * Power management strategy: The device is suspended unless a TFM exists for
0285  * one of the algorithms proposed by this driver.
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  * When power management is enabled, this function enables the PM and set the
0334  * device as suspended
0335  * When power management is disabled, this function just enables the device
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      * Check that clock have the correct rates given in the datasheet
0408      * Try to set the clock to the maximum allowed
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      * The only impact on clocks below requirement are bad performance,
0418      * so do not print "errors"
0419      * warn on Overclocked clocks
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      * Datasheet named it "Die Bonding ID"
0452      * I expect to be a sort of Security System Revision number.
0453      * Since the A80 seems to have an other version of SS
0454      * this info could be useful
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     /* Ignore error of debugfs */
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>");