xref: /rk3399_rockchip-uboot/drivers/crypto/rockchip/crypto_v2.c (revision a24b2aebd37cd898e711ff941ec0b3f4d6e84e36)
1b353a43cSLin Jinhan // SPDX-License-Identifier: GPL-2.0
2b353a43cSLin Jinhan /*
3b353a43cSLin Jinhan  * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4b353a43cSLin Jinhan  */
5b353a43cSLin Jinhan 
6b353a43cSLin Jinhan #include <common.h>
7b353a43cSLin Jinhan #include <clk.h>
8b353a43cSLin Jinhan #include <crypto.h>
9b353a43cSLin Jinhan #include <dm.h>
10b353a43cSLin Jinhan #include <asm/io.h>
11b353a43cSLin Jinhan #include <asm/arch/hardware.h>
12b353a43cSLin Jinhan #include <asm/arch/clock.h>
13c48f1acfSLin Jinhan #include <rockchip/crypto_hash_cache.h>
14b353a43cSLin Jinhan #include <rockchip/crypto_v2.h>
15b353a43cSLin Jinhan #include <rockchip/crypto_v2_pka.h>
16b353a43cSLin Jinhan 
17c48f1acfSLin Jinhan #define	RK_HASH_CTX_MAGIC		0x1A1A1A1A
18c48f1acfSLin Jinhan 
1949a2135eSLin Jinhan #ifdef DEBUG
2049a2135eSLin Jinhan #define IMSG(format, ...) printf("[%s, %05d]-trace: " format "\n", \
2149a2135eSLin Jinhan 				 __func__, __LINE__, ##__VA_ARGS__)
2249a2135eSLin Jinhan #else
2349a2135eSLin Jinhan #define IMSG(format, ...)
2449a2135eSLin Jinhan #endif
25c48f1acfSLin Jinhan 
26c48f1acfSLin Jinhan struct crypto_lli_desc {
27c48f1acfSLin Jinhan 	u32 src_addr;
28c48f1acfSLin Jinhan 	u32 src_len;
29c48f1acfSLin Jinhan 	u32 dst_addr;
30c48f1acfSLin Jinhan 	u32 dst_len;
31c48f1acfSLin Jinhan 	u32 user_define;
32c48f1acfSLin Jinhan 	u32 reserve;
33c48f1acfSLin Jinhan 	u32 dma_ctrl;
34c48f1acfSLin Jinhan 	u32 next_addr;
35c48f1acfSLin Jinhan };
36c48f1acfSLin Jinhan 
37c48f1acfSLin Jinhan struct rk_hash_ctx {
38c48f1acfSLin Jinhan 	struct crypto_lli_desc		data_lli;	/* lli desc */
39c48f1acfSLin Jinhan 	struct crypto_hash_cache	*hash_cache;
40c48f1acfSLin Jinhan 	u32				magic;		/* to check ctx */
41c48f1acfSLin Jinhan 	u32				algo;		/* hash algo */
42c48f1acfSLin Jinhan 	u8				digest_size;	/* hash out length */
43c48f1acfSLin Jinhan 	u8				reserved[3];
44c48f1acfSLin Jinhan };
45c48f1acfSLin Jinhan 
4649a2135eSLin Jinhan struct rk_crypto_soc_data {
4749a2135eSLin Jinhan 	u32 capability;
4849a2135eSLin Jinhan };
4949a2135eSLin Jinhan 
50b353a43cSLin Jinhan struct rockchip_crypto_priv {
51b353a43cSLin Jinhan 	fdt_addr_t			reg;
52b353a43cSLin Jinhan 	struct clk			clk;
53b353a43cSLin Jinhan 	u32				frequency;
54b353a43cSLin Jinhan 	char				*clocks;
55b353a43cSLin Jinhan 	u32				*frequencies;
56b353a43cSLin Jinhan 	u32				nclocks;
57b353a43cSLin Jinhan 	u32				length;
581606a214SLin Jinhan 	struct rk_hash_ctx		*hw_ctx;
5949a2135eSLin Jinhan 	struct rk_crypto_soc_data	*soc_data;
60b353a43cSLin Jinhan };
61b353a43cSLin Jinhan 
6249a2135eSLin Jinhan #define LLI_ADDR_ALIGN_SIZE	8
6349a2135eSLin Jinhan #define DATA_ADDR_ALIGN_SIZE	8
6449a2135eSLin Jinhan #define DATA_LEN_ALIGN_SIZE	64
651606a214SLin Jinhan 
66086e8fa8SLin Jinhan /* crypto timeout 500ms, must support more than 32M data per times*/
67086e8fa8SLin Jinhan #define HASH_UPDATE_LIMIT	(32 * 1024 * 1024)
6849a2135eSLin Jinhan #define RK_CRYPTO_TIMEOUT	500000
69b353a43cSLin Jinhan 
7049a2135eSLin Jinhan #define RK_POLL_TIMEOUT(condition, timeout) \
7149a2135eSLin Jinhan ({ \
7249a2135eSLin Jinhan 	int time_out = timeout; \
73b353a43cSLin Jinhan 	while (condition) { \
7449a2135eSLin Jinhan 		if (--time_out <= 0) { \
751606a214SLin Jinhan 			debug("[%s] %d: time out!\n", __func__,\
76b353a43cSLin Jinhan 				__LINE__); \
77b353a43cSLin Jinhan 			break; \
78b353a43cSLin Jinhan 		} \
79b353a43cSLin Jinhan 		udelay(1); \
80b353a43cSLin Jinhan 	} \
8149a2135eSLin Jinhan 	(time_out <= 0) ? -ETIMEDOUT : 0; \
8249a2135eSLin Jinhan })
83b353a43cSLin Jinhan 
84d9332f1cSLin Jinhan #define WAIT_TAG_VALID(channel, timeout) ({ \
85d9332f1cSLin Jinhan 	u32 tag_mask = CRYPTO_CH0_TAG_VALID << (channel);\
86d9332f1cSLin Jinhan 	int ret;\
87d9332f1cSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_TAG_VALID) & tag_mask),\
88d9332f1cSLin Jinhan 			      timeout);\
89d9332f1cSLin Jinhan 	crypto_write(crypto_read(CRYPTO_TAG_VALID) & tag_mask, CRYPTO_TAG_VALID);\
90d9332f1cSLin Jinhan 	ret;\
91d9332f1cSLin Jinhan })
92d9332f1cSLin Jinhan 
93b353a43cSLin Jinhan #define virt_to_phys(addr)		(((unsigned long)addr) & 0xffffffff)
94b353a43cSLin Jinhan #define phys_to_virt(addr, area)	((unsigned long)addr)
95b353a43cSLin Jinhan 
9649a2135eSLin Jinhan #define align_malloc(bytes, alignment)	memalign(alignment, bytes)
9749a2135eSLin Jinhan #define align_free(addr)		free(addr)
9849a2135eSLin Jinhan 
9949a2135eSLin Jinhan #define ROUNDUP(size, alignment)	round_up(size, alignment)
10049a2135eSLin Jinhan #define cache_op_inner(type, addr, size) \
10149a2135eSLin Jinhan 					crypto_flush_cacheline((ulong)addr, size)
10249a2135eSLin Jinhan 
103d9332f1cSLin Jinhan #define IS_NEED_IV(rk_mode) ((rk_mode) != RK_MODE_ECB && \
104d9332f1cSLin Jinhan 			     (rk_mode) != RK_MODE_CMAC && \
105d9332f1cSLin Jinhan 			     (rk_mode) != RK_MODE_CBC_MAC)
106d9332f1cSLin Jinhan 
107d9332f1cSLin Jinhan #define IS_NEED_TAG(rk_mode) ((rk_mode) == RK_MODE_CMAC || \
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 
222b353a43cSLin Jinhan static int hw_crypto_reset(void)
223b353a43cSLin Jinhan {
22449a2135eSLin Jinhan 	u32 val = 0, mask = 0;
225b353a43cSLin Jinhan 	int ret;
226b353a43cSLin Jinhan 
22749a2135eSLin Jinhan 	val = CRYPTO_SW_PKA_RESET | CRYPTO_SW_CC_RESET;
22849a2135eSLin Jinhan 	mask = val << CRYPTO_WRITE_MASK_SHIFT;
229b353a43cSLin Jinhan 
230b353a43cSLin Jinhan 	/* reset pka and crypto modules*/
23149a2135eSLin Jinhan 	crypto_write(val | mask, CRYPTO_RST_CTL);
232b353a43cSLin Jinhan 
233b353a43cSLin Jinhan 	/* wait reset compelete */
23449a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL), RK_CRYPTO_TIMEOUT);
23549a2135eSLin Jinhan 
236b353a43cSLin Jinhan 	return ret;
237b353a43cSLin Jinhan }
238b353a43cSLin Jinhan 
239b353a43cSLin Jinhan static void hw_hash_clean_ctx(struct rk_hash_ctx *ctx)
240b353a43cSLin Jinhan {
241b353a43cSLin Jinhan 	/* clear hash status */
242b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
243b353a43cSLin Jinhan 
2441606a214SLin Jinhan 	assert(ctx);
2451606a214SLin Jinhan 	assert(ctx->magic == RK_HASH_CTX_MAGIC);
2461606a214SLin Jinhan 
247c48f1acfSLin Jinhan 	crypto_hash_cache_free(ctx->hash_cache);
2481606a214SLin Jinhan 
2491606a214SLin Jinhan 	memset(ctx, 0x00, sizeof(*ctx));
250b353a43cSLin Jinhan }
251b353a43cSLin Jinhan 
252c48f1acfSLin Jinhan static int rk_hash_init(void *hw_ctx, u32 algo)
253b353a43cSLin Jinhan {
254b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)hw_ctx;
255b353a43cSLin Jinhan 	u32 reg_ctrl = 0;
256b353a43cSLin Jinhan 	int ret;
257b353a43cSLin Jinhan 
258b353a43cSLin Jinhan 	if (!tmp_ctx)
259b353a43cSLin Jinhan 		return -EINVAL;
260b353a43cSLin Jinhan 
2611606a214SLin Jinhan 	reg_ctrl = CRYPTO_SW_CC_RESET;
2621606a214SLin Jinhan 	crypto_write(reg_ctrl | (reg_ctrl << CRYPTO_WRITE_MASK_SHIFT),
2631606a214SLin Jinhan 		     CRYPTO_RST_CTL);
2641606a214SLin Jinhan 
2651606a214SLin Jinhan 	/* wait reset compelete */
26649a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL),
26749a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
2681606a214SLin Jinhan 
2691606a214SLin Jinhan 	reg_ctrl = 0;
270b353a43cSLin Jinhan 	tmp_ctx->algo = algo;
271b353a43cSLin Jinhan 	switch (algo) {
272b353a43cSLin Jinhan 	case CRYPTO_MD5:
27349a2135eSLin Jinhan 	case CRYPTO_HMAC_MD5:
274b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_MD5;
275b353a43cSLin Jinhan 		tmp_ctx->digest_size = 16;
276b353a43cSLin Jinhan 		break;
277b353a43cSLin Jinhan 	case CRYPTO_SHA1:
27849a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA1:
279b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA1;
280b353a43cSLin Jinhan 		tmp_ctx->digest_size = 20;
281b353a43cSLin Jinhan 		break;
282b353a43cSLin Jinhan 	case CRYPTO_SHA256:
28349a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA256:
284b353a43cSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA256;
285b353a43cSLin Jinhan 		tmp_ctx->digest_size = 32;
286b353a43cSLin Jinhan 		break;
287e7846385SLin Jinhan 	case CRYPTO_SHA512:
28849a2135eSLin Jinhan 	case CRYPTO_HMAC_SHA512:
289e7846385SLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SHA512;
290e7846385SLin Jinhan 		tmp_ctx->digest_size = 64;
291e7846385SLin Jinhan 		break;
29249a2135eSLin Jinhan 	case CRYPTO_SM3:
29349a2135eSLin Jinhan 	case CRYPTO_HMAC_SM3:
29449a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_MODE_SM3;
29549a2135eSLin Jinhan 		tmp_ctx->digest_size = 32;
29649a2135eSLin Jinhan 		break;
297b353a43cSLin Jinhan 	default:
298b353a43cSLin Jinhan 		ret = -EINVAL;
299b353a43cSLin Jinhan 		goto exit;
300b353a43cSLin Jinhan 	}
301b353a43cSLin Jinhan 
302b353a43cSLin Jinhan 	clear_hash_out_reg();
303b353a43cSLin Jinhan 
304b353a43cSLin Jinhan 	/* enable hardware padding */
305b353a43cSLin Jinhan 	reg_ctrl |= CRYPTO_HW_PAD_ENABLE;
306b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
307b353a43cSLin Jinhan 
308b353a43cSLin Jinhan 	/* FIFO input and output data byte swap */
309b353a43cSLin Jinhan 	/* such as B0, B1, B2, B3 -> B3, B2, B1, B0 */
310b353a43cSLin Jinhan 	reg_ctrl = CRYPTO_DOUT_BYTESWAP | CRYPTO_DOIN_BYTESWAP;
311b353a43cSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_FIFO_CTL);
312b353a43cSLin Jinhan 
3131606a214SLin Jinhan 	/* enable src_item_done interrupt */
3141606a214SLin Jinhan 	crypto_write(CRYPTO_SRC_ITEM_INT_EN, CRYPTO_DMA_INT_EN);
315b353a43cSLin Jinhan 
316b353a43cSLin Jinhan 	tmp_ctx->magic = RK_HASH_CTX_MAGIC;
317b353a43cSLin Jinhan 
318b353a43cSLin Jinhan 	return 0;
319b353a43cSLin Jinhan exit:
320b353a43cSLin Jinhan 	/* clear hash setting if init failed */
321b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
322b353a43cSLin Jinhan 
323b353a43cSLin Jinhan 	return ret;
324b353a43cSLin Jinhan }
325b353a43cSLin Jinhan 
326c48f1acfSLin Jinhan static int rk_hash_direct_calc(void *hw_data, const u8 *data,
3271606a214SLin Jinhan 			       u32 data_len, u8 *started_flag, u8 is_last)
328b353a43cSLin Jinhan {
329c48f1acfSLin Jinhan 	struct rockchip_crypto_priv *priv = hw_data;
330c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
331c48f1acfSLin Jinhan 	struct crypto_lli_desc *lli = &hash_ctx->data_lli;
332b353a43cSLin Jinhan 	int ret = -EINVAL;
33300fa57d8SLin Jinhan 	u32 tmp = 0, mask = 0;
334b353a43cSLin Jinhan 
33549a2135eSLin Jinhan 	assert(IS_ALIGNED((ulong)data, DATA_ADDR_ALIGN_SIZE));
33649a2135eSLin Jinhan 	assert(is_last || IS_ALIGNED(data_len, DATA_LEN_ALIGN_SIZE));
337b353a43cSLin Jinhan 
3381606a214SLin Jinhan 	debug("%s: data = %p, len = %u, s = %x, l = %x\n",
3391606a214SLin Jinhan 	      __func__, data, data_len, *started_flag, is_last);
340b353a43cSLin Jinhan 
3411606a214SLin Jinhan 	memset(lli, 0x00, sizeof(*lli));
3421606a214SLin Jinhan 	lli->src_addr = (u32)virt_to_phys(data);
3431606a214SLin Jinhan 	lli->src_len = data_len;
3441606a214SLin Jinhan 	lli->dma_ctrl = LLI_DMA_CTRL_SRC_DONE;
345b353a43cSLin Jinhan 
3461606a214SLin Jinhan 	if (is_last) {
3471606a214SLin Jinhan 		lli->user_define |= LLI_USER_STRING_LAST;
3481606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_LAST;
349b353a43cSLin Jinhan 	} else {
3501606a214SLin Jinhan 		lli->next_addr = (u32)virt_to_phys(lli);
3511606a214SLin Jinhan 		lli->dma_ctrl |= LLI_DMA_CTRL_PAUSE;
3521606a214SLin Jinhan 	}
3531606a214SLin Jinhan 
3541606a214SLin Jinhan 	if (!(*started_flag)) {
3551606a214SLin Jinhan 		lli->user_define |=
3561606a214SLin Jinhan 			(LLI_USER_STRING_START | LLI_USER_CPIHER_START);
3571606a214SLin Jinhan 		crypto_write((u32)virt_to_phys(lli), CRYPTO_DMA_LLI_ADDR);
3581606a214SLin Jinhan 		crypto_write((CRYPTO_HASH_ENABLE << CRYPTO_WRITE_MASK_SHIFT) |
3591606a214SLin Jinhan 			     CRYPTO_HASH_ENABLE, CRYPTO_HASH_CTL);
3601606a214SLin Jinhan 		tmp = CRYPTO_DMA_START;
3611606a214SLin Jinhan 		*started_flag = 1;
3621606a214SLin Jinhan 	} else {
363b353a43cSLin Jinhan 		tmp = CRYPTO_DMA_RESTART;
364b353a43cSLin Jinhan 	}
365b353a43cSLin Jinhan 
366b353a43cSLin Jinhan 	/* flush cache */
367c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)lli, sizeof(*lli));
368c48f1acfSLin Jinhan 	crypto_flush_cacheline((ulong)data, data_len);
369b353a43cSLin Jinhan 
370b353a43cSLin Jinhan 	/* start calculate */
371b353a43cSLin Jinhan 	crypto_write(tmp << CRYPTO_WRITE_MASK_SHIFT | tmp,
372b353a43cSLin Jinhan 		     CRYPTO_DMA_CTL);
373b353a43cSLin Jinhan 
37400fa57d8SLin Jinhan 	/* mask CRYPTO_SYNC_LOCKSTEP_INT_ST flag */
37500fa57d8SLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
37600fa57d8SLin Jinhan 
377b353a43cSLin Jinhan 	/* wait calc ok */
37849a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
37949a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
380b353a43cSLin Jinhan 
381b353a43cSLin Jinhan 	/* clear interrupt status */
382b353a43cSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
383b353a43cSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
384b353a43cSLin Jinhan 
385b353a43cSLin Jinhan 	if (tmp != CRYPTO_SRC_ITEM_DONE_INT_ST &&
386b353a43cSLin Jinhan 	    tmp != CRYPTO_ZERO_LEN_INT_ST) {
3871606a214SLin Jinhan 		debug("[%s] %d: CRYPTO_DMA_INT_ST = 0x%x\n",
388b353a43cSLin Jinhan 		      __func__, __LINE__, tmp);
3891606a214SLin Jinhan 		goto exit;
390b353a43cSLin Jinhan 	}
391b353a43cSLin Jinhan 
392c48f1acfSLin Jinhan 	priv->length += data_len;
3931606a214SLin Jinhan exit:
3941606a214SLin Jinhan 	return ret;
395b353a43cSLin Jinhan }
3961606a214SLin Jinhan 
3971606a214SLin Jinhan int rk_hash_update(void *ctx, const u8 *data, u32 data_len)
3981606a214SLin Jinhan {
3991606a214SLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
400c48f1acfSLin Jinhan 	int ret = -EINVAL;
4011606a214SLin Jinhan 
4021606a214SLin Jinhan 	debug("\n");
4031606a214SLin Jinhan 	if (!tmp_ctx || !data)
404c48f1acfSLin Jinhan 		goto exit;
4051606a214SLin Jinhan 
4061606a214SLin Jinhan 	if (tmp_ctx->digest_size == 0 || tmp_ctx->magic != RK_HASH_CTX_MAGIC)
407c48f1acfSLin Jinhan 		goto exit;
4081606a214SLin Jinhan 
409c48f1acfSLin Jinhan 	ret = crypto_hash_update_with_cache(tmp_ctx->hash_cache,
410c48f1acfSLin Jinhan 					    data, data_len);
4111606a214SLin Jinhan 
412c48f1acfSLin Jinhan exit:
413b353a43cSLin Jinhan 	/* free lli list */
414c48f1acfSLin Jinhan 	if (ret)
415b353a43cSLin Jinhan 		hw_hash_clean_ctx(tmp_ctx);
416b353a43cSLin Jinhan 
417c48f1acfSLin Jinhan 	return ret;
418b353a43cSLin Jinhan }
419b353a43cSLin Jinhan 
420b353a43cSLin Jinhan int rk_hash_final(void *ctx, u8 *digest, size_t len)
421b353a43cSLin Jinhan {
422b353a43cSLin Jinhan 	struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
423b353a43cSLin Jinhan 	int ret = -EINVAL;
424b353a43cSLin Jinhan 
425b353a43cSLin Jinhan 	if (!digest)
426b353a43cSLin Jinhan 		goto exit;
427b353a43cSLin Jinhan 
428b353a43cSLin Jinhan 	if (!tmp_ctx ||
429b353a43cSLin Jinhan 	    tmp_ctx->digest_size == 0 ||
430b353a43cSLin Jinhan 	    len > tmp_ctx->digest_size ||
431b353a43cSLin Jinhan 	    tmp_ctx->magic != RK_HASH_CTX_MAGIC) {
432b353a43cSLin Jinhan 		goto exit;
433b353a43cSLin Jinhan 	}
434b353a43cSLin Jinhan 
435b353a43cSLin Jinhan 	/* wait hash value ok */
43649a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!crypto_read(CRYPTO_HASH_VALID),
43749a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
438b353a43cSLin Jinhan 
439c3ce9937SLin Jinhan 	read_regs(CRYPTO_HASH_DOUT_0, digest, len);
440b353a43cSLin Jinhan 
441b353a43cSLin Jinhan 	/* clear hash status */
442b353a43cSLin Jinhan 	crypto_write(CRYPTO_HASH_IS_VALID, CRYPTO_HASH_VALID);
443b353a43cSLin Jinhan 	crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
444b353a43cSLin Jinhan 
445b353a43cSLin Jinhan exit:
446b353a43cSLin Jinhan 
447b353a43cSLin Jinhan 	return ret;
448b353a43cSLin Jinhan }
449b353a43cSLin Jinhan 
450b353a43cSLin Jinhan static u32 rockchip_crypto_capability(struct udevice *dev)
451b353a43cSLin Jinhan {
45249a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
45349a2135eSLin Jinhan 	u32 capability, mask = 0;
4547eea1823SLin Jinhan 
45549a2135eSLin Jinhan 	capability = priv->soc_data->capability;
45649a2135eSLin Jinhan 
45749a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_CIPHER))
45849a2135eSLin Jinhan 	mask |= (CRYPTO_DES | CRYPTO_AES | CRYPTO_SM4);
459c0e47d03SLin Jinhan #endif
4607eea1823SLin Jinhan 
46149a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_HMAC))
46249a2135eSLin Jinhan 	mask |= (CRYPTO_HMAC_MD5 | CRYPTO_HMAC_SHA1 | CRYPTO_HMAC_SHA256 |
46349a2135eSLin Jinhan 			 CRYPTO_HMAC_SHA512 | CRYPTO_HMAC_SM3);
46449a2135eSLin Jinhan #endif
46549a2135eSLin Jinhan 
46649a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_RSA))
46749a2135eSLin Jinhan 	mask |= (CRYPTO_RSA512 | CRYPTO_RSA1024 | CRYPTO_RSA2048 |
46849a2135eSLin Jinhan 			 CRYPTO_RSA3072 | CRYPTO_RSA4096);
46949a2135eSLin Jinhan #endif
47049a2135eSLin Jinhan 
47149a2135eSLin Jinhan 	return capability & (~mask);
472b353a43cSLin Jinhan }
473b353a43cSLin Jinhan 
474b353a43cSLin Jinhan static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx)
475b353a43cSLin Jinhan {
476b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
477c48f1acfSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
478b353a43cSLin Jinhan 
479b353a43cSLin Jinhan 	if (!ctx)
480b353a43cSLin Jinhan 		return -EINVAL;
481b353a43cSLin Jinhan 
482c48f1acfSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
483b353a43cSLin Jinhan 
484c48f1acfSLin Jinhan 	priv->length = 0;
485c48f1acfSLin Jinhan 
486c48f1acfSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
487c48f1acfSLin Jinhan 						       priv, ctx->length,
48849a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
48949a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
490c48f1acfSLin Jinhan 	if (!hash_ctx->hash_cache)
491c48f1acfSLin Jinhan 		return -EFAULT;
492c48f1acfSLin Jinhan 
493c48f1acfSLin Jinhan 	return rk_hash_init(hash_ctx, ctx->algo);
494b353a43cSLin Jinhan }
495b353a43cSLin Jinhan 
496b353a43cSLin Jinhan static int rockchip_crypto_sha_update(struct udevice *dev,
497b353a43cSLin Jinhan 				      u32 *input, u32 len)
498b353a43cSLin Jinhan {
499b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
500086e8fa8SLin Jinhan 	int ret, i;
501086e8fa8SLin Jinhan 	u8 *p;
502b353a43cSLin Jinhan 
503b353a43cSLin Jinhan 	if (!len)
504b353a43cSLin Jinhan 		return -EINVAL;
505b353a43cSLin Jinhan 
506086e8fa8SLin Jinhan 	p = (u8 *)input;
507086e8fa8SLin Jinhan 
508086e8fa8SLin Jinhan 	for (i = 0; i < len / HASH_UPDATE_LIMIT; i++, p += HASH_UPDATE_LIMIT) {
509086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, HASH_UPDATE_LIMIT);
510086e8fa8SLin Jinhan 		if (ret)
511086e8fa8SLin Jinhan 			goto exit;
512086e8fa8SLin Jinhan 	}
513086e8fa8SLin Jinhan 
514086e8fa8SLin Jinhan 	if (len % HASH_UPDATE_LIMIT)
515086e8fa8SLin Jinhan 		ret = rk_hash_update(priv->hw_ctx, p, len % HASH_UPDATE_LIMIT);
516086e8fa8SLin Jinhan 
517086e8fa8SLin Jinhan exit:
518086e8fa8SLin Jinhan 	return ret;
519b353a43cSLin Jinhan }
520b353a43cSLin Jinhan 
521b353a43cSLin Jinhan static int rockchip_crypto_sha_final(struct udevice *dev,
522b353a43cSLin Jinhan 				     sha_context *ctx, u8 *output)
523b353a43cSLin Jinhan {
524b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
525b353a43cSLin Jinhan 	u32 nbits;
526c48f1acfSLin Jinhan 	int ret;
527b353a43cSLin Jinhan 
528b353a43cSLin Jinhan 	nbits = crypto_algo_nbits(ctx->algo);
529b353a43cSLin Jinhan 
530c48f1acfSLin Jinhan 	if (priv->length != ctx->length) {
531c48f1acfSLin Jinhan 		printf("total length(0x%08x) != init length(0x%08x)!\n",
532c48f1acfSLin Jinhan 		       priv->length, ctx->length);
533c48f1acfSLin Jinhan 		ret = -EIO;
534c48f1acfSLin Jinhan 		goto exit;
535c48f1acfSLin Jinhan 	}
536c48f1acfSLin Jinhan 
537c48f1acfSLin Jinhan 	ret = rk_hash_final(priv->hw_ctx, (u8 *)output, BITS2BYTE(nbits));
538c48f1acfSLin Jinhan 
539c48f1acfSLin Jinhan exit:
540c48f1acfSLin Jinhan 	hw_hash_clean_ctx(priv->hw_ctx);
541c48f1acfSLin Jinhan 	return ret;
542b353a43cSLin Jinhan }
543b353a43cSLin Jinhan 
54449a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
54549a2135eSLin Jinhan int rk_hmac_init(void *hw_ctx, u32 algo, u8 *key, u32 key_len)
54649a2135eSLin Jinhan {
54749a2135eSLin Jinhan 	u32 reg_ctrl = 0;
54849a2135eSLin Jinhan 	int ret;
54949a2135eSLin Jinhan 
55049a2135eSLin Jinhan 	if (!key || !key_len || key_len > 64)
55149a2135eSLin Jinhan 		return -EINVAL;
55249a2135eSLin Jinhan 
55349a2135eSLin Jinhan 	clear_key_regs();
55449a2135eSLin Jinhan 
55549a2135eSLin Jinhan 	write_key_reg(0, key, key_len);
55649a2135eSLin Jinhan 
55749a2135eSLin Jinhan 	ret = rk_hash_init(hw_ctx, algo);
55849a2135eSLin Jinhan 	if (ret)
55949a2135eSLin Jinhan 		return ret;
56049a2135eSLin Jinhan 
56149a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_HASH_CTL) | CRYPTO_HMAC_ENABLE;
56249a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
56349a2135eSLin Jinhan 
56449a2135eSLin Jinhan 	return ret;
56549a2135eSLin Jinhan }
56649a2135eSLin Jinhan 
56749a2135eSLin Jinhan static int rockchip_crypto_hmac_init(struct udevice *dev,
56849a2135eSLin Jinhan 				     sha_context *ctx, u8 *key, u32 key_len)
56949a2135eSLin Jinhan {
57049a2135eSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
57149a2135eSLin Jinhan 	struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
57249a2135eSLin Jinhan 
57349a2135eSLin Jinhan 	if (!ctx)
57449a2135eSLin Jinhan 		return -EINVAL;
57549a2135eSLin Jinhan 
57649a2135eSLin Jinhan 	memset(hash_ctx, 0x00, sizeof(*hash_ctx));
57749a2135eSLin Jinhan 
57849a2135eSLin Jinhan 	priv->length = 0;
57949a2135eSLin Jinhan 
58049a2135eSLin Jinhan 	hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
58149a2135eSLin Jinhan 						       priv, ctx->length,
58249a2135eSLin Jinhan 						       DATA_ADDR_ALIGN_SIZE,
58349a2135eSLin Jinhan 						       DATA_LEN_ALIGN_SIZE);
58449a2135eSLin Jinhan 	if (!hash_ctx->hash_cache)
58549a2135eSLin Jinhan 		return -EFAULT;
58649a2135eSLin Jinhan 
58749a2135eSLin Jinhan 	return rk_hmac_init(priv->hw_ctx, ctx->algo, key, key_len);
58849a2135eSLin Jinhan }
58949a2135eSLin Jinhan 
59049a2135eSLin Jinhan static int rockchip_crypto_hmac_update(struct udevice *dev,
59149a2135eSLin Jinhan 				       u32 *input, u32 len)
59249a2135eSLin Jinhan {
59349a2135eSLin Jinhan 	return rockchip_crypto_sha_update(dev, input, len);
59449a2135eSLin Jinhan }
59549a2135eSLin Jinhan 
59649a2135eSLin Jinhan static int rockchip_crypto_hmac_final(struct udevice *dev,
59749a2135eSLin Jinhan 				      sha_context *ctx, u8 *output)
59849a2135eSLin Jinhan {
59949a2135eSLin Jinhan 	return rockchip_crypto_sha_final(dev, ctx, output);
60049a2135eSLin Jinhan }
60149a2135eSLin Jinhan 
60249a2135eSLin Jinhan #endif
60349a2135eSLin Jinhan 
60449a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
60549a2135eSLin Jinhan static u8 g_key_chn;
60649a2135eSLin Jinhan 
60749a2135eSLin Jinhan static const u32 rk_mode2bc_mode[RK_MODE_MAX] = {
60849a2135eSLin Jinhan 	[RK_MODE_ECB] = CRYPTO_BC_ECB,
60949a2135eSLin Jinhan 	[RK_MODE_CBC] = CRYPTO_BC_CBC,
61049a2135eSLin Jinhan 	[RK_MODE_CTS] = CRYPTO_BC_CTS,
61149a2135eSLin Jinhan 	[RK_MODE_CTR] = CRYPTO_BC_CTR,
61249a2135eSLin Jinhan 	[RK_MODE_CFB] = CRYPTO_BC_CFB,
61349a2135eSLin Jinhan 	[RK_MODE_OFB] = CRYPTO_BC_OFB,
61449a2135eSLin Jinhan 	[RK_MODE_XTS] = CRYPTO_BC_XTS,
615c3ce9937SLin Jinhan 	[RK_MODE_CCM] = CRYPTO_BC_CCM,
616c3ce9937SLin Jinhan 	[RK_MODE_GCM] = CRYPTO_BC_GCM,
617d9332f1cSLin Jinhan 	[RK_MODE_CMAC] = CRYPTO_BC_CMAC,
618d9332f1cSLin Jinhan 	[RK_MODE_CBC_MAC] = CRYPTO_BC_CBC_MAC,
61949a2135eSLin Jinhan };
62049a2135eSLin Jinhan 
621c3ce9937SLin Jinhan static inline void set_pc_len_reg(u32 chn, u64 pc_len)
622c3ce9937SLin Jinhan {
623c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_PC_LEN_0 + chn * 0x08;
624c3ce9937SLin Jinhan 
625c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
626c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
627c3ce9937SLin Jinhan }
628c3ce9937SLin Jinhan 
629c3ce9937SLin Jinhan static inline void set_aad_len_reg(u32 chn, u64 pc_len)
630c3ce9937SLin Jinhan {
631c3ce9937SLin Jinhan 	u32 chn_base = CRYPTO_CH0_AAD_LEN_0 + chn * 0x08;
632c3ce9937SLin Jinhan 
633c3ce9937SLin Jinhan 	crypto_write(pc_len & 0xffffffff, chn_base);
634c3ce9937SLin Jinhan 	crypto_write(pc_len >> 32, chn_base + 4);
635c3ce9937SLin Jinhan }
636c3ce9937SLin Jinhan 
63749a2135eSLin Jinhan static inline bool is_des_mode(u32 rk_mode)
63849a2135eSLin Jinhan {
63949a2135eSLin Jinhan 	return (rk_mode == RK_MODE_ECB ||
64049a2135eSLin Jinhan 		rk_mode == RK_MODE_CBC ||
64149a2135eSLin Jinhan 		rk_mode == RK_MODE_CFB ||
64249a2135eSLin Jinhan 		rk_mode == RK_MODE_OFB);
64349a2135eSLin Jinhan }
64449a2135eSLin Jinhan 
6456b53126aSLin Jinhan static void dump_crypto_state(struct crypto_lli_desc *desc,
6466b53126aSLin Jinhan 			      u32 tmp, u32 expt_int,
6476b53126aSLin Jinhan 			      const u8 *in, const u8 *out,
6486b53126aSLin Jinhan 			      u32 len, int ret)
64949a2135eSLin Jinhan {
65049a2135eSLin Jinhan 	IMSG("%s\n", ret == -ETIME ? "timeout" : "dismatch");
65149a2135eSLin Jinhan 
65249a2135eSLin Jinhan 	IMSG("CRYPTO_DMA_INT_ST = %08x, expect_int = %08x\n",
65349a2135eSLin Jinhan 	     tmp, expt_int);
65449a2135eSLin Jinhan 	IMSG("data desc		= %p\n", desc);
65549a2135eSLin Jinhan 	IMSG("\taddr_in		= [%08x <=> %08x]\n",
65649a2135eSLin Jinhan 	     desc->src_addr, (u32)virt_to_phys(in));
65749a2135eSLin Jinhan 	IMSG("\taddr_out	= [%08x <=> %08x]\n",
65849a2135eSLin Jinhan 	     desc->dst_addr, (u32)virt_to_phys(out));
65949a2135eSLin Jinhan 	IMSG("\tsrc_len		= [%08x <=> %08x]\n",
66049a2135eSLin Jinhan 	     desc->src_len, (u32)len);
66149a2135eSLin Jinhan 	IMSG("\tdst_len		= %08x\n", desc->dst_len);
66249a2135eSLin Jinhan 	IMSG("\tdma_ctl		= %08x\n", desc->dma_ctrl);
66349a2135eSLin Jinhan 	IMSG("\tuser_define	= %08x\n", desc->user_define);
66449a2135eSLin Jinhan 
66549a2135eSLin Jinhan 	IMSG("\n\nDMA CRYPTO_DMA_LLI_ADDR status = %08x\n",
66649a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_ADDR));
66749a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_ST status = %08x\n",
66849a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_ST));
66949a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_STATE status = %08x\n",
67049a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_STATE));
67149a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_LLI_RADDR status = %08x\n",
67249a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_LLI_RADDR));
67349a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_SRC_RADDR status = %08x\n",
67449a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_SRC_RADDR));
67549a2135eSLin Jinhan 	IMSG("DMA CRYPTO_DMA_DST_RADDR status = %08x\n",
67649a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
67749a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_ST status = %08x\n",
67849a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_ST));
67949a2135eSLin Jinhan 	IMSG("DMA CRYPTO_CIPHER_STATE status = %08x\n",
68049a2135eSLin Jinhan 	     crypto_read(CRYPTO_CIPHER_STATE));
68149a2135eSLin Jinhan 	IMSG("DMA CRYPTO_TAG_VALID status = %08x\n",
68249a2135eSLin Jinhan 	     crypto_read(CRYPTO_TAG_VALID));
68349a2135eSLin Jinhan 	IMSG("LOCKSTEP status = %08x\n\n",
68449a2135eSLin Jinhan 	     crypto_read(0x618));
68549a2135eSLin Jinhan 
68649a2135eSLin Jinhan 	IMSG("dst %dbyte not transferred\n",
68749a2135eSLin Jinhan 	     desc->dst_addr + desc->dst_len -
68849a2135eSLin Jinhan 	     crypto_read(CRYPTO_DMA_DST_RADDR));
68949a2135eSLin Jinhan }
69049a2135eSLin Jinhan 
691c3ce9937SLin Jinhan static int ccm128_set_iv_reg(u32 chn, const u8 *nonce, u32 nlen)
692c3ce9937SLin Jinhan {
693c3ce9937SLin Jinhan 	u8 iv_buf[AES_BLOCK_SIZE];
694c3ce9937SLin Jinhan 	u32 L;
695c3ce9937SLin Jinhan 
696c3ce9937SLin Jinhan 	memset(iv_buf, 0x00, sizeof(iv_buf));
697c3ce9937SLin Jinhan 
698c3ce9937SLin Jinhan 	L = 15 - nlen;
699c3ce9937SLin Jinhan 	iv_buf[0] = ((u8)(L - 1) & 7);
700c3ce9937SLin Jinhan 
701c3ce9937SLin Jinhan 	/* the L parameter */
702c3ce9937SLin Jinhan 	L = iv_buf[0] & 7;
703c3ce9937SLin Jinhan 
704c3ce9937SLin Jinhan 	/* nonce is too short */
705c3ce9937SLin Jinhan 	if (nlen < (14 - L))
706c3ce9937SLin Jinhan 		return -EINVAL;
707c3ce9937SLin Jinhan 
708c3ce9937SLin Jinhan 	/* clear aad flag */
709c3ce9937SLin Jinhan 	iv_buf[0] &= ~0x40;
710c3ce9937SLin Jinhan 	memcpy(&iv_buf[1], nonce, 14 - L);
711c3ce9937SLin Jinhan 
712c3ce9937SLin Jinhan 	set_iv_reg(chn, iv_buf, AES_BLOCK_SIZE);
713c3ce9937SLin Jinhan 
714c3ce9937SLin Jinhan 	return 0;
715c3ce9937SLin Jinhan }
716c3ce9937SLin Jinhan 
717c3ce9937SLin Jinhan static void ccm_aad_padding(u32 aad_len, u8 *padding, u32 *padding_size)
718c3ce9937SLin Jinhan {
719c3ce9937SLin Jinhan 	u32 i;
720c3ce9937SLin Jinhan 
721c3ce9937SLin Jinhan 	i = aad_len < (0x10000 - 0x100) ? 2 : 6;
722c3ce9937SLin Jinhan 
723c3ce9937SLin Jinhan 	if (i == 2) {
724c3ce9937SLin Jinhan 		padding[0] = (u8)(aad_len >> 8);
725c3ce9937SLin Jinhan 		padding[1] = (u8)aad_len;
726c3ce9937SLin Jinhan 	} else {
727c3ce9937SLin Jinhan 		padding[0] = 0xFF;
728c3ce9937SLin Jinhan 		padding[1] = 0xFE;
729c3ce9937SLin Jinhan 		padding[2] = (u8)(aad_len >> 24);
730c3ce9937SLin Jinhan 		padding[3] = (u8)(aad_len >> 16);
731c3ce9937SLin Jinhan 		padding[4] = (u8)(aad_len >> 8);
732c3ce9937SLin Jinhan 	}
733c3ce9937SLin Jinhan 
734c3ce9937SLin Jinhan 	*padding_size = i;
735c3ce9937SLin Jinhan }
736c3ce9937SLin Jinhan 
737c3ce9937SLin Jinhan static int ccm_compose_aad_iv(u8 *aad_iv, u32 data_len, u32 tag_size)
738c3ce9937SLin Jinhan {
739c3ce9937SLin Jinhan 	aad_iv[0] |= ((u8)(((tag_size - 2) / 2) & 7) << 3);
740c3ce9937SLin Jinhan 
741c3ce9937SLin Jinhan 	aad_iv[12] = (u8)(data_len >> 24);
742c3ce9937SLin Jinhan 	aad_iv[13] = (u8)(data_len >> 16);
743c3ce9937SLin Jinhan 	aad_iv[14] = (u8)(data_len >> 8);
744c3ce9937SLin Jinhan 	aad_iv[15] = (u8)data_len;
745c3ce9937SLin Jinhan 
746c3ce9937SLin Jinhan 	aad_iv[0] |= 0x40;	//set aad flag
747c3ce9937SLin Jinhan 
748c3ce9937SLin Jinhan 	return 0;
749c3ce9937SLin Jinhan }
750c3ce9937SLin Jinhan 
75149a2135eSLin Jinhan static int hw_cipher_init(u32 chn, const u8 *key, const u8 *twk_key,
75249a2135eSLin Jinhan 			  u32 key_len, const u8 *iv, u32 iv_len,
75349a2135eSLin Jinhan 			  u32 algo, u32 mode, bool enc)
75449a2135eSLin Jinhan {
75549a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
75649a2135eSLin Jinhan 	u32 key_chn_sel = chn;
75749a2135eSLin Jinhan 	u32 reg_ctrl = 0;
75849a2135eSLin Jinhan 
75949a2135eSLin Jinhan 	IMSG("%s: key addr is %p, key_len is %d, iv addr is %p",
76049a2135eSLin Jinhan 	     __func__, key, key_len, iv);
76149a2135eSLin Jinhan 	if (rk_mode >= RK_MODE_MAX)
76249a2135eSLin Jinhan 		return -EINVAL;
76349a2135eSLin Jinhan 
76449a2135eSLin Jinhan 	switch (algo) {
76549a2135eSLin Jinhan 	case CRYPTO_DES:
76649a2135eSLin Jinhan 		if (key_len > DES_BLOCK_SIZE)
76749a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_TDES;
76849a2135eSLin Jinhan 		else
76949a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_DES;
77049a2135eSLin Jinhan 		break;
77149a2135eSLin Jinhan 	case CRYPTO_AES:
77249a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_AES;
77349a2135eSLin Jinhan 		break;
77449a2135eSLin Jinhan 	case CRYPTO_SM4:
77549a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_SM4;
77649a2135eSLin Jinhan 		break;
77749a2135eSLin Jinhan 	default:
77849a2135eSLin Jinhan 		return -EINVAL;
77949a2135eSLin Jinhan 	}
78049a2135eSLin Jinhan 
78149a2135eSLin Jinhan 	if (algo == CRYPTO_AES || algo == CRYPTO_SM4) {
78249a2135eSLin Jinhan 		switch (key_len) {
78349a2135eSLin Jinhan 		case AES_KEYSIZE_128:
78449a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_128_bit_key;
78549a2135eSLin Jinhan 			break;
78649a2135eSLin Jinhan 		case AES_KEYSIZE_192:
78749a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_192_bit_key;
78849a2135eSLin Jinhan 			break;
78949a2135eSLin Jinhan 		case AES_KEYSIZE_256:
79049a2135eSLin Jinhan 			reg_ctrl |= CRYPTO_BC_256_bit_key;
79149a2135eSLin Jinhan 			break;
79249a2135eSLin Jinhan 		default:
79349a2135eSLin Jinhan 			return -EINVAL;
79449a2135eSLin Jinhan 		}
79549a2135eSLin Jinhan 	}
79649a2135eSLin Jinhan 
79749a2135eSLin Jinhan 	reg_ctrl |= rk_mode2bc_mode[rk_mode];
79849a2135eSLin Jinhan 	if (!enc)
79949a2135eSLin Jinhan 		reg_ctrl |= CRYPTO_BC_DECRYPT;
80049a2135eSLin Jinhan 
80149a2135eSLin Jinhan 	/* write key data to reg */
80249a2135eSLin Jinhan 	write_key_reg(key_chn_sel, key, key_len);
80349a2135eSLin Jinhan 
80449a2135eSLin Jinhan 	/* write twk key for xts mode */
80549a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS)
80649a2135eSLin Jinhan 		write_key_reg(key_chn_sel + 4, twk_key, key_len);
80749a2135eSLin Jinhan 
80849a2135eSLin Jinhan 	/* set iv reg */
809c3ce9937SLin Jinhan 	if (rk_mode == RK_MODE_CCM)
810c3ce9937SLin Jinhan 		ccm128_set_iv_reg(chn, iv, iv_len);
811c3ce9937SLin Jinhan 	else
81249a2135eSLin Jinhan 		set_iv_reg(chn, iv, iv_len);
81349a2135eSLin Jinhan 
81449a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
81549a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
81649a2135eSLin Jinhan 	crypto_write(CRYPTO_LIST_DONE_INT_EN | CRYPTO_DST_ITEM_DONE_INT_EN,
81749a2135eSLin Jinhan 		     CRYPTO_DMA_INT_EN);
81849a2135eSLin Jinhan 
81949a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
82049a2135eSLin Jinhan 
82149a2135eSLin Jinhan 	return 0;
82249a2135eSLin Jinhan }
82349a2135eSLin Jinhan 
82449a2135eSLin Jinhan static int hw_cipher_crypt(const u8 *in, u8 *out, u64 len,
825c3ce9937SLin Jinhan 			   const u8 *aad, u32 aad_len,
826c3ce9937SLin Jinhan 			   u8 *tag, u32 tag_len, u32 mode)
82749a2135eSLin Jinhan {
828c3ce9937SLin Jinhan 	struct crypto_lli_desc *data_desc = NULL, *aad_desc = NULL;
829c3ce9937SLin Jinhan 	u8 *dma_in = NULL, *dma_out = NULL, *aad_tmp = NULL;
83049a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
83149a2135eSLin Jinhan 	u32 reg_ctrl = 0, tmp_len = 0;
83249a2135eSLin Jinhan 	u32 expt_int = 0, mask = 0;
83349a2135eSLin Jinhan 	u32 key_chn = g_key_chn;
83449a2135eSLin Jinhan 	u32 tmp, dst_len = 0;
83549a2135eSLin Jinhan 	int ret = -1;
83649a2135eSLin Jinhan 
83749a2135eSLin Jinhan 	if (rk_mode == RK_MODE_CTS && len <= AES_BLOCK_SIZE) {
83849a2135eSLin Jinhan 		printf("CTS mode length %u < 16Byte\n", (u32)len);
83949a2135eSLin Jinhan 		return -EINVAL;
84049a2135eSLin Jinhan 	}
84149a2135eSLin Jinhan 
84249a2135eSLin Jinhan 	tmp_len = (rk_mode == RK_MODE_CTR) ? ROUNDUP(len, AES_BLOCK_SIZE) : len;
84349a2135eSLin Jinhan 
84449a2135eSLin Jinhan 	data_desc = align_malloc(sizeof(*data_desc), LLI_ADDR_ALIGN_SIZE);
84549a2135eSLin Jinhan 	if (!data_desc)
84649a2135eSLin Jinhan 		goto exit;
84749a2135eSLin Jinhan 
84849a2135eSLin Jinhan 	if (IS_ALIGNED((ulong)in, DATA_ADDR_ALIGN_SIZE) && tmp_len == len)
84949a2135eSLin Jinhan 		dma_in = (void *)in;
85049a2135eSLin Jinhan 	else
85149a2135eSLin Jinhan 		dma_in = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
85249a2135eSLin Jinhan 	if (!dma_in)
85349a2135eSLin Jinhan 		goto exit;
85449a2135eSLin Jinhan 
85549a2135eSLin Jinhan 	if (out) {
85649a2135eSLin Jinhan 		if (IS_ALIGNED((ulong)out, DATA_ADDR_ALIGN_SIZE) &&
85749a2135eSLin Jinhan 		    tmp_len == len)
85849a2135eSLin Jinhan 			dma_out = out;
85949a2135eSLin Jinhan 		else
86049a2135eSLin Jinhan 			dma_out = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
86149a2135eSLin Jinhan 		if (!dma_out)
86249a2135eSLin Jinhan 			goto exit;
86349a2135eSLin Jinhan 		dst_len = tmp_len;
86449a2135eSLin Jinhan 	}
86549a2135eSLin Jinhan 
86649a2135eSLin Jinhan 	memset(data_desc, 0x00, sizeof(*data_desc));
86749a2135eSLin Jinhan 	if (dma_in != in)
86849a2135eSLin Jinhan 		memcpy(dma_in, in, len);
86949a2135eSLin Jinhan 
87049a2135eSLin Jinhan 	data_desc->src_addr    = (u32)virt_to_phys(dma_in);
87149a2135eSLin Jinhan 	data_desc->src_len     = tmp_len;
87249a2135eSLin Jinhan 	data_desc->dst_addr    = (u32)virt_to_phys(dma_out);
87349a2135eSLin Jinhan 	data_desc->dst_len     = dst_len;
874d9332f1cSLin Jinhan 	data_desc->dma_ctrl    = LLI_DMA_CTRL_LAST;
875d9332f1cSLin Jinhan 
876d9332f1cSLin Jinhan 	if (IS_MAC_MODE(rk_mode)) {
877d9332f1cSLin Jinhan 		expt_int = CRYPTO_LIST_DONE_INT_ST;
878d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_LIST_DONE;
879d9332f1cSLin Jinhan 	} else {
88049a2135eSLin Jinhan 		expt_int = CRYPTO_DST_ITEM_DONE_INT_ST;
881d9332f1cSLin Jinhan 		data_desc->dma_ctrl |= LLI_DMA_CTRL_DST_DONE;
882d9332f1cSLin Jinhan 	}
88349a2135eSLin Jinhan 
884c3ce9937SLin Jinhan 	if (rk_mode == RK_MODE_CCM || rk_mode == RK_MODE_GCM) {
885c3ce9937SLin Jinhan 		u32 aad_tmp_len = 0;
886c3ce9937SLin Jinhan 
887c3ce9937SLin Jinhan 		data_desc->user_define = LLI_USER_STRING_START |
888c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
889c3ce9937SLin Jinhan 					 (key_chn << 4);
890c3ce9937SLin Jinhan 
891c3ce9937SLin Jinhan 		aad_desc = align_malloc(sizeof(*aad_desc), LLI_ADDR_ALIGN_SIZE);
892c3ce9937SLin Jinhan 		if (!aad_desc)
893c3ce9937SLin Jinhan 			goto exit;
894c3ce9937SLin Jinhan 
895c3ce9937SLin Jinhan 		memset(aad_desc, 0x00, sizeof(*aad_desc));
896c3ce9937SLin Jinhan 		aad_desc->next_addr = (u32)virt_to_phys(data_desc);
897c3ce9937SLin Jinhan 		aad_desc->user_define = LLI_USER_CPIHER_START |
898c3ce9937SLin Jinhan 					 LLI_USER_STRING_START |
899c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
900c3ce9937SLin Jinhan 					 LLI_USER_STRING_AAD |
901c3ce9937SLin Jinhan 					 (key_chn << 4);
902c3ce9937SLin Jinhan 
903c3ce9937SLin Jinhan 		if (rk_mode == RK_MODE_CCM) {
904c3ce9937SLin Jinhan 			u8 padding[AES_BLOCK_SIZE];
905c3ce9937SLin Jinhan 			u32 padding_size = 0;
906c3ce9937SLin Jinhan 
907c3ce9937SLin Jinhan 			memset(padding, 0x00, sizeof(padding));
908c3ce9937SLin Jinhan 			ccm_aad_padding(aad_len, padding, &padding_size);
909c3ce9937SLin Jinhan 
910c3ce9937SLin Jinhan 			aad_tmp_len = aad_len + AES_BLOCK_SIZE + padding_size;
911c3ce9937SLin Jinhan 			aad_tmp_len = ROUNDUP(aad_tmp_len, AES_BLOCK_SIZE);
912c3ce9937SLin Jinhan 			aad_tmp = align_malloc(aad_tmp_len,
913c3ce9937SLin Jinhan 					       DATA_ADDR_ALIGN_SIZE);
914c3ce9937SLin Jinhan 			if (!aad_tmp)
915c3ce9937SLin Jinhan 				goto exit;
916c3ce9937SLin Jinhan 
917c3ce9937SLin Jinhan 			/* read iv data from reg */
918c3ce9937SLin Jinhan 			get_iv_reg(key_chn, aad_tmp, AES_BLOCK_SIZE);
919c3ce9937SLin Jinhan 			ccm_compose_aad_iv(aad_tmp, tmp_len, tag_len);
920c3ce9937SLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE, padding, padding_size);
921c3ce9937SLin Jinhan 			memset(aad_tmp + aad_tmp_len - AES_BLOCK_SIZE,
922c3ce9937SLin Jinhan 			       0x00, AES_BLOCK_SIZE);
923c3ce9937SLin Jinhan 			memcpy(aad_tmp + AES_BLOCK_SIZE + padding_size,
924c3ce9937SLin Jinhan 			       aad, aad_len);
925c3ce9937SLin Jinhan 		} else {
926c3ce9937SLin Jinhan 			aad_tmp_len = aad_len;
927b83c40a4SLin Jinhan 			if (IS_ALIGNED((ulong)aad, DATA_ADDR_ALIGN_SIZE)) {
928b83c40a4SLin Jinhan 				aad_tmp = (void *)aad;
929b83c40a4SLin Jinhan 			} else {
930c3ce9937SLin Jinhan 				aad_tmp = align_malloc(aad_tmp_len,
931c3ce9937SLin Jinhan 						       DATA_ADDR_ALIGN_SIZE);
932c3ce9937SLin Jinhan 				if (!aad_tmp)
933c3ce9937SLin Jinhan 					goto exit;
934c3ce9937SLin Jinhan 
935c3ce9937SLin Jinhan 				memcpy(aad_tmp, aad, aad_tmp_len);
936b83c40a4SLin Jinhan 			}
937b83c40a4SLin Jinhan 
938c3ce9937SLin Jinhan 			set_aad_len_reg(key_chn, aad_tmp_len);
939c3ce9937SLin Jinhan 			set_pc_len_reg(key_chn, tmp_len);
940c3ce9937SLin Jinhan 		}
941c3ce9937SLin Jinhan 
942c3ce9937SLin Jinhan 		aad_desc->src_addr = (u32)virt_to_phys(aad_tmp);
943c3ce9937SLin Jinhan 		aad_desc->src_len  = aad_tmp_len;
944c3ce9937SLin Jinhan 		crypto_write((u32)virt_to_phys(aad_desc), CRYPTO_DMA_LLI_ADDR);
945c3ce9937SLin Jinhan 		cache_op_inner(DCACHE_AREA_CLEAN, aad_tmp, aad_tmp_len);
946c3ce9937SLin Jinhan 		cache_op_inner(DCACHE_AREA_CLEAN, aad_desc, sizeof(*aad_desc));
947c3ce9937SLin Jinhan 	} else {
948c3ce9937SLin Jinhan 		data_desc->user_define = LLI_USER_CPIHER_START |
949c3ce9937SLin Jinhan 					 LLI_USER_STRING_START |
950c3ce9937SLin Jinhan 					 LLI_USER_STRING_LAST |
951c3ce9937SLin Jinhan 					 (key_chn << 4);
95249a2135eSLin Jinhan 		crypto_write((u32)virt_to_phys(data_desc), CRYPTO_DMA_LLI_ADDR);
953c3ce9937SLin Jinhan 	}
95449a2135eSLin Jinhan 
95549a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, data_desc, sizeof(*data_desc));
95649a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_CLEAN, dma_in, tmp_len);
95749a2135eSLin Jinhan 	cache_op_inner(DCACHE_AREA_INVALIDATE, dma_out, tmp_len);
95849a2135eSLin Jinhan 
95949a2135eSLin Jinhan 	/* din_swap set 1, dout_swap set 1, default 1. */
96049a2135eSLin Jinhan 	crypto_write(0x00030003, CRYPTO_FIFO_CTL);
96149a2135eSLin Jinhan 	crypto_write(CRYPTO_DST_ITEM_DONE_INT_EN | CRYPTO_LIST_DONE_INT_EN,
96249a2135eSLin Jinhan 		     CRYPTO_DMA_INT_EN);
96349a2135eSLin Jinhan 
96449a2135eSLin Jinhan 	reg_ctrl = crypto_read(CRYPTO_BC_CTL) | CRYPTO_BC_ENABLE;
96549a2135eSLin Jinhan 	crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
96649a2135eSLin Jinhan 	crypto_write(0x00010001, CRYPTO_DMA_CTL);//start
96749a2135eSLin Jinhan 
96849a2135eSLin Jinhan 	mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
96949a2135eSLin Jinhan 
97049a2135eSLin Jinhan 	/* wait calc ok */
97149a2135eSLin Jinhan 	ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
97249a2135eSLin Jinhan 			      RK_CRYPTO_TIMEOUT);
97349a2135eSLin Jinhan 	tmp = crypto_read(CRYPTO_DMA_INT_ST);
97449a2135eSLin Jinhan 	crypto_write(tmp, CRYPTO_DMA_INT_ST);
97549a2135eSLin Jinhan 
97649a2135eSLin Jinhan 	if ((tmp & mask) == expt_int) {
97749a2135eSLin Jinhan 		if (out && out != dma_out)
97849a2135eSLin Jinhan 			memcpy(out, dma_out, len);
979d9332f1cSLin Jinhan 
980d9332f1cSLin Jinhan 		if (IS_NEED_TAG(rk_mode)) {
981d9332f1cSLin Jinhan 			ret = WAIT_TAG_VALID(key_chn, RK_CRYPTO_TIMEOUT);
982d9332f1cSLin Jinhan 			get_tag_from_reg(key_chn, tag, AES_BLOCK_SIZE);
983d9332f1cSLin Jinhan 		}
98449a2135eSLin Jinhan 	} else {
9856b53126aSLin Jinhan 		dump_crypto_state(data_desc, tmp, expt_int, in, out, len, ret);
98649a2135eSLin Jinhan 		ret = -1;
98749a2135eSLin Jinhan 	}
98849a2135eSLin Jinhan 
98949a2135eSLin Jinhan exit:
99049a2135eSLin Jinhan 	crypto_write(0xffff0000, CRYPTO_BC_CTL);//bc_ctl disable
99149a2135eSLin Jinhan 	align_free(data_desc);
992c3ce9937SLin Jinhan 	align_free(aad_desc);
993b83c40a4SLin Jinhan 	if (dma_in != in)
99449a2135eSLin Jinhan 		align_free(dma_in);
995b83c40a4SLin Jinhan 	if (out && dma_out != out)
99649a2135eSLin Jinhan 		align_free(dma_out);
997b83c40a4SLin Jinhan 	if (aad && aad != aad_tmp)
998b83c40a4SLin Jinhan 		align_free(aad_tmp);
99949a2135eSLin Jinhan 
100049a2135eSLin Jinhan 	return ret;
100149a2135eSLin Jinhan }
100249a2135eSLin Jinhan 
100349a2135eSLin Jinhan static int hw_aes_init(u32 chn, const u8 *key, const u8 *twk_key, u32 key_len,
100449a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
100549a2135eSLin Jinhan {
100649a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
100749a2135eSLin Jinhan 
1008d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
1009d9332f1cSLin Jinhan 		return -EINVAL;
1010d9332f1cSLin Jinhan 
101149a2135eSLin Jinhan 	if (iv_len > AES_BLOCK_SIZE)
101249a2135eSLin Jinhan 		return -EINVAL;
101349a2135eSLin Jinhan 
1014d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
101549a2135eSLin Jinhan 		if (!iv || iv_len != AES_BLOCK_SIZE)
101649a2135eSLin Jinhan 			return -EINVAL;
101749a2135eSLin Jinhan 	} else {
101849a2135eSLin Jinhan 		iv_len = 0;
101949a2135eSLin Jinhan 	}
102049a2135eSLin Jinhan 
102149a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
102249a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_256)
102349a2135eSLin Jinhan 			return -EINVAL;
102449a2135eSLin Jinhan 
102549a2135eSLin Jinhan 		if (!key || !twk_key)
102649a2135eSLin Jinhan 			return -EINVAL;
102749a2135eSLin Jinhan 	} else {
102849a2135eSLin Jinhan 		if (key_len != AES_KEYSIZE_128 &&
102949a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_192 &&
103049a2135eSLin Jinhan 		    key_len != AES_KEYSIZE_256)
103149a2135eSLin Jinhan 			return -EINVAL;
103249a2135eSLin Jinhan 	}
103349a2135eSLin Jinhan 
103449a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
103549a2135eSLin Jinhan 			      CRYPTO_AES, mode, enc);
103649a2135eSLin Jinhan }
103749a2135eSLin Jinhan 
103849a2135eSLin Jinhan static int hw_sm4_init(u32  chn, const u8 *key, const u8 *twk_key, u32 key_len,
103949a2135eSLin Jinhan 		       const u8 *iv, u32 iv_len, u32 mode, bool enc)
104049a2135eSLin Jinhan {
104149a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
104249a2135eSLin Jinhan 
1043d9332f1cSLin Jinhan 	if (rk_mode > RK_MODE_XTS)
1044d9332f1cSLin Jinhan 		return -EINVAL;
1045d9332f1cSLin Jinhan 
104649a2135eSLin Jinhan 	if (iv_len > SM4_BLOCK_SIZE || key_len != SM4_KEYSIZE)
104749a2135eSLin Jinhan 		return -EINVAL;
104849a2135eSLin Jinhan 
1049d9332f1cSLin Jinhan 	if (IS_NEED_IV(rk_mode)) {
105049a2135eSLin Jinhan 		if (!iv || iv_len != SM4_BLOCK_SIZE)
105149a2135eSLin Jinhan 			return -EINVAL;
105249a2135eSLin Jinhan 	} else {
105349a2135eSLin Jinhan 		iv_len = 0;
105449a2135eSLin Jinhan 	}
105549a2135eSLin Jinhan 
105649a2135eSLin Jinhan 	if (rk_mode == RK_MODE_XTS) {
105749a2135eSLin Jinhan 		if (!key || !twk_key)
105849a2135eSLin Jinhan 			return -EINVAL;
105949a2135eSLin Jinhan 	}
106049a2135eSLin Jinhan 
106149a2135eSLin Jinhan 	return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
106249a2135eSLin Jinhan 			      CRYPTO_SM4, mode, enc);
106349a2135eSLin Jinhan }
106449a2135eSLin Jinhan 
106549a2135eSLin Jinhan int rk_crypto_des(struct udevice *dev, u32 mode, const u8 *key, u32 key_len,
106649a2135eSLin Jinhan 		  const u8 *iv, const u8 *in, u8 *out, u32 len, bool enc)
106749a2135eSLin Jinhan {
106849a2135eSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
106949a2135eSLin Jinhan 	u8 tmp_key[24];
107049a2135eSLin Jinhan 	int ret;
107149a2135eSLin Jinhan 
107249a2135eSLin Jinhan 	if (!is_des_mode(rk_mode))
107349a2135eSLin Jinhan 		return -EINVAL;
107449a2135eSLin Jinhan 
107549a2135eSLin Jinhan 	if (key_len == DES_BLOCK_SIZE || key_len == 3 * DES_BLOCK_SIZE) {
107649a2135eSLin Jinhan 		memcpy(tmp_key, key, key_len);
107749a2135eSLin Jinhan 	} else if (key_len == 2 * DES_BLOCK_SIZE) {
107849a2135eSLin Jinhan 		memcpy(tmp_key, key, 16);
107949a2135eSLin Jinhan 		memcpy(tmp_key + 16, key, 8);
108049a2135eSLin Jinhan 		key_len = 3 * DES_BLOCK_SIZE;
108149a2135eSLin Jinhan 	} else {
108249a2135eSLin Jinhan 		return -EINVAL;
108349a2135eSLin Jinhan 	}
108449a2135eSLin Jinhan 
108549a2135eSLin Jinhan 	ret = hw_cipher_init(0, tmp_key, NULL, key_len, iv, DES_BLOCK_SIZE,
108649a2135eSLin Jinhan 			     CRYPTO_DES, mode, enc);
108749a2135eSLin Jinhan 	if (ret)
108849a2135eSLin Jinhan 		goto exit;
108949a2135eSLin Jinhan 
109049a2135eSLin Jinhan 	ret = hw_cipher_crypt(in, out, len, NULL, 0,
109149a2135eSLin Jinhan 			      NULL, 0, mode);
109249a2135eSLin Jinhan 
109349a2135eSLin Jinhan exit:
109449a2135eSLin Jinhan 	return ret;
109549a2135eSLin Jinhan }
109649a2135eSLin Jinhan 
109749a2135eSLin Jinhan int rk_crypto_aes(struct udevice *dev, u32 mode,
109849a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
109949a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
110049a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
110149a2135eSLin Jinhan {
110249a2135eSLin Jinhan 	int ret;
110349a2135eSLin Jinhan 
110449a2135eSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
110549a2135eSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
110649a2135eSLin Jinhan 	if (key_len == AES_KEYSIZE_192)
110749a2135eSLin Jinhan 		return -EINVAL;
110849a2135eSLin Jinhan #endif
110949a2135eSLin Jinhan 
111049a2135eSLin Jinhan 	ret = hw_aes_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
111149a2135eSLin Jinhan 	if (ret)
111249a2135eSLin Jinhan 		return ret;
111349a2135eSLin Jinhan 
111449a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0,
111549a2135eSLin Jinhan 			       NULL, 0, mode);
111649a2135eSLin Jinhan }
111749a2135eSLin Jinhan 
111849a2135eSLin Jinhan int rk_crypto_sm4(struct udevice *dev, u32 mode,
111949a2135eSLin Jinhan 		  const u8 *key, const u8 *twk_key, u32 key_len,
112049a2135eSLin Jinhan 		  const u8 *iv, u32 iv_len,
112149a2135eSLin Jinhan 		  const u8 *in, u8 *out, u32 len, bool enc)
112249a2135eSLin Jinhan {
112349a2135eSLin Jinhan 	int ret;
112449a2135eSLin Jinhan 
112549a2135eSLin Jinhan 	ret = hw_sm4_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
112649a2135eSLin Jinhan 	if (ret)
112749a2135eSLin Jinhan 		return ret;
112849a2135eSLin Jinhan 
112949a2135eSLin Jinhan 	return hw_cipher_crypt(in, out, len, NULL, 0, NULL, 0, mode);
113049a2135eSLin Jinhan }
113149a2135eSLin Jinhan 
113249a2135eSLin Jinhan int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx,
113349a2135eSLin Jinhan 			   const u8 *in, u8 *out, u32 len, bool enc)
113449a2135eSLin Jinhan {
113549a2135eSLin Jinhan 	switch (ctx->algo) {
113649a2135eSLin Jinhan 	case CRYPTO_DES:
113749a2135eSLin Jinhan 		return rk_crypto_des(dev, ctx->mode, ctx->key, ctx->key_len,
113849a2135eSLin Jinhan 				     ctx->iv, in, out, len, enc);
113949a2135eSLin Jinhan 	case CRYPTO_AES:
114049a2135eSLin Jinhan 		return rk_crypto_aes(dev, ctx->mode,
114149a2135eSLin Jinhan 				     ctx->key, ctx->twk_key, ctx->key_len,
114249a2135eSLin Jinhan 				     ctx->iv, ctx->iv_len, in, out, len, enc);
114349a2135eSLin Jinhan 	case CRYPTO_SM4:
114449a2135eSLin Jinhan 		return rk_crypto_sm4(dev, ctx->mode,
114549a2135eSLin Jinhan 				     ctx->key, ctx->twk_key, ctx->key_len,
114649a2135eSLin Jinhan 				     ctx->iv, ctx->iv_len, in, out, len, enc);
114749a2135eSLin Jinhan 	default:
114849a2135eSLin Jinhan 		return -EINVAL;
114949a2135eSLin Jinhan 	}
115049a2135eSLin Jinhan }
1151d9332f1cSLin Jinhan 
1152d9332f1cSLin Jinhan int rk_crypto_mac(struct udevice *dev, u32 algo, u32 mode,
1153d9332f1cSLin Jinhan 		  const u8 *key, u32 key_len,
1154d9332f1cSLin Jinhan 		  const u8 *in, u32 len, u8 *tag)
1155d9332f1cSLin Jinhan {
1156d9332f1cSLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1157d9332f1cSLin Jinhan 	int ret;
1158d9332f1cSLin Jinhan 
1159d9332f1cSLin Jinhan 	if (!IS_MAC_MODE(rk_mode))
1160d9332f1cSLin Jinhan 		return -EINVAL;
1161d9332f1cSLin Jinhan 
1162d9332f1cSLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1163d9332f1cSLin Jinhan 		return -EINVAL;
1164d9332f1cSLin Jinhan 
1165d9332f1cSLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1166d9332f1cSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1167d9332f1cSLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1168d9332f1cSLin Jinhan 		return -EINVAL;
1169d9332f1cSLin Jinhan #endif
1170d9332f1cSLin Jinhan 
1171d9332f1cSLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, NULL, 0,
1172d9332f1cSLin Jinhan 			     algo, mode, true);
1173d9332f1cSLin Jinhan 	if (ret)
1174d9332f1cSLin Jinhan 		return ret;
1175d9332f1cSLin Jinhan 
1176d9332f1cSLin Jinhan 	return hw_cipher_crypt(in, NULL, len, NULL, 0,
1177d9332f1cSLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1178d9332f1cSLin Jinhan }
1179d9332f1cSLin Jinhan 
1180d9332f1cSLin Jinhan int rockchip_crypto_mac(struct udevice *dev, cipher_context *ctx,
1181d9332f1cSLin Jinhan 			const u8 *in, u32 len, u8 *tag)
1182d9332f1cSLin Jinhan {
1183d9332f1cSLin Jinhan 	return rk_crypto_mac(dev, ctx->algo, ctx->mode,
1184d9332f1cSLin Jinhan 			     ctx->key, ctx->key_len, in, len, tag);
1185d9332f1cSLin Jinhan }
1186d9332f1cSLin Jinhan 
1187c3ce9937SLin Jinhan int rk_crypto_ae(struct udevice *dev, u32 algo, u32 mode,
1188c3ce9937SLin Jinhan 		 const u8 *key, u32 key_len, const u8 *nonce, u32 nonce_len,
1189c3ce9937SLin Jinhan 		 const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1190c3ce9937SLin Jinhan 		 u8 *out, u8 *tag)
1191c3ce9937SLin Jinhan {
1192c3ce9937SLin Jinhan 	u32 rk_mode = RK_GET_RK_MODE(mode);
1193c3ce9937SLin Jinhan 	int ret;
1194c3ce9937SLin Jinhan 
1195c3ce9937SLin Jinhan 	if (!IS_AE_MODE(rk_mode))
1196c3ce9937SLin Jinhan 		return -EINVAL;
1197c3ce9937SLin Jinhan 
1198c3ce9937SLin Jinhan 	if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1199c3ce9937SLin Jinhan 		return -EINVAL;
1200c3ce9937SLin Jinhan 
1201c3ce9937SLin Jinhan 	/* RV1126/RV1109 do not support aes-192 */
1202c3ce9937SLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1203c3ce9937SLin Jinhan 	if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1204c3ce9937SLin Jinhan 		return -EINVAL;
1205c3ce9937SLin Jinhan #endif
1206c3ce9937SLin Jinhan 
1207c3ce9937SLin Jinhan 	ret = hw_cipher_init(g_key_chn, key, NULL, key_len, nonce, nonce_len,
1208c3ce9937SLin Jinhan 			     algo, mode, true);
1209c3ce9937SLin Jinhan 	if (ret)
1210c3ce9937SLin Jinhan 		return ret;
1211c3ce9937SLin Jinhan 
1212c3ce9937SLin Jinhan 	return hw_cipher_crypt(in, out, len, aad, aad_len,
1213c3ce9937SLin Jinhan 			       tag, AES_BLOCK_SIZE, mode);
1214c3ce9937SLin Jinhan }
1215c3ce9937SLin Jinhan 
1216c3ce9937SLin Jinhan int rockchip_crypto_ae(struct udevice *dev, cipher_context *ctx,
1217c3ce9937SLin Jinhan 		       const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1218c3ce9937SLin Jinhan 		       u8 *out, u8 *tag)
1219c3ce9937SLin Jinhan 
1220c3ce9937SLin Jinhan {
1221c3ce9937SLin Jinhan 	return rk_crypto_ae(dev, ctx->algo, ctx->mode, ctx->key, ctx->key_len,
1222c3ce9937SLin Jinhan 			    ctx->iv, ctx->iv_len, in, len,
1223c3ce9937SLin Jinhan 			    aad, aad_len, out, tag);
1224c3ce9937SLin Jinhan }
1225c3ce9937SLin Jinhan 
122649a2135eSLin Jinhan #endif
122749a2135eSLin Jinhan 
1228864e581cSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1229b353a43cSLin Jinhan static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx,
1230b353a43cSLin Jinhan 				      u8 *sign, u8 *output)
1231b353a43cSLin Jinhan {
1232b353a43cSLin Jinhan 	struct mpa_num *mpa_m = NULL, *mpa_e = NULL, *mpa_n = NULL;
1233b353a43cSLin Jinhan 	struct mpa_num *mpa_c = NULL, *mpa_result = NULL;
1234b353a43cSLin Jinhan 	u32 n_bits, n_words;
1235b353a43cSLin Jinhan 	u32 *rsa_result;
1236b353a43cSLin Jinhan 	int ret;
1237b353a43cSLin Jinhan 
1238b353a43cSLin Jinhan 	if (!ctx)
1239b353a43cSLin Jinhan 		return -EINVAL;
1240b353a43cSLin Jinhan 
1241b353a43cSLin Jinhan 	if (ctx->algo != CRYPTO_RSA512 &&
1242b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA1024 &&
1243b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA2048 &&
1244b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA3072 &&
1245b353a43cSLin Jinhan 	    ctx->algo != CRYPTO_RSA4096)
1246b353a43cSLin Jinhan 		return -EINVAL;
1247b353a43cSLin Jinhan 
1248b353a43cSLin Jinhan 	n_bits = crypto_algo_nbits(ctx->algo);
1249b353a43cSLin Jinhan 	n_words = BITS2WORD(n_bits);
1250b353a43cSLin Jinhan 
1251b353a43cSLin Jinhan 	rsa_result = malloc(BITS2BYTE(n_bits));
1252b353a43cSLin Jinhan 	if (!rsa_result)
1253b353a43cSLin Jinhan 		return -ENOMEM;
1254b353a43cSLin Jinhan 
1255b353a43cSLin Jinhan 	memset(rsa_result, 0x00, BITS2BYTE(n_bits));
1256b353a43cSLin Jinhan 
1257b353a43cSLin Jinhan 	ret = rk_mpa_alloc(&mpa_m);
1258b353a43cSLin Jinhan 	ret |= rk_mpa_alloc(&mpa_e);
1259b353a43cSLin Jinhan 	ret |= rk_mpa_alloc(&mpa_n);
1260b353a43cSLin Jinhan 	ret |= rk_mpa_alloc(&mpa_c);
1261b353a43cSLin Jinhan 	ret |= rk_mpa_alloc(&mpa_result);
1262b353a43cSLin Jinhan 	if (ret)
1263b353a43cSLin Jinhan 		goto exit;
1264b353a43cSLin Jinhan 
1265b353a43cSLin Jinhan 	mpa_m->d = (void *)sign;
1266b353a43cSLin Jinhan 	mpa_e->d = (void *)ctx->e;
1267b353a43cSLin Jinhan 	mpa_n->d = (void *)ctx->n;
1268b353a43cSLin Jinhan 	mpa_c->d = (void *)ctx->c;
1269b353a43cSLin Jinhan 	mpa_result->d = (void *)rsa_result;
1270b353a43cSLin Jinhan 
1271b353a43cSLin Jinhan 	mpa_m->size = n_words;
1272b353a43cSLin Jinhan 	mpa_e->size = n_words;
1273b353a43cSLin Jinhan 	mpa_n->size = n_words;
1274b353a43cSLin Jinhan 	mpa_c->size = n_words;
1275b353a43cSLin Jinhan 	mpa_result->size = n_words;
1276b353a43cSLin Jinhan 
1277b353a43cSLin Jinhan 	ret = rk_exptmod_np(mpa_m, mpa_e, mpa_n, mpa_c, mpa_result);
1278b353a43cSLin Jinhan 	if (!ret)
1279b353a43cSLin Jinhan 		memcpy(output, rsa_result, BITS2BYTE(n_bits));
1280b353a43cSLin Jinhan 
1281b353a43cSLin Jinhan exit:
1282b353a43cSLin Jinhan 	free(rsa_result);
1283b353a43cSLin Jinhan 	rk_mpa_free(&mpa_m);
1284b353a43cSLin Jinhan 	rk_mpa_free(&mpa_e);
1285b353a43cSLin Jinhan 	rk_mpa_free(&mpa_n);
1286b353a43cSLin Jinhan 	rk_mpa_free(&mpa_c);
1287b353a43cSLin Jinhan 	rk_mpa_free(&mpa_result);
1288b353a43cSLin Jinhan 
1289b353a43cSLin Jinhan 	return ret;
1290b353a43cSLin Jinhan }
1291864e581cSLin Jinhan #endif
1292b353a43cSLin Jinhan 
1293b353a43cSLin Jinhan static const struct dm_crypto_ops rockchip_crypto_ops = {
1294b353a43cSLin Jinhan 	.capability   = rockchip_crypto_capability,
1295b353a43cSLin Jinhan 	.sha_init     = rockchip_crypto_sha_init,
1296b353a43cSLin Jinhan 	.sha_update   = rockchip_crypto_sha_update,
1297b353a43cSLin Jinhan 	.sha_final    = rockchip_crypto_sha_final,
129849a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1299b353a43cSLin Jinhan 	.rsa_verify   = rockchip_crypto_rsa_verify,
130049a2135eSLin Jinhan #endif
130149a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
130249a2135eSLin Jinhan 	.hmac_init    = rockchip_crypto_hmac_init,
130349a2135eSLin Jinhan 	.hmac_update  = rockchip_crypto_hmac_update,
130449a2135eSLin Jinhan 	.hmac_final   = rockchip_crypto_hmac_final,
130549a2135eSLin Jinhan #endif
130649a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
130749a2135eSLin Jinhan 	.cipher_crypt = rockchip_crypto_cipher,
1308d9332f1cSLin Jinhan 	.cipher_mac = rockchip_crypto_mac,
1309c3ce9937SLin Jinhan 	.cipher_ae  = rockchip_crypto_ae,
131049a2135eSLin Jinhan #endif
1311b353a43cSLin Jinhan };
1312b353a43cSLin Jinhan 
1313b353a43cSLin Jinhan /*
1314b353a43cSLin Jinhan  * Only use "clocks" to parse crypto clock id and use rockchip_get_clk().
1315b353a43cSLin Jinhan  * Because we always add crypto node in U-Boot dts, when kernel dtb enabled :
1316b353a43cSLin Jinhan  *
1317b353a43cSLin Jinhan  *   1. There is cru phandle mismatch between U-Boot and kernel dtb;
1318b353a43cSLin Jinhan  *   2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property;
1319b353a43cSLin Jinhan  */
1320b353a43cSLin Jinhan static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev)
1321b353a43cSLin Jinhan {
1322b353a43cSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1323b353a43cSLin Jinhan 	int len, ret = -EINVAL;
1324b353a43cSLin Jinhan 
1325*a24b2aebSLin Jinhan 	memset(priv, 0x00, sizeof(*priv));
1326*a24b2aebSLin Jinhan 
1327*a24b2aebSLin Jinhan 	priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev);
1328*a24b2aebSLin Jinhan 	if (priv->reg == FDT_ADDR_T_NONE)
1329*a24b2aebSLin Jinhan 		return -EINVAL;
1330*a24b2aebSLin Jinhan 
1331*a24b2aebSLin Jinhan 	crypto_base = priv->reg;
1332*a24b2aebSLin Jinhan 
1333*a24b2aebSLin Jinhan 	/* if there is no clocks in dts, just skip it */
1334b353a43cSLin Jinhan 	if (!dev_read_prop(dev, "clocks", &len)) {
1335b353a43cSLin Jinhan 		printf("Can't find \"clocks\" property\n");
1336*a24b2aebSLin Jinhan 		return 0;
1337b353a43cSLin Jinhan 	}
1338b353a43cSLin Jinhan 
1339b353a43cSLin Jinhan 	memset(priv, 0x00, sizeof(*priv));
1340b353a43cSLin Jinhan 	priv->clocks = malloc(len);
1341b353a43cSLin Jinhan 	if (!priv->clocks)
1342b353a43cSLin Jinhan 		return -ENOMEM;
1343b353a43cSLin Jinhan 
1344b353a43cSLin Jinhan 	priv->nclocks = len / sizeof(u32);
1345b353a43cSLin Jinhan 	if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks,
1346b353a43cSLin Jinhan 			       priv->nclocks)) {
1347b353a43cSLin Jinhan 		printf("Can't read \"clocks\" property\n");
1348b353a43cSLin Jinhan 		ret = -EINVAL;
1349b353a43cSLin Jinhan 		goto exit;
1350b353a43cSLin Jinhan 	}
1351b353a43cSLin Jinhan 
1352b353a43cSLin Jinhan 	if (!dev_read_prop(dev, "clock-frequency", &len)) {
1353b353a43cSLin Jinhan 		printf("Can't find \"clock-frequency\" property\n");
1354b353a43cSLin Jinhan 		ret = -EINVAL;
1355b353a43cSLin Jinhan 		goto exit;
1356b353a43cSLin Jinhan 	}
1357b353a43cSLin Jinhan 
1358b353a43cSLin Jinhan 	priv->frequencies = malloc(len);
1359b353a43cSLin Jinhan 	if (!priv->frequencies) {
1360b353a43cSLin Jinhan 		ret = -ENOMEM;
1361b353a43cSLin Jinhan 		goto exit;
1362b353a43cSLin Jinhan 	}
1363b353a43cSLin Jinhan 
1364b353a43cSLin Jinhan 	priv->nclocks = len / sizeof(u32);
1365b353a43cSLin Jinhan 	if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies,
1366b353a43cSLin Jinhan 			       priv->nclocks)) {
1367b353a43cSLin Jinhan 		printf("Can't read \"clock-frequency\" property\n");
1368b353a43cSLin Jinhan 		ret = -EINVAL;
1369b353a43cSLin Jinhan 		goto exit;
1370b353a43cSLin Jinhan 	}
1371b353a43cSLin Jinhan 
1372b353a43cSLin Jinhan 	return 0;
1373b353a43cSLin Jinhan exit:
1374b353a43cSLin Jinhan 	if (priv->clocks)
1375b353a43cSLin Jinhan 		free(priv->clocks);
1376b353a43cSLin Jinhan 
1377b353a43cSLin Jinhan 	if (priv->frequencies)
1378b353a43cSLin Jinhan 		free(priv->frequencies);
1379b353a43cSLin Jinhan 
1380b353a43cSLin Jinhan 	return ret;
1381b353a43cSLin Jinhan }
1382b353a43cSLin Jinhan 
1383*a24b2aebSLin Jinhan static int rk_crypto_set_clk(struct rockchip_crypto_priv *priv)
1384b353a43cSLin Jinhan {
1385*a24b2aebSLin Jinhan 	int i, ret;
1386b353a43cSLin Jinhan 	u32* clocks;
1387b353a43cSLin Jinhan 
1388*a24b2aebSLin Jinhan 	if (!priv->clocks && priv->nclocks == 0)
1389*a24b2aebSLin Jinhan 		return 0;
139049a2135eSLin Jinhan 
1391*a24b2aebSLin Jinhan #ifdef CONFIG_CLK_SCMI
1392*a24b2aebSLin Jinhan 	ret = rockchip_get_scmi_clk(&priv->clk.dev);
1393*a24b2aebSLin Jinhan #else
1394b353a43cSLin Jinhan 	ret = rockchip_get_clk(&priv->clk.dev);
1395*a24b2aebSLin Jinhan #endif
1396*a24b2aebSLin Jinhan 	if (priv->nclocks && ret) {
1397b353a43cSLin Jinhan 		printf("Failed to get clk device, ret=%d\n", ret);
1398b353a43cSLin Jinhan 		return ret;
1399b353a43cSLin Jinhan 	}
1400b353a43cSLin Jinhan 
1401b353a43cSLin Jinhan 	clocks = (u32 *)priv->clocks;
1402b353a43cSLin Jinhan 	for (i = 0; i < priv->nclocks; i++) {
1403b353a43cSLin Jinhan 		priv->clk.id = clocks[i * 2 + 1];
1404b353a43cSLin Jinhan 		ret = clk_set_rate(&priv->clk, priv->frequencies[i]);
1405b353a43cSLin Jinhan 		if (ret < 0) {
1406b353a43cSLin Jinhan 			printf("%s: Failed to set clk(%ld): ret=%d\n",
1407b353a43cSLin Jinhan 			       __func__, priv->clk.id, ret);
1408b353a43cSLin Jinhan 			return ret;
1409b353a43cSLin Jinhan 		}
1410b353a43cSLin Jinhan 	}
1411b353a43cSLin Jinhan 
1412*a24b2aebSLin Jinhan 	return 0;
1413*a24b2aebSLin Jinhan }
1414*a24b2aebSLin Jinhan 
1415*a24b2aebSLin Jinhan static int rockchip_crypto_probe(struct udevice *dev)
1416*a24b2aebSLin Jinhan {
1417*a24b2aebSLin Jinhan 	struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1418*a24b2aebSLin Jinhan 	struct rk_crypto_soc_data *sdata;
1419*a24b2aebSLin Jinhan 	int ret = 0;
1420*a24b2aebSLin Jinhan 
1421*a24b2aebSLin Jinhan 	sdata = (struct rk_crypto_soc_data *)dev_get_driver_data(dev);
1422*a24b2aebSLin Jinhan 	priv->soc_data = sdata;
1423*a24b2aebSLin Jinhan 
1424*a24b2aebSLin Jinhan 	priv->hw_ctx = memalign(LLI_ADDR_ALIGN_SIZE,
1425*a24b2aebSLin Jinhan 				sizeof(struct rk_hash_ctx));
1426*a24b2aebSLin Jinhan 	if (!priv->hw_ctx)
1427*a24b2aebSLin Jinhan 		return -ENOMEM;
1428*a24b2aebSLin Jinhan 
1429*a24b2aebSLin Jinhan 	ret = rk_crypto_set_clk(priv);
1430*a24b2aebSLin Jinhan 	if (ret)
1431*a24b2aebSLin Jinhan 		return ret;
1432*a24b2aebSLin Jinhan 
1433b353a43cSLin Jinhan 	hw_crypto_reset();
1434b353a43cSLin Jinhan 
1435b353a43cSLin Jinhan 	return 0;
1436b353a43cSLin Jinhan }
1437b353a43cSLin Jinhan 
143849a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base = {
143949a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
144049a2135eSLin Jinhan 		      CRYPTO_SHA1 |
144149a2135eSLin Jinhan 		      CRYPTO_SHA256 |
144249a2135eSLin Jinhan 		      CRYPTO_SHA512 |
144349a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
144449a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
144549a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
144649a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
144749a2135eSLin Jinhan 		      CRYPTO_RSA512 |
144849a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
144949a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
145049a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
145149a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
145249a2135eSLin Jinhan 		      CRYPTO_DES |
145349a2135eSLin Jinhan 		      CRYPTO_AES,
145449a2135eSLin Jinhan };
145549a2135eSLin Jinhan 
145649a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base_sm = {
145749a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
145849a2135eSLin Jinhan 		      CRYPTO_SHA1 |
145949a2135eSLin Jinhan 		      CRYPTO_SHA256 |
146049a2135eSLin Jinhan 		      CRYPTO_SHA512 |
146149a2135eSLin Jinhan 		      CRYPTO_SM3 |
146249a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
146349a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
146449a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
146549a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA512 |
146649a2135eSLin Jinhan 		      CRYPTO_HMAC_SM3 |
146749a2135eSLin Jinhan 		      CRYPTO_RSA512 |
146849a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
146949a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
147049a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
147149a2135eSLin Jinhan 		      CRYPTO_RSA4096 |
147249a2135eSLin Jinhan 		      CRYPTO_DES |
147349a2135eSLin Jinhan 		      CRYPTO_AES |
147449a2135eSLin Jinhan 		      CRYPTO_SM4,
147549a2135eSLin Jinhan };
147649a2135eSLin Jinhan 
147749a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_rk1808 = {
147849a2135eSLin Jinhan 	.capability = CRYPTO_MD5 |
147949a2135eSLin Jinhan 		      CRYPTO_SHA1 |
148049a2135eSLin Jinhan 		      CRYPTO_SHA256 |
148149a2135eSLin Jinhan 		      CRYPTO_HMAC_MD5 |
148249a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA1 |
148349a2135eSLin Jinhan 		      CRYPTO_HMAC_SHA256 |
148449a2135eSLin Jinhan 		      CRYPTO_RSA512 |
148549a2135eSLin Jinhan 		      CRYPTO_RSA1024 |
148649a2135eSLin Jinhan 		      CRYPTO_RSA2048 |
148749a2135eSLin Jinhan 		      CRYPTO_RSA3072 |
148849a2135eSLin Jinhan 		      CRYPTO_RSA4096,
148949a2135eSLin Jinhan };
149049a2135eSLin Jinhan 
1491b353a43cSLin Jinhan static const struct udevice_id rockchip_crypto_ids[] = {
149249a2135eSLin Jinhan 	{
149349a2135eSLin Jinhan 		.compatible = "rockchip,px30-crypto",
149449a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
149549a2135eSLin Jinhan 	},
149649a2135eSLin Jinhan 	{
149749a2135eSLin Jinhan 		.compatible = "rockchip,rk1808-crypto",
149849a2135eSLin Jinhan 		.data = (ulong)&soc_data_rk1808
149949a2135eSLin Jinhan 	},
150049a2135eSLin Jinhan 	{
150149a2135eSLin Jinhan 		.compatible = "rockchip,rk3308-crypto",
150249a2135eSLin Jinhan 		.data = (ulong)&soc_data_base
150349a2135eSLin Jinhan 	},
150449a2135eSLin Jinhan 	{
150549a2135eSLin Jinhan 		.compatible = "rockchip,rv1126-crypto",
150649a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
150749a2135eSLin Jinhan 	},
150849a2135eSLin Jinhan 	{
150949a2135eSLin Jinhan 		.compatible = "rockchip,rk3568-crypto",
151049a2135eSLin Jinhan 		.data = (ulong)&soc_data_base_sm
151149a2135eSLin Jinhan 	},
15125b3e3895SLin Jinhan 	{
15135b3e3895SLin Jinhan 		.compatible = "rockchip,rk3588-crypto",
15145b3e3895SLin Jinhan 		.data = (ulong)&soc_data_base_sm
15155b3e3895SLin Jinhan 	},
1516b353a43cSLin Jinhan 	{ }
1517b353a43cSLin Jinhan };
1518b353a43cSLin Jinhan 
1519b353a43cSLin Jinhan U_BOOT_DRIVER(rockchip_crypto_v2) = {
1520b353a43cSLin Jinhan 	.name		= "rockchip_crypto_v2",
1521b353a43cSLin Jinhan 	.id		= UCLASS_CRYPTO,
1522b353a43cSLin Jinhan 	.of_match	= rockchip_crypto_ids,
1523b353a43cSLin Jinhan 	.ops		= &rockchip_crypto_ops,
1524b353a43cSLin Jinhan 	.probe		= rockchip_crypto_probe,
1525b353a43cSLin Jinhan 	.ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata,
1526b353a43cSLin Jinhan 	.priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv),
1527b353a43cSLin Jinhan };
1528