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