1b353a43cSLin Jinhan // SPDX-License-Identifier: GPL-2.0
2b353a43cSLin Jinhan /*
3b353a43cSLin Jinhan * Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
4b353a43cSLin Jinhan */
5b353a43cSLin Jinhan
6b353a43cSLin Jinhan #include <common.h>
7b353a43cSLin Jinhan #include <clk.h>
8b353a43cSLin Jinhan #include <crypto.h>
9b353a43cSLin Jinhan #include <dm.h>
10b353a43cSLin Jinhan #include <asm/io.h>
11dd7763a8SFinley Xiao #include <clk-uclass.h>
12b353a43cSLin Jinhan #include <asm/arch/hardware.h>
13b353a43cSLin Jinhan #include <asm/arch/clock.h>
1402b4cf42SLin Jinhan #include <rockchip/crypto_ecc.h>
15c48f1acfSLin Jinhan #include <rockchip/crypto_hash_cache.h>
16b353a43cSLin Jinhan #include <rockchip/crypto_v2.h>
17b353a43cSLin Jinhan #include <rockchip/crypto_v2_pka.h>
18b353a43cSLin Jinhan
19c48f1acfSLin Jinhan #define RK_HASH_CTX_MAGIC 0x1A1A1A1A
20c48f1acfSLin Jinhan
21e0c259feSLin Jinhan #define CRYPTO_MAJOR_VER(ver) ((ver) & 0x0f000000)
22e0c259feSLin Jinhan
23e0c259feSLin Jinhan #define CRYPTO_MAJOR_VER_3 0x03000000
24e0c259feSLin Jinhan #define CRYPTO_MAJOR_VER_4 0x04000000
253cbec420SJoseph Chen #ifdef CONFIG_ROCKCHIP_RK3562
263cbec420SJoseph Chen #define CRYPTO_S_BY_KEYLAD_BASE 0xFF8A8000
273cbec420SJoseph Chen #endif
28e0c259feSLin Jinhan
2949a2135eSLin Jinhan #ifdef DEBUG
3049a2135eSLin Jinhan #define IMSG(format, ...) printf("[%s, %05d]-trace: " format "\n", \
3149a2135eSLin Jinhan __func__, __LINE__, ##__VA_ARGS__)
3249a2135eSLin Jinhan #else
3349a2135eSLin Jinhan #define IMSG(format, ...)
3449a2135eSLin Jinhan #endif
35c48f1acfSLin Jinhan
36c48f1acfSLin Jinhan struct crypto_lli_desc {
37c48f1acfSLin Jinhan u32 src_addr;
38c48f1acfSLin Jinhan u32 src_len;
39c48f1acfSLin Jinhan u32 dst_addr;
40c48f1acfSLin Jinhan u32 dst_len;
41c48f1acfSLin Jinhan u32 user_define;
42c48f1acfSLin Jinhan u32 reserve;
43c48f1acfSLin Jinhan u32 dma_ctrl;
44c48f1acfSLin Jinhan u32 next_addr;
45c48f1acfSLin Jinhan };
46c48f1acfSLin Jinhan
47c48f1acfSLin Jinhan struct rk_hash_ctx {
48c48f1acfSLin Jinhan struct crypto_lli_desc data_lli; /* lli desc */
49c48f1acfSLin Jinhan struct crypto_hash_cache *hash_cache;
50c48f1acfSLin Jinhan u32 magic; /* to check ctx */
51c48f1acfSLin Jinhan u32 algo; /* hash algo */
52c48f1acfSLin Jinhan u8 digest_size; /* hash out length */
53c48f1acfSLin Jinhan u8 reserved[3];
54c48f1acfSLin Jinhan };
55c48f1acfSLin Jinhan
5649a2135eSLin Jinhan struct rk_crypto_soc_data {
5749a2135eSLin Jinhan u32 capability;
5858432b6fSLin Jinhan u32 (*dynamic_cap)(void);
5949a2135eSLin Jinhan };
6049a2135eSLin Jinhan
61b353a43cSLin Jinhan struct rockchip_crypto_priv {
62b353a43cSLin Jinhan fdt_addr_t reg;
63b353a43cSLin Jinhan u32 frequency;
64b353a43cSLin Jinhan char *clocks;
65b353a43cSLin Jinhan u32 *frequencies;
66b353a43cSLin Jinhan u32 nclocks;
67da703fb5SLin Jinhan u32 freq_nclocks;
68b353a43cSLin Jinhan u32 length;
691606a214SLin Jinhan struct rk_hash_ctx *hw_ctx;
7049a2135eSLin Jinhan struct rk_crypto_soc_data *soc_data;
7136e17db4Stroy.lin
7236e17db4Stroy.lin u16 secure;
7336e17db4Stroy.lin u16 enabled;
74b353a43cSLin Jinhan };
75b353a43cSLin Jinhan
7649a2135eSLin Jinhan #define LLI_ADDR_ALIGN_SIZE 8
7749a2135eSLin Jinhan #define DATA_ADDR_ALIGN_SIZE 8
7849a2135eSLin Jinhan #define DATA_LEN_ALIGN_SIZE 64
791606a214SLin Jinhan
80086e8fa8SLin Jinhan /* crypto timeout 500ms, must support more than 32M data per times*/
81086e8fa8SLin Jinhan #define HASH_UPDATE_LIMIT (32 * 1024 * 1024)
8249a2135eSLin Jinhan #define RK_CRYPTO_TIMEOUT 500000
83b353a43cSLin Jinhan
8449a2135eSLin Jinhan #define RK_POLL_TIMEOUT(condition, timeout) \
8549a2135eSLin Jinhan ({ \
8649a2135eSLin Jinhan int time_out = timeout; \
87b353a43cSLin Jinhan while (condition) { \
8849a2135eSLin Jinhan if (--time_out <= 0) { \
891606a214SLin Jinhan debug("[%s] %d: time out!\n", __func__,\
90b353a43cSLin Jinhan __LINE__); \
91b353a43cSLin Jinhan break; \
92b353a43cSLin Jinhan } \
93b353a43cSLin Jinhan udelay(1); \
94b353a43cSLin Jinhan } \
9549a2135eSLin Jinhan (time_out <= 0) ? -ETIMEDOUT : 0; \
9649a2135eSLin Jinhan })
97b353a43cSLin Jinhan
98d9332f1cSLin Jinhan #define WAIT_TAG_VALID(channel, timeout) ({ \
99d9332f1cSLin Jinhan u32 tag_mask = CRYPTO_CH0_TAG_VALID << (channel);\
100e0c259feSLin Jinhan int ret = 0;\
101e0c259feSLin Jinhan if (is_check_tag_valid()) { \
102d9332f1cSLin Jinhan ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_TAG_VALID) & tag_mask),\
103d9332f1cSLin Jinhan timeout);\
104e0c259feSLin Jinhan } \
105d9332f1cSLin Jinhan crypto_write(crypto_read(CRYPTO_TAG_VALID) & tag_mask, CRYPTO_TAG_VALID);\
106d9332f1cSLin Jinhan ret;\
107d9332f1cSLin Jinhan })
108d9332f1cSLin Jinhan
109b353a43cSLin Jinhan #define virt_to_phys(addr) (((unsigned long)addr) & 0xffffffff)
110b353a43cSLin Jinhan #define phys_to_virt(addr, area) ((unsigned long)addr)
111b353a43cSLin Jinhan
11249a2135eSLin Jinhan #define align_malloc(bytes, alignment) memalign(alignment, bytes)
113dbca2fe7SLin Jinhan #define align_free(addr) do {if (addr) free(addr);} while (0)
11449a2135eSLin Jinhan
11549a2135eSLin Jinhan #define ROUNDUP(size, alignment) round_up(size, alignment)
11649a2135eSLin Jinhan #define cache_op_inner(type, addr, size) \
11749a2135eSLin Jinhan crypto_flush_cacheline((ulong)addr, size)
11849a2135eSLin Jinhan
119d9332f1cSLin Jinhan #define IS_NEED_IV(rk_mode) ((rk_mode) != RK_MODE_ECB && \
120d9332f1cSLin Jinhan (rk_mode) != RK_MODE_CMAC && \
121d9332f1cSLin Jinhan (rk_mode) != RK_MODE_CBC_MAC)
122d9332f1cSLin Jinhan
123d9332f1cSLin Jinhan #define IS_NEED_TAG(rk_mode) ((rk_mode) == RK_MODE_CMAC || \
124c3ce9937SLin Jinhan (rk_mode) == RK_MODE_CBC_MAC || \
125c3ce9937SLin Jinhan (rk_mode) == RK_MODE_CCM || \
126c3ce9937SLin Jinhan (rk_mode) == RK_MODE_GCM)
127d9332f1cSLin Jinhan
128d9332f1cSLin Jinhan #define IS_MAC_MODE(rk_mode) ((rk_mode) == RK_MODE_CMAC || \
129d9332f1cSLin Jinhan (rk_mode) == RK_MODE_CBC_MAC)
130d9332f1cSLin Jinhan
131c3ce9937SLin Jinhan #define IS_AE_MODE(rk_mode) ((rk_mode) == RK_MODE_CCM || \
132c3ce9937SLin Jinhan (rk_mode) == RK_MODE_GCM)
133c3ce9937SLin Jinhan
134b353a43cSLin Jinhan fdt_addr_t crypto_base;
135e0c259feSLin Jinhan static uint32_t g_crypto_version;
136e0c259feSLin Jinhan
is_check_hash_valid(void)137e0c259feSLin Jinhan static inline bool is_check_hash_valid(void)
138e0c259feSLin Jinhan {
139e0c259feSLin Jinhan /* crypto < v4 need to check hash valid */
140e0c259feSLin Jinhan return CRYPTO_MAJOR_VER(g_crypto_version) < CRYPTO_MAJOR_VER_4;
141e0c259feSLin Jinhan }
142e0c259feSLin Jinhan
is_check_tag_valid(void)143e0c259feSLin Jinhan static inline bool is_check_tag_valid(void)
144e0c259feSLin Jinhan {
145e0c259feSLin Jinhan /* crypto < v4 need to check hash valid */
146e0c259feSLin Jinhan return CRYPTO_MAJOR_VER(g_crypto_version) < CRYPTO_MAJOR_VER_4;
147e0c259feSLin Jinhan }
148b353a43cSLin Jinhan
word2byte_be(u32 word,u8 * ch)14949a2135eSLin Jinhan static inline void word2byte_be(u32 word, u8 *ch)
150b353a43cSLin Jinhan {
151b353a43cSLin Jinhan ch[0] = (word >> 24) & 0xff;
152b353a43cSLin Jinhan ch[1] = (word >> 16) & 0xff;
153b353a43cSLin Jinhan ch[2] = (word >> 8) & 0xff;
154b353a43cSLin Jinhan ch[3] = (word >> 0) & 0xff;
155b353a43cSLin Jinhan }
156b353a43cSLin Jinhan
byte2word_be(const u8 * ch)15749a2135eSLin Jinhan static inline u32 byte2word_be(const u8 *ch)
15849a2135eSLin Jinhan {
15949a2135eSLin Jinhan return (*ch << 24) + (*(ch + 1) << 16) + (*(ch + 2) << 8) + *(ch + 3);
16049a2135eSLin Jinhan }
16149a2135eSLin Jinhan
clear_regs(u32 base,u32 words)16249a2135eSLin Jinhan static inline void clear_regs(u32 base, u32 words)
163b353a43cSLin Jinhan {
164b353a43cSLin Jinhan int i;
165b353a43cSLin Jinhan
166b353a43cSLin Jinhan /*clear out register*/
16749a2135eSLin Jinhan for (i = 0; i < words; i++)
16849a2135eSLin Jinhan crypto_write(0, base + 4 * i);
16949a2135eSLin Jinhan }
17049a2135eSLin Jinhan
clear_key_regs(void)17149a2135eSLin Jinhan static inline void clear_key_regs(void)
17249a2135eSLin Jinhan {
17349a2135eSLin Jinhan clear_regs(CRYPTO_CH0_KEY_0, CRYPTO_KEY_CHANNEL_NUM * 4);
17449a2135eSLin Jinhan }
17549a2135eSLin Jinhan
read_regs(u32 base,u8 * data,u32 data_len)176c3ce9937SLin Jinhan static inline void read_regs(u32 base, u8 *data, u32 data_len)
177c3ce9937SLin Jinhan {
178c3ce9937SLin Jinhan u8 tmp_buf[4];
179c3ce9937SLin Jinhan u32 i;
180c3ce9937SLin Jinhan
181c3ce9937SLin Jinhan for (i = 0; i < data_len / 4; i++)
182c3ce9937SLin Jinhan word2byte_be(crypto_read(base + i * 4),
183c3ce9937SLin Jinhan data + i * 4);
184c3ce9937SLin Jinhan
185c3ce9937SLin Jinhan if (data_len % 4) {
186c3ce9937SLin Jinhan word2byte_be(crypto_read(base + i * 4), tmp_buf);
187c3ce9937SLin Jinhan memcpy(data + i * 4, tmp_buf, data_len % 4);
188c3ce9937SLin Jinhan }
189c3ce9937SLin Jinhan }
190c3ce9937SLin Jinhan
write_regs(u32 base,const u8 * data,u32 data_len)19149a2135eSLin Jinhan static inline void write_regs(u32 base, const u8 *data, u32 data_len)
19249a2135eSLin Jinhan {
19349a2135eSLin Jinhan u8 tmp_buf[4];
19449a2135eSLin Jinhan u32 i;
19549a2135eSLin Jinhan
19649a2135eSLin Jinhan for (i = 0; i < data_len / 4; i++, base += 4)
19749a2135eSLin Jinhan crypto_write(byte2word_be(data + i * 4), base);
19849a2135eSLin Jinhan
19949a2135eSLin Jinhan if (data_len % 4) {
20049a2135eSLin Jinhan memset(tmp_buf, 0x00, sizeof(tmp_buf));
20149a2135eSLin Jinhan memcpy((u8 *)tmp_buf, data + i * 4, data_len % 4);
20249a2135eSLin Jinhan crypto_write(byte2word_be(tmp_buf), base);
20349a2135eSLin Jinhan }
20449a2135eSLin Jinhan }
20549a2135eSLin Jinhan
write_key_reg(u32 chn,const u8 * key,u32 key_len)20649a2135eSLin Jinhan static inline void write_key_reg(u32 chn, const u8 *key, u32 key_len)
20749a2135eSLin Jinhan {
20849a2135eSLin Jinhan write_regs(CRYPTO_CH0_KEY_0 + chn * 0x10, key, key_len);
20949a2135eSLin Jinhan }
21049a2135eSLin Jinhan
set_iv_reg(u32 chn,const u8 * iv,u32 iv_len)21149a2135eSLin Jinhan static inline void set_iv_reg(u32 chn, const u8 *iv, u32 iv_len)
21249a2135eSLin Jinhan {
21349a2135eSLin Jinhan u32 base_iv;
21449a2135eSLin Jinhan
21549a2135eSLin Jinhan base_iv = CRYPTO_CH0_IV_0 + chn * 0x10;
21649a2135eSLin Jinhan
21749a2135eSLin Jinhan /* clear iv */
21849a2135eSLin Jinhan clear_regs(base_iv, 4);
21949a2135eSLin Jinhan
22049a2135eSLin Jinhan if (!iv || iv_len == 0)
22149a2135eSLin Jinhan return;
22249a2135eSLin Jinhan
22349a2135eSLin Jinhan write_regs(base_iv, iv, iv_len);
22449a2135eSLin Jinhan
22549a2135eSLin Jinhan crypto_write(iv_len, CRYPTO_CH0_IV_LEN_0 + 4 * chn);
226b353a43cSLin Jinhan }
227b353a43cSLin Jinhan
get_iv_reg(u32 chn,u8 * iv,u32 iv_len)228c3ce9937SLin Jinhan static inline void get_iv_reg(u32 chn, u8 *iv, u32 iv_len)
229c3ce9937SLin Jinhan {
230c3ce9937SLin Jinhan u32 base_iv;
231c3ce9937SLin Jinhan
232c3ce9937SLin Jinhan base_iv = CRYPTO_CH0_IV_0 + chn * 0x10;
233c3ce9937SLin Jinhan
234c3ce9937SLin Jinhan read_regs(base_iv, iv, iv_len);
235c3ce9937SLin Jinhan }
236c3ce9937SLin Jinhan
get_tag_from_reg(u32 chn,u8 * tag,u32 tag_len)237d9332f1cSLin Jinhan static inline void get_tag_from_reg(u32 chn, u8 *tag, u32 tag_len)
238d9332f1cSLin Jinhan {
239d9332f1cSLin Jinhan u32 i;
240d9332f1cSLin Jinhan u32 chn_base = CRYPTO_CH0_TAG_0 + 0x10 * chn;
241d9332f1cSLin Jinhan
242d9332f1cSLin Jinhan for (i = 0; i < tag_len / 4; i++, chn_base += 4)
243d9332f1cSLin Jinhan word2byte_be(crypto_read(chn_base), tag + 4 * i);
244d9332f1cSLin Jinhan }
245d9332f1cSLin Jinhan
rk_crypto_do_enable_clk(struct udevice * dev,int enable)246dd7763a8SFinley Xiao static int rk_crypto_do_enable_clk(struct udevice *dev, int enable)
247dd7763a8SFinley Xiao {
248dd7763a8SFinley Xiao struct rockchip_crypto_priv *priv = dev_get_priv(dev);
249dd7763a8SFinley Xiao struct clk clk;
250dd7763a8SFinley Xiao int i, ret;
251dd7763a8SFinley Xiao
252dd7763a8SFinley Xiao for (i = 0; i < priv->nclocks; i++) {
253dd7763a8SFinley Xiao ret = clk_get_by_index(dev, i, &clk);
254dd7763a8SFinley Xiao if (ret < 0) {
255dd7763a8SFinley Xiao printf("Failed to get clk index %d, ret=%d\n", i, ret);
256dd7763a8SFinley Xiao return ret;
257dd7763a8SFinley Xiao }
258dd7763a8SFinley Xiao
259dd7763a8SFinley Xiao if (enable)
260dd7763a8SFinley Xiao ret = clk_enable(&clk);
261dd7763a8SFinley Xiao else
262dd7763a8SFinley Xiao ret = clk_disable(&clk);
263dd7763a8SFinley Xiao if (ret < 0 && ret != -ENOSYS) {
264*f84a40b4SLin Jinhan debug("Failed to enable(%d) clk(%ld): ret=%d\n",
265dd7763a8SFinley Xiao enable, clk.id, ret);
266dd7763a8SFinley Xiao return ret;
267dd7763a8SFinley Xiao }
268dd7763a8SFinley Xiao }
269dd7763a8SFinley Xiao
270dd7763a8SFinley Xiao return 0;
271dd7763a8SFinley Xiao }
272dd7763a8SFinley Xiao
rk_crypto_enable_clk(struct udevice * dev)273dd7763a8SFinley Xiao static int rk_crypto_enable_clk(struct udevice *dev)
274dd7763a8SFinley Xiao {
27536e17db4Stroy.lin struct rockchip_crypto_priv *priv = dev_get_priv(dev);
27636e17db4Stroy.lin
27736e17db4Stroy.lin crypto_base = priv->reg;
27836e17db4Stroy.lin
279dd7763a8SFinley Xiao return rk_crypto_do_enable_clk(dev, 1);
280dd7763a8SFinley Xiao }
281dd7763a8SFinley Xiao
rk_crypto_disable_clk(struct udevice * dev)282dd7763a8SFinley Xiao static int rk_crypto_disable_clk(struct udevice *dev)
283dd7763a8SFinley Xiao {
28436e17db4Stroy.lin crypto_base = 0;
28536e17db4Stroy.lin
286dd7763a8SFinley Xiao return rk_crypto_do_enable_clk(dev, 0);
287dd7763a8SFinley Xiao }
288dd7763a8SFinley Xiao
crypto_v3_dynamic_cap(void)28958432b6fSLin Jinhan static u32 crypto_v3_dynamic_cap(void)
29058432b6fSLin Jinhan {
29158432b6fSLin Jinhan u32 capability = 0;
29258432b6fSLin Jinhan u32 ver_reg, i;
29358432b6fSLin Jinhan struct cap_map {
29458432b6fSLin Jinhan u32 ver_offset;
29558432b6fSLin Jinhan u32 mask;
29658432b6fSLin Jinhan u32 cap_bit;
29758432b6fSLin Jinhan };
29858432b6fSLin Jinhan const struct cap_map cap_tbl[] = {
29958432b6fSLin Jinhan {CRYPTO_HASH_VERSION, CRYPTO_HASH_MD5_FLAG, CRYPTO_MD5},
30058432b6fSLin Jinhan {CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA1_FLAG, CRYPTO_SHA1},
30158432b6fSLin Jinhan {CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA256_FLAG, CRYPTO_SHA256},
30258432b6fSLin Jinhan {CRYPTO_HASH_VERSION, CRYPTO_HASH_SHA512_FLAG, CRYPTO_SHA512},
30358432b6fSLin Jinhan {CRYPTO_HASH_VERSION, CRYPTO_HASH_SM3_FLAG, CRYPTO_SM3},
30458432b6fSLin Jinhan
30558432b6fSLin Jinhan {CRYPTO_HMAC_VERSION, CRYPTO_HMAC_MD5_FLAG, CRYPTO_HMAC_MD5},
30658432b6fSLin Jinhan {CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA1_FLAG, CRYPTO_HMAC_SHA1},
30758432b6fSLin Jinhan {CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA256_FLAG, CRYPTO_HMAC_SHA256},
30858432b6fSLin Jinhan {CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SHA512_FLAG, CRYPTO_HMAC_SHA512},
30958432b6fSLin Jinhan {CRYPTO_HMAC_VERSION, CRYPTO_HMAC_SM3_FLAG, CRYPTO_HMAC_SM3},
31058432b6fSLin Jinhan
31158432b6fSLin Jinhan {CRYPTO_AES_VERSION, CRYPTO_AES256_FLAG, CRYPTO_AES},
31258432b6fSLin Jinhan {CRYPTO_DES_VERSION, CRYPTO_TDES_FLAG, CRYPTO_DES},
31358432b6fSLin Jinhan {CRYPTO_SM4_VERSION, CRYPTO_ECB_FLAG, CRYPTO_SM4},
31458432b6fSLin Jinhan };
31558432b6fSLin Jinhan
31658432b6fSLin Jinhan /* rsa */
31758432b6fSLin Jinhan capability = CRYPTO_RSA512 |
31858432b6fSLin Jinhan CRYPTO_RSA1024 |
31958432b6fSLin Jinhan CRYPTO_RSA2048 |
32058432b6fSLin Jinhan CRYPTO_RSA3072 |
32158432b6fSLin Jinhan CRYPTO_RSA4096;
32258432b6fSLin Jinhan
32302b4cf42SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
32402b4cf42SLin Jinhan capability |= (CRYPTO_SM2 |
32502b4cf42SLin Jinhan CRYPTO_ECC_192R1 |
32602b4cf42SLin Jinhan CRYPTO_ECC_224R1 |
32702b4cf42SLin Jinhan CRYPTO_ECC_256R1);
32802b4cf42SLin Jinhan #endif
32902b4cf42SLin Jinhan
33058432b6fSLin Jinhan for (i = 0; i < ARRAY_SIZE(cap_tbl); i++) {
33158432b6fSLin Jinhan ver_reg = crypto_read(cap_tbl[i].ver_offset);
33258432b6fSLin Jinhan
33358432b6fSLin Jinhan if ((ver_reg & cap_tbl[i].mask) == cap_tbl[i].mask)
33458432b6fSLin Jinhan capability |= cap_tbl[i].cap_bit;
33558432b6fSLin Jinhan }
33658432b6fSLin Jinhan
33758432b6fSLin Jinhan return capability;
33858432b6fSLin Jinhan }
33958432b6fSLin Jinhan
hw_crypto_reset(void)340b353a43cSLin Jinhan static int hw_crypto_reset(void)
341b353a43cSLin Jinhan {
34249a2135eSLin Jinhan u32 val = 0, mask = 0;
343b353a43cSLin Jinhan int ret;
344b353a43cSLin Jinhan
34549a2135eSLin Jinhan val = CRYPTO_SW_PKA_RESET | CRYPTO_SW_CC_RESET;
34649a2135eSLin Jinhan mask = val << CRYPTO_WRITE_MASK_SHIFT;
347b353a43cSLin Jinhan
348b353a43cSLin Jinhan /* reset pka and crypto modules*/
34949a2135eSLin Jinhan crypto_write(val | mask, CRYPTO_RST_CTL);
350b353a43cSLin Jinhan
351b353a43cSLin Jinhan /* wait reset compelete */
35249a2135eSLin Jinhan ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL), RK_CRYPTO_TIMEOUT);
35349a2135eSLin Jinhan
354e0c259feSLin Jinhan g_crypto_version = crypto_read(CRYPTO_CRYPTO_VERSION_NEW);
355e0c259feSLin Jinhan
356b353a43cSLin Jinhan return ret;
357b353a43cSLin Jinhan }
358b353a43cSLin Jinhan
hw_hash_clean_ctx(struct rk_hash_ctx * ctx)359b353a43cSLin Jinhan static void hw_hash_clean_ctx(struct rk_hash_ctx *ctx)
360b353a43cSLin Jinhan {
361b353a43cSLin Jinhan /* clear hash status */
362b353a43cSLin Jinhan crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
363b353a43cSLin Jinhan
3641606a214SLin Jinhan assert(ctx);
3651606a214SLin Jinhan assert(ctx->magic == RK_HASH_CTX_MAGIC);
3661606a214SLin Jinhan
367c48f1acfSLin Jinhan crypto_hash_cache_free(ctx->hash_cache);
3681606a214SLin Jinhan
3691606a214SLin Jinhan memset(ctx, 0x00, sizeof(*ctx));
370b353a43cSLin Jinhan }
371b353a43cSLin Jinhan
rk_hash_init(void * hw_ctx,u32 algo)372c48f1acfSLin Jinhan static int rk_hash_init(void *hw_ctx, u32 algo)
373b353a43cSLin Jinhan {
374b353a43cSLin Jinhan struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)hw_ctx;
375b353a43cSLin Jinhan u32 reg_ctrl = 0;
376b353a43cSLin Jinhan int ret;
377b353a43cSLin Jinhan
378b353a43cSLin Jinhan if (!tmp_ctx)
379b353a43cSLin Jinhan return -EINVAL;
380b353a43cSLin Jinhan
3811606a214SLin Jinhan reg_ctrl = CRYPTO_SW_CC_RESET;
3821606a214SLin Jinhan crypto_write(reg_ctrl | (reg_ctrl << CRYPTO_WRITE_MASK_SHIFT),
3831606a214SLin Jinhan CRYPTO_RST_CTL);
3841606a214SLin Jinhan
3851606a214SLin Jinhan /* wait reset compelete */
38649a2135eSLin Jinhan ret = RK_POLL_TIMEOUT(crypto_read(CRYPTO_RST_CTL),
38749a2135eSLin Jinhan RK_CRYPTO_TIMEOUT);
3881606a214SLin Jinhan
3891606a214SLin Jinhan reg_ctrl = 0;
390b353a43cSLin Jinhan tmp_ctx->algo = algo;
391b353a43cSLin Jinhan switch (algo) {
392b353a43cSLin Jinhan case CRYPTO_MD5:
39349a2135eSLin Jinhan case CRYPTO_HMAC_MD5:
394b353a43cSLin Jinhan reg_ctrl |= CRYPTO_MODE_MD5;
395b353a43cSLin Jinhan tmp_ctx->digest_size = 16;
396b353a43cSLin Jinhan break;
397b353a43cSLin Jinhan case CRYPTO_SHA1:
39849a2135eSLin Jinhan case CRYPTO_HMAC_SHA1:
399b353a43cSLin Jinhan reg_ctrl |= CRYPTO_MODE_SHA1;
400b353a43cSLin Jinhan tmp_ctx->digest_size = 20;
401b353a43cSLin Jinhan break;
402b353a43cSLin Jinhan case CRYPTO_SHA256:
40349a2135eSLin Jinhan case CRYPTO_HMAC_SHA256:
404b353a43cSLin Jinhan reg_ctrl |= CRYPTO_MODE_SHA256;
405b353a43cSLin Jinhan tmp_ctx->digest_size = 32;
406b353a43cSLin Jinhan break;
407e7846385SLin Jinhan case CRYPTO_SHA512:
40849a2135eSLin Jinhan case CRYPTO_HMAC_SHA512:
409e7846385SLin Jinhan reg_ctrl |= CRYPTO_MODE_SHA512;
410e7846385SLin Jinhan tmp_ctx->digest_size = 64;
411e7846385SLin Jinhan break;
41249a2135eSLin Jinhan case CRYPTO_SM3:
41349a2135eSLin Jinhan case CRYPTO_HMAC_SM3:
41449a2135eSLin Jinhan reg_ctrl |= CRYPTO_MODE_SM3;
41549a2135eSLin Jinhan tmp_ctx->digest_size = 32;
41649a2135eSLin Jinhan break;
417b353a43cSLin Jinhan default:
418b353a43cSLin Jinhan ret = -EINVAL;
419b353a43cSLin Jinhan goto exit;
420b353a43cSLin Jinhan }
421b353a43cSLin Jinhan
422b353a43cSLin Jinhan /* enable hardware padding */
423b353a43cSLin Jinhan reg_ctrl |= CRYPTO_HW_PAD_ENABLE;
424b353a43cSLin Jinhan crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
425b353a43cSLin Jinhan
426b353a43cSLin Jinhan /* FIFO input and output data byte swap */
427b353a43cSLin Jinhan /* such as B0, B1, B2, B3 -> B3, B2, B1, B0 */
428b353a43cSLin Jinhan reg_ctrl = CRYPTO_DOUT_BYTESWAP | CRYPTO_DOIN_BYTESWAP;
429b353a43cSLin Jinhan crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_FIFO_CTL);
430b353a43cSLin Jinhan
4311606a214SLin Jinhan /* enable src_item_done interrupt */
432fe0c4b19SLin Jinhan crypto_write(0, CRYPTO_DMA_INT_EN);
433b353a43cSLin Jinhan
434b353a43cSLin Jinhan tmp_ctx->magic = RK_HASH_CTX_MAGIC;
435b353a43cSLin Jinhan
436b353a43cSLin Jinhan return 0;
437b353a43cSLin Jinhan exit:
438b353a43cSLin Jinhan /* clear hash setting if init failed */
439b353a43cSLin Jinhan crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
440b353a43cSLin Jinhan
441b353a43cSLin Jinhan return ret;
442b353a43cSLin Jinhan }
443b353a43cSLin Jinhan
rk_hash_direct_calc(void * hw_data,const u8 * data,u32 data_len,u8 * started_flag,u8 is_last)444c48f1acfSLin Jinhan static int rk_hash_direct_calc(void *hw_data, const u8 *data,
4451606a214SLin Jinhan u32 data_len, u8 *started_flag, u8 is_last)
446b353a43cSLin Jinhan {
447c48f1acfSLin Jinhan struct rockchip_crypto_priv *priv = hw_data;
448c48f1acfSLin Jinhan struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
449c48f1acfSLin Jinhan struct crypto_lli_desc *lli = &hash_ctx->data_lli;
450b353a43cSLin Jinhan int ret = -EINVAL;
45100fa57d8SLin Jinhan u32 tmp = 0, mask = 0;
452b353a43cSLin Jinhan
45349a2135eSLin Jinhan assert(IS_ALIGNED((ulong)data, DATA_ADDR_ALIGN_SIZE));
45449a2135eSLin Jinhan assert(is_last || IS_ALIGNED(data_len, DATA_LEN_ALIGN_SIZE));
455b353a43cSLin Jinhan
4561606a214SLin Jinhan debug("%s: data = %p, len = %u, s = %x, l = %x\n",
4571606a214SLin Jinhan __func__, data, data_len, *started_flag, is_last);
458b353a43cSLin Jinhan
4591606a214SLin Jinhan memset(lli, 0x00, sizeof(*lli));
4601606a214SLin Jinhan lli->src_addr = (u32)virt_to_phys(data);
4611606a214SLin Jinhan lli->src_len = data_len;
4621606a214SLin Jinhan lli->dma_ctrl = LLI_DMA_CTRL_SRC_DONE;
463b353a43cSLin Jinhan
4641606a214SLin Jinhan if (is_last) {
4651606a214SLin Jinhan lli->user_define |= LLI_USER_STRING_LAST;
4661606a214SLin Jinhan lli->dma_ctrl |= LLI_DMA_CTRL_LAST;
467b353a43cSLin Jinhan } else {
4681606a214SLin Jinhan lli->next_addr = (u32)virt_to_phys(lli);
4691606a214SLin Jinhan lli->dma_ctrl |= LLI_DMA_CTRL_PAUSE;
4701606a214SLin Jinhan }
4711606a214SLin Jinhan
4721606a214SLin Jinhan if (!(*started_flag)) {
4731606a214SLin Jinhan lli->user_define |=
474ce7f4cd6SLin Jinhan (LLI_USER_STRING_START | LLI_USER_CIPHER_START);
4751606a214SLin Jinhan crypto_write((u32)virt_to_phys(lli), CRYPTO_DMA_LLI_ADDR);
4761606a214SLin Jinhan crypto_write((CRYPTO_HASH_ENABLE << CRYPTO_WRITE_MASK_SHIFT) |
4771606a214SLin Jinhan CRYPTO_HASH_ENABLE, CRYPTO_HASH_CTL);
4781606a214SLin Jinhan tmp = CRYPTO_DMA_START;
4791606a214SLin Jinhan *started_flag = 1;
4801606a214SLin Jinhan } else {
481b353a43cSLin Jinhan tmp = CRYPTO_DMA_RESTART;
482b353a43cSLin Jinhan }
483b353a43cSLin Jinhan
484b353a43cSLin Jinhan /* flush cache */
485c48f1acfSLin Jinhan crypto_flush_cacheline((ulong)lli, sizeof(*lli));
486c48f1acfSLin Jinhan crypto_flush_cacheline((ulong)data, data_len);
487b353a43cSLin Jinhan
488b353a43cSLin Jinhan /* start calculate */
489b353a43cSLin Jinhan crypto_write(tmp << CRYPTO_WRITE_MASK_SHIFT | tmp,
490b353a43cSLin Jinhan CRYPTO_DMA_CTL);
491b353a43cSLin Jinhan
49200fa57d8SLin Jinhan /* mask CRYPTO_SYNC_LOCKSTEP_INT_ST flag */
49300fa57d8SLin Jinhan mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
49400fa57d8SLin Jinhan
495b353a43cSLin Jinhan /* wait calc ok */
49649a2135eSLin Jinhan ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
49749a2135eSLin Jinhan RK_CRYPTO_TIMEOUT);
498b353a43cSLin Jinhan
499b353a43cSLin Jinhan /* clear interrupt status */
500b353a43cSLin Jinhan tmp = crypto_read(CRYPTO_DMA_INT_ST);
501b353a43cSLin Jinhan crypto_write(tmp, CRYPTO_DMA_INT_ST);
502b353a43cSLin Jinhan
50349cbb0faSLin Jinhan if ((tmp & mask) != CRYPTO_SRC_ITEM_DONE_INT_ST &&
50449cbb0faSLin Jinhan (tmp & mask) != CRYPTO_ZERO_LEN_INT_ST) {
50546aac970SLin Jinhan ret = -EFAULT;
5061606a214SLin Jinhan debug("[%s] %d: CRYPTO_DMA_INT_ST = 0x%x\n",
507b353a43cSLin Jinhan __func__, __LINE__, tmp);
5081606a214SLin Jinhan goto exit;
509b353a43cSLin Jinhan }
510b353a43cSLin Jinhan
511c48f1acfSLin Jinhan priv->length += data_len;
5121606a214SLin Jinhan exit:
5131606a214SLin Jinhan return ret;
514b353a43cSLin Jinhan }
5151606a214SLin Jinhan
rk_hash_update(void * ctx,const u8 * data,u32 data_len)5161606a214SLin Jinhan int rk_hash_update(void *ctx, const u8 *data, u32 data_len)
5171606a214SLin Jinhan {
5181606a214SLin Jinhan struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
519c48f1acfSLin Jinhan int ret = -EINVAL;
5201606a214SLin Jinhan
5211606a214SLin Jinhan debug("\n");
5221606a214SLin Jinhan if (!tmp_ctx || !data)
523c48f1acfSLin Jinhan goto exit;
5241606a214SLin Jinhan
5251606a214SLin Jinhan if (tmp_ctx->digest_size == 0 || tmp_ctx->magic != RK_HASH_CTX_MAGIC)
526c48f1acfSLin Jinhan goto exit;
5271606a214SLin Jinhan
528c48f1acfSLin Jinhan ret = crypto_hash_update_with_cache(tmp_ctx->hash_cache,
529c48f1acfSLin Jinhan data, data_len);
5301606a214SLin Jinhan
531c48f1acfSLin Jinhan exit:
532b353a43cSLin Jinhan /* free lli list */
533c48f1acfSLin Jinhan if (ret)
534b353a43cSLin Jinhan hw_hash_clean_ctx(tmp_ctx);
535b353a43cSLin Jinhan
536c48f1acfSLin Jinhan return ret;
537b353a43cSLin Jinhan }
538b353a43cSLin Jinhan
rk_hash_final(void * ctx,u8 * digest,size_t len)539b353a43cSLin Jinhan int rk_hash_final(void *ctx, u8 *digest, size_t len)
540b353a43cSLin Jinhan {
541b353a43cSLin Jinhan struct rk_hash_ctx *tmp_ctx = (struct rk_hash_ctx *)ctx;
542e0c259feSLin Jinhan int ret = 0;
543b353a43cSLin Jinhan
544b353a43cSLin Jinhan if (!digest)
545b353a43cSLin Jinhan goto exit;
546b353a43cSLin Jinhan
547b353a43cSLin Jinhan if (!tmp_ctx ||
548b353a43cSLin Jinhan tmp_ctx->digest_size == 0 ||
549b353a43cSLin Jinhan len > tmp_ctx->digest_size ||
550b353a43cSLin Jinhan tmp_ctx->magic != RK_HASH_CTX_MAGIC) {
551b353a43cSLin Jinhan goto exit;
552b353a43cSLin Jinhan }
553b353a43cSLin Jinhan
554e0c259feSLin Jinhan if(is_check_hash_valid()) {
555b353a43cSLin Jinhan /* wait hash value ok */
55649a2135eSLin Jinhan ret = RK_POLL_TIMEOUT(!crypto_read(CRYPTO_HASH_VALID),
55749a2135eSLin Jinhan RK_CRYPTO_TIMEOUT);
558e0c259feSLin Jinhan }
559b353a43cSLin Jinhan
560c3ce9937SLin Jinhan read_regs(CRYPTO_HASH_DOUT_0, digest, len);
561b353a43cSLin Jinhan
562b353a43cSLin Jinhan /* clear hash status */
563b353a43cSLin Jinhan crypto_write(CRYPTO_HASH_IS_VALID, CRYPTO_HASH_VALID);
564b353a43cSLin Jinhan crypto_write(CRYPTO_WRITE_MASK_ALL | 0, CRYPTO_HASH_CTL);
565b353a43cSLin Jinhan
566b353a43cSLin Jinhan exit:
567b353a43cSLin Jinhan
568b353a43cSLin Jinhan return ret;
569b353a43cSLin Jinhan }
570b353a43cSLin Jinhan
rockchip_crypto_capability(struct udevice * dev)571b353a43cSLin Jinhan static u32 rockchip_crypto_capability(struct udevice *dev)
572b353a43cSLin Jinhan {
57349a2135eSLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
57449a2135eSLin Jinhan u32 capability, mask = 0;
5757eea1823SLin Jinhan
57636e17db4Stroy.lin if (!priv->enabled)
57736e17db4Stroy.lin return 0;
57836e17db4Stroy.lin
57949a2135eSLin Jinhan capability = priv->soc_data->capability;
58049a2135eSLin Jinhan
58149a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_CIPHER))
58249a2135eSLin Jinhan mask |= (CRYPTO_DES | CRYPTO_AES | CRYPTO_SM4);
583c0e47d03SLin Jinhan #endif
5847eea1823SLin Jinhan
58549a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_HMAC))
58649a2135eSLin Jinhan mask |= (CRYPTO_HMAC_MD5 | CRYPTO_HMAC_SHA1 | CRYPTO_HMAC_SHA256 |
58749a2135eSLin Jinhan CRYPTO_HMAC_SHA512 | CRYPTO_HMAC_SM3);
58849a2135eSLin Jinhan #endif
58949a2135eSLin Jinhan
59049a2135eSLin Jinhan #if !(CONFIG_IS_ENABLED(ROCKCHIP_RSA))
59149a2135eSLin Jinhan mask |= (CRYPTO_RSA512 | CRYPTO_RSA1024 | CRYPTO_RSA2048 |
59249a2135eSLin Jinhan CRYPTO_RSA3072 | CRYPTO_RSA4096);
59349a2135eSLin Jinhan #endif
59449a2135eSLin Jinhan
59549a2135eSLin Jinhan return capability & (~mask);
596b353a43cSLin Jinhan }
597b353a43cSLin Jinhan
rockchip_crypto_sha_init(struct udevice * dev,sha_context * ctx)598b353a43cSLin Jinhan static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx)
599b353a43cSLin Jinhan {
600b353a43cSLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
601c48f1acfSLin Jinhan struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
602dd7763a8SFinley Xiao int ret = 0;
603b353a43cSLin Jinhan
604b353a43cSLin Jinhan if (!ctx)
605b353a43cSLin Jinhan return -EINVAL;
606b353a43cSLin Jinhan
607c48f1acfSLin Jinhan memset(hash_ctx, 0x00, sizeof(*hash_ctx));
608b353a43cSLin Jinhan
609c48f1acfSLin Jinhan priv->length = 0;
610c48f1acfSLin Jinhan
611c48f1acfSLin Jinhan hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
612c48f1acfSLin Jinhan priv, ctx->length,
61349a2135eSLin Jinhan DATA_ADDR_ALIGN_SIZE,
61449a2135eSLin Jinhan DATA_LEN_ALIGN_SIZE);
615c48f1acfSLin Jinhan if (!hash_ctx->hash_cache)
616c48f1acfSLin Jinhan return -EFAULT;
617c48f1acfSLin Jinhan
618dd7763a8SFinley Xiao rk_crypto_enable_clk(dev);
619dd7763a8SFinley Xiao ret = rk_hash_init(hash_ctx, ctx->algo);
620dd7763a8SFinley Xiao if (ret)
621dd7763a8SFinley Xiao rk_crypto_disable_clk(dev);
622dd7763a8SFinley Xiao
623dd7763a8SFinley Xiao return ret;
624b353a43cSLin Jinhan }
625b353a43cSLin Jinhan
rockchip_crypto_sha_update(struct udevice * dev,u32 * input,u32 len)626b353a43cSLin Jinhan static int rockchip_crypto_sha_update(struct udevice *dev,
627b353a43cSLin Jinhan u32 *input, u32 len)
628b353a43cSLin Jinhan {
629b353a43cSLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
630086e8fa8SLin Jinhan int ret, i;
631086e8fa8SLin Jinhan u8 *p;
632b353a43cSLin Jinhan
633dd7763a8SFinley Xiao if (!len) {
634dd7763a8SFinley Xiao ret = -EINVAL;
635dd7763a8SFinley Xiao goto exit;
636dd7763a8SFinley Xiao }
637b353a43cSLin Jinhan
638086e8fa8SLin Jinhan p = (u8 *)input;
639086e8fa8SLin Jinhan
640086e8fa8SLin Jinhan for (i = 0; i < len / HASH_UPDATE_LIMIT; i++, p += HASH_UPDATE_LIMIT) {
641086e8fa8SLin Jinhan ret = rk_hash_update(priv->hw_ctx, p, HASH_UPDATE_LIMIT);
642086e8fa8SLin Jinhan if (ret)
643086e8fa8SLin Jinhan goto exit;
644086e8fa8SLin Jinhan }
645086e8fa8SLin Jinhan
646086e8fa8SLin Jinhan if (len % HASH_UPDATE_LIMIT)
647086e8fa8SLin Jinhan ret = rk_hash_update(priv->hw_ctx, p, len % HASH_UPDATE_LIMIT);
648086e8fa8SLin Jinhan
649086e8fa8SLin Jinhan exit:
650dd7763a8SFinley Xiao if (ret)
651dd7763a8SFinley Xiao rk_crypto_disable_clk(dev);
652dd7763a8SFinley Xiao
653086e8fa8SLin Jinhan return ret;
654b353a43cSLin Jinhan }
655b353a43cSLin Jinhan
rockchip_crypto_sha_final(struct udevice * dev,sha_context * ctx,u8 * output)656b353a43cSLin Jinhan static int rockchip_crypto_sha_final(struct udevice *dev,
657b353a43cSLin Jinhan sha_context *ctx, u8 *output)
658b353a43cSLin Jinhan {
659b353a43cSLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
660b353a43cSLin Jinhan u32 nbits;
661c48f1acfSLin Jinhan int ret;
662b353a43cSLin Jinhan
663b353a43cSLin Jinhan nbits = crypto_algo_nbits(ctx->algo);
664b353a43cSLin Jinhan
665c48f1acfSLin Jinhan if (priv->length != ctx->length) {
666c48f1acfSLin Jinhan printf("total length(0x%08x) != init length(0x%08x)!\n",
667c48f1acfSLin Jinhan priv->length, ctx->length);
668c48f1acfSLin Jinhan ret = -EIO;
669c48f1acfSLin Jinhan goto exit;
670c48f1acfSLin Jinhan }
671c48f1acfSLin Jinhan
672c48f1acfSLin Jinhan ret = rk_hash_final(priv->hw_ctx, (u8 *)output, BITS2BYTE(nbits));
673c48f1acfSLin Jinhan
674c48f1acfSLin Jinhan exit:
675c48f1acfSLin Jinhan hw_hash_clean_ctx(priv->hw_ctx);
676dd7763a8SFinley Xiao rk_crypto_disable_clk(dev);
677dd7763a8SFinley Xiao
678c48f1acfSLin Jinhan return ret;
679b353a43cSLin Jinhan }
680b353a43cSLin Jinhan
68149a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
rk_hmac_init(void * hw_ctx,u32 algo,u8 * key,u32 key_len)68249a2135eSLin Jinhan int rk_hmac_init(void *hw_ctx, u32 algo, u8 *key, u32 key_len)
68349a2135eSLin Jinhan {
68449a2135eSLin Jinhan u32 reg_ctrl = 0;
68549a2135eSLin Jinhan int ret;
68649a2135eSLin Jinhan
68749a2135eSLin Jinhan if (!key || !key_len || key_len > 64)
68849a2135eSLin Jinhan return -EINVAL;
68949a2135eSLin Jinhan
69049a2135eSLin Jinhan clear_key_regs();
69149a2135eSLin Jinhan
69249a2135eSLin Jinhan write_key_reg(0, key, key_len);
69349a2135eSLin Jinhan
69449a2135eSLin Jinhan ret = rk_hash_init(hw_ctx, algo);
69549a2135eSLin Jinhan if (ret)
69649a2135eSLin Jinhan return ret;
69749a2135eSLin Jinhan
69849a2135eSLin Jinhan reg_ctrl = crypto_read(CRYPTO_HASH_CTL) | CRYPTO_HMAC_ENABLE;
69949a2135eSLin Jinhan crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_HASH_CTL);
70049a2135eSLin Jinhan
70149a2135eSLin Jinhan return ret;
70249a2135eSLin Jinhan }
70349a2135eSLin Jinhan
rockchip_crypto_hmac_init(struct udevice * dev,sha_context * ctx,u8 * key,u32 key_len)70449a2135eSLin Jinhan static int rockchip_crypto_hmac_init(struct udevice *dev,
70549a2135eSLin Jinhan sha_context *ctx, u8 *key, u32 key_len)
70649a2135eSLin Jinhan {
70749a2135eSLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
70849a2135eSLin Jinhan struct rk_hash_ctx *hash_ctx = priv->hw_ctx;
709dd7763a8SFinley Xiao int ret = 0;
71049a2135eSLin Jinhan
71149a2135eSLin Jinhan if (!ctx)
71249a2135eSLin Jinhan return -EINVAL;
71349a2135eSLin Jinhan
71449a2135eSLin Jinhan memset(hash_ctx, 0x00, sizeof(*hash_ctx));
71549a2135eSLin Jinhan
71649a2135eSLin Jinhan priv->length = 0;
71749a2135eSLin Jinhan
71849a2135eSLin Jinhan hash_ctx->hash_cache = crypto_hash_cache_alloc(rk_hash_direct_calc,
71949a2135eSLin Jinhan priv, ctx->length,
72049a2135eSLin Jinhan DATA_ADDR_ALIGN_SIZE,
72149a2135eSLin Jinhan DATA_LEN_ALIGN_SIZE);
72249a2135eSLin Jinhan if (!hash_ctx->hash_cache)
72349a2135eSLin Jinhan return -EFAULT;
72449a2135eSLin Jinhan
725dd7763a8SFinley Xiao rk_crypto_enable_clk(dev);
726dd7763a8SFinley Xiao ret = rk_hmac_init(priv->hw_ctx, ctx->algo, key, key_len);
727dd7763a8SFinley Xiao if (ret)
728dd7763a8SFinley Xiao rk_crypto_disable_clk(dev);
729dd7763a8SFinley Xiao
730dd7763a8SFinley Xiao return ret;
73149a2135eSLin Jinhan }
73249a2135eSLin Jinhan
rockchip_crypto_hmac_update(struct udevice * dev,u32 * input,u32 len)73349a2135eSLin Jinhan static int rockchip_crypto_hmac_update(struct udevice *dev,
73449a2135eSLin Jinhan u32 *input, u32 len)
73549a2135eSLin Jinhan {
73649a2135eSLin Jinhan return rockchip_crypto_sha_update(dev, input, len);
73749a2135eSLin Jinhan }
73849a2135eSLin Jinhan
rockchip_crypto_hmac_final(struct udevice * dev,sha_context * ctx,u8 * output)73949a2135eSLin Jinhan static int rockchip_crypto_hmac_final(struct udevice *dev,
74049a2135eSLin Jinhan sha_context *ctx, u8 *output)
74149a2135eSLin Jinhan {
74249a2135eSLin Jinhan return rockchip_crypto_sha_final(dev, ctx, output);
74349a2135eSLin Jinhan }
74449a2135eSLin Jinhan
74549a2135eSLin Jinhan #endif
74649a2135eSLin Jinhan
74749a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
74849a2135eSLin Jinhan static u8 g_key_chn;
74949a2135eSLin Jinhan
75049a2135eSLin Jinhan static const u32 rk_mode2bc_mode[RK_MODE_MAX] = {
75149a2135eSLin Jinhan [RK_MODE_ECB] = CRYPTO_BC_ECB,
75249a2135eSLin Jinhan [RK_MODE_CBC] = CRYPTO_BC_CBC,
75349a2135eSLin Jinhan [RK_MODE_CTS] = CRYPTO_BC_CTS,
75449a2135eSLin Jinhan [RK_MODE_CTR] = CRYPTO_BC_CTR,
75549a2135eSLin Jinhan [RK_MODE_CFB] = CRYPTO_BC_CFB,
75649a2135eSLin Jinhan [RK_MODE_OFB] = CRYPTO_BC_OFB,
75749a2135eSLin Jinhan [RK_MODE_XTS] = CRYPTO_BC_XTS,
758c3ce9937SLin Jinhan [RK_MODE_CCM] = CRYPTO_BC_CCM,
759c3ce9937SLin Jinhan [RK_MODE_GCM] = CRYPTO_BC_GCM,
760d9332f1cSLin Jinhan [RK_MODE_CMAC] = CRYPTO_BC_CMAC,
761d9332f1cSLin Jinhan [RK_MODE_CBC_MAC] = CRYPTO_BC_CBC_MAC,
76249a2135eSLin Jinhan };
76349a2135eSLin Jinhan
set_pc_len_reg(u32 chn,u64 pc_len)764c3ce9937SLin Jinhan static inline void set_pc_len_reg(u32 chn, u64 pc_len)
765c3ce9937SLin Jinhan {
766c3ce9937SLin Jinhan u32 chn_base = CRYPTO_CH0_PC_LEN_0 + chn * 0x08;
767c3ce9937SLin Jinhan
768c3ce9937SLin Jinhan crypto_write(pc_len & 0xffffffff, chn_base);
769c3ce9937SLin Jinhan crypto_write(pc_len >> 32, chn_base + 4);
770c3ce9937SLin Jinhan }
771c3ce9937SLin Jinhan
set_aad_len_reg(u32 chn,u64 pc_len)772c3ce9937SLin Jinhan static inline void set_aad_len_reg(u32 chn, u64 pc_len)
773c3ce9937SLin Jinhan {
774c3ce9937SLin Jinhan u32 chn_base = CRYPTO_CH0_AAD_LEN_0 + chn * 0x08;
775c3ce9937SLin Jinhan
776c3ce9937SLin Jinhan crypto_write(pc_len & 0xffffffff, chn_base);
777c3ce9937SLin Jinhan crypto_write(pc_len >> 32, chn_base + 4);
778c3ce9937SLin Jinhan }
779c3ce9937SLin Jinhan
is_des_mode(u32 rk_mode)78049a2135eSLin Jinhan static inline bool is_des_mode(u32 rk_mode)
78149a2135eSLin Jinhan {
78249a2135eSLin Jinhan return (rk_mode == RK_MODE_ECB ||
78349a2135eSLin Jinhan rk_mode == RK_MODE_CBC ||
78449a2135eSLin Jinhan rk_mode == RK_MODE_CFB ||
78549a2135eSLin Jinhan rk_mode == RK_MODE_OFB);
78649a2135eSLin Jinhan }
78749a2135eSLin Jinhan
dump_crypto_state(struct crypto_lli_desc * desc,u32 tmp,u32 expt_int,const u8 * in,const u8 * out,u32 len,int ret)7886b53126aSLin Jinhan static void dump_crypto_state(struct crypto_lli_desc *desc,
7896b53126aSLin Jinhan u32 tmp, u32 expt_int,
7906b53126aSLin Jinhan const u8 *in, const u8 *out,
7916b53126aSLin Jinhan u32 len, int ret)
79249a2135eSLin Jinhan {
79349a2135eSLin Jinhan IMSG("%s\n", ret == -ETIME ? "timeout" : "dismatch");
79449a2135eSLin Jinhan
79549a2135eSLin Jinhan IMSG("CRYPTO_DMA_INT_ST = %08x, expect_int = %08x\n",
79649a2135eSLin Jinhan tmp, expt_int);
79749a2135eSLin Jinhan IMSG("data desc = %p\n", desc);
79849a2135eSLin Jinhan IMSG("\taddr_in = [%08x <=> %08x]\n",
79949a2135eSLin Jinhan desc->src_addr, (u32)virt_to_phys(in));
80049a2135eSLin Jinhan IMSG("\taddr_out = [%08x <=> %08x]\n",
80149a2135eSLin Jinhan desc->dst_addr, (u32)virt_to_phys(out));
80249a2135eSLin Jinhan IMSG("\tsrc_len = [%08x <=> %08x]\n",
80349a2135eSLin Jinhan desc->src_len, (u32)len);
80449a2135eSLin Jinhan IMSG("\tdst_len = %08x\n", desc->dst_len);
80549a2135eSLin Jinhan IMSG("\tdma_ctl = %08x\n", desc->dma_ctrl);
80649a2135eSLin Jinhan IMSG("\tuser_define = %08x\n", desc->user_define);
80749a2135eSLin Jinhan
80849a2135eSLin Jinhan IMSG("\n\nDMA CRYPTO_DMA_LLI_ADDR status = %08x\n",
80949a2135eSLin Jinhan crypto_read(CRYPTO_DMA_LLI_ADDR));
81049a2135eSLin Jinhan IMSG("DMA CRYPTO_DMA_ST status = %08x\n",
81149a2135eSLin Jinhan crypto_read(CRYPTO_DMA_ST));
81249a2135eSLin Jinhan IMSG("DMA CRYPTO_DMA_STATE status = %08x\n",
81349a2135eSLin Jinhan crypto_read(CRYPTO_DMA_STATE));
81449a2135eSLin Jinhan IMSG("DMA CRYPTO_DMA_LLI_RADDR status = %08x\n",
81549a2135eSLin Jinhan crypto_read(CRYPTO_DMA_LLI_RADDR));
81649a2135eSLin Jinhan IMSG("DMA CRYPTO_DMA_SRC_RADDR status = %08x\n",
81749a2135eSLin Jinhan crypto_read(CRYPTO_DMA_SRC_RADDR));
81849a2135eSLin Jinhan IMSG("DMA CRYPTO_DMA_DST_RADDR status = %08x\n",
81949a2135eSLin Jinhan crypto_read(CRYPTO_DMA_DST_RADDR));
82049a2135eSLin Jinhan IMSG("DMA CRYPTO_CIPHER_ST status = %08x\n",
82149a2135eSLin Jinhan crypto_read(CRYPTO_CIPHER_ST));
82249a2135eSLin Jinhan IMSG("DMA CRYPTO_CIPHER_STATE status = %08x\n",
82349a2135eSLin Jinhan crypto_read(CRYPTO_CIPHER_STATE));
82449a2135eSLin Jinhan IMSG("DMA CRYPTO_TAG_VALID status = %08x\n",
82549a2135eSLin Jinhan crypto_read(CRYPTO_TAG_VALID));
82649a2135eSLin Jinhan IMSG("LOCKSTEP status = %08x\n\n",
82749a2135eSLin Jinhan crypto_read(0x618));
82849a2135eSLin Jinhan
82949a2135eSLin Jinhan IMSG("dst %dbyte not transferred\n",
83049a2135eSLin Jinhan desc->dst_addr + desc->dst_len -
83149a2135eSLin Jinhan crypto_read(CRYPTO_DMA_DST_RADDR));
83249a2135eSLin Jinhan }
83349a2135eSLin Jinhan
ccm128_set_iv_reg(u32 chn,const u8 * nonce,u32 nlen)834c3ce9937SLin Jinhan static int ccm128_set_iv_reg(u32 chn, const u8 *nonce, u32 nlen)
835c3ce9937SLin Jinhan {
836c3ce9937SLin Jinhan u8 iv_buf[AES_BLOCK_SIZE];
837c3ce9937SLin Jinhan u32 L;
838c3ce9937SLin Jinhan
839c3ce9937SLin Jinhan memset(iv_buf, 0x00, sizeof(iv_buf));
840c3ce9937SLin Jinhan
841c3ce9937SLin Jinhan L = 15 - nlen;
842c3ce9937SLin Jinhan iv_buf[0] = ((u8)(L - 1) & 7);
843c3ce9937SLin Jinhan
844c3ce9937SLin Jinhan /* the L parameter */
845c3ce9937SLin Jinhan L = iv_buf[0] & 7;
846c3ce9937SLin Jinhan
847c3ce9937SLin Jinhan /* nonce is too short */
848c3ce9937SLin Jinhan if (nlen < (14 - L))
849c3ce9937SLin Jinhan return -EINVAL;
850c3ce9937SLin Jinhan
851c3ce9937SLin Jinhan /* clear aad flag */
852c3ce9937SLin Jinhan iv_buf[0] &= ~0x40;
853c3ce9937SLin Jinhan memcpy(&iv_buf[1], nonce, 14 - L);
854c3ce9937SLin Jinhan
855c3ce9937SLin Jinhan set_iv_reg(chn, iv_buf, AES_BLOCK_SIZE);
856c3ce9937SLin Jinhan
857c3ce9937SLin Jinhan return 0;
858c3ce9937SLin Jinhan }
859c3ce9937SLin Jinhan
ccm_aad_padding(u32 aad_len,u8 * padding,u32 * padding_size)860c3ce9937SLin Jinhan static void ccm_aad_padding(u32 aad_len, u8 *padding, u32 *padding_size)
861c3ce9937SLin Jinhan {
862c3ce9937SLin Jinhan u32 i;
863c3ce9937SLin Jinhan
8642db770efSLin Jinhan if (aad_len == 0) {
8652db770efSLin Jinhan *padding_size = 0;
8662db770efSLin Jinhan return;
8672db770efSLin Jinhan }
8682db770efSLin Jinhan
869c3ce9937SLin Jinhan i = aad_len < (0x10000 - 0x100) ? 2 : 6;
870c3ce9937SLin Jinhan
871c3ce9937SLin Jinhan if (i == 2) {
872c3ce9937SLin Jinhan padding[0] = (u8)(aad_len >> 8);
873c3ce9937SLin Jinhan padding[1] = (u8)aad_len;
874c3ce9937SLin Jinhan } else {
875c3ce9937SLin Jinhan padding[0] = 0xFF;
876c3ce9937SLin Jinhan padding[1] = 0xFE;
877c3ce9937SLin Jinhan padding[2] = (u8)(aad_len >> 24);
878c3ce9937SLin Jinhan padding[3] = (u8)(aad_len >> 16);
879c3ce9937SLin Jinhan padding[4] = (u8)(aad_len >> 8);
880c3ce9937SLin Jinhan }
881c3ce9937SLin Jinhan
882c3ce9937SLin Jinhan *padding_size = i;
883c3ce9937SLin Jinhan }
884c3ce9937SLin Jinhan
ccm_compose_aad_iv(u8 * aad_iv,u32 data_len,u32 aad_len,u32 tag_size)8852db770efSLin Jinhan static int ccm_compose_aad_iv(u8 *aad_iv, u32 data_len, u32 aad_len, u32 tag_size)
886c3ce9937SLin Jinhan {
887c3ce9937SLin Jinhan aad_iv[0] |= ((u8)(((tag_size - 2) / 2) & 7) << 3);
888c3ce9937SLin Jinhan
889c3ce9937SLin Jinhan aad_iv[12] = (u8)(data_len >> 24);
890c3ce9937SLin Jinhan aad_iv[13] = (u8)(data_len >> 16);
891c3ce9937SLin Jinhan aad_iv[14] = (u8)(data_len >> 8);
892c3ce9937SLin Jinhan aad_iv[15] = (u8)data_len;
893c3ce9937SLin Jinhan
8942db770efSLin Jinhan if (aad_len)
895c3ce9937SLin Jinhan aad_iv[0] |= 0x40; //set aad flag
896c3ce9937SLin Jinhan
897c3ce9937SLin Jinhan return 0;
898c3ce9937SLin Jinhan }
899c3ce9937SLin Jinhan
hw_cipher_init(u32 chn,const u8 * key,const u8 * twk_key,u32 key_len,const u8 * iv,u32 iv_len,u32 algo,u32 mode,bool enc)90049a2135eSLin Jinhan static int hw_cipher_init(u32 chn, const u8 *key, const u8 *twk_key,
90149a2135eSLin Jinhan u32 key_len, const u8 *iv, u32 iv_len,
90249a2135eSLin Jinhan u32 algo, u32 mode, bool enc)
90349a2135eSLin Jinhan {
90449a2135eSLin Jinhan u32 rk_mode = RK_GET_RK_MODE(mode);
90549a2135eSLin Jinhan u32 key_chn_sel = chn;
90649a2135eSLin Jinhan u32 reg_ctrl = 0;
907eecb3765SLin Jinhan bool use_otpkey = false;
908eecb3765SLin Jinhan
909eecb3765SLin Jinhan if (!key && key_len)
910eecb3765SLin Jinhan use_otpkey = true;
91149a2135eSLin Jinhan
91249a2135eSLin Jinhan IMSG("%s: key addr is %p, key_len is %d, iv addr is %p",
91349a2135eSLin Jinhan __func__, key, key_len, iv);
91449a2135eSLin Jinhan if (rk_mode >= RK_MODE_MAX)
91549a2135eSLin Jinhan return -EINVAL;
91649a2135eSLin Jinhan
91749a2135eSLin Jinhan switch (algo) {
91849a2135eSLin Jinhan case CRYPTO_DES:
91949a2135eSLin Jinhan if (key_len > DES_BLOCK_SIZE)
92049a2135eSLin Jinhan reg_ctrl |= CRYPTO_BC_TDES;
92149a2135eSLin Jinhan else
92249a2135eSLin Jinhan reg_ctrl |= CRYPTO_BC_DES;
92349a2135eSLin Jinhan break;
92449a2135eSLin Jinhan case CRYPTO_AES:
92549a2135eSLin Jinhan reg_ctrl |= CRYPTO_BC_AES;
92649a2135eSLin Jinhan break;
92749a2135eSLin Jinhan case CRYPTO_SM4:
92849a2135eSLin Jinhan reg_ctrl |= CRYPTO_BC_SM4;
92949a2135eSLin Jinhan break;
93049a2135eSLin Jinhan default:
93149a2135eSLin Jinhan return -EINVAL;
93249a2135eSLin Jinhan }
93349a2135eSLin Jinhan
93449a2135eSLin Jinhan if (algo == CRYPTO_AES || algo == CRYPTO_SM4) {
93549a2135eSLin Jinhan switch (key_len) {
93649a2135eSLin Jinhan case AES_KEYSIZE_128:
93749a2135eSLin Jinhan reg_ctrl |= CRYPTO_BC_128_bit_key;
93849a2135eSLin Jinhan break;
93949a2135eSLin Jinhan case AES_KEYSIZE_192:
94049a2135eSLin Jinhan reg_ctrl |= CRYPTO_BC_192_bit_key;
94149a2135eSLin Jinhan break;
94249a2135eSLin Jinhan case AES_KEYSIZE_256:
94349a2135eSLin Jinhan reg_ctrl |= CRYPTO_BC_256_bit_key;
94449a2135eSLin Jinhan break;
94549a2135eSLin Jinhan default:
94649a2135eSLin Jinhan return -EINVAL;
94749a2135eSLin Jinhan }
94849a2135eSLin Jinhan }
94949a2135eSLin Jinhan
95049a2135eSLin Jinhan reg_ctrl |= rk_mode2bc_mode[rk_mode];
95149a2135eSLin Jinhan if (!enc)
95249a2135eSLin Jinhan reg_ctrl |= CRYPTO_BC_DECRYPT;
95349a2135eSLin Jinhan
95449a2135eSLin Jinhan /* write key data to reg */
955eecb3765SLin Jinhan if (!use_otpkey) {
95649a2135eSLin Jinhan write_key_reg(key_chn_sel, key, key_len);
957eecb3765SLin Jinhan crypto_write(CRYPTO_SEL_USER, CRYPTO_KEY_SEL);
958eecb3765SLin Jinhan } else {
959eecb3765SLin Jinhan crypto_write(CRYPTO_SEL_KEYTABLE, CRYPTO_KEY_SEL);
960eecb3765SLin Jinhan }
96149a2135eSLin Jinhan
96249a2135eSLin Jinhan /* write twk key for xts mode */
96349a2135eSLin Jinhan if (rk_mode == RK_MODE_XTS)
96449a2135eSLin Jinhan write_key_reg(key_chn_sel + 4, twk_key, key_len);
96549a2135eSLin Jinhan
96649a2135eSLin Jinhan /* set iv reg */
967c3ce9937SLin Jinhan if (rk_mode == RK_MODE_CCM)
968c3ce9937SLin Jinhan ccm128_set_iv_reg(chn, iv, iv_len);
969c3ce9937SLin Jinhan else
97049a2135eSLin Jinhan set_iv_reg(chn, iv, iv_len);
97149a2135eSLin Jinhan
97249a2135eSLin Jinhan /* din_swap set 1, dout_swap set 1, default 1. */
97349a2135eSLin Jinhan crypto_write(0x00030003, CRYPTO_FIFO_CTL);
974fe0c4b19SLin Jinhan crypto_write(0, CRYPTO_DMA_INT_EN);
97549a2135eSLin Jinhan
97649a2135eSLin Jinhan crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
97749a2135eSLin Jinhan
97849a2135eSLin Jinhan return 0;
97949a2135eSLin Jinhan }
98049a2135eSLin Jinhan
hw_cipher_crypt(const u8 * in,u8 * out,u64 len,const u8 * aad,u32 aad_len,u8 * tag,u32 tag_len,u32 mode)98149a2135eSLin Jinhan static int hw_cipher_crypt(const u8 *in, u8 *out, u64 len,
982c3ce9937SLin Jinhan const u8 *aad, u32 aad_len,
983c3ce9937SLin Jinhan u8 *tag, u32 tag_len, u32 mode)
98449a2135eSLin Jinhan {
985c3ce9937SLin Jinhan struct crypto_lli_desc *data_desc = NULL, *aad_desc = NULL;
986c3ce9937SLin Jinhan u8 *dma_in = NULL, *dma_out = NULL, *aad_tmp = NULL;
98749a2135eSLin Jinhan u32 rk_mode = RK_GET_RK_MODE(mode);
98849a2135eSLin Jinhan u32 reg_ctrl = 0, tmp_len = 0;
98949a2135eSLin Jinhan u32 expt_int = 0, mask = 0;
99049a2135eSLin Jinhan u32 key_chn = g_key_chn;
99149a2135eSLin Jinhan u32 tmp, dst_len = 0;
99249a2135eSLin Jinhan int ret = -1;
99349a2135eSLin Jinhan
99449a2135eSLin Jinhan if (rk_mode == RK_MODE_CTS && len <= AES_BLOCK_SIZE) {
99549a2135eSLin Jinhan printf("CTS mode length %u < 16Byte\n", (u32)len);
99649a2135eSLin Jinhan return -EINVAL;
99749a2135eSLin Jinhan }
99849a2135eSLin Jinhan
99949a2135eSLin Jinhan tmp_len = (rk_mode == RK_MODE_CTR) ? ROUNDUP(len, AES_BLOCK_SIZE) : len;
100049a2135eSLin Jinhan
100149a2135eSLin Jinhan data_desc = align_malloc(sizeof(*data_desc), LLI_ADDR_ALIGN_SIZE);
100249a2135eSLin Jinhan if (!data_desc)
100349a2135eSLin Jinhan goto exit;
100449a2135eSLin Jinhan
100549a2135eSLin Jinhan if (IS_ALIGNED((ulong)in, DATA_ADDR_ALIGN_SIZE) && tmp_len == len)
100649a2135eSLin Jinhan dma_in = (void *)in;
100749a2135eSLin Jinhan else
100849a2135eSLin Jinhan dma_in = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
100949a2135eSLin Jinhan if (!dma_in)
101049a2135eSLin Jinhan goto exit;
101149a2135eSLin Jinhan
101249a2135eSLin Jinhan if (out) {
101349a2135eSLin Jinhan if (IS_ALIGNED((ulong)out, DATA_ADDR_ALIGN_SIZE) &&
101449a2135eSLin Jinhan tmp_len == len)
101549a2135eSLin Jinhan dma_out = out;
101649a2135eSLin Jinhan else
101749a2135eSLin Jinhan dma_out = align_malloc(tmp_len, DATA_ADDR_ALIGN_SIZE);
101849a2135eSLin Jinhan if (!dma_out)
101949a2135eSLin Jinhan goto exit;
102049a2135eSLin Jinhan dst_len = tmp_len;
102149a2135eSLin Jinhan }
102249a2135eSLin Jinhan
102349a2135eSLin Jinhan memset(data_desc, 0x00, sizeof(*data_desc));
102449a2135eSLin Jinhan if (dma_in != in)
102549a2135eSLin Jinhan memcpy(dma_in, in, len);
102649a2135eSLin Jinhan
102749a2135eSLin Jinhan data_desc->src_addr = (u32)virt_to_phys(dma_in);
102849a2135eSLin Jinhan data_desc->src_len = tmp_len;
102949a2135eSLin Jinhan data_desc->dst_addr = (u32)virt_to_phys(dma_out);
103049a2135eSLin Jinhan data_desc->dst_len = dst_len;
1031d9332f1cSLin Jinhan data_desc->dma_ctrl = LLI_DMA_CTRL_LAST;
1032d9332f1cSLin Jinhan
1033d9332f1cSLin Jinhan if (IS_MAC_MODE(rk_mode)) {
1034d9332f1cSLin Jinhan expt_int = CRYPTO_LIST_DONE_INT_ST;
1035d9332f1cSLin Jinhan data_desc->dma_ctrl |= LLI_DMA_CTRL_LIST_DONE;
1036d9332f1cSLin Jinhan } else {
103749a2135eSLin Jinhan expt_int = CRYPTO_DST_ITEM_DONE_INT_ST;
1038d9332f1cSLin Jinhan data_desc->dma_ctrl |= LLI_DMA_CTRL_DST_DONE;
1039d9332f1cSLin Jinhan }
104049a2135eSLin Jinhan
1041ce7f4cd6SLin Jinhan data_desc->user_define = LLI_USER_CIPHER_START |
1042afdbec36SLin Jinhan LLI_USER_STRING_START |
1043c3ce9937SLin Jinhan LLI_USER_STRING_LAST |
1044c3ce9937SLin Jinhan (key_chn << 4);
1045afdbec36SLin Jinhan crypto_write((u32)virt_to_phys(data_desc), CRYPTO_DMA_LLI_ADDR);
1046afdbec36SLin Jinhan
1047afdbec36SLin Jinhan if (rk_mode == RK_MODE_CCM || rk_mode == RK_MODE_GCM) {
1048afdbec36SLin Jinhan u32 aad_tmp_len = 0;
1049c3ce9937SLin Jinhan
1050c3ce9937SLin Jinhan aad_desc = align_malloc(sizeof(*aad_desc), LLI_ADDR_ALIGN_SIZE);
1051c3ce9937SLin Jinhan if (!aad_desc)
1052c3ce9937SLin Jinhan goto exit;
1053c3ce9937SLin Jinhan
1054c3ce9937SLin Jinhan memset(aad_desc, 0x00, sizeof(*aad_desc));
1055c3ce9937SLin Jinhan aad_desc->next_addr = (u32)virt_to_phys(data_desc);
1056ce7f4cd6SLin Jinhan aad_desc->user_define = LLI_USER_CIPHER_START |
1057c3ce9937SLin Jinhan LLI_USER_STRING_START |
1058c3ce9937SLin Jinhan LLI_USER_STRING_LAST |
1059c3ce9937SLin Jinhan LLI_USER_STRING_AAD |
1060c3ce9937SLin Jinhan (key_chn << 4);
1061c3ce9937SLin Jinhan
1062c3ce9937SLin Jinhan if (rk_mode == RK_MODE_CCM) {
1063c3ce9937SLin Jinhan u8 padding[AES_BLOCK_SIZE];
1064c3ce9937SLin Jinhan u32 padding_size = 0;
1065c3ce9937SLin Jinhan
1066c3ce9937SLin Jinhan memset(padding, 0x00, sizeof(padding));
1067c3ce9937SLin Jinhan ccm_aad_padding(aad_len, padding, &padding_size);
1068c3ce9937SLin Jinhan
1069c3ce9937SLin Jinhan aad_tmp_len = aad_len + AES_BLOCK_SIZE + padding_size;
1070c3ce9937SLin Jinhan aad_tmp_len = ROUNDUP(aad_tmp_len, AES_BLOCK_SIZE);
1071c3ce9937SLin Jinhan aad_tmp = align_malloc(aad_tmp_len,
1072c3ce9937SLin Jinhan DATA_ADDR_ALIGN_SIZE);
1073c3ce9937SLin Jinhan if (!aad_tmp)
1074c3ce9937SLin Jinhan goto exit;
1075c3ce9937SLin Jinhan
10762db770efSLin Jinhan /* clear last block */
1077c3ce9937SLin Jinhan memset(aad_tmp + aad_tmp_len - AES_BLOCK_SIZE,
1078c3ce9937SLin Jinhan 0x00, AES_BLOCK_SIZE);
10792db770efSLin Jinhan
10802db770efSLin Jinhan /* read iv data from reg */
10812db770efSLin Jinhan get_iv_reg(key_chn, aad_tmp, AES_BLOCK_SIZE);
10822db770efSLin Jinhan ccm_compose_aad_iv(aad_tmp, tmp_len, aad_len, tag_len);
10832db770efSLin Jinhan memcpy(aad_tmp + AES_BLOCK_SIZE, padding, padding_size);
10842db770efSLin Jinhan
1085c3ce9937SLin Jinhan memcpy(aad_tmp + AES_BLOCK_SIZE + padding_size,
1086c3ce9937SLin Jinhan aad, aad_len);
1087c3ce9937SLin Jinhan } else {
1088c3ce9937SLin Jinhan aad_tmp_len = aad_len;
1089b83c40a4SLin Jinhan if (IS_ALIGNED((ulong)aad, DATA_ADDR_ALIGN_SIZE)) {
1090b83c40a4SLin Jinhan aad_tmp = (void *)aad;
1091b83c40a4SLin Jinhan } else {
1092c3ce9937SLin Jinhan aad_tmp = align_malloc(aad_tmp_len,
1093c3ce9937SLin Jinhan DATA_ADDR_ALIGN_SIZE);
1094c3ce9937SLin Jinhan if (!aad_tmp)
1095c3ce9937SLin Jinhan goto exit;
1096c3ce9937SLin Jinhan
1097c3ce9937SLin Jinhan memcpy(aad_tmp, aad, aad_tmp_len);
1098b83c40a4SLin Jinhan }
1099b83c40a4SLin Jinhan
1100c3ce9937SLin Jinhan set_aad_len_reg(key_chn, aad_tmp_len);
1101c3ce9937SLin Jinhan set_pc_len_reg(key_chn, tmp_len);
1102c3ce9937SLin Jinhan }
1103c3ce9937SLin Jinhan
1104c3ce9937SLin Jinhan aad_desc->src_addr = (u32)virt_to_phys(aad_tmp);
1105c3ce9937SLin Jinhan aad_desc->src_len = aad_tmp_len;
1106afdbec36SLin Jinhan
1107afdbec36SLin Jinhan if (aad_tmp_len) {
1108afdbec36SLin Jinhan data_desc->user_define = LLI_USER_STRING_START |
1109afdbec36SLin Jinhan LLI_USER_STRING_LAST |
1110afdbec36SLin Jinhan (key_chn << 4);
1111c3ce9937SLin Jinhan crypto_write((u32)virt_to_phys(aad_desc), CRYPTO_DMA_LLI_ADDR);
1112c3ce9937SLin Jinhan cache_op_inner(DCACHE_AREA_CLEAN, aad_tmp, aad_tmp_len);
1113c3ce9937SLin Jinhan cache_op_inner(DCACHE_AREA_CLEAN, aad_desc, sizeof(*aad_desc));
1114afdbec36SLin Jinhan }
1115c3ce9937SLin Jinhan }
111649a2135eSLin Jinhan
111749a2135eSLin Jinhan cache_op_inner(DCACHE_AREA_CLEAN, data_desc, sizeof(*data_desc));
111849a2135eSLin Jinhan cache_op_inner(DCACHE_AREA_CLEAN, dma_in, tmp_len);
111949a2135eSLin Jinhan cache_op_inner(DCACHE_AREA_INVALIDATE, dma_out, tmp_len);
112049a2135eSLin Jinhan
112149a2135eSLin Jinhan /* din_swap set 1, dout_swap set 1, default 1. */
112249a2135eSLin Jinhan crypto_write(0x00030003, CRYPTO_FIFO_CTL);
1123fe0c4b19SLin Jinhan crypto_write(0, CRYPTO_DMA_INT_EN);
112449a2135eSLin Jinhan
112549a2135eSLin Jinhan reg_ctrl = crypto_read(CRYPTO_BC_CTL) | CRYPTO_BC_ENABLE;
112649a2135eSLin Jinhan crypto_write(reg_ctrl | CRYPTO_WRITE_MASK_ALL, CRYPTO_BC_CTL);
112749a2135eSLin Jinhan crypto_write(0x00010001, CRYPTO_DMA_CTL);//start
112849a2135eSLin Jinhan
112949a2135eSLin Jinhan mask = ~(mask | CRYPTO_SYNC_LOCKSTEP_INT_ST);
113049a2135eSLin Jinhan
113149a2135eSLin Jinhan /* wait calc ok */
113249a2135eSLin Jinhan ret = RK_POLL_TIMEOUT(!(crypto_read(CRYPTO_DMA_INT_ST) & mask),
113349a2135eSLin Jinhan RK_CRYPTO_TIMEOUT);
113449a2135eSLin Jinhan tmp = crypto_read(CRYPTO_DMA_INT_ST);
113549a2135eSLin Jinhan crypto_write(tmp, CRYPTO_DMA_INT_ST);
113649a2135eSLin Jinhan
113749a2135eSLin Jinhan if ((tmp & mask) == expt_int) {
113849a2135eSLin Jinhan if (out && out != dma_out)
113949a2135eSLin Jinhan memcpy(out, dma_out, len);
1140d9332f1cSLin Jinhan
1141d9332f1cSLin Jinhan if (IS_NEED_TAG(rk_mode)) {
1142d9332f1cSLin Jinhan ret = WAIT_TAG_VALID(key_chn, RK_CRYPTO_TIMEOUT);
1143d9332f1cSLin Jinhan get_tag_from_reg(key_chn, tag, AES_BLOCK_SIZE);
1144d9332f1cSLin Jinhan }
114549a2135eSLin Jinhan } else {
11466b53126aSLin Jinhan dump_crypto_state(data_desc, tmp, expt_int, in, out, len, ret);
114749a2135eSLin Jinhan ret = -1;
114849a2135eSLin Jinhan }
114949a2135eSLin Jinhan
115049a2135eSLin Jinhan exit:
115149a2135eSLin Jinhan crypto_write(0xffff0000, CRYPTO_BC_CTL);//bc_ctl disable
115249a2135eSLin Jinhan align_free(data_desc);
1153c3ce9937SLin Jinhan align_free(aad_desc);
1154b83c40a4SLin Jinhan if (dma_in != in)
115549a2135eSLin Jinhan align_free(dma_in);
1156b83c40a4SLin Jinhan if (out && dma_out != out)
115749a2135eSLin Jinhan align_free(dma_out);
1158b83c40a4SLin Jinhan if (aad && aad != aad_tmp)
1159b83c40a4SLin Jinhan align_free(aad_tmp);
116049a2135eSLin Jinhan
116149a2135eSLin Jinhan return ret;
116249a2135eSLin Jinhan }
116349a2135eSLin Jinhan
hw_aes_init(u32 chn,const u8 * key,const u8 * twk_key,u32 key_len,const u8 * iv,u32 iv_len,u32 mode,bool enc)116449a2135eSLin Jinhan static int hw_aes_init(u32 chn, const u8 *key, const u8 *twk_key, u32 key_len,
116549a2135eSLin Jinhan const u8 *iv, u32 iv_len, u32 mode, bool enc)
116649a2135eSLin Jinhan {
116749a2135eSLin Jinhan u32 rk_mode = RK_GET_RK_MODE(mode);
116849a2135eSLin Jinhan
1169d9332f1cSLin Jinhan if (rk_mode > RK_MODE_XTS)
1170d9332f1cSLin Jinhan return -EINVAL;
1171d9332f1cSLin Jinhan
117249a2135eSLin Jinhan if (iv_len > AES_BLOCK_SIZE)
117349a2135eSLin Jinhan return -EINVAL;
117449a2135eSLin Jinhan
1175d9332f1cSLin Jinhan if (IS_NEED_IV(rk_mode)) {
117649a2135eSLin Jinhan if (!iv || iv_len != AES_BLOCK_SIZE)
117749a2135eSLin Jinhan return -EINVAL;
117849a2135eSLin Jinhan } else {
117949a2135eSLin Jinhan iv_len = 0;
118049a2135eSLin Jinhan }
118149a2135eSLin Jinhan
118249a2135eSLin Jinhan if (rk_mode == RK_MODE_XTS) {
118349a2135eSLin Jinhan if (key_len != AES_KEYSIZE_128 && key_len != AES_KEYSIZE_256)
118449a2135eSLin Jinhan return -EINVAL;
118549a2135eSLin Jinhan
118649a2135eSLin Jinhan if (!key || !twk_key)
118749a2135eSLin Jinhan return -EINVAL;
118849a2135eSLin Jinhan } else {
118949a2135eSLin Jinhan if (key_len != AES_KEYSIZE_128 &&
119049a2135eSLin Jinhan key_len != AES_KEYSIZE_192 &&
119149a2135eSLin Jinhan key_len != AES_KEYSIZE_256)
119249a2135eSLin Jinhan return -EINVAL;
119349a2135eSLin Jinhan }
119449a2135eSLin Jinhan
119549a2135eSLin Jinhan return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
119649a2135eSLin Jinhan CRYPTO_AES, mode, enc);
119749a2135eSLin Jinhan }
119849a2135eSLin Jinhan
hw_sm4_init(u32 chn,const u8 * key,const u8 * twk_key,u32 key_len,const u8 * iv,u32 iv_len,u32 mode,bool enc)119949a2135eSLin Jinhan static int hw_sm4_init(u32 chn, const u8 *key, const u8 *twk_key, u32 key_len,
120049a2135eSLin Jinhan const u8 *iv, u32 iv_len, u32 mode, bool enc)
120149a2135eSLin Jinhan {
120249a2135eSLin Jinhan u32 rk_mode = RK_GET_RK_MODE(mode);
120349a2135eSLin Jinhan
1204d9332f1cSLin Jinhan if (rk_mode > RK_MODE_XTS)
1205d9332f1cSLin Jinhan return -EINVAL;
1206d9332f1cSLin Jinhan
120749a2135eSLin Jinhan if (iv_len > SM4_BLOCK_SIZE || key_len != SM4_KEYSIZE)
120849a2135eSLin Jinhan return -EINVAL;
120949a2135eSLin Jinhan
1210d9332f1cSLin Jinhan if (IS_NEED_IV(rk_mode)) {
121149a2135eSLin Jinhan if (!iv || iv_len != SM4_BLOCK_SIZE)
121249a2135eSLin Jinhan return -EINVAL;
121349a2135eSLin Jinhan } else {
121449a2135eSLin Jinhan iv_len = 0;
121549a2135eSLin Jinhan }
121649a2135eSLin Jinhan
121749a2135eSLin Jinhan if (rk_mode == RK_MODE_XTS) {
121849a2135eSLin Jinhan if (!key || !twk_key)
121949a2135eSLin Jinhan return -EINVAL;
122049a2135eSLin Jinhan }
122149a2135eSLin Jinhan
122249a2135eSLin Jinhan return hw_cipher_init(chn, key, twk_key, key_len, iv, iv_len,
122349a2135eSLin Jinhan CRYPTO_SM4, mode, enc);
122449a2135eSLin Jinhan }
122549a2135eSLin Jinhan
rk_crypto_des(struct udevice * dev,u32 mode,const u8 * key,u32 key_len,const u8 * iv,const u8 * in,u8 * out,u32 len,bool enc)122649a2135eSLin Jinhan int rk_crypto_des(struct udevice *dev, u32 mode, const u8 *key, u32 key_len,
122749a2135eSLin Jinhan const u8 *iv, const u8 *in, u8 *out, u32 len, bool enc)
122849a2135eSLin Jinhan {
122949a2135eSLin Jinhan u32 rk_mode = RK_GET_RK_MODE(mode);
123049a2135eSLin Jinhan u8 tmp_key[24];
123149a2135eSLin Jinhan int ret;
123249a2135eSLin Jinhan
123349a2135eSLin Jinhan if (!is_des_mode(rk_mode))
123449a2135eSLin Jinhan return -EINVAL;
123549a2135eSLin Jinhan
123649a2135eSLin Jinhan if (key_len == DES_BLOCK_SIZE || key_len == 3 * DES_BLOCK_SIZE) {
123749a2135eSLin Jinhan memcpy(tmp_key, key, key_len);
123849a2135eSLin Jinhan } else if (key_len == 2 * DES_BLOCK_SIZE) {
123949a2135eSLin Jinhan memcpy(tmp_key, key, 16);
124049a2135eSLin Jinhan memcpy(tmp_key + 16, key, 8);
124149a2135eSLin Jinhan key_len = 3 * DES_BLOCK_SIZE;
124249a2135eSLin Jinhan } else {
124349a2135eSLin Jinhan return -EINVAL;
124449a2135eSLin Jinhan }
124549a2135eSLin Jinhan
124649a2135eSLin Jinhan ret = hw_cipher_init(0, tmp_key, NULL, key_len, iv, DES_BLOCK_SIZE,
124749a2135eSLin Jinhan CRYPTO_DES, mode, enc);
124849a2135eSLin Jinhan if (ret)
124949a2135eSLin Jinhan goto exit;
125049a2135eSLin Jinhan
125149a2135eSLin Jinhan ret = hw_cipher_crypt(in, out, len, NULL, 0,
125249a2135eSLin Jinhan NULL, 0, mode);
125349a2135eSLin Jinhan
125449a2135eSLin Jinhan exit:
125549a2135eSLin Jinhan return ret;
125649a2135eSLin Jinhan }
125749a2135eSLin Jinhan
rk_crypto_aes(struct udevice * dev,u32 mode,const u8 * key,const u8 * twk_key,u32 key_len,const u8 * iv,u32 iv_len,const u8 * in,u8 * out,u32 len,bool enc)125849a2135eSLin Jinhan int rk_crypto_aes(struct udevice *dev, u32 mode,
125949a2135eSLin Jinhan const u8 *key, const u8 *twk_key, u32 key_len,
126049a2135eSLin Jinhan const u8 *iv, u32 iv_len,
126149a2135eSLin Jinhan const u8 *in, u8 *out, u32 len, bool enc)
126249a2135eSLin Jinhan {
126349a2135eSLin Jinhan int ret;
126449a2135eSLin Jinhan
126549a2135eSLin Jinhan /* RV1126/RV1109 do not support aes-192 */
126649a2135eSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
126749a2135eSLin Jinhan if (key_len == AES_KEYSIZE_192)
126849a2135eSLin Jinhan return -EINVAL;
126949a2135eSLin Jinhan #endif
127049a2135eSLin Jinhan
127149a2135eSLin Jinhan ret = hw_aes_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
127249a2135eSLin Jinhan if (ret)
127349a2135eSLin Jinhan return ret;
127449a2135eSLin Jinhan
127549a2135eSLin Jinhan return hw_cipher_crypt(in, out, len, NULL, 0,
127649a2135eSLin Jinhan NULL, 0, mode);
127749a2135eSLin Jinhan }
127849a2135eSLin Jinhan
rk_crypto_sm4(struct udevice * dev,u32 mode,const u8 * key,const u8 * twk_key,u32 key_len,const u8 * iv,u32 iv_len,const u8 * in,u8 * out,u32 len,bool enc)127949a2135eSLin Jinhan int rk_crypto_sm4(struct udevice *dev, u32 mode,
128049a2135eSLin Jinhan const u8 *key, const u8 *twk_key, u32 key_len,
128149a2135eSLin Jinhan const u8 *iv, u32 iv_len,
128249a2135eSLin Jinhan const u8 *in, u8 *out, u32 len, bool enc)
128349a2135eSLin Jinhan {
128449a2135eSLin Jinhan int ret;
128549a2135eSLin Jinhan
128649a2135eSLin Jinhan ret = hw_sm4_init(0, key, twk_key, key_len, iv, iv_len, mode, enc);
128749a2135eSLin Jinhan if (ret)
128849a2135eSLin Jinhan return ret;
128949a2135eSLin Jinhan
129049a2135eSLin Jinhan return hw_cipher_crypt(in, out, len, NULL, 0, NULL, 0, mode);
129149a2135eSLin Jinhan }
129249a2135eSLin Jinhan
rockchip_crypto_cipher(struct udevice * dev,cipher_context * ctx,const u8 * in,u8 * out,u32 len,bool enc)129349a2135eSLin Jinhan int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx,
129449a2135eSLin Jinhan const u8 *in, u8 *out, u32 len, bool enc)
129549a2135eSLin Jinhan {
1296dd7763a8SFinley Xiao int ret;
1297dd7763a8SFinley Xiao
1298dd7763a8SFinley Xiao rk_crypto_enable_clk(dev);
1299dd7763a8SFinley Xiao
130049a2135eSLin Jinhan switch (ctx->algo) {
130149a2135eSLin Jinhan case CRYPTO_DES:
1302dd7763a8SFinley Xiao ret = rk_crypto_des(dev, ctx->mode, ctx->key, ctx->key_len,
130349a2135eSLin Jinhan ctx->iv, in, out, len, enc);
13049b9c232aSLin Jinhan break;
130549a2135eSLin Jinhan case CRYPTO_AES:
1306dd7763a8SFinley Xiao ret = rk_crypto_aes(dev, ctx->mode,
130749a2135eSLin Jinhan ctx->key, ctx->twk_key, ctx->key_len,
130849a2135eSLin Jinhan ctx->iv, ctx->iv_len, in, out, len, enc);
13099b9c232aSLin Jinhan break;
131049a2135eSLin Jinhan case CRYPTO_SM4:
1311dd7763a8SFinley Xiao ret = rk_crypto_sm4(dev, ctx->mode,
131249a2135eSLin Jinhan ctx->key, ctx->twk_key, ctx->key_len,
131349a2135eSLin Jinhan ctx->iv, ctx->iv_len, in, out, len, enc);
13149b9c232aSLin Jinhan break;
131549a2135eSLin Jinhan default:
1316dd7763a8SFinley Xiao ret = -EINVAL;
13179b9c232aSLin Jinhan break;
131849a2135eSLin Jinhan }
1319dd7763a8SFinley Xiao
1320dd7763a8SFinley Xiao rk_crypto_disable_clk(dev);
1321dd7763a8SFinley Xiao
1322dd7763a8SFinley Xiao return ret;
132349a2135eSLin Jinhan }
1324d9332f1cSLin Jinhan
rk_crypto_mac(struct udevice * dev,u32 algo,u32 mode,const u8 * key,u32 key_len,const u8 * in,u32 len,u8 * tag)1325d9332f1cSLin Jinhan int rk_crypto_mac(struct udevice *dev, u32 algo, u32 mode,
1326d9332f1cSLin Jinhan const u8 *key, u32 key_len,
1327d9332f1cSLin Jinhan const u8 *in, u32 len, u8 *tag)
1328d9332f1cSLin Jinhan {
1329d9332f1cSLin Jinhan u32 rk_mode = RK_GET_RK_MODE(mode);
1330d9332f1cSLin Jinhan int ret;
1331d9332f1cSLin Jinhan
1332d9332f1cSLin Jinhan if (!IS_MAC_MODE(rk_mode))
1333d9332f1cSLin Jinhan return -EINVAL;
1334d9332f1cSLin Jinhan
1335d9332f1cSLin Jinhan if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1336d9332f1cSLin Jinhan return -EINVAL;
1337d9332f1cSLin Jinhan
1338d9332f1cSLin Jinhan /* RV1126/RV1109 do not support aes-192 */
1339d9332f1cSLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1340d9332f1cSLin Jinhan if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1341d9332f1cSLin Jinhan return -EINVAL;
1342d9332f1cSLin Jinhan #endif
1343d9332f1cSLin Jinhan
1344d9332f1cSLin Jinhan ret = hw_cipher_init(g_key_chn, key, NULL, key_len, NULL, 0,
1345d9332f1cSLin Jinhan algo, mode, true);
1346d9332f1cSLin Jinhan if (ret)
1347d9332f1cSLin Jinhan return ret;
1348d9332f1cSLin Jinhan
1349d9332f1cSLin Jinhan return hw_cipher_crypt(in, NULL, len, NULL, 0,
1350d9332f1cSLin Jinhan tag, AES_BLOCK_SIZE, mode);
1351d9332f1cSLin Jinhan }
1352d9332f1cSLin Jinhan
rockchip_crypto_mac(struct udevice * dev,cipher_context * ctx,const u8 * in,u32 len,u8 * tag)1353d9332f1cSLin Jinhan int rockchip_crypto_mac(struct udevice *dev, cipher_context *ctx,
1354d9332f1cSLin Jinhan const u8 *in, u32 len, u8 *tag)
1355d9332f1cSLin Jinhan {
1356dd7763a8SFinley Xiao int ret = 0;
1357dd7763a8SFinley Xiao
1358dd7763a8SFinley Xiao rk_crypto_enable_clk(dev);
1359dd7763a8SFinley Xiao
1360dd7763a8SFinley Xiao ret = rk_crypto_mac(dev, ctx->algo, ctx->mode,
1361d9332f1cSLin Jinhan ctx->key, ctx->key_len, in, len, tag);
1362dd7763a8SFinley Xiao
1363dd7763a8SFinley Xiao rk_crypto_disable_clk(dev);
1364dd7763a8SFinley Xiao
1365dd7763a8SFinley Xiao return ret;
1366d9332f1cSLin Jinhan }
1367d9332f1cSLin Jinhan
rk_crypto_ae(struct udevice * dev,u32 algo,u32 mode,const u8 * key,u32 key_len,const u8 * nonce,u32 nonce_len,const u8 * in,u32 len,const u8 * aad,u32 aad_len,u8 * out,u8 * tag)1368c3ce9937SLin Jinhan int rk_crypto_ae(struct udevice *dev, u32 algo, u32 mode,
1369c3ce9937SLin Jinhan const u8 *key, u32 key_len, const u8 *nonce, u32 nonce_len,
1370c3ce9937SLin Jinhan const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1371c3ce9937SLin Jinhan u8 *out, u8 *tag)
1372c3ce9937SLin Jinhan {
1373c3ce9937SLin Jinhan u32 rk_mode = RK_GET_RK_MODE(mode);
1374c3ce9937SLin Jinhan int ret;
1375c3ce9937SLin Jinhan
1376c3ce9937SLin Jinhan if (!IS_AE_MODE(rk_mode))
1377c3ce9937SLin Jinhan return -EINVAL;
1378c3ce9937SLin Jinhan
1379afdbec36SLin Jinhan if (len == 0)
1380afdbec36SLin Jinhan return -EINVAL;
1381afdbec36SLin Jinhan
1382c3ce9937SLin Jinhan if (algo != CRYPTO_AES && algo != CRYPTO_SM4)
1383c3ce9937SLin Jinhan return -EINVAL;
1384c3ce9937SLin Jinhan
1385c3ce9937SLin Jinhan /* RV1126/RV1109 do not support aes-192 */
1386c3ce9937SLin Jinhan #if defined(CONFIG_ROCKCHIP_RV1126)
1387c3ce9937SLin Jinhan if (algo == CRYPTO_AES && key_len == AES_KEYSIZE_192)
1388c3ce9937SLin Jinhan return -EINVAL;
1389c3ce9937SLin Jinhan #endif
1390c3ce9937SLin Jinhan
1391c3ce9937SLin Jinhan ret = hw_cipher_init(g_key_chn, key, NULL, key_len, nonce, nonce_len,
1392c3ce9937SLin Jinhan algo, mode, true);
1393c3ce9937SLin Jinhan if (ret)
1394c3ce9937SLin Jinhan return ret;
1395c3ce9937SLin Jinhan
1396c3ce9937SLin Jinhan return hw_cipher_crypt(in, out, len, aad, aad_len,
1397c3ce9937SLin Jinhan tag, AES_BLOCK_SIZE, mode);
1398c3ce9937SLin Jinhan }
1399c3ce9937SLin Jinhan
rockchip_crypto_ae(struct udevice * dev,cipher_context * ctx,const u8 * in,u32 len,const u8 * aad,u32 aad_len,u8 * out,u8 * tag)1400c3ce9937SLin Jinhan int rockchip_crypto_ae(struct udevice *dev, cipher_context *ctx,
1401c3ce9937SLin Jinhan const u8 *in, u32 len, const u8 *aad, u32 aad_len,
1402c3ce9937SLin Jinhan u8 *out, u8 *tag)
1403c3ce9937SLin Jinhan {
1404dd7763a8SFinley Xiao int ret = 0;
1405dd7763a8SFinley Xiao
1406dd7763a8SFinley Xiao rk_crypto_enable_clk(dev);
1407dd7763a8SFinley Xiao
1408dd7763a8SFinley Xiao ret = rk_crypto_ae(dev, ctx->algo, ctx->mode, ctx->key, ctx->key_len,
1409c3ce9937SLin Jinhan ctx->iv, ctx->iv_len, in, len,
1410c3ce9937SLin Jinhan aad, aad_len, out, tag);
1411dd7763a8SFinley Xiao
1412dd7763a8SFinley Xiao rk_crypto_disable_clk(dev);
1413dd7763a8SFinley Xiao
1414dd7763a8SFinley Xiao return ret;
1415c3ce9937SLin Jinhan }
1416c3ce9937SLin Jinhan
1417f489a6d7SJoseph Chen #if CONFIG_IS_ENABLED(DM_KEYLAD)
rockchip_crypto_fw_cipher(struct udevice * dev,cipher_fw_context * ctx,const u8 * in,u8 * out,u32 len,bool enc)1418f489a6d7SJoseph Chen int rockchip_crypto_fw_cipher(struct udevice *dev, cipher_fw_context *ctx,
1419f489a6d7SJoseph Chen const u8 *in, u8 *out, u32 len, bool enc)
1420f489a6d7SJoseph Chen {
1421f489a6d7SJoseph Chen int ret;
1422f489a6d7SJoseph Chen
1423f489a6d7SJoseph Chen rk_crypto_enable_clk(dev);
1424f489a6d7SJoseph Chen
1425f489a6d7SJoseph Chen switch (ctx->algo) {
1426f489a6d7SJoseph Chen case CRYPTO_DES:
1427f489a6d7SJoseph Chen ret = rk_crypto_des(dev, ctx->mode, NULL, ctx->key_len,
1428f489a6d7SJoseph Chen ctx->iv, in, out, len, enc);
1429f489a6d7SJoseph Chen break;
1430f489a6d7SJoseph Chen case CRYPTO_AES:
1431f489a6d7SJoseph Chen ret = rk_crypto_aes(dev, ctx->mode, NULL, NULL, ctx->key_len,
1432f489a6d7SJoseph Chen ctx->iv, ctx->iv_len, in, out, len, enc);
1433f489a6d7SJoseph Chen break;
1434f489a6d7SJoseph Chen case CRYPTO_SM4:
1435f489a6d7SJoseph Chen ret = rk_crypto_sm4(dev, ctx->mode, NULL, NULL, ctx->key_len,
1436f489a6d7SJoseph Chen ctx->iv, ctx->iv_len, in, out, len, enc);
1437f489a6d7SJoseph Chen break;
1438f489a6d7SJoseph Chen default:
1439f489a6d7SJoseph Chen ret = -EINVAL;
1440f489a6d7SJoseph Chen break;
1441f489a6d7SJoseph Chen }
1442f489a6d7SJoseph Chen
1443f489a6d7SJoseph Chen rk_crypto_disable_clk(dev);
1444f489a6d7SJoseph Chen
1445f489a6d7SJoseph Chen return ret;
1446f489a6d7SJoseph Chen }
1447f489a6d7SJoseph Chen
rockchip_crypto_keytable_addr(struct udevice * dev)1448eecb3765SLin Jinhan static ulong rockchip_crypto_keytable_addr(struct udevice *dev)
1449eecb3765SLin Jinhan {
1450eecb3765SLin Jinhan return CRYPTO_S_BY_KEYLAD_BASE + CRYPTO_CH0_KEY_0;
1451eecb3765SLin Jinhan }
1452f489a6d7SJoseph Chen #endif
145349a2135eSLin Jinhan #endif
145449a2135eSLin Jinhan
1455864e581cSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
rockchip_crypto_rsa_verify(struct udevice * dev,rsa_key * ctx,u8 * sign,u8 * output)1456b353a43cSLin Jinhan static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx,
1457b353a43cSLin Jinhan u8 *sign, u8 *output)
1458b353a43cSLin Jinhan {
1459b353a43cSLin Jinhan struct mpa_num *mpa_m = NULL, *mpa_e = NULL, *mpa_n = NULL;
1460b353a43cSLin Jinhan struct mpa_num *mpa_c = NULL, *mpa_result = NULL;
1461b353a43cSLin Jinhan u32 n_bits, n_words;
1462b353a43cSLin Jinhan int ret;
1463b353a43cSLin Jinhan
1464b353a43cSLin Jinhan if (!ctx)
1465b353a43cSLin Jinhan return -EINVAL;
1466b353a43cSLin Jinhan
1467b353a43cSLin Jinhan if (ctx->algo != CRYPTO_RSA512 &&
1468b353a43cSLin Jinhan ctx->algo != CRYPTO_RSA1024 &&
1469b353a43cSLin Jinhan ctx->algo != CRYPTO_RSA2048 &&
1470b353a43cSLin Jinhan ctx->algo != CRYPTO_RSA3072 &&
1471b353a43cSLin Jinhan ctx->algo != CRYPTO_RSA4096)
1472b353a43cSLin Jinhan return -EINVAL;
1473b353a43cSLin Jinhan
1474b353a43cSLin Jinhan n_bits = crypto_algo_nbits(ctx->algo);
1475b353a43cSLin Jinhan n_words = BITS2WORD(n_bits);
1476b353a43cSLin Jinhan
1477549a74f7SLin Jinhan ret = rk_mpa_alloc(&mpa_m, sign, n_words);
1478b353a43cSLin Jinhan if (ret)
1479b353a43cSLin Jinhan goto exit;
1480b353a43cSLin Jinhan
1481549a74f7SLin Jinhan ret = rk_mpa_alloc(&mpa_e, ctx->e, n_words);
1482549a74f7SLin Jinhan if (ret)
1483549a74f7SLin Jinhan goto exit;
1484b353a43cSLin Jinhan
1485549a74f7SLin Jinhan ret = rk_mpa_alloc(&mpa_n, ctx->n, n_words);
1486549a74f7SLin Jinhan if (ret)
1487549a74f7SLin Jinhan goto exit;
1488549a74f7SLin Jinhan
1489549a74f7SLin Jinhan if (ctx->c) {
1490549a74f7SLin Jinhan ret = rk_mpa_alloc(&mpa_c, ctx->c, n_words);
1491549a74f7SLin Jinhan if (ret)
1492549a74f7SLin Jinhan goto exit;
1493549a74f7SLin Jinhan }
1494549a74f7SLin Jinhan
1495549a74f7SLin Jinhan ret = rk_mpa_alloc(&mpa_result, NULL, n_words);
1496549a74f7SLin Jinhan if (ret)
1497549a74f7SLin Jinhan goto exit;
1498b353a43cSLin Jinhan
1499dd7763a8SFinley Xiao rk_crypto_enable_clk(dev);
1500b353a43cSLin Jinhan ret = rk_exptmod_np(mpa_m, mpa_e, mpa_n, mpa_c, mpa_result);
1501b353a43cSLin Jinhan if (!ret)
1502549a74f7SLin Jinhan memcpy(output, mpa_result->d, BITS2BYTE(n_bits));
1503dd7763a8SFinley Xiao rk_crypto_disable_clk(dev);
1504b353a43cSLin Jinhan
1505b353a43cSLin Jinhan exit:
1506b353a43cSLin Jinhan rk_mpa_free(&mpa_m);
1507b353a43cSLin Jinhan rk_mpa_free(&mpa_e);
1508b353a43cSLin Jinhan rk_mpa_free(&mpa_n);
1509b353a43cSLin Jinhan rk_mpa_free(&mpa_c);
1510b353a43cSLin Jinhan rk_mpa_free(&mpa_result);
1511b353a43cSLin Jinhan
1512b353a43cSLin Jinhan return ret;
1513b353a43cSLin Jinhan }
1514864e581cSLin Jinhan #endif
1515b353a43cSLin Jinhan
151602b4cf42SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
rockchip_crypto_ec_verify(struct udevice * dev,ec_key * ctx,u8 * hash,u32 hash_len,u8 * sign)151702b4cf42SLin Jinhan static int rockchip_crypto_ec_verify(struct udevice *dev, ec_key *ctx,
151802b4cf42SLin Jinhan u8 *hash, u32 hash_len, u8 *sign)
151902b4cf42SLin Jinhan {
152002b4cf42SLin Jinhan struct mpa_num *bn_sign = NULL;
152102b4cf42SLin Jinhan struct rk_ecp_point point_P, point_sign;
152202b4cf42SLin Jinhan u32 n_bits, n_words;
152302b4cf42SLin Jinhan int ret;
152402b4cf42SLin Jinhan
152502b4cf42SLin Jinhan if (!ctx)
152602b4cf42SLin Jinhan return -EINVAL;
152702b4cf42SLin Jinhan
152802b4cf42SLin Jinhan if (ctx->algo != CRYPTO_SM2 &&
152902b4cf42SLin Jinhan ctx->algo != CRYPTO_ECC_192R1 &&
153002b4cf42SLin Jinhan ctx->algo != CRYPTO_ECC_224R1 &&
153102b4cf42SLin Jinhan ctx->algo != CRYPTO_ECC_256R1)
153202b4cf42SLin Jinhan return -EINVAL;
153302b4cf42SLin Jinhan
153402b4cf42SLin Jinhan n_bits = crypto_algo_nbits(ctx->algo);
153502b4cf42SLin Jinhan n_words = BITS2WORD(n_bits);
153602b4cf42SLin Jinhan
153702b4cf42SLin Jinhan ret = rk_mpa_alloc(&bn_sign, sign, n_words);
153802b4cf42SLin Jinhan if (ret)
153902b4cf42SLin Jinhan goto exit;
154002b4cf42SLin Jinhan
154102b4cf42SLin Jinhan ret = rk_mpa_alloc(&point_P.x, ctx->x, n_words);
154202b4cf42SLin Jinhan ret |= rk_mpa_alloc(&point_P.y, ctx->y, n_words);
154302b4cf42SLin Jinhan if (ret)
154402b4cf42SLin Jinhan goto exit;
154502b4cf42SLin Jinhan
154602b4cf42SLin Jinhan ret = rk_mpa_alloc(&point_sign.x, sign, n_words);
154702b4cf42SLin Jinhan ret |= rk_mpa_alloc(&point_sign.y, sign + WORD2BYTE(n_words), n_words);
154802b4cf42SLin Jinhan if (ret)
154902b4cf42SLin Jinhan goto exit;
155002b4cf42SLin Jinhan
155102b4cf42SLin Jinhan rk_crypto_enable_clk(dev);
155202b4cf42SLin Jinhan ret = rockchip_ecc_verify(ctx->algo, hash, hash_len, &point_P, &point_sign);
155302b4cf42SLin Jinhan rk_crypto_disable_clk(dev);
155402b4cf42SLin Jinhan exit:
155502b4cf42SLin Jinhan rk_mpa_free(&bn_sign);
155602b4cf42SLin Jinhan rk_mpa_free(&point_P.x);
155702b4cf42SLin Jinhan rk_mpa_free(&point_P.y);
155802b4cf42SLin Jinhan rk_mpa_free(&point_sign.x);
155902b4cf42SLin Jinhan rk_mpa_free(&point_sign.y);
156002b4cf42SLin Jinhan
156102b4cf42SLin Jinhan return ret;
156202b4cf42SLin Jinhan }
156302b4cf42SLin Jinhan #endif
156402b4cf42SLin Jinhan
rockchip_crypto_is_secure(struct udevice * dev)156536e17db4Stroy.lin static bool rockchip_crypto_is_secure(struct udevice *dev)
156636e17db4Stroy.lin {
156736e17db4Stroy.lin struct rockchip_crypto_priv *priv = dev_get_priv(dev);
156836e17db4Stroy.lin
156936e17db4Stroy.lin return priv->secure;
157036e17db4Stroy.lin }
157136e17db4Stroy.lin
1572b353a43cSLin Jinhan static const struct dm_crypto_ops rockchip_crypto_ops = {
1573b353a43cSLin Jinhan .capability = rockchip_crypto_capability,
1574b353a43cSLin Jinhan .sha_init = rockchip_crypto_sha_init,
1575b353a43cSLin Jinhan .sha_update = rockchip_crypto_sha_update,
1576b353a43cSLin Jinhan .sha_final = rockchip_crypto_sha_final,
157749a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
1578b353a43cSLin Jinhan .rsa_verify = rockchip_crypto_rsa_verify,
157949a2135eSLin Jinhan #endif
158002b4cf42SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
158102b4cf42SLin Jinhan .ec_verify = rockchip_crypto_ec_verify,
158202b4cf42SLin Jinhan #endif
158349a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
158449a2135eSLin Jinhan .hmac_init = rockchip_crypto_hmac_init,
158549a2135eSLin Jinhan .hmac_update = rockchip_crypto_hmac_update,
158649a2135eSLin Jinhan .hmac_final = rockchip_crypto_hmac_final,
158749a2135eSLin Jinhan #endif
158849a2135eSLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
158949a2135eSLin Jinhan .cipher_crypt = rockchip_crypto_cipher,
1590d9332f1cSLin Jinhan .cipher_mac = rockchip_crypto_mac,
1591c3ce9937SLin Jinhan .cipher_ae = rockchip_crypto_ae,
1592f489a6d7SJoseph Chen #if CONFIG_IS_ENABLED(DM_KEYLAD)
1593eecb3765SLin Jinhan .cipher_fw_crypt = rockchip_crypto_fw_cipher,
1594eecb3765SLin Jinhan .keytable_addr = rockchip_crypto_keytable_addr,
159549a2135eSLin Jinhan #endif
1596f489a6d7SJoseph Chen #endif
159736e17db4Stroy.lin .is_secure = rockchip_crypto_is_secure,
1598b353a43cSLin Jinhan };
1599b353a43cSLin Jinhan
1600b353a43cSLin Jinhan /*
1601b353a43cSLin Jinhan * Only use "clocks" to parse crypto clock id and use rockchip_get_clk().
1602b353a43cSLin Jinhan * Because we always add crypto node in U-Boot dts, when kernel dtb enabled :
1603b353a43cSLin Jinhan *
1604b353a43cSLin Jinhan * 1. There is cru phandle mismatch between U-Boot and kernel dtb;
1605b353a43cSLin Jinhan * 2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property;
1606b353a43cSLin Jinhan */
rockchip_crypto_ofdata_to_platdata(struct udevice * dev)1607b353a43cSLin Jinhan static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev)
1608b353a43cSLin Jinhan {
1609b353a43cSLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1610b353a43cSLin Jinhan int len, ret = -EINVAL;
1611b353a43cSLin Jinhan
1612a24b2aebSLin Jinhan memset(priv, 0x00, sizeof(*priv));
1613a24b2aebSLin Jinhan
1614a24b2aebSLin Jinhan priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev);
1615a24b2aebSLin Jinhan if (priv->reg == FDT_ADDR_T_NONE)
1616a24b2aebSLin Jinhan return -EINVAL;
1617a24b2aebSLin Jinhan
1618a24b2aebSLin Jinhan crypto_base = priv->reg;
1619a24b2aebSLin Jinhan
162036e17db4Stroy.lin priv->secure = dev_read_bool(dev, "secure");
162136e17db4Stroy.lin priv->enabled = true;
162236e17db4Stroy.lin
162336e17db4Stroy.lin #if !defined(CONFIG_SPL_BUILD)
162436e17db4Stroy.lin /* uboot disabled secure crypto */
162536e17db4Stroy.lin priv->enabled = !priv->secure;
162636e17db4Stroy.lin #endif
162736e17db4Stroy.lin if (!priv->enabled)
162836e17db4Stroy.lin return 0;
162936e17db4Stroy.lin
1630a24b2aebSLin Jinhan /* if there is no clocks in dts, just skip it */
1631b353a43cSLin Jinhan if (!dev_read_prop(dev, "clocks", &len)) {
1632b353a43cSLin Jinhan printf("Can't find \"clocks\" property\n");
1633a24b2aebSLin Jinhan return 0;
1634b353a43cSLin Jinhan }
1635b353a43cSLin Jinhan
1636b353a43cSLin Jinhan priv->clocks = malloc(len);
1637b353a43cSLin Jinhan if (!priv->clocks)
1638b353a43cSLin Jinhan return -ENOMEM;
1639b353a43cSLin Jinhan
1640da703fb5SLin Jinhan priv->nclocks = len / (2 * sizeof(u32));
1641b353a43cSLin Jinhan if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks,
1642b353a43cSLin Jinhan priv->nclocks)) {
1643b353a43cSLin Jinhan printf("Can't read \"clocks\" property\n");
1644b353a43cSLin Jinhan ret = -EINVAL;
1645b353a43cSLin Jinhan goto exit;
1646b353a43cSLin Jinhan }
1647b353a43cSLin Jinhan
1648da703fb5SLin Jinhan if (dev_read_prop(dev, "clock-frequency", &len)) {
1649b353a43cSLin Jinhan priv->frequencies = malloc(len);
1650b353a43cSLin Jinhan if (!priv->frequencies) {
1651b353a43cSLin Jinhan ret = -ENOMEM;
1652b353a43cSLin Jinhan goto exit;
1653b353a43cSLin Jinhan }
1654a8335d81SFinley Xiao priv->freq_nclocks = len / sizeof(u32);
1655b353a43cSLin Jinhan if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies,
1656da703fb5SLin Jinhan priv->freq_nclocks)) {
1657b353a43cSLin Jinhan printf("Can't read \"clock-frequency\" property\n");
1658b353a43cSLin Jinhan ret = -EINVAL;
1659b353a43cSLin Jinhan goto exit;
1660b353a43cSLin Jinhan }
1661da703fb5SLin Jinhan }
1662b353a43cSLin Jinhan
1663b353a43cSLin Jinhan return 0;
1664b353a43cSLin Jinhan exit:
1665b353a43cSLin Jinhan if (priv->clocks)
1666b353a43cSLin Jinhan free(priv->clocks);
1667b353a43cSLin Jinhan
1668b353a43cSLin Jinhan if (priv->frequencies)
1669b353a43cSLin Jinhan free(priv->frequencies);
1670b353a43cSLin Jinhan
1671b353a43cSLin Jinhan return ret;
1672b353a43cSLin Jinhan }
1673b353a43cSLin Jinhan
rk_crypto_set_clk(struct udevice * dev)16746cebff12SJoseph Chen static int rk_crypto_set_clk(struct udevice *dev)
1675b353a43cSLin Jinhan {
16766cebff12SJoseph Chen struct rockchip_crypto_priv *priv = dev_get_priv(dev);
16776cebff12SJoseph Chen struct clk clk;
1678a24b2aebSLin Jinhan int i, ret;
1679b353a43cSLin Jinhan
1680a8335d81SFinley Xiao /* use standard "assigned-clock-rates" props */
1681a8335d81SFinley Xiao if (dev_read_size(dev, "assigned-clock-rates") > 0)
1682a8335d81SFinley Xiao return clk_set_defaults(dev);
1683da703fb5SLin Jinhan
1684a8335d81SFinley Xiao /* use "clock-frequency" props */
1685da703fb5SLin Jinhan if (priv->freq_nclocks == 0)
1686a24b2aebSLin Jinhan return 0;
168749a2135eSLin Jinhan
1688da703fb5SLin Jinhan for (i = 0; i < priv->freq_nclocks; i++) {
16896cebff12SJoseph Chen ret = clk_get_by_index(dev, i, &clk);
16906cebff12SJoseph Chen if (ret < 0) {
16916cebff12SJoseph Chen printf("Failed to get clk index %d, ret=%d\n", i, ret);
1692b353a43cSLin Jinhan return ret;
1693b353a43cSLin Jinhan }
16946cebff12SJoseph Chen ret = clk_set_rate(&clk, priv->frequencies[i]);
1695b353a43cSLin Jinhan if (ret < 0) {
1696b353a43cSLin Jinhan printf("%s: Failed to set clk(%ld): ret=%d\n",
16976cebff12SJoseph Chen __func__, clk.id, ret);
1698b353a43cSLin Jinhan return ret;
1699b353a43cSLin Jinhan }
1700b353a43cSLin Jinhan }
1701b353a43cSLin Jinhan
1702a24b2aebSLin Jinhan return 0;
1703a24b2aebSLin Jinhan }
1704a24b2aebSLin Jinhan
rockchip_crypto_probe(struct udevice * dev)1705a24b2aebSLin Jinhan static int rockchip_crypto_probe(struct udevice *dev)
1706a24b2aebSLin Jinhan {
1707a24b2aebSLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
1708a24b2aebSLin Jinhan struct rk_crypto_soc_data *sdata;
1709a24b2aebSLin Jinhan int ret = 0;
1710a24b2aebSLin Jinhan
1711a24b2aebSLin Jinhan sdata = (struct rk_crypto_soc_data *)dev_get_driver_data(dev);
171258432b6fSLin Jinhan
171336e17db4Stroy.lin if (!priv->enabled)
171436e17db4Stroy.lin return 0;
1715a24b2aebSLin Jinhan
1716a24b2aebSLin Jinhan priv->hw_ctx = memalign(LLI_ADDR_ALIGN_SIZE,
1717a24b2aebSLin Jinhan sizeof(struct rk_hash_ctx));
1718a24b2aebSLin Jinhan if (!priv->hw_ctx)
1719a24b2aebSLin Jinhan return -ENOMEM;
1720a24b2aebSLin Jinhan
17216cebff12SJoseph Chen ret = rk_crypto_set_clk(dev);
1722a24b2aebSLin Jinhan if (ret)
1723a24b2aebSLin Jinhan return ret;
1724a24b2aebSLin Jinhan
1725f2c2c30cSLin Jinhan rk_crypto_enable_clk(dev);
1726f2c2c30cSLin Jinhan
1727b353a43cSLin Jinhan hw_crypto_reset();
1728b353a43cSLin Jinhan
172936e17db4Stroy.lin if (sdata->dynamic_cap)
173036e17db4Stroy.lin sdata->capability = sdata->dynamic_cap();
173136e17db4Stroy.lin
173236e17db4Stroy.lin priv->soc_data = sdata;
173336e17db4Stroy.lin
1734f2c2c30cSLin Jinhan rk_crypto_disable_clk(dev);
1735f2c2c30cSLin Jinhan
1736b353a43cSLin Jinhan return 0;
1737b353a43cSLin Jinhan }
1738b353a43cSLin Jinhan
173949a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base = {
174049a2135eSLin Jinhan .capability = CRYPTO_MD5 |
174149a2135eSLin Jinhan CRYPTO_SHA1 |
174249a2135eSLin Jinhan CRYPTO_SHA256 |
174349a2135eSLin Jinhan CRYPTO_SHA512 |
174449a2135eSLin Jinhan CRYPTO_HMAC_MD5 |
174549a2135eSLin Jinhan CRYPTO_HMAC_SHA1 |
174649a2135eSLin Jinhan CRYPTO_HMAC_SHA256 |
174749a2135eSLin Jinhan CRYPTO_HMAC_SHA512 |
174849a2135eSLin Jinhan CRYPTO_RSA512 |
174949a2135eSLin Jinhan CRYPTO_RSA1024 |
175049a2135eSLin Jinhan CRYPTO_RSA2048 |
175149a2135eSLin Jinhan CRYPTO_RSA3072 |
175249a2135eSLin Jinhan CRYPTO_RSA4096 |
175349a2135eSLin Jinhan CRYPTO_DES |
175449a2135eSLin Jinhan CRYPTO_AES,
175549a2135eSLin Jinhan };
175649a2135eSLin Jinhan
175749a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_base_sm = {
175849a2135eSLin Jinhan .capability = CRYPTO_MD5 |
175949a2135eSLin Jinhan CRYPTO_SHA1 |
176049a2135eSLin Jinhan CRYPTO_SHA256 |
176149a2135eSLin Jinhan CRYPTO_SHA512 |
176249a2135eSLin Jinhan CRYPTO_SM3 |
176349a2135eSLin Jinhan CRYPTO_HMAC_MD5 |
176449a2135eSLin Jinhan CRYPTO_HMAC_SHA1 |
176549a2135eSLin Jinhan CRYPTO_HMAC_SHA256 |
176649a2135eSLin Jinhan CRYPTO_HMAC_SHA512 |
176749a2135eSLin Jinhan CRYPTO_HMAC_SM3 |
176849a2135eSLin Jinhan CRYPTO_RSA512 |
176949a2135eSLin Jinhan CRYPTO_RSA1024 |
177049a2135eSLin Jinhan CRYPTO_RSA2048 |
177149a2135eSLin Jinhan CRYPTO_RSA3072 |
177249a2135eSLin Jinhan CRYPTO_RSA4096 |
177349a2135eSLin Jinhan CRYPTO_DES |
177449a2135eSLin Jinhan CRYPTO_AES |
177549a2135eSLin Jinhan CRYPTO_SM4,
177649a2135eSLin Jinhan };
177749a2135eSLin Jinhan
177849a2135eSLin Jinhan static const struct rk_crypto_soc_data soc_data_rk1808 = {
177949a2135eSLin Jinhan .capability = CRYPTO_MD5 |
178049a2135eSLin Jinhan CRYPTO_SHA1 |
178149a2135eSLin Jinhan CRYPTO_SHA256 |
178249a2135eSLin Jinhan CRYPTO_HMAC_MD5 |
178349a2135eSLin Jinhan CRYPTO_HMAC_SHA1 |
178449a2135eSLin Jinhan CRYPTO_HMAC_SHA256 |
178549a2135eSLin Jinhan CRYPTO_RSA512 |
178649a2135eSLin Jinhan CRYPTO_RSA1024 |
178749a2135eSLin Jinhan CRYPTO_RSA2048 |
178849a2135eSLin Jinhan CRYPTO_RSA3072 |
178949a2135eSLin Jinhan CRYPTO_RSA4096,
179049a2135eSLin Jinhan };
179149a2135eSLin Jinhan
179258432b6fSLin Jinhan static const struct rk_crypto_soc_data soc_data_cryptov3 = {
179358432b6fSLin Jinhan .capability = 0,
179458432b6fSLin Jinhan .dynamic_cap = crypto_v3_dynamic_cap,
179558432b6fSLin Jinhan };
179658432b6fSLin Jinhan
1797b353a43cSLin Jinhan static const struct udevice_id rockchip_crypto_ids[] = {
179849a2135eSLin Jinhan {
179949a2135eSLin Jinhan .compatible = "rockchip,px30-crypto",
180049a2135eSLin Jinhan .data = (ulong)&soc_data_base
180149a2135eSLin Jinhan },
180249a2135eSLin Jinhan {
180349a2135eSLin Jinhan .compatible = "rockchip,rk1808-crypto",
180449a2135eSLin Jinhan .data = (ulong)&soc_data_rk1808
180549a2135eSLin Jinhan },
180649a2135eSLin Jinhan {
180749a2135eSLin Jinhan .compatible = "rockchip,rk3308-crypto",
180849a2135eSLin Jinhan .data = (ulong)&soc_data_base
180949a2135eSLin Jinhan },
181049a2135eSLin Jinhan {
181149a2135eSLin Jinhan .compatible = "rockchip,rv1126-crypto",
181249a2135eSLin Jinhan .data = (ulong)&soc_data_base_sm
181349a2135eSLin Jinhan },
181449a2135eSLin Jinhan {
181549a2135eSLin Jinhan .compatible = "rockchip,rk3568-crypto",
181649a2135eSLin Jinhan .data = (ulong)&soc_data_base_sm
181749a2135eSLin Jinhan },
18185b3e3895SLin Jinhan {
18195b3e3895SLin Jinhan .compatible = "rockchip,rk3588-crypto",
18205b3e3895SLin Jinhan .data = (ulong)&soc_data_base_sm
18215b3e3895SLin Jinhan },
182258432b6fSLin Jinhan {
1823f93f9077SLin Jinhan .compatible = "rockchip,crypto-v3",
182458432b6fSLin Jinhan .data = (ulong)&soc_data_cryptov3
182558432b6fSLin Jinhan },
18262bcebb1aSLin Jinhan {
18272bcebb1aSLin Jinhan .compatible = "rockchip,crypto-v4",
18282bcebb1aSLin Jinhan .data = (ulong)&soc_data_cryptov3 /* reuse crypto v3 config */
18292bcebb1aSLin Jinhan },
1830b353a43cSLin Jinhan { }
1831b353a43cSLin Jinhan };
1832b353a43cSLin Jinhan
1833b353a43cSLin Jinhan U_BOOT_DRIVER(rockchip_crypto_v2) = {
1834b353a43cSLin Jinhan .name = "rockchip_crypto_v2",
1835b353a43cSLin Jinhan .id = UCLASS_CRYPTO,
1836b353a43cSLin Jinhan .of_match = rockchip_crypto_ids,
1837b353a43cSLin Jinhan .ops = &rockchip_crypto_ops,
1838b353a43cSLin Jinhan .probe = rockchip_crypto_probe,
1839b353a43cSLin Jinhan .ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata,
1840b353a43cSLin Jinhan .priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv),
1841b353a43cSLin Jinhan };
1842