1 // SPDX-License-Identifier: GPL-2.0
3 * sun8i-ss-prng.c - hardware cryptographic offloader for
4 * Allwinner A80/A83T SoC
6 * Copyright (C) 2015-2020 Corentin Labbe <clabbe@baylibre.com>
8 * This file handle the PRNG found in the SS
10 * You could find a link for the datasheet in Documentation/arm/sunxi.rst
13 #include <linux/dma-mapping.h>
14 #include <linux/pm_runtime.h>
15 #include <crypto/internal/rng.h>
17 int sun8i_ss_prng_seed(struct crypto_rng
*tfm
, const u8
*seed
,
20 struct sun8i_ss_rng_tfm_ctx
*ctx
= crypto_rng_ctx(tfm
);
22 if (ctx
->seed
&& ctx
->slen
!= slen
) {
23 memzero_explicit(ctx
->seed
, ctx
->slen
);
29 ctx
->seed
= kmalloc(slen
, GFP_KERNEL
| GFP_DMA
);
33 memcpy(ctx
->seed
, seed
, slen
);
39 int sun8i_ss_prng_init(struct crypto_tfm
*tfm
)
41 struct sun8i_ss_rng_tfm_ctx
*ctx
= crypto_tfm_ctx(tfm
);
43 memset(ctx
, 0, sizeof(struct sun8i_ss_rng_tfm_ctx
));
47 void sun8i_ss_prng_exit(struct crypto_tfm
*tfm
)
49 struct sun8i_ss_rng_tfm_ctx
*ctx
= crypto_tfm_ctx(tfm
);
51 memzero_explicit(ctx
->seed
, ctx
->slen
);
57 int sun8i_ss_prng_generate(struct crypto_rng
*tfm
, const u8
*src
,
58 unsigned int slen
, u8
*dst
, unsigned int dlen
)
60 struct sun8i_ss_rng_tfm_ctx
*ctx
= crypto_rng_ctx(tfm
);
61 struct rng_alg
*alg
= crypto_rng_alg(tfm
);
62 struct sun8i_ss_alg_template
*algt
;
63 struct sun8i_ss_dev
*ss
;
64 dma_addr_t dma_iv
, dma_dst
;
71 algt
= container_of(alg
, struct sun8i_ss_alg_template
, alg
.rng
);
75 dev_err(ss
->dev
, "The PRNG is not seeded\n");
79 /* The SS does not give an updated seed, so we need to get a new one.
80 * So we will ask for an extra PRNG_SEED_SIZE data.
81 * We want dlen + seedsize rounded up to a multiple of PRNG_DATA_SIZE
83 todo
= dlen
+ PRNG_SEED_SIZE
+ PRNG_DATA_SIZE
;
84 todo
-= todo
% PRNG_DATA_SIZE
;
86 d
= kzalloc(todo
, GFP_KERNEL
| GFP_DMA
);
90 flow
= sun8i_ss_get_engine_number(ss
);
92 #ifdef CONFIG_CRYPTO_DEV_SUN8I_SS_DEBUG
94 algt
->stat_bytes
+= todo
;
97 v
= SS_ALG_PRNG
| SS_PRNG_CONTINUE
| SS_START
;
103 dma_iv
= dma_map_single(ss
->dev
, ctx
->seed
, ctx
->slen
, DMA_TO_DEVICE
);
104 if (dma_mapping_error(ss
->dev
, dma_iv
)) {
105 dev_err(ss
->dev
, "Cannot DMA MAP IV\n");
109 dma_dst
= dma_map_single(ss
->dev
, d
, todo
, DMA_FROM_DEVICE
);
110 if (dma_mapping_error(ss
->dev
, dma_dst
)) {
111 dev_err(ss
->dev
, "Cannot DMA MAP DST\n");
116 err
= pm_runtime_get_sync(ss
->dev
);
118 pm_runtime_put_noidle(ss
->dev
);
123 mutex_lock(&ss
->mlock
);
124 writel(dma_iv
, ss
->base
+ SS_IV_ADR_REG
);
125 /* the PRNG act badly (failing rngtest) without SS_KEY_ADR_REG set */
126 writel(dma_iv
, ss
->base
+ SS_KEY_ADR_REG
);
127 writel(dma_dst
, ss
->base
+ SS_DST_ADR_REG
);
128 writel(todo
/ 4, ss
->base
+ SS_LEN_ADR_REG
);
130 reinit_completion(&ss
->flows
[flow
].complete
);
131 ss
->flows
[flow
].status
= 0;
132 /* Be sure all data is written before enabling the task */
135 writel(v
, ss
->base
+ SS_CTL_REG
);
137 wait_for_completion_interruptible_timeout(&ss
->flows
[flow
].complete
,
138 msecs_to_jiffies(todo
));
139 if (ss
->flows
[flow
].status
== 0) {
140 dev_err(ss
->dev
, "DMA timeout for PRNG (size=%u)\n", todo
);
143 /* Since cipher and hash use the linux/cryptoengine and that we have
144 * a cryptoengine per flow, we are sure that they will issue only one
146 * Since the cryptoengine wait for completion before submitting a new
147 * one, the mlock could be left just after the final writel.
148 * But cryptoengine cannot handle crypto_rng, so we need to be sure
149 * nothing will use our flow.
150 * The easiest way is to grab mlock until the hardware end our requests.
151 * We could have used a per flow lock, but this would increase
153 * The drawback is that no request could be handled for the other flow.
155 mutex_unlock(&ss
->mlock
);
157 pm_runtime_put(ss
->dev
);
160 dma_unmap_single(ss
->dev
, dma_dst
, todo
, DMA_FROM_DEVICE
);
162 dma_unmap_single(ss
->dev
, dma_iv
, ctx
->slen
, DMA_TO_DEVICE
);
165 memcpy(dst
, d
, dlen
);
167 memcpy(ctx
->seed
, d
+ dlen
, ctx
->slen
);
169 memzero_explicit(d
, todo
);