xref: /linux/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
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/arch/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/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 static int sun4i_ss_debugfs_show(struct seq_file *seq, void *v)
238 {
239 	unsigned int i;
240 
241 	for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
242 		if (!ss_algs[i].ss)
243 			continue;
244 		switch (ss_algs[i].type) {
245 		case CRYPTO_ALG_TYPE_SKCIPHER:
246 			seq_printf(seq, "%s %s reqs=%lu opti=%lu fallback=%lu tsize=%lu\n",
247 				   ss_algs[i].alg.crypto.base.cra_driver_name,
248 				   ss_algs[i].alg.crypto.base.cra_name,
249 				   ss_algs[i].stat_req, ss_algs[i].stat_opti, ss_algs[i].stat_fb,
250 				   ss_algs[i].stat_bytes);
251 			break;
252 		case CRYPTO_ALG_TYPE_RNG:
253 			seq_printf(seq, "%s %s reqs=%lu tsize=%lu\n",
254 				   ss_algs[i].alg.rng.base.cra_driver_name,
255 				   ss_algs[i].alg.rng.base.cra_name,
256 				   ss_algs[i].stat_req, ss_algs[i].stat_bytes);
257 			break;
258 		case CRYPTO_ALG_TYPE_AHASH:
259 			seq_printf(seq, "%s %s reqs=%lu\n",
260 				   ss_algs[i].alg.hash.halg.base.cra_driver_name,
261 				   ss_algs[i].alg.hash.halg.base.cra_name,
262 				   ss_algs[i].stat_req);
263 			break;
264 		}
265 	}
266 	return 0;
267 }
268 DEFINE_SHOW_ATTRIBUTE(sun4i_ss_debugfs);
269 
270 /*
271  * Power management strategy: The device is suspended unless a TFM exists for
272  * one of the algorithms proposed by this driver.
273  */
274 static int sun4i_ss_pm_suspend(struct device *dev)
275 {
276 	struct sun4i_ss_ctx *ss = dev_get_drvdata(dev);
277 
278 	reset_control_assert(ss->reset);
279 
280 	clk_disable_unprepare(ss->ssclk);
281 	clk_disable_unprepare(ss->busclk);
282 	return 0;
283 }
284 
285 static int sun4i_ss_pm_resume(struct device *dev)
286 {
287 	struct sun4i_ss_ctx *ss = dev_get_drvdata(dev);
288 
289 	int err;
290 
291 	err = clk_prepare_enable(ss->busclk);
292 	if (err) {
293 		dev_err(ss->dev, "Cannot prepare_enable busclk\n");
294 		goto err_enable;
295 	}
296 
297 	err = clk_prepare_enable(ss->ssclk);
298 	if (err) {
299 		dev_err(ss->dev, "Cannot prepare_enable ssclk\n");
300 		goto err_enable;
301 	}
302 
303 	err = reset_control_deassert(ss->reset);
304 	if (err) {
305 		dev_err(ss->dev, "Cannot deassert reset control\n");
306 		goto err_enable;
307 	}
308 
309 	return err;
310 err_enable:
311 	sun4i_ss_pm_suspend(dev);
312 	return err;
313 }
314 
315 static const struct dev_pm_ops sun4i_ss_pm_ops = {
316 	SET_RUNTIME_PM_OPS(sun4i_ss_pm_suspend, sun4i_ss_pm_resume, NULL)
317 };
318 
319 /*
320  * When power management is enabled, this function enables the PM and set the
321  * device as suspended
322  * When power management is disabled, this function just enables the device
323  */
324 static int sun4i_ss_pm_init(struct sun4i_ss_ctx *ss)
325 {
326 	int err;
327 
328 	pm_runtime_use_autosuspend(ss->dev);
329 	pm_runtime_set_autosuspend_delay(ss->dev, 2000);
330 
331 	err = pm_runtime_set_suspended(ss->dev);
332 	if (err)
333 		return err;
334 	pm_runtime_enable(ss->dev);
335 	return err;
336 }
337 
338 static void sun4i_ss_pm_exit(struct sun4i_ss_ctx *ss)
339 {
340 	pm_runtime_disable(ss->dev);
341 }
342 
343 static int sun4i_ss_probe(struct platform_device *pdev)
344 {
345 	u32 v;
346 	int err, i;
347 	unsigned long cr;
348 	const unsigned long cr_ahb = 24 * 1000 * 1000;
349 	const unsigned long cr_mod = 150 * 1000 * 1000;
350 	struct sun4i_ss_ctx *ss;
351 
352 	if (!pdev->dev.of_node)
353 		return -ENODEV;
354 
355 	ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL);
356 	if (!ss)
357 		return -ENOMEM;
358 
359 	ss->base = devm_platform_ioremap_resource(pdev, 0);
360 	if (IS_ERR(ss->base)) {
361 		dev_err(&pdev->dev, "Cannot request MMIO\n");
362 		return PTR_ERR(ss->base);
363 	}
364 
365 	ss->variant = of_device_get_match_data(&pdev->dev);
366 	if (!ss->variant) {
367 		dev_err(&pdev->dev, "Missing Security System variant\n");
368 		return -EINVAL;
369 	}
370 
371 	ss->ssclk = devm_clk_get(&pdev->dev, "mod");
372 	if (IS_ERR(ss->ssclk)) {
373 		err = PTR_ERR(ss->ssclk);
374 		dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err);
375 		return err;
376 	}
377 	dev_dbg(&pdev->dev, "clock ss acquired\n");
378 
379 	ss->busclk = devm_clk_get(&pdev->dev, "ahb");
380 	if (IS_ERR(ss->busclk)) {
381 		err = PTR_ERR(ss->busclk);
382 		dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err);
383 		return err;
384 	}
385 	dev_dbg(&pdev->dev, "clock ahb_ss acquired\n");
386 
387 	ss->reset = devm_reset_control_get_optional(&pdev->dev, "ahb");
388 	if (IS_ERR(ss->reset))
389 		return PTR_ERR(ss->reset);
390 	if (!ss->reset)
391 		dev_info(&pdev->dev, "no reset control found\n");
392 
393 	/*
394 	 * Check that clock have the correct rates given in the datasheet
395 	 * Try to set the clock to the maximum allowed
396 	 */
397 	err = clk_set_rate(ss->ssclk, cr_mod);
398 	if (err) {
399 		dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n");
400 		return err;
401 	}
402 
403 	/*
404 	 * The only impact on clocks below requirement are bad performance,
405 	 * so do not print "errors"
406 	 * warn on Overclocked clocks
407 	 */
408 	cr = clk_get_rate(ss->busclk);
409 	if (cr >= cr_ahb)
410 		dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
411 			cr, cr / 1000000, cr_ahb);
412 	else
413 		dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
414 			 cr, cr / 1000000, cr_ahb);
415 
416 	cr = clk_get_rate(ss->ssclk);
417 	if (cr <= cr_mod)
418 		if (cr < cr_mod)
419 			dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
420 				 cr, cr / 1000000, cr_mod);
421 		else
422 			dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
423 				cr, cr / 1000000, cr_mod);
424 	else
425 		dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n",
426 			 cr, cr / 1000000, cr_mod);
427 
428 	ss->dev = &pdev->dev;
429 	platform_set_drvdata(pdev, ss);
430 
431 	spin_lock_init(&ss->slock);
432 
433 	err = sun4i_ss_pm_init(ss);
434 	if (err)
435 		return err;
436 
437 	/*
438 	 * Datasheet named it "Die Bonding ID"
439 	 * I expect to be a sort of Security System Revision number.
440 	 * Since the A80 seems to have an other version of SS
441 	 * this info could be useful
442 	 */
443 
444 	err = pm_runtime_resume_and_get(ss->dev);
445 	if (err < 0)
446 		goto error_pm;
447 
448 	writel(SS_ENABLED, ss->base + SS_CTL);
449 	v = readl(ss->base + SS_CTL);
450 	v >>= 16;
451 	v &= 0x07;
452 	dev_info(&pdev->dev, "Die ID %d\n", v);
453 	writel(0, ss->base + SS_CTL);
454 
455 	pm_runtime_put_sync(ss->dev);
456 
457 	for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
458 		ss_algs[i].ss = ss;
459 		switch (ss_algs[i].type) {
460 		case CRYPTO_ALG_TYPE_SKCIPHER:
461 			err = crypto_register_skcipher(&ss_algs[i].alg.crypto);
462 			if (err) {
463 				dev_err(ss->dev, "Fail to register %s\n",
464 					ss_algs[i].alg.crypto.base.cra_name);
465 				goto error_alg;
466 			}
467 			break;
468 		case CRYPTO_ALG_TYPE_AHASH:
469 			err = crypto_register_ahash(&ss_algs[i].alg.hash);
470 			if (err) {
471 				dev_err(ss->dev, "Fail to register %s\n",
472 					ss_algs[i].alg.hash.halg.base.cra_name);
473 				goto error_alg;
474 			}
475 			break;
476 		case CRYPTO_ALG_TYPE_RNG:
477 			err = crypto_register_rng(&ss_algs[i].alg.rng);
478 			if (err) {
479 				dev_err(ss->dev, "Fail to register %s\n",
480 					ss_algs[i].alg.rng.base.cra_name);
481 			}
482 			break;
483 		}
484 	}
485 
486 	/* Ignore error of debugfs */
487 	ss->dbgfs_dir = debugfs_create_dir("sun4i-ss", NULL);
488 	ss->dbgfs_stats = debugfs_create_file("stats", 0444, ss->dbgfs_dir, ss,
489 					      &sun4i_ss_debugfs_fops);
490 
491 	return 0;
492 error_alg:
493 	i--;
494 	for (; i >= 0; i--) {
495 		switch (ss_algs[i].type) {
496 		case CRYPTO_ALG_TYPE_SKCIPHER:
497 			crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
498 			break;
499 		case CRYPTO_ALG_TYPE_AHASH:
500 			crypto_unregister_ahash(&ss_algs[i].alg.hash);
501 			break;
502 		case CRYPTO_ALG_TYPE_RNG:
503 			crypto_unregister_rng(&ss_algs[i].alg.rng);
504 			break;
505 		}
506 	}
507 error_pm:
508 	sun4i_ss_pm_exit(ss);
509 	return err;
510 }
511 
512 static int sun4i_ss_remove(struct platform_device *pdev)
513 {
514 	int i;
515 	struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev);
516 
517 	for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
518 		switch (ss_algs[i].type) {
519 		case CRYPTO_ALG_TYPE_SKCIPHER:
520 			crypto_unregister_skcipher(&ss_algs[i].alg.crypto);
521 			break;
522 		case CRYPTO_ALG_TYPE_AHASH:
523 			crypto_unregister_ahash(&ss_algs[i].alg.hash);
524 			break;
525 		case CRYPTO_ALG_TYPE_RNG:
526 			crypto_unregister_rng(&ss_algs[i].alg.rng);
527 			break;
528 		}
529 	}
530 
531 	sun4i_ss_pm_exit(ss);
532 	return 0;
533 }
534 
535 static const struct of_device_id a20ss_crypto_of_match_table[] = {
536 	{ .compatible = "allwinner,sun4i-a10-crypto",
537 	  .data = &ss_a10_variant
538 	},
539 	{ .compatible = "allwinner,sun8i-a33-crypto",
540 	  .data = &ss_a33_variant
541 	},
542 	{}
543 };
544 MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table);
545 
546 static struct platform_driver sun4i_ss_driver = {
547 	.probe          = sun4i_ss_probe,
548 	.remove         = sun4i_ss_remove,
549 	.driver         = {
550 		.name           = "sun4i-ss",
551 		.pm		= &sun4i_ss_pm_ops,
552 		.of_match_table	= a20ss_crypto_of_match_table,
553 	},
554 };
555 
556 module_platform_driver(sun4i_ss_driver);
557 
558 MODULE_ALIAS("platform:sun4i-ss");
559 MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator");
560 MODULE_LICENSE("GPL");
561 MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>");
562