xref: /rk3399_rockchip-uboot/drivers/crypto/rockchip/crypto_v2.c (revision 2bcebb1a79550117e5474bb586bdc094e4fe0576)
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;
4858432b6fSLin Jinhan 	u32 (*dynamic_cap)(void);
4949a2135eSLin Jinhan };
5049a2135eSLin Jinhan 
51b353a43cSLin Jinhan struct rockchip_crypto_priv {
52b353a43cSLin Jinhan 	fdt_addr_t			reg;
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)
97dbca2fe7SLin Jinhan #define align_free(addr)		do {if (addr) free(addr);} while (0)
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 || \
108c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_CBC_MAC || \
109c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_CCM || \
110c3ce9937SLin 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 
115c3ce9937SLin Jinhan #define IS_AE_MODE(rk_mode) ((rk_mode) == RK_MODE_CCM || \
116c3ce9937SLin Jinhan 			     (rk_mode) == RK_MODE_GCM)
117c3ce9937SLin 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 
152c3ce9937SLin Jinhan static inline void read_regs(u32 base, u8 *data, u32 data_len)
153c3ce9937SLin Jinhan {
154c3ce9937SLin Jinhan 	u8 tmp_buf[4];
155c3ce9937SLin Jinhan 	u32 i;
156c3ce9937SLin Jinhan 
157c3ce9937SLin Jinhan 	for (i = 0; i < data_len / 4; i++)
158c3ce9937SLin Jinhan 		word2byte_be(crypto_read(base + i * 4),
159c3ce9937SLin Jinhan 			     data + i * 4);
160c3ce9937SLin Jinhan 
161c3ce9937SLin Jinhan 	if (data_len % 4) {
162c3ce9937SLin Jinhan 		word2byte_be(crypto_read(base + i * 4), tmp_buf);
163c3ce9937SLin Jinhan 		memcpy(data + i * 4, tmp_buf, data_len % 4);
164c3ce9937SLin Jinhan 	}
165c3ce9937SLin Jinhan }
166c3ce9937SLin 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 
204c3ce9937SLin Jinhan static inline void get_iv_reg(u32 chn, u8 *iv, u32 iv_len)
205c3ce9937SLin Jinhan {
206c3ce9937SLin Jinhan 	u32 base_iv;
207c3ce9937SLin Jinhan 
208c3ce9937SLin Jinhan 	base_iv = CRYPTO_CH0_IV_0 + chn * 0x10;
209c3ce9937SLin Jinhan 
210c3ce9937SLin Jinhan 	read_regs(base_iv, iv, iv_len);
211c3ce9937SLin Jinhan }
212c3ce9937SLin 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 
22258432b6fSLin Jinhan static u32 crypto_v3_dynamic_cap(void)
22358432b6fSLin Jinhan {
22458432b6fSLin Jinhan 	u32 capability = 0;
22558432b6fSLin Jinhan 	u32 ver_reg, i;
22658432b6fSLin Jinhan 	struct cap_map {
22758432b6fSLin Jinhan 		u32 ver_offset;
22858432b6fSLin Jinhan 		u32 mask;
22958432b6fSLin Jinhan 		u32 cap_bit;
23058432b6fSLin Jinhan 	};
23158432b6fSLin Jinhan 	const struct cap_map cap_tbl[] = {
23258432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_MD5_FLAG,    CRYPTO_MD5},
23358432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA1_FLAG,   CRYPTO_SHA1},
23458432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA256_FLAG, CRYPTO_SHA256},
23558432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA512_FLAG, CRYPTO_SHA512},
23658432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SM3_FLAG,    CRYPTO_SM3},
23758432b6fSLin Jinhan 
23858432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_MD5_FLAG,    CRYPTO_HMAC_MD5},
23958432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA1_FLAG,   CRYPTO_HMAC_SHA1},
24058432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA256_FLAG, CRYPTO_HMAC_SHA256},
24158432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA512_FLAG, CRYPTO_HMAC_SHA512},
24258432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SM3_FLAG,    CRYPTO_HMAC_SM3},
24358432b6fSLin Jinhan 
24458432b6fSLin Jinhan 	{CRYPTO_AES_VERSION,  CRYPTO_AES256_FLAG,      CRYPTO_AES},
24558432b6fSLin Jinhan 	{CRYPTO_DES_VERSION,  CRYPTO_TDES_FLAG,        CRYPTO_DES},
24658432b6fSLin Jinhan 	{CRYPTO_SM4_VERSION,  CRYPTO_ECB_FLAG,         CRYPTO_SM4},
24758432b6fSLin Jinhan 	};
24858432b6fSLin Jinhan 
24958432b6fSLin Jinhan 	/* rsa */
25058432b6fSLin Jinhan 	capability = CRYPTO_RSA512 |
25158432b6fSLin Jinhan 		     CRYPTO_RSA1024 |
25258432b6fSLin Jinhan 		     CRYPTO_RSA2048 |
25358432b6fSLin Jinhan 		     CRYPTO_RSA3072 |
25458432b6fSLin Jinhan 		     CRYPTO_RSA4096;
25558432b6fSLin Jinhan 
25658432b6fSLin Jinhan 	for (i = 0; i < ARRAY_SIZE(cap_tbl); i++) {
25758432b6fSLin Jinhan 		ver_reg = crypto_read(cap_tbl[i].ver_offset);
25858432b6fSLin Jinhan 
25958432b6fSLin Jinhan 		if ((ver_reg & cap_tbl[i].mask) == cap_tbl[i].mask)
26058432b6fSLin Jinhan 			capability |= cap_tbl[i].cap_bit;
26158432b6fSLin Jinhan 	}
26258432b6fSLin Jinhan 
26358432b6fSLin Jinhan 	return capability;
26458432b6fSLin Jinhan }
26558432b6fSLin Jinhan 
266b353a43cSLin Jinhan static int hw_crypto_reset(void)
267b353a43cSLin Jinhan {
26849a2135eSLin Jinhan 	u32 val = 0, mask = 0;
269b353a43cSLin Jinhan 	int ret;
270b353a43cSLin Jinhan 
27149a2135eSLin Jinhan 	val = CRYPTO_SW_PKA_RESET | CRYPTO_SW_CC_RESET;
27249a2135eSLin Jinhan 	mask = val << CRYPTO_WRITE_MASK_SHIFT;
273b353a43cSLin Jinhan 
274b353a43cSLin Jinhan 	/* reset pka and crypto modules*/
27549a2135eSLin Jinhan 	crypto_write(val | mask, CRYPTO_RST_CTL);
276b353a43cSLin Jinhan 
277b353a43cSLin Jinhan 	/* wait reset compelete */
27849a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL), RK_CRYPTO_TIMEOUT);
27949a2135eSLin Jinhan 
280b353a43cSLin Jinhan 	return ret;
281b353a43cSLin Jinhan }
282b353a43cSLin Jinhan 
283b353a43cSLin Jinhan static void hw_hash_clean_ctx(struct rk_hash_ctx *ctx)
284b353a43cSLin Jinhan {
285b353a43cSLin Jinhan 	/* clear hash status */
286b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
287b353a43cSLin Jinhan 
2881606a214SLin Jinhan 	assert(ctx);
2891606a214SLin Jinhan 	assert(ctx->magic == RK_HASH_CTX_MAGIC);
2901606a214SLin Jinhan 
291c48f1acfSLin Jinhan 	crypto_hash_cache_free(ctx->hash_cache);
2921606a214SLin Jinhan 
2931606a214SLin Jinhan 	memset(ctx, 0x00, sizeof(*ctx));
294b353a43cSLin Jinhan }
295b353a43cSLin Jinhan 
296c48f1acfSLin Jinhan static int rk_hash_init(void *hw_ctx, u32 algo)
297b353a43cSLin Jinhan {
298b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)hw_ctx;
299b353a43cSLin Jinhan 	u32 reg_ctrl = 0;
300b353a43cSLin Jinhan 	int ret;
301b353a43cSLin Jinhan 
302b353a43cSLin Jinhan 	if (!tmp_ctx)
303b353a43cSLin Jinhan 		return -EINVAL;
304b353a43cSLin Jinhan 
3051606a214SLin Jinhan 	reg_ctrl = CRYPTO_SW_CC_RESET;
3061606a214SLin Jinhan 	crypto_write(reg_ctrl | (reg_ctrl << CRYPTO_WRITE_MASK_SHIFT),
3071606a214SLin Jinhan 		     CRYPTO_RST_CTL);
3081606a214SLin Jinhan 
3091606a214SLin Jinhan 	/* wait reset compelete */
31049a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL),
31149a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
3121606a214SLin Jinhan 
3131606a214SLin Jinhan 	reg_ctrl = 0;
314b353a43cSLin Jinhan 	tmp_ctx->algo = algo;
315b353a43cSLin Jinhan 	switch (algo) {
316b353a43cSLin Jinhan 	case CRYPTO_MD5:
31749a2135eSLin Jinhan 	case CRYPTO_HMAC_MD5:
318b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_MD5;
319b353a43cSLin Jinhan 		tmp_ctx->digest_size = 16;
320b353a43cSLin Jinhan 		break;
321b353a43cSLin Jinhan 	case CRYPTO_SHA1:
32249a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA1:
323b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA1;
324b353a43cSLin Jinhan 		tmp_ctx->digest_size = 20;
325b353a43cSLin Jinhan 		break;
326b353a43cSLin Jinhan 	case CRYPTO_SHA256:
32749a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA256:
328b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA256;
329b353a43cSLin Jinhan 		tmp_ctx->digest_size = 32;
330b353a43cSLin Jinhan 		break;
331e7846385SLin Jinhan 	case CRYPTO_SHA512:
33249a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA512:
333e7846385SLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA512;
334e7846385SLin Jinhan 		tmp_ctx->digest_size = 64;
335e7846385SLin Jinhan 		break;
33649a2135eSLin Jinhan 	case CRYPTO_SM3:
33749a2135eSLin Jinhan 	case CRYPTO_HMAC_SM3:
33849a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SM3;
33949a2135eSLin Jinhan 		tmp_ctx->digest_size = 32;
34049a2135eSLin Jinhan 		break;
341b353a43cSLin Jinhan 	default:
342b353a43cSLin Jinhan 		ret = -EINVAL;
343b353a43cSLin Jinhan 		goto exit;
344b353a43cSLin Jinhan 	}
345b353a43cSLin Jinhan 
346b353a43cSLin Jinhan 	clear_hash_out_reg();
347b353a43cSLin Jinhan 
348b353a43cSLin Jinhan 	/* enable hardware padding */
349b353a43cSLin Jinhan 	reg_ctrl |= CRYPTO_HW_PAD_ENABLE;
350b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
351b353a43cSLin Jinhan 
352b353a43cSLin Jinhan 	/* FIFO input and output data byte swap */
353b353a43cSLin Jinhan 	/* such as B0, B1, B2, B3 -> B3, B2, B1, B0 */
354b353a43cSLin Jinhan 	reg_ctrl = CRYPTO_DOUT_BYTESWAP | CRYPTO_DOIN_BYTESWAP;
355b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_FIFO_CTL);
356b353a43cSLin Jinhan 
3571606a214SLin Jinhan 	/* enable src_item_done interrupt */
358fe0c4b19SLin Jinhan 	crypto_write(0, CRYPTO_DMA_INT_EN);
359b353a43cSLin Jinhan 
360b353a43cSLin Jinhan 	tmp_ctx->magic = RK_HASH_CTX_MAGIC;
361b353a43cSLin Jinhan 
362b353a43cSLin Jinhan 	return 0;
363b353a43cSLin Jinhan exit:
364b353a43cSLin Jinhan 	/* clear hash setting if init failed */
365b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
366b353a43cSLin Jinhan 
367b353a43cSLin Jinhan 	return ret;
368b353a43cSLin Jinhan }
369b353a43cSLin Jinhan 
370c48f1acfSLin Jinhan static int rk_hash_direct_calc(void *hw_data, const u8 *data,
3711606a214SLin Jinhan 			       u32 data_len, u8 *started_flag, u8 is_last)
372b353a43cSLin Jinhan {
373c48f1acfSLin Jinhan 	struct rockchip_crypto_priv *priv = hw_data;
374c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
375c48f1acfSLin Jinhan 	struct crypto_lli_desc *lli = &hash_ctx->data_lli;
376b353a43cSLin Jinhan 	int ret = -EINVAL;
37700fa57d8SLin Jinhan 	u32 tmp = 0, mask = 0;
378b353a43cSLin Jinhan 
37949a2135eSLin Jinhan 	assert(IS_ALIGNED((ulong)data, DATA_ADDR_ALIGN_SIZE));
38049a2135eSLin Jinhan 	assert(is_last || IS_ALIGNED(data_len, DATA_LEN_ALIGN_SIZE));
381b353a43cSLin Jinhan 
3821606a214SLin Jinhan 	debug("%s: data = %p, len = %u, s = %x, l = %x\n",
3831606a214SLin Jinhan 	      __func__, data, data_len, *started_flag, is_last);
384b353a43cSLin Jinhan 
3851606a214SLin Jinhan 	memset(lli, 0x00, sizeof(*lli));
3861606a214SLin Jinhan 	lli->src_addr = (u32)virt_to_phys(data);
3871606a214SLin Jinhan 	lli->src_len = data_len;
3881606a214SLin Jinhan 	lli->dma_ctrl = LLI_DMA_CTRL_SRC_DONE;
389b353a43cSLin Jinhan 
3901606a214SLin Jinhan 	if (is_last) {
3911606a214SLin Jinhan 		lli->user_define |= LLI_USER_STRING_LAST;
3921606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_LAST;
393b353a43cSLin Jinhan 	} else {
3941606a214SLin Jinhan 		lli->next_addr = (u32)virt_to_phys(lli);
3951606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_PAUSE;
3961606a214SLin Jinhan 	}
3971606a214SLin Jinhan 
3981606a214SLin Jinhan 	if (!(*started_flag)) {
3991606a214SLin Jinhan 		lli->user_define |=
4001606a214SLin Jinhan 			(LLI_USER_STRING_START | LLI_USER_CPIHER_START);
4011606a214SLin Jinhan 		crypto_write((u32)virt_to_phys(lli), CRYPTO_DMA_LLI_ADDR);
4021606a214SLin Jinhan 		crypto_write((CRYPTO_HASH_ENABLE << CRYPTO_WRITE_MASK_SHIFT) |
4031606a214SLin Jinhan 			     CRYPTO_HASH_ENABLE, CRYPTO_HASH_CTL);
4041606a214SLin Jinhan 		tmp = CRYPTO_DMA_START;
4051606a214SLin Jinhan 		*started_flag = 1;
4061606a214SLin Jinhan 	} else {
407b353a43cSLin Jinhan 		tmp = CRYPTO_DMA_RESTART;
408b353a43cSLin Jinhan 	}
409b353a43cSLin Jinhan 
410b353a43cSLin Jinhan 	/* flush cache */
411c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)lli, sizeof(*lli));
412c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)data, data_len);
413b353a43cSLin Jinhan 
414b353a43cSLin Jinhan 	/* start calculate */
415b353a43cSLin Jinhan 	crypto_write(tmp << CRYPTO_WRITE_MASK_SHIFT | tmp,
416b353a43cSLin Jinhan 		     CRYPTO_DMA_CTL);
417b353a43cSLin Jinhan 
41800fa57d8SLin Jinhan 	/* mask CRYPTO_SYNC_LOCKSTEP_INT_ST flag */
41900fa57d8SLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
42000fa57d8SLin Jinhan 
421b353a43cSLin Jinhan 	/* wait calc ok */
42249a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
42349a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
424b353a43cSLin Jinhan 
425b353a43cSLin Jinhan 	/* clear interrupt status */
426b353a43cSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
427b353a43cSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
428b353a43cSLin Jinhan 
42949cbb0faSLin Jinhan 	if ((tmp & mask) != CRYPTO_SRC_ITEM_DONE_INT_ST &&
43049cbb0faSLin Jinhan 	    (tmp & mask) != CRYPTO_ZERO_LEN_INT_ST) {
43146aac970SLin Jinhan 		ret = -EFAULT;
4321606a214SLin Jinhan 		debug("[%s] %d: CRYPTO_DMA_INT_ST = 0x%x\n",
433b353a43cSLin Jinhan 		      __func__, __LINE__, tmp);
4341606a214SLin Jinhan 		goto exit;
435b353a43cSLin Jinhan 	}
436b353a43cSLin Jinhan 
437c48f1acfSLin Jinhan 	priv->length += data_len;
4381606a214SLin Jinhan exit:
4391606a214SLin Jinhan 	return ret;
440b353a43cSLin Jinhan }
4411606a214SLin Jinhan 
4421606a214SLin Jinhan int rk_hash_update(void *ctx, const u8 *data, u32 data_len)
4431606a214SLin Jinhan {
4441606a214SLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
445c48f1acfSLin Jinhan 	int ret = -EINVAL;
4461606a214SLin Jinhan 
4471606a214SLin Jinhan 	debug("\n");
4481606a214SLin Jinhan 	if (!tmp_ctx || !data)
449c48f1acfSLin Jinhan 		goto exit;
4501606a214SLin Jinhan 
4511606a214SLin Jinhan 	if (tmp_ctx->digest_size == 0 || tmp_ctx->magic != RK_HASH_CTX_MAGIC)
452c48f1acfSLin Jinhan 		goto exit;
4531606a214SLin Jinhan 
454c48f1acfSLin Jinhan 	ret = crypto_hash_update_with_cache(tmp_ctx->hash_cache,
455c48f1acfSLin Jinhan 					    data, data_len);
4561606a214SLin Jinhan 
457c48f1acfSLin Jinhan exit:
458b353a43cSLin Jinhan 	/* free lli list */
459c48f1acfSLin Jinhan 	if (ret)
460b353a43cSLin Jinhan 		hw_hash_clean_ctx(tmp_ctx);
461b353a43cSLin Jinhan 
462c48f1acfSLin Jinhan 	return ret;
463b353a43cSLin Jinhan }
464b353a43cSLin Jinhan 
465b353a43cSLin Jinhan int rk_hash_final(void *ctx, u8 *digest, size_t len)
466b353a43cSLin Jinhan {
467b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
468b353a43cSLin Jinhan 	int ret = -EINVAL;
469b353a43cSLin Jinhan 
470b353a43cSLin Jinhan 	if (!digest)
471b353a43cSLin Jinhan 		goto exit;
472b353a43cSLin Jinhan 
473b353a43cSLin Jinhan 	if (!tmp_ctx ||
474b353a43cSLin Jinhan 	    tmp_ctx->digest_size == 0 ||
475b353a43cSLin Jinhan 	    len > tmp_ctx->digest_size ||
476b353a43cSLin Jinhan 	    tmp_ctx->magic != RK_HASH_CTX_MAGIC) {
477b353a43cSLin Jinhan 		goto exit;
478b353a43cSLin Jinhan 	}
479b353a43cSLin Jinhan 
480b353a43cSLin Jinhan 	/* wait hash value ok */
48149a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!crypto_read(CRYPTO_HASH_VALID),
48249a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
483b353a43cSLin Jinhan 
484c3ce9937SLin Jinhan 	read_regs(CRYPTO_HASH_DOUT_0, digest, len);
485b353a43cSLin Jinhan 
486b353a43cSLin Jinhan 	/* clear hash status */
487b353a43cSLin Jinhan 	crypto_write(CRYPTO_HASH_IS_VALID, CRYPTO_HASH_VALID);
488b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
489b353a43cSLin Jinhan 
490b353a43cSLin Jinhan exit:
491b353a43cSLin Jinhan 
492b353a43cSLin Jinhan 	return ret;
493b353a43cSLin Jinhan }
494b353a43cSLin Jinhan 
495b353a43cSLin Jinhan static u32 rockchip_crypto_capability(struct udevice *dev)
496b353a43cSLin Jinhan {
49749a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
49849a2135eSLin Jinhan 	u32 capability, mask = 0;
4997eea1823SLin Jinhan 
50049a2135eSLin Jinhan 	capability = priv->soc_data->capability;
50149a2135eSLin Jinhan 
50249a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_CIPHER))
50349a2135eSLin Jinhan 	mask |= (CRYPTO_DES | CRYPTO_AES | CRYPTO_SM4);
504c0e47d03SLin Jinhan #endif
5057eea1823SLin Jinhan 
50649a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_HMAC))
50749a2135eSLin Jinhan 	mask |= (CRYPTO_HMAC_MD5 | CRYPTO_HMAC_SHA1 | CRYPTO_HMAC_SHA256 |
50849a2135eSLin Jinhan 			 CRYPTO_HMAC_SHA512 | CRYPTO_HMAC_SM3);
50949a2135eSLin Jinhan #endif
51049a2135eSLin Jinhan 
51149a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_RSA))
51249a2135eSLin Jinhan 	mask |= (CRYPTO_RSA512 | CRYPTO_RSA1024 | CRYPTO_RSA2048 |
51349a2135eSLin Jinhan 			 CRYPTO_RSA3072 | CRYPTO_RSA4096);
51449a2135eSLin Jinhan #endif
51549a2135eSLin Jinhan 
51649a2135eSLin Jinhan 	return capability & (~mask);
517b353a43cSLin Jinhan }
518b353a43cSLin Jinhan 
519b353a43cSLin Jinhan static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx)
520b353a43cSLin Jinhan {
521b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
522c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
523b353a43cSLin Jinhan 
524b353a43cSLin Jinhan 	if (!ctx)
525b353a43cSLin Jinhan 		return -EINVAL;
526b353a43cSLin Jinhan 
527c48f1acfSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
528b353a43cSLin Jinhan 
529c48f1acfSLin Jinhan 	priv->length = 0;
530c48f1acfSLin Jinhan 
531c48f1acfSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
532c48f1acfSLin Jinhan 						       priv, ctx->length,
53349a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
53449a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
535c48f1acfSLin Jinhan 	if (!hash_ctx->hash_cache)
536c48f1acfSLin Jinhan 		return -EFAULT;
537c48f1acfSLin Jinhan 
538c48f1acfSLin Jinhan 	return rk_hash_init(hash_ctx, ctx->algo);
539b353a43cSLin Jinhan }
540b353a43cSLin Jinhan 
541b353a43cSLin Jinhan static int rockchip_crypto_sha_update(struct udevice *dev,
542b353a43cSLin Jinhan 				      u32 *input, u32 len)
543b353a43cSLin Jinhan {
544b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
545086e8fa8SLin Jinhan 	int ret, i;
546086e8fa8SLin Jinhan 	u8 *p;
547b353a43cSLin Jinhan 
548b353a43cSLin Jinhan 	if (!len)
549b353a43cSLin Jinhan 		return -EINVAL;
550b353a43cSLin Jinhan 
551086e8fa8SLin Jinhan 	p = (u8 *)input;
552086e8fa8SLin Jinhan 
553086e8fa8SLin Jinhan 	for (i = 0; i < len / HASH_UPDATE_LIMIT; i++, p += HASH_UPDATE_LIMIT) {
554086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, HASH_UPDATE_LIMIT);
555086e8fa8SLin Jinhan 		if (ret)
556086e8fa8SLin Jinhan 			goto exit;
557086e8fa8SLin Jinhan 	}
558086e8fa8SLin Jinhan 
559086e8fa8SLin Jinhan 	if (len % HASH_UPDATE_LIMIT)
560086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, len % HASH_UPDATE_LIMIT);
561086e8fa8SLin Jinhan 
562086e8fa8SLin Jinhan exit:
563086e8fa8SLin Jinhan 	return ret;
564b353a43cSLin Jinhan }
565b353a43cSLin Jinhan 
566b353a43cSLin Jinhan static int rockchip_crypto_sha_final(struct udevice *dev,
567b353a43cSLin Jinhan 				     sha_context *ctx, u8 *output)
568b353a43cSLin Jinhan {
569b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
570b353a43cSLin Jinhan 	u32 nbits;
571c48f1acfSLin Jinhan 	int ret;
572b353a43cSLin Jinhan 
573b353a43cSLin Jinhan 	nbits = crypto_algo_nbits(ctx->algo);
574b353a43cSLin Jinhan 
575c48f1acfSLin Jinhan 	if (priv->length != ctx->length) {
576c48f1acfSLin Jinhan 		printf("total length(0x%08x) != init length(0x%08x)!\n",
577c48f1acfSLin Jinhan 		       priv->length, ctx->length);
578c48f1acfSLin Jinhan 		ret = -EIO;
579c48f1acfSLin Jinhan 		goto exit;
580c48f1acfSLin Jinhan 	}
581c48f1acfSLin Jinhan 
582c48f1acfSLin Jinhan 	ret = rk_hash_final(priv->hw_ctx, (u8 *)output, BITS2BYTE(nbits));
583c48f1acfSLin Jinhan 
584c48f1acfSLin Jinhan exit:
585c48f1acfSLin Jinhan 	hw_hash_clean_ctx(priv->hw_ctx);
586c48f1acfSLin Jinhan 	return ret;
587b353a43cSLin Jinhan }
588b353a43cSLin Jinhan 
58949a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
59049a2135eSLin Jinhan int rk_hmac_init(void *hw_ctx, u32 algo, u8 *key, u32 key_len)
59149a2135eSLin Jinhan {
59249a2135eSLin Jinhan 	u32 reg_ctrl = 0;
59349a2135eSLin Jinhan 	int ret;
59449a2135eSLin Jinhan 
59549a2135eSLin Jinhan 	if (!key || !key_len || key_len > 64)
59649a2135eSLin Jinhan 		return -EINVAL;
59749a2135eSLin Jinhan 
59849a2135eSLin Jinhan 	clear_key_regs();
59949a2135eSLin Jinhan 
60049a2135eSLin Jinhan 	write_key_reg(0, key, key_len);
60149a2135eSLin Jinhan 
60249a2135eSLin Jinhan 	ret = rk_hash_init(hw_ctx, algo);
60349a2135eSLin Jinhan 	if (ret)
60449a2135eSLin Jinhan 		return ret;
60549a2135eSLin Jinhan 
60649a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_HASH_CTL) | CRYPTO_HMAC_ENABLE;
60749a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
60849a2135eSLin Jinhan 
60949a2135eSLin Jinhan 	return ret;
61049a2135eSLin Jinhan }
61149a2135eSLin Jinhan 
61249a2135eSLin Jinhan static int rockchip_crypto_hmac_init(struct udevice *dev,
61349a2135eSLin Jinhan 				     sha_context *ctx, u8 *key, u32 key_len)
61449a2135eSLin Jinhan {
61549a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
61649a2135eSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
61749a2135eSLin Jinhan 
61849a2135eSLin Jinhan 	if (!ctx)
61949a2135eSLin Jinhan 		return -EINVAL;
62049a2135eSLin Jinhan 
62149a2135eSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
62249a2135eSLin Jinhan 
62349a2135eSLin Jinhan 	priv->length = 0;
62449a2135eSLin Jinhan 
62549a2135eSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
62649a2135eSLin Jinhan 						       priv, ctx->length,
62749a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
62849a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
62949a2135eSLin Jinhan 	if (!hash_ctx->hash_cache)
63049a2135eSLin Jinhan 		return -EFAULT;
63149a2135eSLin Jinhan 
63249a2135eSLin Jinhan 	return rk_hmac_init(priv->hw_ctx, ctx->algo, key, key_len);
63349a2135eSLin Jinhan }
63449a2135eSLin Jinhan 
63549a2135eSLin Jinhan static int rockchip_crypto_hmac_update(struct udevice *dev,
63649a2135eSLin Jinhan 				       u32 *input, u32 len)
63749a2135eSLin Jinhan {
63849a2135eSLin Jinhan 	return rockchip_crypto_sha_update(dev, input, len);
63949a2135eSLin Jinhan }
64049a2135eSLin Jinhan 
64149a2135eSLin Jinhan static int rockchip_crypto_hmac_final(struct udevice *dev,
64249a2135eSLin Jinhan 				      sha_context *ctx, u8 *output)
64349a2135eSLin Jinhan {
64449a2135eSLin Jinhan 	return rockchip_crypto_sha_final(dev, ctx, output);
64549a2135eSLin Jinhan }
64649a2135eSLin Jinhan 
64749a2135eSLin Jinhan #endif
64849a2135eSLin Jinhan 
64949a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
65049a2135eSLin Jinhan static u8 g_key_chn;
65149a2135eSLin Jinhan 
65249a2135eSLin Jinhan static const u32 rk_mode2bc_mode[RK_MODE_MAX] = {
65349a2135eSLin Jinhan 	[RK_MODE_ECB] = CRYPTO_BC_ECB,
65449a2135eSLin Jinhan 	[RK_MODE_CBC] = CRYPTO_BC_CBC,
65549a2135eSLin Jinhan 	[RK_MODE_CTS] = CRYPTO_BC_CTS,
65649a2135eSLin Jinhan 	[RK_MODE_CTR] = CRYPTO_BC_CTR,
65749a2135eSLin Jinhan 	[RK_MODE_CFB] = CRYPTO_BC_CFB,
65849a2135eSLin Jinhan 	[RK_MODE_OFB] = CRYPTO_BC_OFB,
65949a2135eSLin Jinhan 	[RK_MODE_XTS] = CRYPTO_BC_XTS,
660c3ce9937SLin Jinhan 	[RK_MODE_CCM] = CRYPTO_BC_CCM,
661c3ce9937SLin Jinhan 	[RK_MODE_GCM] = CRYPTO_BC_GCM,
662d9332f1cSLin Jinhan 	[RK_MODE_CMAC] = CRYPTO_BC_CMAC,
663d9332f1cSLin Jinhan 	[RK_MODE_CBC_MAC] = CRYPTO_BC_CBC_MAC,
66449a2135eSLin Jinhan };
66549a2135eSLin Jinhan 
666c3ce9937SLin Jinhan static inline void set_pc_len_reg(u32 chn, u64 pc_len)
667c3ce9937SLin Jinhan {
668c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_PC_LEN_0 + chn * 0x08;
669c3ce9937SLin Jinhan 
670c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
671c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
672c3ce9937SLin Jinhan }
673c3ce9937SLin Jinhan 
674c3ce9937SLin Jinhan static inline void set_aad_len_reg(u32 chn, u64 pc_len)
675c3ce9937SLin Jinhan {
676c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_AAD_LEN_0 + chn * 0x08;
677c3ce9937SLin Jinhan 
678c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
679c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
680c3ce9937SLin Jinhan }
681c3ce9937SLin Jinhan 
68249a2135eSLin Jinhan static inline bool is_des_mode(u32 rk_mode)
68349a2135eSLin Jinhan {
68449a2135eSLin Jinhan 	return (rk_mode == RK_MODE_ECB ||
68549a2135eSLin Jinhan 		rk_mode == RK_MODE_CBC ||
68649a2135eSLin Jinhan 		rk_mode == RK_MODE_CFB ||
68749a2135eSLin Jinhan 		rk_mode == RK_MODE_OFB);
68849a2135eSLin Jinhan }
68949a2135eSLin Jinhan 
6906b53126aSLin Jinhan static void dump_crypto_state(struct crypto_lli_desc *desc,
6916b53126aSLin Jinhan 			      u32 tmp, u32 expt_int,
6926b53126aSLin Jinhan 			      const u8 *in, const u8 *out,
6936b53126aSLin Jinhan 			      u32 len, int ret)
69449a2135eSLin Jinhan {
69549a2135eSLin Jinhan 	IMSG("%s\n", ret == -ETIME ? "timeout" : "dismatch");
69649a2135eSLin Jinhan 
69749a2135eSLin Jinhan 	IMSG("CRYPTO_DMA_INT_ST = %08x, expect_int = %08x\n",
69849a2135eSLin Jinhan 	     tmp, expt_int);
69949a2135eSLin Jinhan 	IMSG("data desc		= %p\n", desc);
70049a2135eSLin Jinhan 	IMSG("\taddr_in		= [%08x <=> %08x]\n",
70149a2135eSLin Jinhan 	     desc->src_addr, (u32)virt_to_phys(in));
70249a2135eSLin Jinhan 	IMSG("\taddr_out	= [%08x <=> %08x]\n",
70349a2135eSLin Jinhan 	     desc->dst_addr, (u32)virt_to_phys(out));
70449a2135eSLin Jinhan 	IMSG("\tsrc_len		= [%08x <=> %08x]\n",
70549a2135eSLin Jinhan 	     desc->src_len, (u32)len);
70649a2135eSLin Jinhan 	IMSG("\tdst_len		= %08x\n", desc->dst_len);
70749a2135eSLin Jinhan 	IMSG("\tdma_ctl		= %08x\n", desc->dma_ctrl);
70849a2135eSLin Jinhan 	IMSG("\tuser_define	= %08x\n", desc->user_define);
70949a2135eSLin Jinhan 
71049a2135eSLin Jinhan 	IMSG("\n\nDMA CRYPTO_DMA_LLI_ADDR status = %08x\n",
71149a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_ADDR));
71249a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_ST status = %08x\n",
71349a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_ST));
71449a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_STATE status = %08x\n",
71549a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_STATE));
71649a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_LLI_RADDR status = %08x\n",
71749a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_RADDR));
71849a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_SRC_RADDR status = %08x\n",
71949a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_SRC_RADDR));
72049a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_DST_RADDR status = %08x\n",
72149a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
72249a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_ST status = %08x\n",
72349a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_ST));
72449a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_STATE status = %08x\n",
72549a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_STATE));
72649a2135eSLin Jinhan 	IMSG("DMA CRYPTO_TAG_VALID status = %08x\n",
72749a2135eSLin Jinhan 	     crypto_read(CRYPTO_TAG_VALID));
72849a2135eSLin Jinhan 	IMSG("LOCKSTEP status = %08x\n\n",
72949a2135eSLin Jinhan 	     crypto_read(0x618));
73049a2135eSLin Jinhan 
73149a2135eSLin Jinhan 	IMSG("dst %dbyte not transferred\n",
73249a2135eSLin Jinhan 	     desc->dst_addr + desc->dst_len -
73349a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
73449a2135eSLin Jinhan }
73549a2135eSLin Jinhan 
736c3ce9937SLin Jinhan static int ccm128_set_iv_reg(u32 chn, const u8 *nonce, u32 nlen)
737c3ce9937SLin Jinhan {
738c3ce9937SLin Jinhan 	u8 iv_buf[AES_BLOCK_SIZE];
739c3ce9937SLin Jinhan 	u32 L;
740c3ce9937SLin Jinhan 
741c3ce9937SLin Jinhan 	memset(iv_buf, 0x00, sizeof(iv_buf));
742c3ce9937SLin Jinhan 
743c3ce9937SLin Jinhan 	L = 15 - nlen;
744c3ce9937SLin Jinhan 	iv_buf[0] = ((u8)(L - 1) & 7);
745c3ce9937SLin Jinhan 
746c3ce9937SLin Jinhan 	/* the L parameter */
747c3ce9937SLin Jinhan 	L = iv_buf[0] & 7;
748c3ce9937SLin Jinhan 
749c3ce9937SLin Jinhan 	/* nonce is too short */
750c3ce9937SLin Jinhan 	if (nlen < (14 - L))
751c3ce9937SLin Jinhan 		return -EINVAL;
752c3ce9937SLin Jinhan 
753c3ce9937SLin Jinhan 	/* clear aad flag */
754c3ce9937SLin Jinhan 	iv_buf[0] &= ~0x40;
755c3ce9937SLin Jinhan 	memcpy(&iv_buf[1], nonce, 14 - L);
756c3ce9937SLin Jinhan 
757c3ce9937SLin Jinhan 	set_iv_reg(chn, iv_buf, AES_BLOCK_SIZE);
758c3ce9937SLin Jinhan 
759c3ce9937SLin Jinhan 	return 0;
760c3ce9937SLin Jinhan }
761c3ce9937SLin Jinhan 
762c3ce9937SLin Jinhan static void ccm_aad_padding(u32 aad_len, u8 *padding, u32 *padding_size)
763c3ce9937SLin Jinhan {
764c3ce9937SLin Jinhan 	u32 i;
765c3ce9937SLin Jinhan 
766c3ce9937SLin Jinhan 	i = aad_len < (0x10000 - 0x100) ? 2 : 6;
767c3ce9937SLin Jinhan 
768c3ce9937SLin Jinhan 	if (i == 2) {
769c3ce9937SLin Jinhan 		padding[0] = (u8)(aad_len >> 8);
770c3ce9937SLin Jinhan 		padding[1] = (u8)aad_len;
771c3ce9937SLin Jinhan 	} else {
772c3ce9937SLin Jinhan 		padding[0] = 0xFF;
773c3ce9937SLin Jinhan 		padding[1] = 0xFE;
774c3ce9937SLin Jinhan 		padding[2] = (u8)(aad_len >> 24);
775c3ce9937SLin Jinhan 		padding[3] = (u8)(aad_len >> 16);
776c3ce9937SLin Jinhan 		padding[4] = (u8)(aad_len >> 8);
777c3ce9937SLin Jinhan 	}
778c3ce9937SLin Jinhan 
779c3ce9937SLin Jinhan 	*padding_size = i;
780c3ce9937SLin Jinhan }
781c3ce9937SLin Jinhan 
782c3ce9937SLin Jinhan static int ccm_compose_aad_iv(u8 *aad_iv, u32 data_len, u32 tag_size)
783c3ce9937SLin Jinhan {
784c3ce9937SLin Jinhan 	aad_iv[0] |= ((u8)(((tag_size - 2) / 2) & 7) << 3);
785c3ce9937SLin Jinhan 
786c3ce9937SLin Jinhan 	aad_iv[12] = (u8)(data_len >> 24);
787c3ce9937SLin Jinhan 	aad_iv[13] = (u8)(data_len >> 16);
788c3ce9937SLin Jinhan 	aad_iv[14] = (u8)(data_len >> 8);
789c3ce9937SLin Jinhan 	aad_iv[15] = (u8)data_len;
790c3ce9937SLin Jinhan 
791c3ce9937SLin Jinhan 	aad_iv[0] |= 0x40;	//set aad flag
792c3ce9937SLin Jinhan 
793c3ce9937SLin Jinhan 	return 0;
794c3ce9937SLin Jinhan }
795c3ce9937SLin Jinhan 
79649a2135eSLin Jinhan static int hw_cipher_init(u32 chn, const u8 *key, const u8 *twk_key,
79749a2135eSLin Jinhan 			  u32 key_len, const u8 *iv, u32 iv_len,
79849a2135eSLin Jinhan 			  u32 algo, u32 mode, bool enc)
79949a2135eSLin Jinhan {
80049a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
80149a2135eSLin Jinhan 	u32 key_chn_sel = chn;
80249a2135eSLin Jinhan 	u32 reg_ctrl = 0;
80349a2135eSLin Jinhan 
80449a2135eSLin Jinhan 	IMSG("%s: key addr is %p, key_len is %d, iv addr is %p",
80549a2135eSLin Jinhan 	     __func__, key, key_len, iv);
80649a2135eSLin Jinhan 	if (rk_mode >= RK_MODE_MAX)
80749a2135eSLin Jinhan 		return -EINVAL;
80849a2135eSLin Jinhan 
80949a2135eSLin Jinhan 	switch (algo) {
81049a2135eSLin Jinhan 	case CRYPTO_DES:
81149a2135eSLin Jinhan 		if (key_len > DES_BLOCK_SIZE)
81249a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_TDES;
81349a2135eSLin Jinhan 		else
81449a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_DES;
81549a2135eSLin Jinhan 		break;
81649a2135eSLin Jinhan 	case CRYPTO_AES:
81749a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_AES;
81849a2135eSLin Jinhan 		break;
81949a2135eSLin Jinhan 	case CRYPTO_SM4:
82049a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_SM4;
82149a2135eSLin Jinhan 		break;
82249a2135eSLin Jinhan 	default:
82349a2135eSLin Jinhan 		return -EINVAL;
82449a2135eSLin Jinhan 	}
82549a2135eSLin Jinhan 
82649a2135eSLin Jinhan 	if (algo == CRYPTO_AES || algo == CRYPTO_SM4) {
82749a2135eSLin Jinhan 		switch (key_len) {
82849a2135eSLin Jinhan 		case AES_KEYSIZE_128:
82949a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_128_bit_key;
83049a2135eSLin Jinhan 			break;
83149a2135eSLin Jinhan 		case AES_KEYSIZE_192:
83249a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_192_bit_key;
83349a2135eSLin Jinhan 			break;
83449a2135eSLin Jinhan 		case AES_KEYSIZE_256:
83549a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_256_bit_key;
83649a2135eSLin Jinhan 			break;
83749a2135eSLin Jinhan 		default:
83849a2135eSLin Jinhan 			return -EINVAL;
83949a2135eSLin Jinhan 		}
84049a2135eSLin Jinhan 	}
84149a2135eSLin Jinhan 
84249a2135eSLin Jinhan 	reg_ctrl |= rk_mode2bc_mode[rk_mode];
84349a2135eSLin Jinhan 	if (!enc)
84449a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_DECRYPT;
84549a2135eSLin Jinhan 
84649a2135eSLin Jinhan 	/* write key data to reg */
84749a2135eSLin Jinhan 	write_key_reg(key_chn_sel, key, key_len);
84849a2135eSLin Jinhan 
84949a2135eSLin Jinhan 	/* write twk key for xts mode */
85049a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS)
85149a2135eSLin Jinhan 		write_key_reg(key_chn_sel + 4, twk_key, key_len);
85249a2135eSLin Jinhan 
85349a2135eSLin Jinhan 	/* set iv reg */
854c3ce9937SLin Jinhan 	if (rk_mode == RK_MODE_CCM)
855c3ce9937SLin Jinhan 		ccm128_set_iv_reg(chn, iv, iv_len);
856c3ce9937SLin Jinhan 	else
85749a2135eSLin Jinhan 		set_iv_reg(chn, iv, iv_len);
85849a2135eSLin Jinhan 
85949a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
86049a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
861fe0c4b19SLin Jinhan 	crypto_write(0, CRYPTO_DMA_INT_EN);
86249a2135eSLin Jinhan 
86349a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
86449a2135eSLin Jinhan 
86549a2135eSLin Jinhan 	return 0;
86649a2135eSLin Jinhan }
86749a2135eSLin Jinhan 
86849a2135eSLin Jinhan static int hw_cipher_crypt(const u8 *in, u8 *out, u64 len,
869c3ce9937SLin Jinhan 			   const u8 *aad, u32 aad_len,
870c3ce9937SLin Jinhan 			   u8 *tag, u32 tag_len, u32 mode)
87149a2135eSLin Jinhan {
872c3ce9937SLin Jinhan 	struct crypto_lli_desc *data_desc = NULL, *aad_desc = NULL;
873c3ce9937SLin Jinhan 	u8 *dma_in = NULL, *dma_out = NULL, *aad_tmp = NULL;
87449a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
87549a2135eSLin Jinhan 	u32 reg_ctrl = 0, tmp_len = 0;
87649a2135eSLin Jinhan 	u32 expt_int = 0, mask = 0;
87749a2135eSLin Jinhan 	u32 key_chn = g_key_chn;
87849a2135eSLin Jinhan 	u32 tmp, dst_len = 0;
87949a2135eSLin Jinhan 	int ret = -1;
88049a2135eSLin Jinhan 
88149a2135eSLin Jinhan 	if (rk_mode == RK_MODE_CTS && len <= AES_BLOCK_SIZE) {
88249a2135eSLin Jinhan 		printf("CTS mode length %u < 16Byte\n", (u32)len);
88349a2135eSLin Jinhan 		return -EINVAL;
88449a2135eSLin Jinhan 	}
88549a2135eSLin Jinhan 
88649a2135eSLin Jinhan 	tmp_len = (rk_mode == RK_MODE_CTR) ? ROUNDUP(len, AES_BLOCK_SIZE) : len;
88749a2135eSLin Jinhan 
88849a2135eSLin Jinhan 	data_desc = align_malloc(sizeof(*data_desc), LLI_ADDR_ALIGN_SIZE);
88949a2135eSLin Jinhan 	if (!data_desc)
89049a2135eSLin Jinhan 		goto exit;
89149a2135eSLin Jinhan 
89249a2135eSLin Jinhan 	if (IS_ALIGNED((ulong)in, DATA_ADDR_ALIGN_SIZE) && tmp_len == len)
89349a2135eSLin Jinhan 		dma_in = (void *)in;
89449a2135eSLin Jinhan 	else
89549a2135eSLin Jinhan 		dma_in = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
89649a2135eSLin Jinhan 	if (!dma_in)
89749a2135eSLin Jinhan 		goto exit;
89849a2135eSLin Jinhan 
89949a2135eSLin Jinhan 	if (out) {
90049a2135eSLin Jinhan 		if (IS_ALIGNED((ulong)out, DATA_ADDR_ALIGN_SIZE) &&
90149a2135eSLin Jinhan 		    tmp_len == len)
90249a2135eSLin Jinhan 			dma_out = out;
90349a2135eSLin Jinhan 		else
90449a2135eSLin Jinhan 			dma_out = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
90549a2135eSLin Jinhan 		if (!dma_out)
90649a2135eSLin Jinhan 			goto exit;
90749a2135eSLin Jinhan 		dst_len = tmp_len;
90849a2135eSLin Jinhan 	}
90949a2135eSLin Jinhan 
91049a2135eSLin Jinhan 	memset(data_desc, 0x00, sizeof(*data_desc));
91149a2135eSLin Jinhan 	if (dma_in != in)
91249a2135eSLin Jinhan 		memcpy(dma_in, in, len);
91349a2135eSLin Jinhan 
91449a2135eSLin Jinhan 	data_desc->src_addr    = (u32)virt_to_phys(dma_in);
91549a2135eSLin Jinhan 	data_desc->src_len     = tmp_len;
91649a2135eSLin Jinhan 	data_desc->dst_addr    = (u32)virt_to_phys(dma_out);
91749a2135eSLin Jinhan 	data_desc->dst_len     = dst_len;
918d9332f1cSLin Jinhan 	data_desc->dma_ctrl    = LLI_DMA_CTRL_LAST;
919d9332f1cSLin Jinhan 
920d9332f1cSLin Jinhan 	if (IS_MAC_MODE(rk_mode)) {
921d9332f1cSLin Jinhan 		expt_int = CRYPTO_LIST_DONE_INT_ST;
922d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_LIST_DONE;
923d9332f1cSLin Jinhan 	} else {
92449a2135eSLin Jinhan 		expt_int = CRYPTO_DST_ITEM_DONE_INT_ST;
925d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_DST_DONE;
926d9332f1cSLin Jinhan 	}
92749a2135eSLin Jinhan 
928c3ce9937SLin Jinhan 	if (rk_mode == RK_MODE_CCM || rk_mode == RK_MODE_GCM) {
929c3ce9937SLin Jinhan 		u32 aad_tmp_len = 0;
930c3ce9937SLin Jinhan 
931c3ce9937SLin Jinhan 		data_desc->user_define = LLI_USER_STRING_START |
932c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
933c3ce9937SLin Jinhan 					 (key_chn << 4);
934c3ce9937SLin Jinhan 
935c3ce9937SLin Jinhan 		aad_desc = align_malloc(sizeof(*aad_desc), LLI_ADDR_ALIGN_SIZE);
936c3ce9937SLin Jinhan 		if (!aad_desc)
937c3ce9937SLin Jinhan 			goto exit;
938c3ce9937SLin Jinhan 
939c3ce9937SLin Jinhan 		memset(aad_desc, 0x00, sizeof(*aad_desc));
940c3ce9937SLin Jinhan 		aad_desc->next_addr = (u32)virt_to_phys(data_desc);
941c3ce9937SLin Jinhan 		aad_desc->user_define = LLI_USER_CPIHER_START |
942c3ce9937SLin Jinhan 					 LLI_USER_STRING_START |
943c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
944c3ce9937SLin Jinhan 					 LLI_USER_STRING_AAD |
945c3ce9937SLin Jinhan 					 (key_chn << 4);
946c3ce9937SLin Jinhan 
947c3ce9937SLin Jinhan 		if (rk_mode == RK_MODE_CCM) {
948c3ce9937SLin Jinhan 			u8 padding[AES_BLOCK_SIZE];
949c3ce9937SLin Jinhan 			u32 padding_size = 0;
950c3ce9937SLin Jinhan 
951c3ce9937SLin Jinhan 			memset(padding, 0x00, sizeof(padding));
952c3ce9937SLin Jinhan 			ccm_aad_padding(aad_len, padding, &padding_size);
953c3ce9937SLin Jinhan 
954c3ce9937SLin Jinhan 			aad_tmp_len = aad_len + AES_BLOCK_SIZE + padding_size;
955c3ce9937SLin Jinhan 			aad_tmp_len = ROUNDUP(aad_tmp_len, AES_BLOCK_SIZE);
956c3ce9937SLin Jinhan 			aad_tmp = align_malloc(aad_tmp_len,
957c3ce9937SLin Jinhan 					       DATA_ADDR_ALIGN_SIZE);
958c3ce9937SLin Jinhan 			if (!aad_tmp)
959c3ce9937SLin Jinhan 				goto exit;
960c3ce9937SLin Jinhan 
961c3ce9937SLin Jinhan 			/* read iv data from reg */
962c3ce9937SLin Jinhan 			get_iv_reg(key_chn, aad_tmp, AES_BLOCK_SIZE);
963c3ce9937SLin Jinhan 			ccm_compose_aad_iv(aad_tmp, tmp_len, tag_len);
964c3ce9937SLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE, padding, padding_size);
965c3ce9937SLin Jinhan 			memset(aad_tmp + aad_tmp_len - AES_BLOCK_SIZE,
966c3ce9937SLin Jinhan 			       0x00, AES_BLOCK_SIZE);
967c3ce9937SLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE + padding_size,
968c3ce9937SLin Jinhan 			       aad, aad_len);
969c3ce9937SLin Jinhan 		} else {
970c3ce9937SLin Jinhan 			aad_tmp_len = aad_len;
971b83c40a4SLin Jinhan 			if (IS_ALIGNED((ulong)aad, DATA_ADDR_ALIGN_SIZE)) {
972b83c40a4SLin Jinhan 				aad_tmp = (void *)aad;
973b83c40a4SLin Jinhan 			} else {
974c3ce9937SLin Jinhan 				aad_tmp = align_malloc(aad_tmp_len,
975c3ce9937SLin Jinhan 						       DATA_ADDR_ALIGN_SIZE);
976c3ce9937SLin Jinhan 				if (!aad_tmp)
977c3ce9937SLin Jinhan 					goto exit;
978c3ce9937SLin Jinhan 
979c3ce9937SLin Jinhan 				memcpy(aad_tmp, aad, aad_tmp_len);
980b83c40a4SLin Jinhan 			}
981b83c40a4SLin Jinhan 
982c3ce9937SLin Jinhan 			set_aad_len_reg(key_chn, aad_tmp_len);
983c3ce9937SLin Jinhan 			set_pc_len_reg(key_chn, tmp_len);
984c3ce9937SLin Jinhan 		}
985c3ce9937SLin Jinhan 
986c3ce9937SLin Jinhan 		aad_desc->src_addr = (u32)virt_to_phys(aad_tmp);
987c3ce9937SLin Jinhan 		aad_desc->src_len  = aad_tmp_len;
988c3ce9937SLin Jinhan 		crypto_write((u32)virt_to_phys(aad_desc), CRYPTO_DMA_LLI_ADDR);
989c3ce9937SLin Jinhan 		cache_op_inner(DCACHE_AREA_CLEAN, aad_tmp, aad_tmp_len);
990c3ce9937SLin Jinhan 		cache_op_inner(DCACHE_AREA_CLEAN, aad_desc, sizeof(*aad_desc));
991c3ce9937SLin Jinhan 	} else {
992c3ce9937SLin Jinhan 		data_desc->user_define = LLI_USER_CPIHER_START |
993c3ce9937SLin Jinhan 					 LLI_USER_STRING_START |
994c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
995c3ce9937SLin Jinhan 					 (key_chn << 4);
99649a2135eSLin Jinhan 		crypto_write((u32)virt_to_phys(data_desc), CRYPTO_DMA_LLI_ADDR);
997c3ce9937SLin Jinhan 	}
99849a2135eSLin Jinhan 
99949a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, data_desc, sizeof(*data_desc));
100049a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, dma_in, tmp_len);
100149a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_INVALIDATE, dma_out, tmp_len);
100249a2135eSLin Jinhan 
100349a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
100449a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
1005fe0c4b19SLin Jinhan 	crypto_write(0, CRYPTO_DMA_INT_EN);
100649a2135eSLin Jinhan 
100749a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_BC_CTL) | CRYPTO_BC_ENABLE;
100849a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
100949a2135eSLin Jinhan 	crypto_write(0x00010001, CRYPTO_DMA_CTL);//start
101049a2135eSLin Jinhan 
101149a2135eSLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
101249a2135eSLin Jinhan 
101349a2135eSLin Jinhan 	/* wait calc ok */
101449a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
101549a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
101649a2135eSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
101749a2135eSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
101849a2135eSLin Jinhan 
101949a2135eSLin Jinhan 	if ((tmp & mask) == expt_int) {
102049a2135eSLin Jinhan 		if (out && out != dma_out)
102149a2135eSLin Jinhan 			memcpy(out, dma_out, len);
1022d9332f1cSLin Jinhan 
1023d9332f1cSLin Jinhan 		if (IS_NEED_TAG(rk_mode)) {
1024d9332f1cSLin Jinhan 			ret = WAIT_TAG_VALID(key_chn, RK_CRYPTO_TIMEOUT);
1025d9332f1cSLin Jinhan 			get_tag_from_reg(key_chn, tag, AES_BLOCK_SIZE);
1026d9332f1cSLin Jinhan 		}
102749a2135eSLin Jinhan 	} else {
10286b53126aSLin Jinhan 		dump_crypto_state(data_desc, tmp, expt_int, in, out, len, ret);
102949a2135eSLin Jinhan 		ret = -1;
103049a2135eSLin Jinhan 	}
103149a2135eSLin Jinhan 
103249a2135eSLin Jinhan exit:
103349a2135eSLin Jinhan 	crypto_write(0xffff0000, CRYPTO_BC_CTL);//bc_ctl disable
103449a2135eSLin Jinhan 	align_free(data_desc);
1035c3ce9937SLin Jinhan 	align_free(aad_desc);
1036b83c40a4SLin Jinhan 	if (dma_in != in)
103749a2135eSLin Jinhan 		align_free(dma_in);
1038b83c40a4SLin Jinhan 	if (out && dma_out != out)
103949a2135eSLin Jinhan 		align_free(dma_out);
1040b83c40a4SLin Jinhan 	if (aad && aad != aad_tmp)
1041b83c40a4SLin Jinhan 		align_free(aad_tmp);
104249a2135eSLin Jinhan 
104349a2135eSLin Jinhan 	return ret;
104449a2135eSLin Jinhan }
104549a2135eSLin Jinhan 
104649a2135eSLin Jinhan static int hw_aes_init(u32 chn, const u8 *key, const u8 *twk_key, u32 key_len,
104749a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
104849a2135eSLin Jinhan {
104949a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
105049a2135eSLin Jinhan 
1051d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
1052d9332f1cSLin Jinhan 		return -EINVAL;
1053d9332f1cSLin Jinhan 
105449a2135eSLin Jinhan 	if (iv_len > AES_BLOCK_SIZE)
105549a2135eSLin Jinhan 		return -EINVAL;
105649a2135eSLin Jinhan 
1057d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
105849a2135eSLin Jinhan 		if (!iv || iv_len != AES_BLOCK_SIZE)
105949a2135eSLin Jinhan 			return -EINVAL;
106049a2135eSLin Jinhan 	} else {
106149a2135eSLin Jinhan 		iv_len = 0;
106249a2135eSLin Jinhan 	}
106349a2135eSLin Jinhan 
106449a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
106549a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_256)
106649a2135eSLin Jinhan 			return -EINVAL;
106749a2135eSLin Jinhan 
106849a2135eSLin Jinhan 		if (!key || !twk_key)
106949a2135eSLin Jinhan 			return -EINVAL;
107049a2135eSLin Jinhan 	} else {
107149a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 &&
107249a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_192 &&
107349a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_256)
107449a2135eSLin Jinhan 			return -EINVAL;
107549a2135eSLin Jinhan 	}
107649a2135eSLin Jinhan 
107749a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
107849a2135eSLin Jinhan 			      CRYPTO_AES, mode, enc);
107949a2135eSLin Jinhan }
108049a2135eSLin Jinhan 
108149a2135eSLin Jinhan static int hw_sm4_init(u32  chn, const u8 *key, const u8 *twk_key, u32 key_len,
108249a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
108349a2135eSLin Jinhan {
108449a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
108549a2135eSLin Jinhan 
1086d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
1087d9332f1cSLin Jinhan 		return -EINVAL;
1088d9332f1cSLin Jinhan 
108949a2135eSLin Jinhan 	if (iv_len > SM4_BLOCK_SIZE || key_len != SM4_KEYSIZE)
109049a2135eSLin Jinhan 		return -EINVAL;
109149a2135eSLin Jinhan 
1092d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
109349a2135eSLin Jinhan 		if (!iv || iv_len != SM4_BLOCK_SIZE)
109449a2135eSLin Jinhan 			return -EINVAL;
109549a2135eSLin Jinhan 	} else {
109649a2135eSLin Jinhan 		iv_len = 0;
109749a2135eSLin Jinhan 	}
109849a2135eSLin Jinhan 
109949a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
110049a2135eSLin Jinhan 		if (!key || !twk_key)
110149a2135eSLin Jinhan 			return -EINVAL;
110249a2135eSLin Jinhan 	}
110349a2135eSLin Jinhan 
110449a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
110549a2135eSLin Jinhan 			      CRYPTO_SM4, mode, enc);
110649a2135eSLin Jinhan }
110749a2135eSLin Jinhan 
110849a2135eSLin Jinhan int rk_crypto_des(struct udevice *dev, u32 mode, const u8 *key, u32 key_len,
110949a2135eSLin Jinhan 		  const u8 *iv, const u8 *in, u8 *out, u32 len, bool enc)
111049a2135eSLin Jinhan {
111149a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
111249a2135eSLin Jinhan 	u8 tmp_key[24];
111349a2135eSLin Jinhan 	int ret;
111449a2135eSLin Jinhan 
111549a2135eSLin Jinhan 	if (!is_des_mode(rk_mode))
111649a2135eSLin Jinhan 		return -EINVAL;
111749a2135eSLin Jinhan 
111849a2135eSLin Jinhan 	if (key_len == DES_BLOCK_SIZE || key_len == 3 * DES_BLOCK_SIZE) {
111949a2135eSLin Jinhan 		memcpy(tmp_key, key, key_len);
112049a2135eSLin Jinhan 	} else if (key_len == 2 * DES_BLOCK_SIZE) {
112149a2135eSLin Jinhan 		memcpy(tmp_key, key, 16);
112249a2135eSLin Jinhan 		memcpy(tmp_key + 16, key, 8);
112349a2135eSLin Jinhan 		key_len = 3 * DES_BLOCK_SIZE;
112449a2135eSLin Jinhan 	} else {
112549a2135eSLin Jinhan 		return -EINVAL;
112649a2135eSLin Jinhan 	}
112749a2135eSLin Jinhan 
112849a2135eSLin Jinhan 	ret = hw_cipher_init(0, tmp_key, NULL, key_len, iv, DES_BLOCK_SIZE,
112949a2135eSLin Jinhan 			     CRYPTO_DES, mode, enc);
113049a2135eSLin Jinhan 	if (ret)
113149a2135eSLin Jinhan 		goto exit;
113249a2135eSLin Jinhan 
113349a2135eSLin Jinhan 	ret = hw_cipher_crypt(in, out, len, NULL, 0,
113449a2135eSLin Jinhan 			      NULL, 0, mode);
113549a2135eSLin Jinhan 
113649a2135eSLin Jinhan exit:
113749a2135eSLin Jinhan 	return ret;
113849a2135eSLin Jinhan }
113949a2135eSLin Jinhan 
114049a2135eSLin Jinhan int rk_crypto_aes(struct udevice *dev, u32 mode,
114149a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
114249a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
114349a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
114449a2135eSLin Jinhan {
114549a2135eSLin Jinhan 	int ret;
114649a2135eSLin Jinhan 
114749a2135eSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
114849a2135eSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
114949a2135eSLin Jinhan 	if (key_len == AES_KEYSIZE_192)
115049a2135eSLin Jinhan 		return -EINVAL;
115149a2135eSLin Jinhan #endif
115249a2135eSLin Jinhan 
115349a2135eSLin Jinhan 	ret = hw_aes_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
115449a2135eSLin Jinhan 	if (ret)
115549a2135eSLin Jinhan 		return ret;
115649a2135eSLin Jinhan 
115749a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0,
115849a2135eSLin Jinhan 			       NULL, 0, mode);
115949a2135eSLin Jinhan }
116049a2135eSLin Jinhan 
116149a2135eSLin Jinhan int rk_crypto_sm4(struct udevice *dev, u32 mode,
116249a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
116349a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
116449a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
116549a2135eSLin Jinhan {
116649a2135eSLin Jinhan 	int ret;
116749a2135eSLin Jinhan 
116849a2135eSLin Jinhan 	ret = hw_sm4_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
116949a2135eSLin Jinhan 	if (ret)
117049a2135eSLin Jinhan 		return ret;
117149a2135eSLin Jinhan 
117249a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0, NULL, 0, mode);
117349a2135eSLin Jinhan }
117449a2135eSLin Jinhan 
117549a2135eSLin Jinhan int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx,
117649a2135eSLin Jinhan 			   const u8 *in, u8 *out, u32 len, bool enc)
117749a2135eSLin Jinhan {
117849a2135eSLin Jinhan 	switch (ctx->algo) {
117949a2135eSLin Jinhan 	case CRYPTO_DES:
118049a2135eSLin Jinhan 		return rk_crypto_des(dev, ctx->mode, ctx->key, ctx->key_len,
118149a2135eSLin Jinhan 				     ctx->iv, in, out, len, enc);
118249a2135eSLin Jinhan 	case CRYPTO_AES:
118349a2135eSLin Jinhan 		return rk_crypto_aes(dev, ctx->mode,
118449a2135eSLin Jinhan 				     ctx->key, ctx->twk_key, ctx->key_len,
118549a2135eSLin Jinhan 				     ctx->iv, ctx->iv_len, in, out, len, enc);
118649a2135eSLin Jinhan 	case CRYPTO_SM4:
118749a2135eSLin Jinhan 		return rk_crypto_sm4(dev, ctx->mode,
118849a2135eSLin Jinhan 				     ctx->key, ctx->twk_key, ctx->key_len,
118949a2135eSLin Jinhan 				     ctx->iv, ctx->iv_len, in, out, len, enc);
119049a2135eSLin Jinhan 	default:
119149a2135eSLin Jinhan 		return -EINVAL;
119249a2135eSLin Jinhan 	}
119349a2135eSLin Jinhan }
1194d9332f1cSLin Jinhan 
1195d9332f1cSLin Jinhan int rk_crypto_mac(struct udevice *dev, u32 algo, u32 mode,
1196d9332f1cSLin Jinhan 		  const u8 *key, u32 key_len,
1197d9332f1cSLin Jinhan 		  const u8 *in, u32 len, u8 *tag)
1198d9332f1cSLin Jinhan {
1199d9332f1cSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1200d9332f1cSLin Jinhan 	int ret;
1201d9332f1cSLin Jinhan 
1202d9332f1cSLin Jinhan 	if (!IS_MAC_MODE(rk_mode))
1203d9332f1cSLin Jinhan 		return -EINVAL;
1204d9332f1cSLin Jinhan 
1205d9332f1cSLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1206d9332f1cSLin Jinhan 		return -EINVAL;
1207d9332f1cSLin Jinhan 
1208d9332f1cSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1209d9332f1cSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1210d9332f1cSLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1211d9332f1cSLin Jinhan 		return -EINVAL;
1212d9332f1cSLin Jinhan #endif
1213d9332f1cSLin Jinhan 
1214d9332f1cSLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, NULL, 0,
1215d9332f1cSLin Jinhan 			     algo, mode, true);
1216d9332f1cSLin Jinhan 	if (ret)
1217d9332f1cSLin Jinhan 		return ret;
1218d9332f1cSLin Jinhan 
1219d9332f1cSLin Jinhan 	return hw_cipher_crypt(in, NULL, len, NULL, 0,
1220d9332f1cSLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1221d9332f1cSLin Jinhan }
1222d9332f1cSLin Jinhan 
1223d9332f1cSLin Jinhan int rockchip_crypto_mac(struct udevice *dev, cipher_context *ctx,
1224d9332f1cSLin Jinhan 			const u8 *in, u32 len, u8 *tag)
1225d9332f1cSLin Jinhan {
1226d9332f1cSLin Jinhan 	return rk_crypto_mac(dev, ctx->algo, ctx->mode,
1227d9332f1cSLin Jinhan 			     ctx->key, ctx->key_len, in, len, tag);
1228d9332f1cSLin Jinhan }
1229d9332f1cSLin Jinhan 
1230c3ce9937SLin Jinhan int rk_crypto_ae(struct udevice *dev, u32 algo, u32 mode,
1231c3ce9937SLin Jinhan 		 const u8 *key, u32 key_len, const u8 *nonce, u32 nonce_len,
1232c3ce9937SLin Jinhan 		 const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1233c3ce9937SLin Jinhan 		 u8 *out, u8 *tag)
1234c3ce9937SLin Jinhan {
1235c3ce9937SLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1236c3ce9937SLin Jinhan 	int ret;
1237c3ce9937SLin Jinhan 
1238c3ce9937SLin Jinhan 	if (!IS_AE_MODE(rk_mode))
1239c3ce9937SLin Jinhan 		return -EINVAL;
1240c3ce9937SLin Jinhan 
1241c3ce9937SLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1242c3ce9937SLin Jinhan 		return -EINVAL;
1243c3ce9937SLin Jinhan 
1244c3ce9937SLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1245c3ce9937SLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1246c3ce9937SLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1247c3ce9937SLin Jinhan 		return -EINVAL;
1248c3ce9937SLin Jinhan #endif
1249c3ce9937SLin Jinhan 
1250c3ce9937SLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, nonce, nonce_len,
1251c3ce9937SLin Jinhan 			     algo, mode, true);
1252c3ce9937SLin Jinhan 	if (ret)
1253c3ce9937SLin Jinhan 		return ret;
1254c3ce9937SLin Jinhan 
1255c3ce9937SLin Jinhan 	return hw_cipher_crypt(in, out, len, aad, aad_len,
1256c3ce9937SLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1257c3ce9937SLin Jinhan }
1258c3ce9937SLin Jinhan 
1259c3ce9937SLin Jinhan int rockchip_crypto_ae(struct udevice *dev, cipher_context *ctx,
1260c3ce9937SLin Jinhan 		       const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1261c3ce9937SLin Jinhan 		       u8 *out, u8 *tag)
1262c3ce9937SLin Jinhan 
1263c3ce9937SLin Jinhan {
1264c3ce9937SLin Jinhan 	return rk_crypto_ae(dev, ctx->algo, ctx->mode, ctx->key, ctx->key_len,
1265c3ce9937SLin Jinhan 			    ctx->iv, ctx->iv_len, in, len,
1266c3ce9937SLin Jinhan 			    aad, aad_len, out, tag);
1267c3ce9937SLin Jinhan }
1268c3ce9937SLin Jinhan 
126949a2135eSLin Jinhan #endif
127049a2135eSLin Jinhan 
1271864e581cSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1272b353a43cSLin Jinhan static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx,
1273b353a43cSLin Jinhan 				      u8 *sign, u8 *output)
1274b353a43cSLin Jinhan {
1275b353a43cSLin Jinhan 	struct mpa_num *mpa_m = NULL, *mpa_e = NULL, *mpa_n = NULL;
1276b353a43cSLin Jinhan 	struct mpa_num *mpa_c = NULL, *mpa_result = NULL;
1277b353a43cSLin Jinhan 	u32 n_bits, n_words;
1278b353a43cSLin Jinhan 	int ret;
1279b353a43cSLin Jinhan 
1280b353a43cSLin Jinhan 	if (!ctx)
1281b353a43cSLin Jinhan 		return -EINVAL;
1282b353a43cSLin Jinhan 
1283b353a43cSLin Jinhan 	if (ctx->algo != CRYPTO_RSA512 &&
1284b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA1024 &&
1285b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA2048 &&
1286b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA3072 &&
1287b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA4096)
1288b353a43cSLin Jinhan 		return -EINVAL;
1289b353a43cSLin Jinhan 
1290b353a43cSLin Jinhan 	n_bits = crypto_algo_nbits(ctx->algo);
1291b353a43cSLin Jinhan 	n_words = BITS2WORD(n_bits);
1292b353a43cSLin Jinhan 
1293549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_m, sign, n_words);
1294b353a43cSLin Jinhan 	if (ret)
1295b353a43cSLin Jinhan 		goto exit;
1296b353a43cSLin Jinhan 
1297549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_e, ctx->e, n_words);
1298549a74f7SLin Jinhan 	if (ret)
1299549a74f7SLin Jinhan 		goto exit;
1300b353a43cSLin Jinhan 
1301549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_n, ctx->n, n_words);
1302549a74f7SLin Jinhan 	if (ret)
1303549a74f7SLin Jinhan 		goto exit;
1304549a74f7SLin Jinhan 
1305549a74f7SLin Jinhan 	if (ctx->c) {
1306549a74f7SLin Jinhan 		ret = rk_mpa_alloc(&mpa_c, ctx->c, n_words);
1307549a74f7SLin Jinhan 		if (ret)
1308549a74f7SLin Jinhan 			goto exit;
1309549a74f7SLin Jinhan 	}
1310549a74f7SLin Jinhan 
1311549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_result, NULL, n_words);
1312549a74f7SLin Jinhan 	if (ret)
1313549a74f7SLin Jinhan 		goto exit;
1314b353a43cSLin Jinhan 
1315b353a43cSLin Jinhan 	ret = rk_exptmod_np(mpa_m, mpa_e, mpa_n, mpa_c, mpa_result);
1316b353a43cSLin Jinhan 	if (!ret)
1317549a74f7SLin Jinhan 		memcpy(output, mpa_result->d, BITS2BYTE(n_bits));
1318b353a43cSLin Jinhan 
1319b353a43cSLin Jinhan exit:
1320b353a43cSLin Jinhan 	rk_mpa_free(&mpa_m);
1321b353a43cSLin Jinhan 	rk_mpa_free(&mpa_e);
1322b353a43cSLin Jinhan 	rk_mpa_free(&mpa_n);
1323b353a43cSLin Jinhan 	rk_mpa_free(&mpa_c);
1324b353a43cSLin Jinhan 	rk_mpa_free(&mpa_result);
1325b353a43cSLin Jinhan 
1326b353a43cSLin Jinhan 	return ret;
1327b353a43cSLin Jinhan }
1328864e581cSLin Jinhan #endif
1329b353a43cSLin Jinhan 
1330b353a43cSLin Jinhan static const struct dm_crypto_ops rockchip_crypto_ops = {
1331b353a43cSLin Jinhan 	.capability   = rockchip_crypto_capability,
1332b353a43cSLin Jinhan 	.sha_init     = rockchip_crypto_sha_init,
1333b353a43cSLin Jinhan 	.sha_update   = rockchip_crypto_sha_update,
1334b353a43cSLin Jinhan 	.sha_final    = rockchip_crypto_sha_final,
133549a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1336b353a43cSLin Jinhan 	.rsa_verify   = rockchip_crypto_rsa_verify,
133749a2135eSLin Jinhan #endif
133849a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
133949a2135eSLin Jinhan 	.hmac_init    = rockchip_crypto_hmac_init,
134049a2135eSLin Jinhan 	.hmac_update  = rockchip_crypto_hmac_update,
134149a2135eSLin Jinhan 	.hmac_final   = rockchip_crypto_hmac_final,
134249a2135eSLin Jinhan #endif
134349a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
134449a2135eSLin Jinhan 	.cipher_crypt = rockchip_crypto_cipher,
1345d9332f1cSLin Jinhan 	.cipher_mac = rockchip_crypto_mac,
1346c3ce9937SLin Jinhan 	.cipher_ae  = rockchip_crypto_ae,
134749a2135eSLin Jinhan #endif
1348b353a43cSLin Jinhan };
1349b353a43cSLin Jinhan 
1350b353a43cSLin Jinhan /*
1351b353a43cSLin Jinhan  * Only use "clocks" to parse crypto clock id and use rockchip_get_clk().
1352b353a43cSLin Jinhan  * Because we always add crypto node in U-Boot dts, when kernel dtb enabled :
1353b353a43cSLin Jinhan  *
1354b353a43cSLin Jinhan  *   1. There is cru phandle mismatch between U-Boot and kernel dtb;
1355b353a43cSLin Jinhan  *   2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property;
1356b353a43cSLin Jinhan  */
1357b353a43cSLin Jinhan static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev)
1358b353a43cSLin Jinhan {
1359b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1360b353a43cSLin Jinhan 	int len, ret = -EINVAL;
1361b353a43cSLin Jinhan 
1362a24b2aebSLin Jinhan 	memset(priv, 0x00, sizeof(*priv));
1363a24b2aebSLin Jinhan 
1364a24b2aebSLin Jinhan 	priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev);
1365a24b2aebSLin Jinhan 	if (priv->reg == FDT_ADDR_T_NONE)
1366a24b2aebSLin Jinhan 		return -EINVAL;
1367a24b2aebSLin Jinhan 
1368a24b2aebSLin Jinhan 	crypto_base = priv->reg;
1369a24b2aebSLin Jinhan 
1370a24b2aebSLin Jinhan 	/* if there is no clocks in dts, just skip it */
1371b353a43cSLin Jinhan 	if (!dev_read_prop(dev, "clocks", &len)) {
1372b353a43cSLin Jinhan 		printf("Can't find \"clocks\" property\n");
1373a24b2aebSLin Jinhan 		return 0;
1374b353a43cSLin Jinhan 	}
1375b353a43cSLin Jinhan 
1376b353a43cSLin Jinhan 	memset(priv, 0x00, sizeof(*priv));
1377b353a43cSLin Jinhan 	priv->clocks = malloc(len);
1378b353a43cSLin Jinhan 	if (!priv->clocks)
1379b353a43cSLin Jinhan 		return -ENOMEM;
1380b353a43cSLin Jinhan 
1381b353a43cSLin Jinhan 	priv->nclocks = len / sizeof(u32);
1382b353a43cSLin Jinhan 	if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks,
1383b353a43cSLin Jinhan 			       priv->nclocks)) {
1384b353a43cSLin Jinhan 		printf("Can't read \"clocks\" property\n");
1385b353a43cSLin Jinhan 		ret = -EINVAL;
1386b353a43cSLin Jinhan 		goto exit;
1387b353a43cSLin Jinhan 	}
1388b353a43cSLin Jinhan 
1389b353a43cSLin Jinhan 	if (!dev_read_prop(dev, "clock-frequency", &len)) {
1390b353a43cSLin Jinhan 		printf("Can't find \"clock-frequency\" property\n");
1391b353a43cSLin Jinhan 		ret = -EINVAL;
1392b353a43cSLin Jinhan 		goto exit;
1393b353a43cSLin Jinhan 	}
1394b353a43cSLin Jinhan 
1395b353a43cSLin Jinhan 	priv->frequencies = malloc(len);
1396b353a43cSLin Jinhan 	if (!priv->frequencies) {
1397b353a43cSLin Jinhan 		ret = -ENOMEM;
1398b353a43cSLin Jinhan 		goto exit;
1399b353a43cSLin Jinhan 	}
1400b353a43cSLin Jinhan 
1401b353a43cSLin Jinhan 	priv->nclocks = len / sizeof(u32);
1402b353a43cSLin Jinhan 	if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies,
1403b353a43cSLin Jinhan 			       priv->nclocks)) {
1404b353a43cSLin Jinhan 		printf("Can't read \"clock-frequency\" property\n");
1405b353a43cSLin Jinhan 		ret = -EINVAL;
1406b353a43cSLin Jinhan 		goto exit;
1407b353a43cSLin Jinhan 	}
1408b353a43cSLin Jinhan 
1409b353a43cSLin Jinhan 	return 0;
1410b353a43cSLin Jinhan exit:
1411b353a43cSLin Jinhan 	if (priv->clocks)
1412b353a43cSLin Jinhan 		free(priv->clocks);
1413b353a43cSLin Jinhan 
1414b353a43cSLin Jinhan 	if (priv->frequencies)
1415b353a43cSLin Jinhan 		free(priv->frequencies);
1416b353a43cSLin Jinhan 
1417b353a43cSLin Jinhan 	return ret;
1418b353a43cSLin Jinhan }
1419b353a43cSLin Jinhan 
14206cebff12SJoseph Chen static int rk_crypto_set_clk(struct udevice *dev)
1421b353a43cSLin Jinhan {
14226cebff12SJoseph Chen 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
14236cebff12SJoseph Chen 	struct clk clk;
1424a24b2aebSLin Jinhan 	int i, ret;
1425b353a43cSLin Jinhan 
1426a24b2aebSLin Jinhan 	if (!priv->clocks && priv->nclocks == 0)
1427a24b2aebSLin Jinhan 		return 0;
142849a2135eSLin Jinhan 
14296cebff12SJoseph Chen 	for (i = 0; i < priv->nclocks; i++) {
14306cebff12SJoseph Chen 		ret = clk_get_by_index(dev, i, &clk);
14316cebff12SJoseph Chen 		if (ret < 0) {
14326cebff12SJoseph Chen 			printf("Failed to get clk index %d, ret=%d\n", i, ret);
1433b353a43cSLin Jinhan 			return ret;
1434b353a43cSLin Jinhan 		}
14356cebff12SJoseph Chen 		ret = clk_set_rate(&clk, priv->frequencies[i]);
1436b353a43cSLin Jinhan 		if (ret < 0) {
1437b353a43cSLin Jinhan 			printf("%s: Failed to set clk(%ld): ret=%d\n",
14386cebff12SJoseph Chen 			       __func__, clk.id, ret);
1439b353a43cSLin Jinhan 			return ret;
1440b353a43cSLin Jinhan 		}
1441b353a43cSLin Jinhan 	}
1442b353a43cSLin Jinhan 
1443a24b2aebSLin Jinhan 	return 0;
1444a24b2aebSLin Jinhan }
1445a24b2aebSLin Jinhan 
1446a24b2aebSLin Jinhan static int rockchip_crypto_probe(struct udevice *dev)
1447a24b2aebSLin Jinhan {
1448a24b2aebSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1449a24b2aebSLin Jinhan 	struct rk_crypto_soc_data *sdata;
1450a24b2aebSLin Jinhan 	int ret = 0;
1451a24b2aebSLin Jinhan 
1452a24b2aebSLin Jinhan 	sdata = (struct rk_crypto_soc_data *)dev_get_driver_data(dev);
145358432b6fSLin Jinhan 
145458432b6fSLin Jinhan 	if (sdata->dynamic_cap)
145558432b6fSLin Jinhan 		sdata->capability = sdata->dynamic_cap();
145658432b6fSLin Jinhan 
1457a24b2aebSLin Jinhan 	priv->soc_data = sdata;
1458a24b2aebSLin Jinhan 
1459a24b2aebSLin Jinhan 	priv->hw_ctx = memalign(LLI_ADDR_ALIGN_SIZE,
1460a24b2aebSLin Jinhan 				sizeof(struct rk_hash_ctx));
1461a24b2aebSLin Jinhan 	if (!priv->hw_ctx)
1462a24b2aebSLin Jinhan 		return -ENOMEM;
1463a24b2aebSLin Jinhan 
14646cebff12SJoseph Chen 	ret = rk_crypto_set_clk(dev);
1465a24b2aebSLin Jinhan 	if (ret)
1466a24b2aebSLin Jinhan 		return ret;
1467a24b2aebSLin Jinhan 
1468b353a43cSLin Jinhan 	hw_crypto_reset();
1469b353a43cSLin Jinhan 
1470b353a43cSLin Jinhan 	return 0;
1471b353a43cSLin Jinhan }
1472b353a43cSLin Jinhan 
147349a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base = {
147449a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
147549a2135eSLin Jinhan 		      CRYPTO_SHA1 |
147649a2135eSLin Jinhan 		      CRYPTO_SHA256 |
147749a2135eSLin Jinhan 		      CRYPTO_SHA512 |
147849a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
147949a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
148049a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
148149a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
148249a2135eSLin Jinhan 		      CRYPTO_RSA512 |
148349a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
148449a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
148549a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
148649a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
148749a2135eSLin Jinhan 		      CRYPTO_DES |
148849a2135eSLin Jinhan 		      CRYPTO_AES,
148949a2135eSLin Jinhan };
149049a2135eSLin Jinhan 
149149a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base_sm = {
149249a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
149349a2135eSLin Jinhan 		      CRYPTO_SHA1 |
149449a2135eSLin Jinhan 		      CRYPTO_SHA256 |
149549a2135eSLin Jinhan 		      CRYPTO_SHA512 |
149649a2135eSLin Jinhan 		      CRYPTO_SM3 |
149749a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
149849a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
149949a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
150049a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
150149a2135eSLin Jinhan 		      CRYPTO_HMAC_SM3 |
150249a2135eSLin Jinhan 		      CRYPTO_RSA512 |
150349a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
150449a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
150549a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
150649a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
150749a2135eSLin Jinhan 		      CRYPTO_DES |
150849a2135eSLin Jinhan 		      CRYPTO_AES |
150949a2135eSLin Jinhan 		      CRYPTO_SM4,
151049a2135eSLin Jinhan };
151149a2135eSLin Jinhan 
151249a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_rk1808 = {
151349a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
151449a2135eSLin Jinhan 		      CRYPTO_SHA1 |
151549a2135eSLin Jinhan 		      CRYPTO_SHA256 |
151649a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
151749a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
151849a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
151949a2135eSLin Jinhan 		      CRYPTO_RSA512 |
152049a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
152149a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
152249a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
152349a2135eSLin Jinhan 		      CRYPTO_RSA4096,
152449a2135eSLin Jinhan };
152549a2135eSLin Jinhan 
152658432b6fSLin Jinhan static const struct rk_crypto_soc_data soc_data_cryptov3 = {
152758432b6fSLin Jinhan 	.capability  = 0,
152858432b6fSLin Jinhan 	.dynamic_cap = crypto_v3_dynamic_cap,
152958432b6fSLin Jinhan };
153058432b6fSLin Jinhan 
1531b353a43cSLin Jinhan static const struct udevice_id rockchip_crypto_ids[] = {
153249a2135eSLin Jinhan 	{
153349a2135eSLin Jinhan 		.compatible = "rockchip,px30-crypto",
153449a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
153549a2135eSLin Jinhan 	},
153649a2135eSLin Jinhan 	{
153749a2135eSLin Jinhan 		.compatible = "rockchip,rk1808-crypto",
153849a2135eSLin Jinhan 		.data = (ulong)&soc_data_rk1808
153949a2135eSLin Jinhan 	},
154049a2135eSLin Jinhan 	{
154149a2135eSLin Jinhan 		.compatible = "rockchip,rk3308-crypto",
154249a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
154349a2135eSLin Jinhan 	},
154449a2135eSLin Jinhan 	{
154549a2135eSLin Jinhan 		.compatible = "rockchip,rv1126-crypto",
154649a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
154749a2135eSLin Jinhan 	},
154849a2135eSLin Jinhan 	{
154949a2135eSLin Jinhan 		.compatible = "rockchip,rk3568-crypto",
155049a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
155149a2135eSLin Jinhan 	},
15525b3e3895SLin Jinhan 	{
15535b3e3895SLin Jinhan 		.compatible = "rockchip,rk3588-crypto",
15545b3e3895SLin Jinhan 		.data = (ulong)&soc_data_base_sm
15555b3e3895SLin Jinhan 	},
155658432b6fSLin Jinhan 	{
1557f93f9077SLin Jinhan 		.compatible = "rockchip,crypto-v3",
155858432b6fSLin Jinhan 		.data = (ulong)&soc_data_cryptov3
155958432b6fSLin Jinhan 	},
1560*2bcebb1aSLin Jinhan 	{
1561*2bcebb1aSLin Jinhan 		.compatible = "rockchip,crypto-v4",
1562*2bcebb1aSLin Jinhan 		.data = (ulong)&soc_data_cryptov3 /* reuse crypto v3 config */
1563*2bcebb1aSLin Jinhan 	},
1564b353a43cSLin Jinhan 	{ }
1565b353a43cSLin Jinhan };
1566b353a43cSLin Jinhan 
1567b353a43cSLin Jinhan U_BOOT_DRIVER(rockchip_crypto_v2) = {
1568b353a43cSLin Jinhan 	.name		= "rockchip_crypto_v2",
1569b353a43cSLin Jinhan 	.id		= UCLASS_CRYPTO,
1570b353a43cSLin Jinhan 	.of_match	= rockchip_crypto_ids,
1571b353a43cSLin Jinhan 	.ops		= &rockchip_crypto_ops,
1572b353a43cSLin Jinhan 	.probe		= rockchip_crypto_probe,
1573b353a43cSLin Jinhan 	.ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata,
1574b353a43cSLin Jinhan 	.priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv),
1575b353a43cSLin Jinhan };
1576