xref: /rk3399_rockchip-uboot/drivers/crypto/rockchip/crypto_v2.c (revision da703fb5eeb8c66c0c4c97a53fa19fb16c9714ae)
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;
57*da703fb5SLin Jinhan 	u32				freq_nclocks;
58b353a43cSLin Jinhan 	u32				length;
591606a214SLin Jinhan 	struct rk_hash_ctx		*hw_ctx;
6049a2135eSLin Jinhan 	struct rk_crypto_soc_data	*soc_data;
61b353a43cSLin Jinhan };
62b353a43cSLin Jinhan 
6349a2135eSLin Jinhan #define LLI_ADDR_ALIGN_SIZE	8
6449a2135eSLin Jinhan #define DATA_ADDR_ALIGN_SIZE	8
6549a2135eSLin Jinhan #define DATA_LEN_ALIGN_SIZE	64
661606a214SLin Jinhan 
67086e8fa8SLin Jinhan /* crypto timeout 500ms, must support more than 32M data per times*/
68086e8fa8SLin Jinhan #define HASH_UPDATE_LIMIT	(32 * 1024 * 1024)
6949a2135eSLin Jinhan #define RK_CRYPTO_TIMEOUT	500000
70b353a43cSLin Jinhan 
7149a2135eSLin Jinhan #define RK_POLL_TIMEOUT(condition, timeout) \
7249a2135eSLin Jinhan ({ \
7349a2135eSLin Jinhan 	int time_out = timeout; \
74b353a43cSLin Jinhan 	while (condition) { \
7549a2135eSLin Jinhan 		if (--time_out <= 0) { \
761606a214SLin Jinhan 			debug("[%s] %d: time out!\n", __func__,\
77b353a43cSLin Jinhan 				__LINE__); \
78b353a43cSLin Jinhan 			break; \
79b353a43cSLin Jinhan 		} \
80b353a43cSLin Jinhan 		udelay(1); \
81b353a43cSLin Jinhan 	} \
8249a2135eSLin Jinhan 	(time_out <= 0) ? -ETIMEDOUT : 0; \
8349a2135eSLin Jinhan })
84b353a43cSLin Jinhan 
85d9332f1cSLin Jinhan #define WAIT_TAG_VALID(channel, timeout) ({ \
86d9332f1cSLin Jinhan 	u32 tag_mask = CRYPTO_CH0_TAG_VALID << (channel);\
87d9332f1cSLin Jinhan 	int ret;\
88d9332f1cSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_TAG_VALID) & tag_mask),\
89d9332f1cSLin Jinhan 			      timeout);\
90d9332f1cSLin Jinhan 	crypto_write(crypto_read(CRYPTO_TAG_VALID) & tag_mask, CRYPTO_TAG_VALID);\
91d9332f1cSLin Jinhan 	ret;\
92d9332f1cSLin Jinhan })
93d9332f1cSLin Jinhan 
94b353a43cSLin Jinhan #define virt_to_phys(addr)		(((unsigned long)addr) & 0xffffffff)
95b353a43cSLin Jinhan #define phys_to_virt(addr, area)	((unsigned long)addr)
96b353a43cSLin Jinhan 
9749a2135eSLin Jinhan #define align_malloc(bytes, alignment)	memalign(alignment, bytes)
98dbca2fe7SLin Jinhan #define align_free(addr)		do {if (addr) free(addr);} while (0)
9949a2135eSLin Jinhan 
10049a2135eSLin Jinhan #define ROUNDUP(size, alignment)	round_up(size, alignment)
10149a2135eSLin Jinhan #define cache_op_inner(type, addr, size) \
10249a2135eSLin Jinhan 					crypto_flush_cacheline((ulong)addr, size)
10349a2135eSLin Jinhan 
104d9332f1cSLin Jinhan #define IS_NEED_IV(rk_mode) ((rk_mode) != RK_MODE_ECB && \
105d9332f1cSLin Jinhan 			     (rk_mode) != RK_MODE_CMAC && \
106d9332f1cSLin Jinhan 			     (rk_mode) != RK_MODE_CBC_MAC)
107d9332f1cSLin Jinhan 
108d9332f1cSLin Jinhan #define IS_NEED_TAG(rk_mode) ((rk_mode) == RK_MODE_CMAC || \
109c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_CBC_MAC || \
110c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_CCM || \
111c3ce9937SLin Jinhan 			      (rk_mode) == RK_MODE_GCM)
112d9332f1cSLin Jinhan 
113d9332f1cSLin Jinhan #define IS_MAC_MODE(rk_mode) ((rk_mode) == RK_MODE_CMAC || \
114d9332f1cSLin Jinhan 			      (rk_mode) == RK_MODE_CBC_MAC)
115d9332f1cSLin Jinhan 
116c3ce9937SLin Jinhan #define IS_AE_MODE(rk_mode) ((rk_mode) == RK_MODE_CCM || \
117c3ce9937SLin Jinhan 			     (rk_mode) == RK_MODE_GCM)
118c3ce9937SLin Jinhan 
119b353a43cSLin Jinhan fdt_addr_t crypto_base;
120b353a43cSLin Jinhan 
12149a2135eSLin Jinhan static inline void word2byte_be(u32 word, u8 *ch)
122b353a43cSLin Jinhan {
123b353a43cSLin Jinhan 	ch[0] = (word >> 24) & 0xff;
124b353a43cSLin Jinhan 	ch[1] = (word >> 16) & 0xff;
125b353a43cSLin Jinhan 	ch[2] = (word >> 8) & 0xff;
126b353a43cSLin Jinhan 	ch[3] = (word >> 0) & 0xff;
127b353a43cSLin Jinhan }
128b353a43cSLin Jinhan 
12949a2135eSLin Jinhan static inline u32 byte2word_be(const u8 *ch)
13049a2135eSLin Jinhan {
13149a2135eSLin Jinhan 	return (*ch << 24) + (*(ch + 1) << 16) + (*(ch + 2) << 8) + *(ch + 3);
13249a2135eSLin Jinhan }
13349a2135eSLin Jinhan 
13449a2135eSLin Jinhan static inline void clear_regs(u32 base, u32 words)
135b353a43cSLin Jinhan {
136b353a43cSLin Jinhan 	int i;
137b353a43cSLin Jinhan 
138b353a43cSLin Jinhan 	/*clear out register*/
13949a2135eSLin Jinhan 	for (i = 0; i < words; i++)
14049a2135eSLin Jinhan 		crypto_write(0, base + 4 * i);
14149a2135eSLin Jinhan }
14249a2135eSLin Jinhan 
14349a2135eSLin Jinhan static inline void clear_hash_out_reg(void)
14449a2135eSLin Jinhan {
14549a2135eSLin Jinhan 	clear_regs(CRYPTO_HASH_DOUT_0, 16);
14649a2135eSLin Jinhan }
14749a2135eSLin Jinhan 
14849a2135eSLin Jinhan static inline void clear_key_regs(void)
14949a2135eSLin Jinhan {
15049a2135eSLin Jinhan 	clear_regs(CRYPTO_CH0_KEY_0, CRYPTO_KEY_CHANNEL_NUM * 4);
15149a2135eSLin Jinhan }
15249a2135eSLin Jinhan 
153c3ce9937SLin Jinhan static inline void read_regs(u32 base, u8 *data, u32 data_len)
154c3ce9937SLin Jinhan {
155c3ce9937SLin Jinhan 	u8 tmp_buf[4];
156c3ce9937SLin Jinhan 	u32 i;
157c3ce9937SLin Jinhan 
158c3ce9937SLin Jinhan 	for (i = 0; i < data_len / 4; i++)
159c3ce9937SLin Jinhan 		word2byte_be(crypto_read(base + i * 4),
160c3ce9937SLin Jinhan 			     data + i * 4);
161c3ce9937SLin Jinhan 
162c3ce9937SLin Jinhan 	if (data_len % 4) {
163c3ce9937SLin Jinhan 		word2byte_be(crypto_read(base + i * 4), tmp_buf);
164c3ce9937SLin Jinhan 		memcpy(data + i * 4, tmp_buf, data_len % 4);
165c3ce9937SLin Jinhan 	}
166c3ce9937SLin Jinhan }
167c3ce9937SLin Jinhan 
16849a2135eSLin Jinhan static inline void write_regs(u32 base, const u8 *data, u32 data_len)
16949a2135eSLin Jinhan {
17049a2135eSLin Jinhan 	u8 tmp_buf[4];
17149a2135eSLin Jinhan 	u32 i;
17249a2135eSLin Jinhan 
17349a2135eSLin Jinhan 	for (i = 0; i < data_len / 4; i++, base += 4)
17449a2135eSLin Jinhan 		crypto_write(byte2word_be(data + i * 4), base);
17549a2135eSLin Jinhan 
17649a2135eSLin Jinhan 	if (data_len % 4) {
17749a2135eSLin Jinhan 		memset(tmp_buf, 0x00, sizeof(tmp_buf));
17849a2135eSLin Jinhan 		memcpy((u8 *)tmp_buf, data + i * 4, data_len % 4);
17949a2135eSLin Jinhan 		crypto_write(byte2word_be(tmp_buf), base);
18049a2135eSLin Jinhan 	}
18149a2135eSLin Jinhan }
18249a2135eSLin Jinhan 
18349a2135eSLin Jinhan static inline void write_key_reg(u32 chn, const u8 *key, u32 key_len)
18449a2135eSLin Jinhan {
18549a2135eSLin Jinhan 	write_regs(CRYPTO_CH0_KEY_0 + chn * 0x10, key, key_len);
18649a2135eSLin Jinhan }
18749a2135eSLin Jinhan 
18849a2135eSLin Jinhan static inline void set_iv_reg(u32 chn, const u8 *iv, u32 iv_len)
18949a2135eSLin Jinhan {
19049a2135eSLin Jinhan 	u32 base_iv;
19149a2135eSLin Jinhan 
19249a2135eSLin Jinhan 	base_iv = CRYPTO_CH0_IV_0 + chn * 0x10;
19349a2135eSLin Jinhan 
19449a2135eSLin Jinhan 	/* clear iv */
19549a2135eSLin Jinhan 	clear_regs(base_iv, 4);
19649a2135eSLin Jinhan 
19749a2135eSLin Jinhan 	if (!iv || iv_len == 0)
19849a2135eSLin Jinhan 		return;
19949a2135eSLin Jinhan 
20049a2135eSLin Jinhan 	write_regs(base_iv, iv, iv_len);
20149a2135eSLin Jinhan 
20249a2135eSLin Jinhan 	crypto_write(iv_len, CRYPTO_CH0_IV_LEN_0 + 4 * chn);
203b353a43cSLin Jinhan }
204b353a43cSLin Jinhan 
205c3ce9937SLin Jinhan static inline void get_iv_reg(u32 chn, u8 *iv, u32 iv_len)
206c3ce9937SLin Jinhan {
207c3ce9937SLin Jinhan 	u32 base_iv;
208c3ce9937SLin Jinhan 
209c3ce9937SLin Jinhan 	base_iv = CRYPTO_CH0_IV_0 + chn * 0x10;
210c3ce9937SLin Jinhan 
211c3ce9937SLin Jinhan 	read_regs(base_iv, iv, iv_len);
212c3ce9937SLin Jinhan }
213c3ce9937SLin Jinhan 
214d9332f1cSLin Jinhan static inline void get_tag_from_reg(u32 chn, u8 *tag, u32 tag_len)
215d9332f1cSLin Jinhan {
216d9332f1cSLin Jinhan 	u32 i;
217d9332f1cSLin Jinhan 	u32 chn_base = CRYPTO_CH0_TAG_0 + 0x10 * chn;
218d9332f1cSLin Jinhan 
219d9332f1cSLin Jinhan 	for (i = 0; i < tag_len / 4; i++, chn_base += 4)
220d9332f1cSLin Jinhan 		word2byte_be(crypto_read(chn_base), tag + 4 * i);
221d9332f1cSLin Jinhan }
222d9332f1cSLin Jinhan 
22358432b6fSLin Jinhan static u32 crypto_v3_dynamic_cap(void)
22458432b6fSLin Jinhan {
22558432b6fSLin Jinhan 	u32 capability = 0;
22658432b6fSLin Jinhan 	u32 ver_reg, i;
22758432b6fSLin Jinhan 	struct cap_map {
22858432b6fSLin Jinhan 		u32 ver_offset;
22958432b6fSLin Jinhan 		u32 mask;
23058432b6fSLin Jinhan 		u32 cap_bit;
23158432b6fSLin Jinhan 	};
23258432b6fSLin Jinhan 	const struct cap_map cap_tbl[] = {
23358432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_MD5_FLAG,    CRYPTO_MD5},
23458432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA1_FLAG,   CRYPTO_SHA1},
23558432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA256_FLAG, CRYPTO_SHA256},
23658432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA512_FLAG, CRYPTO_SHA512},
23758432b6fSLin Jinhan 	{CRYPTO_HASH_VERSION, CRYPTO_HASH_SM3_FLAG,    CRYPTO_SM3},
23858432b6fSLin Jinhan 
23958432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_MD5_FLAG,    CRYPTO_HMAC_MD5},
24058432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA1_FLAG,   CRYPTO_HMAC_SHA1},
24158432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA256_FLAG, CRYPTO_HMAC_SHA256},
24258432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA512_FLAG, CRYPTO_HMAC_SHA512},
24358432b6fSLin Jinhan 	{CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SM3_FLAG,    CRYPTO_HMAC_SM3},
24458432b6fSLin Jinhan 
24558432b6fSLin Jinhan 	{CRYPTO_AES_VERSION,  CRYPTO_AES256_FLAG,      CRYPTO_AES},
24658432b6fSLin Jinhan 	{CRYPTO_DES_VERSION,  CRYPTO_TDES_FLAG,        CRYPTO_DES},
24758432b6fSLin Jinhan 	{CRYPTO_SM4_VERSION,  CRYPTO_ECB_FLAG,         CRYPTO_SM4},
24858432b6fSLin Jinhan 	};
24958432b6fSLin Jinhan 
25058432b6fSLin Jinhan 	/* rsa */
25158432b6fSLin Jinhan 	capability = CRYPTO_RSA512 |
25258432b6fSLin Jinhan 		     CRYPTO_RSA1024 |
25358432b6fSLin Jinhan 		     CRYPTO_RSA2048 |
25458432b6fSLin Jinhan 		     CRYPTO_RSA3072 |
25558432b6fSLin Jinhan 		     CRYPTO_RSA4096;
25658432b6fSLin Jinhan 
25758432b6fSLin Jinhan 	for (i = 0; i < ARRAY_SIZE(cap_tbl); i++) {
25858432b6fSLin Jinhan 		ver_reg = crypto_read(cap_tbl[i].ver_offset);
25958432b6fSLin Jinhan 
26058432b6fSLin Jinhan 		if ((ver_reg & cap_tbl[i].mask) == cap_tbl[i].mask)
26158432b6fSLin Jinhan 			capability |= cap_tbl[i].cap_bit;
26258432b6fSLin Jinhan 	}
26358432b6fSLin Jinhan 
26458432b6fSLin Jinhan 	return capability;
26558432b6fSLin Jinhan }
26658432b6fSLin Jinhan 
267b353a43cSLin Jinhan static int hw_crypto_reset(void)
268b353a43cSLin Jinhan {
26949a2135eSLin Jinhan 	u32 val = 0, mask = 0;
270b353a43cSLin Jinhan 	int ret;
271b353a43cSLin Jinhan 
27249a2135eSLin Jinhan 	val = CRYPTO_SW_PKA_RESET | CRYPTO_SW_CC_RESET;
27349a2135eSLin Jinhan 	mask = val << CRYPTO_WRITE_MASK_SHIFT;
274b353a43cSLin Jinhan 
275b353a43cSLin Jinhan 	/* reset pka and crypto modules*/
27649a2135eSLin Jinhan 	crypto_write(val | mask, CRYPTO_RST_CTL);
277b353a43cSLin Jinhan 
278b353a43cSLin Jinhan 	/* wait reset compelete */
27949a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL), RK_CRYPTO_TIMEOUT);
28049a2135eSLin Jinhan 
281b353a43cSLin Jinhan 	return ret;
282b353a43cSLin Jinhan }
283b353a43cSLin Jinhan 
284b353a43cSLin Jinhan static void hw_hash_clean_ctx(struct rk_hash_ctx *ctx)
285b353a43cSLin Jinhan {
286b353a43cSLin Jinhan 	/* clear hash status */
287b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
288b353a43cSLin Jinhan 
2891606a214SLin Jinhan 	assert(ctx);
2901606a214SLin Jinhan 	assert(ctx->magic == RK_HASH_CTX_MAGIC);
2911606a214SLin Jinhan 
292c48f1acfSLin Jinhan 	crypto_hash_cache_free(ctx->hash_cache);
2931606a214SLin Jinhan 
2941606a214SLin Jinhan 	memset(ctx, 0x00, sizeof(*ctx));
295b353a43cSLin Jinhan }
296b353a43cSLin Jinhan 
297c48f1acfSLin Jinhan static int rk_hash_init(void *hw_ctx, u32 algo)
298b353a43cSLin Jinhan {
299b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)hw_ctx;
300b353a43cSLin Jinhan 	u32 reg_ctrl = 0;
301b353a43cSLin Jinhan 	int ret;
302b353a43cSLin Jinhan 
303b353a43cSLin Jinhan 	if (!tmp_ctx)
304b353a43cSLin Jinhan 		return -EINVAL;
305b353a43cSLin Jinhan 
3061606a214SLin Jinhan 	reg_ctrl = CRYPTO_SW_CC_RESET;
3071606a214SLin Jinhan 	crypto_write(reg_ctrl | (reg_ctrl << CRYPTO_WRITE_MASK_SHIFT),
3081606a214SLin Jinhan 		     CRYPTO_RST_CTL);
3091606a214SLin Jinhan 
3101606a214SLin Jinhan 	/* wait reset compelete */
31149a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL),
31249a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
3131606a214SLin Jinhan 
3141606a214SLin Jinhan 	reg_ctrl = 0;
315b353a43cSLin Jinhan 	tmp_ctx->algo = algo;
316b353a43cSLin Jinhan 	switch (algo) {
317b353a43cSLin Jinhan 	case CRYPTO_MD5:
31849a2135eSLin Jinhan 	case CRYPTO_HMAC_MD5:
319b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_MD5;
320b353a43cSLin Jinhan 		tmp_ctx->digest_size = 16;
321b353a43cSLin Jinhan 		break;
322b353a43cSLin Jinhan 	case CRYPTO_SHA1:
32349a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA1:
324b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA1;
325b353a43cSLin Jinhan 		tmp_ctx->digest_size = 20;
326b353a43cSLin Jinhan 		break;
327b353a43cSLin Jinhan 	case CRYPTO_SHA256:
32849a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA256:
329b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA256;
330b353a43cSLin Jinhan 		tmp_ctx->digest_size = 32;
331b353a43cSLin Jinhan 		break;
332e7846385SLin Jinhan 	case CRYPTO_SHA512:
33349a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA512:
334e7846385SLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA512;
335e7846385SLin Jinhan 		tmp_ctx->digest_size = 64;
336e7846385SLin Jinhan 		break;
33749a2135eSLin Jinhan 	case CRYPTO_SM3:
33849a2135eSLin Jinhan 	case CRYPTO_HMAC_SM3:
33949a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SM3;
34049a2135eSLin Jinhan 		tmp_ctx->digest_size = 32;
34149a2135eSLin Jinhan 		break;
342b353a43cSLin Jinhan 	default:
343b353a43cSLin Jinhan 		ret = -EINVAL;
344b353a43cSLin Jinhan 		goto exit;
345b353a43cSLin Jinhan 	}
346b353a43cSLin Jinhan 
347b353a43cSLin Jinhan 	clear_hash_out_reg();
348b353a43cSLin Jinhan 
349b353a43cSLin Jinhan 	/* enable hardware padding */
350b353a43cSLin Jinhan 	reg_ctrl |= CRYPTO_HW_PAD_ENABLE;
351b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
352b353a43cSLin Jinhan 
353b353a43cSLin Jinhan 	/* FIFO input and output data byte swap */
354b353a43cSLin Jinhan 	/* such as B0, B1, B2, B3 -> B3, B2, B1, B0 */
355b353a43cSLin Jinhan 	reg_ctrl = CRYPTO_DOUT_BYTESWAP | CRYPTO_DOIN_BYTESWAP;
356b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_FIFO_CTL);
357b353a43cSLin Jinhan 
3581606a214SLin Jinhan 	/* enable src_item_done interrupt */
359fe0c4b19SLin Jinhan 	crypto_write(0, CRYPTO_DMA_INT_EN);
360b353a43cSLin Jinhan 
361b353a43cSLin Jinhan 	tmp_ctx->magic = RK_HASH_CTX_MAGIC;
362b353a43cSLin Jinhan 
363b353a43cSLin Jinhan 	return 0;
364b353a43cSLin Jinhan exit:
365b353a43cSLin Jinhan 	/* clear hash setting if init failed */
366b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
367b353a43cSLin Jinhan 
368b353a43cSLin Jinhan 	return ret;
369b353a43cSLin Jinhan }
370b353a43cSLin Jinhan 
371c48f1acfSLin Jinhan static int rk_hash_direct_calc(void *hw_data, const u8 *data,
3721606a214SLin Jinhan 			       u32 data_len, u8 *started_flag, u8 is_last)
373b353a43cSLin Jinhan {
374c48f1acfSLin Jinhan 	struct rockchip_crypto_priv *priv = hw_data;
375c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
376c48f1acfSLin Jinhan 	struct crypto_lli_desc *lli = &hash_ctx->data_lli;
377b353a43cSLin Jinhan 	int ret = -EINVAL;
37800fa57d8SLin Jinhan 	u32 tmp = 0, mask = 0;
379b353a43cSLin Jinhan 
38049a2135eSLin Jinhan 	assert(IS_ALIGNED((ulong)data, DATA_ADDR_ALIGN_SIZE));
38149a2135eSLin Jinhan 	assert(is_last || IS_ALIGNED(data_len, DATA_LEN_ALIGN_SIZE));
382b353a43cSLin Jinhan 
3831606a214SLin Jinhan 	debug("%s: data = %p, len = %u, s = %x, l = %x\n",
3841606a214SLin Jinhan 	      __func__, data, data_len, *started_flag, is_last);
385b353a43cSLin Jinhan 
3861606a214SLin Jinhan 	memset(lli, 0x00, sizeof(*lli));
3871606a214SLin Jinhan 	lli->src_addr = (u32)virt_to_phys(data);
3881606a214SLin Jinhan 	lli->src_len = data_len;
3891606a214SLin Jinhan 	lli->dma_ctrl = LLI_DMA_CTRL_SRC_DONE;
390b353a43cSLin Jinhan 
3911606a214SLin Jinhan 	if (is_last) {
3921606a214SLin Jinhan 		lli->user_define |= LLI_USER_STRING_LAST;
3931606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_LAST;
394b353a43cSLin Jinhan 	} else {
3951606a214SLin Jinhan 		lli->next_addr = (u32)virt_to_phys(lli);
3961606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_PAUSE;
3971606a214SLin Jinhan 	}
3981606a214SLin Jinhan 
3991606a214SLin Jinhan 	if (!(*started_flag)) {
4001606a214SLin Jinhan 		lli->user_define |=
401ce7f4cd6SLin Jinhan 			(LLI_USER_STRING_START | LLI_USER_CIPHER_START);
4021606a214SLin Jinhan 		crypto_write((u32)virt_to_phys(lli), CRYPTO_DMA_LLI_ADDR);
4031606a214SLin Jinhan 		crypto_write((CRYPTO_HASH_ENABLE << CRYPTO_WRITE_MASK_SHIFT) |
4041606a214SLin Jinhan 			     CRYPTO_HASH_ENABLE, CRYPTO_HASH_CTL);
4051606a214SLin Jinhan 		tmp = CRYPTO_DMA_START;
4061606a214SLin Jinhan 		*started_flag = 1;
4071606a214SLin Jinhan 	} else {
408b353a43cSLin Jinhan 		tmp = CRYPTO_DMA_RESTART;
409b353a43cSLin Jinhan 	}
410b353a43cSLin Jinhan 
411b353a43cSLin Jinhan 	/* flush cache */
412c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)lli, sizeof(*lli));
413c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)data, data_len);
414b353a43cSLin Jinhan 
415b353a43cSLin Jinhan 	/* start calculate */
416b353a43cSLin Jinhan 	crypto_write(tmp << CRYPTO_WRITE_MASK_SHIFT | tmp,
417b353a43cSLin Jinhan 		     CRYPTO_DMA_CTL);
418b353a43cSLin Jinhan 
41900fa57d8SLin Jinhan 	/* mask CRYPTO_SYNC_LOCKSTEP_INT_ST flag */
42000fa57d8SLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
42100fa57d8SLin Jinhan 
422b353a43cSLin Jinhan 	/* wait calc ok */
42349a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
42449a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
425b353a43cSLin Jinhan 
426b353a43cSLin Jinhan 	/* clear interrupt status */
427b353a43cSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
428b353a43cSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
429b353a43cSLin Jinhan 
43049cbb0faSLin Jinhan 	if ((tmp & mask) != CRYPTO_SRC_ITEM_DONE_INT_ST &&
43149cbb0faSLin Jinhan 	    (tmp & mask) != CRYPTO_ZERO_LEN_INT_ST) {
43246aac970SLin Jinhan 		ret = -EFAULT;
4331606a214SLin Jinhan 		debug("[%s] %d: CRYPTO_DMA_INT_ST = 0x%x\n",
434b353a43cSLin Jinhan 		      __func__, __LINE__, tmp);
4351606a214SLin Jinhan 		goto exit;
436b353a43cSLin Jinhan 	}
437b353a43cSLin Jinhan 
438c48f1acfSLin Jinhan 	priv->length += data_len;
4391606a214SLin Jinhan exit:
4401606a214SLin Jinhan 	return ret;
441b353a43cSLin Jinhan }
4421606a214SLin Jinhan 
4431606a214SLin Jinhan int rk_hash_update(void *ctx, const u8 *data, u32 data_len)
4441606a214SLin Jinhan {
4451606a214SLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
446c48f1acfSLin Jinhan 	int ret = -EINVAL;
4471606a214SLin Jinhan 
4481606a214SLin Jinhan 	debug("\n");
4491606a214SLin Jinhan 	if (!tmp_ctx || !data)
450c48f1acfSLin Jinhan 		goto exit;
4511606a214SLin Jinhan 
4521606a214SLin Jinhan 	if (tmp_ctx->digest_size == 0 || tmp_ctx->magic != RK_HASH_CTX_MAGIC)
453c48f1acfSLin Jinhan 		goto exit;
4541606a214SLin Jinhan 
455c48f1acfSLin Jinhan 	ret = crypto_hash_update_with_cache(tmp_ctx->hash_cache,
456c48f1acfSLin Jinhan 					    data, data_len);
4571606a214SLin Jinhan 
458c48f1acfSLin Jinhan exit:
459b353a43cSLin Jinhan 	/* free lli list */
460c48f1acfSLin Jinhan 	if (ret)
461b353a43cSLin Jinhan 		hw_hash_clean_ctx(tmp_ctx);
462b353a43cSLin Jinhan 
463c48f1acfSLin Jinhan 	return ret;
464b353a43cSLin Jinhan }
465b353a43cSLin Jinhan 
466b353a43cSLin Jinhan int rk_hash_final(void *ctx, u8 *digest, size_t len)
467b353a43cSLin Jinhan {
468b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
469b353a43cSLin Jinhan 	int ret = -EINVAL;
470b353a43cSLin Jinhan 
471b353a43cSLin Jinhan 	if (!digest)
472b353a43cSLin Jinhan 		goto exit;
473b353a43cSLin Jinhan 
474b353a43cSLin Jinhan 	if (!tmp_ctx ||
475b353a43cSLin Jinhan 	    tmp_ctx->digest_size == 0 ||
476b353a43cSLin Jinhan 	    len > tmp_ctx->digest_size ||
477b353a43cSLin Jinhan 	    tmp_ctx->magic != RK_HASH_CTX_MAGIC) {
478b353a43cSLin Jinhan 		goto exit;
479b353a43cSLin Jinhan 	}
480b353a43cSLin Jinhan 
481b353a43cSLin Jinhan 	/* wait hash value ok */
48249a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!crypto_read(CRYPTO_HASH_VALID),
48349a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
484b353a43cSLin Jinhan 
485c3ce9937SLin Jinhan 	read_regs(CRYPTO_HASH_DOUT_0, digest, len);
486b353a43cSLin Jinhan 
487b353a43cSLin Jinhan 	/* clear hash status */
488b353a43cSLin Jinhan 	crypto_write(CRYPTO_HASH_IS_VALID, CRYPTO_HASH_VALID);
489b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
490b353a43cSLin Jinhan 
491b353a43cSLin Jinhan exit:
492b353a43cSLin Jinhan 
493b353a43cSLin Jinhan 	return ret;
494b353a43cSLin Jinhan }
495b353a43cSLin Jinhan 
496b353a43cSLin Jinhan static u32 rockchip_crypto_capability(struct udevice *dev)
497b353a43cSLin Jinhan {
49849a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
49949a2135eSLin Jinhan 	u32 capability, mask = 0;
5007eea1823SLin Jinhan 
50149a2135eSLin Jinhan 	capability = priv->soc_data->capability;
50249a2135eSLin Jinhan 
50349a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_CIPHER))
50449a2135eSLin Jinhan 	mask |= (CRYPTO_DES | CRYPTO_AES | CRYPTO_SM4);
505c0e47d03SLin Jinhan #endif
5067eea1823SLin Jinhan 
50749a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_HMAC))
50849a2135eSLin Jinhan 	mask |= (CRYPTO_HMAC_MD5 | CRYPTO_HMAC_SHA1 | CRYPTO_HMAC_SHA256 |
50949a2135eSLin Jinhan 			 CRYPTO_HMAC_SHA512 | CRYPTO_HMAC_SM3);
51049a2135eSLin Jinhan #endif
51149a2135eSLin Jinhan 
51249a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_RSA))
51349a2135eSLin Jinhan 	mask |= (CRYPTO_RSA512 | CRYPTO_RSA1024 | CRYPTO_RSA2048 |
51449a2135eSLin Jinhan 			 CRYPTO_RSA3072 | CRYPTO_RSA4096);
51549a2135eSLin Jinhan #endif
51649a2135eSLin Jinhan 
51749a2135eSLin Jinhan 	return capability & (~mask);
518b353a43cSLin Jinhan }
519b353a43cSLin Jinhan 
520b353a43cSLin Jinhan static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx)
521b353a43cSLin Jinhan {
522b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
523c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
524b353a43cSLin Jinhan 
525b353a43cSLin Jinhan 	if (!ctx)
526b353a43cSLin Jinhan 		return -EINVAL;
527b353a43cSLin Jinhan 
528c48f1acfSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
529b353a43cSLin Jinhan 
530c48f1acfSLin Jinhan 	priv->length = 0;
531c48f1acfSLin Jinhan 
532c48f1acfSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
533c48f1acfSLin Jinhan 						       priv, ctx->length,
53449a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
53549a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
536c48f1acfSLin Jinhan 	if (!hash_ctx->hash_cache)
537c48f1acfSLin Jinhan 		return -EFAULT;
538c48f1acfSLin Jinhan 
539c48f1acfSLin Jinhan 	return rk_hash_init(hash_ctx, ctx->algo);
540b353a43cSLin Jinhan }
541b353a43cSLin Jinhan 
542b353a43cSLin Jinhan static int rockchip_crypto_sha_update(struct udevice *dev,
543b353a43cSLin Jinhan 				      u32 *input, u32 len)
544b353a43cSLin Jinhan {
545b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
546086e8fa8SLin Jinhan 	int ret, i;
547086e8fa8SLin Jinhan 	u8 *p;
548b353a43cSLin Jinhan 
549b353a43cSLin Jinhan 	if (!len)
550b353a43cSLin Jinhan 		return -EINVAL;
551b353a43cSLin Jinhan 
552086e8fa8SLin Jinhan 	p = (u8 *)input;
553086e8fa8SLin Jinhan 
554086e8fa8SLin Jinhan 	for (i = 0; i < len / HASH_UPDATE_LIMIT; i++, p += HASH_UPDATE_LIMIT) {
555086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, HASH_UPDATE_LIMIT);
556086e8fa8SLin Jinhan 		if (ret)
557086e8fa8SLin Jinhan 			goto exit;
558086e8fa8SLin Jinhan 	}
559086e8fa8SLin Jinhan 
560086e8fa8SLin Jinhan 	if (len % HASH_UPDATE_LIMIT)
561086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, len % HASH_UPDATE_LIMIT);
562086e8fa8SLin Jinhan 
563086e8fa8SLin Jinhan exit:
564086e8fa8SLin Jinhan 	return ret;
565b353a43cSLin Jinhan }
566b353a43cSLin Jinhan 
567b353a43cSLin Jinhan static int rockchip_crypto_sha_final(struct udevice *dev,
568b353a43cSLin Jinhan 				     sha_context *ctx, u8 *output)
569b353a43cSLin Jinhan {
570b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
571b353a43cSLin Jinhan 	u32 nbits;
572c48f1acfSLin Jinhan 	int ret;
573b353a43cSLin Jinhan 
574b353a43cSLin Jinhan 	nbits = crypto_algo_nbits(ctx->algo);
575b353a43cSLin Jinhan 
576c48f1acfSLin Jinhan 	if (priv->length != ctx->length) {
577c48f1acfSLin Jinhan 		printf("total length(0x%08x) != init length(0x%08x)!\n",
578c48f1acfSLin Jinhan 		       priv->length, ctx->length);
579c48f1acfSLin Jinhan 		ret = -EIO;
580c48f1acfSLin Jinhan 		goto exit;
581c48f1acfSLin Jinhan 	}
582c48f1acfSLin Jinhan 
583c48f1acfSLin Jinhan 	ret = rk_hash_final(priv->hw_ctx, (u8 *)output, BITS2BYTE(nbits));
584c48f1acfSLin Jinhan 
585c48f1acfSLin Jinhan exit:
586c48f1acfSLin Jinhan 	hw_hash_clean_ctx(priv->hw_ctx);
587c48f1acfSLin Jinhan 	return ret;
588b353a43cSLin Jinhan }
589b353a43cSLin Jinhan 
59049a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
59149a2135eSLin Jinhan int rk_hmac_init(void *hw_ctx, u32 algo, u8 *key, u32 key_len)
59249a2135eSLin Jinhan {
59349a2135eSLin Jinhan 	u32 reg_ctrl = 0;
59449a2135eSLin Jinhan 	int ret;
59549a2135eSLin Jinhan 
59649a2135eSLin Jinhan 	if (!key || !key_len || key_len > 64)
59749a2135eSLin Jinhan 		return -EINVAL;
59849a2135eSLin Jinhan 
59949a2135eSLin Jinhan 	clear_key_regs();
60049a2135eSLin Jinhan 
60149a2135eSLin Jinhan 	write_key_reg(0, key, key_len);
60249a2135eSLin Jinhan 
60349a2135eSLin Jinhan 	ret = rk_hash_init(hw_ctx, algo);
60449a2135eSLin Jinhan 	if (ret)
60549a2135eSLin Jinhan 		return ret;
60649a2135eSLin Jinhan 
60749a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_HASH_CTL) | CRYPTO_HMAC_ENABLE;
60849a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
60949a2135eSLin Jinhan 
61049a2135eSLin Jinhan 	return ret;
61149a2135eSLin Jinhan }
61249a2135eSLin Jinhan 
61349a2135eSLin Jinhan static int rockchip_crypto_hmac_init(struct udevice *dev,
61449a2135eSLin Jinhan 				     sha_context *ctx, u8 *key, u32 key_len)
61549a2135eSLin Jinhan {
61649a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
61749a2135eSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
61849a2135eSLin Jinhan 
61949a2135eSLin Jinhan 	if (!ctx)
62049a2135eSLin Jinhan 		return -EINVAL;
62149a2135eSLin Jinhan 
62249a2135eSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
62349a2135eSLin Jinhan 
62449a2135eSLin Jinhan 	priv->length = 0;
62549a2135eSLin Jinhan 
62649a2135eSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
62749a2135eSLin Jinhan 						       priv, ctx->length,
62849a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
62949a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
63049a2135eSLin Jinhan 	if (!hash_ctx->hash_cache)
63149a2135eSLin Jinhan 		return -EFAULT;
63249a2135eSLin Jinhan 
63349a2135eSLin Jinhan 	return rk_hmac_init(priv->hw_ctx, ctx->algo, key, key_len);
63449a2135eSLin Jinhan }
63549a2135eSLin Jinhan 
63649a2135eSLin Jinhan static int rockchip_crypto_hmac_update(struct udevice *dev,
63749a2135eSLin Jinhan 				       u32 *input, u32 len)
63849a2135eSLin Jinhan {
63949a2135eSLin Jinhan 	return rockchip_crypto_sha_update(dev, input, len);
64049a2135eSLin Jinhan }
64149a2135eSLin Jinhan 
64249a2135eSLin Jinhan static int rockchip_crypto_hmac_final(struct udevice *dev,
64349a2135eSLin Jinhan 				      sha_context *ctx, u8 *output)
64449a2135eSLin Jinhan {
64549a2135eSLin Jinhan 	return rockchip_crypto_sha_final(dev, ctx, output);
64649a2135eSLin Jinhan }
64749a2135eSLin Jinhan 
64849a2135eSLin Jinhan #endif
64949a2135eSLin Jinhan 
65049a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
65149a2135eSLin Jinhan static u8 g_key_chn;
65249a2135eSLin Jinhan 
65349a2135eSLin Jinhan static const u32 rk_mode2bc_mode[RK_MODE_MAX] = {
65449a2135eSLin Jinhan 	[RK_MODE_ECB] = CRYPTO_BC_ECB,
65549a2135eSLin Jinhan 	[RK_MODE_CBC] = CRYPTO_BC_CBC,
65649a2135eSLin Jinhan 	[RK_MODE_CTS] = CRYPTO_BC_CTS,
65749a2135eSLin Jinhan 	[RK_MODE_CTR] = CRYPTO_BC_CTR,
65849a2135eSLin Jinhan 	[RK_MODE_CFB] = CRYPTO_BC_CFB,
65949a2135eSLin Jinhan 	[RK_MODE_OFB] = CRYPTO_BC_OFB,
66049a2135eSLin Jinhan 	[RK_MODE_XTS] = CRYPTO_BC_XTS,
661c3ce9937SLin Jinhan 	[RK_MODE_CCM] = CRYPTO_BC_CCM,
662c3ce9937SLin Jinhan 	[RK_MODE_GCM] = CRYPTO_BC_GCM,
663d9332f1cSLin Jinhan 	[RK_MODE_CMAC] = CRYPTO_BC_CMAC,
664d9332f1cSLin Jinhan 	[RK_MODE_CBC_MAC] = CRYPTO_BC_CBC_MAC,
66549a2135eSLin Jinhan };
66649a2135eSLin Jinhan 
667c3ce9937SLin Jinhan static inline void set_pc_len_reg(u32 chn, u64 pc_len)
668c3ce9937SLin Jinhan {
669c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_PC_LEN_0 + chn * 0x08;
670c3ce9937SLin Jinhan 
671c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
672c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
673c3ce9937SLin Jinhan }
674c3ce9937SLin Jinhan 
675c3ce9937SLin Jinhan static inline void set_aad_len_reg(u32 chn, u64 pc_len)
676c3ce9937SLin Jinhan {
677c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_AAD_LEN_0 + chn * 0x08;
678c3ce9937SLin Jinhan 
679c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
680c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
681c3ce9937SLin Jinhan }
682c3ce9937SLin Jinhan 
68349a2135eSLin Jinhan static inline bool is_des_mode(u32 rk_mode)
68449a2135eSLin Jinhan {
68549a2135eSLin Jinhan 	return (rk_mode == RK_MODE_ECB ||
68649a2135eSLin Jinhan 		rk_mode == RK_MODE_CBC ||
68749a2135eSLin Jinhan 		rk_mode == RK_MODE_CFB ||
68849a2135eSLin Jinhan 		rk_mode == RK_MODE_OFB);
68949a2135eSLin Jinhan }
69049a2135eSLin Jinhan 
6916b53126aSLin Jinhan static void dump_crypto_state(struct crypto_lli_desc *desc,
6926b53126aSLin Jinhan 			      u32 tmp, u32 expt_int,
6936b53126aSLin Jinhan 			      const u8 *in, const u8 *out,
6946b53126aSLin Jinhan 			      u32 len, int ret)
69549a2135eSLin Jinhan {
69649a2135eSLin Jinhan 	IMSG("%s\n", ret == -ETIME ? "timeout" : "dismatch");
69749a2135eSLin Jinhan 
69849a2135eSLin Jinhan 	IMSG("CRYPTO_DMA_INT_ST = %08x, expect_int = %08x\n",
69949a2135eSLin Jinhan 	     tmp, expt_int);
70049a2135eSLin Jinhan 	IMSG("data desc		= %p\n", desc);
70149a2135eSLin Jinhan 	IMSG("\taddr_in		= [%08x <=> %08x]\n",
70249a2135eSLin Jinhan 	     desc->src_addr, (u32)virt_to_phys(in));
70349a2135eSLin Jinhan 	IMSG("\taddr_out	= [%08x <=> %08x]\n",
70449a2135eSLin Jinhan 	     desc->dst_addr, (u32)virt_to_phys(out));
70549a2135eSLin Jinhan 	IMSG("\tsrc_len		= [%08x <=> %08x]\n",
70649a2135eSLin Jinhan 	     desc->src_len, (u32)len);
70749a2135eSLin Jinhan 	IMSG("\tdst_len		= %08x\n", desc->dst_len);
70849a2135eSLin Jinhan 	IMSG("\tdma_ctl		= %08x\n", desc->dma_ctrl);
70949a2135eSLin Jinhan 	IMSG("\tuser_define	= %08x\n", desc->user_define);
71049a2135eSLin Jinhan 
71149a2135eSLin Jinhan 	IMSG("\n\nDMA CRYPTO_DMA_LLI_ADDR status = %08x\n",
71249a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_ADDR));
71349a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_ST status = %08x\n",
71449a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_ST));
71549a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_STATE status = %08x\n",
71649a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_STATE));
71749a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_LLI_RADDR status = %08x\n",
71849a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_RADDR));
71949a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_SRC_RADDR status = %08x\n",
72049a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_SRC_RADDR));
72149a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_DST_RADDR status = %08x\n",
72249a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
72349a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_ST status = %08x\n",
72449a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_ST));
72549a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_STATE status = %08x\n",
72649a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_STATE));
72749a2135eSLin Jinhan 	IMSG("DMA CRYPTO_TAG_VALID status = %08x\n",
72849a2135eSLin Jinhan 	     crypto_read(CRYPTO_TAG_VALID));
72949a2135eSLin Jinhan 	IMSG("LOCKSTEP status = %08x\n\n",
73049a2135eSLin Jinhan 	     crypto_read(0x618));
73149a2135eSLin Jinhan 
73249a2135eSLin Jinhan 	IMSG("dst %dbyte not transferred\n",
73349a2135eSLin Jinhan 	     desc->dst_addr + desc->dst_len -
73449a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
73549a2135eSLin Jinhan }
73649a2135eSLin Jinhan 
737c3ce9937SLin Jinhan static int ccm128_set_iv_reg(u32 chn, const u8 *nonce, u32 nlen)
738c3ce9937SLin Jinhan {
739c3ce9937SLin Jinhan 	u8 iv_buf[AES_BLOCK_SIZE];
740c3ce9937SLin Jinhan 	u32 L;
741c3ce9937SLin Jinhan 
742c3ce9937SLin Jinhan 	memset(iv_buf, 0x00, sizeof(iv_buf));
743c3ce9937SLin Jinhan 
744c3ce9937SLin Jinhan 	L = 15 - nlen;
745c3ce9937SLin Jinhan 	iv_buf[0] = ((u8)(L - 1) & 7);
746c3ce9937SLin Jinhan 
747c3ce9937SLin Jinhan 	/* the L parameter */
748c3ce9937SLin Jinhan 	L = iv_buf[0] & 7;
749c3ce9937SLin Jinhan 
750c3ce9937SLin Jinhan 	/* nonce is too short */
751c3ce9937SLin Jinhan 	if (nlen < (14 - L))
752c3ce9937SLin Jinhan 		return -EINVAL;
753c3ce9937SLin Jinhan 
754c3ce9937SLin Jinhan 	/* clear aad flag */
755c3ce9937SLin Jinhan 	iv_buf[0] &= ~0x40;
756c3ce9937SLin Jinhan 	memcpy(&iv_buf[1], nonce, 14 - L);
757c3ce9937SLin Jinhan 
758c3ce9937SLin Jinhan 	set_iv_reg(chn, iv_buf, AES_BLOCK_SIZE);
759c3ce9937SLin Jinhan 
760c3ce9937SLin Jinhan 	return 0;
761c3ce9937SLin Jinhan }
762c3ce9937SLin Jinhan 
763c3ce9937SLin Jinhan static void ccm_aad_padding(u32 aad_len, u8 *padding, u32 *padding_size)
764c3ce9937SLin Jinhan {
765c3ce9937SLin Jinhan 	u32 i;
766c3ce9937SLin Jinhan 
7672db770efSLin Jinhan 	if (aad_len == 0) {
7682db770efSLin Jinhan 		*padding_size = 0;
7692db770efSLin Jinhan 		return;
7702db770efSLin Jinhan 	}
7712db770efSLin Jinhan 
772c3ce9937SLin Jinhan 	i = aad_len < (0x10000 - 0x100) ? 2 : 6;
773c3ce9937SLin Jinhan 
774c3ce9937SLin Jinhan 	if (i == 2) {
775c3ce9937SLin Jinhan 		padding[0] = (u8)(aad_len >> 8);
776c3ce9937SLin Jinhan 		padding[1] = (u8)aad_len;
777c3ce9937SLin Jinhan 	} else {
778c3ce9937SLin Jinhan 		padding[0] = 0xFF;
779c3ce9937SLin Jinhan 		padding[1] = 0xFE;
780c3ce9937SLin Jinhan 		padding[2] = (u8)(aad_len >> 24);
781c3ce9937SLin Jinhan 		padding[3] = (u8)(aad_len >> 16);
782c3ce9937SLin Jinhan 		padding[4] = (u8)(aad_len >> 8);
783c3ce9937SLin Jinhan 	}
784c3ce9937SLin Jinhan 
785c3ce9937SLin Jinhan 	*padding_size = i;
786c3ce9937SLin Jinhan }
787c3ce9937SLin Jinhan 
7882db770efSLin Jinhan static int ccm_compose_aad_iv(u8 *aad_iv, u32 data_len, u32 aad_len, u32 tag_size)
789c3ce9937SLin Jinhan {
790c3ce9937SLin Jinhan 	aad_iv[0] |= ((u8)(((tag_size - 2) / 2) & 7) << 3);
791c3ce9937SLin Jinhan 
792c3ce9937SLin Jinhan 	aad_iv[12] = (u8)(data_len >> 24);
793c3ce9937SLin Jinhan 	aad_iv[13] = (u8)(data_len >> 16);
794c3ce9937SLin Jinhan 	aad_iv[14] = (u8)(data_len >> 8);
795c3ce9937SLin Jinhan 	aad_iv[15] = (u8)data_len;
796c3ce9937SLin Jinhan 
7972db770efSLin Jinhan 	if (aad_len)
798c3ce9937SLin Jinhan 		aad_iv[0] |= 0x40;	//set aad flag
799c3ce9937SLin Jinhan 
800c3ce9937SLin Jinhan 	return 0;
801c3ce9937SLin Jinhan }
802c3ce9937SLin Jinhan 
80349a2135eSLin Jinhan static int hw_cipher_init(u32 chn, const u8 *key, const u8 *twk_key,
80449a2135eSLin Jinhan 			  u32 key_len, const u8 *iv, u32 iv_len,
80549a2135eSLin Jinhan 			  u32 algo, u32 mode, bool enc)
80649a2135eSLin Jinhan {
80749a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
80849a2135eSLin Jinhan 	u32 key_chn_sel = chn;
80949a2135eSLin Jinhan 	u32 reg_ctrl = 0;
81049a2135eSLin Jinhan 
81149a2135eSLin Jinhan 	IMSG("%s: key addr is %p, key_len is %d, iv addr is %p",
81249a2135eSLin Jinhan 	     __func__, key, key_len, iv);
81349a2135eSLin Jinhan 	if (rk_mode >= RK_MODE_MAX)
81449a2135eSLin Jinhan 		return -EINVAL;
81549a2135eSLin Jinhan 
81649a2135eSLin Jinhan 	switch (algo) {
81749a2135eSLin Jinhan 	case CRYPTO_DES:
81849a2135eSLin Jinhan 		if (key_len > DES_BLOCK_SIZE)
81949a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_TDES;
82049a2135eSLin Jinhan 		else
82149a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_DES;
82249a2135eSLin Jinhan 		break;
82349a2135eSLin Jinhan 	case CRYPTO_AES:
82449a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_AES;
82549a2135eSLin Jinhan 		break;
82649a2135eSLin Jinhan 	case CRYPTO_SM4:
82749a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_SM4;
82849a2135eSLin Jinhan 		break;
82949a2135eSLin Jinhan 	default:
83049a2135eSLin Jinhan 		return -EINVAL;
83149a2135eSLin Jinhan 	}
83249a2135eSLin Jinhan 
83349a2135eSLin Jinhan 	if (algo == CRYPTO_AES || algo == CRYPTO_SM4) {
83449a2135eSLin Jinhan 		switch (key_len) {
83549a2135eSLin Jinhan 		case AES_KEYSIZE_128:
83649a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_128_bit_key;
83749a2135eSLin Jinhan 			break;
83849a2135eSLin Jinhan 		case AES_KEYSIZE_192:
83949a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_192_bit_key;
84049a2135eSLin Jinhan 			break;
84149a2135eSLin Jinhan 		case AES_KEYSIZE_256:
84249a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_256_bit_key;
84349a2135eSLin Jinhan 			break;
84449a2135eSLin Jinhan 		default:
84549a2135eSLin Jinhan 			return -EINVAL;
84649a2135eSLin Jinhan 		}
84749a2135eSLin Jinhan 	}
84849a2135eSLin Jinhan 
84949a2135eSLin Jinhan 	reg_ctrl |= rk_mode2bc_mode[rk_mode];
85049a2135eSLin Jinhan 	if (!enc)
85149a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_DECRYPT;
85249a2135eSLin Jinhan 
85349a2135eSLin Jinhan 	/* write key data to reg */
85449a2135eSLin Jinhan 	write_key_reg(key_chn_sel, key, key_len);
85549a2135eSLin Jinhan 
85649a2135eSLin Jinhan 	/* write twk key for xts mode */
85749a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS)
85849a2135eSLin Jinhan 		write_key_reg(key_chn_sel + 4, twk_key, key_len);
85949a2135eSLin Jinhan 
86049a2135eSLin Jinhan 	/* set iv reg */
861c3ce9937SLin Jinhan 	if (rk_mode == RK_MODE_CCM)
862c3ce9937SLin Jinhan 		ccm128_set_iv_reg(chn, iv, iv_len);
863c3ce9937SLin Jinhan 	else
86449a2135eSLin Jinhan 		set_iv_reg(chn, iv, iv_len);
86549a2135eSLin Jinhan 
86649a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
86749a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
868fe0c4b19SLin Jinhan 	crypto_write(0, CRYPTO_DMA_INT_EN);
86949a2135eSLin Jinhan 
87049a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
87149a2135eSLin Jinhan 
87249a2135eSLin Jinhan 	return 0;
87349a2135eSLin Jinhan }
87449a2135eSLin Jinhan 
87549a2135eSLin Jinhan static int hw_cipher_crypt(const u8 *in, u8 *out, u64 len,
876c3ce9937SLin Jinhan 			   const u8 *aad, u32 aad_len,
877c3ce9937SLin Jinhan 			   u8 *tag, u32 tag_len, u32 mode)
87849a2135eSLin Jinhan {
879c3ce9937SLin Jinhan 	struct crypto_lli_desc *data_desc = NULL, *aad_desc = NULL;
880c3ce9937SLin Jinhan 	u8 *dma_in = NULL, *dma_out = NULL, *aad_tmp = NULL;
88149a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
88249a2135eSLin Jinhan 	u32 reg_ctrl = 0, tmp_len = 0;
88349a2135eSLin Jinhan 	u32 expt_int = 0, mask = 0;
88449a2135eSLin Jinhan 	u32 key_chn = g_key_chn;
88549a2135eSLin Jinhan 	u32 tmp, dst_len = 0;
88649a2135eSLin Jinhan 	int ret = -1;
88749a2135eSLin Jinhan 
88849a2135eSLin Jinhan 	if (rk_mode == RK_MODE_CTS && len <= AES_BLOCK_SIZE) {
88949a2135eSLin Jinhan 		printf("CTS mode length %u < 16Byte\n", (u32)len);
89049a2135eSLin Jinhan 		return -EINVAL;
89149a2135eSLin Jinhan 	}
89249a2135eSLin Jinhan 
89349a2135eSLin Jinhan 	tmp_len = (rk_mode == RK_MODE_CTR) ? ROUNDUP(len, AES_BLOCK_SIZE) : len;
89449a2135eSLin Jinhan 
89549a2135eSLin Jinhan 	data_desc = align_malloc(sizeof(*data_desc), LLI_ADDR_ALIGN_SIZE);
89649a2135eSLin Jinhan 	if (!data_desc)
89749a2135eSLin Jinhan 		goto exit;
89849a2135eSLin Jinhan 
89949a2135eSLin Jinhan 	if (IS_ALIGNED((ulong)in, DATA_ADDR_ALIGN_SIZE) && tmp_len == len)
90049a2135eSLin Jinhan 		dma_in = (void *)in;
90149a2135eSLin Jinhan 	else
90249a2135eSLin Jinhan 		dma_in = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
90349a2135eSLin Jinhan 	if (!dma_in)
90449a2135eSLin Jinhan 		goto exit;
90549a2135eSLin Jinhan 
90649a2135eSLin Jinhan 	if (out) {
90749a2135eSLin Jinhan 		if (IS_ALIGNED((ulong)out, DATA_ADDR_ALIGN_SIZE) &&
90849a2135eSLin Jinhan 		    tmp_len == len)
90949a2135eSLin Jinhan 			dma_out = out;
91049a2135eSLin Jinhan 		else
91149a2135eSLin Jinhan 			dma_out = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
91249a2135eSLin Jinhan 		if (!dma_out)
91349a2135eSLin Jinhan 			goto exit;
91449a2135eSLin Jinhan 		dst_len = tmp_len;
91549a2135eSLin Jinhan 	}
91649a2135eSLin Jinhan 
91749a2135eSLin Jinhan 	memset(data_desc, 0x00, sizeof(*data_desc));
91849a2135eSLin Jinhan 	if (dma_in != in)
91949a2135eSLin Jinhan 		memcpy(dma_in, in, len);
92049a2135eSLin Jinhan 
92149a2135eSLin Jinhan 	data_desc->src_addr    = (u32)virt_to_phys(dma_in);
92249a2135eSLin Jinhan 	data_desc->src_len     = tmp_len;
92349a2135eSLin Jinhan 	data_desc->dst_addr    = (u32)virt_to_phys(dma_out);
92449a2135eSLin Jinhan 	data_desc->dst_len     = dst_len;
925d9332f1cSLin Jinhan 	data_desc->dma_ctrl    = LLI_DMA_CTRL_LAST;
926d9332f1cSLin Jinhan 
927d9332f1cSLin Jinhan 	if (IS_MAC_MODE(rk_mode)) {
928d9332f1cSLin Jinhan 		expt_int = CRYPTO_LIST_DONE_INT_ST;
929d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_LIST_DONE;
930d9332f1cSLin Jinhan 	} else {
93149a2135eSLin Jinhan 		expt_int = CRYPTO_DST_ITEM_DONE_INT_ST;
932d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_DST_DONE;
933d9332f1cSLin Jinhan 	}
93449a2135eSLin Jinhan 
935ce7f4cd6SLin Jinhan 	data_desc->user_define = LLI_USER_CIPHER_START |
936afdbec36SLin Jinhan 				 LLI_USER_STRING_START |
937c3ce9937SLin Jinhan 				 LLI_USER_STRING_LAST |
938c3ce9937SLin Jinhan 				 (key_chn << 4);
939afdbec36SLin Jinhan 	crypto_write((u32)virt_to_phys(data_desc), CRYPTO_DMA_LLI_ADDR);
940afdbec36SLin Jinhan 
941afdbec36SLin Jinhan 	if (rk_mode == RK_MODE_CCM || rk_mode == RK_MODE_GCM) {
942afdbec36SLin Jinhan 		u32 aad_tmp_len = 0;
943c3ce9937SLin Jinhan 
944c3ce9937SLin Jinhan 		aad_desc = align_malloc(sizeof(*aad_desc), LLI_ADDR_ALIGN_SIZE);
945c3ce9937SLin Jinhan 		if (!aad_desc)
946c3ce9937SLin Jinhan 			goto exit;
947c3ce9937SLin Jinhan 
948c3ce9937SLin Jinhan 		memset(aad_desc, 0x00, sizeof(*aad_desc));
949c3ce9937SLin Jinhan 		aad_desc->next_addr = (u32)virt_to_phys(data_desc);
950ce7f4cd6SLin Jinhan 		aad_desc->user_define = LLI_USER_CIPHER_START |
951c3ce9937SLin Jinhan 					 LLI_USER_STRING_START |
952c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
953c3ce9937SLin Jinhan 					 LLI_USER_STRING_AAD |
954c3ce9937SLin Jinhan 					 (key_chn << 4);
955c3ce9937SLin Jinhan 
956c3ce9937SLin Jinhan 		if (rk_mode == RK_MODE_CCM) {
957c3ce9937SLin Jinhan 			u8 padding[AES_BLOCK_SIZE];
958c3ce9937SLin Jinhan 			u32 padding_size = 0;
959c3ce9937SLin Jinhan 
960c3ce9937SLin Jinhan 			memset(padding, 0x00, sizeof(padding));
961c3ce9937SLin Jinhan 			ccm_aad_padding(aad_len, padding, &padding_size);
962c3ce9937SLin Jinhan 
963c3ce9937SLin Jinhan 			aad_tmp_len = aad_len + AES_BLOCK_SIZE + padding_size;
964c3ce9937SLin Jinhan 			aad_tmp_len = ROUNDUP(aad_tmp_len, AES_BLOCK_SIZE);
965c3ce9937SLin Jinhan 			aad_tmp = align_malloc(aad_tmp_len,
966c3ce9937SLin Jinhan 					       DATA_ADDR_ALIGN_SIZE);
967c3ce9937SLin Jinhan 			if (!aad_tmp)
968c3ce9937SLin Jinhan 				goto exit;
969c3ce9937SLin Jinhan 
9702db770efSLin Jinhan 			/* clear last block */
971c3ce9937SLin Jinhan 			memset(aad_tmp + aad_tmp_len - AES_BLOCK_SIZE,
972c3ce9937SLin Jinhan 			       0x00, AES_BLOCK_SIZE);
9732db770efSLin Jinhan 
9742db770efSLin Jinhan 			/* read iv data from reg */
9752db770efSLin Jinhan 			get_iv_reg(key_chn, aad_tmp, AES_BLOCK_SIZE);
9762db770efSLin Jinhan 			ccm_compose_aad_iv(aad_tmp, tmp_len, aad_len, tag_len);
9772db770efSLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE, padding, padding_size);
9782db770efSLin Jinhan 
979c3ce9937SLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE + padding_size,
980c3ce9937SLin Jinhan 			       aad, aad_len);
981c3ce9937SLin Jinhan 		} else {
982c3ce9937SLin Jinhan 			aad_tmp_len = aad_len;
983b83c40a4SLin Jinhan 			if (IS_ALIGNED((ulong)aad, DATA_ADDR_ALIGN_SIZE)) {
984b83c40a4SLin Jinhan 				aad_tmp = (void *)aad;
985b83c40a4SLin Jinhan 			} else {
986c3ce9937SLin Jinhan 				aad_tmp = align_malloc(aad_tmp_len,
987c3ce9937SLin Jinhan 						       DATA_ADDR_ALIGN_SIZE);
988c3ce9937SLin Jinhan 				if (!aad_tmp)
989c3ce9937SLin Jinhan 					goto exit;
990c3ce9937SLin Jinhan 
991c3ce9937SLin Jinhan 				memcpy(aad_tmp, aad, aad_tmp_len);
992b83c40a4SLin Jinhan 			}
993b83c40a4SLin Jinhan 
994c3ce9937SLin Jinhan 			set_aad_len_reg(key_chn, aad_tmp_len);
995c3ce9937SLin Jinhan 			set_pc_len_reg(key_chn, tmp_len);
996c3ce9937SLin Jinhan 		}
997c3ce9937SLin Jinhan 
998c3ce9937SLin Jinhan 		aad_desc->src_addr = (u32)virt_to_phys(aad_tmp);
999c3ce9937SLin Jinhan 		aad_desc->src_len  = aad_tmp_len;
1000afdbec36SLin Jinhan 
1001afdbec36SLin Jinhan 		if (aad_tmp_len) {
1002afdbec36SLin Jinhan 			data_desc->user_define = LLI_USER_STRING_START |
1003afdbec36SLin Jinhan 						 LLI_USER_STRING_LAST |
1004afdbec36SLin Jinhan 						 (key_chn << 4);
1005c3ce9937SLin Jinhan 			crypto_write((u32)virt_to_phys(aad_desc), CRYPTO_DMA_LLI_ADDR);
1006c3ce9937SLin Jinhan 			cache_op_inner(DCACHE_AREA_CLEAN, aad_tmp, aad_tmp_len);
1007c3ce9937SLin Jinhan 			cache_op_inner(DCACHE_AREA_CLEAN, aad_desc, sizeof(*aad_desc));
1008afdbec36SLin Jinhan 		}
1009c3ce9937SLin Jinhan 	}
101049a2135eSLin Jinhan 
101149a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, data_desc, sizeof(*data_desc));
101249a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, dma_in, tmp_len);
101349a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_INVALIDATE, dma_out, tmp_len);
101449a2135eSLin Jinhan 
101549a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
101649a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
1017fe0c4b19SLin Jinhan 	crypto_write(0, CRYPTO_DMA_INT_EN);
101849a2135eSLin Jinhan 
101949a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_BC_CTL) | CRYPTO_BC_ENABLE;
102049a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
102149a2135eSLin Jinhan 	crypto_write(0x00010001, CRYPTO_DMA_CTL);//start
102249a2135eSLin Jinhan 
102349a2135eSLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
102449a2135eSLin Jinhan 
102549a2135eSLin Jinhan 	/* wait calc ok */
102649a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
102749a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
102849a2135eSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
102949a2135eSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
103049a2135eSLin Jinhan 
103149a2135eSLin Jinhan 	if ((tmp & mask) == expt_int) {
103249a2135eSLin Jinhan 		if (out && out != dma_out)
103349a2135eSLin Jinhan 			memcpy(out, dma_out, len);
1034d9332f1cSLin Jinhan 
1035d9332f1cSLin Jinhan 		if (IS_NEED_TAG(rk_mode)) {
1036d9332f1cSLin Jinhan 			ret = WAIT_TAG_VALID(key_chn, RK_CRYPTO_TIMEOUT);
1037d9332f1cSLin Jinhan 			get_tag_from_reg(key_chn, tag, AES_BLOCK_SIZE);
1038d9332f1cSLin Jinhan 		}
103949a2135eSLin Jinhan 	} else {
10406b53126aSLin Jinhan 		dump_crypto_state(data_desc, tmp, expt_int, in, out, len, ret);
104149a2135eSLin Jinhan 		ret = -1;
104249a2135eSLin Jinhan 	}
104349a2135eSLin Jinhan 
104449a2135eSLin Jinhan exit:
104549a2135eSLin Jinhan 	crypto_write(0xffff0000, CRYPTO_BC_CTL);//bc_ctl disable
104649a2135eSLin Jinhan 	align_free(data_desc);
1047c3ce9937SLin Jinhan 	align_free(aad_desc);
1048b83c40a4SLin Jinhan 	if (dma_in != in)
104949a2135eSLin Jinhan 		align_free(dma_in);
1050b83c40a4SLin Jinhan 	if (out && dma_out != out)
105149a2135eSLin Jinhan 		align_free(dma_out);
1052b83c40a4SLin Jinhan 	if (aad && aad != aad_tmp)
1053b83c40a4SLin Jinhan 		align_free(aad_tmp);
105449a2135eSLin Jinhan 
105549a2135eSLin Jinhan 	return ret;
105649a2135eSLin Jinhan }
105749a2135eSLin Jinhan 
105849a2135eSLin Jinhan static int hw_aes_init(u32 chn, const u8 *key, const u8 *twk_key, u32 key_len,
105949a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
106049a2135eSLin Jinhan {
106149a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
106249a2135eSLin Jinhan 
1063d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
1064d9332f1cSLin Jinhan 		return -EINVAL;
1065d9332f1cSLin Jinhan 
106649a2135eSLin Jinhan 	if (iv_len > AES_BLOCK_SIZE)
106749a2135eSLin Jinhan 		return -EINVAL;
106849a2135eSLin Jinhan 
1069d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
107049a2135eSLin Jinhan 		if (!iv || iv_len != AES_BLOCK_SIZE)
107149a2135eSLin Jinhan 			return -EINVAL;
107249a2135eSLin Jinhan 	} else {
107349a2135eSLin Jinhan 		iv_len = 0;
107449a2135eSLin Jinhan 	}
107549a2135eSLin Jinhan 
107649a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
107749a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_256)
107849a2135eSLin Jinhan 			return -EINVAL;
107949a2135eSLin Jinhan 
108049a2135eSLin Jinhan 		if (!key || !twk_key)
108149a2135eSLin Jinhan 			return -EINVAL;
108249a2135eSLin Jinhan 	} else {
108349a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 &&
108449a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_192 &&
108549a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_256)
108649a2135eSLin Jinhan 			return -EINVAL;
108749a2135eSLin Jinhan 	}
108849a2135eSLin Jinhan 
108949a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
109049a2135eSLin Jinhan 			      CRYPTO_AES, mode, enc);
109149a2135eSLin Jinhan }
109249a2135eSLin Jinhan 
109349a2135eSLin Jinhan static int hw_sm4_init(u32  chn, const u8 *key, const u8 *twk_key, u32 key_len,
109449a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
109549a2135eSLin Jinhan {
109649a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
109749a2135eSLin Jinhan 
1098d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
1099d9332f1cSLin Jinhan 		return -EINVAL;
1100d9332f1cSLin Jinhan 
110149a2135eSLin Jinhan 	if (iv_len > SM4_BLOCK_SIZE || key_len != SM4_KEYSIZE)
110249a2135eSLin Jinhan 		return -EINVAL;
110349a2135eSLin Jinhan 
1104d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
110549a2135eSLin Jinhan 		if (!iv || iv_len != SM4_BLOCK_SIZE)
110649a2135eSLin Jinhan 			return -EINVAL;
110749a2135eSLin Jinhan 	} else {
110849a2135eSLin Jinhan 		iv_len = 0;
110949a2135eSLin Jinhan 	}
111049a2135eSLin Jinhan 
111149a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
111249a2135eSLin Jinhan 		if (!key || !twk_key)
111349a2135eSLin Jinhan 			return -EINVAL;
111449a2135eSLin Jinhan 	}
111549a2135eSLin Jinhan 
111649a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
111749a2135eSLin Jinhan 			      CRYPTO_SM4, mode, enc);
111849a2135eSLin Jinhan }
111949a2135eSLin Jinhan 
112049a2135eSLin Jinhan int rk_crypto_des(struct udevice *dev, u32 mode, const u8 *key, u32 key_len,
112149a2135eSLin Jinhan 		  const u8 *iv, const u8 *in, u8 *out, u32 len, bool enc)
112249a2135eSLin Jinhan {
112349a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
112449a2135eSLin Jinhan 	u8 tmp_key[24];
112549a2135eSLin Jinhan 	int ret;
112649a2135eSLin Jinhan 
112749a2135eSLin Jinhan 	if (!is_des_mode(rk_mode))
112849a2135eSLin Jinhan 		return -EINVAL;
112949a2135eSLin Jinhan 
113049a2135eSLin Jinhan 	if (key_len == DES_BLOCK_SIZE || key_len == 3 * DES_BLOCK_SIZE) {
113149a2135eSLin Jinhan 		memcpy(tmp_key, key, key_len);
113249a2135eSLin Jinhan 	} else if (key_len == 2 * DES_BLOCK_SIZE) {
113349a2135eSLin Jinhan 		memcpy(tmp_key, key, 16);
113449a2135eSLin Jinhan 		memcpy(tmp_key + 16, key, 8);
113549a2135eSLin Jinhan 		key_len = 3 * DES_BLOCK_SIZE;
113649a2135eSLin Jinhan 	} else {
113749a2135eSLin Jinhan 		return -EINVAL;
113849a2135eSLin Jinhan 	}
113949a2135eSLin Jinhan 
114049a2135eSLin Jinhan 	ret = hw_cipher_init(0, tmp_key, NULL, key_len, iv, DES_BLOCK_SIZE,
114149a2135eSLin Jinhan 			     CRYPTO_DES, mode, enc);
114249a2135eSLin Jinhan 	if (ret)
114349a2135eSLin Jinhan 		goto exit;
114449a2135eSLin Jinhan 
114549a2135eSLin Jinhan 	ret = hw_cipher_crypt(in, out, len, NULL, 0,
114649a2135eSLin Jinhan 			      NULL, 0, mode);
114749a2135eSLin Jinhan 
114849a2135eSLin Jinhan exit:
114949a2135eSLin Jinhan 	return ret;
115049a2135eSLin Jinhan }
115149a2135eSLin Jinhan 
115249a2135eSLin Jinhan int rk_crypto_aes(struct udevice *dev, u32 mode,
115349a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
115449a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
115549a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
115649a2135eSLin Jinhan {
115749a2135eSLin Jinhan 	int ret;
115849a2135eSLin Jinhan 
115949a2135eSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
116049a2135eSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
116149a2135eSLin Jinhan 	if (key_len == AES_KEYSIZE_192)
116249a2135eSLin Jinhan 		return -EINVAL;
116349a2135eSLin Jinhan #endif
116449a2135eSLin Jinhan 
116549a2135eSLin Jinhan 	ret = hw_aes_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
116649a2135eSLin Jinhan 	if (ret)
116749a2135eSLin Jinhan 		return ret;
116849a2135eSLin Jinhan 
116949a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0,
117049a2135eSLin Jinhan 			       NULL, 0, mode);
117149a2135eSLin Jinhan }
117249a2135eSLin Jinhan 
117349a2135eSLin Jinhan int rk_crypto_sm4(struct udevice *dev, u32 mode,
117449a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
117549a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
117649a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
117749a2135eSLin Jinhan {
117849a2135eSLin Jinhan 	int ret;
117949a2135eSLin Jinhan 
118049a2135eSLin Jinhan 	ret = hw_sm4_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
118149a2135eSLin Jinhan 	if (ret)
118249a2135eSLin Jinhan 		return ret;
118349a2135eSLin Jinhan 
118449a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0, NULL, 0, mode);
118549a2135eSLin Jinhan }
118649a2135eSLin Jinhan 
118749a2135eSLin Jinhan int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx,
118849a2135eSLin Jinhan 			   const u8 *in, u8 *out, u32 len, bool enc)
118949a2135eSLin Jinhan {
119049a2135eSLin Jinhan 	switch (ctx->algo) {
119149a2135eSLin Jinhan 	case CRYPTO_DES:
119249a2135eSLin Jinhan 		return rk_crypto_des(dev, ctx->mode, ctx->key, ctx->key_len,
119349a2135eSLin Jinhan 				     ctx->iv, in, out, len, enc);
119449a2135eSLin Jinhan 	case CRYPTO_AES:
119549a2135eSLin Jinhan 		return rk_crypto_aes(dev, ctx->mode,
119649a2135eSLin Jinhan 				     ctx->key, ctx->twk_key, ctx->key_len,
119749a2135eSLin Jinhan 				     ctx->iv, ctx->iv_len, in, out, len, enc);
119849a2135eSLin Jinhan 	case CRYPTO_SM4:
119949a2135eSLin Jinhan 		return rk_crypto_sm4(dev, ctx->mode,
120049a2135eSLin Jinhan 				     ctx->key, ctx->twk_key, ctx->key_len,
120149a2135eSLin Jinhan 				     ctx->iv, ctx->iv_len, in, out, len, enc);
120249a2135eSLin Jinhan 	default:
120349a2135eSLin Jinhan 		return -EINVAL;
120449a2135eSLin Jinhan 	}
120549a2135eSLin Jinhan }
1206d9332f1cSLin Jinhan 
1207d9332f1cSLin Jinhan int rk_crypto_mac(struct udevice *dev, u32 algo, u32 mode,
1208d9332f1cSLin Jinhan 		  const u8 *key, u32 key_len,
1209d9332f1cSLin Jinhan 		  const u8 *in, u32 len, u8 *tag)
1210d9332f1cSLin Jinhan {
1211d9332f1cSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1212d9332f1cSLin Jinhan 	int ret;
1213d9332f1cSLin Jinhan 
1214d9332f1cSLin Jinhan 	if (!IS_MAC_MODE(rk_mode))
1215d9332f1cSLin Jinhan 		return -EINVAL;
1216d9332f1cSLin Jinhan 
1217d9332f1cSLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1218d9332f1cSLin Jinhan 		return -EINVAL;
1219d9332f1cSLin Jinhan 
1220d9332f1cSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1221d9332f1cSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1222d9332f1cSLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1223d9332f1cSLin Jinhan 		return -EINVAL;
1224d9332f1cSLin Jinhan #endif
1225d9332f1cSLin Jinhan 
1226d9332f1cSLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, NULL, 0,
1227d9332f1cSLin Jinhan 			     algo, mode, true);
1228d9332f1cSLin Jinhan 	if (ret)
1229d9332f1cSLin Jinhan 		return ret;
1230d9332f1cSLin Jinhan 
1231d9332f1cSLin Jinhan 	return hw_cipher_crypt(in, NULL, len, NULL, 0,
1232d9332f1cSLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1233d9332f1cSLin Jinhan }
1234d9332f1cSLin Jinhan 
1235d9332f1cSLin Jinhan int rockchip_crypto_mac(struct udevice *dev, cipher_context *ctx,
1236d9332f1cSLin Jinhan 			const u8 *in, u32 len, u8 *tag)
1237d9332f1cSLin Jinhan {
1238d9332f1cSLin Jinhan 	return rk_crypto_mac(dev, ctx->algo, ctx->mode,
1239d9332f1cSLin Jinhan 			     ctx->key, ctx->key_len, in, len, tag);
1240d9332f1cSLin Jinhan }
1241d9332f1cSLin Jinhan 
1242c3ce9937SLin Jinhan int rk_crypto_ae(struct udevice *dev, u32 algo, u32 mode,
1243c3ce9937SLin Jinhan 		 const u8 *key, u32 key_len, const u8 *nonce, u32 nonce_len,
1244c3ce9937SLin Jinhan 		 const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1245c3ce9937SLin Jinhan 		 u8 *out, u8 *tag)
1246c3ce9937SLin Jinhan {
1247c3ce9937SLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1248c3ce9937SLin Jinhan 	int ret;
1249c3ce9937SLin Jinhan 
1250c3ce9937SLin Jinhan 	if (!IS_AE_MODE(rk_mode))
1251c3ce9937SLin Jinhan 		return -EINVAL;
1252c3ce9937SLin Jinhan 
1253afdbec36SLin Jinhan 	if (len == 0)
1254afdbec36SLin Jinhan 		return -EINVAL;
1255afdbec36SLin Jinhan 
1256c3ce9937SLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1257c3ce9937SLin Jinhan 		return -EINVAL;
1258c3ce9937SLin Jinhan 
1259c3ce9937SLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1260c3ce9937SLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1261c3ce9937SLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1262c3ce9937SLin Jinhan 		return -EINVAL;
1263c3ce9937SLin Jinhan #endif
1264c3ce9937SLin Jinhan 
1265c3ce9937SLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, nonce, nonce_len,
1266c3ce9937SLin Jinhan 			     algo, mode, true);
1267c3ce9937SLin Jinhan 	if (ret)
1268c3ce9937SLin Jinhan 		return ret;
1269c3ce9937SLin Jinhan 
1270c3ce9937SLin Jinhan 	return hw_cipher_crypt(in, out, len, aad, aad_len,
1271c3ce9937SLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1272c3ce9937SLin Jinhan }
1273c3ce9937SLin Jinhan 
1274c3ce9937SLin Jinhan int rockchip_crypto_ae(struct udevice *dev, cipher_context *ctx,
1275c3ce9937SLin Jinhan 		       const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1276c3ce9937SLin Jinhan 		       u8 *out, u8 *tag)
1277c3ce9937SLin Jinhan 
1278c3ce9937SLin Jinhan {
1279c3ce9937SLin Jinhan 	return rk_crypto_ae(dev, ctx->algo, ctx->mode, ctx->key, ctx->key_len,
1280c3ce9937SLin Jinhan 			    ctx->iv, ctx->iv_len, in, len,
1281c3ce9937SLin Jinhan 			    aad, aad_len, out, tag);
1282c3ce9937SLin Jinhan }
1283c3ce9937SLin Jinhan 
128449a2135eSLin Jinhan #endif
128549a2135eSLin Jinhan 
1286864e581cSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1287b353a43cSLin Jinhan static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx,
1288b353a43cSLin Jinhan 				      u8 *sign, u8 *output)
1289b353a43cSLin Jinhan {
1290b353a43cSLin Jinhan 	struct mpa_num *mpa_m = NULL, *mpa_e = NULL, *mpa_n = NULL;
1291b353a43cSLin Jinhan 	struct mpa_num *mpa_c = NULL, *mpa_result = NULL;
1292b353a43cSLin Jinhan 	u32 n_bits, n_words;
1293b353a43cSLin Jinhan 	int ret;
1294b353a43cSLin Jinhan 
1295b353a43cSLin Jinhan 	if (!ctx)
1296b353a43cSLin Jinhan 		return -EINVAL;
1297b353a43cSLin Jinhan 
1298b353a43cSLin Jinhan 	if (ctx->algo != CRYPTO_RSA512 &&
1299b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA1024 &&
1300b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA2048 &&
1301b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA3072 &&
1302b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA4096)
1303b353a43cSLin Jinhan 		return -EINVAL;
1304b353a43cSLin Jinhan 
1305b353a43cSLin Jinhan 	n_bits = crypto_algo_nbits(ctx->algo);
1306b353a43cSLin Jinhan 	n_words = BITS2WORD(n_bits);
1307b353a43cSLin Jinhan 
1308549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_m, sign, n_words);
1309b353a43cSLin Jinhan 	if (ret)
1310b353a43cSLin Jinhan 		goto exit;
1311b353a43cSLin Jinhan 
1312549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_e, ctx->e, n_words);
1313549a74f7SLin Jinhan 	if (ret)
1314549a74f7SLin Jinhan 		goto exit;
1315b353a43cSLin Jinhan 
1316549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_n, ctx->n, n_words);
1317549a74f7SLin Jinhan 	if (ret)
1318549a74f7SLin Jinhan 		goto exit;
1319549a74f7SLin Jinhan 
1320549a74f7SLin Jinhan 	if (ctx->c) {
1321549a74f7SLin Jinhan 		ret = rk_mpa_alloc(&mpa_c, ctx->c, n_words);
1322549a74f7SLin Jinhan 		if (ret)
1323549a74f7SLin Jinhan 			goto exit;
1324549a74f7SLin Jinhan 	}
1325549a74f7SLin Jinhan 
1326549a74f7SLin Jinhan 	ret = rk_mpa_alloc(&mpa_result, NULL, n_words);
1327549a74f7SLin Jinhan 	if (ret)
1328549a74f7SLin Jinhan 		goto exit;
1329b353a43cSLin Jinhan 
1330b353a43cSLin Jinhan 	ret = rk_exptmod_np(mpa_m, mpa_e, mpa_n, mpa_c, mpa_result);
1331b353a43cSLin Jinhan 	if (!ret)
1332549a74f7SLin Jinhan 		memcpy(output, mpa_result->d, BITS2BYTE(n_bits));
1333b353a43cSLin Jinhan 
1334b353a43cSLin Jinhan exit:
1335b353a43cSLin Jinhan 	rk_mpa_free(&mpa_m);
1336b353a43cSLin Jinhan 	rk_mpa_free(&mpa_e);
1337b353a43cSLin Jinhan 	rk_mpa_free(&mpa_n);
1338b353a43cSLin Jinhan 	rk_mpa_free(&mpa_c);
1339b353a43cSLin Jinhan 	rk_mpa_free(&mpa_result);
1340b353a43cSLin Jinhan 
1341b353a43cSLin Jinhan 	return ret;
1342b353a43cSLin Jinhan }
1343864e581cSLin Jinhan #endif
1344b353a43cSLin Jinhan 
1345b353a43cSLin Jinhan static const struct dm_crypto_ops rockchip_crypto_ops = {
1346b353a43cSLin Jinhan 	.capability   = rockchip_crypto_capability,
1347b353a43cSLin Jinhan 	.sha_init     = rockchip_crypto_sha_init,
1348b353a43cSLin Jinhan 	.sha_update   = rockchip_crypto_sha_update,
1349b353a43cSLin Jinhan 	.sha_final    = rockchip_crypto_sha_final,
135049a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1351b353a43cSLin Jinhan 	.rsa_verify   = rockchip_crypto_rsa_verify,
135249a2135eSLin Jinhan #endif
135349a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
135449a2135eSLin Jinhan 	.hmac_init    = rockchip_crypto_hmac_init,
135549a2135eSLin Jinhan 	.hmac_update  = rockchip_crypto_hmac_update,
135649a2135eSLin Jinhan 	.hmac_final   = rockchip_crypto_hmac_final,
135749a2135eSLin Jinhan #endif
135849a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
135949a2135eSLin Jinhan 	.cipher_crypt = rockchip_crypto_cipher,
1360d9332f1cSLin Jinhan 	.cipher_mac = rockchip_crypto_mac,
1361c3ce9937SLin Jinhan 	.cipher_ae  = rockchip_crypto_ae,
136249a2135eSLin Jinhan #endif
1363b353a43cSLin Jinhan };
1364b353a43cSLin Jinhan 
1365b353a43cSLin Jinhan /*
1366b353a43cSLin Jinhan  * Only use "clocks" to parse crypto clock id and use rockchip_get_clk().
1367b353a43cSLin Jinhan  * Because we always add crypto node in U-Boot dts, when kernel dtb enabled :
1368b353a43cSLin Jinhan  *
1369b353a43cSLin Jinhan  *   1. There is cru phandle mismatch between U-Boot and kernel dtb;
1370b353a43cSLin Jinhan  *   2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property;
1371b353a43cSLin Jinhan  */
1372b353a43cSLin Jinhan static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev)
1373b353a43cSLin Jinhan {
1374b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1375b353a43cSLin Jinhan 	int len, ret = -EINVAL;
1376b353a43cSLin Jinhan 
1377a24b2aebSLin Jinhan 	memset(priv, 0x00, sizeof(*priv));
1378a24b2aebSLin Jinhan 
1379a24b2aebSLin Jinhan 	priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev);
1380a24b2aebSLin Jinhan 	if (priv->reg == FDT_ADDR_T_NONE)
1381a24b2aebSLin Jinhan 		return -EINVAL;
1382a24b2aebSLin Jinhan 
1383a24b2aebSLin Jinhan 	crypto_base = priv->reg;
1384a24b2aebSLin Jinhan 
1385a24b2aebSLin Jinhan 	/* if there is no clocks in dts, just skip it */
1386b353a43cSLin Jinhan 	if (!dev_read_prop(dev, "clocks", &len)) {
1387b353a43cSLin Jinhan 		printf("Can't find \"clocks\" property\n");
1388a24b2aebSLin Jinhan 		return 0;
1389b353a43cSLin Jinhan 	}
1390b353a43cSLin Jinhan 
1391b353a43cSLin Jinhan 	memset(priv, 0x00, sizeof(*priv));
1392b353a43cSLin Jinhan 	priv->clocks = malloc(len);
1393b353a43cSLin Jinhan 	if (!priv->clocks)
1394b353a43cSLin Jinhan 		return -ENOMEM;
1395b353a43cSLin Jinhan 
1396*da703fb5SLin Jinhan 	priv->nclocks = len / (2 * sizeof(u32));
1397b353a43cSLin Jinhan 	if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks,
1398b353a43cSLin Jinhan 			       priv->nclocks)) {
1399b353a43cSLin Jinhan 		printf("Can't read \"clocks\" property\n");
1400b353a43cSLin Jinhan 		ret = -EINVAL;
1401b353a43cSLin Jinhan 		goto exit;
1402b353a43cSLin Jinhan 	}
1403b353a43cSLin Jinhan 
1404*da703fb5SLin Jinhan 	if (dev_read_prop(dev, "clock-frequency", &len)) {
1405b353a43cSLin Jinhan 		priv->frequencies = malloc(len);
1406b353a43cSLin Jinhan 		if (!priv->frequencies) {
1407b353a43cSLin Jinhan 			ret = -ENOMEM;
1408b353a43cSLin Jinhan 			goto exit;
1409b353a43cSLin Jinhan 		}
1410b353a43cSLin Jinhan 
1411*da703fb5SLin Jinhan 		priv->freq_nclocks = len / (2 * sizeof(u32));
1412b353a43cSLin Jinhan 		if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies,
1413*da703fb5SLin Jinhan 				       priv->freq_nclocks)) {
1414b353a43cSLin Jinhan 			printf("Can't read \"clock-frequency\" property\n");
1415b353a43cSLin Jinhan 			ret = -EINVAL;
1416b353a43cSLin Jinhan 			goto exit;
1417b353a43cSLin Jinhan 		}
1418*da703fb5SLin Jinhan 	}
1419b353a43cSLin Jinhan 
1420b353a43cSLin Jinhan 	return 0;
1421b353a43cSLin Jinhan exit:
1422b353a43cSLin Jinhan 	if (priv->clocks)
1423b353a43cSLin Jinhan 		free(priv->clocks);
1424b353a43cSLin Jinhan 
1425b353a43cSLin Jinhan 	if (priv->frequencies)
1426b353a43cSLin Jinhan 		free(priv->frequencies);
1427b353a43cSLin Jinhan 
1428b353a43cSLin Jinhan 	return ret;
1429b353a43cSLin Jinhan }
1430b353a43cSLin Jinhan 
14316cebff12SJoseph Chen static int rk_crypto_set_clk(struct udevice *dev)
1432b353a43cSLin Jinhan {
14336cebff12SJoseph Chen 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
14346cebff12SJoseph Chen 	struct clk clk;
1435a24b2aebSLin Jinhan 	int i, ret;
1436b353a43cSLin Jinhan 
1437*da703fb5SLin Jinhan 	ret = clk_set_defaults(dev);
1438*da703fb5SLin Jinhan 	if (!ret)
1439*da703fb5SLin Jinhan 		return ret;
1440*da703fb5SLin Jinhan 
1441*da703fb5SLin Jinhan 	if (priv->freq_nclocks == 0)
1442a24b2aebSLin Jinhan 		return 0;
144349a2135eSLin Jinhan 
1444*da703fb5SLin Jinhan 	for (i = 0; i < priv->freq_nclocks; i++) {
14456cebff12SJoseph Chen 		ret = clk_get_by_index(dev, i, &clk);
14466cebff12SJoseph Chen 		if (ret < 0) {
14476cebff12SJoseph Chen 			printf("Failed to get clk index %d, ret=%d\n", i, ret);
1448b353a43cSLin Jinhan 			return ret;
1449b353a43cSLin Jinhan 		}
14506cebff12SJoseph Chen 		ret = clk_set_rate(&clk, priv->frequencies[i]);
1451b353a43cSLin Jinhan 		if (ret < 0) {
1452b353a43cSLin Jinhan 			printf("%s: Failed to set clk(%ld): ret=%d\n",
14536cebff12SJoseph Chen 			       __func__, clk.id, ret);
1454b353a43cSLin Jinhan 			return ret;
1455b353a43cSLin Jinhan 		}
1456b353a43cSLin Jinhan 	}
1457b353a43cSLin Jinhan 
1458a24b2aebSLin Jinhan 	return 0;
1459a24b2aebSLin Jinhan }
1460a24b2aebSLin Jinhan 
1461a24b2aebSLin Jinhan static int rockchip_crypto_probe(struct udevice *dev)
1462a24b2aebSLin Jinhan {
1463a24b2aebSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1464a24b2aebSLin Jinhan 	struct rk_crypto_soc_data *sdata;
1465a24b2aebSLin Jinhan 	int ret = 0;
1466a24b2aebSLin Jinhan 
1467a24b2aebSLin Jinhan 	sdata = (struct rk_crypto_soc_data *)dev_get_driver_data(dev);
146858432b6fSLin Jinhan 
146958432b6fSLin Jinhan 	if (sdata->dynamic_cap)
147058432b6fSLin Jinhan 		sdata->capability = sdata->dynamic_cap();
147158432b6fSLin Jinhan 
1472a24b2aebSLin Jinhan 	priv->soc_data = sdata;
1473a24b2aebSLin Jinhan 
1474a24b2aebSLin Jinhan 	priv->hw_ctx = memalign(LLI_ADDR_ALIGN_SIZE,
1475a24b2aebSLin Jinhan 				sizeof(struct rk_hash_ctx));
1476a24b2aebSLin Jinhan 	if (!priv->hw_ctx)
1477a24b2aebSLin Jinhan 		return -ENOMEM;
1478a24b2aebSLin Jinhan 
14796cebff12SJoseph Chen 	ret = rk_crypto_set_clk(dev);
1480a24b2aebSLin Jinhan 	if (ret)
1481a24b2aebSLin Jinhan 		return ret;
1482a24b2aebSLin Jinhan 
1483b353a43cSLin Jinhan 	hw_crypto_reset();
1484b353a43cSLin Jinhan 
1485b353a43cSLin Jinhan 	return 0;
1486b353a43cSLin Jinhan }
1487b353a43cSLin Jinhan 
148849a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base = {
148949a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
149049a2135eSLin Jinhan 		      CRYPTO_SHA1 |
149149a2135eSLin Jinhan 		      CRYPTO_SHA256 |
149249a2135eSLin Jinhan 		      CRYPTO_SHA512 |
149349a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
149449a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
149549a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
149649a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
149749a2135eSLin Jinhan 		      CRYPTO_RSA512 |
149849a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
149949a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
150049a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
150149a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
150249a2135eSLin Jinhan 		      CRYPTO_DES |
150349a2135eSLin Jinhan 		      CRYPTO_AES,
150449a2135eSLin Jinhan };
150549a2135eSLin Jinhan 
150649a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base_sm = {
150749a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
150849a2135eSLin Jinhan 		      CRYPTO_SHA1 |
150949a2135eSLin Jinhan 		      CRYPTO_SHA256 |
151049a2135eSLin Jinhan 		      CRYPTO_SHA512 |
151149a2135eSLin Jinhan 		      CRYPTO_SM3 |
151249a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
151349a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
151449a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
151549a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
151649a2135eSLin Jinhan 		      CRYPTO_HMAC_SM3 |
151749a2135eSLin Jinhan 		      CRYPTO_RSA512 |
151849a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
151949a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
152049a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
152149a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
152249a2135eSLin Jinhan 		      CRYPTO_DES |
152349a2135eSLin Jinhan 		      CRYPTO_AES |
152449a2135eSLin Jinhan 		      CRYPTO_SM4,
152549a2135eSLin Jinhan };
152649a2135eSLin Jinhan 
152749a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_rk1808 = {
152849a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
152949a2135eSLin Jinhan 		      CRYPTO_SHA1 |
153049a2135eSLin Jinhan 		      CRYPTO_SHA256 |
153149a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
153249a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
153349a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
153449a2135eSLin Jinhan 		      CRYPTO_RSA512 |
153549a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
153649a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
153749a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
153849a2135eSLin Jinhan 		      CRYPTO_RSA4096,
153949a2135eSLin Jinhan };
154049a2135eSLin Jinhan 
154158432b6fSLin Jinhan static const struct rk_crypto_soc_data soc_data_cryptov3 = {
154258432b6fSLin Jinhan 	.capability  = 0,
154358432b6fSLin Jinhan 	.dynamic_cap = crypto_v3_dynamic_cap,
154458432b6fSLin Jinhan };
154558432b6fSLin Jinhan 
1546b353a43cSLin Jinhan static const struct udevice_id rockchip_crypto_ids[] = {
154749a2135eSLin Jinhan 	{
154849a2135eSLin Jinhan 		.compatible = "rockchip,px30-crypto",
154949a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
155049a2135eSLin Jinhan 	},
155149a2135eSLin Jinhan 	{
155249a2135eSLin Jinhan 		.compatible = "rockchip,rk1808-crypto",
155349a2135eSLin Jinhan 		.data = (ulong)&soc_data_rk1808
155449a2135eSLin Jinhan 	},
155549a2135eSLin Jinhan 	{
155649a2135eSLin Jinhan 		.compatible = "rockchip,rk3308-crypto",
155749a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
155849a2135eSLin Jinhan 	},
155949a2135eSLin Jinhan 	{
156049a2135eSLin Jinhan 		.compatible = "rockchip,rv1126-crypto",
156149a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
156249a2135eSLin Jinhan 	},
156349a2135eSLin Jinhan 	{
156449a2135eSLin Jinhan 		.compatible = "rockchip,rk3568-crypto",
156549a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
156649a2135eSLin Jinhan 	},
15675b3e3895SLin Jinhan 	{
15685b3e3895SLin Jinhan 		.compatible = "rockchip,rk3588-crypto",
15695b3e3895SLin Jinhan 		.data = (ulong)&soc_data_base_sm
15705b3e3895SLin Jinhan 	},
157158432b6fSLin Jinhan 	{
1572f93f9077SLin Jinhan 		.compatible = "rockchip,crypto-v3",
157358432b6fSLin Jinhan 		.data = (ulong)&soc_data_cryptov3
157458432b6fSLin Jinhan 	},
15752bcebb1aSLin Jinhan 	{
15762bcebb1aSLin Jinhan 		.compatible = "rockchip,crypto-v4",
15772bcebb1aSLin Jinhan 		.data = (ulong)&soc_data_cryptov3 /* reuse crypto v3 config */
15782bcebb1aSLin Jinhan 	},
1579b353a43cSLin Jinhan 	{ }
1580b353a43cSLin Jinhan };
1581b353a43cSLin Jinhan 
1582b353a43cSLin Jinhan U_BOOT_DRIVER(rockchip_crypto_v2) = {
1583b353a43cSLin Jinhan 	.name		= "rockchip_crypto_v2",
1584b353a43cSLin Jinhan 	.id		= UCLASS_CRYPTO,
1585b353a43cSLin Jinhan 	.of_match	= rockchip_crypto_ids,
1586b353a43cSLin Jinhan 	.ops		= &rockchip_crypto_ops,
1587b353a43cSLin Jinhan 	.probe		= rockchip_crypto_probe,
1588b353a43cSLin Jinhan 	.ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata,
1589b353a43cSLin Jinhan 	.priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv),
1590b353a43cSLin Jinhan };
1591