xref: /rk3399_rockchip-uboot/drivers/crypto/rockchip/crypto_v2.c (revision f489a6d71deeff5a974c2a71b1763a9dd6e9a3ce)
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>
11dd7763a8SFinley Xiao #include <clk-uclass.h>
12b353a43cSLin Jinhan #include <asm/arch/hardware.h>
13b353a43cSLin Jinhan #include <asm/arch/clock.h>
1402b4cf42SLin Jinhan #include <rockchip/crypto_ecc.h>
15c48f1acfSLin Jinhan #include <rockchip/crypto_hash_cache.h>
16b353a43cSLin Jinhan #include <rockchip/crypto_v2.h>
17b353a43cSLin Jinhan #include <rockchip/crypto_v2_pka.h>
18b353a43cSLin Jinhan 
19c48f1acfSLin Jinhan #define	RK_HASH_CTX_MAGIC		0x1A1A1A1A
20c48f1acfSLin Jinhan 
21e0c259feSLin Jinhan #define CRYPTO_MAJOR_VER(ver)		((ver) & 0x0f000000)
22e0c259feSLin Jinhan 
23e0c259feSLin Jinhan #define CRYPTO_MAJOR_VER_3		0x03000000
24e0c259feSLin Jinhan #define CRYPTO_MAJOR_VER_4		0x04000000
253cbec420SJoseph Chen #ifdef CONFIG_ROCKCHIP_RK3562
263cbec420SJoseph Chen #define CRYPTO_S_BY_KEYLAD_BASE  	0xFF8A8000
273cbec420SJoseph Chen #endif
28e0c259feSLin Jinhan 
2949a2135eSLin Jinhan #ifdef DEBUG
3049a2135eSLin Jinhan #define IMSG(format, ...) printf("[%s, %05d]-trace: " format "\n", \
3149a2135eSLin Jinhan 				 __func__, __LINE__, ##__VA_ARGS__)
3249a2135eSLin Jinhan #else
3349a2135eSLin Jinhan #define IMSG(format, ...)
3449a2135eSLin Jinhan #endif
35c48f1acfSLin Jinhan 
36c48f1acfSLin Jinhan struct crypto_lli_desc {
37c48f1acfSLin Jinhan 	u32 src_addr;
38c48f1acfSLin Jinhan 	u32 src_len;
39c48f1acfSLin Jinhan 	u32 dst_addr;
40c48f1acfSLin Jinhan 	u32 dst_len;
41c48f1acfSLin Jinhan 	u32 user_define;
42c48f1acfSLin Jinhan 	u32 reserve;
43c48f1acfSLin Jinhan 	u32 dma_ctrl;
44c48f1acfSLin Jinhan 	u32 next_addr;
45c48f1acfSLin Jinhan };
46c48f1acfSLin Jinhan 
47c48f1acfSLin Jinhan struct rk_hash_ctx {
48c48f1acfSLin Jinhan 	struct crypto_lli_desc		data_lli;	/* lli desc */
49c48f1acfSLin Jinhan 	struct crypto_hash_cache	*hash_cache;
50c48f1acfSLin Jinhan 	u32				magic;		/* to check ctx */
51c48f1acfSLin Jinhan 	u32				algo;		/* hash algo */
52c48f1acfSLin Jinhan 	u8				digest_size;	/* hash out length */
53c48f1acfSLin Jinhan 	u8				reserved[3];
54c48f1acfSLin Jinhan };
55c48f1acfSLin Jinhan 
5649a2135eSLin Jinhan struct rk_crypto_soc_data {
5749a2135eSLin Jinhan 	u32 capability;
5858432b6fSLin Jinhan 	u32 (*dynamic_cap)(void);
5949a2135eSLin Jinhan };
6049a2135eSLin Jinhan 
61b353a43cSLin Jinhan struct rockchip_crypto_priv {
62b353a43cSLin Jinhan 	fdt_addr_t			reg;
63b353a43cSLin Jinhan 	u32				frequency;
64b353a43cSLin Jinhan 	char				*clocks;
65b353a43cSLin Jinhan 	u32				*frequencies;
66b353a43cSLin Jinhan 	u32				nclocks;
67da703fb5SLin Jinhan 	u32				freq_nclocks;
68b353a43cSLin Jinhan 	u32				length;
691606a214SLin Jinhan 	struct rk_hash_ctx		*hw_ctx;
7049a2135eSLin Jinhan 	struct rk_crypto_soc_data	*soc_data;
71b353a43cSLin Jinhan };
72b353a43cSLin Jinhan 
7349a2135eSLin Jinhan #define LLI_ADDR_ALIGN_SIZE	8
7449a2135eSLin Jinhan #define DATA_ADDR_ALIGN_SIZE	8
7549a2135eSLin Jinhan #define DATA_LEN_ALIGN_SIZE	64
761606a214SLin Jinhan 
77086e8fa8SLin Jinhan /* crypto timeout 500ms, must support more than 32M data per times*/
78086e8fa8SLin Jinhan #define HASH_UPDATE_LIMIT	(32 * 1024 * 1024)
7949a2135eSLin Jinhan #define RK_CRYPTO_TIMEOUT	500000
80b353a43cSLin Jinhan 
8149a2135eSLin Jinhan #define RK_POLL_TIMEOUT(condition, timeout) \
8249a2135eSLin Jinhan ({ \
8349a2135eSLin Jinhan 	int time_out = timeout; \
84b353a43cSLin Jinhan 	while (condition) { \
8549a2135eSLin Jinhan 		if (--time_out <= 0) { \
861606a214SLin Jinhan 			debug("[%s] %d: time out!\n", __func__,\
87b353a43cSLin Jinhan 				__LINE__); \
88b353a43cSLin Jinhan 			break; \
89b353a43cSLin Jinhan 		} \
90b353a43cSLin Jinhan 		udelay(1); \
91b353a43cSLin Jinhan 	} \
9249a2135eSLin Jinhan 	(time_out <= 0) ? -ETIMEDOUT : 0; \
9349a2135eSLin Jinhan })
94b353a43cSLin Jinhan 
95d9332f1cSLin Jinhan #define WAIT_TAG_VALID(channel, timeout) ({ \
96d9332f1cSLin Jinhan 	u32 tag_mask = CRYPTO_CH0_TAG_VALID << (channel);\
97e0c259feSLin Jinhan 	int ret = 0;\
98e0c259feSLin Jinhan 	if (is_check_tag_valid()) { \
99d9332f1cSLin Jinhan 		ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_TAG_VALID) & tag_mask),\
100d9332f1cSLin Jinhan 				      timeout);\
101e0c259feSLin Jinhan 	} \
102d9332f1cSLin Jinhan 	crypto_write(crypto_read(CRYPTO_TAG_VALID) & tag_mask, CRYPTO_TAG_VALID);\
103d9332f1cSLin Jinhan 	ret;\
104d9332f1cSLin Jinhan })
105d9332f1cSLin Jinhan 
106b353a43cSLin Jinhan #define virt_to_phys(addr)		(((unsigned long)addr) & 0xffffffff)
107b353a43cSLin Jinhan #define phys_to_virt(addr, area)	((unsigned long)addr)
108b353a43cSLin Jinhan 
10949a2135eSLin Jinhan #define align_malloc(bytes, alignment)	memalign(alignment, bytes)
110dbca2fe7SLin Jinhan #define align_free(addr)		do {if (addr) free(addr);} while (0)
11149a2135eSLin Jinhan 
11249a2135eSLin Jinhan #define ROUNDUP(size, alignment)	round_up(size, alignment)
11349a2135eSLin Jinhan #define cache_op_inner(type, addr, size) \
11449a2135eSLin Jinhan 					crypto_flush_cacheline((ulong)addr, size)
11549a2135eSLin Jinhan 
116d9332f1cSLin Jinhan #define IS_NEED_IV(rk_mode) ((rk_mode) != RK_MODE_ECB && \
117d9332f1cSLin Jinhan 			     (rk_mode) != RK_MODE_CMAC && \
118d9332f1cSLin Jinhan 			     (rk_mode) != RK_MODE_CBC_MAC)
119d9332f1cSLin Jinhan 
120d9332f1cSLin Jinhan #define IS_NEED_TAG(rk_mode) ((rk_mode) == RK_MODE_CMAC || \
121c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_CBC_MAC || \
122c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_CCM || \
123c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_GCM)
124d9332f1cSLin Jinhan 
125d9332f1cSLin Jinhan #define IS_MAC_MODE(rk_mode) ((rk_mode) == RK_MODE_CMAC || \
126d9332f1cSLin Jinhan 			      (rk_mode) == RK_MODE_CBC_MAC)
127d9332f1cSLin Jinhan 
128c3ce9937SLin Jinhan #define IS_AE_MODE(rk_mode) ((rk_mode) == RK_MODE_CCM || \
129c3ce9937SLin Jinhan 			     (rk_mode) == RK_MODE_GCM)
130c3ce9937SLin Jinhan 
131b353a43cSLin Jinhan fdt_addr_t crypto_base;
132e0c259feSLin Jinhan static uint32_t g_crypto_version;
133e0c259feSLin Jinhan 
134e0c259feSLin Jinhan static inline bool is_check_hash_valid(void)
135e0c259feSLin Jinhan {
136e0c259feSLin Jinhan 	/* crypto < v4 need to check hash valid */
137e0c259feSLin Jinhan 	return CRYPTO_MAJOR_VER(g_crypto_version) < CRYPTO_MAJOR_VER_4;
138e0c259feSLin Jinhan }
139e0c259feSLin Jinhan 
140e0c259feSLin Jinhan static inline bool is_check_tag_valid(void)
141e0c259feSLin Jinhan {
142e0c259feSLin Jinhan 	/* crypto < v4 need to check hash valid */
143e0c259feSLin Jinhan 	return CRYPTO_MAJOR_VER(g_crypto_version) < CRYPTO_MAJOR_VER_4;
144e0c259feSLin Jinhan }
145b353a43cSLin Jinhan 
14649a2135eSLin Jinhan static inline void word2byte_be(u32 word, u8 *ch)
147b353a43cSLin Jinhan {
148b353a43cSLin Jinhan 	ch[0] = (word >> 24) & 0xff;
149b353a43cSLin Jinhan 	ch[1] = (word >> 16) & 0xff;
150b353a43cSLin Jinhan 	ch[2] = (word >> 8) & 0xff;
151b353a43cSLin Jinhan 	ch[3] = (word >> 0) & 0xff;
152b353a43cSLin Jinhan }
153b353a43cSLin Jinhan 
15449a2135eSLin Jinhan static inline u32 byte2word_be(const u8 *ch)
15549a2135eSLin Jinhan {
15649a2135eSLin Jinhan 	return (*ch << 24) + (*(ch + 1) << 16) + (*(ch + 2) << 8) + *(ch + 3);
15749a2135eSLin Jinhan }
15849a2135eSLin Jinhan 
15949a2135eSLin Jinhan static inline void clear_regs(u32 base, u32 words)
160b353a43cSLin Jinhan {
161b353a43cSLin Jinhan 	int i;
162b353a43cSLin Jinhan 
163b353a43cSLin Jinhan 	/*clear out register*/
16449a2135eSLin Jinhan 	for (i = 0; i < words; i++)
16549a2135eSLin Jinhan 		crypto_write(0, base + 4 * i);
16649a2135eSLin Jinhan }
16749a2135eSLin Jinhan 
16849a2135eSLin Jinhan static inline void clear_key_regs(void)
16949a2135eSLin Jinhan {
17049a2135eSLin Jinhan 	clear_regs(CRYPTO_CH0_KEY_0, CRYPTO_KEY_CHANNEL_NUM * 4);
17149a2135eSLin Jinhan }
17249a2135eSLin Jinhan 
173c3ce9937SLin Jinhan static inline void read_regs(u32 base, u8 *data, u32 data_len)
174c3ce9937SLin Jinhan {
175c3ce9937SLin Jinhan 	u8 tmp_buf[4];
176c3ce9937SLin Jinhan 	u32 i;
177c3ce9937SLin Jinhan 
178c3ce9937SLin Jinhan 	for (i = 0; i < data_len / 4; i++)
179c3ce9937SLin Jinhan 		word2byte_be(crypto_read(base + i * 4),
180c3ce9937SLin Jinhan 			     data + i * 4);
181c3ce9937SLin Jinhan 
182c3ce9937SLin Jinhan 	if (data_len % 4) {
183c3ce9937SLin Jinhan 		word2byte_be(crypto_read(base + i * 4), tmp_buf);
184c3ce9937SLin Jinhan 		memcpy(data + i * 4, tmp_buf, data_len % 4);
185c3ce9937SLin Jinhan 	}
186c3ce9937SLin Jinhan }
187c3ce9937SLin Jinhan 
18849a2135eSLin Jinhan static inline void write_regs(u32 base, const u8 *data, u32 data_len)
18949a2135eSLin Jinhan {
19049a2135eSLin Jinhan 	u8 tmp_buf[4];
19149a2135eSLin Jinhan 	u32 i;
19249a2135eSLin Jinhan 
19349a2135eSLin Jinhan 	for (i = 0; i < data_len / 4; i++, base += 4)
19449a2135eSLin Jinhan 		crypto_write(byte2word_be(data + i * 4), base);
19549a2135eSLin Jinhan 
19649a2135eSLin Jinhan 	if (data_len % 4) {
19749a2135eSLin Jinhan 		memset(tmp_buf, 0x00, sizeof(tmp_buf));
19849a2135eSLin Jinhan 		memcpy((u8 *)tmp_buf, data + i * 4, data_len % 4);
19949a2135eSLin Jinhan 		crypto_write(byte2word_be(tmp_buf), base);
20049a2135eSLin Jinhan 	}
20149a2135eSLin Jinhan }
20249a2135eSLin Jinhan 
20349a2135eSLin Jinhan static inline void write_key_reg(u32 chn, const u8 *key, u32 key_len)
20449a2135eSLin Jinhan {
20549a2135eSLin Jinhan 	write_regs(CRYPTO_CH0_KEY_0 + chn * 0x10, key, key_len);
20649a2135eSLin Jinhan }
20749a2135eSLin Jinhan 
20849a2135eSLin Jinhan static inline void set_iv_reg(u32 chn, const u8 *iv, u32 iv_len)
20949a2135eSLin Jinhan {
21049a2135eSLin Jinhan 	u32 base_iv;
21149a2135eSLin Jinhan 
21249a2135eSLin Jinhan 	base_iv = CRYPTO_CH0_IV_0 + chn * 0x10;
21349a2135eSLin Jinhan 
21449a2135eSLin Jinhan 	/* clear iv */
21549a2135eSLin Jinhan 	clear_regs(base_iv, 4);
21649a2135eSLin Jinhan 
21749a2135eSLin Jinhan 	if (!iv || iv_len == 0)
21849a2135eSLin Jinhan 		return;
21949a2135eSLin Jinhan 
22049a2135eSLin Jinhan 	write_regs(base_iv, iv, iv_len);
22149a2135eSLin Jinhan 
22249a2135eSLin Jinhan 	crypto_write(iv_len, CRYPTO_CH0_IV_LEN_0 + 4 * chn);
223b353a43cSLin Jinhan }
224b353a43cSLin Jinhan 
225c3ce9937SLin Jinhan static inline void get_iv_reg(u32 chn, u8 *iv, u32 iv_len)
226c3ce9937SLin Jinhan {
227c3ce9937SLin Jinhan 	u32 base_iv;
228c3ce9937SLin Jinhan 
229c3ce9937SLin Jinhan 	base_iv = CRYPTO_CH0_IV_0 + chn * 0x10;
230c3ce9937SLin Jinhan 
231c3ce9937SLin Jinhan 	read_regs(base_iv, iv, iv_len);
232c3ce9937SLin Jinhan }
233c3ce9937SLin Jinhan 
234d9332f1cSLin Jinhan static inline void get_tag_from_reg(u32 chn, u8 *tag, u32 tag_len)
235d9332f1cSLin Jinhan {
236d9332f1cSLin Jinhan 	u32 i;
237d9332f1cSLin Jinhan 	u32 chn_base = CRYPTO_CH0_TAG_0 + 0x10 * chn;
238d9332f1cSLin Jinhan 
239d9332f1cSLin Jinhan 	for (i = 0; i < tag_len / 4; i++, chn_base += 4)
240d9332f1cSLin Jinhan 		word2byte_be(crypto_read(chn_base), tag + 4 * i);
241d9332f1cSLin Jinhan }
242d9332f1cSLin Jinhan 
243dd7763a8SFinley Xiao static int rk_crypto_do_enable_clk(struct udevice *dev, int enable)
244dd7763a8SFinley Xiao {
245dd7763a8SFinley Xiao 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
246dd7763a8SFinley Xiao 	struct clk clk;
247dd7763a8SFinley Xiao 	int i, ret;
248dd7763a8SFinley Xiao 
249dd7763a8SFinley Xiao 	for (i = 0; i < priv->nclocks; i++) {
250dd7763a8SFinley Xiao 		ret = clk_get_by_index(dev, i, &clk);
251dd7763a8SFinley Xiao 		if (ret < 0) {
252dd7763a8SFinley Xiao 			printf("Failed to get clk index %d, ret=%d\n", i, ret);
253dd7763a8SFinley Xiao 			return ret;
254dd7763a8SFinley Xiao 		}
255dd7763a8SFinley Xiao 
256dd7763a8SFinley Xiao 		if (enable)
257dd7763a8SFinley Xiao 			ret = clk_enable(&clk);
258dd7763a8SFinley Xiao 		else
259dd7763a8SFinley Xiao 			ret = clk_disable(&clk);
260dd7763a8SFinley Xiao 		if (ret < 0 && ret != -ENOSYS) {
261dd7763a8SFinley Xiao 			printf("Failed to enable(%d) clk(%ld): ret=%d\n",
262dd7763a8SFinley Xiao 			       enable, clk.id, ret);
263dd7763a8SFinley Xiao 			return ret;
264dd7763a8SFinley Xiao 		}
265dd7763a8SFinley Xiao 	}
266dd7763a8SFinley Xiao 
267dd7763a8SFinley Xiao 	return 0;
268dd7763a8SFinley Xiao }
269dd7763a8SFinley Xiao 
270dd7763a8SFinley Xiao static int rk_crypto_enable_clk(struct udevice *dev)
271dd7763a8SFinley Xiao {
272dd7763a8SFinley Xiao 	return rk_crypto_do_enable_clk(dev, 1);
273dd7763a8SFinley Xiao }
274dd7763a8SFinley Xiao 
275dd7763a8SFinley Xiao static int rk_crypto_disable_clk(struct udevice *dev)
276dd7763a8SFinley Xiao {
277dd7763a8SFinley Xiao 	return rk_crypto_do_enable_clk(dev, 0);
278dd7763a8SFinley Xiao }
279dd7763a8SFinley Xiao 
28058432b6fSLin Jinhan static u32 crypto_v3_dynamic_cap(void)
28158432b6fSLin Jinhan {
28258432b6fSLin Jinhan 	u32 capability = 0;
28358432b6fSLin Jinhan 	u32 ver_reg, i;
28458432b6fSLin Jinhan 	struct cap_map {
28558432b6fSLin Jinhan 		u32 ver_offset;
28658432b6fSLin Jinhan 		u32 mask;
28758432b6fSLin Jinhan 		u32 cap_bit;
28858432b6fSLin Jinhan 	};
28958432b6fSLin Jinhan 	const struct cap_map cap_tbl[] = {
29058432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_MD5_FLAG,    CRYPTO_MD5},
29158432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA1_FLAG,   CRYPTO_SHA1},
29258432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA256_FLAG, CRYPTO_SHA256},
29358432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA512_FLAG, CRYPTO_SHA512},
29458432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SM3_FLAG,    CRYPTO_SM3},
29558432b6fSLin Jinhan 
29658432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_MD5_FLAG,    CRYPTO_HMAC_MD5},
29758432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA1_FLAG,   CRYPTO_HMAC_SHA1},
29858432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA256_FLAG, CRYPTO_HMAC_SHA256},
29958432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA512_FLAG, CRYPTO_HMAC_SHA512},
30058432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SM3_FLAG,    CRYPTO_HMAC_SM3},
30158432b6fSLin Jinhan 
30258432b6fSLin Jinhan 	{CRYPTO_AES_VERSION,  CRYPTO_AES256_FLAG,      CRYPTO_AES},
30358432b6fSLin Jinhan 	{CRYPTO_DES_VERSION,  CRYPTO_TDES_FLAG,        CRYPTO_DES},
30458432b6fSLin Jinhan 	{CRYPTO_SM4_VERSION,  CRYPTO_ECB_FLAG,         CRYPTO_SM4},
30558432b6fSLin Jinhan 	};
30658432b6fSLin Jinhan 
30758432b6fSLin Jinhan 	/* rsa */
30858432b6fSLin Jinhan 	capability = CRYPTO_RSA512 |
30958432b6fSLin Jinhan 		     CRYPTO_RSA1024 |
31058432b6fSLin Jinhan 		     CRYPTO_RSA2048 |
31158432b6fSLin Jinhan 		     CRYPTO_RSA3072 |
31258432b6fSLin Jinhan 		     CRYPTO_RSA4096;
31358432b6fSLin Jinhan 
31402b4cf42SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
31502b4cf42SLin Jinhan 	capability |= (CRYPTO_SM2 |
31602b4cf42SLin Jinhan 		       CRYPTO_ECC_192R1 |
31702b4cf42SLin Jinhan 		       CRYPTO_ECC_224R1 |
31802b4cf42SLin Jinhan 		       CRYPTO_ECC_256R1);
31902b4cf42SLin Jinhan #endif
32002b4cf42SLin Jinhan 
32158432b6fSLin Jinhan 	for (i = 0; i < ARRAY_SIZE(cap_tbl); i++) {
32258432b6fSLin Jinhan 		ver_reg = crypto_read(cap_tbl[i].ver_offset);
32358432b6fSLin Jinhan 
32458432b6fSLin Jinhan 		if ((ver_reg & cap_tbl[i].mask) == cap_tbl[i].mask)
32558432b6fSLin Jinhan 			capability |= cap_tbl[i].cap_bit;
32658432b6fSLin Jinhan 	}
32758432b6fSLin Jinhan 
32858432b6fSLin Jinhan 	return capability;
32958432b6fSLin Jinhan }
33058432b6fSLin Jinhan 
331b353a43cSLin Jinhan static int hw_crypto_reset(void)
332b353a43cSLin Jinhan {
33349a2135eSLin Jinhan 	u32 val = 0, mask = 0;
334b353a43cSLin Jinhan 	int ret;
335b353a43cSLin Jinhan 
33649a2135eSLin Jinhan 	val = CRYPTO_SW_PKA_RESET | CRYPTO_SW_CC_RESET;
33749a2135eSLin Jinhan 	mask = val << CRYPTO_WRITE_MASK_SHIFT;
338b353a43cSLin Jinhan 
339b353a43cSLin Jinhan 	/* reset pka and crypto modules*/
34049a2135eSLin Jinhan 	crypto_write(val | mask, CRYPTO_RST_CTL);
341b353a43cSLin Jinhan 
342b353a43cSLin Jinhan 	/* wait reset compelete */
34349a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL), RK_CRYPTO_TIMEOUT);
34449a2135eSLin Jinhan 
345e0c259feSLin Jinhan 	g_crypto_version = crypto_read(CRYPTO_CRYPTO_VERSION_NEW);
346e0c259feSLin Jinhan 
347b353a43cSLin Jinhan 	return ret;
348b353a43cSLin Jinhan }
349b353a43cSLin Jinhan 
350b353a43cSLin Jinhan static void hw_hash_clean_ctx(struct rk_hash_ctx *ctx)
351b353a43cSLin Jinhan {
352b353a43cSLin Jinhan 	/* clear hash status */
353b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
354b353a43cSLin Jinhan 
3551606a214SLin Jinhan 	assert(ctx);
3561606a214SLin Jinhan 	assert(ctx->magic == RK_HASH_CTX_MAGIC);
3571606a214SLin Jinhan 
358c48f1acfSLin Jinhan 	crypto_hash_cache_free(ctx->hash_cache);
3591606a214SLin Jinhan 
3601606a214SLin Jinhan 	memset(ctx, 0x00, sizeof(*ctx));
361b353a43cSLin Jinhan }
362b353a43cSLin Jinhan 
363c48f1acfSLin Jinhan static int rk_hash_init(void *hw_ctx, u32 algo)
364b353a43cSLin Jinhan {
365b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)hw_ctx;
366b353a43cSLin Jinhan 	u32 reg_ctrl = 0;
367b353a43cSLin Jinhan 	int ret;
368b353a43cSLin Jinhan 
369b353a43cSLin Jinhan 	if (!tmp_ctx)
370b353a43cSLin Jinhan 		return -EINVAL;
371b353a43cSLin Jinhan 
3721606a214SLin Jinhan 	reg_ctrl = CRYPTO_SW_CC_RESET;
3731606a214SLin Jinhan 	crypto_write(reg_ctrl | (reg_ctrl << CRYPTO_WRITE_MASK_SHIFT),
3741606a214SLin Jinhan 		     CRYPTO_RST_CTL);
3751606a214SLin Jinhan 
3761606a214SLin Jinhan 	/* wait reset compelete */
37749a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL),
37849a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
3791606a214SLin Jinhan 
3801606a214SLin Jinhan 	reg_ctrl = 0;
381b353a43cSLin Jinhan 	tmp_ctx->algo = algo;
382b353a43cSLin Jinhan 	switch (algo) {
383b353a43cSLin Jinhan 	case CRYPTO_MD5:
38449a2135eSLin Jinhan 	case CRYPTO_HMAC_MD5:
385b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_MD5;
386b353a43cSLin Jinhan 		tmp_ctx->digest_size = 16;
387b353a43cSLin Jinhan 		break;
388b353a43cSLin Jinhan 	case CRYPTO_SHA1:
38949a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA1:
390b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA1;
391b353a43cSLin Jinhan 		tmp_ctx->digest_size = 20;
392b353a43cSLin Jinhan 		break;
393b353a43cSLin Jinhan 	case CRYPTO_SHA256:
39449a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA256:
395b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA256;
396b353a43cSLin Jinhan 		tmp_ctx->digest_size = 32;
397b353a43cSLin Jinhan 		break;
398e7846385SLin Jinhan 	case CRYPTO_SHA512:
39949a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA512:
400e7846385SLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA512;
401e7846385SLin Jinhan 		tmp_ctx->digest_size = 64;
402e7846385SLin Jinhan 		break;
40349a2135eSLin Jinhan 	case CRYPTO_SM3:
40449a2135eSLin Jinhan 	case CRYPTO_HMAC_SM3:
40549a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SM3;
40649a2135eSLin Jinhan 		tmp_ctx->digest_size = 32;
40749a2135eSLin Jinhan 		break;
408b353a43cSLin Jinhan 	default:
409b353a43cSLin Jinhan 		ret = -EINVAL;
410b353a43cSLin Jinhan 		goto exit;
411b353a43cSLin Jinhan 	}
412b353a43cSLin Jinhan 
413b353a43cSLin Jinhan 	/* enable hardware padding */
414b353a43cSLin Jinhan 	reg_ctrl |= CRYPTO_HW_PAD_ENABLE;
415b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
416b353a43cSLin Jinhan 
417b353a43cSLin Jinhan 	/* FIFO input and output data byte swap */
418b353a43cSLin Jinhan 	/* such as B0, B1, B2, B3 -> B3, B2, B1, B0 */
419b353a43cSLin Jinhan 	reg_ctrl = CRYPTO_DOUT_BYTESWAP | CRYPTO_DOIN_BYTESWAP;
420b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_FIFO_CTL);
421b353a43cSLin Jinhan 
4221606a214SLin Jinhan 	/* enable src_item_done interrupt */
423fe0c4b19SLin Jinhan 	crypto_write(0, CRYPTO_DMA_INT_EN);
424b353a43cSLin Jinhan 
425b353a43cSLin Jinhan 	tmp_ctx->magic = RK_HASH_CTX_MAGIC;
426b353a43cSLin Jinhan 
427b353a43cSLin Jinhan 	return 0;
428b353a43cSLin Jinhan exit:
429b353a43cSLin Jinhan 	/* clear hash setting if init failed */
430b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
431b353a43cSLin Jinhan 
432b353a43cSLin Jinhan 	return ret;
433b353a43cSLin Jinhan }
434b353a43cSLin Jinhan 
435c48f1acfSLin Jinhan static int rk_hash_direct_calc(void *hw_data, const u8 *data,
4361606a214SLin Jinhan 			       u32 data_len, u8 *started_flag, u8 is_last)
437b353a43cSLin Jinhan {
438c48f1acfSLin Jinhan 	struct rockchip_crypto_priv *priv = hw_data;
439c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
440c48f1acfSLin Jinhan 	struct crypto_lli_desc *lli = &hash_ctx->data_lli;
441b353a43cSLin Jinhan 	int ret = -EINVAL;
44200fa57d8SLin Jinhan 	u32 tmp = 0, mask = 0;
443b353a43cSLin Jinhan 
44449a2135eSLin Jinhan 	assert(IS_ALIGNED((ulong)data, DATA_ADDR_ALIGN_SIZE));
44549a2135eSLin Jinhan 	assert(is_last || IS_ALIGNED(data_len, DATA_LEN_ALIGN_SIZE));
446b353a43cSLin Jinhan 
4471606a214SLin Jinhan 	debug("%s: data = %p, len = %u, s = %x, l = %x\n",
4481606a214SLin Jinhan 	      __func__, data, data_len, *started_flag, is_last);
449b353a43cSLin Jinhan 
4501606a214SLin Jinhan 	memset(lli, 0x00, sizeof(*lli));
4511606a214SLin Jinhan 	lli->src_addr = (u32)virt_to_phys(data);
4521606a214SLin Jinhan 	lli->src_len = data_len;
4531606a214SLin Jinhan 	lli->dma_ctrl = LLI_DMA_CTRL_SRC_DONE;
454b353a43cSLin Jinhan 
4551606a214SLin Jinhan 	if (is_last) {
4561606a214SLin Jinhan 		lli->user_define |= LLI_USER_STRING_LAST;
4571606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_LAST;
458b353a43cSLin Jinhan 	} else {
4591606a214SLin Jinhan 		lli->next_addr = (u32)virt_to_phys(lli);
4601606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_PAUSE;
4611606a214SLin Jinhan 	}
4621606a214SLin Jinhan 
4631606a214SLin Jinhan 	if (!(*started_flag)) {
4641606a214SLin Jinhan 		lli->user_define |=
465ce7f4cd6SLin Jinhan 			(LLI_USER_STRING_START | LLI_USER_CIPHER_START);
4661606a214SLin Jinhan 		crypto_write((u32)virt_to_phys(lli), CRYPTO_DMA_LLI_ADDR);
4671606a214SLin Jinhan 		crypto_write((CRYPTO_HASH_ENABLE << CRYPTO_WRITE_MASK_SHIFT) |
4681606a214SLin Jinhan 			     CRYPTO_HASH_ENABLE, CRYPTO_HASH_CTL);
4691606a214SLin Jinhan 		tmp = CRYPTO_DMA_START;
4701606a214SLin Jinhan 		*started_flag = 1;
4711606a214SLin Jinhan 	} else {
472b353a43cSLin Jinhan 		tmp = CRYPTO_DMA_RESTART;
473b353a43cSLin Jinhan 	}
474b353a43cSLin Jinhan 
475b353a43cSLin Jinhan 	/* flush cache */
476c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)lli, sizeof(*lli));
477c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)data, data_len);
478b353a43cSLin Jinhan 
479b353a43cSLin Jinhan 	/* start calculate */
480b353a43cSLin Jinhan 	crypto_write(tmp << CRYPTO_WRITE_MASK_SHIFT | tmp,
481b353a43cSLin Jinhan 		     CRYPTO_DMA_CTL);
482b353a43cSLin Jinhan 
48300fa57d8SLin Jinhan 	/* mask CRYPTO_SYNC_LOCKSTEP_INT_ST flag */
48400fa57d8SLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
48500fa57d8SLin Jinhan 
486b353a43cSLin Jinhan 	/* wait calc ok */
48749a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
48849a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
489b353a43cSLin Jinhan 
490b353a43cSLin Jinhan 	/* clear interrupt status */
491b353a43cSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
492b353a43cSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
493b353a43cSLin Jinhan 
49449cbb0faSLin Jinhan 	if ((tmp & mask) != CRYPTO_SRC_ITEM_DONE_INT_ST &&
49549cbb0faSLin Jinhan 	    (tmp & mask) != CRYPTO_ZERO_LEN_INT_ST) {
49646aac970SLin Jinhan 		ret = -EFAULT;
4971606a214SLin Jinhan 		debug("[%s] %d: CRYPTO_DMA_INT_ST = 0x%x\n",
498b353a43cSLin Jinhan 		      __func__, __LINE__, tmp);
4991606a214SLin Jinhan 		goto exit;
500b353a43cSLin Jinhan 	}
501b353a43cSLin Jinhan 
502c48f1acfSLin Jinhan 	priv->length += data_len;
5031606a214SLin Jinhan exit:
5041606a214SLin Jinhan 	return ret;
505b353a43cSLin Jinhan }
5061606a214SLin Jinhan 
5071606a214SLin Jinhan int rk_hash_update(void *ctx, const u8 *data, u32 data_len)
5081606a214SLin Jinhan {
5091606a214SLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
510c48f1acfSLin Jinhan 	int ret = -EINVAL;
5111606a214SLin Jinhan 
5121606a214SLin Jinhan 	debug("\n");
5131606a214SLin Jinhan 	if (!tmp_ctx || !data)
514c48f1acfSLin Jinhan 		goto exit;
5151606a214SLin Jinhan 
5161606a214SLin Jinhan 	if (tmp_ctx->digest_size == 0 || tmp_ctx->magic != RK_HASH_CTX_MAGIC)
517c48f1acfSLin Jinhan 		goto exit;
5181606a214SLin Jinhan 
519c48f1acfSLin Jinhan 	ret = crypto_hash_update_with_cache(tmp_ctx->hash_cache,
520c48f1acfSLin Jinhan 					    data, data_len);
5211606a214SLin Jinhan 
522c48f1acfSLin Jinhan exit:
523b353a43cSLin Jinhan 	/* free lli list */
524c48f1acfSLin Jinhan 	if (ret)
525b353a43cSLin Jinhan 		hw_hash_clean_ctx(tmp_ctx);
526b353a43cSLin Jinhan 
527c48f1acfSLin Jinhan 	return ret;
528b353a43cSLin Jinhan }
529b353a43cSLin Jinhan 
530b353a43cSLin Jinhan int rk_hash_final(void *ctx, u8 *digest, size_t len)
531b353a43cSLin Jinhan {
532b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
533e0c259feSLin Jinhan 	int ret = 0;
534b353a43cSLin Jinhan 
535b353a43cSLin Jinhan 	if (!digest)
536b353a43cSLin Jinhan 		goto exit;
537b353a43cSLin Jinhan 
538b353a43cSLin Jinhan 	if (!tmp_ctx ||
539b353a43cSLin Jinhan 	    tmp_ctx->digest_size == 0 ||
540b353a43cSLin Jinhan 	    len > tmp_ctx->digest_size ||
541b353a43cSLin Jinhan 	    tmp_ctx->magic != RK_HASH_CTX_MAGIC) {
542b353a43cSLin Jinhan 		goto exit;
543b353a43cSLin Jinhan 	}
544b353a43cSLin Jinhan 
545e0c259feSLin Jinhan 	if(is_check_hash_valid()) {
546b353a43cSLin Jinhan 		/* wait hash value ok */
54749a2135eSLin Jinhan 		ret = RK_POLL_TIMEOUT(!crypto_read(CRYPTO_HASH_VALID),
54849a2135eSLin Jinhan 				      RK_CRYPTO_TIMEOUT);
549e0c259feSLin Jinhan 	}
550b353a43cSLin Jinhan 
551c3ce9937SLin Jinhan 	read_regs(CRYPTO_HASH_DOUT_0, digest, len);
552b353a43cSLin Jinhan 
553b353a43cSLin Jinhan 	/* clear hash status */
554b353a43cSLin Jinhan 	crypto_write(CRYPTO_HASH_IS_VALID, CRYPTO_HASH_VALID);
555b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
556b353a43cSLin Jinhan 
557b353a43cSLin Jinhan exit:
558b353a43cSLin Jinhan 
559b353a43cSLin Jinhan 	return ret;
560b353a43cSLin Jinhan }
561b353a43cSLin Jinhan 
562b353a43cSLin Jinhan static u32 rockchip_crypto_capability(struct udevice *dev)
563b353a43cSLin Jinhan {
56449a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
56549a2135eSLin Jinhan 	u32 capability, mask = 0;
5667eea1823SLin Jinhan 
56749a2135eSLin Jinhan 	capability = priv->soc_data->capability;
56849a2135eSLin Jinhan 
56949a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_CIPHER))
57049a2135eSLin Jinhan 	mask |= (CRYPTO_DES | CRYPTO_AES | CRYPTO_SM4);
571c0e47d03SLin Jinhan #endif
5727eea1823SLin Jinhan 
57349a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_HMAC))
57449a2135eSLin Jinhan 	mask |= (CRYPTO_HMAC_MD5 | CRYPTO_HMAC_SHA1 | CRYPTO_HMAC_SHA256 |
57549a2135eSLin Jinhan 			 CRYPTO_HMAC_SHA512 | CRYPTO_HMAC_SM3);
57649a2135eSLin Jinhan #endif
57749a2135eSLin Jinhan 
57849a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_RSA))
57949a2135eSLin Jinhan 	mask |= (CRYPTO_RSA512 | CRYPTO_RSA1024 | CRYPTO_RSA2048 |
58049a2135eSLin Jinhan 			 CRYPTO_RSA3072 | CRYPTO_RSA4096);
58149a2135eSLin Jinhan #endif
58249a2135eSLin Jinhan 
58349a2135eSLin Jinhan 	return capability & (~mask);
584b353a43cSLin Jinhan }
585b353a43cSLin Jinhan 
586b353a43cSLin Jinhan static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx)
587b353a43cSLin Jinhan {
588b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
589c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
590dd7763a8SFinley Xiao 	int ret = 0;
591b353a43cSLin Jinhan 
592b353a43cSLin Jinhan 	if (!ctx)
593b353a43cSLin Jinhan 		return -EINVAL;
594b353a43cSLin Jinhan 
595c48f1acfSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
596b353a43cSLin Jinhan 
597c48f1acfSLin Jinhan 	priv->length = 0;
598c48f1acfSLin Jinhan 
599c48f1acfSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
600c48f1acfSLin Jinhan 						       priv, ctx->length,
60149a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
60249a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
603c48f1acfSLin Jinhan 	if (!hash_ctx->hash_cache)
604c48f1acfSLin Jinhan 		return -EFAULT;
605c48f1acfSLin Jinhan 
606dd7763a8SFinley Xiao 	rk_crypto_enable_clk(dev);
607dd7763a8SFinley Xiao 	ret = rk_hash_init(hash_ctx, ctx->algo);
608dd7763a8SFinley Xiao 	if (ret)
609dd7763a8SFinley Xiao 		rk_crypto_disable_clk(dev);
610dd7763a8SFinley Xiao 
611dd7763a8SFinley Xiao 	return ret;
612b353a43cSLin Jinhan }
613b353a43cSLin Jinhan 
614b353a43cSLin Jinhan static int rockchip_crypto_sha_update(struct udevice *dev,
615b353a43cSLin Jinhan 				      u32 *input, u32 len)
616b353a43cSLin Jinhan {
617b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
618086e8fa8SLin Jinhan 	int ret, i;
619086e8fa8SLin Jinhan 	u8 *p;
620b353a43cSLin Jinhan 
621dd7763a8SFinley Xiao 	if (!len) {
622dd7763a8SFinley Xiao 		ret = -EINVAL;
623dd7763a8SFinley Xiao 		goto exit;
624dd7763a8SFinley Xiao 	}
625b353a43cSLin Jinhan 
626086e8fa8SLin Jinhan 	p = (u8 *)input;
627086e8fa8SLin Jinhan 
628086e8fa8SLin Jinhan 	for (i = 0; i < len / HASH_UPDATE_LIMIT; i++, p += HASH_UPDATE_LIMIT) {
629086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, HASH_UPDATE_LIMIT);
630086e8fa8SLin Jinhan 		if (ret)
631086e8fa8SLin Jinhan 			goto exit;
632086e8fa8SLin Jinhan 	}
633086e8fa8SLin Jinhan 
634086e8fa8SLin Jinhan 	if (len % HASH_UPDATE_LIMIT)
635086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, len % HASH_UPDATE_LIMIT);
636086e8fa8SLin Jinhan 
637086e8fa8SLin Jinhan exit:
638dd7763a8SFinley Xiao 	if (ret)
639dd7763a8SFinley Xiao 		rk_crypto_disable_clk(dev);
640dd7763a8SFinley Xiao 
641086e8fa8SLin Jinhan 	return ret;
642b353a43cSLin Jinhan }
643b353a43cSLin Jinhan 
644b353a43cSLin Jinhan static int rockchip_crypto_sha_final(struct udevice *dev,
645b353a43cSLin Jinhan 				     sha_context *ctx, u8 *output)
646b353a43cSLin Jinhan {
647b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
648b353a43cSLin Jinhan 	u32 nbits;
649c48f1acfSLin Jinhan 	int ret;
650b353a43cSLin Jinhan 
651b353a43cSLin Jinhan 	nbits = crypto_algo_nbits(ctx->algo);
652b353a43cSLin Jinhan 
653c48f1acfSLin Jinhan 	if (priv->length != ctx->length) {
654c48f1acfSLin Jinhan 		printf("total length(0x%08x) != init length(0x%08x)!\n",
655c48f1acfSLin Jinhan 		       priv->length, ctx->length);
656c48f1acfSLin Jinhan 		ret = -EIO;
657c48f1acfSLin Jinhan 		goto exit;
658c48f1acfSLin Jinhan 	}
659c48f1acfSLin Jinhan 
660c48f1acfSLin Jinhan 	ret = rk_hash_final(priv->hw_ctx, (u8 *)output, BITS2BYTE(nbits));
661c48f1acfSLin Jinhan 
662c48f1acfSLin Jinhan exit:
663c48f1acfSLin Jinhan 	hw_hash_clean_ctx(priv->hw_ctx);
664dd7763a8SFinley Xiao 	rk_crypto_disable_clk(dev);
665dd7763a8SFinley Xiao 
666c48f1acfSLin Jinhan 	return ret;
667b353a43cSLin Jinhan }
668b353a43cSLin Jinhan 
66949a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
67049a2135eSLin Jinhan int rk_hmac_init(void *hw_ctx, u32 algo, u8 *key, u32 key_len)
67149a2135eSLin Jinhan {
67249a2135eSLin Jinhan 	u32 reg_ctrl = 0;
67349a2135eSLin Jinhan 	int ret;
67449a2135eSLin Jinhan 
67549a2135eSLin Jinhan 	if (!key || !key_len || key_len > 64)
67649a2135eSLin Jinhan 		return -EINVAL;
67749a2135eSLin Jinhan 
67849a2135eSLin Jinhan 	clear_key_regs();
67949a2135eSLin Jinhan 
68049a2135eSLin Jinhan 	write_key_reg(0, key, key_len);
68149a2135eSLin Jinhan 
68249a2135eSLin Jinhan 	ret = rk_hash_init(hw_ctx, algo);
68349a2135eSLin Jinhan 	if (ret)
68449a2135eSLin Jinhan 		return ret;
68549a2135eSLin Jinhan 
68649a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_HASH_CTL) | CRYPTO_HMAC_ENABLE;
68749a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
68849a2135eSLin Jinhan 
68949a2135eSLin Jinhan 	return ret;
69049a2135eSLin Jinhan }
69149a2135eSLin Jinhan 
69249a2135eSLin Jinhan static int rockchip_crypto_hmac_init(struct udevice *dev,
69349a2135eSLin Jinhan 				     sha_context *ctx, u8 *key, u32 key_len)
69449a2135eSLin Jinhan {
69549a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
69649a2135eSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
697dd7763a8SFinley Xiao 	int ret = 0;
69849a2135eSLin Jinhan 
69949a2135eSLin Jinhan 	if (!ctx)
70049a2135eSLin Jinhan 		return -EINVAL;
70149a2135eSLin Jinhan 
70249a2135eSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
70349a2135eSLin Jinhan 
70449a2135eSLin Jinhan 	priv->length = 0;
70549a2135eSLin Jinhan 
70649a2135eSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
70749a2135eSLin Jinhan 						       priv, ctx->length,
70849a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
70949a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
71049a2135eSLin Jinhan 	if (!hash_ctx->hash_cache)
71149a2135eSLin Jinhan 		return -EFAULT;
71249a2135eSLin Jinhan 
713dd7763a8SFinley Xiao 	rk_crypto_enable_clk(dev);
714dd7763a8SFinley Xiao 	ret = rk_hmac_init(priv->hw_ctx, ctx->algo, key, key_len);
715dd7763a8SFinley Xiao 	if (ret)
716dd7763a8SFinley Xiao 		rk_crypto_disable_clk(dev);
717dd7763a8SFinley Xiao 
718dd7763a8SFinley Xiao 	return ret;
71949a2135eSLin Jinhan }
72049a2135eSLin Jinhan 
72149a2135eSLin Jinhan static int rockchip_crypto_hmac_update(struct udevice *dev,
72249a2135eSLin Jinhan 				       u32 *input, u32 len)
72349a2135eSLin Jinhan {
72449a2135eSLin Jinhan 	return rockchip_crypto_sha_update(dev, input, len);
72549a2135eSLin Jinhan }
72649a2135eSLin Jinhan 
72749a2135eSLin Jinhan static int rockchip_crypto_hmac_final(struct udevice *dev,
72849a2135eSLin Jinhan 				      sha_context *ctx, u8 *output)
72949a2135eSLin Jinhan {
73049a2135eSLin Jinhan 	return rockchip_crypto_sha_final(dev, ctx, output);
73149a2135eSLin Jinhan }
73249a2135eSLin Jinhan 
73349a2135eSLin Jinhan #endif
73449a2135eSLin Jinhan 
73549a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
73649a2135eSLin Jinhan static u8 g_key_chn;
73749a2135eSLin Jinhan 
73849a2135eSLin Jinhan static const u32 rk_mode2bc_mode[RK_MODE_MAX] = {
73949a2135eSLin Jinhan 	[RK_MODE_ECB] = CRYPTO_BC_ECB,
74049a2135eSLin Jinhan 	[RK_MODE_CBC] = CRYPTO_BC_CBC,
74149a2135eSLin Jinhan 	[RK_MODE_CTS] = CRYPTO_BC_CTS,
74249a2135eSLin Jinhan 	[RK_MODE_CTR] = CRYPTO_BC_CTR,
74349a2135eSLin Jinhan 	[RK_MODE_CFB] = CRYPTO_BC_CFB,
74449a2135eSLin Jinhan 	[RK_MODE_OFB] = CRYPTO_BC_OFB,
74549a2135eSLin Jinhan 	[RK_MODE_XTS] = CRYPTO_BC_XTS,
746c3ce9937SLin Jinhan 	[RK_MODE_CCM] = CRYPTO_BC_CCM,
747c3ce9937SLin Jinhan 	[RK_MODE_GCM] = CRYPTO_BC_GCM,
748d9332f1cSLin Jinhan 	[RK_MODE_CMAC] = CRYPTO_BC_CMAC,
749d9332f1cSLin Jinhan 	[RK_MODE_CBC_MAC] = CRYPTO_BC_CBC_MAC,
75049a2135eSLin Jinhan };
75149a2135eSLin Jinhan 
752c3ce9937SLin Jinhan static inline void set_pc_len_reg(u32 chn, u64 pc_len)
753c3ce9937SLin Jinhan {
754c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_PC_LEN_0 + chn * 0x08;
755c3ce9937SLin Jinhan 
756c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
757c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
758c3ce9937SLin Jinhan }
759c3ce9937SLin Jinhan 
760c3ce9937SLin Jinhan static inline void set_aad_len_reg(u32 chn, u64 pc_len)
761c3ce9937SLin Jinhan {
762c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_AAD_LEN_0 + chn * 0x08;
763c3ce9937SLin Jinhan 
764c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
765c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
766c3ce9937SLin Jinhan }
767c3ce9937SLin Jinhan 
76849a2135eSLin Jinhan static inline bool is_des_mode(u32 rk_mode)
76949a2135eSLin Jinhan {
77049a2135eSLin Jinhan 	return (rk_mode == RK_MODE_ECB ||
77149a2135eSLin Jinhan 		rk_mode == RK_MODE_CBC ||
77249a2135eSLin Jinhan 		rk_mode == RK_MODE_CFB ||
77349a2135eSLin Jinhan 		rk_mode == RK_MODE_OFB);
77449a2135eSLin Jinhan }
77549a2135eSLin Jinhan 
7766b53126aSLin Jinhan static void dump_crypto_state(struct crypto_lli_desc *desc,
7776b53126aSLin Jinhan 			      u32 tmp, u32 expt_int,
7786b53126aSLin Jinhan 			      const u8 *in, const u8 *out,
7796b53126aSLin Jinhan 			      u32 len, int ret)
78049a2135eSLin Jinhan {
78149a2135eSLin Jinhan 	IMSG("%s\n", ret == -ETIME ? "timeout" : "dismatch");
78249a2135eSLin Jinhan 
78349a2135eSLin Jinhan 	IMSG("CRYPTO_DMA_INT_ST = %08x, expect_int = %08x\n",
78449a2135eSLin Jinhan 	     tmp, expt_int);
78549a2135eSLin Jinhan 	IMSG("data desc		= %p\n", desc);
78649a2135eSLin Jinhan 	IMSG("\taddr_in		= [%08x <=> %08x]\n",
78749a2135eSLin Jinhan 	     desc->src_addr, (u32)virt_to_phys(in));
78849a2135eSLin Jinhan 	IMSG("\taddr_out	= [%08x <=> %08x]\n",
78949a2135eSLin Jinhan 	     desc->dst_addr, (u32)virt_to_phys(out));
79049a2135eSLin Jinhan 	IMSG("\tsrc_len		= [%08x <=> %08x]\n",
79149a2135eSLin Jinhan 	     desc->src_len, (u32)len);
79249a2135eSLin Jinhan 	IMSG("\tdst_len		= %08x\n", desc->dst_len);
79349a2135eSLin Jinhan 	IMSG("\tdma_ctl		= %08x\n", desc->dma_ctrl);
79449a2135eSLin Jinhan 	IMSG("\tuser_define	= %08x\n", desc->user_define);
79549a2135eSLin Jinhan 
79649a2135eSLin Jinhan 	IMSG("\n\nDMA CRYPTO_DMA_LLI_ADDR status = %08x\n",
79749a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_ADDR));
79849a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_ST status = %08x\n",
79949a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_ST));
80049a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_STATE status = %08x\n",
80149a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_STATE));
80249a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_LLI_RADDR status = %08x\n",
80349a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_RADDR));
80449a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_SRC_RADDR status = %08x\n",
80549a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_SRC_RADDR));
80649a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_DST_RADDR status = %08x\n",
80749a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
80849a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_ST status = %08x\n",
80949a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_ST));
81049a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_STATE status = %08x\n",
81149a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_STATE));
81249a2135eSLin Jinhan 	IMSG("DMA CRYPTO_TAG_VALID status = %08x\n",
81349a2135eSLin Jinhan 	     crypto_read(CRYPTO_TAG_VALID));
81449a2135eSLin Jinhan 	IMSG("LOCKSTEP status = %08x\n\n",
81549a2135eSLin Jinhan 	     crypto_read(0x618));
81649a2135eSLin Jinhan 
81749a2135eSLin Jinhan 	IMSG("dst %dbyte not transferred\n",
81849a2135eSLin Jinhan 	     desc->dst_addr + desc->dst_len -
81949a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
82049a2135eSLin Jinhan }
82149a2135eSLin Jinhan 
822c3ce9937SLin Jinhan static int ccm128_set_iv_reg(u32 chn, const u8 *nonce, u32 nlen)
823c3ce9937SLin Jinhan {
824c3ce9937SLin Jinhan 	u8 iv_buf[AES_BLOCK_SIZE];
825c3ce9937SLin Jinhan 	u32 L;
826c3ce9937SLin Jinhan 
827c3ce9937SLin Jinhan 	memset(iv_buf, 0x00, sizeof(iv_buf));
828c3ce9937SLin Jinhan 
829c3ce9937SLin Jinhan 	L = 15 - nlen;
830c3ce9937SLin Jinhan 	iv_buf[0] = ((u8)(L - 1) & 7);
831c3ce9937SLin Jinhan 
832c3ce9937SLin Jinhan 	/* the L parameter */
833c3ce9937SLin Jinhan 	L = iv_buf[0] & 7;
834c3ce9937SLin Jinhan 
835c3ce9937SLin Jinhan 	/* nonce is too short */
836c3ce9937SLin Jinhan 	if (nlen < (14 - L))
837c3ce9937SLin Jinhan 		return -EINVAL;
838c3ce9937SLin Jinhan 
839c3ce9937SLin Jinhan 	/* clear aad flag */
840c3ce9937SLin Jinhan 	iv_buf[0] &= ~0x40;
841c3ce9937SLin Jinhan 	memcpy(&iv_buf[1], nonce, 14 - L);
842c3ce9937SLin Jinhan 
843c3ce9937SLin Jinhan 	set_iv_reg(chn, iv_buf, AES_BLOCK_SIZE);
844c3ce9937SLin Jinhan 
845c3ce9937SLin Jinhan 	return 0;
846c3ce9937SLin Jinhan }
847c3ce9937SLin Jinhan 
848c3ce9937SLin Jinhan static void ccm_aad_padding(u32 aad_len, u8 *padding, u32 *padding_size)
849c3ce9937SLin Jinhan {
850c3ce9937SLin Jinhan 	u32 i;
851c3ce9937SLin Jinhan 
8522db770efSLin Jinhan 	if (aad_len == 0) {
8532db770efSLin Jinhan 		*padding_size = 0;
8542db770efSLin Jinhan 		return;
8552db770efSLin Jinhan 	}
8562db770efSLin Jinhan 
857c3ce9937SLin Jinhan 	i = aad_len < (0x10000 - 0x100) ? 2 : 6;
858c3ce9937SLin Jinhan 
859c3ce9937SLin Jinhan 	if (i == 2) {
860c3ce9937SLin Jinhan 		padding[0] = (u8)(aad_len >> 8);
861c3ce9937SLin Jinhan 		padding[1] = (u8)aad_len;
862c3ce9937SLin Jinhan 	} else {
863c3ce9937SLin Jinhan 		padding[0] = 0xFF;
864c3ce9937SLin Jinhan 		padding[1] = 0xFE;
865c3ce9937SLin Jinhan 		padding[2] = (u8)(aad_len >> 24);
866c3ce9937SLin Jinhan 		padding[3] = (u8)(aad_len >> 16);
867c3ce9937SLin Jinhan 		padding[4] = (u8)(aad_len >> 8);
868c3ce9937SLin Jinhan 	}
869c3ce9937SLin Jinhan 
870c3ce9937SLin Jinhan 	*padding_size = i;
871c3ce9937SLin Jinhan }
872c3ce9937SLin Jinhan 
8732db770efSLin Jinhan static int ccm_compose_aad_iv(u8 *aad_iv, u32 data_len, u32 aad_len, u32 tag_size)
874c3ce9937SLin Jinhan {
875c3ce9937SLin Jinhan 	aad_iv[0] |= ((u8)(((tag_size - 2) / 2) & 7) << 3);
876c3ce9937SLin Jinhan 
877c3ce9937SLin Jinhan 	aad_iv[12] = (u8)(data_len >> 24);
878c3ce9937SLin Jinhan 	aad_iv[13] = (u8)(data_len >> 16);
879c3ce9937SLin Jinhan 	aad_iv[14] = (u8)(data_len >> 8);
880c3ce9937SLin Jinhan 	aad_iv[15] = (u8)data_len;
881c3ce9937SLin Jinhan 
8822db770efSLin Jinhan 	if (aad_len)
883c3ce9937SLin Jinhan 		aad_iv[0] |= 0x40;	//set aad flag
884c3ce9937SLin Jinhan 
885c3ce9937SLin Jinhan 	return 0;
886c3ce9937SLin Jinhan }
887c3ce9937SLin Jinhan 
88849a2135eSLin Jinhan static int hw_cipher_init(u32 chn, const u8 *key, const u8 *twk_key,
88949a2135eSLin Jinhan 			  u32 key_len, const u8 *iv, u32 iv_len,
89049a2135eSLin Jinhan 			  u32 algo, u32 mode, bool enc)
89149a2135eSLin Jinhan {
89249a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
89349a2135eSLin Jinhan 	u32 key_chn_sel = chn;
89449a2135eSLin Jinhan 	u32 reg_ctrl = 0;
895eecb3765SLin Jinhan 	bool use_otpkey = false;
896eecb3765SLin Jinhan 
897eecb3765SLin Jinhan 	if (!key && key_len)
898eecb3765SLin Jinhan 		use_otpkey = true;
89949a2135eSLin Jinhan 
90049a2135eSLin Jinhan 	IMSG("%s: key addr is %p, key_len is %d, iv addr is %p",
90149a2135eSLin Jinhan 	     __func__, key, key_len, iv);
90249a2135eSLin Jinhan 	if (rk_mode >= RK_MODE_MAX)
90349a2135eSLin Jinhan 		return -EINVAL;
90449a2135eSLin Jinhan 
90549a2135eSLin Jinhan 	switch (algo) {
90649a2135eSLin Jinhan 	case CRYPTO_DES:
90749a2135eSLin Jinhan 		if (key_len > DES_BLOCK_SIZE)
90849a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_TDES;
90949a2135eSLin Jinhan 		else
91049a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_DES;
91149a2135eSLin Jinhan 		break;
91249a2135eSLin Jinhan 	case CRYPTO_AES:
91349a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_AES;
91449a2135eSLin Jinhan 		break;
91549a2135eSLin Jinhan 	case CRYPTO_SM4:
91649a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_SM4;
91749a2135eSLin Jinhan 		break;
91849a2135eSLin Jinhan 	default:
91949a2135eSLin Jinhan 		return -EINVAL;
92049a2135eSLin Jinhan 	}
92149a2135eSLin Jinhan 
92249a2135eSLin Jinhan 	if (algo == CRYPTO_AES || algo == CRYPTO_SM4) {
92349a2135eSLin Jinhan 		switch (key_len) {
92449a2135eSLin Jinhan 		case AES_KEYSIZE_128:
92549a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_128_bit_key;
92649a2135eSLin Jinhan 			break;
92749a2135eSLin Jinhan 		case AES_KEYSIZE_192:
92849a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_192_bit_key;
92949a2135eSLin Jinhan 			break;
93049a2135eSLin Jinhan 		case AES_KEYSIZE_256:
93149a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_256_bit_key;
93249a2135eSLin Jinhan 			break;
93349a2135eSLin Jinhan 		default:
93449a2135eSLin Jinhan 			return -EINVAL;
93549a2135eSLin Jinhan 		}
93649a2135eSLin Jinhan 	}
93749a2135eSLin Jinhan 
93849a2135eSLin Jinhan 	reg_ctrl |= rk_mode2bc_mode[rk_mode];
93949a2135eSLin Jinhan 	if (!enc)
94049a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_DECRYPT;
94149a2135eSLin Jinhan 
94249a2135eSLin Jinhan 	/* write key data to reg */
943eecb3765SLin Jinhan 	if (!use_otpkey) {
94449a2135eSLin Jinhan 		write_key_reg(key_chn_sel, key, key_len);
945eecb3765SLin Jinhan 		crypto_write(CRYPTO_SEL_USER, CRYPTO_KEY_SEL);
946eecb3765SLin Jinhan 	} else {
947eecb3765SLin Jinhan 		crypto_write(CRYPTO_SEL_KEYTABLE, CRYPTO_KEY_SEL);
948eecb3765SLin Jinhan 	}
94949a2135eSLin Jinhan 
95049a2135eSLin Jinhan 	/* write twk key for xts mode */
95149a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS)
95249a2135eSLin Jinhan 		write_key_reg(key_chn_sel + 4, twk_key, key_len);
95349a2135eSLin Jinhan 
95449a2135eSLin Jinhan 	/* set iv reg */
955c3ce9937SLin Jinhan 	if (rk_mode == RK_MODE_CCM)
956c3ce9937SLin Jinhan 		ccm128_set_iv_reg(chn, iv, iv_len);
957c3ce9937SLin Jinhan 	else
95849a2135eSLin Jinhan 		set_iv_reg(chn, iv, iv_len);
95949a2135eSLin Jinhan 
96049a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
96149a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
962fe0c4b19SLin Jinhan 	crypto_write(0, CRYPTO_DMA_INT_EN);
96349a2135eSLin Jinhan 
96449a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
96549a2135eSLin Jinhan 
96649a2135eSLin Jinhan 	return 0;
96749a2135eSLin Jinhan }
96849a2135eSLin Jinhan 
96949a2135eSLin Jinhan static int hw_cipher_crypt(const u8 *in, u8 *out, u64 len,
970c3ce9937SLin Jinhan 			   const u8 *aad, u32 aad_len,
971c3ce9937SLin Jinhan 			   u8 *tag, u32 tag_len, u32 mode)
97249a2135eSLin Jinhan {
973c3ce9937SLin Jinhan 	struct crypto_lli_desc *data_desc = NULL, *aad_desc = NULL;
974c3ce9937SLin Jinhan 	u8 *dma_in = NULL, *dma_out = NULL, *aad_tmp = NULL;
97549a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
97649a2135eSLin Jinhan 	u32 reg_ctrl = 0, tmp_len = 0;
97749a2135eSLin Jinhan 	u32 expt_int = 0, mask = 0;
97849a2135eSLin Jinhan 	u32 key_chn = g_key_chn;
97949a2135eSLin Jinhan 	u32 tmp, dst_len = 0;
98049a2135eSLin Jinhan 	int ret = -1;
98149a2135eSLin Jinhan 
98249a2135eSLin Jinhan 	if (rk_mode == RK_MODE_CTS && len <= AES_BLOCK_SIZE) {
98349a2135eSLin Jinhan 		printf("CTS mode length %u < 16Byte\n", (u32)len);
98449a2135eSLin Jinhan 		return -EINVAL;
98549a2135eSLin Jinhan 	}
98649a2135eSLin Jinhan 
98749a2135eSLin Jinhan 	tmp_len = (rk_mode == RK_MODE_CTR) ? ROUNDUP(len, AES_BLOCK_SIZE) : len;
98849a2135eSLin Jinhan 
98949a2135eSLin Jinhan 	data_desc = align_malloc(sizeof(*data_desc), LLI_ADDR_ALIGN_SIZE);
99049a2135eSLin Jinhan 	if (!data_desc)
99149a2135eSLin Jinhan 		goto exit;
99249a2135eSLin Jinhan 
99349a2135eSLin Jinhan 	if (IS_ALIGNED((ulong)in, DATA_ADDR_ALIGN_SIZE) && tmp_len == len)
99449a2135eSLin Jinhan 		dma_in = (void *)in;
99549a2135eSLin Jinhan 	else
99649a2135eSLin Jinhan 		dma_in = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
99749a2135eSLin Jinhan 	if (!dma_in)
99849a2135eSLin Jinhan 		goto exit;
99949a2135eSLin Jinhan 
100049a2135eSLin Jinhan 	if (out) {
100149a2135eSLin Jinhan 		if (IS_ALIGNED((ulong)out, DATA_ADDR_ALIGN_SIZE) &&
100249a2135eSLin Jinhan 		    tmp_len == len)
100349a2135eSLin Jinhan 			dma_out = out;
100449a2135eSLin Jinhan 		else
100549a2135eSLin Jinhan 			dma_out = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
100649a2135eSLin Jinhan 		if (!dma_out)
100749a2135eSLin Jinhan 			goto exit;
100849a2135eSLin Jinhan 		dst_len = tmp_len;
100949a2135eSLin Jinhan 	}
101049a2135eSLin Jinhan 
101149a2135eSLin Jinhan 	memset(data_desc, 0x00, sizeof(*data_desc));
101249a2135eSLin Jinhan 	if (dma_in != in)
101349a2135eSLin Jinhan 		memcpy(dma_in, in, len);
101449a2135eSLin Jinhan 
101549a2135eSLin Jinhan 	data_desc->src_addr    = (u32)virt_to_phys(dma_in);
101649a2135eSLin Jinhan 	data_desc->src_len     = tmp_len;
101749a2135eSLin Jinhan 	data_desc->dst_addr    = (u32)virt_to_phys(dma_out);
101849a2135eSLin Jinhan 	data_desc->dst_len     = dst_len;
1019d9332f1cSLin Jinhan 	data_desc->dma_ctrl    = LLI_DMA_CTRL_LAST;
1020d9332f1cSLin Jinhan 
1021d9332f1cSLin Jinhan 	if (IS_MAC_MODE(rk_mode)) {
1022d9332f1cSLin Jinhan 		expt_int = CRYPTO_LIST_DONE_INT_ST;
1023d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_LIST_DONE;
1024d9332f1cSLin Jinhan 	} else {
102549a2135eSLin Jinhan 		expt_int = CRYPTO_DST_ITEM_DONE_INT_ST;
1026d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_DST_DONE;
1027d9332f1cSLin Jinhan 	}
102849a2135eSLin Jinhan 
1029ce7f4cd6SLin Jinhan 	data_desc->user_define = LLI_USER_CIPHER_START |
1030afdbec36SLin Jinhan 				 LLI_USER_STRING_START |
1031c3ce9937SLin Jinhan 				 LLI_USER_STRING_LAST |
1032c3ce9937SLin Jinhan 				 (key_chn << 4);
1033afdbec36SLin Jinhan 	crypto_write((u32)virt_to_phys(data_desc), CRYPTO_DMA_LLI_ADDR);
1034afdbec36SLin Jinhan 
1035afdbec36SLin Jinhan 	if (rk_mode == RK_MODE_CCM || rk_mode == RK_MODE_GCM) {
1036afdbec36SLin Jinhan 		u32 aad_tmp_len = 0;
1037c3ce9937SLin Jinhan 
1038c3ce9937SLin Jinhan 		aad_desc = align_malloc(sizeof(*aad_desc), LLI_ADDR_ALIGN_SIZE);
1039c3ce9937SLin Jinhan 		if (!aad_desc)
1040c3ce9937SLin Jinhan 			goto exit;
1041c3ce9937SLin Jinhan 
1042c3ce9937SLin Jinhan 		memset(aad_desc, 0x00, sizeof(*aad_desc));
1043c3ce9937SLin Jinhan 		aad_desc->next_addr = (u32)virt_to_phys(data_desc);
1044ce7f4cd6SLin Jinhan 		aad_desc->user_define = LLI_USER_CIPHER_START |
1045c3ce9937SLin Jinhan 					 LLI_USER_STRING_START |
1046c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
1047c3ce9937SLin Jinhan 					 LLI_USER_STRING_AAD |
1048c3ce9937SLin Jinhan 					 (key_chn << 4);
1049c3ce9937SLin Jinhan 
1050c3ce9937SLin Jinhan 		if (rk_mode == RK_MODE_CCM) {
1051c3ce9937SLin Jinhan 			u8 padding[AES_BLOCK_SIZE];
1052c3ce9937SLin Jinhan 			u32 padding_size = 0;
1053c3ce9937SLin Jinhan 
1054c3ce9937SLin Jinhan 			memset(padding, 0x00, sizeof(padding));
1055c3ce9937SLin Jinhan 			ccm_aad_padding(aad_len, padding, &padding_size);
1056c3ce9937SLin Jinhan 
1057c3ce9937SLin Jinhan 			aad_tmp_len = aad_len + AES_BLOCK_SIZE + padding_size;
1058c3ce9937SLin Jinhan 			aad_tmp_len = ROUNDUP(aad_tmp_len, AES_BLOCK_SIZE);
1059c3ce9937SLin Jinhan 			aad_tmp = align_malloc(aad_tmp_len,
1060c3ce9937SLin Jinhan 					       DATA_ADDR_ALIGN_SIZE);
1061c3ce9937SLin Jinhan 			if (!aad_tmp)
1062c3ce9937SLin Jinhan 				goto exit;
1063c3ce9937SLin Jinhan 
10642db770efSLin Jinhan 			/* clear last block */
1065c3ce9937SLin Jinhan 			memset(aad_tmp + aad_tmp_len - AES_BLOCK_SIZE,
1066c3ce9937SLin Jinhan 			       0x00, AES_BLOCK_SIZE);
10672db770efSLin Jinhan 
10682db770efSLin Jinhan 			/* read iv data from reg */
10692db770efSLin Jinhan 			get_iv_reg(key_chn, aad_tmp, AES_BLOCK_SIZE);
10702db770efSLin Jinhan 			ccm_compose_aad_iv(aad_tmp, tmp_len, aad_len, tag_len);
10712db770efSLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE, padding, padding_size);
10722db770efSLin Jinhan 
1073c3ce9937SLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE + padding_size,
1074c3ce9937SLin Jinhan 			       aad, aad_len);
1075c3ce9937SLin Jinhan 		} else {
1076c3ce9937SLin Jinhan 			aad_tmp_len = aad_len;
1077b83c40a4SLin Jinhan 			if (IS_ALIGNED((ulong)aad, DATA_ADDR_ALIGN_SIZE)) {
1078b83c40a4SLin Jinhan 				aad_tmp = (void *)aad;
1079b83c40a4SLin Jinhan 			} else {
1080c3ce9937SLin Jinhan 				aad_tmp = align_malloc(aad_tmp_len,
1081c3ce9937SLin Jinhan 						       DATA_ADDR_ALIGN_SIZE);
1082c3ce9937SLin Jinhan 				if (!aad_tmp)
1083c3ce9937SLin Jinhan 					goto exit;
1084c3ce9937SLin Jinhan 
1085c3ce9937SLin Jinhan 				memcpy(aad_tmp, aad, aad_tmp_len);
1086b83c40a4SLin Jinhan 			}
1087b83c40a4SLin Jinhan 
1088c3ce9937SLin Jinhan 			set_aad_len_reg(key_chn, aad_tmp_len);
1089c3ce9937SLin Jinhan 			set_pc_len_reg(key_chn, tmp_len);
1090c3ce9937SLin Jinhan 		}
1091c3ce9937SLin Jinhan 
1092c3ce9937SLin Jinhan 		aad_desc->src_addr = (u32)virt_to_phys(aad_tmp);
1093c3ce9937SLin Jinhan 		aad_desc->src_len  = aad_tmp_len;
1094afdbec36SLin Jinhan 
1095afdbec36SLin Jinhan 		if (aad_tmp_len) {
1096afdbec36SLin Jinhan 			data_desc->user_define = LLI_USER_STRING_START |
1097afdbec36SLin Jinhan 						 LLI_USER_STRING_LAST |
1098afdbec36SLin Jinhan 						 (key_chn << 4);
1099c3ce9937SLin Jinhan 			crypto_write((u32)virt_to_phys(aad_desc), CRYPTO_DMA_LLI_ADDR);
1100c3ce9937SLin Jinhan 			cache_op_inner(DCACHE_AREA_CLEAN, aad_tmp, aad_tmp_len);
1101c3ce9937SLin Jinhan 			cache_op_inner(DCACHE_AREA_CLEAN, aad_desc, sizeof(*aad_desc));
1102afdbec36SLin Jinhan 		}
1103c3ce9937SLin Jinhan 	}
110449a2135eSLin Jinhan 
110549a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, data_desc, sizeof(*data_desc));
110649a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, dma_in, tmp_len);
110749a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_INVALIDATE, dma_out, tmp_len);
110849a2135eSLin Jinhan 
110949a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
111049a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
1111fe0c4b19SLin Jinhan 	crypto_write(0, CRYPTO_DMA_INT_EN);
111249a2135eSLin Jinhan 
111349a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_BC_CTL) | CRYPTO_BC_ENABLE;
111449a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
111549a2135eSLin Jinhan 	crypto_write(0x00010001, CRYPTO_DMA_CTL);//start
111649a2135eSLin Jinhan 
111749a2135eSLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
111849a2135eSLin Jinhan 
111949a2135eSLin Jinhan 	/* wait calc ok */
112049a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
112149a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
112249a2135eSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
112349a2135eSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
112449a2135eSLin Jinhan 
112549a2135eSLin Jinhan 	if ((tmp & mask) == expt_int) {
112649a2135eSLin Jinhan 		if (out && out != dma_out)
112749a2135eSLin Jinhan 			memcpy(out, dma_out, len);
1128d9332f1cSLin Jinhan 
1129d9332f1cSLin Jinhan 		if (IS_NEED_TAG(rk_mode)) {
1130d9332f1cSLin Jinhan 			ret = WAIT_TAG_VALID(key_chn, RK_CRYPTO_TIMEOUT);
1131d9332f1cSLin Jinhan 			get_tag_from_reg(key_chn, tag, AES_BLOCK_SIZE);
1132d9332f1cSLin Jinhan 		}
113349a2135eSLin Jinhan 	} else {
11346b53126aSLin Jinhan 		dump_crypto_state(data_desc, tmp, expt_int, in, out, len, ret);
113549a2135eSLin Jinhan 		ret = -1;
113649a2135eSLin Jinhan 	}
113749a2135eSLin Jinhan 
113849a2135eSLin Jinhan exit:
113949a2135eSLin Jinhan 	crypto_write(0xffff0000, CRYPTO_BC_CTL);//bc_ctl disable
114049a2135eSLin Jinhan 	align_free(data_desc);
1141c3ce9937SLin Jinhan 	align_free(aad_desc);
1142b83c40a4SLin Jinhan 	if (dma_in != in)
114349a2135eSLin Jinhan 		align_free(dma_in);
1144b83c40a4SLin Jinhan 	if (out && dma_out != out)
114549a2135eSLin Jinhan 		align_free(dma_out);
1146b83c40a4SLin Jinhan 	if (aad && aad != aad_tmp)
1147b83c40a4SLin Jinhan 		align_free(aad_tmp);
114849a2135eSLin Jinhan 
114949a2135eSLin Jinhan 	return ret;
115049a2135eSLin Jinhan }
115149a2135eSLin Jinhan 
115249a2135eSLin Jinhan static int hw_aes_init(u32 chn, const u8 *key, const u8 *twk_key, u32 key_len,
115349a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
115449a2135eSLin Jinhan {
115549a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
115649a2135eSLin Jinhan 
1157d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
1158d9332f1cSLin Jinhan 		return -EINVAL;
1159d9332f1cSLin Jinhan 
116049a2135eSLin Jinhan 	if (iv_len > AES_BLOCK_SIZE)
116149a2135eSLin Jinhan 		return -EINVAL;
116249a2135eSLin Jinhan 
1163d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
116449a2135eSLin Jinhan 		if (!iv || iv_len != AES_BLOCK_SIZE)
116549a2135eSLin Jinhan 			return -EINVAL;
116649a2135eSLin Jinhan 	} else {
116749a2135eSLin Jinhan 		iv_len = 0;
116849a2135eSLin Jinhan 	}
116949a2135eSLin Jinhan 
117049a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
117149a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_256)
117249a2135eSLin Jinhan 			return -EINVAL;
117349a2135eSLin Jinhan 
117449a2135eSLin Jinhan 		if (!key || !twk_key)
117549a2135eSLin Jinhan 			return -EINVAL;
117649a2135eSLin Jinhan 	} else {
117749a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 &&
117849a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_192 &&
117949a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_256)
118049a2135eSLin Jinhan 			return -EINVAL;
118149a2135eSLin Jinhan 	}
118249a2135eSLin Jinhan 
118349a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
118449a2135eSLin Jinhan 			      CRYPTO_AES, mode, enc);
118549a2135eSLin Jinhan }
118649a2135eSLin Jinhan 
118749a2135eSLin Jinhan static int hw_sm4_init(u32  chn, const u8 *key, const u8 *twk_key, u32 key_len,
118849a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
118949a2135eSLin Jinhan {
119049a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
119149a2135eSLin Jinhan 
1192d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
1193d9332f1cSLin Jinhan 		return -EINVAL;
1194d9332f1cSLin Jinhan 
119549a2135eSLin Jinhan 	if (iv_len > SM4_BLOCK_SIZE || key_len != SM4_KEYSIZE)
119649a2135eSLin Jinhan 		return -EINVAL;
119749a2135eSLin Jinhan 
1198d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
119949a2135eSLin Jinhan 		if (!iv || iv_len != SM4_BLOCK_SIZE)
120049a2135eSLin Jinhan 			return -EINVAL;
120149a2135eSLin Jinhan 	} else {
120249a2135eSLin Jinhan 		iv_len = 0;
120349a2135eSLin Jinhan 	}
120449a2135eSLin Jinhan 
120549a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
120649a2135eSLin Jinhan 		if (!key || !twk_key)
120749a2135eSLin Jinhan 			return -EINVAL;
120849a2135eSLin Jinhan 	}
120949a2135eSLin Jinhan 
121049a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
121149a2135eSLin Jinhan 			      CRYPTO_SM4, mode, enc);
121249a2135eSLin Jinhan }
121349a2135eSLin Jinhan 
121449a2135eSLin Jinhan int rk_crypto_des(struct udevice *dev, u32 mode, const u8 *key, u32 key_len,
121549a2135eSLin Jinhan 		  const u8 *iv, const u8 *in, u8 *out, u32 len, bool enc)
121649a2135eSLin Jinhan {
121749a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
121849a2135eSLin Jinhan 	u8 tmp_key[24];
121949a2135eSLin Jinhan 	int ret;
122049a2135eSLin Jinhan 
122149a2135eSLin Jinhan 	if (!is_des_mode(rk_mode))
122249a2135eSLin Jinhan 		return -EINVAL;
122349a2135eSLin Jinhan 
122449a2135eSLin Jinhan 	if (key_len == DES_BLOCK_SIZE || key_len == 3 * DES_BLOCK_SIZE) {
122549a2135eSLin Jinhan 		memcpy(tmp_key, key, key_len);
122649a2135eSLin Jinhan 	} else if (key_len == 2 * DES_BLOCK_SIZE) {
122749a2135eSLin Jinhan 		memcpy(tmp_key, key, 16);
122849a2135eSLin Jinhan 		memcpy(tmp_key + 16, key, 8);
122949a2135eSLin Jinhan 		key_len = 3 * DES_BLOCK_SIZE;
123049a2135eSLin Jinhan 	} else {
123149a2135eSLin Jinhan 		return -EINVAL;
123249a2135eSLin Jinhan 	}
123349a2135eSLin Jinhan 
123449a2135eSLin Jinhan 	ret = hw_cipher_init(0, tmp_key, NULL, key_len, iv, DES_BLOCK_SIZE,
123549a2135eSLin Jinhan 			     CRYPTO_DES, mode, enc);
123649a2135eSLin Jinhan 	if (ret)
123749a2135eSLin Jinhan 		goto exit;
123849a2135eSLin Jinhan 
123949a2135eSLin Jinhan 	ret = hw_cipher_crypt(in, out, len, NULL, 0,
124049a2135eSLin Jinhan 			      NULL, 0, mode);
124149a2135eSLin Jinhan 
124249a2135eSLin Jinhan exit:
124349a2135eSLin Jinhan 	return ret;
124449a2135eSLin Jinhan }
124549a2135eSLin Jinhan 
124649a2135eSLin Jinhan int rk_crypto_aes(struct udevice *dev, u32 mode,
124749a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
124849a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
124949a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
125049a2135eSLin Jinhan {
125149a2135eSLin Jinhan 	int ret;
125249a2135eSLin Jinhan 
125349a2135eSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
125449a2135eSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
125549a2135eSLin Jinhan 	if (key_len == AES_KEYSIZE_192)
125649a2135eSLin Jinhan 		return -EINVAL;
125749a2135eSLin Jinhan #endif
125849a2135eSLin Jinhan 
125949a2135eSLin Jinhan 	ret = hw_aes_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
126049a2135eSLin Jinhan 	if (ret)
126149a2135eSLin Jinhan 		return ret;
126249a2135eSLin Jinhan 
126349a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0,
126449a2135eSLin Jinhan 			       NULL, 0, mode);
126549a2135eSLin Jinhan }
126649a2135eSLin Jinhan 
126749a2135eSLin Jinhan int rk_crypto_sm4(struct udevice *dev, u32 mode,
126849a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
126949a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
127049a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
127149a2135eSLin Jinhan {
127249a2135eSLin Jinhan 	int ret;
127349a2135eSLin Jinhan 
127449a2135eSLin Jinhan 	ret = hw_sm4_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
127549a2135eSLin Jinhan 	if (ret)
127649a2135eSLin Jinhan 		return ret;
127749a2135eSLin Jinhan 
127849a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0, NULL, 0, mode);
127949a2135eSLin Jinhan }
128049a2135eSLin Jinhan 
128149a2135eSLin Jinhan int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx,
128249a2135eSLin Jinhan 			   const u8 *in, u8 *out, u32 len, bool enc)
128349a2135eSLin Jinhan {
1284dd7763a8SFinley Xiao 	int ret;
1285dd7763a8SFinley Xiao 
1286dd7763a8SFinley Xiao 	rk_crypto_enable_clk(dev);
1287dd7763a8SFinley Xiao 
128849a2135eSLin Jinhan 	switch (ctx->algo) {
128949a2135eSLin Jinhan 	case CRYPTO_DES:
1290dd7763a8SFinley Xiao 		ret = rk_crypto_des(dev, ctx->mode, ctx->key, ctx->key_len,
129149a2135eSLin Jinhan 				    ctx->iv, in, out, len, enc);
12929b9c232aSLin Jinhan 		break;
129349a2135eSLin Jinhan 	case CRYPTO_AES:
1294dd7763a8SFinley Xiao 		ret = rk_crypto_aes(dev, ctx->mode,
129549a2135eSLin Jinhan 				    ctx->key, ctx->twk_key, ctx->key_len,
129649a2135eSLin Jinhan 				    ctx->iv, ctx->iv_len, in, out, len, enc);
12979b9c232aSLin Jinhan 		break;
129849a2135eSLin Jinhan 	case CRYPTO_SM4:
1299dd7763a8SFinley Xiao 		ret = rk_crypto_sm4(dev, ctx->mode,
130049a2135eSLin Jinhan 				    ctx->key, ctx->twk_key, ctx->key_len,
130149a2135eSLin Jinhan 				    ctx->iv, ctx->iv_len, in, out, len, enc);
13029b9c232aSLin Jinhan 		break;
130349a2135eSLin Jinhan 	default:
1304dd7763a8SFinley Xiao 		ret = -EINVAL;
13059b9c232aSLin Jinhan 		break;
130649a2135eSLin Jinhan 	}
1307dd7763a8SFinley Xiao 
1308dd7763a8SFinley Xiao 	rk_crypto_disable_clk(dev);
1309dd7763a8SFinley Xiao 
1310dd7763a8SFinley Xiao 	return ret;
131149a2135eSLin Jinhan }
1312d9332f1cSLin Jinhan 
1313d9332f1cSLin Jinhan int rk_crypto_mac(struct udevice *dev, u32 algo, u32 mode,
1314d9332f1cSLin Jinhan 		  const u8 *key, u32 key_len,
1315d9332f1cSLin Jinhan 		  const u8 *in, u32 len, u8 *tag)
1316d9332f1cSLin Jinhan {
1317d9332f1cSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1318d9332f1cSLin Jinhan 	int ret;
1319d9332f1cSLin Jinhan 
1320d9332f1cSLin Jinhan 	if (!IS_MAC_MODE(rk_mode))
1321d9332f1cSLin Jinhan 		return -EINVAL;
1322d9332f1cSLin Jinhan 
1323d9332f1cSLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1324d9332f1cSLin Jinhan 		return -EINVAL;
1325d9332f1cSLin Jinhan 
1326d9332f1cSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1327d9332f1cSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1328d9332f1cSLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1329d9332f1cSLin Jinhan 		return -EINVAL;
1330d9332f1cSLin Jinhan #endif
1331d9332f1cSLin Jinhan 
1332d9332f1cSLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, NULL, 0,
1333d9332f1cSLin Jinhan 			     algo, mode, true);
1334d9332f1cSLin Jinhan 	if (ret)
1335d9332f1cSLin Jinhan 		return ret;
1336d9332f1cSLin Jinhan 
1337d9332f1cSLin Jinhan 	return hw_cipher_crypt(in, NULL, len, NULL, 0,
1338d9332f1cSLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1339d9332f1cSLin Jinhan }
1340d9332f1cSLin Jinhan 
1341d9332f1cSLin Jinhan int rockchip_crypto_mac(struct udevice *dev, cipher_context *ctx,
1342d9332f1cSLin Jinhan 			const u8 *in, u32 len, u8 *tag)
1343d9332f1cSLin Jinhan {
1344dd7763a8SFinley Xiao 	int ret = 0;
1345dd7763a8SFinley Xiao 
1346dd7763a8SFinley Xiao 	rk_crypto_enable_clk(dev);
1347dd7763a8SFinley Xiao 
1348dd7763a8SFinley Xiao 	ret = rk_crypto_mac(dev, ctx->algo, ctx->mode,
1349d9332f1cSLin Jinhan 			    ctx->key, ctx->key_len, in, len, tag);
1350dd7763a8SFinley Xiao 
1351dd7763a8SFinley Xiao 	rk_crypto_disable_clk(dev);
1352dd7763a8SFinley Xiao 
1353dd7763a8SFinley Xiao 	return ret;
1354d9332f1cSLin Jinhan }
1355d9332f1cSLin Jinhan 
1356c3ce9937SLin Jinhan int rk_crypto_ae(struct udevice *dev, u32 algo, u32 mode,
1357c3ce9937SLin Jinhan 		 const u8 *key, u32 key_len, const u8 *nonce, u32 nonce_len,
1358c3ce9937SLin Jinhan 		 const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1359c3ce9937SLin Jinhan 		 u8 *out, u8 *tag)
1360c3ce9937SLin Jinhan {
1361c3ce9937SLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1362c3ce9937SLin Jinhan 	int ret;
1363c3ce9937SLin Jinhan 
1364c3ce9937SLin Jinhan 	if (!IS_AE_MODE(rk_mode))
1365c3ce9937SLin Jinhan 		return -EINVAL;
1366c3ce9937SLin Jinhan 
1367afdbec36SLin Jinhan 	if (len == 0)
1368afdbec36SLin Jinhan 		return -EINVAL;
1369afdbec36SLin Jinhan 
1370c3ce9937SLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1371c3ce9937SLin Jinhan 		return -EINVAL;
1372c3ce9937SLin Jinhan 
1373c3ce9937SLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1374c3ce9937SLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1375c3ce9937SLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1376c3ce9937SLin Jinhan 		return -EINVAL;
1377c3ce9937SLin Jinhan #endif
1378c3ce9937SLin Jinhan 
1379c3ce9937SLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, nonce, nonce_len,
1380c3ce9937SLin Jinhan 			     algo, mode, true);
1381c3ce9937SLin Jinhan 	if (ret)
1382c3ce9937SLin Jinhan 		return ret;
1383c3ce9937SLin Jinhan 
1384c3ce9937SLin Jinhan 	return hw_cipher_crypt(in, out, len, aad, aad_len,
1385c3ce9937SLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1386c3ce9937SLin Jinhan }
1387c3ce9937SLin Jinhan 
1388c3ce9937SLin Jinhan int rockchip_crypto_ae(struct udevice *dev, cipher_context *ctx,
1389c3ce9937SLin Jinhan 		       const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1390c3ce9937SLin Jinhan 		       u8 *out, u8 *tag)
13916b0f7484SLin Jinhan 
1392c3ce9937SLin Jinhan {
1393dd7763a8SFinley Xiao 	int ret = 0;
1394dd7763a8SFinley Xiao 
1395dd7763a8SFinley Xiao 	rk_crypto_enable_clk(dev);
1396dd7763a8SFinley Xiao 
1397dd7763a8SFinley Xiao 	ret = rk_crypto_ae(dev, ctx->algo, ctx->mode, ctx->key, ctx->key_len,
1398c3ce9937SLin Jinhan 			   ctx->iv, ctx->iv_len, in, len,
1399c3ce9937SLin Jinhan 			   aad, aad_len, out, tag);
1400dd7763a8SFinley Xiao 
1401dd7763a8SFinley Xiao 	rk_crypto_disable_clk(dev);
1402dd7763a8SFinley Xiao 
1403dd7763a8SFinley Xiao 	return ret;
1404c3ce9937SLin Jinhan }
1405c3ce9937SLin Jinhan 
1406*f489a6d7SJoseph Chen #if CONFIG_IS_ENABLED(DM_KEYLAD)
1407*f489a6d7SJoseph Chen int rockchip_crypto_fw_cipher(struct udevice *dev, cipher_fw_context *ctx,
1408*f489a6d7SJoseph Chen 			      const u8 *in, u8 *out, u32 len, bool enc)
1409*f489a6d7SJoseph Chen {
1410*f489a6d7SJoseph Chen 	int ret;
1411*f489a6d7SJoseph Chen 
1412*f489a6d7SJoseph Chen 	rk_crypto_enable_clk(dev);
1413*f489a6d7SJoseph Chen 
1414*f489a6d7SJoseph Chen 	switch (ctx->algo) {
1415*f489a6d7SJoseph Chen 	case CRYPTO_DES:
1416*f489a6d7SJoseph Chen 		ret = rk_crypto_des(dev, ctx->mode, NULL, ctx->key_len,
1417*f489a6d7SJoseph Chen 				    ctx->iv, in, out, len, enc);
1418*f489a6d7SJoseph Chen 		break;
1419*f489a6d7SJoseph Chen 	case CRYPTO_AES:
1420*f489a6d7SJoseph Chen 		ret = rk_crypto_aes(dev, ctx->mode, NULL, NULL, ctx->key_len,
1421*f489a6d7SJoseph Chen 				    ctx->iv, ctx->iv_len, in, out, len, enc);
1422*f489a6d7SJoseph Chen 		break;
1423*f489a6d7SJoseph Chen 	case CRYPTO_SM4:
1424*f489a6d7SJoseph Chen 		ret = rk_crypto_sm4(dev, ctx->mode, NULL, NULL, ctx->key_len,
1425*f489a6d7SJoseph Chen 				    ctx->iv, ctx->iv_len, in, out, len, enc);
1426*f489a6d7SJoseph Chen 		break;
1427*f489a6d7SJoseph Chen 	default:
1428*f489a6d7SJoseph Chen 		ret = -EINVAL;
1429*f489a6d7SJoseph Chen 		break;
1430*f489a6d7SJoseph Chen 	}
1431*f489a6d7SJoseph Chen 
1432*f489a6d7SJoseph Chen 	rk_crypto_disable_clk(dev);
1433*f489a6d7SJoseph Chen 
1434*f489a6d7SJoseph Chen 	return ret;
1435*f489a6d7SJoseph Chen }
1436*f489a6d7SJoseph Chen 
1437eecb3765SLin Jinhan static ulong rockchip_crypto_keytable_addr(struct udevice *dev)
1438eecb3765SLin Jinhan {
1439eecb3765SLin Jinhan 	return CRYPTO_S_BY_KEYLAD_BASE + CRYPTO_CH0_KEY_0;
1440eecb3765SLin Jinhan }
1441*f489a6d7SJoseph Chen #endif
144249a2135eSLin Jinhan #endif
144349a2135eSLin Jinhan 
1444864e581cSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1445b353a43cSLin Jinhan static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx,
1446b353a43cSLin Jinhan 				      u8 *sign, u8 *output)
1447b353a43cSLin Jinhan {
1448b353a43cSLin Jinhan 	struct mpa_num *mpa_m = NULL, *mpa_e = NULL, *mpa_n = NULL;
1449b353a43cSLin Jinhan 	struct mpa_num *mpa_c = NULL, *mpa_result = NULL;
1450b353a43cSLin Jinhan 	u32 n_bits, n_words;
1451b353a43cSLin Jinhan 	int ret;
1452b353a43cSLin Jinhan 
1453b353a43cSLin Jinhan 	if (!ctx)
1454b353a43cSLin Jinhan 		return -EINVAL;
1455b353a43cSLin Jinhan 
1456b353a43cSLin Jinhan 	if (ctx->algo != CRYPTO_RSA512 &&
1457b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA1024 &&
1458b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA2048 &&
1459b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA3072 &&
1460b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA4096)
1461b353a43cSLin Jinhan 		return -EINVAL;
1462b353a43cSLin Jinhan 
1463b353a43cSLin Jinhan 	n_bits = crypto_algo_nbits(ctx->algo);
1464b353a43cSLin Jinhan 	n_words = BITS2WORD(n_bits);
1465b353a43cSLin Jinhan 
1466549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_m, sign, n_words);
1467b353a43cSLin Jinhan 	if (ret)
1468b353a43cSLin Jinhan 		goto exit;
1469b353a43cSLin Jinhan 
1470549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_e, ctx->e, n_words);
1471549a74f7SLin Jinhan 	if (ret)
1472549a74f7SLin Jinhan 		goto exit;
1473b353a43cSLin Jinhan 
1474549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_n, ctx->n, n_words);
1475549a74f7SLin Jinhan 	if (ret)
1476549a74f7SLin Jinhan 		goto exit;
1477549a74f7SLin Jinhan 
1478549a74f7SLin Jinhan 	if (ctx->c) {
1479549a74f7SLin Jinhan 		ret = rk_mpa_alloc(&mpa_c, ctx->c, n_words);
1480549a74f7SLin Jinhan 		if (ret)
1481549a74f7SLin Jinhan 			goto exit;
1482549a74f7SLin Jinhan 	}
1483549a74f7SLin Jinhan 
1484549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_result, NULL, n_words);
1485549a74f7SLin Jinhan 	if (ret)
1486549a74f7SLin Jinhan 		goto exit;
1487b353a43cSLin Jinhan 
1488dd7763a8SFinley Xiao 	rk_crypto_enable_clk(dev);
1489b353a43cSLin Jinhan 	ret = rk_exptmod_np(mpa_m, mpa_e, mpa_n, mpa_c, mpa_result);
1490b353a43cSLin Jinhan 	if (!ret)
1491549a74f7SLin Jinhan 		memcpy(output, mpa_result->d, BITS2BYTE(n_bits));
1492dd7763a8SFinley Xiao 	rk_crypto_disable_clk(dev);
1493b353a43cSLin Jinhan 
1494b353a43cSLin Jinhan exit:
1495b353a43cSLin Jinhan 	rk_mpa_free(&mpa_m);
1496b353a43cSLin Jinhan 	rk_mpa_free(&mpa_e);
1497b353a43cSLin Jinhan 	rk_mpa_free(&mpa_n);
1498b353a43cSLin Jinhan 	rk_mpa_free(&mpa_c);
1499b353a43cSLin Jinhan 	rk_mpa_free(&mpa_result);
1500b353a43cSLin Jinhan 
1501b353a43cSLin Jinhan 	return ret;
1502b353a43cSLin Jinhan }
1503864e581cSLin Jinhan #endif
1504b353a43cSLin Jinhan 
150502b4cf42SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
150602b4cf42SLin Jinhan static int rockchip_crypto_ec_verify(struct udevice *dev, ec_key *ctx,
150702b4cf42SLin Jinhan 				     u8 *hash, u32 hash_len, u8 *sign)
150802b4cf42SLin Jinhan {
150902b4cf42SLin Jinhan 	struct mpa_num *bn_sign = NULL;
151002b4cf42SLin Jinhan 	struct rk_ecp_point point_P, point_sign;
151102b4cf42SLin Jinhan 	u32 n_bits, n_words;
151202b4cf42SLin Jinhan 	int ret;
151302b4cf42SLin Jinhan 
151402b4cf42SLin Jinhan 	if (!ctx)
151502b4cf42SLin Jinhan 		return -EINVAL;
151602b4cf42SLin Jinhan 
151702b4cf42SLin Jinhan 	if (ctx->algo != CRYPTO_SM2 &&
151802b4cf42SLin Jinhan 	    ctx->algo != CRYPTO_ECC_192R1 &&
151902b4cf42SLin Jinhan 	    ctx->algo != CRYPTO_ECC_224R1 &&
152002b4cf42SLin Jinhan 	    ctx->algo != CRYPTO_ECC_256R1)
152102b4cf42SLin Jinhan 		return -EINVAL;
152202b4cf42SLin Jinhan 
152302b4cf42SLin Jinhan 	n_bits = crypto_algo_nbits(ctx->algo);
152402b4cf42SLin Jinhan 	n_words = BITS2WORD(n_bits);
152502b4cf42SLin Jinhan 
152602b4cf42SLin Jinhan 	ret = rk_mpa_alloc(&bn_sign, sign, n_words);
152702b4cf42SLin Jinhan 	if (ret)
152802b4cf42SLin Jinhan 		goto exit;
152902b4cf42SLin Jinhan 
153002b4cf42SLin Jinhan 	ret = rk_mpa_alloc(&point_P.x, ctx->x, n_words);
153102b4cf42SLin Jinhan 	ret |= rk_mpa_alloc(&point_P.y, ctx->y, n_words);
153202b4cf42SLin Jinhan 	if (ret)
153302b4cf42SLin Jinhan 		goto exit;
153402b4cf42SLin Jinhan 
153502b4cf42SLin Jinhan 	ret = rk_mpa_alloc(&point_sign.x, sign, n_words);
153602b4cf42SLin Jinhan 	ret |= rk_mpa_alloc(&point_sign.y, sign + WORD2BYTE(n_words), n_words);
153702b4cf42SLin Jinhan 	if (ret)
153802b4cf42SLin Jinhan 		goto exit;
153902b4cf42SLin Jinhan 
154002b4cf42SLin Jinhan 	rk_crypto_enable_clk(dev);
154102b4cf42SLin Jinhan 	ret = rockchip_ecc_verify(ctx->algo, hash, hash_len, &point_P, &point_sign);
154202b4cf42SLin Jinhan 	rk_crypto_disable_clk(dev);
154302b4cf42SLin Jinhan exit:
154402b4cf42SLin Jinhan 	rk_mpa_free(&bn_sign);
154502b4cf42SLin Jinhan 	rk_mpa_free(&point_P.x);
154602b4cf42SLin Jinhan 	rk_mpa_free(&point_P.y);
154702b4cf42SLin Jinhan 	rk_mpa_free(&point_sign.x);
154802b4cf42SLin Jinhan 	rk_mpa_free(&point_sign.y);
154902b4cf42SLin Jinhan 
155002b4cf42SLin Jinhan 	return ret;
155102b4cf42SLin Jinhan }
155202b4cf42SLin Jinhan #endif
155302b4cf42SLin Jinhan 
1554b353a43cSLin Jinhan static const struct dm_crypto_ops rockchip_crypto_ops = {
1555b353a43cSLin Jinhan 	.capability   = rockchip_crypto_capability,
1556b353a43cSLin Jinhan 	.sha_init     = rockchip_crypto_sha_init,
1557b353a43cSLin Jinhan 	.sha_update   = rockchip_crypto_sha_update,
1558b353a43cSLin Jinhan 	.sha_final    = rockchip_crypto_sha_final,
155949a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1560b353a43cSLin Jinhan 	.rsa_verify   = rockchip_crypto_rsa_verify,
156149a2135eSLin Jinhan #endif
156202b4cf42SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
156302b4cf42SLin Jinhan 	.ec_verify    = rockchip_crypto_ec_verify,
156402b4cf42SLin Jinhan #endif
156549a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
156649a2135eSLin Jinhan 	.hmac_init    = rockchip_crypto_hmac_init,
156749a2135eSLin Jinhan 	.hmac_update  = rockchip_crypto_hmac_update,
156849a2135eSLin Jinhan 	.hmac_final   = rockchip_crypto_hmac_final,
156949a2135eSLin Jinhan #endif
157049a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
157149a2135eSLin Jinhan 	.cipher_crypt    = rockchip_crypto_cipher,
1572d9332f1cSLin Jinhan 	.cipher_mac      = rockchip_crypto_mac,
1573c3ce9937SLin Jinhan 	.cipher_ae       = rockchip_crypto_ae,
1574*f489a6d7SJoseph Chen #if CONFIG_IS_ENABLED(DM_KEYLAD)
1575eecb3765SLin Jinhan 	.cipher_fw_crypt = rockchip_crypto_fw_cipher,
1576eecb3765SLin Jinhan 	.keytable_addr   = rockchip_crypto_keytable_addr,
157749a2135eSLin Jinhan #endif
1578*f489a6d7SJoseph Chen #endif
1579b353a43cSLin Jinhan };
1580b353a43cSLin Jinhan 
1581b353a43cSLin Jinhan /*
1582b353a43cSLin Jinhan  * Only use "clocks" to parse crypto clock id and use rockchip_get_clk().
1583b353a43cSLin Jinhan  * Because we always add crypto node in U-Boot dts, when kernel dtb enabled :
1584b353a43cSLin Jinhan  *
1585b353a43cSLin Jinhan  *   1. There is cru phandle mismatch between U-Boot and kernel dtb;
1586b353a43cSLin Jinhan  *   2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property;
1587b353a43cSLin Jinhan  */
1588b353a43cSLin Jinhan static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev)
1589b353a43cSLin Jinhan {
1590b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1591b353a43cSLin Jinhan 	int len, ret = -EINVAL;
1592b353a43cSLin Jinhan 
1593a24b2aebSLin Jinhan 	memset(priv, 0x00, sizeof(*priv));
1594a24b2aebSLin Jinhan 
1595a24b2aebSLin Jinhan 	priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev);
1596a24b2aebSLin Jinhan 	if (priv->reg == FDT_ADDR_T_NONE)
1597a24b2aebSLin Jinhan 		return -EINVAL;
1598a24b2aebSLin Jinhan 
1599a24b2aebSLin Jinhan 	crypto_base = priv->reg;
1600a24b2aebSLin Jinhan 
1601a24b2aebSLin Jinhan 	/* if there is no clocks in dts, just skip it */
1602b353a43cSLin Jinhan 	if (!dev_read_prop(dev, "clocks", &len)) {
1603b353a43cSLin Jinhan 		printf("Can't find \"clocks\" property\n");
1604a24b2aebSLin Jinhan 		return 0;
1605b353a43cSLin Jinhan 	}
1606b353a43cSLin Jinhan 
16076b0f7484SLin Jinhan 	memset(priv, 0x00, sizeof(*priv));
1608b353a43cSLin Jinhan 	priv->clocks = malloc(len);
1609b353a43cSLin Jinhan 	if (!priv->clocks)
1610b353a43cSLin Jinhan 		return -ENOMEM;
1611b353a43cSLin Jinhan 
1612da703fb5SLin Jinhan 	priv->nclocks = len / (2 * sizeof(u32));
1613b353a43cSLin Jinhan 	if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks,
1614b353a43cSLin Jinhan 			       priv->nclocks)) {
1615b353a43cSLin Jinhan 		printf("Can't read \"clocks\" property\n");
1616b353a43cSLin Jinhan 		ret = -EINVAL;
1617b353a43cSLin Jinhan 		goto exit;
1618b353a43cSLin Jinhan 	}
1619b353a43cSLin Jinhan 
1620da703fb5SLin Jinhan 	if (dev_read_prop(dev, "clock-frequency", &len)) {
1621b353a43cSLin Jinhan 		priv->frequencies = malloc(len);
1622b353a43cSLin Jinhan 		if (!priv->frequencies) {
1623b353a43cSLin Jinhan 			ret = -ENOMEM;
1624b353a43cSLin Jinhan 			goto exit;
1625b353a43cSLin Jinhan 		}
1626a8335d81SFinley Xiao 		priv->freq_nclocks = len / sizeof(u32);
1627b353a43cSLin Jinhan 		if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies,
1628da703fb5SLin Jinhan 				       priv->freq_nclocks)) {
1629b353a43cSLin Jinhan 			printf("Can't read \"clock-frequency\" property\n");
1630b353a43cSLin Jinhan 			ret = -EINVAL;
1631b353a43cSLin Jinhan 			goto exit;
1632b353a43cSLin Jinhan 		}
1633da703fb5SLin Jinhan 	}
1634b353a43cSLin Jinhan 
1635b353a43cSLin Jinhan 	return 0;
1636b353a43cSLin Jinhan exit:
1637b353a43cSLin Jinhan 	if (priv->clocks)
1638b353a43cSLin Jinhan 		free(priv->clocks);
1639b353a43cSLin Jinhan 
1640b353a43cSLin Jinhan 	if (priv->frequencies)
1641b353a43cSLin Jinhan 		free(priv->frequencies);
1642b353a43cSLin Jinhan 
1643b353a43cSLin Jinhan 	return ret;
1644b353a43cSLin Jinhan }
1645b353a43cSLin Jinhan 
16466cebff12SJoseph Chen static int rk_crypto_set_clk(struct udevice *dev)
1647b353a43cSLin Jinhan {
16486cebff12SJoseph Chen 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
16496cebff12SJoseph Chen 	struct clk clk;
1650a24b2aebSLin Jinhan 	int i, ret;
1651b353a43cSLin Jinhan 
1652a8335d81SFinley Xiao 	/* use standard "assigned-clock-rates" props */
1653a8335d81SFinley Xiao 	if (dev_read_size(dev, "assigned-clock-rates") > 0)
1654a8335d81SFinley Xiao 		return clk_set_defaults(dev);
1655da703fb5SLin Jinhan 
1656a8335d81SFinley Xiao 	/* use "clock-frequency" props */
1657da703fb5SLin Jinhan 	if (priv->freq_nclocks == 0)
1658a24b2aebSLin Jinhan 		return 0;
165949a2135eSLin Jinhan 
1660da703fb5SLin Jinhan 	for (i = 0; i < priv->freq_nclocks; i++) {
16616cebff12SJoseph Chen 		ret = clk_get_by_index(dev, i, &clk);
16626cebff12SJoseph Chen 		if (ret < 0) {
16636cebff12SJoseph Chen 			printf("Failed to get clk index %d, ret=%d\n", i, ret);
1664b353a43cSLin Jinhan 			return ret;
1665b353a43cSLin Jinhan 		}
16666cebff12SJoseph Chen 		ret = clk_set_rate(&clk, priv->frequencies[i]);
1667b353a43cSLin Jinhan 		if (ret < 0) {
1668b353a43cSLin Jinhan 			printf("%s: Failed to set clk(%ld): ret=%d\n",
16696cebff12SJoseph Chen 			       __func__, clk.id, ret);
1670b353a43cSLin Jinhan 			return ret;
1671b353a43cSLin Jinhan 		}
1672b353a43cSLin Jinhan 	}
1673b353a43cSLin Jinhan 
1674a24b2aebSLin Jinhan 	return 0;
1675a24b2aebSLin Jinhan }
1676a24b2aebSLin Jinhan 
1677a24b2aebSLin Jinhan static int rockchip_crypto_probe(struct udevice *dev)
1678a24b2aebSLin Jinhan {
1679a24b2aebSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1680a24b2aebSLin Jinhan 	struct rk_crypto_soc_data *sdata;
1681a24b2aebSLin Jinhan 	int ret = 0;
1682a24b2aebSLin Jinhan 
1683a24b2aebSLin Jinhan 	sdata = (struct rk_crypto_soc_data *)dev_get_driver_data(dev);
168458432b6fSLin Jinhan 
168558432b6fSLin Jinhan 	if (sdata->dynamic_cap)
168658432b6fSLin Jinhan 		sdata->capability = sdata->dynamic_cap();
168758432b6fSLin Jinhan 
1688a24b2aebSLin Jinhan 	priv->soc_data = sdata;
1689a24b2aebSLin Jinhan 
1690a24b2aebSLin Jinhan 	priv->hw_ctx = memalign(LLI_ADDR_ALIGN_SIZE,
1691a24b2aebSLin Jinhan 				sizeof(struct rk_hash_ctx));
1692a24b2aebSLin Jinhan 	if (!priv->hw_ctx)
1693a24b2aebSLin Jinhan 		return -ENOMEM;
1694a24b2aebSLin Jinhan 
16956cebff12SJoseph Chen 	ret = rk_crypto_set_clk(dev);
1696a24b2aebSLin Jinhan 	if (ret)
1697a24b2aebSLin Jinhan 		return ret;
1698a24b2aebSLin Jinhan 
1699f2c2c30cSLin Jinhan 	rk_crypto_enable_clk(dev);
1700f2c2c30cSLin Jinhan 
1701b353a43cSLin Jinhan 	hw_crypto_reset();
1702b353a43cSLin Jinhan 
1703f2c2c30cSLin Jinhan 	rk_crypto_disable_clk(dev);
1704f2c2c30cSLin Jinhan 
1705b353a43cSLin Jinhan 	return 0;
1706b353a43cSLin Jinhan }
1707b353a43cSLin Jinhan 
170849a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base = {
170949a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
171049a2135eSLin Jinhan 		      CRYPTO_SHA1 |
171149a2135eSLin Jinhan 		      CRYPTO_SHA256 |
171249a2135eSLin Jinhan 		      CRYPTO_SHA512 |
171349a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
171449a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
171549a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
171649a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
171749a2135eSLin Jinhan 		      CRYPTO_RSA512 |
171849a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
171949a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
172049a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
172149a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
172249a2135eSLin Jinhan 		      CRYPTO_DES |
172349a2135eSLin Jinhan 		      CRYPTO_AES,
172449a2135eSLin Jinhan };
172549a2135eSLin Jinhan 
172649a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base_sm = {
172749a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
172849a2135eSLin Jinhan 		      CRYPTO_SHA1 |
172949a2135eSLin Jinhan 		      CRYPTO_SHA256 |
173049a2135eSLin Jinhan 		      CRYPTO_SHA512 |
173149a2135eSLin Jinhan 		      CRYPTO_SM3 |
173249a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
173349a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
173449a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
173549a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
173649a2135eSLin Jinhan 		      CRYPTO_HMAC_SM3 |
173749a2135eSLin Jinhan 		      CRYPTO_RSA512 |
173849a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
173949a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
174049a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
174149a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
174249a2135eSLin Jinhan 		      CRYPTO_DES |
174349a2135eSLin Jinhan 		      CRYPTO_AES |
174449a2135eSLin Jinhan 		      CRYPTO_SM4,
174549a2135eSLin Jinhan };
174649a2135eSLin Jinhan 
174749a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_rk1808 = {
174849a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
174949a2135eSLin Jinhan 		      CRYPTO_SHA1 |
175049a2135eSLin Jinhan 		      CRYPTO_SHA256 |
175149a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
175249a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
175349a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
175449a2135eSLin Jinhan 		      CRYPTO_RSA512 |
175549a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
175649a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
175749a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
175849a2135eSLin Jinhan 		      CRYPTO_RSA4096,
175949a2135eSLin Jinhan };
176049a2135eSLin Jinhan 
176158432b6fSLin Jinhan static const struct rk_crypto_soc_data soc_data_cryptov3 = {
176258432b6fSLin Jinhan 	.capability  = 0,
176358432b6fSLin Jinhan 	.dynamic_cap = crypto_v3_dynamic_cap,
176458432b6fSLin Jinhan };
176558432b6fSLin Jinhan 
1766b353a43cSLin Jinhan static const struct udevice_id rockchip_crypto_ids[] = {
176749a2135eSLin Jinhan 	{
176849a2135eSLin Jinhan 		.compatible = "rockchip,px30-crypto",
176949a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
177049a2135eSLin Jinhan 	},
177149a2135eSLin Jinhan 	{
177249a2135eSLin Jinhan 		.compatible = "rockchip,rk1808-crypto",
177349a2135eSLin Jinhan 		.data = (ulong)&soc_data_rk1808
177449a2135eSLin Jinhan 	},
177549a2135eSLin Jinhan 	{
177649a2135eSLin Jinhan 		.compatible = "rockchip,rk3308-crypto",
177749a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
177849a2135eSLin Jinhan 	},
177949a2135eSLin Jinhan 	{
178049a2135eSLin Jinhan 		.compatible = "rockchip,rv1126-crypto",
178149a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
178249a2135eSLin Jinhan 	},
178349a2135eSLin Jinhan 	{
178449a2135eSLin Jinhan 		.compatible = "rockchip,rk3568-crypto",
178549a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
178649a2135eSLin Jinhan 	},
17875b3e3895SLin Jinhan 	{
17885b3e3895SLin Jinhan 		.compatible = "rockchip,rk3588-crypto",
17895b3e3895SLin Jinhan 		.data = (ulong)&soc_data_base_sm
17905b3e3895SLin Jinhan 	},
179158432b6fSLin Jinhan 	{
1792f93f9077SLin Jinhan 		.compatible = "rockchip,crypto-v3",
179358432b6fSLin Jinhan 		.data = (ulong)&soc_data_cryptov3
179458432b6fSLin Jinhan 	},
17952bcebb1aSLin Jinhan 	{
17962bcebb1aSLin Jinhan 		.compatible = "rockchip,crypto-v4",
17972bcebb1aSLin Jinhan 		.data = (ulong)&soc_data_cryptov3 /* reuse crypto v3 config */
17982bcebb1aSLin Jinhan 	},
1799b353a43cSLin Jinhan 	{ }
1800b353a43cSLin Jinhan };
1801b353a43cSLin Jinhan 
1802b353a43cSLin Jinhan U_BOOT_DRIVER(rockchip_crypto_v2) = {
1803b353a43cSLin Jinhan 	.name		= "rockchip_crypto_v2",
1804b353a43cSLin Jinhan 	.id		= UCLASS_CRYPTO,
1805b353a43cSLin Jinhan 	.of_match	= rockchip_crypto_ids,
1806b353a43cSLin Jinhan 	.ops		= &rockchip_crypto_ops,
1807b353a43cSLin Jinhan 	.probe		= rockchip_crypto_probe,
1808b353a43cSLin Jinhan 	.ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata,
1809b353a43cSLin Jinhan 	.priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv),
1810b353a43cSLin Jinhan };
1811