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