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