root/drivers/crypto/sunxi-ss/sun4i-ss-core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sun4i_ss_probe
  2. sun4i_ss_remove

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

/* [<][>][^][v][top][bottom][index][help] */