2 * sun4i-ss-core.c - hardware cryptographic accelerator for Allwinner A20 SoC
4 * Copyright (C) 2013-2015 Corentin LABBE <clabbe.montjoie@gmail.com>
6 * Core file which registers crypto algorithms supported by the SS.
8 * You could find a link for the datasheet in Documentation/arm/sunxi/README
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.
15 #include <linux/clk.h>
16 #include <linux/crypto.h>
18 #include <linux/module.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>
29 static struct sun4i_ss_alg_template ss_algs
[] = {
30 { .type
= CRYPTO_ALG_TYPE_AHASH
,
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
,
41 .digestsize
= MD5_DIGEST_SIZE
,
42 .statesize
= sizeof(struct md5_state
),
45 .cra_driver_name
= "md5-sun4i-ss",
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
56 { .type
= CRYPTO_ALG_TYPE_AHASH
,
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
,
67 .digestsize
= SHA1_DIGEST_SIZE
,
68 .statesize
= sizeof(struct sha1_state
),
71 .cra_driver_name
= "sha1-sun4i-ss",
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
82 { .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
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
,
91 .cra_name
= "cbc(aes)",
92 .cra_driver_name
= "cbc-aes-sun4i-ss",
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
,
99 .cra_init
= sun4i_ss_cipher_init
,
103 { .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
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
,
112 .cra_name
= "ecb(aes)",
113 .cra_driver_name
= "ecb-aes-sun4i-ss",
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
,
120 .cra_init
= sun4i_ss_cipher_init
,
124 { .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
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
,
133 .cra_name
= "cbc(des)",
134 .cra_driver_name
= "cbc-des-sun4i-ss",
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
,
141 .cra_init
= sun4i_ss_cipher_init
,
145 { .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
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
,
153 .cra_name
= "ecb(des)",
154 .cra_driver_name
= "ecb-des-sun4i-ss",
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
,
161 .cra_init
= sun4i_ss_cipher_init
,
165 { .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
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
,
174 .cra_name
= "cbc(des3_ede)",
175 .cra_driver_name
= "cbc-des3-sun4i-ss",
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
,
182 .cra_init
= sun4i_ss_cipher_init
,
186 { .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
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
,
195 .cra_name
= "ecb(des3_ede)",
196 .cra_driver_name
= "ecb-des3-sun4i-ss",
198 .cra_blocksize
= DES3_EDE_BLOCK_SIZE
,
199 .cra_ctxsize
= sizeof(struct sun4i_req_ctx
),
200 .cra_module
= THIS_MODULE
,
202 .cra_init
= sun4i_ss_cipher_init
,
206 #ifdef CONFIG_CRYPTO_DEV_SUN4I_SS_PRNG
208 .type
= CRYPTO_ALG_TYPE_RNG
,
211 .cra_name
= "stdrng",
212 .cra_driver_name
= "sun4i_ss_rng",
215 .cra_module
= THIS_MODULE
,
217 .generate
= sun4i_ss_prng_generate
,
218 .seed
= sun4i_ss_prng_seed
,
219 .seedsize
= SS_SEED_LEN
/ BITS_PER_BYTE
,
225 static int sun4i_ss_probe(struct platform_device
*pdev
)
227 struct resource
*res
;
231 const unsigned long cr_ahb
= 24 * 1000 * 1000;
232 const unsigned long cr_mod
= 150 * 1000 * 1000;
233 struct sun4i_ss_ctx
*ss
;
235 if (!pdev
->dev
.of_node
)
238 ss
= devm_kzalloc(&pdev
->dev
, sizeof(*ss
), GFP_KERNEL
);
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
);
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
);
255 dev_dbg(&pdev
->dev
, "clock ss acquired\n");
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
);
263 dev_dbg(&pdev
->dev
, "clock ahb_ss acquired\n");
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");
273 /* Enable both clocks */
274 err
= clk_prepare_enable(ss
->busclk
);
276 dev_err(&pdev
->dev
, "Cannot prepare_enable busclk\n");
279 err
= clk_prepare_enable(ss
->ssclk
);
281 dev_err(&pdev
->dev
, "Cannot prepare_enable ssclk\n");
286 * Check that clock have the correct rates given in the datasheet
287 * Try to set the clock to the maximum allowed
289 err
= clk_set_rate(ss
->ssclk
, cr_mod
);
291 dev_err(&pdev
->dev
, "Cannot set clock rate to ssclk\n");
295 /* Deassert reset if we have a reset control */
297 err
= reset_control_deassert(ss
->reset
);
299 dev_err(&pdev
->dev
, "Cannot deassert reset control\n");
305 * The only impact on clocks below requirement are bad performance,
306 * so do not print "errors"
307 * warn on Overclocked clocks
309 cr
= clk_get_rate(ss
->busclk
);
311 dev_dbg(&pdev
->dev
, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
312 cr
, cr
/ 1000000, cr_ahb
);
314 dev_warn(&pdev
->dev
, "Clock bus %lu (%lu MHz) (must be >= %lu)\n",
315 cr
, cr
/ 1000000, cr_ahb
);
317 cr
= clk_get_rate(ss
->ssclk
);
320 dev_warn(&pdev
->dev
, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
321 cr
, cr
/ 1000000, cr_mod
);
323 dev_dbg(&pdev
->dev
, "Clock ss %lu (%lu MHz) (must be <= %lu)\n",
324 cr
, cr
/ 1000000, cr_mod
);
326 dev_warn(&pdev
->dev
, "Clock ss is at %lu (%lu MHz) (must be <= %lu)\n",
327 cr
, cr
/ 1000000, cr_mod
);
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
335 writel(SS_ENABLED
, ss
->base
+ SS_CTL
);
336 v
= readl(ss
->base
+ SS_CTL
);
339 dev_info(&pdev
->dev
, "Die ID %d\n", v
);
340 writel(0, ss
->base
+ SS_CTL
);
342 ss
->dev
= &pdev
->dev
;
344 spin_lock_init(&ss
->slock
);
346 for (i
= 0; i
< ARRAY_SIZE(ss_algs
); i
++) {
348 switch (ss_algs
[i
].type
) {
349 case CRYPTO_ALG_TYPE_SKCIPHER
:
350 err
= crypto_register_skcipher(&ss_algs
[i
].alg
.crypto
);
352 dev_err(ss
->dev
, "Fail to register %s\n",
353 ss_algs
[i
].alg
.crypto
.base
.cra_name
);
357 case CRYPTO_ALG_TYPE_AHASH
:
358 err
= crypto_register_ahash(&ss_algs
[i
].alg
.hash
);
360 dev_err(ss
->dev
, "Fail to register %s\n",
361 ss_algs
[i
].alg
.hash
.halg
.base
.cra_name
);
365 case CRYPTO_ALG_TYPE_RNG
:
366 err
= crypto_register_rng(&ss_algs
[i
].alg
.rng
);
368 dev_err(ss
->dev
, "Fail to register %s\n",
369 ss_algs
[i
].alg
.rng
.base
.cra_name
);
374 platform_set_drvdata(pdev
, ss
);
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
);
383 case CRYPTO_ALG_TYPE_AHASH
:
384 crypto_unregister_ahash(&ss_algs
[i
].alg
.hash
);
386 case CRYPTO_ALG_TYPE_RNG
:
387 crypto_unregister_rng(&ss_algs
[i
].alg
.rng
);
392 reset_control_assert(ss
->reset
);
394 clk_disable_unprepare(ss
->ssclk
);
396 clk_disable_unprepare(ss
->busclk
);
400 static int sun4i_ss_remove(struct platform_device
*pdev
)
403 struct sun4i_ss_ctx
*ss
= platform_get_drvdata(pdev
);
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
);
410 case CRYPTO_ALG_TYPE_AHASH
:
411 crypto_unregister_ahash(&ss_algs
[i
].alg
.hash
);
413 case CRYPTO_ALG_TYPE_RNG
:
414 crypto_unregister_rng(&ss_algs
[i
].alg
.rng
);
419 writel(0, ss
->base
+ SS_CTL
);
421 reset_control_assert(ss
->reset
);
422 clk_disable_unprepare(ss
->busclk
);
423 clk_disable_unprepare(ss
->ssclk
);
427 static const struct of_device_id a20ss_crypto_of_match_table
[] = {
428 { .compatible
= "allwinner,sun4i-a10-crypto" },
431 MODULE_DEVICE_TABLE(of
, a20ss_crypto_of_match_table
);
433 static struct platform_driver sun4i_ss_driver
= {
434 .probe
= sun4i_ss_probe
,
435 .remove
= sun4i_ss_remove
,
438 .of_match_table
= a20ss_crypto_of_match_table
,
442 module_platform_driver(sun4i_ss_driver
);
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>");