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