xref: /rk3399_rockchip-uboot/drivers/crypto/rockchip/crypto_v2.c (revision c3ce993789b241f7bfc245002cbdd7d111499e3f)
1b353a43cSLin Jinhan // SPDX-License-Identifier: GPL-2.0
2b353a43cSLin Jinhan /*
3b353a43cSLin Jinhan  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4b353a43cSLin Jinhan  */
5b353a43cSLin Jinhan 
6b353a43cSLin Jinhan #include <common.h>
7b353a43cSLin Jinhan #include <clk.h>
8b353a43cSLin Jinhan #include <crypto.h>
9b353a43cSLin Jinhan #include <dm.h>
10b353a43cSLin Jinhan #include <asm/io.h>
11b353a43cSLin Jinhan #include <asm/arch/hardware.h>
12b353a43cSLin Jinhan #include <asm/arch/clock.h>
13c48f1acfSLin Jinhan #include <rockchip/crypto_hash_cache.h>
14b353a43cSLin Jinhan #include <rockchip/crypto_v2.h>
15b353a43cSLin Jinhan #include <rockchip/crypto_v2_pka.h>
16b353a43cSLin Jinhan 
17c48f1acfSLin Jinhan #define	RK_HASH_CTX_MAGIC		0x1A1A1A1A
18c48f1acfSLin Jinhan 
1949a2135eSLin Jinhan #ifdef DEBUG
2049a2135eSLin Jinhan #define IMSG(format, ...) printf("[%s, %05d]-trace: " format "\n", \
2149a2135eSLin Jinhan 				 __func__, __LINE__, ##__VA_ARGS__)
2249a2135eSLin Jinhan #else
2349a2135eSLin Jinhan #define IMSG(format, ...)
2449a2135eSLin Jinhan #endif
25c48f1acfSLin Jinhan 
26c48f1acfSLin Jinhan struct crypto_lli_desc {
27c48f1acfSLin Jinhan 	u32 src_addr;
28c48f1acfSLin Jinhan 	u32 src_len;
29c48f1acfSLin Jinhan 	u32 dst_addr;
30c48f1acfSLin Jinhan 	u32 dst_len;
31c48f1acfSLin Jinhan 	u32 user_define;
32c48f1acfSLin Jinhan 	u32 reserve;
33c48f1acfSLin Jinhan 	u32 dma_ctrl;
34c48f1acfSLin Jinhan 	u32 next_addr;
35c48f1acfSLin Jinhan };
36c48f1acfSLin Jinhan 
37c48f1acfSLin Jinhan struct rk_hash_ctx {
38c48f1acfSLin Jinhan 	struct crypto_lli_desc		data_lli;	/* lli desc */
39c48f1acfSLin Jinhan 	struct crypto_hash_cache	*hash_cache;
40c48f1acfSLin Jinhan 	u32				magic;		/* to check ctx */
41c48f1acfSLin Jinhan 	u32				algo;		/* hash algo */
42c48f1acfSLin Jinhan 	u8				digest_size;	/* hash out length */
43c48f1acfSLin Jinhan 	u8				reserved[3];
44c48f1acfSLin Jinhan };
45c48f1acfSLin Jinhan 
4649a2135eSLin Jinhan struct rk_crypto_soc_data {
4749a2135eSLin Jinhan 	u32 capability;
4849a2135eSLin Jinhan };
4949a2135eSLin Jinhan 
50b353a43cSLin Jinhan struct rockchip_crypto_priv {
51b353a43cSLin Jinhan 	fdt_addr_t			reg;
52b353a43cSLin Jinhan 	struct clk			clk;
53b353a43cSLin Jinhan 	u32				frequency;
54b353a43cSLin Jinhan 	char				*clocks;
55b353a43cSLin Jinhan 	u32				*frequencies;
56b353a43cSLin Jinhan 	u32				nclocks;
57b353a43cSLin Jinhan 	u32				length;
581606a214SLin Jinhan 	struct rk_hash_ctx		*hw_ctx;
5949a2135eSLin Jinhan 	struct rk_crypto_soc_data	*soc_data;
60b353a43cSLin Jinhan };
61b353a43cSLin Jinhan 
6249a2135eSLin Jinhan #define LLI_ADDR_ALIGN_SIZE	8
6349a2135eSLin Jinhan #define DATA_ADDR_ALIGN_SIZE	8
6449a2135eSLin Jinhan #define DATA_LEN_ALIGN_SIZE	64
651606a214SLin Jinhan 
66086e8fa8SLin Jinhan /* crypto timeout 500ms, must support more than 32M data per times*/
67086e8fa8SLin Jinhan #define HASH_UPDATE_LIMIT	(32 * 1024 * 1024)
6849a2135eSLin Jinhan #define RK_CRYPTO_TIMEOUT	500000
69b353a43cSLin Jinhan 
7049a2135eSLin Jinhan #define RK_POLL_TIMEOUT(condition, timeout) \
7149a2135eSLin Jinhan ({ \
7249a2135eSLin Jinhan 	int time_out = timeout; \
73b353a43cSLin Jinhan 	while (condition) { \
7449a2135eSLin Jinhan 		if (--time_out <= 0) { \
751606a214SLin Jinhan 			debug("[%s] %d: time out!\n", __func__,\
76b353a43cSLin Jinhan 				__LINE__); \
77b353a43cSLin Jinhan 			break; \
78b353a43cSLin Jinhan 		} \
79b353a43cSLin Jinhan 		udelay(1); \
80b353a43cSLin Jinhan 	} \
8149a2135eSLin Jinhan 	(time_out <= 0) ? -ETIMEDOUT : 0; \
8249a2135eSLin Jinhan })
83b353a43cSLin Jinhan 
84d9332f1cSLin Jinhan #define WAIT_TAG_VALID(channel, timeout) ({ \
85d9332f1cSLin Jinhan 	u32 tag_mask = CRYPTO_CH0_TAG_VALID << (channel);\
86d9332f1cSLin Jinhan 	int ret;\
87d9332f1cSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_TAG_VALID) & tag_mask),\
88d9332f1cSLin Jinhan 			      timeout);\
89d9332f1cSLin Jinhan 	crypto_write(crypto_read(CRYPTO_TAG_VALID) & tag_mask, CRYPTO_TAG_VALID);\
90d9332f1cSLin Jinhan 	ret;\
91d9332f1cSLin Jinhan })
92d9332f1cSLin Jinhan 
93b353a43cSLin Jinhan #define virt_to_phys(addr)		(((unsigned long)addr) & 0xffffffff)
94b353a43cSLin Jinhan #define phys_to_virt(addr, area)	((unsigned long)addr)
95b353a43cSLin Jinhan 
9649a2135eSLin Jinhan #define align_malloc(bytes, alignment)	memalign(alignment, bytes)
9749a2135eSLin Jinhan #define align_free(addr)		free(addr)
9849a2135eSLin Jinhan 
9949a2135eSLin Jinhan #define ROUNDUP(size, alignment)	round_up(size, alignment)
10049a2135eSLin Jinhan #define cache_op_inner(type, addr, size) \
10149a2135eSLin Jinhan 					crypto_flush_cacheline((ulong)addr, size)
10249a2135eSLin Jinhan 
103d9332f1cSLin Jinhan #define IS_NEED_IV(rk_mode) ((rk_mode) != RK_MODE_ECB && \
104d9332f1cSLin Jinhan 			     (rk_mode) != RK_MODE_CMAC && \
105d9332f1cSLin Jinhan 			     (rk_mode) != RK_MODE_CBC_MAC)
106d9332f1cSLin Jinhan 
107d9332f1cSLin Jinhan #define IS_NEED_TAG(rk_mode) ((rk_mode) == RK_MODE_CMAC || \
108*c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_CBC_MAC || \
109*c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_CCM || \
110*c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_GCM)
111d9332f1cSLin Jinhan 
112d9332f1cSLin Jinhan #define IS_MAC_MODE(rk_mode) ((rk_mode) == RK_MODE_CMAC || \
113d9332f1cSLin Jinhan 			      (rk_mode) == RK_MODE_CBC_MAC)
114d9332f1cSLin Jinhan 
115*c3ce9937SLin Jinhan #define IS_AE_MODE(rk_mode) ((rk_mode) == RK_MODE_CCM || \
116*c3ce9937SLin Jinhan 			     (rk_mode) == RK_MODE_GCM)
117*c3ce9937SLin Jinhan 
118b353a43cSLin Jinhan fdt_addr_t crypto_base;
119b353a43cSLin Jinhan 
12049a2135eSLin Jinhan static inline void word2byte_be(u32 word, u8 *ch)
121b353a43cSLin Jinhan {
122b353a43cSLin Jinhan 	ch[0] = (word >> 24) & 0xff;
123b353a43cSLin Jinhan 	ch[1] = (word >> 16) & 0xff;
124b353a43cSLin Jinhan 	ch[2] = (word >> 8) & 0xff;
125b353a43cSLin Jinhan 	ch[3] = (word >> 0) & 0xff;
126b353a43cSLin Jinhan }
127b353a43cSLin Jinhan 
12849a2135eSLin Jinhan static inline u32 byte2word_be(const u8 *ch)
12949a2135eSLin Jinhan {
13049a2135eSLin Jinhan 	return (*ch << 24) + (*(ch + 1) << 16) + (*(ch + 2) << 8) + *(ch + 3);
13149a2135eSLin Jinhan }
13249a2135eSLin Jinhan 
13349a2135eSLin Jinhan static inline void clear_regs(u32 base, u32 words)
134b353a43cSLin Jinhan {
135b353a43cSLin Jinhan 	int i;
136b353a43cSLin Jinhan 
137b353a43cSLin Jinhan 	/*clear out register*/
13849a2135eSLin Jinhan 	for (i = 0; i < words; i++)
13949a2135eSLin Jinhan 		crypto_write(0, base + 4 * i);
14049a2135eSLin Jinhan }
14149a2135eSLin Jinhan 
14249a2135eSLin Jinhan static inline void clear_hash_out_reg(void)
14349a2135eSLin Jinhan {
14449a2135eSLin Jinhan 	clear_regs(CRYPTO_HASH_DOUT_0, 16);
14549a2135eSLin Jinhan }
14649a2135eSLin Jinhan 
14749a2135eSLin Jinhan static inline void clear_key_regs(void)
14849a2135eSLin Jinhan {
14949a2135eSLin Jinhan 	clear_regs(CRYPTO_CH0_KEY_0, CRYPTO_KEY_CHANNEL_NUM * 4);
15049a2135eSLin Jinhan }
15149a2135eSLin Jinhan 
152*c3ce9937SLin Jinhan static inline void read_regs(u32 base, u8 *data, u32 data_len)
153*c3ce9937SLin Jinhan {
154*c3ce9937SLin Jinhan 	u8 tmp_buf[4];
155*c3ce9937SLin Jinhan 	u32 i;
156*c3ce9937SLin Jinhan 
157*c3ce9937SLin Jinhan 	for (i = 0; i < data_len / 4; i++)
158*c3ce9937SLin Jinhan 		word2byte_be(crypto_read(base + i * 4),
159*c3ce9937SLin Jinhan 			     data + i * 4);
160*c3ce9937SLin Jinhan 
161*c3ce9937SLin Jinhan 	if (data_len % 4) {
162*c3ce9937SLin Jinhan 		word2byte_be(crypto_read(base + i * 4), tmp_buf);
163*c3ce9937SLin Jinhan 		memcpy(data + i * 4, tmp_buf, data_len % 4);
164*c3ce9937SLin Jinhan 	}
165*c3ce9937SLin Jinhan }
166*c3ce9937SLin Jinhan 
16749a2135eSLin Jinhan static inline void write_regs(u32 base, const u8 *data, u32 data_len)
16849a2135eSLin Jinhan {
16949a2135eSLin Jinhan 	u8 tmp_buf[4];
17049a2135eSLin Jinhan 	u32 i;
17149a2135eSLin Jinhan 
17249a2135eSLin Jinhan 	for (i = 0; i < data_len / 4; i++, base += 4)
17349a2135eSLin Jinhan 		crypto_write(byte2word_be(data + i * 4), base);
17449a2135eSLin Jinhan 
17549a2135eSLin Jinhan 	if (data_len % 4) {
17649a2135eSLin Jinhan 		memset(tmp_buf, 0x00, sizeof(tmp_buf));
17749a2135eSLin Jinhan 		memcpy((u8 *)tmp_buf, data + i * 4, data_len % 4);
17849a2135eSLin Jinhan 		crypto_write(byte2word_be(tmp_buf), base);
17949a2135eSLin Jinhan 	}
18049a2135eSLin Jinhan }
18149a2135eSLin Jinhan 
18249a2135eSLin Jinhan static inline void write_key_reg(u32 chn, const u8 *key, u32 key_len)
18349a2135eSLin Jinhan {
18449a2135eSLin Jinhan 	write_regs(CRYPTO_CH0_KEY_0 + chn * 0x10, key, key_len);
18549a2135eSLin Jinhan }
18649a2135eSLin Jinhan 
18749a2135eSLin Jinhan static inline void set_iv_reg(u32 chn, const u8 *iv, u32 iv_len)
18849a2135eSLin Jinhan {
18949a2135eSLin Jinhan 	u32 base_iv;
19049a2135eSLin Jinhan 
19149a2135eSLin Jinhan 	base_iv = CRYPTO_CH0_IV_0 + chn * 0x10;
19249a2135eSLin Jinhan 
19349a2135eSLin Jinhan 	/* clear iv */
19449a2135eSLin Jinhan 	clear_regs(base_iv, 4);
19549a2135eSLin Jinhan 
19649a2135eSLin Jinhan 	if (!iv || iv_len == 0)
19749a2135eSLin Jinhan 		return;
19849a2135eSLin Jinhan 
19949a2135eSLin Jinhan 	write_regs(base_iv, iv, iv_len);
20049a2135eSLin Jinhan 
20149a2135eSLin Jinhan 	crypto_write(iv_len, CRYPTO_CH0_IV_LEN_0 + 4 * chn);
202b353a43cSLin Jinhan }
203b353a43cSLin Jinhan 
204*c3ce9937SLin Jinhan static inline void get_iv_reg(u32 chn, u8 *iv, u32 iv_len)
205*c3ce9937SLin Jinhan {
206*c3ce9937SLin Jinhan 	u32 base_iv;
207*c3ce9937SLin Jinhan 
208*c3ce9937SLin Jinhan 	base_iv = CRYPTO_CH0_IV_0 + chn * 0x10;
209*c3ce9937SLin Jinhan 
210*c3ce9937SLin Jinhan 	read_regs(base_iv, iv, iv_len);
211*c3ce9937SLin Jinhan }
212*c3ce9937SLin Jinhan 
213d9332f1cSLin Jinhan static inline void get_tag_from_reg(u32 chn, u8 *tag, u32 tag_len)
214d9332f1cSLin Jinhan {
215d9332f1cSLin Jinhan 	u32 i;
216d9332f1cSLin Jinhan 	u32 chn_base = CRYPTO_CH0_TAG_0 + 0x10 * chn;
217d9332f1cSLin Jinhan 
218d9332f1cSLin Jinhan 	for (i = 0; i < tag_len / 4; i++, chn_base += 4)
219d9332f1cSLin Jinhan 		word2byte_be(crypto_read(chn_base), tag + 4 * i);
220d9332f1cSLin Jinhan }
221d9332f1cSLin Jinhan 
222b353a43cSLin Jinhan static int hw_crypto_reset(void)
223b353a43cSLin Jinhan {
22449a2135eSLin Jinhan 	u32 val = 0, mask = 0;
225b353a43cSLin Jinhan 	int ret;
226b353a43cSLin Jinhan 
22749a2135eSLin Jinhan 	val = CRYPTO_SW_PKA_RESET | CRYPTO_SW_CC_RESET;
22849a2135eSLin Jinhan 	mask = val << CRYPTO_WRITE_MASK_SHIFT;
229b353a43cSLin Jinhan 
230b353a43cSLin Jinhan 	/* reset pka and crypto modules*/
23149a2135eSLin Jinhan 	crypto_write(val | mask, CRYPTO_RST_CTL);
232b353a43cSLin Jinhan 
233b353a43cSLin Jinhan 	/* wait reset compelete */
23449a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL), RK_CRYPTO_TIMEOUT);
23549a2135eSLin Jinhan 
236b353a43cSLin Jinhan 	return ret;
237b353a43cSLin Jinhan }
238b353a43cSLin Jinhan 
239b353a43cSLin Jinhan static void hw_hash_clean_ctx(struct rk_hash_ctx *ctx)
240b353a43cSLin Jinhan {
241b353a43cSLin Jinhan 	/* clear hash status */
242b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
243b353a43cSLin Jinhan 
2441606a214SLin Jinhan 	assert(ctx);
2451606a214SLin Jinhan 	assert(ctx->magic == RK_HASH_CTX_MAGIC);
2461606a214SLin Jinhan 
247c48f1acfSLin Jinhan 	crypto_hash_cache_free(ctx->hash_cache);
2481606a214SLin Jinhan 
2491606a214SLin Jinhan 	memset(ctx, 0x00, sizeof(*ctx));
250b353a43cSLin Jinhan }
251b353a43cSLin Jinhan 
252c48f1acfSLin Jinhan static int rk_hash_init(void *hw_ctx, u32 algo)
253b353a43cSLin Jinhan {
254b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)hw_ctx;
255b353a43cSLin Jinhan 	u32 reg_ctrl = 0;
256b353a43cSLin Jinhan 	int ret;
257b353a43cSLin Jinhan 
258b353a43cSLin Jinhan 	if (!tmp_ctx)
259b353a43cSLin Jinhan 		return -EINVAL;
260b353a43cSLin Jinhan 
2611606a214SLin Jinhan 	reg_ctrl = CRYPTO_SW_CC_RESET;
2621606a214SLin Jinhan 	crypto_write(reg_ctrl | (reg_ctrl << CRYPTO_WRITE_MASK_SHIFT),
2631606a214SLin Jinhan 		     CRYPTO_RST_CTL);
2641606a214SLin Jinhan 
2651606a214SLin Jinhan 	/* wait reset compelete */
26649a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL),
26749a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
2681606a214SLin Jinhan 
2691606a214SLin Jinhan 	reg_ctrl = 0;
270b353a43cSLin Jinhan 	tmp_ctx->algo = algo;
271b353a43cSLin Jinhan 	switch (algo) {
272b353a43cSLin Jinhan 	case CRYPTO_MD5:
27349a2135eSLin Jinhan 	case CRYPTO_HMAC_MD5:
274b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_MD5;
275b353a43cSLin Jinhan 		tmp_ctx->digest_size = 16;
276b353a43cSLin Jinhan 		break;
277b353a43cSLin Jinhan 	case CRYPTO_SHA1:
27849a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA1:
279b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA1;
280b353a43cSLin Jinhan 		tmp_ctx->digest_size = 20;
281b353a43cSLin Jinhan 		break;
282b353a43cSLin Jinhan 	case CRYPTO_SHA256:
28349a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA256:
284b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA256;
285b353a43cSLin Jinhan 		tmp_ctx->digest_size = 32;
286b353a43cSLin Jinhan 		break;
287e7846385SLin Jinhan 	case CRYPTO_SHA512:
28849a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA512:
289e7846385SLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA512;
290e7846385SLin Jinhan 		tmp_ctx->digest_size = 64;
291e7846385SLin Jinhan 		break;
29249a2135eSLin Jinhan 	case CRYPTO_SM3:
29349a2135eSLin Jinhan 	case CRYPTO_HMAC_SM3:
29449a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SM3;
29549a2135eSLin Jinhan 		tmp_ctx->digest_size = 32;
29649a2135eSLin Jinhan 		break;
297b353a43cSLin Jinhan 	default:
298b353a43cSLin Jinhan 		ret = -EINVAL;
299b353a43cSLin Jinhan 		goto exit;
300b353a43cSLin Jinhan 	}
301b353a43cSLin Jinhan 
302b353a43cSLin Jinhan 	clear_hash_out_reg();
303b353a43cSLin Jinhan 
304b353a43cSLin Jinhan 	/* enable hardware padding */
305b353a43cSLin Jinhan 	reg_ctrl |= CRYPTO_HW_PAD_ENABLE;
306b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
307b353a43cSLin Jinhan 
308b353a43cSLin Jinhan 	/* FIFO input and output data byte swap */
309b353a43cSLin Jinhan 	/* such as B0, B1, B2, B3 -> B3, B2, B1, B0 */
310b353a43cSLin Jinhan 	reg_ctrl = CRYPTO_DOUT_BYTESWAP | CRYPTO_DOIN_BYTESWAP;
311b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_FIFO_CTL);
312b353a43cSLin Jinhan 
3131606a214SLin Jinhan 	/* enable src_item_done interrupt */
3141606a214SLin Jinhan 	crypto_write(CRYPTO_SRC_ITEM_INT_EN, CRYPTO_DMA_INT_EN);
315b353a43cSLin Jinhan 
316b353a43cSLin Jinhan 	tmp_ctx->magic = RK_HASH_CTX_MAGIC;
317b353a43cSLin Jinhan 
318b353a43cSLin Jinhan 	return 0;
319b353a43cSLin Jinhan exit:
320b353a43cSLin Jinhan 	/* clear hash setting if init failed */
321b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
322b353a43cSLin Jinhan 
323b353a43cSLin Jinhan 	return ret;
324b353a43cSLin Jinhan }
325b353a43cSLin Jinhan 
326c48f1acfSLin Jinhan static int rk_hash_direct_calc(void *hw_data, const u8 *data,
3271606a214SLin Jinhan 			       u32 data_len, u8 *started_flag, u8 is_last)
328b353a43cSLin Jinhan {
329c48f1acfSLin Jinhan 	struct rockchip_crypto_priv *priv = hw_data;
330c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
331c48f1acfSLin Jinhan 	struct crypto_lli_desc *lli = &hash_ctx->data_lli;
332b353a43cSLin Jinhan 	int ret = -EINVAL;
33300fa57d8SLin Jinhan 	u32 tmp = 0, mask = 0;
334b353a43cSLin Jinhan 
33549a2135eSLin Jinhan 	assert(IS_ALIGNED((ulong)data, DATA_ADDR_ALIGN_SIZE));
33649a2135eSLin Jinhan 	assert(is_last || IS_ALIGNED(data_len, DATA_LEN_ALIGN_SIZE));
337b353a43cSLin Jinhan 
3381606a214SLin Jinhan 	debug("%s: data = %p, len = %u, s = %x, l = %x\n",
3391606a214SLin Jinhan 	      __func__, data, data_len, *started_flag, is_last);
340b353a43cSLin Jinhan 
3411606a214SLin Jinhan 	memset(lli, 0x00, sizeof(*lli));
3421606a214SLin Jinhan 	lli->src_addr = (u32)virt_to_phys(data);
3431606a214SLin Jinhan 	lli->src_len = data_len;
3441606a214SLin Jinhan 	lli->dma_ctrl = LLI_DMA_CTRL_SRC_DONE;
345b353a43cSLin Jinhan 
3461606a214SLin Jinhan 	if (is_last) {
3471606a214SLin Jinhan 		lli->user_define |= LLI_USER_STRING_LAST;
3481606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_LAST;
349b353a43cSLin Jinhan 	} else {
3501606a214SLin Jinhan 		lli->next_addr = (u32)virt_to_phys(lli);
3511606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_PAUSE;
3521606a214SLin Jinhan 	}
3531606a214SLin Jinhan 
3541606a214SLin Jinhan 	if (!(*started_flag)) {
3551606a214SLin Jinhan 		lli->user_define |=
3561606a214SLin Jinhan 			(LLI_USER_STRING_START | LLI_USER_CPIHER_START);
3571606a214SLin Jinhan 		crypto_write((u32)virt_to_phys(lli), CRYPTO_DMA_LLI_ADDR);
3581606a214SLin Jinhan 		crypto_write((CRYPTO_HASH_ENABLE << CRYPTO_WRITE_MASK_SHIFT) |
3591606a214SLin Jinhan 			     CRYPTO_HASH_ENABLE, CRYPTO_HASH_CTL);
3601606a214SLin Jinhan 		tmp = CRYPTO_DMA_START;
3611606a214SLin Jinhan 		*started_flag = 1;
3621606a214SLin Jinhan 	} else {
363b353a43cSLin Jinhan 		tmp = CRYPTO_DMA_RESTART;
364b353a43cSLin Jinhan 	}
365b353a43cSLin Jinhan 
366b353a43cSLin Jinhan 	/* flush cache */
367c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)lli, sizeof(*lli));
368c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)data, data_len);
369b353a43cSLin Jinhan 
370b353a43cSLin Jinhan 	/* start calculate */
371b353a43cSLin Jinhan 	crypto_write(tmp << CRYPTO_WRITE_MASK_SHIFT | tmp,
372b353a43cSLin Jinhan 		     CRYPTO_DMA_CTL);
373b353a43cSLin Jinhan 
37400fa57d8SLin Jinhan 	/* mask CRYPTO_SYNC_LOCKSTEP_INT_ST flag */
37500fa57d8SLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
37600fa57d8SLin Jinhan 
377b353a43cSLin Jinhan 	/* wait calc ok */
37849a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
37949a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
380b353a43cSLin Jinhan 
381b353a43cSLin Jinhan 	/* clear interrupt status */
382b353a43cSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
383b353a43cSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
384b353a43cSLin Jinhan 
385b353a43cSLin Jinhan 	if (tmp != CRYPTO_SRC_ITEM_DONE_INT_ST &&
386b353a43cSLin Jinhan 	    tmp != CRYPTO_ZERO_LEN_INT_ST) {
3871606a214SLin Jinhan 		debug("[%s] %d: CRYPTO_DMA_INT_ST = 0x%x\n",
388b353a43cSLin Jinhan 		      __func__, __LINE__, tmp);
3891606a214SLin Jinhan 		goto exit;
390b353a43cSLin Jinhan 	}
391b353a43cSLin Jinhan 
392c48f1acfSLin Jinhan 	priv->length += data_len;
3931606a214SLin Jinhan exit:
3941606a214SLin Jinhan 	return ret;
395b353a43cSLin Jinhan }
3961606a214SLin Jinhan 
3971606a214SLin Jinhan int rk_hash_update(void *ctx, const u8 *data, u32 data_len)
3981606a214SLin Jinhan {
3991606a214SLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
400c48f1acfSLin Jinhan 	int ret = -EINVAL;
4011606a214SLin Jinhan 
4021606a214SLin Jinhan 	debug("\n");
4031606a214SLin Jinhan 	if (!tmp_ctx || !data)
404c48f1acfSLin Jinhan 		goto exit;
4051606a214SLin Jinhan 
4061606a214SLin Jinhan 	if (tmp_ctx->digest_size == 0 || tmp_ctx->magic != RK_HASH_CTX_MAGIC)
407c48f1acfSLin Jinhan 		goto exit;
4081606a214SLin Jinhan 
409c48f1acfSLin Jinhan 	ret = crypto_hash_update_with_cache(tmp_ctx->hash_cache,
410c48f1acfSLin Jinhan 					    data, data_len);
4111606a214SLin Jinhan 
412c48f1acfSLin Jinhan exit:
413b353a43cSLin Jinhan 	/* free lli list */
414c48f1acfSLin Jinhan 	if (ret)
415b353a43cSLin Jinhan 		hw_hash_clean_ctx(tmp_ctx);
416b353a43cSLin Jinhan 
417c48f1acfSLin Jinhan 	return ret;
418b353a43cSLin Jinhan }
419b353a43cSLin Jinhan 
420b353a43cSLin Jinhan int rk_hash_final(void *ctx, u8 *digest, size_t len)
421b353a43cSLin Jinhan {
422b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
423b353a43cSLin Jinhan 	int ret = -EINVAL;
424b353a43cSLin Jinhan 
425b353a43cSLin Jinhan 	if (!digest)
426b353a43cSLin Jinhan 		goto exit;
427b353a43cSLin Jinhan 
428b353a43cSLin Jinhan 	if (!tmp_ctx ||
429b353a43cSLin Jinhan 	    tmp_ctx->digest_size == 0 ||
430b353a43cSLin Jinhan 	    len > tmp_ctx->digest_size ||
431b353a43cSLin Jinhan 	    tmp_ctx->magic != RK_HASH_CTX_MAGIC) {
432b353a43cSLin Jinhan 		goto exit;
433b353a43cSLin Jinhan 	}
434b353a43cSLin Jinhan 
435b353a43cSLin Jinhan 	/* wait hash value ok */
43649a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!crypto_read(CRYPTO_HASH_VALID),
43749a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
438b353a43cSLin Jinhan 
439*c3ce9937SLin Jinhan 	read_regs(CRYPTO_HASH_DOUT_0, digest, len);
440b353a43cSLin Jinhan 
441b353a43cSLin Jinhan 	/* clear hash status */
442b353a43cSLin Jinhan 	crypto_write(CRYPTO_HASH_IS_VALID, CRYPTO_HASH_VALID);
443b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
444b353a43cSLin Jinhan 
445b353a43cSLin Jinhan exit:
446b353a43cSLin Jinhan 
447b353a43cSLin Jinhan 	return ret;
448b353a43cSLin Jinhan }
449b353a43cSLin Jinhan 
450b353a43cSLin Jinhan static u32 rockchip_crypto_capability(struct udevice *dev)
451b353a43cSLin Jinhan {
45249a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
45349a2135eSLin Jinhan 	u32 capability, mask = 0;
4547eea1823SLin Jinhan 
45549a2135eSLin Jinhan 	capability = priv->soc_data->capability;
45649a2135eSLin Jinhan 
45749a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_CIPHER))
45849a2135eSLin Jinhan 	mask |= (CRYPTO_DES | CRYPTO_AES | CRYPTO_SM4);
459c0e47d03SLin Jinhan #endif
4607eea1823SLin Jinhan 
46149a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_HMAC))
46249a2135eSLin Jinhan 	mask |= (CRYPTO_HMAC_MD5 | CRYPTO_HMAC_SHA1 | CRYPTO_HMAC_SHA256 |
46349a2135eSLin Jinhan 			 CRYPTO_HMAC_SHA512 | CRYPTO_HMAC_SM3);
46449a2135eSLin Jinhan #endif
46549a2135eSLin Jinhan 
46649a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_RSA))
46749a2135eSLin Jinhan 	mask |= (CRYPTO_RSA512 | CRYPTO_RSA1024 | CRYPTO_RSA2048 |
46849a2135eSLin Jinhan 			 CRYPTO_RSA3072 | CRYPTO_RSA4096);
46949a2135eSLin Jinhan #endif
47049a2135eSLin Jinhan 
47149a2135eSLin Jinhan 	return capability & (~mask);
472b353a43cSLin Jinhan }
473b353a43cSLin Jinhan 
474b353a43cSLin Jinhan static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx)
475b353a43cSLin Jinhan {
476b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
477c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
478b353a43cSLin Jinhan 
479b353a43cSLin Jinhan 	if (!ctx)
480b353a43cSLin Jinhan 		return -EINVAL;
481b353a43cSLin Jinhan 
482c48f1acfSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
483b353a43cSLin Jinhan 
484c48f1acfSLin Jinhan 	priv->length = 0;
485c48f1acfSLin Jinhan 
486c48f1acfSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
487c48f1acfSLin Jinhan 						       priv, ctx->length,
48849a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
48949a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
490c48f1acfSLin Jinhan 	if (!hash_ctx->hash_cache)
491c48f1acfSLin Jinhan 		return -EFAULT;
492c48f1acfSLin Jinhan 
493c48f1acfSLin Jinhan 	return rk_hash_init(hash_ctx, ctx->algo);
494b353a43cSLin Jinhan }
495b353a43cSLin Jinhan 
496b353a43cSLin Jinhan static int rockchip_crypto_sha_update(struct udevice *dev,
497b353a43cSLin Jinhan 				      u32 *input, u32 len)
498b353a43cSLin Jinhan {
499b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
500086e8fa8SLin Jinhan 	int ret, i;
501086e8fa8SLin Jinhan 	u8 *p;
502b353a43cSLin Jinhan 
503b353a43cSLin Jinhan 	if (!len)
504b353a43cSLin Jinhan 		return -EINVAL;
505b353a43cSLin Jinhan 
506086e8fa8SLin Jinhan 	p = (u8 *)input;
507086e8fa8SLin Jinhan 
508086e8fa8SLin Jinhan 	for (i = 0; i < len / HASH_UPDATE_LIMIT; i++, p += HASH_UPDATE_LIMIT) {
509086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, HASH_UPDATE_LIMIT);
510086e8fa8SLin Jinhan 		if (ret)
511086e8fa8SLin Jinhan 			goto exit;
512086e8fa8SLin Jinhan 	}
513086e8fa8SLin Jinhan 
514086e8fa8SLin Jinhan 	if (len % HASH_UPDATE_LIMIT)
515086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, len % HASH_UPDATE_LIMIT);
516086e8fa8SLin Jinhan 
517086e8fa8SLin Jinhan exit:
518086e8fa8SLin Jinhan 	return ret;
519b353a43cSLin Jinhan }
520b353a43cSLin Jinhan 
521b353a43cSLin Jinhan static int rockchip_crypto_sha_final(struct udevice *dev,
522b353a43cSLin Jinhan 				     sha_context *ctx, u8 *output)
523b353a43cSLin Jinhan {
524b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
525b353a43cSLin Jinhan 	u32 nbits;
526c48f1acfSLin Jinhan 	int ret;
527b353a43cSLin Jinhan 
528b353a43cSLin Jinhan 	nbits = crypto_algo_nbits(ctx->algo);
529b353a43cSLin Jinhan 
530c48f1acfSLin Jinhan 	if (priv->length != ctx->length) {
531c48f1acfSLin Jinhan 		printf("total length(0x%08x) != init length(0x%08x)!\n",
532c48f1acfSLin Jinhan 		       priv->length, ctx->length);
533c48f1acfSLin Jinhan 		ret = -EIO;
534c48f1acfSLin Jinhan 		goto exit;
535c48f1acfSLin Jinhan 	}
536c48f1acfSLin Jinhan 
537c48f1acfSLin Jinhan 	ret = rk_hash_final(priv->hw_ctx, (u8 *)output, BITS2BYTE(nbits));
538c48f1acfSLin Jinhan 
539c48f1acfSLin Jinhan exit:
540c48f1acfSLin Jinhan 	hw_hash_clean_ctx(priv->hw_ctx);
541c48f1acfSLin Jinhan 	return ret;
542b353a43cSLin Jinhan }
543b353a43cSLin Jinhan 
54449a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
54549a2135eSLin Jinhan int rk_hmac_init(void *hw_ctx, u32 algo, u8 *key, u32 key_len)
54649a2135eSLin Jinhan {
54749a2135eSLin Jinhan 	u32 reg_ctrl = 0;
54849a2135eSLin Jinhan 	int ret;
54949a2135eSLin Jinhan 
55049a2135eSLin Jinhan 	if (!key || !key_len || key_len > 64)
55149a2135eSLin Jinhan 		return -EINVAL;
55249a2135eSLin Jinhan 
55349a2135eSLin Jinhan 	clear_key_regs();
55449a2135eSLin Jinhan 
55549a2135eSLin Jinhan 	write_key_reg(0, key, key_len);
55649a2135eSLin Jinhan 
55749a2135eSLin Jinhan 	ret = rk_hash_init(hw_ctx, algo);
55849a2135eSLin Jinhan 	if (ret)
55949a2135eSLin Jinhan 		return ret;
56049a2135eSLin Jinhan 
56149a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_HASH_CTL) | CRYPTO_HMAC_ENABLE;
56249a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
56349a2135eSLin Jinhan 
56449a2135eSLin Jinhan 	return ret;
56549a2135eSLin Jinhan }
56649a2135eSLin Jinhan 
56749a2135eSLin Jinhan static int rockchip_crypto_hmac_init(struct udevice *dev,
56849a2135eSLin Jinhan 				     sha_context *ctx, u8 *key, u32 key_len)
56949a2135eSLin Jinhan {
57049a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
57149a2135eSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
57249a2135eSLin Jinhan 
57349a2135eSLin Jinhan 	if (!ctx)
57449a2135eSLin Jinhan 		return -EINVAL;
57549a2135eSLin Jinhan 
57649a2135eSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
57749a2135eSLin Jinhan 
57849a2135eSLin Jinhan 	priv->length = 0;
57949a2135eSLin Jinhan 
58049a2135eSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
58149a2135eSLin Jinhan 						       priv, ctx->length,
58249a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
58349a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
58449a2135eSLin Jinhan 	if (!hash_ctx->hash_cache)
58549a2135eSLin Jinhan 		return -EFAULT;
58649a2135eSLin Jinhan 
58749a2135eSLin Jinhan 	return rk_hmac_init(priv->hw_ctx, ctx->algo, key, key_len);
58849a2135eSLin Jinhan }
58949a2135eSLin Jinhan 
59049a2135eSLin Jinhan static int rockchip_crypto_hmac_update(struct udevice *dev,
59149a2135eSLin Jinhan 				       u32 *input, u32 len)
59249a2135eSLin Jinhan {
59349a2135eSLin Jinhan 	return rockchip_crypto_sha_update(dev, input, len);
59449a2135eSLin Jinhan }
59549a2135eSLin Jinhan 
59649a2135eSLin Jinhan static int rockchip_crypto_hmac_final(struct udevice *dev,
59749a2135eSLin Jinhan 				      sha_context *ctx, u8 *output)
59849a2135eSLin Jinhan {
59949a2135eSLin Jinhan 	return rockchip_crypto_sha_final(dev, ctx, output);
60049a2135eSLin Jinhan }
60149a2135eSLin Jinhan 
60249a2135eSLin Jinhan #endif
60349a2135eSLin Jinhan 
60449a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
60549a2135eSLin Jinhan static u8 g_key_chn;
60649a2135eSLin Jinhan 
60749a2135eSLin Jinhan static const u32 rk_mode2bc_mode[RK_MODE_MAX] = {
60849a2135eSLin Jinhan 	[RK_MODE_ECB] = CRYPTO_BC_ECB,
60949a2135eSLin Jinhan 	[RK_MODE_CBC] = CRYPTO_BC_CBC,
61049a2135eSLin Jinhan 	[RK_MODE_CTS] = CRYPTO_BC_CTS,
61149a2135eSLin Jinhan 	[RK_MODE_CTR] = CRYPTO_BC_CTR,
61249a2135eSLin Jinhan 	[RK_MODE_CFB] = CRYPTO_BC_CFB,
61349a2135eSLin Jinhan 	[RK_MODE_OFB] = CRYPTO_BC_OFB,
61449a2135eSLin Jinhan 	[RK_MODE_XTS] = CRYPTO_BC_XTS,
615*c3ce9937SLin Jinhan 	[RK_MODE_CCM] = CRYPTO_BC_CCM,
616*c3ce9937SLin Jinhan 	[RK_MODE_GCM] = CRYPTO_BC_GCM,
617d9332f1cSLin Jinhan 	[RK_MODE_CMAC] = CRYPTO_BC_CMAC,
618d9332f1cSLin Jinhan 	[RK_MODE_CBC_MAC] = CRYPTO_BC_CBC_MAC,
61949a2135eSLin Jinhan };
62049a2135eSLin Jinhan 
621*c3ce9937SLin Jinhan static inline void set_pc_len_reg(u32 chn, u64 pc_len)
622*c3ce9937SLin Jinhan {
623*c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_PC_LEN_0 + chn * 0x08;
624*c3ce9937SLin Jinhan 
625*c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
626*c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
627*c3ce9937SLin Jinhan }
628*c3ce9937SLin Jinhan 
629*c3ce9937SLin Jinhan static inline void set_aad_len_reg(u32 chn, u64 pc_len)
630*c3ce9937SLin Jinhan {
631*c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_AAD_LEN_0 + chn * 0x08;
632*c3ce9937SLin Jinhan 
633*c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
634*c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
635*c3ce9937SLin Jinhan }
636*c3ce9937SLin Jinhan 
63749a2135eSLin Jinhan static inline bool is_des_mode(u32 rk_mode)
63849a2135eSLin Jinhan {
63949a2135eSLin Jinhan 	return (rk_mode == RK_MODE_ECB ||
64049a2135eSLin Jinhan 		rk_mode == RK_MODE_CBC ||
64149a2135eSLin Jinhan 		rk_mode == RK_MODE_CFB ||
64249a2135eSLin Jinhan 		rk_mode == RK_MODE_OFB);
64349a2135eSLin Jinhan }
64449a2135eSLin Jinhan 
64549a2135eSLin Jinhan static void dump_crypto_state(struct crypto_lli_desc *desc, int ret)
64649a2135eSLin Jinhan {
64749a2135eSLin Jinhan 	IMSG("%s\n", ret == -ETIME ? "timeout" : "dismatch");
64849a2135eSLin Jinhan 
64949a2135eSLin Jinhan 	IMSG("CRYPTO_DMA_INT_ST = %08x, expect_int = %08x\n",
65049a2135eSLin Jinhan 	     tmp, expt_int);
65149a2135eSLin Jinhan 	IMSG("data desc		= %p\n", desc);
65249a2135eSLin Jinhan 	IMSG("\taddr_in		= [%08x <=> %08x]\n",
65349a2135eSLin Jinhan 	     desc->src_addr, (u32)virt_to_phys(in));
65449a2135eSLin Jinhan 	IMSG("\taddr_out	= [%08x <=> %08x]\n",
65549a2135eSLin Jinhan 	     desc->dst_addr, (u32)virt_to_phys(out));
65649a2135eSLin Jinhan 	IMSG("\tsrc_len		= [%08x <=> %08x]\n",
65749a2135eSLin Jinhan 	     desc->src_len, (u32)len);
65849a2135eSLin Jinhan 	IMSG("\tdst_len		= %08x\n", desc->dst_len);
65949a2135eSLin Jinhan 	IMSG("\tdma_ctl		= %08x\n", desc->dma_ctrl);
66049a2135eSLin Jinhan 	IMSG("\tuser_define	= %08x\n", desc->user_define);
66149a2135eSLin Jinhan 
66249a2135eSLin Jinhan 	IMSG("\n\nDMA CRYPTO_DMA_LLI_ADDR status = %08x\n",
66349a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_ADDR));
66449a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_ST status = %08x\n",
66549a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_ST));
66649a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_STATE status = %08x\n",
66749a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_STATE));
66849a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_LLI_RADDR status = %08x\n",
66949a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_RADDR));
67049a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_SRC_RADDR status = %08x\n",
67149a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_SRC_RADDR));
67249a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_DST_RADDR status = %08x\n",
67349a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
67449a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_ST status = %08x\n",
67549a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_ST));
67649a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_STATE status = %08x\n",
67749a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_STATE));
67849a2135eSLin Jinhan 	IMSG("DMA CRYPTO_TAG_VALID status = %08x\n",
67949a2135eSLin Jinhan 	     crypto_read(CRYPTO_TAG_VALID));
68049a2135eSLin Jinhan 	IMSG("LOCKSTEP status = %08x\n\n",
68149a2135eSLin Jinhan 	     crypto_read(0x618));
68249a2135eSLin Jinhan 
68349a2135eSLin Jinhan 	IMSG("dst %dbyte not transferred\n",
68449a2135eSLin Jinhan 	     desc->dst_addr + desc->dst_len -
68549a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
68649a2135eSLin Jinhan }
68749a2135eSLin Jinhan 
688*c3ce9937SLin Jinhan static int ccm128_set_iv_reg(u32 chn, const u8 *nonce, u32 nlen)
689*c3ce9937SLin Jinhan {
690*c3ce9937SLin Jinhan 	u8 iv_buf[AES_BLOCK_SIZE];
691*c3ce9937SLin Jinhan 	u32 L;
692*c3ce9937SLin Jinhan 
693*c3ce9937SLin Jinhan 	memset(iv_buf, 0x00, sizeof(iv_buf));
694*c3ce9937SLin Jinhan 
695*c3ce9937SLin Jinhan 	L = 15 - nlen;
696*c3ce9937SLin Jinhan 	iv_buf[0] = ((u8)(L - 1) & 7);
697*c3ce9937SLin Jinhan 
698*c3ce9937SLin Jinhan 	/* the L parameter */
699*c3ce9937SLin Jinhan 	L = iv_buf[0] & 7;
700*c3ce9937SLin Jinhan 
701*c3ce9937SLin Jinhan 	/* nonce is too short */
702*c3ce9937SLin Jinhan 	if (nlen < (14 - L))
703*c3ce9937SLin Jinhan 		return -EINVAL;
704*c3ce9937SLin Jinhan 
705*c3ce9937SLin Jinhan 	/* clear aad flag */
706*c3ce9937SLin Jinhan 	iv_buf[0] &= ~0x40;
707*c3ce9937SLin Jinhan 	memcpy(&iv_buf[1], nonce, 14 - L);
708*c3ce9937SLin Jinhan 
709*c3ce9937SLin Jinhan 	set_iv_reg(chn, iv_buf, AES_BLOCK_SIZE);
710*c3ce9937SLin Jinhan 
711*c3ce9937SLin Jinhan 	return 0;
712*c3ce9937SLin Jinhan }
713*c3ce9937SLin Jinhan 
714*c3ce9937SLin Jinhan static void ccm_aad_padding(u32 aad_len, u8 *padding, u32 *padding_size)
715*c3ce9937SLin Jinhan {
716*c3ce9937SLin Jinhan 	u32 i;
717*c3ce9937SLin Jinhan 
718*c3ce9937SLin Jinhan 	i = aad_len < (0x10000 - 0x100) ? 2 : 6;
719*c3ce9937SLin Jinhan 
720*c3ce9937SLin Jinhan 	if (i == 2) {
721*c3ce9937SLin Jinhan 		padding[0] = (u8)(aad_len >> 8);
722*c3ce9937SLin Jinhan 		padding[1] = (u8)aad_len;
723*c3ce9937SLin Jinhan 	} else {
724*c3ce9937SLin Jinhan 		padding[0] = 0xFF;
725*c3ce9937SLin Jinhan 		padding[1] = 0xFE;
726*c3ce9937SLin Jinhan 		padding[2] = (u8)(aad_len >> 24);
727*c3ce9937SLin Jinhan 		padding[3] = (u8)(aad_len >> 16);
728*c3ce9937SLin Jinhan 		padding[4] = (u8)(aad_len >> 8);
729*c3ce9937SLin Jinhan 	}
730*c3ce9937SLin Jinhan 
731*c3ce9937SLin Jinhan 	*padding_size = i;
732*c3ce9937SLin Jinhan }
733*c3ce9937SLin Jinhan 
734*c3ce9937SLin Jinhan static int ccm_compose_aad_iv(u8 *aad_iv, u32 data_len, u32 tag_size)
735*c3ce9937SLin Jinhan {
736*c3ce9937SLin Jinhan 	aad_iv[0] |= ((u8)(((tag_size - 2) / 2) & 7) << 3);
737*c3ce9937SLin Jinhan 
738*c3ce9937SLin Jinhan 	aad_iv[12] = (u8)(data_len >> 24);
739*c3ce9937SLin Jinhan 	aad_iv[13] = (u8)(data_len >> 16);
740*c3ce9937SLin Jinhan 	aad_iv[14] = (u8)(data_len >> 8);
741*c3ce9937SLin Jinhan 	aad_iv[15] = (u8)data_len;
742*c3ce9937SLin Jinhan 
743*c3ce9937SLin Jinhan 	aad_iv[0] |= 0x40;	//set aad flag
744*c3ce9937SLin Jinhan 
745*c3ce9937SLin Jinhan 	return 0;
746*c3ce9937SLin Jinhan }
747*c3ce9937SLin Jinhan 
74849a2135eSLin Jinhan static int hw_cipher_init(u32 chn, const u8 *key, const u8 *twk_key,
74949a2135eSLin Jinhan 			  u32 key_len, const u8 *iv, u32 iv_len,
75049a2135eSLin Jinhan 			  u32 algo, u32 mode, bool enc)
75149a2135eSLin Jinhan {
75249a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
75349a2135eSLin Jinhan 	u32 key_chn_sel = chn;
75449a2135eSLin Jinhan 	u32 reg_ctrl = 0;
75549a2135eSLin Jinhan 
75649a2135eSLin Jinhan 	IMSG("%s: key addr is %p, key_len is %d, iv addr is %p",
75749a2135eSLin Jinhan 	     __func__, key, key_len, iv);
75849a2135eSLin Jinhan 	if (rk_mode >= RK_MODE_MAX)
75949a2135eSLin Jinhan 		return -EINVAL;
76049a2135eSLin Jinhan 
76149a2135eSLin Jinhan 	switch (algo) {
76249a2135eSLin Jinhan 	case CRYPTO_DES:
76349a2135eSLin Jinhan 		if (key_len > DES_BLOCK_SIZE)
76449a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_TDES;
76549a2135eSLin Jinhan 		else
76649a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_DES;
76749a2135eSLin Jinhan 		break;
76849a2135eSLin Jinhan 	case CRYPTO_AES:
76949a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_AES;
77049a2135eSLin Jinhan 		break;
77149a2135eSLin Jinhan 	case CRYPTO_SM4:
77249a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_SM4;
77349a2135eSLin Jinhan 		break;
77449a2135eSLin Jinhan 	default:
77549a2135eSLin Jinhan 		return -EINVAL;
77649a2135eSLin Jinhan 	}
77749a2135eSLin Jinhan 
77849a2135eSLin Jinhan 	if (algo == CRYPTO_AES || algo == CRYPTO_SM4) {
77949a2135eSLin Jinhan 		switch (key_len) {
78049a2135eSLin Jinhan 		case AES_KEYSIZE_128:
78149a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_128_bit_key;
78249a2135eSLin Jinhan 			break;
78349a2135eSLin Jinhan 		case AES_KEYSIZE_192:
78449a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_192_bit_key;
78549a2135eSLin Jinhan 			break;
78649a2135eSLin Jinhan 		case AES_KEYSIZE_256:
78749a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_256_bit_key;
78849a2135eSLin Jinhan 			break;
78949a2135eSLin Jinhan 		default:
79049a2135eSLin Jinhan 			return -EINVAL;
79149a2135eSLin Jinhan 		}
79249a2135eSLin Jinhan 	}
79349a2135eSLin Jinhan 
79449a2135eSLin Jinhan 	reg_ctrl |= rk_mode2bc_mode[rk_mode];
79549a2135eSLin Jinhan 	if (!enc)
79649a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_DECRYPT;
79749a2135eSLin Jinhan 
79849a2135eSLin Jinhan 	/* write key data to reg */
79949a2135eSLin Jinhan 	write_key_reg(key_chn_sel, key, key_len);
80049a2135eSLin Jinhan 
80149a2135eSLin Jinhan 	/* write twk key for xts mode */
80249a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS)
80349a2135eSLin Jinhan 		write_key_reg(key_chn_sel + 4, twk_key, key_len);
80449a2135eSLin Jinhan 
80549a2135eSLin Jinhan 	/* set iv reg */
806*c3ce9937SLin Jinhan 	if (rk_mode == RK_MODE_CCM)
807*c3ce9937SLin Jinhan 		ccm128_set_iv_reg(chn, iv, iv_len);
808*c3ce9937SLin Jinhan 	else
80949a2135eSLin Jinhan 		set_iv_reg(chn, iv, iv_len);
81049a2135eSLin Jinhan 
81149a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
81249a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
81349a2135eSLin Jinhan 	crypto_write(CRYPTO_LIST_DONE_INT_EN | CRYPTO_DST_ITEM_DONE_INT_EN,
81449a2135eSLin Jinhan 		     CRYPTO_DMA_INT_EN);
81549a2135eSLin Jinhan 
81649a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
81749a2135eSLin Jinhan 
81849a2135eSLin Jinhan 	return 0;
81949a2135eSLin Jinhan }
82049a2135eSLin Jinhan 
82149a2135eSLin Jinhan static int hw_cipher_crypt(const u8 *in, u8 *out, u64 len,
822*c3ce9937SLin Jinhan 			   const u8 *aad, u32 aad_len,
823*c3ce9937SLin Jinhan 			   u8 *tag, u32 tag_len, u32 mode)
82449a2135eSLin Jinhan {
825*c3ce9937SLin Jinhan 	struct crypto_lli_desc *data_desc = NULL, *aad_desc = NULL;
826*c3ce9937SLin Jinhan 	u8 *dma_in = NULL, *dma_out = NULL, *aad_tmp = NULL;
82749a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
82849a2135eSLin Jinhan 	u32 reg_ctrl = 0, tmp_len = 0;
82949a2135eSLin Jinhan 	u32 expt_int = 0, mask = 0;
83049a2135eSLin Jinhan 	u32 key_chn = g_key_chn;
83149a2135eSLin Jinhan 	u32 tmp, dst_len = 0;
83249a2135eSLin Jinhan 	int ret = -1;
83349a2135eSLin Jinhan 
83449a2135eSLin Jinhan 	if (rk_mode == RK_MODE_CTS && len <= AES_BLOCK_SIZE) {
83549a2135eSLin Jinhan 		printf("CTS mode length %u < 16Byte\n", (u32)len);
83649a2135eSLin Jinhan 		return -EINVAL;
83749a2135eSLin Jinhan 	}
83849a2135eSLin Jinhan 
83949a2135eSLin Jinhan 	tmp_len = (rk_mode == RK_MODE_CTR) ? ROUNDUP(len, AES_BLOCK_SIZE) : len;
84049a2135eSLin Jinhan 
84149a2135eSLin Jinhan 	data_desc = align_malloc(sizeof(*data_desc), LLI_ADDR_ALIGN_SIZE);
84249a2135eSLin Jinhan 	if (!data_desc)
84349a2135eSLin Jinhan 		goto exit;
84449a2135eSLin Jinhan 
84549a2135eSLin Jinhan 	if (IS_ALIGNED((ulong)in, DATA_ADDR_ALIGN_SIZE) && tmp_len == len)
84649a2135eSLin Jinhan 		dma_in = (void *)in;
84749a2135eSLin Jinhan 	else
84849a2135eSLin Jinhan 		dma_in = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
84949a2135eSLin Jinhan 	if (!dma_in)
85049a2135eSLin Jinhan 		goto exit;
85149a2135eSLin Jinhan 
85249a2135eSLin Jinhan 	if (out) {
85349a2135eSLin Jinhan 		if (IS_ALIGNED((ulong)out, DATA_ADDR_ALIGN_SIZE) &&
85449a2135eSLin Jinhan 		    tmp_len == len)
85549a2135eSLin Jinhan 			dma_out = out;
85649a2135eSLin Jinhan 		else
85749a2135eSLin Jinhan 			dma_out = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
85849a2135eSLin Jinhan 		if (!dma_out)
85949a2135eSLin Jinhan 			goto exit;
86049a2135eSLin Jinhan 		dst_len = tmp_len;
86149a2135eSLin Jinhan 	}
86249a2135eSLin Jinhan 
86349a2135eSLin Jinhan 	memset(data_desc, 0x00, sizeof(*data_desc));
86449a2135eSLin Jinhan 	if (dma_in != in)
86549a2135eSLin Jinhan 		memcpy(dma_in, in, len);
86649a2135eSLin Jinhan 
86749a2135eSLin Jinhan 	data_desc->src_addr    = (u32)virt_to_phys(dma_in);
86849a2135eSLin Jinhan 	data_desc->src_len     = tmp_len;
86949a2135eSLin Jinhan 	data_desc->dst_addr    = (u32)virt_to_phys(dma_out);
87049a2135eSLin Jinhan 	data_desc->dst_len     = dst_len;
871d9332f1cSLin Jinhan 	data_desc->dma_ctrl    = LLI_DMA_CTRL_LAST;
872d9332f1cSLin Jinhan 
873d9332f1cSLin Jinhan 	if (IS_MAC_MODE(rk_mode)) {
874d9332f1cSLin Jinhan 		expt_int = CRYPTO_LIST_DONE_INT_ST;
875d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_LIST_DONE;
876d9332f1cSLin Jinhan 	} else {
87749a2135eSLin Jinhan 		expt_int = CRYPTO_DST_ITEM_DONE_INT_ST;
878d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_DST_DONE;
879d9332f1cSLin Jinhan 	}
88049a2135eSLin Jinhan 
881*c3ce9937SLin Jinhan 	if (rk_mode == RK_MODE_CCM || rk_mode == RK_MODE_GCM) {
882*c3ce9937SLin Jinhan 		u32 aad_tmp_len = 0;
883*c3ce9937SLin Jinhan 
884*c3ce9937SLin Jinhan 		data_desc->user_define = LLI_USER_STRING_START |
885*c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
886*c3ce9937SLin Jinhan 					 (key_chn << 4);
887*c3ce9937SLin Jinhan 
888*c3ce9937SLin Jinhan 		aad_desc = align_malloc(sizeof(*aad_desc), LLI_ADDR_ALIGN_SIZE);
889*c3ce9937SLin Jinhan 		if (!aad_desc)
890*c3ce9937SLin Jinhan 			goto exit;
891*c3ce9937SLin Jinhan 
892*c3ce9937SLin Jinhan 		memset(aad_desc, 0x00, sizeof(*aad_desc));
893*c3ce9937SLin Jinhan 		aad_desc->next_addr = (u32)virt_to_phys(data_desc);
894*c3ce9937SLin Jinhan 		aad_desc->user_define = LLI_USER_CPIHER_START |
895*c3ce9937SLin Jinhan 					 LLI_USER_STRING_START |
896*c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
897*c3ce9937SLin Jinhan 					 LLI_USER_STRING_AAD |
898*c3ce9937SLin Jinhan 					 (key_chn << 4);
899*c3ce9937SLin Jinhan 
900*c3ce9937SLin Jinhan 		if (rk_mode == RK_MODE_CCM) {
901*c3ce9937SLin Jinhan 			u8 padding[AES_BLOCK_SIZE];
902*c3ce9937SLin Jinhan 			u32 padding_size = 0;
903*c3ce9937SLin Jinhan 
904*c3ce9937SLin Jinhan 			memset(padding, 0x00, sizeof(padding));
905*c3ce9937SLin Jinhan 			ccm_aad_padding(aad_len, padding, &padding_size);
906*c3ce9937SLin Jinhan 
907*c3ce9937SLin Jinhan 			aad_tmp_len = aad_len + AES_BLOCK_SIZE + padding_size;
908*c3ce9937SLin Jinhan 			aad_tmp_len = ROUNDUP(aad_tmp_len, AES_BLOCK_SIZE);
909*c3ce9937SLin Jinhan 			aad_tmp = align_malloc(aad_tmp_len,
910*c3ce9937SLin Jinhan 					       DATA_ADDR_ALIGN_SIZE);
911*c3ce9937SLin Jinhan 			if (!aad_tmp)
912*c3ce9937SLin Jinhan 				goto exit;
913*c3ce9937SLin Jinhan 
914*c3ce9937SLin Jinhan 			/* read iv data from reg */
915*c3ce9937SLin Jinhan 			get_iv_reg(key_chn, aad_tmp, AES_BLOCK_SIZE);
916*c3ce9937SLin Jinhan 			ccm_compose_aad_iv(aad_tmp, tmp_len, tag_len);
917*c3ce9937SLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE, padding, padding_size);
918*c3ce9937SLin Jinhan 			memset(aad_tmp + aad_tmp_len - AES_BLOCK_SIZE,
919*c3ce9937SLin Jinhan 			       0x00, AES_BLOCK_SIZE);
920*c3ce9937SLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE + padding_size,
921*c3ce9937SLin Jinhan 			       aad, aad_len);
922*c3ce9937SLin Jinhan 		} else {
923*c3ce9937SLin Jinhan 			aad_tmp_len = aad_len;
924*c3ce9937SLin Jinhan 			aad_tmp = align_malloc(aad_tmp_len,
925*c3ce9937SLin Jinhan 					       DATA_ADDR_ALIGN_SIZE);
926*c3ce9937SLin Jinhan 			if (!aad_tmp)
927*c3ce9937SLin Jinhan 				goto exit;
928*c3ce9937SLin Jinhan 
929*c3ce9937SLin Jinhan 			memcpy(aad_tmp, aad, aad_tmp_len);
930*c3ce9937SLin Jinhan 			set_aad_len_reg(key_chn, aad_tmp_len);
931*c3ce9937SLin Jinhan 			set_pc_len_reg(key_chn, tmp_len);
932*c3ce9937SLin Jinhan 		}
933*c3ce9937SLin Jinhan 
934*c3ce9937SLin Jinhan 		aad_desc->src_addr = (u32)virt_to_phys(aad_tmp);
935*c3ce9937SLin Jinhan 		aad_desc->src_len  = aad_tmp_len;
936*c3ce9937SLin Jinhan 		crypto_write((u32)virt_to_phys(aad_desc), CRYPTO_DMA_LLI_ADDR);
937*c3ce9937SLin Jinhan 		cache_op_inner(DCACHE_AREA_CLEAN, aad_tmp, aad_tmp_len);
938*c3ce9937SLin Jinhan 		cache_op_inner(DCACHE_AREA_CLEAN, aad_desc, sizeof(*aad_desc));
939*c3ce9937SLin Jinhan 	} else {
940*c3ce9937SLin Jinhan 		data_desc->user_define = LLI_USER_CPIHER_START |
941*c3ce9937SLin Jinhan 					 LLI_USER_STRING_START |
942*c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
943*c3ce9937SLin Jinhan 					 (key_chn << 4);
94449a2135eSLin Jinhan 		crypto_write((u32)virt_to_phys(data_desc), CRYPTO_DMA_LLI_ADDR);
945*c3ce9937SLin Jinhan 	}
94649a2135eSLin Jinhan 
94749a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, data_desc, sizeof(*data_desc));
94849a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, dma_in, tmp_len);
94949a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_INVALIDATE, dma_out, tmp_len);
95049a2135eSLin Jinhan 
95149a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
95249a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
95349a2135eSLin Jinhan 	crypto_write(CRYPTO_DST_ITEM_DONE_INT_EN | CRYPTO_LIST_DONE_INT_EN,
95449a2135eSLin Jinhan 		     CRYPTO_DMA_INT_EN);
95549a2135eSLin Jinhan 
95649a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_BC_CTL) | CRYPTO_BC_ENABLE;
95749a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
95849a2135eSLin Jinhan 	crypto_write(0x00010001, CRYPTO_DMA_CTL);//start
95949a2135eSLin Jinhan 
96049a2135eSLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
96149a2135eSLin Jinhan 
96249a2135eSLin Jinhan 	/* wait calc ok */
96349a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
96449a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
96549a2135eSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
96649a2135eSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
96749a2135eSLin Jinhan 
96849a2135eSLin Jinhan 	if ((tmp & mask) == expt_int) {
96949a2135eSLin Jinhan 		if (out && out != dma_out)
97049a2135eSLin Jinhan 			memcpy(out, dma_out, len);
971d9332f1cSLin Jinhan 
972d9332f1cSLin Jinhan 		if (IS_NEED_TAG(rk_mode)) {
973d9332f1cSLin Jinhan 			ret = WAIT_TAG_VALID(key_chn, RK_CRYPTO_TIMEOUT);
974d9332f1cSLin Jinhan 			get_tag_from_reg(key_chn, tag, AES_BLOCK_SIZE);
975d9332f1cSLin Jinhan 		}
97649a2135eSLin Jinhan 	} else {
97749a2135eSLin Jinhan 		dump_crypto_state(data_desc, ret);
97849a2135eSLin Jinhan 		ret = -1;
97949a2135eSLin Jinhan 	}
98049a2135eSLin Jinhan 
98149a2135eSLin Jinhan exit:
98249a2135eSLin Jinhan 	crypto_write(0xffff0000, CRYPTO_BC_CTL);//bc_ctl disable
98349a2135eSLin Jinhan 	align_free(data_desc);
984*c3ce9937SLin Jinhan 	align_free(aad_desc);
98549a2135eSLin Jinhan 	if (dma_in && dma_in != in)
98649a2135eSLin Jinhan 		align_free(dma_in);
98749a2135eSLin Jinhan 	if (dma_out && dma_out != out)
98849a2135eSLin Jinhan 		align_free(dma_out);
98949a2135eSLin Jinhan 
99049a2135eSLin Jinhan 	return ret;
99149a2135eSLin Jinhan }
99249a2135eSLin Jinhan 
99349a2135eSLin Jinhan static int hw_aes_init(u32 chn, const u8 *key, const u8 *twk_key, u32 key_len,
99449a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
99549a2135eSLin Jinhan {
99649a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
99749a2135eSLin Jinhan 
998d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
999d9332f1cSLin Jinhan 		return -EINVAL;
1000d9332f1cSLin Jinhan 
100149a2135eSLin Jinhan 	if (iv_len > AES_BLOCK_SIZE)
100249a2135eSLin Jinhan 		return -EINVAL;
100349a2135eSLin Jinhan 
1004d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
100549a2135eSLin Jinhan 		if (!iv || iv_len != AES_BLOCK_SIZE)
100649a2135eSLin Jinhan 			return -EINVAL;
100749a2135eSLin Jinhan 	} else {
100849a2135eSLin Jinhan 		iv_len = 0;
100949a2135eSLin Jinhan 	}
101049a2135eSLin Jinhan 
101149a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
101249a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_256)
101349a2135eSLin Jinhan 			return -EINVAL;
101449a2135eSLin Jinhan 
101549a2135eSLin Jinhan 		if (!key || !twk_key)
101649a2135eSLin Jinhan 			return -EINVAL;
101749a2135eSLin Jinhan 	} else {
101849a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 &&
101949a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_192 &&
102049a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_256)
102149a2135eSLin Jinhan 			return -EINVAL;
102249a2135eSLin Jinhan 	}
102349a2135eSLin Jinhan 
102449a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
102549a2135eSLin Jinhan 			      CRYPTO_AES, mode, enc);
102649a2135eSLin Jinhan }
102749a2135eSLin Jinhan 
102849a2135eSLin Jinhan static int hw_sm4_init(u32  chn, const u8 *key, const u8 *twk_key, u32 key_len,
102949a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
103049a2135eSLin Jinhan {
103149a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
103249a2135eSLin Jinhan 
1033d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
1034d9332f1cSLin Jinhan 		return -EINVAL;
1035d9332f1cSLin Jinhan 
103649a2135eSLin Jinhan 	if (iv_len > SM4_BLOCK_SIZE || key_len != SM4_KEYSIZE)
103749a2135eSLin Jinhan 		return -EINVAL;
103849a2135eSLin Jinhan 
1039d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
104049a2135eSLin Jinhan 		if (!iv || iv_len != SM4_BLOCK_SIZE)
104149a2135eSLin Jinhan 			return -EINVAL;
104249a2135eSLin Jinhan 	} else {
104349a2135eSLin Jinhan 		iv_len = 0;
104449a2135eSLin Jinhan 	}
104549a2135eSLin Jinhan 
104649a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
104749a2135eSLin Jinhan 		if (!key || !twk_key)
104849a2135eSLin Jinhan 			return -EINVAL;
104949a2135eSLin Jinhan 	}
105049a2135eSLin Jinhan 
105149a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
105249a2135eSLin Jinhan 			      CRYPTO_SM4, mode, enc);
105349a2135eSLin Jinhan }
105449a2135eSLin Jinhan 
105549a2135eSLin Jinhan int rk_crypto_des(struct udevice *dev, u32 mode, const u8 *key, u32 key_len,
105649a2135eSLin Jinhan 		  const u8 *iv, const u8 *in, u8 *out, u32 len, bool enc)
105749a2135eSLin Jinhan {
105849a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
105949a2135eSLin Jinhan 	u8 tmp_key[24];
106049a2135eSLin Jinhan 	int ret;
106149a2135eSLin Jinhan 
106249a2135eSLin Jinhan 	if (!is_des_mode(rk_mode))
106349a2135eSLin Jinhan 		return -EINVAL;
106449a2135eSLin Jinhan 
106549a2135eSLin Jinhan 	if (key_len == DES_BLOCK_SIZE || key_len == 3 * DES_BLOCK_SIZE) {
106649a2135eSLin Jinhan 		memcpy(tmp_key, key, key_len);
106749a2135eSLin Jinhan 	} else if (key_len == 2 * DES_BLOCK_SIZE) {
106849a2135eSLin Jinhan 		memcpy(tmp_key, key, 16);
106949a2135eSLin Jinhan 		memcpy(tmp_key + 16, key, 8);
107049a2135eSLin Jinhan 		key_len = 3 * DES_BLOCK_SIZE;
107149a2135eSLin Jinhan 	} else {
107249a2135eSLin Jinhan 		return -EINVAL;
107349a2135eSLin Jinhan 	}
107449a2135eSLin Jinhan 
107549a2135eSLin Jinhan 	ret = hw_cipher_init(0, tmp_key, NULL, key_len, iv, DES_BLOCK_SIZE,
107649a2135eSLin Jinhan 			     CRYPTO_DES, mode, enc);
107749a2135eSLin Jinhan 	if (ret)
107849a2135eSLin Jinhan 		goto exit;
107949a2135eSLin Jinhan 
108049a2135eSLin Jinhan 	ret = hw_cipher_crypt(in, out, len, NULL, 0,
108149a2135eSLin Jinhan 			      NULL, 0, mode);
108249a2135eSLin Jinhan 
108349a2135eSLin Jinhan exit:
108449a2135eSLin Jinhan 	return ret;
108549a2135eSLin Jinhan }
108649a2135eSLin Jinhan 
108749a2135eSLin Jinhan int rk_crypto_aes(struct udevice *dev, u32 mode,
108849a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
108949a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
109049a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
109149a2135eSLin Jinhan {
109249a2135eSLin Jinhan 	int ret;
109349a2135eSLin Jinhan 
109449a2135eSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
109549a2135eSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
109649a2135eSLin Jinhan 	if (key_len == AES_KEYSIZE_192)
109749a2135eSLin Jinhan 		return -EINVAL;
109849a2135eSLin Jinhan #endif
109949a2135eSLin Jinhan 
110049a2135eSLin Jinhan 	ret = hw_aes_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
110149a2135eSLin Jinhan 	if (ret)
110249a2135eSLin Jinhan 		return ret;
110349a2135eSLin Jinhan 
110449a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0,
110549a2135eSLin Jinhan 			       NULL, 0, mode);
110649a2135eSLin Jinhan }
110749a2135eSLin Jinhan 
110849a2135eSLin Jinhan int rk_crypto_sm4(struct udevice *dev, u32 mode,
110949a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
111049a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
111149a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
111249a2135eSLin Jinhan {
111349a2135eSLin Jinhan 	int ret;
111449a2135eSLin Jinhan 
111549a2135eSLin Jinhan 	ret = hw_sm4_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
111649a2135eSLin Jinhan 	if (ret)
111749a2135eSLin Jinhan 		return ret;
111849a2135eSLin Jinhan 
111949a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0, NULL, 0, mode);
112049a2135eSLin Jinhan }
112149a2135eSLin Jinhan 
112249a2135eSLin Jinhan int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx,
112349a2135eSLin Jinhan 			   const u8 *in, u8 *out, u32 len, bool enc)
112449a2135eSLin Jinhan {
112549a2135eSLin Jinhan 	switch (ctx->algo) {
112649a2135eSLin Jinhan 	case CRYPTO_DES:
112749a2135eSLin Jinhan 		return rk_crypto_des(dev, ctx->mode, ctx->key, ctx->key_len,
112849a2135eSLin Jinhan 				     ctx->iv, in, out, len, enc);
112949a2135eSLin Jinhan 	case CRYPTO_AES:
113049a2135eSLin Jinhan 		return rk_crypto_aes(dev, ctx->mode,
113149a2135eSLin Jinhan 				     ctx->key, ctx->twk_key, ctx->key_len,
113249a2135eSLin Jinhan 				     ctx->iv, ctx->iv_len, in, out, len, enc);
113349a2135eSLin Jinhan 	case CRYPTO_SM4:
113449a2135eSLin Jinhan 		return rk_crypto_sm4(dev, ctx->mode,
113549a2135eSLin Jinhan 				     ctx->key, ctx->twk_key, ctx->key_len,
113649a2135eSLin Jinhan 				     ctx->iv, ctx->iv_len, in, out, len, enc);
113749a2135eSLin Jinhan 	default:
113849a2135eSLin Jinhan 		return -EINVAL;
113949a2135eSLin Jinhan 	}
114049a2135eSLin Jinhan }
1141d9332f1cSLin Jinhan 
1142d9332f1cSLin Jinhan int rk_crypto_mac(struct udevice *dev, u32 algo, u32 mode,
1143d9332f1cSLin Jinhan 		  const u8 *key, u32 key_len,
1144d9332f1cSLin Jinhan 		  const u8 *in, u32 len, u8 *tag)
1145d9332f1cSLin Jinhan {
1146d9332f1cSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1147d9332f1cSLin Jinhan 	int ret;
1148d9332f1cSLin Jinhan 
1149d9332f1cSLin Jinhan 	if (!IS_MAC_MODE(rk_mode))
1150d9332f1cSLin Jinhan 		return -EINVAL;
1151d9332f1cSLin Jinhan 
1152d9332f1cSLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1153d9332f1cSLin Jinhan 		return -EINVAL;
1154d9332f1cSLin Jinhan 
1155d9332f1cSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1156d9332f1cSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1157d9332f1cSLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1158d9332f1cSLin Jinhan 		return -EINVAL;
1159d9332f1cSLin Jinhan #endif
1160d9332f1cSLin Jinhan 
1161d9332f1cSLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, NULL, 0,
1162d9332f1cSLin Jinhan 			     algo, mode, true);
1163d9332f1cSLin Jinhan 	if (ret)
1164d9332f1cSLin Jinhan 		return ret;
1165d9332f1cSLin Jinhan 
1166d9332f1cSLin Jinhan 	return hw_cipher_crypt(in, NULL, len, NULL, 0,
1167d9332f1cSLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1168d9332f1cSLin Jinhan }
1169d9332f1cSLin Jinhan 
1170d9332f1cSLin Jinhan int rockchip_crypto_mac(struct udevice *dev, cipher_context *ctx,
1171d9332f1cSLin Jinhan 			const u8 *in, u32 len, u8 *tag)
1172d9332f1cSLin Jinhan {
1173d9332f1cSLin Jinhan 	return rk_crypto_mac(dev, ctx->algo, ctx->mode,
1174d9332f1cSLin Jinhan 			     ctx->key, ctx->key_len, in, len, tag);
1175d9332f1cSLin Jinhan }
1176d9332f1cSLin Jinhan 
1177*c3ce9937SLin Jinhan int rk_crypto_ae(struct udevice *dev, u32 algo, u32 mode,
1178*c3ce9937SLin Jinhan 		 const u8 *key, u32 key_len, const u8 *nonce, u32 nonce_len,
1179*c3ce9937SLin Jinhan 		 const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1180*c3ce9937SLin Jinhan 		 u8 *out, u8 *tag)
1181*c3ce9937SLin Jinhan {
1182*c3ce9937SLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1183*c3ce9937SLin Jinhan 	int ret;
1184*c3ce9937SLin Jinhan 
1185*c3ce9937SLin Jinhan 	if (!IS_AE_MODE(rk_mode))
1186*c3ce9937SLin Jinhan 		return -EINVAL;
1187*c3ce9937SLin Jinhan 
1188*c3ce9937SLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1189*c3ce9937SLin Jinhan 		return -EINVAL;
1190*c3ce9937SLin Jinhan 
1191*c3ce9937SLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1192*c3ce9937SLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1193*c3ce9937SLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1194*c3ce9937SLin Jinhan 		return -EINVAL;
1195*c3ce9937SLin Jinhan #endif
1196*c3ce9937SLin Jinhan 
1197*c3ce9937SLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, nonce, nonce_len,
1198*c3ce9937SLin Jinhan 			     algo, mode, true);
1199*c3ce9937SLin Jinhan 	if (ret)
1200*c3ce9937SLin Jinhan 		return ret;
1201*c3ce9937SLin Jinhan 
1202*c3ce9937SLin Jinhan 	return hw_cipher_crypt(in, out, len, aad, aad_len,
1203*c3ce9937SLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1204*c3ce9937SLin Jinhan }
1205*c3ce9937SLin Jinhan 
1206*c3ce9937SLin Jinhan int rockchip_crypto_ae(struct udevice *dev, cipher_context *ctx,
1207*c3ce9937SLin Jinhan 		       const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1208*c3ce9937SLin Jinhan 		       u8 *out, u8 *tag)
1209*c3ce9937SLin Jinhan 
1210*c3ce9937SLin Jinhan {
1211*c3ce9937SLin Jinhan 	return rk_crypto_ae(dev, ctx->algo, ctx->mode, ctx->key, ctx->key_len,
1212*c3ce9937SLin Jinhan 			    ctx->iv, ctx->iv_len, in, len,
1213*c3ce9937SLin Jinhan 			    aad, aad_len, out, tag);
1214*c3ce9937SLin Jinhan }
1215*c3ce9937SLin Jinhan 
121649a2135eSLin Jinhan #endif
121749a2135eSLin Jinhan 
1218864e581cSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1219b353a43cSLin Jinhan static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx,
1220b353a43cSLin Jinhan 				      u8 *sign, u8 *output)
1221b353a43cSLin Jinhan {
1222b353a43cSLin Jinhan 	struct mpa_num *mpa_m = NULL, *mpa_e = NULL, *mpa_n = NULL;
1223b353a43cSLin Jinhan 	struct mpa_num *mpa_c = NULL, *mpa_result = NULL;
1224b353a43cSLin Jinhan 	u32 n_bits, n_words;
1225b353a43cSLin Jinhan 	u32 *rsa_result;
1226b353a43cSLin Jinhan 	int ret;
1227b353a43cSLin Jinhan 
1228b353a43cSLin Jinhan 	if (!ctx)
1229b353a43cSLin Jinhan 		return -EINVAL;
1230b353a43cSLin Jinhan 
1231b353a43cSLin Jinhan 	if (ctx->algo != CRYPTO_RSA512 &&
1232b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA1024 &&
1233b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA2048 &&
1234b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA3072 &&
1235b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA4096)
1236b353a43cSLin Jinhan 		return -EINVAL;
1237b353a43cSLin Jinhan 
1238b353a43cSLin Jinhan 	n_bits = crypto_algo_nbits(ctx->algo);
1239b353a43cSLin Jinhan 	n_words = BITS2WORD(n_bits);
1240b353a43cSLin Jinhan 
1241b353a43cSLin Jinhan 	rsa_result = malloc(BITS2BYTE(n_bits));
1242b353a43cSLin Jinhan 	if (!rsa_result)
1243b353a43cSLin Jinhan 		return -ENOMEM;
1244b353a43cSLin Jinhan 
1245b353a43cSLin Jinhan 	memset(rsa_result, 0x00, BITS2BYTE(n_bits));
1246b353a43cSLin Jinhan 
1247b353a43cSLin Jinhan 	ret = rk_mpa_alloc(&mpa_m);
1248b353a43cSLin Jinhan 	ret |= rk_mpa_alloc(&mpa_e);
1249b353a43cSLin Jinhan 	ret |= rk_mpa_alloc(&mpa_n);
1250b353a43cSLin Jinhan 	ret |= rk_mpa_alloc(&mpa_c);
1251b353a43cSLin Jinhan 	ret |= rk_mpa_alloc(&mpa_result);
1252b353a43cSLin Jinhan 	if (ret)
1253b353a43cSLin Jinhan 		goto exit;
1254b353a43cSLin Jinhan 
1255b353a43cSLin Jinhan 	mpa_m->d = (void *)sign;
1256b353a43cSLin Jinhan 	mpa_e->d = (void *)ctx->e;
1257b353a43cSLin Jinhan 	mpa_n->d = (void *)ctx->n;
1258b353a43cSLin Jinhan 	mpa_c->d = (void *)ctx->c;
1259b353a43cSLin Jinhan 	mpa_result->d = (void *)rsa_result;
1260b353a43cSLin Jinhan 
1261b353a43cSLin Jinhan 	mpa_m->size = n_words;
1262b353a43cSLin Jinhan 	mpa_e->size = n_words;
1263b353a43cSLin Jinhan 	mpa_n->size = n_words;
1264b353a43cSLin Jinhan 	mpa_c->size = n_words;
1265b353a43cSLin Jinhan 	mpa_result->size = n_words;
1266b353a43cSLin Jinhan 
1267b353a43cSLin Jinhan 	ret = rk_exptmod_np(mpa_m, mpa_e, mpa_n, mpa_c, mpa_result);
1268b353a43cSLin Jinhan 	if (!ret)
1269b353a43cSLin Jinhan 		memcpy(output, rsa_result, BITS2BYTE(n_bits));
1270b353a43cSLin Jinhan 
1271b353a43cSLin Jinhan exit:
1272b353a43cSLin Jinhan 	free(rsa_result);
1273b353a43cSLin Jinhan 	rk_mpa_free(&mpa_m);
1274b353a43cSLin Jinhan 	rk_mpa_free(&mpa_e);
1275b353a43cSLin Jinhan 	rk_mpa_free(&mpa_n);
1276b353a43cSLin Jinhan 	rk_mpa_free(&mpa_c);
1277b353a43cSLin Jinhan 	rk_mpa_free(&mpa_result);
1278b353a43cSLin Jinhan 
1279b353a43cSLin Jinhan 	return ret;
1280b353a43cSLin Jinhan }
1281864e581cSLin Jinhan #endif
1282b353a43cSLin Jinhan 
1283b353a43cSLin Jinhan static const struct dm_crypto_ops rockchip_crypto_ops = {
1284b353a43cSLin Jinhan 	.capability   = rockchip_crypto_capability,
1285b353a43cSLin Jinhan 	.sha_init     = rockchip_crypto_sha_init,
1286b353a43cSLin Jinhan 	.sha_update   = rockchip_crypto_sha_update,
1287b353a43cSLin Jinhan 	.sha_final    = rockchip_crypto_sha_final,
128849a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1289b353a43cSLin Jinhan 	.rsa_verify   = rockchip_crypto_rsa_verify,
129049a2135eSLin Jinhan #endif
129149a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
129249a2135eSLin Jinhan 	.hmac_init    = rockchip_crypto_hmac_init,
129349a2135eSLin Jinhan 	.hmac_update  = rockchip_crypto_hmac_update,
129449a2135eSLin Jinhan 	.hmac_final   = rockchip_crypto_hmac_final,
129549a2135eSLin Jinhan #endif
129649a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
129749a2135eSLin Jinhan 	.cipher_crypt = rockchip_crypto_cipher,
1298d9332f1cSLin Jinhan 	.cipher_mac = rockchip_crypto_mac,
1299*c3ce9937SLin Jinhan 	.cipher_ae  = rockchip_crypto_ae,
130049a2135eSLin Jinhan #endif
1301b353a43cSLin Jinhan };
1302b353a43cSLin Jinhan 
1303b353a43cSLin Jinhan /*
1304b353a43cSLin Jinhan  * Only use "clocks" to parse crypto clock id and use rockchip_get_clk().
1305b353a43cSLin Jinhan  * Because we always add crypto node in U-Boot dts, when kernel dtb enabled :
1306b353a43cSLin Jinhan  *
1307b353a43cSLin Jinhan  *   1. There is cru phandle mismatch between U-Boot and kernel dtb;
1308b353a43cSLin Jinhan  *   2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property;
1309b353a43cSLin Jinhan  */
1310b353a43cSLin Jinhan static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev)
1311b353a43cSLin Jinhan {
1312b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1313b353a43cSLin Jinhan 	int len, ret = -EINVAL;
1314b353a43cSLin Jinhan 
1315b353a43cSLin Jinhan 	if (!dev_read_prop(dev, "clocks", &len)) {
1316b353a43cSLin Jinhan 		printf("Can't find \"clocks\" property\n");
1317b353a43cSLin Jinhan 		return -EINVAL;
1318b353a43cSLin Jinhan 	}
1319b353a43cSLin Jinhan 
1320b353a43cSLin Jinhan 	memset(priv, 0x00, sizeof(*priv));
1321b353a43cSLin Jinhan 	priv->clocks = malloc(len);
1322b353a43cSLin Jinhan 	if (!priv->clocks)
1323b353a43cSLin Jinhan 		return -ENOMEM;
1324b353a43cSLin Jinhan 
1325b353a43cSLin Jinhan 	priv->nclocks = len / sizeof(u32);
1326b353a43cSLin Jinhan 	if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks,
1327b353a43cSLin Jinhan 			       priv->nclocks)) {
1328b353a43cSLin Jinhan 		printf("Can't read \"clocks\" property\n");
1329b353a43cSLin Jinhan 		ret = -EINVAL;
1330b353a43cSLin Jinhan 		goto exit;
1331b353a43cSLin Jinhan 	}
1332b353a43cSLin Jinhan 
1333b353a43cSLin Jinhan 	if (!dev_read_prop(dev, "clock-frequency", &len)) {
1334b353a43cSLin Jinhan 		printf("Can't find \"clock-frequency\" property\n");
1335b353a43cSLin Jinhan 		ret = -EINVAL;
1336b353a43cSLin Jinhan 		goto exit;
1337b353a43cSLin Jinhan 	}
1338b353a43cSLin Jinhan 
1339b353a43cSLin Jinhan 	priv->frequencies = malloc(len);
1340b353a43cSLin Jinhan 	if (!priv->frequencies) {
1341b353a43cSLin Jinhan 		ret = -ENOMEM;
1342b353a43cSLin Jinhan 		goto exit;
1343b353a43cSLin Jinhan 	}
1344b353a43cSLin Jinhan 
1345b353a43cSLin Jinhan 	priv->nclocks = len / sizeof(u32);
1346b353a43cSLin Jinhan 	if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies,
1347b353a43cSLin Jinhan 			       priv->nclocks)) {
1348b353a43cSLin Jinhan 		printf("Can't read \"clock-frequency\" property\n");
1349b353a43cSLin Jinhan 		ret = -EINVAL;
1350b353a43cSLin Jinhan 		goto exit;
1351b353a43cSLin Jinhan 	}
1352b353a43cSLin Jinhan 
1353b353a43cSLin Jinhan 	priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev);
1354b353a43cSLin Jinhan 
1355b353a43cSLin Jinhan 	crypto_base = priv->reg;
1356b353a43cSLin Jinhan 
1357b353a43cSLin Jinhan 	return 0;
1358b353a43cSLin Jinhan exit:
1359b353a43cSLin Jinhan 	if (priv->clocks)
1360b353a43cSLin Jinhan 		free(priv->clocks);
1361b353a43cSLin Jinhan 
1362b353a43cSLin Jinhan 	if (priv->frequencies)
1363b353a43cSLin Jinhan 		free(priv->frequencies);
1364b353a43cSLin Jinhan 
1365b353a43cSLin Jinhan 	return ret;
1366b353a43cSLin Jinhan }
1367b353a43cSLin Jinhan 
1368b353a43cSLin Jinhan static int rockchip_crypto_probe(struct udevice *dev)
1369b353a43cSLin Jinhan {
1370b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
137149a2135eSLin Jinhan 	struct rk_crypto_soc_data *sdata;
1372b353a43cSLin Jinhan 	int i, ret = 0;
1373b353a43cSLin Jinhan 	u32* clocks;
1374b353a43cSLin Jinhan 
137549a2135eSLin Jinhan 	sdata = (struct rk_crypto_soc_data *)dev_get_driver_data(dev);
137649a2135eSLin Jinhan 	priv->soc_data = sdata;
137749a2135eSLin Jinhan 
137849a2135eSLin Jinhan 	priv->hw_ctx = memalign(LLI_ADDR_ALIGN_SIZE,
13791606a214SLin Jinhan 				sizeof(struct rk_hash_ctx));
13801606a214SLin Jinhan 	if (!priv->hw_ctx)
13811606a214SLin Jinhan 		return -ENOMEM;
13821606a214SLin Jinhan 
1383b353a43cSLin Jinhan 	ret = rockchip_get_clk(&priv->clk.dev);
1384b353a43cSLin Jinhan 	if (ret) {
1385b353a43cSLin Jinhan 		printf("Failed to get clk device, ret=%d\n", ret);
1386b353a43cSLin Jinhan 		return ret;
1387b353a43cSLin Jinhan 	}
1388b353a43cSLin Jinhan 
1389b353a43cSLin Jinhan 	clocks = (u32 *)priv->clocks;
1390b353a43cSLin Jinhan 	for (i = 0; i < priv->nclocks; i++) {
1391b353a43cSLin Jinhan 		priv->clk.id = clocks[i * 2 + 1];
1392b353a43cSLin Jinhan 		ret = clk_set_rate(&priv->clk, priv->frequencies[i]);
1393b353a43cSLin Jinhan 		if (ret < 0) {
1394b353a43cSLin Jinhan 			printf("%s: Failed to set clk(%ld): ret=%d\n",
1395b353a43cSLin Jinhan 			       __func__, priv->clk.id, ret);
1396b353a43cSLin Jinhan 			return ret;
1397b353a43cSLin Jinhan 		}
1398b353a43cSLin Jinhan 	}
1399b353a43cSLin Jinhan 
1400b353a43cSLin Jinhan 	hw_crypto_reset();
1401b353a43cSLin Jinhan 
1402b353a43cSLin Jinhan 	return 0;
1403b353a43cSLin Jinhan }
1404b353a43cSLin Jinhan 
140549a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base = {
140649a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
140749a2135eSLin Jinhan 		      CRYPTO_SHA1 |
140849a2135eSLin Jinhan 		      CRYPTO_SHA256 |
140949a2135eSLin Jinhan 		      CRYPTO_SHA512 |
141049a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
141149a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
141249a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
141349a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
141449a2135eSLin Jinhan 		      CRYPTO_RSA512 |
141549a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
141649a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
141749a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
141849a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
141949a2135eSLin Jinhan 		      CRYPTO_DES |
142049a2135eSLin Jinhan 		      CRYPTO_AES,
142149a2135eSLin Jinhan };
142249a2135eSLin Jinhan 
142349a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base_sm = {
142449a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
142549a2135eSLin Jinhan 		      CRYPTO_SHA1 |
142649a2135eSLin Jinhan 		      CRYPTO_SHA256 |
142749a2135eSLin Jinhan 		      CRYPTO_SHA512 |
142849a2135eSLin Jinhan 		      CRYPTO_SM3 |
142949a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
143049a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
143149a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
143249a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
143349a2135eSLin Jinhan 		      CRYPTO_HMAC_SM3 |
143449a2135eSLin Jinhan 		      CRYPTO_RSA512 |
143549a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
143649a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
143749a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
143849a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
143949a2135eSLin Jinhan 		      CRYPTO_DES |
144049a2135eSLin Jinhan 		      CRYPTO_AES |
144149a2135eSLin Jinhan 		      CRYPTO_SM4,
144249a2135eSLin Jinhan };
144349a2135eSLin Jinhan 
144449a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_rk1808 = {
144549a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
144649a2135eSLin Jinhan 		      CRYPTO_SHA1 |
144749a2135eSLin Jinhan 		      CRYPTO_SHA256 |
144849a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
144949a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
145049a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
145149a2135eSLin Jinhan 		      CRYPTO_RSA512 |
145249a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
145349a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
145449a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
145549a2135eSLin Jinhan 		      CRYPTO_RSA4096,
145649a2135eSLin Jinhan };
145749a2135eSLin Jinhan 
1458b353a43cSLin Jinhan static const struct udevice_id rockchip_crypto_ids[] = {
145949a2135eSLin Jinhan 	{
146049a2135eSLin Jinhan 		.compatible = "rockchip,px30-crypto",
146149a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
146249a2135eSLin Jinhan 	},
146349a2135eSLin Jinhan 	{
146449a2135eSLin Jinhan 		.compatible = "rockchip,rk1808-crypto",
146549a2135eSLin Jinhan 		.data = (ulong)&soc_data_rk1808
146649a2135eSLin Jinhan 	},
146749a2135eSLin Jinhan 	{
146849a2135eSLin Jinhan 		.compatible = "rockchip,rk3308-crypto",
146949a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
147049a2135eSLin Jinhan 	},
147149a2135eSLin Jinhan 	{
147249a2135eSLin Jinhan 		.compatible = "rockchip,rv1126-crypto",
147349a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
147449a2135eSLin Jinhan 	},
147549a2135eSLin Jinhan 	{
147649a2135eSLin Jinhan 		.compatible = "rockchip,rk3568-crypto",
147749a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
147849a2135eSLin Jinhan 	},
1479b353a43cSLin Jinhan 	{ }
1480b353a43cSLin Jinhan };
1481b353a43cSLin Jinhan 
1482b353a43cSLin Jinhan U_BOOT_DRIVER(rockchip_crypto_v2) = {
1483b353a43cSLin Jinhan 	.name		= "rockchip_crypto_v2",
1484b353a43cSLin Jinhan 	.id		= UCLASS_CRYPTO,
1485b353a43cSLin Jinhan 	.of_match	= rockchip_crypto_ids,
1486b353a43cSLin Jinhan 	.ops		= &rockchip_crypto_ops,
1487b353a43cSLin Jinhan 	.probe		= rockchip_crypto_probe,
1488b353a43cSLin Jinhan 	.ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata,
1489b353a43cSLin Jinhan 	.priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv),
1490b353a43cSLin Jinhan };
1491