GNU Linux-libre 4.19.295-gnu1
[releases.git] / drivers / crypto / sunxi-ss / sun4i-ss-core.c
1 /*
2  * sun4i-ss-core.c - hardware cryptographic accelerator for Allwinner A20 SoC
3  *
4  * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
5  *
6  * Core file which registers crypto algorithms supported by the SS.
7  *
8  * You could find a link for the datasheet in Documentation/arm/sunxi/README
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  */
15 #include <linux/clk.h>
16 #include <linux/crypto.h>
17 #include <linux/io.h>
18 #include <linux/module.h>
19 #include <linux/of.h>
20 #include <linux/platform_device.h>
21 #include <crypto/scatterwalk.h>
22 #include <linux/scatterlist.h>
23 #include <linux/interrupt.h>
24 #include <linux/delay.h>
25 #include <linux/reset.h>
26
27 #include "sun4i-ss.h"
28
29 static struct sun4i_ss_alg_template ss_algs[] = {
30 {       .type = CRYPTO_ALG_TYPE_AHASH,
31         .mode = SS_OP_MD5,
32         .alg.hash = {
33                 .init = sun4i_hash_init,
34                 .update = sun4i_hash_update,
35                 .final = sun4i_hash_final,
36                 .finup = sun4i_hash_finup,
37                 .digest = sun4i_hash_digest,
38                 .export = sun4i_hash_export_md5,
39                 .import = sun4i_hash_import_md5,
40                 .halg = {
41                         .digestsize = MD5_DIGEST_SIZE,
42                         .statesize = sizeof(struct md5_state),
43                         .base = {
44                                 .cra_name = "md5",
45                                 .cra_driver_name = "md5-sun4i-ss",
46                                 .cra_priority = 300,
47                                 .cra_alignmask = 3,
48                                 .cra_blocksize = MD5_HMAC_BLOCK_SIZE,
49                                 .cra_ctxsize = sizeof(struct sun4i_req_ctx),
50                                 .cra_module = THIS_MODULE,
51                                 .cra_init = sun4i_hash_crainit
52                         }
53                 }
54         }
55 },
56 {       .type = CRYPTO_ALG_TYPE_AHASH,
57         .mode = SS_OP_SHA1,
58         .alg.hash = {
59                 .init = sun4i_hash_init,
60                 .update = sun4i_hash_update,
61                 .final = sun4i_hash_final,
62                 .finup = sun4i_hash_finup,
63                 .digest = sun4i_hash_digest,
64                 .export = sun4i_hash_export_sha1,
65                 .import = sun4i_hash_import_sha1,
66                 .halg = {
67                         .digestsize = SHA1_DIGEST_SIZE,
68                         .statesize = sizeof(struct sha1_state),
69                         .base = {
70                                 .cra_name = "sha1",
71                                 .cra_driver_name = "sha1-sun4i-ss",
72                                 .cra_priority = 300,
73                                 .cra_alignmask = 3,
74                                 .cra_blocksize = SHA1_BLOCK_SIZE,
75                                 .cra_ctxsize = sizeof(struct sun4i_req_ctx),
76                                 .cra_module = THIS_MODULE,
77                                 .cra_init = sun4i_hash_crainit
78                         }
79                 }
80         }
81 },
82 {       .type = CRYPTO_ALG_TYPE_SKCIPHER,
83         .alg.crypto = {
84                 .setkey         = sun4i_ss_aes_setkey,
85                 .encrypt        = sun4i_ss_cbc_aes_encrypt,
86                 .decrypt        = sun4i_ss_cbc_aes_decrypt,
87                 .min_keysize    = AES_MIN_KEY_SIZE,
88                 .max_keysize    = AES_MAX_KEY_SIZE,
89                 .ivsize         = AES_BLOCK_SIZE,
90                 .base = {
91                         .cra_name = "cbc(aes)",
92                         .cra_driver_name = "cbc-aes-sun4i-ss",
93                         .cra_priority = 300,
94                         .cra_blocksize = AES_BLOCK_SIZE,
95                         .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY,
96                         .cra_ctxsize = sizeof(struct sun4i_tfm_ctx),
97                         .cra_module = THIS_MODULE,
98                         .cra_alignmask = 3,
99                         .cra_init = sun4i_ss_cipher_init,
100                 }
101         }
102 },
103 {       .type = CRYPTO_ALG_TYPE_SKCIPHER,
104         .alg.crypto = {
105                 .setkey         = sun4i_ss_aes_setkey,
106                 .encrypt        = sun4i_ss_ecb_aes_encrypt,
107                 .decrypt        = sun4i_ss_ecb_aes_decrypt,
108                 .min_keysize    = AES_MIN_KEY_SIZE,
109                 .max_keysize    = AES_MAX_KEY_SIZE,
110                 .ivsize         = AES_BLOCK_SIZE,
111                 .base = {
112                         .cra_name = "ecb(aes)",
113                         .cra_driver_name = "ecb-aes-sun4i-ss",
114                         .cra_priority = 300,
115                         .cra_blocksize = AES_BLOCK_SIZE,
116                         .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY,
117                         .cra_ctxsize = sizeof(struct sun4i_tfm_ctx),
118                         .cra_module = THIS_MODULE,
119                         .cra_alignmask = 3,
120                         .cra_init = sun4i_ss_cipher_init,
121                 }
122         }
123 },
124 {       .type = CRYPTO_ALG_TYPE_SKCIPHER,
125         .alg.crypto = {
126                 .setkey         = sun4i_ss_des_setkey,
127                 .encrypt        = sun4i_ss_cbc_des_encrypt,
128                 .decrypt        = sun4i_ss_cbc_des_decrypt,
129                 .min_keysize    = DES_KEY_SIZE,
130                 .max_keysize    = DES_KEY_SIZE,
131                 .ivsize         = DES_BLOCK_SIZE,
132                 .base = {
133                         .cra_name = "cbc(des)",
134                         .cra_driver_name = "cbc-des-sun4i-ss",
135                         .cra_priority = 300,
136                         .cra_blocksize = DES_BLOCK_SIZE,
137                         .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY,
138                         .cra_ctxsize = sizeof(struct sun4i_req_ctx),
139                         .cra_module = THIS_MODULE,
140                         .cra_alignmask = 3,
141                         .cra_init = sun4i_ss_cipher_init,
142                 }
143         }
144 },
145 {       .type = CRYPTO_ALG_TYPE_SKCIPHER,
146         .alg.crypto = {
147                 .setkey         = sun4i_ss_des_setkey,
148                 .encrypt        = sun4i_ss_ecb_des_encrypt,
149                 .decrypt        = sun4i_ss_ecb_des_decrypt,
150                 .min_keysize    = DES_KEY_SIZE,
151                 .max_keysize    = DES_KEY_SIZE,
152                 .base = {
153                         .cra_name = "ecb(des)",
154                         .cra_driver_name = "ecb-des-sun4i-ss",
155                         .cra_priority = 300,
156                         .cra_blocksize = DES_BLOCK_SIZE,
157                         .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY,
158                         .cra_ctxsize = sizeof(struct sun4i_req_ctx),
159                         .cra_module = THIS_MODULE,
160                         .cra_alignmask = 3,
161                         .cra_init = sun4i_ss_cipher_init,
162                 }
163         }
164 },
165 {       .type = CRYPTO_ALG_TYPE_SKCIPHER,
166         .alg.crypto = {
167                 .setkey         = sun4i_ss_des3_setkey,
168                 .encrypt        = sun4i_ss_cbc_des3_encrypt,
169                 .decrypt        = sun4i_ss_cbc_des3_decrypt,
170                 .min_keysize    = DES3_EDE_KEY_SIZE,
171                 .max_keysize    = DES3_EDE_KEY_SIZE,
172                 .ivsize         = DES3_EDE_BLOCK_SIZE,
173                 .base = {
174                         .cra_name = "cbc(des3_ede)",
175                         .cra_driver_name = "cbc-des3-sun4i-ss",
176                         .cra_priority = 300,
177                         .cra_blocksize = DES3_EDE_BLOCK_SIZE,
178                         .cra_flags = CRYPTO_ALG_KERN_DRIVER_ONLY,
179                         .cra_ctxsize = sizeof(struct sun4i_req_ctx),
180                         .cra_module = THIS_MODULE,
181                         .cra_alignmask = 3,
182                         .cra_init = sun4i_ss_cipher_init,
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                 .ivsize         = DES3_EDE_BLOCK_SIZE,
194                 .base = {
195                         .cra_name = "ecb(des3_ede)",
196                         .cra_driver_name = "ecb-des3-sun4i-ss",
197                         .cra_priority = 300,
198                         .cra_blocksize = DES3_EDE_BLOCK_SIZE,
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                 }
204         }
205 },
206 #ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
207 {
208         .type = CRYPTO_ALG_TYPE_RNG,
209         .alg.rng = {
210                 .base = {
211                         .cra_name               = "stdrng",
212                         .cra_driver_name        = "sun4i_ss_rng",
213                         .cra_priority           = 300,
214                         .cra_ctxsize            = 0,
215                         .cra_module             = THIS_MODULE,
216                 },
217                 .generate               = sun4i_ss_prng_generate,
218                 .seed                   = sun4i_ss_prng_seed,
219                 .seedsize               = SS_SEED_LEN / BITS_PER_BYTE,
220         }
221 },
222 #endif
223 };
224
225 static int sun4i_ss_probe(struct platform_device *pdev)
226 {
227         struct resource *res;
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         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
243         ss->base = devm_ioremap_resource(&pdev->dev, res);
244         if (IS_ERR(ss->base)) {
245                 dev_err(&pdev->dev, "Cannot request MMIO\n");
246                 return PTR_ERR(ss->base);
247         }
248
249         ss->ssclk = devm_clk_get(&pdev->dev, "mod");
250         if (IS_ERR(ss->ssclk)) {
251                 err = PTR_ERR(ss->ssclk);
252                 dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err);
253                 return err;
254         }
255         dev_dbg(&pdev->dev, "clock ss acquired\n");
256
257         ss->busclk = devm_clk_get(&pdev->dev, "ahb");
258         if (IS_ERR(ss->busclk)) {
259                 err = PTR_ERR(ss->busclk);
260                 dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err);
261                 return err;
262         }
263         dev_dbg(&pdev->dev, "clock ahb_ss acquired\n");
264
265         ss->reset = devm_reset_control_get_optional(&pdev->dev, "ahb");
266         if (IS_ERR(ss->reset)) {
267                 if (PTR_ERR(ss->reset) == -EPROBE_DEFER)
268                         return PTR_ERR(ss->reset);
269                 dev_info(&pdev->dev, "no reset control found\n");
270                 ss->reset = NULL;
271         }
272
273         /* Enable both clocks */
274         err = clk_prepare_enable(ss->busclk);
275         if (err) {
276                 dev_err(&pdev->dev, "Cannot prepare_enable busclk\n");
277                 return err;
278         }
279         err = clk_prepare_enable(ss->ssclk);
280         if (err) {
281                 dev_err(&pdev->dev, "Cannot prepare_enable ssclk\n");
282                 goto error_ssclk;
283         }
284
285         /*
286          * Check that clock have the correct rates given in the datasheet
287          * Try to set the clock to the maximum allowed
288          */
289         err = clk_set_rate(ss->ssclk, cr_mod);
290         if (err) {
291                 dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n");
292                 goto error_clk;
293         }
294
295         /* Deassert reset if we have a reset control */
296         if (ss->reset) {
297                 err = reset_control_deassert(ss->reset);
298                 if (err) {
299                         dev_err(&pdev->dev, "Cannot deassert reset control\n");
300                         goto error_clk;
301                 }
302         }
303
304         /*
305          * The only impact on clocks below requirement are bad performance,
306          * so do not print "errors"
307          * warn on Overclocked clocks
308          */
309         cr = clk_get_rate(ss->busclk);
310         if (cr >= cr_ahb)
311                 dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
312                         cr, cr / 1000000, cr_ahb);
313         else
314                 dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
315                          cr, cr / 1000000, cr_ahb);
316
317         cr = clk_get_rate(ss->ssclk);
318         if (cr <= cr_mod)
319                 if (cr < cr_mod)
320                         dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
321                                  cr, cr / 1000000, cr_mod);
322                 else
323                         dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
324                                 cr, cr / 1000000, cr_mod);
325         else
326                 dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n",
327                          cr, cr / 1000000, cr_mod);
328
329         /*
330          * Datasheet named it "Die Bonding ID"
331          * I expect to be a sort of Security System Revision number.
332          * Since the A80 seems to have an other version of SS
333          * this info could be useful
334          */
335         writel(SS_ENABLED, ss->base + SS_CTL);
336         v = readl(ss->base + SS_CTL);
337         v >>= 16;
338         v &= 0x07;
339         dev_info(&pdev->dev, "Die ID %d\n", v);
340         writel(0, ss->base + SS_CTL);
341
342         ss->dev = &pdev->dev;
343
344         spin_lock_init(&ss->slock);
345
346         for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
347                 ss_algs[i].ss = ss;
348                 switch (ss_algs[i].type) {
349                 case CRYPTO_ALG_TYPE_SKCIPHER:
350                         err = crypto_register_skcipher(&ss_algs[i].alg.crypto);
351                         if (err) {
352                                 dev_err(ss->dev, "Fail to register %s\n",
353                                         ss_algs[i].alg.crypto.base.cra_name);
354                                 goto error_alg;
355                         }
356                         break;
357                 case CRYPTO_ALG_TYPE_AHASH:
358                         err = crypto_register_ahash(&ss_algs[i].alg.hash);
359                         if (err) {
360                                 dev_err(ss->dev, "Fail to register %s\n",
361                                         ss_algs[i].alg.hash.halg.base.cra_name);
362                                 goto error_alg;
363                         }
364                         break;
365                 case CRYPTO_ALG_TYPE_RNG:
366                         err = crypto_register_rng(&ss_algs[i].alg.rng);
367                         if (err) {
368                                 dev_err(ss->dev, "Fail to register %s\n",
369                                         ss_algs[i].alg.rng.base.cra_name);
370                         }
371                         break;
372                 }
373         }
374         platform_set_drvdata(pdev, ss);
375         return 0;
376 error_alg:
377         i--;
378         for (; i >= 0; i--) {
379                 switch (ss_algs[i].type) {
380                 case CRYPTO_ALG_TYPE_SKCIPHER:
381                         crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
382                         break;
383                 case CRYPTO_ALG_TYPE_AHASH:
384                         crypto_unregister_ahash(&ss_algs[i].alg.hash);
385                         break;
386                 case CRYPTO_ALG_TYPE_RNG:
387                         crypto_unregister_rng(&ss_algs[i].alg.rng);
388                         break;
389                 }
390         }
391         if (ss->reset)
392                 reset_control_assert(ss->reset);
393 error_clk:
394         clk_disable_unprepare(ss->ssclk);
395 error_ssclk:
396         clk_disable_unprepare(ss->busclk);
397         return err;
398 }
399
400 static int sun4i_ss_remove(struct platform_device *pdev)
401 {
402         int i;
403         struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev);
404
405         for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
406                 switch (ss_algs[i].type) {
407                 case CRYPTO_ALG_TYPE_SKCIPHER:
408                         crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
409                         break;
410                 case CRYPTO_ALG_TYPE_AHASH:
411                         crypto_unregister_ahash(&ss_algs[i].alg.hash);
412                         break;
413                 case CRYPTO_ALG_TYPE_RNG:
414                         crypto_unregister_rng(&ss_algs[i].alg.rng);
415                         break;
416                 }
417         }
418
419         writel(0, ss->base + SS_CTL);
420         if (ss->reset)
421                 reset_control_assert(ss->reset);
422         clk_disable_unprepare(ss->busclk);
423         clk_disable_unprepare(ss->ssclk);
424         return 0;
425 }
426
427 static const struct of_device_id a20ss_crypto_of_match_table[] = {
428         { .compatible = "allwinner,sun4i-a10-crypto" },
429         {}
430 };
431 MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table);
432
433 static struct platform_driver sun4i_ss_driver = {
434         .probe          = sun4i_ss_probe,
435         .remove         = sun4i_ss_remove,
436         .driver         = {
437                 .name           = "sun4i-ss",
438                 .of_match_table = a20ss_crypto_of_match_table,
439         },
440 };
441
442 module_platform_driver(sun4i_ss_driver);
443
444 MODULE_ALIAS("platform:sun4i-ss");
445 MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator");
446 MODULE_LICENSE("GPL");
447 MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>");