xref: /rk3399_rockchip-uboot/drivers/crypto/rockchip/crypto_v1.c (revision 258d2dcb26879538abc00fc64a8a34c45c046465)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <common.h>
7 #include <clk.h>
8 #include <crypto.h>
9 #include <dm.h>
10 #include <rockchip/crypto_hash_cache.h>
11 #include <rockchip/crypto_v1.h>
12 #include <asm/io.h>
13 #include <asm/arch/hardware.h>
14 #include <asm/arch/clock.h>
15 
16 #define CRYPTO_V1_DEFAULT_RATE		100000000
17 /* crypto timeout 500ms, must support more than 32M data per times*/
18 #define HASH_UPDATE_LIMIT	(32 * 1024 * 1024)
19 #define RK_CRYPTO_TIME_OUT	500000
20 
21 #define LLI_ADDR_ALIGIN_SIZE	8
22 #define DATA_ADDR_ALIGIN_SIZE	8
23 #define DATA_LEN_ALIGIN_SIZE	64
24 
25 struct rockchip_crypto_priv {
26 	struct crypto_hash_cache	*hash_cache;
27 	struct rk_crypto_reg *reg;
28 	struct clk clk;
29 	sha_context *ctx;
30 	u32 frequency;
31 	char *clocks;
32 	u32 nclocks;
33 	u32 length;
34 };
35 
36 static u32 rockchip_crypto_capability(struct udevice *dev)
37 {
38 	return CRYPTO_MD5 |
39 	       CRYPTO_SHA1 |
40 	       CRYPTO_SHA256 |
41 	       CRYPTO_RSA512 |
42 	       CRYPTO_RSA1024 |
43 	       CRYPTO_RSA2048;
44 }
45 
46 static int rk_hash_direct_calc(void *hw_data, const u8 *data,
47 			       u32 data_len, u8 *started_flag, u8 is_last)
48 {
49 	struct rockchip_crypto_priv *priv = hw_data;
50 	struct rk_crypto_reg *reg = priv->reg;
51 
52 	if (!data_len)
53 		return -EINVAL;
54 
55 	/* Must flush dcache before crypto DMA fetch data region */
56 	crypto_flush_cacheline((ulong)data, data_len);
57 
58 	/* Hash Done Interrupt */
59 	writel(HASH_DONE_INT, &reg->crypto_intsts);
60 
61 	/* Set data base and length */
62 	writel((u32)(ulong)data, &reg->crypto_hrdmas);
63 	writel((data_len + 3) >> 2, &reg->crypto_hrdmal);
64 
65 	/* Write 1 to start. When finishes, the core will clear it */
66 	rk_setreg(&reg->crypto_ctrl, HASH_START);
67 
68 	/* Wait last complete */
69 	do {} while (readl(&reg->crypto_ctrl) & HASH_START);
70 
71 	priv->length += data_len;
72 
73 	return 0;
74 }
75 
76 static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx)
77 {
78 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
79 	struct rk_crypto_reg *reg = priv->reg;
80 	u32 val;
81 
82 	if (!ctx)
83 		return -EINVAL;
84 
85 	if (!ctx->length) {
86 		printf("Crypto-v1: require data total length for sha init\n");
87 		return -EINVAL;
88 	}
89 
90 	priv->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
91 						   priv, ctx->length,
92 						   DATA_ADDR_ALIGIN_SIZE,
93 						   DATA_LEN_ALIGIN_SIZE);
94 	if (!priv->hash_cache)
95 		return -EFAULT;
96 
97 	priv->ctx = ctx;
98 	priv->length = 0;
99 	writel(ctx->length, &reg->crypto_hash_msg_len);
100 	if (ctx->algo == CRYPTO_SHA256) {
101 		/* Set SHA256 mode and out byte swap */
102 		writel(HASH_SWAP_DO | ENGINE_SELECTION_SHA256,
103 		       &reg->crypto_hash_ctrl);
104 
105 		val = readl(&reg->crypto_conf);
106 		val &= ~BYTESWAP_HRFIFO;
107 		writel(val, &reg->crypto_conf);
108 	} else if (ctx->algo == CRYPTO_SHA1) {
109 		/* Set SHA160 input byte swap */
110 		val = readl(&reg->crypto_conf);
111 		val |= BYTESWAP_HRFIFO;
112 		writel(val, &reg->crypto_conf);
113 
114 		/* Set SHA160 mode and out byte swap */
115 		writel(HASH_SWAP_DO, &reg->crypto_hash_ctrl);
116 	} else if (ctx->algo == CRYPTO_MD5) {
117 		/* Set MD5 input byte swap */
118 		val = readl(&reg->crypto_conf);
119 		val |= BYTESWAP_HRFIFO;
120 		writel(val, &reg->crypto_conf);
121 
122 		/* Set MD5 mode and out byte swap */
123 		writel(HASH_SWAP_DO | ENGINE_SELECTION_MD5,
124 		       &reg->crypto_hash_ctrl);
125 	} else {
126 		return -EINVAL;
127 	}
128 
129 	rk_setreg(&reg->crypto_ctrl, HASH_FLUSH);
130 	do {} while (readl(&reg->crypto_ctrl) & HASH_FLUSH);
131 
132 	/* SHA256 needs input byte swap */
133 	if (ctx->algo == CRYPTO_SHA256) {
134 		val = readl(&reg->crypto_conf);
135 		val |= BYTESWAP_HRFIFO;
136 		writel(val, &reg->crypto_conf);
137 	}
138 
139 	return 0;
140 }
141 
142 static int rockchip_crypto_sha_update(struct udevice *dev,
143 				      u32 *input, u32 len)
144 {
145 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
146 	int ret = -EINVAL, i;
147 	u8 *p;
148 
149 	if (!input || !len)
150 		goto exit;
151 
152 	p = (u8 *)input;
153 
154 	for (i = 0; i < len / HASH_UPDATE_LIMIT; i++, p += HASH_UPDATE_LIMIT) {
155 		ret = crypto_hash_update_with_cache(priv->hash_cache, p,
156 						    HASH_UPDATE_LIMIT);
157 		if (ret)
158 			goto exit;
159 	}
160 
161 	if (len % HASH_UPDATE_LIMIT)
162 		ret = crypto_hash_update_with_cache(priv->hash_cache, p,
163 						    len % HASH_UPDATE_LIMIT);
164 
165 exit:
166 	if (ret) {
167 		crypto_hash_cache_free(priv->hash_cache);
168 		priv->hash_cache = NULL;
169 	}
170 
171 	return ret;
172 }
173 
174 static int rockchip_crypto_sha_final(struct udevice *dev,
175 				     sha_context *ctx, u8 *output)
176 {
177 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
178 	struct rk_crypto_reg *reg = priv->reg;
179 	u32 *buf = (u32 *)output;
180 	int ret = 0;
181 	u32 nbits;
182 	int i;
183 
184 	if (priv->length != ctx->length) {
185 		printf("total length(0x%08x) != init length(0x%08x)!\n",
186 		       priv->length, ctx->length);
187 		ret = -EIO;
188 		goto exit;
189 	}
190 
191 	/* Wait last complete */
192 	do {} while (readl(&reg->crypto_ctrl) & HASH_START);
193 
194 	/* It is high when finish, and it will not be low until it restart */
195 	do {} while (!readl(&reg->crypto_hash_sts));
196 
197 	/* Read hash data, per-data 32-bit */
198 	nbits = crypto_algo_nbits(ctx->algo);
199 	for (i = 0; i < BITS2WORD(nbits); i++)
200 		buf[i] = readl(&reg->crypto_hash_dout[i]);
201 
202 exit:
203 	crypto_hash_cache_free(priv->hash_cache);
204 	priv->hash_cache = NULL;
205 	return ret;
206 }
207 
208 #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
209 static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx,
210 				      u8 *sign, u8 *output)
211 {
212 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
213 	struct rk_crypto_reg *reg = priv->reg;
214 	u32 nbits, *buf = (u32 *)output;
215 	int i, value;
216 
217 	if (!ctx)
218 		return -EINVAL;
219 
220 	if (ctx->algo == CRYPTO_RSA512)
221 		value = PKA_BLOCK_SIZE_512;
222 	else if (ctx->algo == CRYPTO_RSA1024)
223 		value = PKA_BLOCK_SIZE_1024;
224 	else if (ctx->algo == CRYPTO_RSA2048)
225 		value = PKA_BLOCK_SIZE_2048;
226 	else
227 		return -EINVAL;
228 
229 	/* Specify the nbits of N in PKA calculation */
230 	writel(value, &reg->crypto_pka_ctrl);
231 
232 	/* Flush SHA and RSA */
233 	rk_setreg(&reg->crypto_ctrl, PKA_HASH_CTRL);
234 	writel(0xffffffff, &reg->crypto_intsts);
235 	do {} while (readl(&reg->crypto_ctrl) & PKA_CTRL);
236 
237 	/* Clean PKA done interrupt */
238 	writel(PKA_DONE_INT, &reg->crypto_intsts);
239 
240 	/* Set m/n/e/c */
241 	nbits = crypto_algo_nbits(ctx->algo);
242 	memcpy((void *)&reg->crypto_pka_m, (void *)sign,   BITS2BYTE(nbits));
243 	memcpy((void *)&reg->crypto_pka_n, (void *)ctx->n, BITS2BYTE(nbits));
244 	memcpy((void *)&reg->crypto_pka_e, (void *)ctx->e, BITS2BYTE(nbits));
245 	memcpy((void *)&reg->crypto_pka_c, (void *)ctx->c, BITS2BYTE(nbits));
246 	do {} while (readl(&reg->crypto_ctrl) & PKA_START);
247 
248 	/* Start PKA */
249 	rk_setreg(&reg->crypto_ctrl, PKA_START);
250 
251 	/* Wait PKA done */
252 	do {} while (readl(&reg->crypto_ctrl) & PKA_START);
253 
254 	/* Read hash data, per-data 32-bit */
255 	for (i = 0; i < BITS2WORD(nbits); i++)
256 		buf[i] = readl(&reg->crypto_pka_m[i]);
257 
258 	return 0;
259 }
260 #else
261 static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx,
262 				      u8 *sign, u8 *output)
263 {
264 	return -ENOSYS;
265 }
266 #endif
267 static const struct dm_crypto_ops rockchip_crypto_ops = {
268 	.capability = rockchip_crypto_capability,
269 	.sha_init   = rockchip_crypto_sha_init,
270 	.sha_update = rockchip_crypto_sha_update,
271 	.sha_final  = rockchip_crypto_sha_final,
272 	.rsa_verify = rockchip_crypto_rsa_verify,
273 };
274 
275 /*
276  * Only use "clocks" to parse crypto clock id and use rockchip_get_clk().
277  * Because we always add crypto node in U-Boot dts, when kernel dtb enabled :
278  *
279  *   1. There is cru phandle mismatch between U-Boot and kernel dtb;
280  *   2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property;
281  */
282 static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev)
283 {
284 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
285 	int len;
286 
287 	if (!dev_read_prop(dev, "clocks", &len)) {
288 		printf("Crypto-v1: can't find \"clocks\" property\n");
289 		return -EINVAL;
290 	}
291 
292 	priv->clocks = malloc(len);
293 	if (!priv->clocks)
294 		return -ENOMEM;
295 
296 	priv->nclocks = len / sizeof(u32);
297 	if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks,
298 			       priv->nclocks)) {
299 		printf("Crypto-v1: can't read \"clocks\" property\n");
300 		return -EINVAL;
301 	}
302 
303 	priv->reg = dev_read_addr_ptr(dev);
304 	priv->frequency = dev_read_u32_default(dev, "clock-frequency",
305 					       CRYPTO_V1_DEFAULT_RATE);
306 
307 	return 0;
308 }
309 
310 static int rockchip_crypto_probe(struct udevice *dev)
311 {
312 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
313 	u32 *clocks;
314 	int i, ret;
315 
316 	ret = rockchip_get_clk(&priv->clk.dev);
317 	if (ret) {
318 		printf("Crypto-v1: failed to get clk device, ret=%d\n", ret);
319 		return ret;
320 	}
321 
322 	clocks = (u32 *)priv->clocks;
323 	for (i = 1; i < priv->nclocks; i += 2) {
324 		priv->clk.id = clocks[i];
325 		ret = clk_set_rate(&priv->clk, priv->frequency);
326 		if (ret < 0) {
327 			printf("Crypto-v1: failed to set clk(%ld): ret=%d\n",
328 			       priv->clk.id, ret);
329 			return ret;
330 		}
331 	}
332 
333 	return 0;
334 }
335 
336 static const struct udevice_id rockchip_crypto_ids[] = {
337 	{ .compatible = "rockchip,rk3399-crypto" },
338 	{ .compatible = "rockchip,rk3368-crypto" },
339 	{ .compatible = "rockchip,rk3328-crypto" },
340 	{ .compatible = "rockchip,rk3288-crypto" },
341 	{ .compatible = "rockchip,rk322x-crypto" },
342 	{ .compatible = "rockchip,rk312x-crypto" },
343 	{ }
344 };
345 
346 U_BOOT_DRIVER(rockchip_crypto_v1) = {
347 	.name		= "rockchip_crypto_v1",
348 	.id		= UCLASS_CRYPTO,
349 	.of_match	= rockchip_crypto_ids,
350 	.ops		= &rockchip_crypto_ops,
351 	.probe		= rockchip_crypto_probe,
352 	.ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata,
353 	.priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv),
354 };
355