xref: /linux/drivers/crypto/allwinner/sun4i-ss/sun4i-ss-core.c (revision 48dea9a700c8728cc31a1dd44588b97578de86ee)
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>");
528