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
29static 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_flags = CRYPTO_ALG_TYPE_AHASH,
49				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
50				.cra_ctxsize = sizeof(struct sun4i_req_ctx),
51				.cra_module = THIS_MODULE,
52				.cra_type = &crypto_ahash_type,
53				.cra_init = sun4i_hash_crainit
54			}
55		}
56	}
57},
58{       .type = CRYPTO_ALG_TYPE_AHASH,
59	.mode = SS_OP_SHA1,
60	.alg.hash = {
61		.init = sun4i_hash_init,
62		.update = sun4i_hash_update,
63		.final = sun4i_hash_final,
64		.finup = sun4i_hash_finup,
65		.digest = sun4i_hash_digest,
66		.export = sun4i_hash_export_sha1,
67		.import = sun4i_hash_import_sha1,
68		.halg = {
69			.digestsize = SHA1_DIGEST_SIZE,
70			.statesize = sizeof(struct sha1_state),
71			.base = {
72				.cra_name = "sha1",
73				.cra_driver_name = "sha1-sun4i-ss",
74				.cra_priority = 300,
75				.cra_alignmask = 3,
76				.cra_flags = CRYPTO_ALG_TYPE_AHASH,
77				.cra_blocksize = SHA1_BLOCK_SIZE,
78				.cra_ctxsize = sizeof(struct sun4i_req_ctx),
79				.cra_module = THIS_MODULE,
80				.cra_type = &crypto_ahash_type,
81				.cra_init = sun4i_hash_crainit
82			}
83		}
84	}
85},
86{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
87	.alg.crypto = {
88		.cra_name = "cbc(aes)",
89		.cra_driver_name = "cbc-aes-sun4i-ss",
90		.cra_priority = 300,
91		.cra_blocksize = AES_BLOCK_SIZE,
92		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
93		.cra_ctxsize = sizeof(struct sun4i_tfm_ctx),
94		.cra_module = THIS_MODULE,
95		.cra_alignmask = 3,
96		.cra_type = &crypto_ablkcipher_type,
97		.cra_init = sun4i_ss_cipher_init,
98		.cra_ablkcipher = {
99			.min_keysize	= AES_MIN_KEY_SIZE,
100			.max_keysize	= AES_MAX_KEY_SIZE,
101			.ivsize		= AES_BLOCK_SIZE,
102			.setkey         = sun4i_ss_aes_setkey,
103			.encrypt        = sun4i_ss_cbc_aes_encrypt,
104			.decrypt        = sun4i_ss_cbc_aes_decrypt,
105		}
106	}
107},
108{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
109	.alg.crypto = {
110		.cra_name = "ecb(aes)",
111		.cra_driver_name = "ecb-aes-sun4i-ss",
112		.cra_priority = 300,
113		.cra_blocksize = AES_BLOCK_SIZE,
114		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
115		.cra_ctxsize = sizeof(struct sun4i_tfm_ctx),
116		.cra_module = THIS_MODULE,
117		.cra_alignmask = 3,
118		.cra_type = &crypto_ablkcipher_type,
119		.cra_init = sun4i_ss_cipher_init,
120		.cra_ablkcipher = {
121			.min_keysize	= AES_MIN_KEY_SIZE,
122			.max_keysize	= AES_MAX_KEY_SIZE,
123			.ivsize		= AES_BLOCK_SIZE,
124			.setkey         = sun4i_ss_aes_setkey,
125			.encrypt        = sun4i_ss_ecb_aes_encrypt,
126			.decrypt        = sun4i_ss_ecb_aes_decrypt,
127		}
128	}
129},
130{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
131	.alg.crypto = {
132		.cra_name = "cbc(des)",
133		.cra_driver_name = "cbc-des-sun4i-ss",
134		.cra_priority = 300,
135		.cra_blocksize = DES_BLOCK_SIZE,
136		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
137		.cra_ctxsize = sizeof(struct sun4i_req_ctx),
138		.cra_module = THIS_MODULE,
139		.cra_alignmask = 3,
140		.cra_type = &crypto_ablkcipher_type,
141		.cra_init = sun4i_ss_cipher_init,
142		.cra_u.ablkcipher = {
143			.min_keysize    = DES_KEY_SIZE,
144			.max_keysize    = DES_KEY_SIZE,
145			.ivsize         = DES_BLOCK_SIZE,
146			.setkey         = sun4i_ss_des_setkey,
147			.encrypt        = sun4i_ss_cbc_des_encrypt,
148			.decrypt        = sun4i_ss_cbc_des_decrypt,
149		}
150	}
151},
152{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
153	.alg.crypto = {
154		.cra_name = "ecb(des)",
155		.cra_driver_name = "ecb-des-sun4i-ss",
156		.cra_priority = 300,
157		.cra_blocksize = DES_BLOCK_SIZE,
158		.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
159		.cra_ctxsize = sizeof(struct sun4i_req_ctx),
160		.cra_module = THIS_MODULE,
161		.cra_alignmask = 3,
162		.cra_type = &crypto_ablkcipher_type,
163		.cra_init = sun4i_ss_cipher_init,
164		.cra_u.ablkcipher = {
165			.min_keysize    = DES_KEY_SIZE,
166			.max_keysize    = DES_KEY_SIZE,
167			.setkey         = sun4i_ss_des_setkey,
168			.encrypt        = sun4i_ss_ecb_des_encrypt,
169			.decrypt        = sun4i_ss_ecb_des_decrypt,
170		}
171	}
172},
173{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
174	.alg.crypto = {
175			.cra_name = "cbc(des3_ede)",
176			.cra_driver_name = "cbc-des3-sun4i-ss",
177			.cra_priority = 300,
178			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
179			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
180			.cra_ctxsize = sizeof(struct sun4i_req_ctx),
181			.cra_module = THIS_MODULE,
182			.cra_alignmask = 3,
183			.cra_type = &crypto_ablkcipher_type,
184			.cra_init = sun4i_ss_cipher_init,
185			.cra_u.ablkcipher = {
186				.min_keysize    = DES3_EDE_KEY_SIZE,
187				.max_keysize    = DES3_EDE_KEY_SIZE,
188				.ivsize         = DES3_EDE_BLOCK_SIZE,
189				.setkey         = sun4i_ss_des3_setkey,
190				.encrypt        = sun4i_ss_cbc_des3_encrypt,
191				.decrypt        = sun4i_ss_cbc_des3_decrypt,
192		}
193	}
194},
195{       .type = CRYPTO_ALG_TYPE_ABLKCIPHER,
196	.alg.crypto = {
197			.cra_name = "ecb(des3_ede)",
198			.cra_driver_name = "ecb-des3-sun4i-ss",
199			.cra_priority = 300,
200			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
201			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER,
202			.cra_ctxsize = sizeof(struct sun4i_req_ctx),
203			.cra_module = THIS_MODULE,
204			.cra_alignmask = 3,
205			.cra_type = &crypto_ablkcipher_type,
206			.cra_init = sun4i_ss_cipher_init,
207			.cra_u.ablkcipher = {
208				.min_keysize    = DES3_EDE_KEY_SIZE,
209				.max_keysize    = DES3_EDE_KEY_SIZE,
210				.ivsize         = DES3_EDE_BLOCK_SIZE,
211				.setkey         = sun4i_ss_des3_setkey,
212				.encrypt        = sun4i_ss_ecb_des3_encrypt,
213				.decrypt        = sun4i_ss_ecb_des3_decrypt,
214		}
215	}
216},
217};
218
219static int sun4i_ss_probe(struct platform_device *pdev)
220{
221	struct resource *res;
222	u32 v;
223	int err, i;
224	unsigned long cr;
225	const unsigned long cr_ahb = 24 * 1000 * 1000;
226	const unsigned long cr_mod = 150 * 1000 * 1000;
227	struct sun4i_ss_ctx *ss;
228
229	if (!pdev->dev.of_node)
230		return -ENODEV;
231
232	ss = devm_kzalloc(&pdev->dev, sizeof(*ss), GFP_KERNEL);
233	if (!ss)
234		return -ENOMEM;
235
236	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
237	ss->base = devm_ioremap_resource(&pdev->dev, res);
238	if (IS_ERR(ss->base)) {
239		dev_err(&pdev->dev, "Cannot request MMIO\n");
240		return PTR_ERR(ss->base);
241	}
242
243	ss->ssclk = devm_clk_get(&pdev->dev, "mod");
244	if (IS_ERR(ss->ssclk)) {
245		err = PTR_ERR(ss->ssclk);
246		dev_err(&pdev->dev, "Cannot get SS clock err=%d\n", err);
247		return err;
248	}
249	dev_dbg(&pdev->dev, "clock ss acquired\n");
250
251	ss->busclk = devm_clk_get(&pdev->dev, "ahb");
252	if (IS_ERR(ss->busclk)) {
253		err = PTR_ERR(ss->busclk);
254		dev_err(&pdev->dev, "Cannot get AHB SS clock err=%d\n", err);
255		return err;
256	}
257	dev_dbg(&pdev->dev, "clock ahb_ss acquired\n");
258
259	ss->reset = devm_reset_control_get_optional(&pdev->dev, "ahb");
260	if (IS_ERR(ss->reset)) {
261		if (PTR_ERR(ss->reset) == -EPROBE_DEFER)
262			return PTR_ERR(ss->reset);
263		dev_info(&pdev->dev, "no reset control found\n");
264		ss->reset = NULL;
265	}
266
267	/* Enable both clocks */
268	err = clk_prepare_enable(ss->busclk);
269	if (err != 0) {
270		dev_err(&pdev->dev, "Cannot prepare_enable busclk\n");
271		return err;
272	}
273	err = clk_prepare_enable(ss->ssclk);
274	if (err != 0) {
275		dev_err(&pdev->dev, "Cannot prepare_enable ssclk\n");
276		goto error_ssclk;
277	}
278
279	/*
280	 * Check that clock have the correct rates given in the datasheet
281	 * Try to set the clock to the maximum allowed
282	 */
283	err = clk_set_rate(ss->ssclk, cr_mod);
284	if (err != 0) {
285		dev_err(&pdev->dev, "Cannot set clock rate to ssclk\n");
286		goto error_clk;
287	}
288
289	/* Deassert reset if we have a reset control */
290	if (ss->reset) {
291		err = reset_control_deassert(ss->reset);
292		if (err) {
293			dev_err(&pdev->dev, "Cannot deassert reset control\n");
294			goto error_clk;
295		}
296	}
297
298	/*
299	 * The only impact on clocks below requirement are bad performance,
300	 * so do not print "errors"
301	 * warn on Overclocked clocks
302	 */
303	cr = clk_get_rate(ss->busclk);
304	if (cr >= cr_ahb)
305		dev_dbg(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
306			cr, cr / 1000000, cr_ahb);
307	else
308		dev_warn(&pdev->dev, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
309			 cr, cr / 1000000, cr_ahb);
310
311	cr = clk_get_rate(ss->ssclk);
312	if (cr <= cr_mod)
313		if (cr < cr_mod)
314			dev_warn(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
315				 cr, cr / 1000000, cr_mod);
316		else
317			dev_dbg(&pdev->dev, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
318				cr, cr / 1000000, cr_mod);
319	else
320		dev_warn(&pdev->dev, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n",
321			 cr, cr / 1000000, cr_mod);
322
323	/*
324	 * Datasheet named it "Die Bonding ID"
325	 * I expect to be a sort of Security System Revision number.
326	 * Since the A80 seems to have an other version of SS
327	 * this info could be useful
328	 */
329	writel(SS_ENABLED, ss->base + SS_CTL);
330	v = readl(ss->base + SS_CTL);
331	v >>= 16;
332	v &= 0x07;
333	dev_info(&pdev->dev, "Die ID %d\n", v);
334	writel(0, ss->base + SS_CTL);
335
336	ss->dev = &pdev->dev;
337
338	spin_lock_init(&ss->slock);
339
340	for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
341		ss_algs[i].ss = ss;
342		switch (ss_algs[i].type) {
343		case CRYPTO_ALG_TYPE_ABLKCIPHER:
344			err = crypto_register_alg(&ss_algs[i].alg.crypto);
345			if (err != 0) {
346				dev_err(ss->dev, "Fail to register %s\n",
347					ss_algs[i].alg.crypto.cra_name);
348				goto error_alg;
349			}
350			break;
351		case CRYPTO_ALG_TYPE_AHASH:
352			err = crypto_register_ahash(&ss_algs[i].alg.hash);
353			if (err != 0) {
354				dev_err(ss->dev, "Fail to register %s\n",
355					ss_algs[i].alg.hash.halg.base.cra_name);
356				goto error_alg;
357			}
358			break;
359		}
360	}
361	platform_set_drvdata(pdev, ss);
362	return 0;
363error_alg:
364	i--;
365	for (; i >= 0; i--) {
366		switch (ss_algs[i].type) {
367		case CRYPTO_ALG_TYPE_ABLKCIPHER:
368			crypto_unregister_alg(&ss_algs[i].alg.crypto);
369			break;
370		case CRYPTO_ALG_TYPE_AHASH:
371			crypto_unregister_ahash(&ss_algs[i].alg.hash);
372			break;
373		}
374	}
375	if (ss->reset)
376		reset_control_assert(ss->reset);
377error_clk:
378	clk_disable_unprepare(ss->ssclk);
379error_ssclk:
380	clk_disable_unprepare(ss->busclk);
381	return err;
382}
383
384static int sun4i_ss_remove(struct platform_device *pdev)
385{
386	int i;
387	struct sun4i_ss_ctx *ss = platform_get_drvdata(pdev);
388
389	for (i = 0; i < ARRAY_SIZE(ss_algs); i++) {
390		switch (ss_algs[i].type) {
391		case CRYPTO_ALG_TYPE_ABLKCIPHER:
392			crypto_unregister_alg(&ss_algs[i].alg.crypto);
393			break;
394		case CRYPTO_ALG_TYPE_AHASH:
395			crypto_unregister_ahash(&ss_algs[i].alg.hash);
396			break;
397		}
398	}
399
400	writel(0, ss->base + SS_CTL);
401	if (ss->reset)
402		reset_control_assert(ss->reset);
403	clk_disable_unprepare(ss->busclk);
404	clk_disable_unprepare(ss->ssclk);
405	return 0;
406}
407
408static const struct of_device_id a20ss_crypto_of_match_table[] = {
409	{ .compatible = "allwinner,sun4i-a10-crypto" },
410	{}
411};
412MODULE_DEVICE_TABLE(of, a20ss_crypto_of_match_table);
413
414static struct platform_driver sun4i_ss_driver = {
415	.probe          = sun4i_ss_probe,
416	.remove         = sun4i_ss_remove,
417	.driver         = {
418		.name           = "sun4i-ss",
419		.of_match_table	= a20ss_crypto_of_match_table,
420	},
421};
422
423module_platform_driver(sun4i_ss_driver);
424
425MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator");
426MODULE_LICENSE("GPL");
427MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>");
428