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