1 // SPDX-License-Identifier: GPL-2.0
3 * sun8i-ss-core.c - hardware cryptographic offloader for
4 * Allwinner A80/A83T SoC
6 * Copyright (C) 2015-2019 Corentin Labbe <clabbe.montjoie@gmail.com>
8 * Core file which registers crypto algorithms supported by the SecuritySystem
10 * You could find a link for the datasheet in Documentation/arm/sunxi/README
12 #include <linux/clk.h>
13 #include <linux/crypto.h>
14 #include <linux/delay.h>
15 #include <linux/dma-mapping.h>
16 #include <linux/interrupt.h>
18 #include <linux/irq.h>
19 #include <linux/module.h>
21 #include <linux/of_device.h>
22 #include <linux/platform_device.h>
23 #include <linux/pm_runtime.h>
24 #include <linux/reset.h>
25 #include <crypto/internal/skcipher.h>
29 static const struct ss_variant ss_a80_variant
= {
30 .alg_cipher
= { SS_ALG_AES
, SS_ALG_DES
, SS_ALG_3DES
,
32 .op_mode
= { SS_OP_ECB
, SS_OP_CBC
,
35 { "bus", 0, 300 * 1000 * 1000 },
36 { "mod", 0, 300 * 1000 * 1000 },
40 static const struct ss_variant ss_a83t_variant
= {
41 .alg_cipher
= { SS_ALG_AES
, SS_ALG_DES
, SS_ALG_3DES
,
43 .op_mode
= { SS_OP_ECB
, SS_OP_CBC
,
46 { "bus", 0, 300 * 1000 * 1000 },
47 { "mod", 0, 300 * 1000 * 1000 },
52 * sun8i_ss_get_engine_number() get the next channel slot
53 * This is a simple round-robin way of getting the next channel
55 int sun8i_ss_get_engine_number(struct sun8i_ss_dev
*ss
)
57 return atomic_inc_return(&ss
->flow
) % MAXFLOW
;
60 int sun8i_ss_run_task(struct sun8i_ss_dev
*ss
, struct sun8i_cipher_req_ctx
*rctx
,
63 int flow
= rctx
->flow
;
67 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG
68 ss
->flows
[flow
].stat_req
++;
71 /* choose between stream0/stream1 */
83 switch (rctx
->keylen
) {
85 v
|= SS_AES_128BITS
<< 7;
88 v
|= SS_AES_192BITS
<< 7;
91 v
|= SS_AES_256BITS
<< 7;
95 for (i
= 0; i
< MAX_SG
; i
++) {
96 if (!rctx
->t_dst
[i
].addr
)
99 mutex_lock(&ss
->mlock
);
100 writel(rctx
->p_key
, ss
->base
+ SS_KEY_ADR_REG
);
104 writel(rctx
->p_iv
, ss
->base
+ SS_IV_ADR_REG
);
107 if (rctx
->op_dir
== SS_ENCRYPTION
)
108 writel(rctx
->t_dst
[i
- 1].addr
+ rctx
->t_dst
[i
- 1].len
* 4 - rctx
->ivlen
, ss
->base
+ SS_IV_ADR_REG
);
110 writel(rctx
->t_src
[i
- 1].addr
+ rctx
->t_src
[i
- 1].len
* 4 - rctx
->ivlen
, ss
->base
+ SS_IV_ADR_REG
);
115 "Processing SG %d on flow %d %s ctl=%x %d to %d method=%x opmode=%x opdir=%x srclen=%d\n",
117 rctx
->t_src
[i
].len
, rctx
->t_dst
[i
].len
,
118 rctx
->method
, rctx
->op_mode
,
119 rctx
->op_dir
, rctx
->t_src
[i
].len
);
121 writel(rctx
->t_src
[i
].addr
, ss
->base
+ SS_SRC_ADR_REG
);
122 writel(rctx
->t_dst
[i
].addr
, ss
->base
+ SS_DST_ADR_REG
);
123 writel(rctx
->t_src
[i
].len
, ss
->base
+ SS_LEN_ADR_REG
);
125 reinit_completion(&ss
->flows
[flow
].complete
);
126 ss
->flows
[flow
].status
= 0;
129 writel(v
, ss
->base
+ SS_CTL_REG
);
130 mutex_unlock(&ss
->mlock
);
131 wait_for_completion_interruptible_timeout(&ss
->flows
[flow
].complete
,
132 msecs_to_jiffies(2000));
133 if (ss
->flows
[flow
].status
== 0) {
134 dev_err(ss
->dev
, "DMA timeout for %s\n", name
);
142 static irqreturn_t
ss_irq_handler(int irq
, void *data
)
144 struct sun8i_ss_dev
*ss
= (struct sun8i_ss_dev
*)data
;
148 p
= readl(ss
->base
+ SS_INT_STA_REG
);
149 for (flow
= 0; flow
< MAXFLOW
; flow
++) {
150 if (p
& (BIT(flow
))) {
151 writel(BIT(flow
), ss
->base
+ SS_INT_STA_REG
);
152 ss
->flows
[flow
].status
= 1;
153 complete(&ss
->flows
[flow
].complete
);
160 static struct sun8i_ss_alg_template ss_algs
[] = {
162 .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
163 .ss_algo_id
= SS_ID_CIPHER_AES
,
164 .ss_blockmode
= SS_ID_OP_CBC
,
167 .cra_name
= "cbc(aes)",
168 .cra_driver_name
= "cbc-aes-sun8i-ss",
170 .cra_blocksize
= AES_BLOCK_SIZE
,
171 .cra_flags
= CRYPTO_ALG_TYPE_SKCIPHER
|
172 CRYPTO_ALG_ASYNC
| CRYPTO_ALG_NEED_FALLBACK
,
173 .cra_ctxsize
= sizeof(struct sun8i_cipher_tfm_ctx
),
174 .cra_module
= THIS_MODULE
,
175 .cra_alignmask
= 0xf,
176 .cra_init
= sun8i_ss_cipher_init
,
177 .cra_exit
= sun8i_ss_cipher_exit
,
179 .min_keysize
= AES_MIN_KEY_SIZE
,
180 .max_keysize
= AES_MAX_KEY_SIZE
,
181 .ivsize
= AES_BLOCK_SIZE
,
182 .setkey
= sun8i_ss_aes_setkey
,
183 .encrypt
= sun8i_ss_skencrypt
,
184 .decrypt
= sun8i_ss_skdecrypt
,
188 .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
189 .ss_algo_id
= SS_ID_CIPHER_AES
,
190 .ss_blockmode
= SS_ID_OP_ECB
,
193 .cra_name
= "ecb(aes)",
194 .cra_driver_name
= "ecb-aes-sun8i-ss",
196 .cra_blocksize
= AES_BLOCK_SIZE
,
197 .cra_flags
= CRYPTO_ALG_TYPE_SKCIPHER
|
198 CRYPTO_ALG_ASYNC
| CRYPTO_ALG_NEED_FALLBACK
,
199 .cra_ctxsize
= sizeof(struct sun8i_cipher_tfm_ctx
),
200 .cra_module
= THIS_MODULE
,
201 .cra_alignmask
= 0xf,
202 .cra_init
= sun8i_ss_cipher_init
,
203 .cra_exit
= sun8i_ss_cipher_exit
,
205 .min_keysize
= AES_MIN_KEY_SIZE
,
206 .max_keysize
= AES_MAX_KEY_SIZE
,
207 .setkey
= sun8i_ss_aes_setkey
,
208 .encrypt
= sun8i_ss_skencrypt
,
209 .decrypt
= sun8i_ss_skdecrypt
,
213 .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
214 .ss_algo_id
= SS_ID_CIPHER_DES3
,
215 .ss_blockmode
= SS_ID_OP_CBC
,
218 .cra_name
= "cbc(des3_ede)",
219 .cra_driver_name
= "cbc-des3-sun8i-ss",
221 .cra_blocksize
= DES3_EDE_BLOCK_SIZE
,
222 .cra_flags
= CRYPTO_ALG_TYPE_SKCIPHER
|
223 CRYPTO_ALG_ASYNC
| CRYPTO_ALG_NEED_FALLBACK
,
224 .cra_ctxsize
= sizeof(struct sun8i_cipher_tfm_ctx
),
225 .cra_module
= THIS_MODULE
,
226 .cra_alignmask
= 0xf,
227 .cra_init
= sun8i_ss_cipher_init
,
228 .cra_exit
= sun8i_ss_cipher_exit
,
230 .min_keysize
= DES3_EDE_KEY_SIZE
,
231 .max_keysize
= DES3_EDE_KEY_SIZE
,
232 .ivsize
= DES3_EDE_BLOCK_SIZE
,
233 .setkey
= sun8i_ss_des3_setkey
,
234 .encrypt
= sun8i_ss_skencrypt
,
235 .decrypt
= sun8i_ss_skdecrypt
,
239 .type
= CRYPTO_ALG_TYPE_SKCIPHER
,
240 .ss_algo_id
= SS_ID_CIPHER_DES3
,
241 .ss_blockmode
= SS_ID_OP_ECB
,
244 .cra_name
= "ecb(des3_ede)",
245 .cra_driver_name
= "ecb-des3-sun8i-ss",
247 .cra_blocksize
= DES3_EDE_BLOCK_SIZE
,
248 .cra_flags
= CRYPTO_ALG_TYPE_SKCIPHER
|
249 CRYPTO_ALG_ASYNC
| CRYPTO_ALG_NEED_FALLBACK
,
250 .cra_ctxsize
= sizeof(struct sun8i_cipher_tfm_ctx
),
251 .cra_module
= THIS_MODULE
,
252 .cra_alignmask
= 0xf,
253 .cra_init
= sun8i_ss_cipher_init
,
254 .cra_exit
= sun8i_ss_cipher_exit
,
256 .min_keysize
= DES3_EDE_KEY_SIZE
,
257 .max_keysize
= DES3_EDE_KEY_SIZE
,
258 .setkey
= sun8i_ss_des3_setkey
,
259 .encrypt
= sun8i_ss_skencrypt
,
260 .decrypt
= sun8i_ss_skdecrypt
,
265 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG
266 static int sun8i_ss_dbgfs_read(struct seq_file
*seq
, void *v
)
268 struct sun8i_ss_dev
*ss
= seq
->private;
271 for (i
= 0; i
< MAXFLOW
; i
++)
272 seq_printf(seq
, "Channel %d: nreq %lu\n", i
, ss
->flows
[i
].stat_req
);
274 for (i
= 0; i
< ARRAY_SIZE(ss_algs
); i
++) {
277 switch (ss_algs
[i
].type
) {
278 case CRYPTO_ALG_TYPE_SKCIPHER
:
279 seq_printf(seq
, "%s %s %lu %lu\n",
280 ss_algs
[i
].alg
.skcipher
.base
.cra_driver_name
,
281 ss_algs
[i
].alg
.skcipher
.base
.cra_name
,
282 ss_algs
[i
].stat_req
, ss_algs
[i
].stat_fb
);
289 static int sun8i_ss_dbgfs_open(struct inode
*inode
, struct file
*file
)
291 return single_open(file
, sun8i_ss_dbgfs_read
, inode
->i_private
);
294 static const struct file_operations sun8i_ss_debugfs_fops
= {
295 .owner
= THIS_MODULE
,
296 .open
= sun8i_ss_dbgfs_open
,
299 .release
= single_release
,
303 static void sun8i_ss_free_flows(struct sun8i_ss_dev
*ss
, int i
)
306 crypto_engine_exit(ss
->flows
[i
].engine
);
312 * Allocate the flow list structure
314 static int allocate_flows(struct sun8i_ss_dev
*ss
)
318 ss
->flows
= devm_kcalloc(ss
->dev
, MAXFLOW
, sizeof(struct sun8i_ss_flow
),
323 for (i
= 0; i
< MAXFLOW
; i
++) {
324 init_completion(&ss
->flows
[i
].complete
);
326 ss
->flows
[i
].engine
= crypto_engine_alloc_init(ss
->dev
, true);
327 if (!ss
->flows
[i
].engine
) {
328 dev_err(ss
->dev
, "Cannot allocate engine\n");
333 err
= crypto_engine_start(ss
->flows
[i
].engine
);
335 dev_err(ss
->dev
, "Cannot start engine\n");
341 sun8i_ss_free_flows(ss
, i
);
346 * Power management strategy: The device is suspended unless a TFM exists for
347 * one of the algorithms proposed by this driver.
349 static int sun8i_ss_pm_suspend(struct device
*dev
)
351 struct sun8i_ss_dev
*ss
= dev_get_drvdata(dev
);
354 reset_control_assert(ss
->reset
);
355 for (i
= 0; i
< SS_MAX_CLOCKS
; i
++)
356 clk_disable_unprepare(ss
->ssclks
[i
]);
360 static int sun8i_ss_pm_resume(struct device
*dev
)
362 struct sun8i_ss_dev
*ss
= dev_get_drvdata(dev
);
365 for (i
= 0; i
< SS_MAX_CLOCKS
; i
++) {
366 if (!ss
->variant
->ss_clks
[i
].name
)
368 err
= clk_prepare_enable(ss
->ssclks
[i
]);
370 dev_err(ss
->dev
, "Cannot prepare_enable %s\n",
371 ss
->variant
->ss_clks
[i
].name
);
375 err
= reset_control_deassert(ss
->reset
);
377 dev_err(ss
->dev
, "Cannot deassert reset control\n");
380 /* enable interrupts for all flows */
381 writel(BIT(0) | BIT(1), ss
->base
+ SS_INT_CTL_REG
);
385 sun8i_ss_pm_suspend(dev
);
389 static const struct dev_pm_ops sun8i_ss_pm_ops
= {
390 SET_RUNTIME_PM_OPS(sun8i_ss_pm_suspend
, sun8i_ss_pm_resume
, NULL
)
393 static int sun8i_ss_pm_init(struct sun8i_ss_dev
*ss
)
397 pm_runtime_use_autosuspend(ss
->dev
);
398 pm_runtime_set_autosuspend_delay(ss
->dev
, 2000);
400 err
= pm_runtime_set_suspended(ss
->dev
);
403 pm_runtime_enable(ss
->dev
);
407 static void sun8i_ss_pm_exit(struct sun8i_ss_dev
*ss
)
409 pm_runtime_disable(ss
->dev
);
412 static int sun8i_ss_register_algs(struct sun8i_ss_dev
*ss
)
414 int ss_method
, err
, id
, i
;
416 for (i
= 0; i
< ARRAY_SIZE(ss_algs
); i
++) {
418 switch (ss_algs
[i
].type
) {
419 case CRYPTO_ALG_TYPE_SKCIPHER
:
420 id
= ss_algs
[i
].ss_algo_id
;
421 ss_method
= ss
->variant
->alg_cipher
[id
];
422 if (ss_method
== SS_ID_NOTSUPP
) {
424 "DEBUG: Algo of %s not supported\n",
425 ss_algs
[i
].alg
.skcipher
.base
.cra_name
);
426 ss_algs
[i
].ss
= NULL
;
429 id
= ss_algs
[i
].ss_blockmode
;
430 ss_method
= ss
->variant
->op_mode
[id
];
431 if (ss_method
== SS_ID_NOTSUPP
) {
432 dev_info(ss
->dev
, "DEBUG: Blockmode of %s not supported\n",
433 ss_algs
[i
].alg
.skcipher
.base
.cra_name
);
434 ss_algs
[i
].ss
= NULL
;
437 dev_info(ss
->dev
, "DEBUG: Register %s\n",
438 ss_algs
[i
].alg
.skcipher
.base
.cra_name
);
439 err
= crypto_register_skcipher(&ss_algs
[i
].alg
.skcipher
);
441 dev_err(ss
->dev
, "Fail to register %s\n",
442 ss_algs
[i
].alg
.skcipher
.base
.cra_name
);
443 ss_algs
[i
].ss
= NULL
;
448 ss_algs
[i
].ss
= NULL
;
449 dev_err(ss
->dev
, "ERROR: tried to register an unknown algo\n");
455 static void sun8i_ss_unregister_algs(struct sun8i_ss_dev
*ss
)
459 for (i
= 0; i
< ARRAY_SIZE(ss_algs
); i
++) {
462 switch (ss_algs
[i
].type
) {
463 case CRYPTO_ALG_TYPE_SKCIPHER
:
464 dev_info(ss
->dev
, "Unregister %d %s\n", i
,
465 ss_algs
[i
].alg
.skcipher
.base
.cra_name
);
466 crypto_unregister_skcipher(&ss_algs
[i
].alg
.skcipher
);
472 static int sun8i_ss_get_clks(struct sun8i_ss_dev
*ss
)
477 for (i
= 0; i
< SS_MAX_CLOCKS
; i
++) {
478 if (!ss
->variant
->ss_clks
[i
].name
)
480 ss
->ssclks
[i
] = devm_clk_get(ss
->dev
, ss
->variant
->ss_clks
[i
].name
);
481 if (IS_ERR(ss
->ssclks
[i
])) {
482 err
= PTR_ERR(ss
->ssclks
[i
]);
483 dev_err(ss
->dev
, "Cannot get %s SS clock err=%d\n",
484 ss
->variant
->ss_clks
[i
].name
, err
);
487 cr
= clk_get_rate(ss
->ssclks
[i
]);
490 if (ss
->variant
->ss_clks
[i
].freq
> 0 &&
491 cr
!= ss
->variant
->ss_clks
[i
].freq
) {
492 dev_info(ss
->dev
, "Set %s clock to %lu (%lu Mhz) from %lu (%lu Mhz)\n",
493 ss
->variant
->ss_clks
[i
].name
,
494 ss
->variant
->ss_clks
[i
].freq
,
495 ss
->variant
->ss_clks
[i
].freq
/ 1000000,
497 err
= clk_set_rate(ss
->ssclks
[i
], ss
->variant
->ss_clks
[i
].freq
);
499 dev_err(ss
->dev
, "Fail to set %s clk speed to %lu hz\n",
500 ss
->variant
->ss_clks
[i
].name
,
501 ss
->variant
->ss_clks
[i
].freq
);
503 if (ss
->variant
->ss_clks
[i
].max_freq
> 0 &&
504 cr
> ss
->variant
->ss_clks
[i
].max_freq
)
505 dev_warn(ss
->dev
, "Frequency for %s (%lu hz) is higher than datasheet's recommendation (%lu hz)",
506 ss
->variant
->ss_clks
[i
].name
, cr
,
507 ss
->variant
->ss_clks
[i
].max_freq
);
512 static int sun8i_ss_probe(struct platform_device
*pdev
)
514 struct sun8i_ss_dev
*ss
;
518 ss
= devm_kzalloc(&pdev
->dev
, sizeof(*ss
), GFP_KERNEL
);
522 ss
->dev
= &pdev
->dev
;
523 platform_set_drvdata(pdev
, ss
);
525 ss
->variant
= of_device_get_match_data(&pdev
->dev
);
527 dev_err(&pdev
->dev
, "Missing Crypto Engine variant\n");
531 ss
->base
= devm_platform_ioremap_resource(pdev
, 0);
532 if (IS_ERR(ss
->base
))
533 return PTR_ERR(ss
->base
);
535 err
= sun8i_ss_get_clks(ss
);
539 irq
= platform_get_irq(pdev
, 0);
541 dev_err(ss
->dev
, "Cannot get SecuritySystem IRQ\n");
545 ss
->reset
= devm_reset_control_get(&pdev
->dev
, NULL
);
546 if (IS_ERR(ss
->reset
)) {
547 if (PTR_ERR(ss
->reset
) == -EPROBE_DEFER
)
548 return PTR_ERR(ss
->reset
);
549 dev_err(&pdev
->dev
, "No reset control found\n");
550 return PTR_ERR(ss
->reset
);
553 mutex_init(&ss
->mlock
);
555 err
= allocate_flows(ss
);
559 err
= sun8i_ss_pm_init(ss
);
563 err
= devm_request_irq(&pdev
->dev
, irq
, ss_irq_handler
, 0, "sun8i-ss", ss
);
565 dev_err(ss
->dev
, "Cannot request SecuritySystem IRQ (err=%d)\n", err
);
569 err
= sun8i_ss_register_algs(ss
);
573 err
= pm_runtime_get_sync(ss
->dev
);
577 v
= readl(ss
->base
+ SS_CTL_REG
);
578 v
>>= SS_DIE_ID_SHIFT
;
580 dev_info(&pdev
->dev
, "Security System Die ID %x\n", v
);
582 pm_runtime_put_sync(ss
->dev
);
584 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG
585 /* Ignore error of debugfs */
586 ss
->dbgfs_dir
= debugfs_create_dir("sun8i-ss", NULL
);
587 ss
->dbgfs_stats
= debugfs_create_file("stats", 0444,
589 &sun8i_ss_debugfs_fops
);
594 sun8i_ss_unregister_algs(ss
);
596 sun8i_ss_pm_exit(ss
);
598 sun8i_ss_free_flows(ss
, MAXFLOW
- 1);
602 static int sun8i_ss_remove(struct platform_device
*pdev
)
604 struct sun8i_ss_dev
*ss
= platform_get_drvdata(pdev
);
606 sun8i_ss_unregister_algs(ss
);
608 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG
609 debugfs_remove_recursive(ss
->dbgfs_dir
);
612 sun8i_ss_free_flows(ss
, MAXFLOW
- 1);
614 sun8i_ss_pm_exit(ss
);
619 static const struct of_device_id sun8i_ss_crypto_of_match_table
[] = {
620 { .compatible
= "allwinner,sun8i-a83t-crypto",
621 .data
= &ss_a83t_variant
},
622 { .compatible
= "allwinner,sun9i-a80-crypto",
623 .data
= &ss_a80_variant
},
626 MODULE_DEVICE_TABLE(of
, sun8i_ss_crypto_of_match_table
);
628 static struct platform_driver sun8i_ss_driver
= {
629 .probe
= sun8i_ss_probe
,
630 .remove
= sun8i_ss_remove
,
633 .pm
= &sun8i_ss_pm_ops
,
634 .of_match_table
= sun8i_ss_crypto_of_match_table
,
638 module_platform_driver(sun8i_ss_driver
);
640 MODULE_DESCRIPTION("Allwinner SecuritySystem cryptographic offloader");
641 MODULE_LICENSE("GPL");
642 MODULE_AUTHOR("Corentin Labbe <clabbe.montjoie@gmail.com>");