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