100565589SLin Jinhan // SPDX-License-Identifier: GPL-2.0 200565589SLin Jinhan /* 300565589SLin Jinhan * Copyright (c) 2025 Rockchip Electronics Co., Ltd 400565589SLin Jinhan */ 500565589SLin Jinhan 600565589SLin Jinhan #include <clk.h> 700565589SLin Jinhan #include <clk-uclass.h> 800565589SLin Jinhan #include <common.h> 900565589SLin Jinhan #include <crypto.h> 1000565589SLin Jinhan #include <dm.h> 1100565589SLin Jinhan #include <asm/io.h> 1200565589SLin Jinhan #include <asm/arch/hardware.h> 1300565589SLin Jinhan #include <asm/arch/clock.h> 1400565589SLin Jinhan #include <rockchip/crypto_ecc.h> 1500565589SLin Jinhan #include <rockchip/crypto_v2_pka.h> 1600565589SLin Jinhan #include <rockchip/rkce_core.h> 1700565589SLin Jinhan 1800565589SLin Jinhan fdt_addr_t crypto_base; 1900565589SLin Jinhan 2000565589SLin Jinhan #define ROUNDUP(size, alignment) round_up(size, alignment) 2100565589SLin Jinhan 2200565589SLin Jinhan #define RKCE_HASH_TIMEOUT_MS 1000 2300565589SLin Jinhan #define RKCE_SYMM_TIMEOUT_MS 1000 2400565589SLin Jinhan 2500565589SLin Jinhan struct rkce_sha_contex { 2600565589SLin Jinhan u32 length; 2700565589SLin Jinhan struct rkce_hash_td_ctrl ctrl; 2800565589SLin Jinhan struct rkce_hash_td *td; 2900565589SLin Jinhan struct rkce_hash_td_buf *td_buf; 3000565589SLin Jinhan }; 3100565589SLin Jinhan 3200565589SLin Jinhan struct rkce_cipher_contex { 3300565589SLin Jinhan struct rkce_symm_td *td; 3400565589SLin Jinhan struct rkce_symm_td *td_aad; 3500565589SLin Jinhan struct rkce_symm_td_buf *td_buf; 3600565589SLin Jinhan }; 3700565589SLin Jinhan 3800565589SLin Jinhan struct rockchip_crypto_priv { 3900565589SLin Jinhan fdt_addr_t reg; 4000565589SLin Jinhan u32 frequency; 4100565589SLin Jinhan char *clocks; 4200565589SLin Jinhan u32 *frequencies; 4300565589SLin Jinhan u32 nclocks; 4400565589SLin Jinhan u32 freq_nclocks; 4500565589SLin Jinhan u32 capability; 4600565589SLin Jinhan 4700565589SLin Jinhan void *hardware; 4800565589SLin Jinhan struct rkce_sha_contex *hash_ctx; 4936e17db4Stroy.lin u16 secure; 5036e17db4Stroy.lin u16 enabled; 5100565589SLin Jinhan }; 5200565589SLin Jinhan 5300565589SLin Jinhan struct rockchip_map { 5400565589SLin Jinhan u32 crypto; 5500565589SLin Jinhan u32 rkce; 5600565589SLin Jinhan }; 5700565589SLin Jinhan 5800565589SLin Jinhan static const struct rockchip_map rk_hash_map[] = { 5900565589SLin Jinhan {CRYPTO_SM3, RKCE_HASH_ALGO_SM3}, 6000565589SLin Jinhan {CRYPTO_MD5, RKCE_HASH_ALGO_MD5}, 6100565589SLin Jinhan {CRYPTO_SHA1, RKCE_HASH_ALGO_SHA1}, 6200565589SLin Jinhan {CRYPTO_SHA256, RKCE_HASH_ALGO_SHA256}, 6300565589SLin Jinhan {CRYPTO_SHA512, RKCE_HASH_ALGO_SHA512}, 6400565589SLin Jinhan }; 6500565589SLin Jinhan 6600565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC) 6700565589SLin Jinhan static const struct rockchip_map rk_hmac_map[] = { 6800565589SLin Jinhan {CRYPTO_HMAC_MD5, RKCE_HASH_ALGO_MD5}, 6900565589SLin Jinhan {CRYPTO_HMAC_SHA1, RKCE_HASH_ALGO_SHA1}, 7000565589SLin Jinhan {CRYPTO_HMAC_SHA256, RKCE_HASH_ALGO_SHA256}, 7100565589SLin Jinhan {CRYPTO_HMAC_SHA512, RKCE_HASH_ALGO_SHA512}, 7200565589SLin Jinhan {CRYPTO_HMAC_SM3, RKCE_HASH_ALGO_SM3}, 7300565589SLin Jinhan }; 7400565589SLin Jinhan #endif 7500565589SLin Jinhan 7600565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER) 7700565589SLin Jinhan static const struct rockchip_map rk_cipher_map[] = { 7800565589SLin Jinhan {CRYPTO_AES, RKCE_SYMM_ALGO_AES}, 7900565589SLin Jinhan {CRYPTO_DES, RKCE_SYMM_ALGO_TDES}, 8000565589SLin Jinhan {CRYPTO_SM4, RKCE_SYMM_ALGO_SM4}, 8100565589SLin Jinhan }; 8200565589SLin Jinhan #endif 8300565589SLin Jinhan 8400565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA) 8500565589SLin Jinhan static const struct rockchip_map rk_rsa_map[] = { 8600565589SLin Jinhan {CRYPTO_RSA512, RKCE_ASYM_ALGO_RSA}, 8700565589SLin Jinhan {CRYPTO_RSA1024, RKCE_ASYM_ALGO_RSA}, 8800565589SLin Jinhan {CRYPTO_RSA2048, RKCE_ASYM_ALGO_RSA}, 8900565589SLin Jinhan {CRYPTO_RSA3072, RKCE_ASYM_ALGO_RSA}, 9000565589SLin Jinhan {CRYPTO_RSA4096, RKCE_ASYM_ALGO_RSA}, 9100565589SLin Jinhan }; 9200565589SLin Jinhan #endif 9300565589SLin Jinhan 9400565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC) 9500565589SLin Jinhan static const struct rockchip_map rk_ec_map[] = { 9600565589SLin Jinhan {CRYPTO_SM2, RKCE_ASYM_ALGO_SM2}, 9700565589SLin Jinhan {CRYPTO_ECC_192R1, RKCE_ASYM_ALGO_ECC_P192}, 9800565589SLin Jinhan {CRYPTO_ECC_224R1, RKCE_ASYM_ALGO_ECC_P224}, 9900565589SLin Jinhan {CRYPTO_ECC_256R1, RKCE_ASYM_ALGO_ECC_P256}, 10000565589SLin Jinhan }; 10100565589SLin Jinhan #endif 10200565589SLin Jinhan 10300565589SLin Jinhan static int rk_crypto_enable_clk(struct udevice *dev); 10400565589SLin Jinhan static int rk_crypto_disable_clk(struct udevice *dev); 10500565589SLin Jinhan 1068f7f431fSTroy Lin static void rk_crypto_soft_reset(struct udevice *dev, uint32_t reset_sel) 1078f7f431fSTroy Lin { 1088f7f431fSTroy Lin struct rockchip_crypto_priv *priv = dev_get_priv(dev); 1098f7f431fSTroy Lin 1108f7f431fSTroy Lin if (!priv->hardware) 1118f7f431fSTroy Lin return; 1128f7f431fSTroy Lin 1138f7f431fSTroy Lin rk_crypto_enable_clk(dev); 1148f7f431fSTroy Lin 1158f7f431fSTroy Lin rkce_soft_reset(priv->hardware, reset_sel); 1168f7f431fSTroy Lin 1178f7f431fSTroy Lin rk_crypto_disable_clk(dev); 1188f7f431fSTroy Lin } 1198f7f431fSTroy Lin 12000565589SLin Jinhan static void crypto_flush_cacheline(ulong addr, ulong size) 12100565589SLin Jinhan { 12200565589SLin Jinhan ulong alignment = CONFIG_SYS_CACHELINE_SIZE; 12300565589SLin Jinhan ulong aligned_input, aligned_len; 12400565589SLin Jinhan 12500565589SLin Jinhan if (!addr || !size) 12600565589SLin Jinhan return; 12700565589SLin Jinhan 12800565589SLin Jinhan /* Must flush dcache before crypto DMA fetch data region */ 12900565589SLin Jinhan aligned_input = round_down(addr, alignment); 13000565589SLin Jinhan aligned_len = round_up(size + (addr - aligned_input), alignment); 13100565589SLin Jinhan flush_cache(aligned_input, aligned_len); 13200565589SLin Jinhan } 13300565589SLin Jinhan 13400565589SLin Jinhan static u32 rk_get_cemode(const struct rockchip_map *map, u32 num, u32 algo) 13500565589SLin Jinhan { 13600565589SLin Jinhan u32 i, j; 13700565589SLin Jinhan struct { 13800565589SLin Jinhan const struct rockchip_map *map; 13900565589SLin Jinhan u32 num; 14000565589SLin Jinhan } map_tbl[] = { 14100565589SLin Jinhan {rk_hash_map, ARRAY_SIZE(rk_hash_map)}, 14200565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC) 14300565589SLin Jinhan {rk_hmac_map, ARRAY_SIZE(rk_hmac_map)}, 14400565589SLin Jinhan #endif 14500565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER) 14600565589SLin Jinhan {rk_cipher_map, ARRAY_SIZE(rk_cipher_map)}, 14700565589SLin Jinhan #endif 14800565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA) 14900565589SLin Jinhan {rk_rsa_map, ARRAY_SIZE(rk_rsa_map)}, 15000565589SLin Jinhan #endif 15100565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC) 15200565589SLin Jinhan {rk_ec_map, ARRAY_SIZE(rk_ec_map)}, 15300565589SLin Jinhan #endif 15400565589SLin Jinhan }; 15500565589SLin Jinhan 15600565589SLin Jinhan for (i = 0; i < ARRAY_SIZE(map_tbl); i++) { 15700565589SLin Jinhan const struct rockchip_map *map = map_tbl[i].map; 15800565589SLin Jinhan u32 num = map_tbl[i].num; 15900565589SLin Jinhan 16000565589SLin Jinhan for (j = 0; j < num; j++) { 16100565589SLin Jinhan if (map[j].crypto == algo) 16200565589SLin Jinhan return map[j].rkce; 16300565589SLin Jinhan } 16400565589SLin Jinhan } 16500565589SLin Jinhan 16600565589SLin Jinhan return 0; 16700565589SLin Jinhan } 16800565589SLin Jinhan 16900565589SLin Jinhan static u32 rk_load_map(struct rockchip_crypto_priv *priv, u32 algo_type, 17000565589SLin Jinhan const struct rockchip_map *map, u32 num) 17100565589SLin Jinhan { 17200565589SLin Jinhan u32 i; 17300565589SLin Jinhan u32 capability = 0; 17400565589SLin Jinhan 17500565589SLin Jinhan for (i = 0; i < num; i++) { 17600565589SLin Jinhan if (rkce_hw_algo_valid(priv->hardware, algo_type, map[i].rkce, 0)) 17700565589SLin Jinhan capability |= map[i].crypto; 17800565589SLin Jinhan } 17900565589SLin Jinhan 18000565589SLin Jinhan return capability; 18100565589SLin Jinhan } 18200565589SLin Jinhan 18300565589SLin Jinhan static u32 rockchip_crypto_capability(struct udevice *dev) 18400565589SLin Jinhan { 18500565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev); 18600565589SLin Jinhan u32 cap = 0; 18700565589SLin Jinhan 18836e17db4Stroy.lin if (!priv->enabled) 18936e17db4Stroy.lin return 0; 19036e17db4Stroy.lin 19100565589SLin Jinhan if (priv->capability) 19200565589SLin Jinhan return priv->capability; 19300565589SLin Jinhan 19400565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_HASH, 19500565589SLin Jinhan rk_hash_map, ARRAY_SIZE(rk_hash_map)); 19600565589SLin Jinhan 19700565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC) 19800565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_HMAC, 19900565589SLin Jinhan rk_hmac_map, ARRAY_SIZE(rk_hmac_map)); 20000565589SLin Jinhan #endif 20100565589SLin Jinhan 20200565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER) 20300565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_CIPHER, 20400565589SLin Jinhan rk_cipher_map, ARRAY_SIZE(rk_cipher_map)); 20500565589SLin Jinhan #endif 20600565589SLin Jinhan 20700565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA) 20800565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_ASYM, rk_rsa_map, 20900565589SLin Jinhan ARRAY_SIZE(rk_rsa_map)); 21000565589SLin Jinhan #endif 21100565589SLin Jinhan 21200565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC) 21300565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_ASYM, rk_ec_map, 21400565589SLin Jinhan ARRAY_SIZE(rk_ec_map)); 21500565589SLin Jinhan #endif 21600565589SLin Jinhan 21700565589SLin Jinhan return cap; 21800565589SLin Jinhan } 21900565589SLin Jinhan 22000565589SLin Jinhan static void *rkce_sha_ctx_alloc(void) 22100565589SLin Jinhan { 22200565589SLin Jinhan struct rkce_sha_contex *hw_ctx; 22300565589SLin Jinhan 22400565589SLin Jinhan hw_ctx = malloc(sizeof(*hw_ctx)); 22500565589SLin Jinhan if (!hw_ctx) 22600565589SLin Jinhan return NULL; 22700565589SLin Jinhan 22800565589SLin Jinhan memset(hw_ctx, 0x00, sizeof(*hw_ctx)); 22900565589SLin Jinhan 23000565589SLin Jinhan hw_ctx->td = rkce_cma_alloc(sizeof(struct rkce_hash_td)); 23100565589SLin Jinhan if (!hw_ctx->td) 23200565589SLin Jinhan goto error; 23300565589SLin Jinhan 23400565589SLin Jinhan memset(hw_ctx->td, 0x00, sizeof(struct rkce_hash_td)); 23500565589SLin Jinhan 23600565589SLin Jinhan hw_ctx->td_buf = rkce_cma_alloc(sizeof(struct rkce_hash_td_buf)); 23700565589SLin Jinhan if (!hw_ctx->td_buf) 23800565589SLin Jinhan goto error; 23900565589SLin Jinhan 24000565589SLin Jinhan memset(hw_ctx->td_buf, 0x00, sizeof(struct rkce_hash_td_buf)); 24100565589SLin Jinhan 24200565589SLin Jinhan return hw_ctx; 24300565589SLin Jinhan error: 24400565589SLin Jinhan rkce_cma_free(hw_ctx->td); 24500565589SLin Jinhan rkce_cma_free(hw_ctx->td_buf); 24600565589SLin Jinhan free(hw_ctx); 24700565589SLin Jinhan 24800565589SLin Jinhan return NULL; 24900565589SLin Jinhan } 25000565589SLin Jinhan 25100565589SLin Jinhan static void rkce_sha_ctx_free(struct rkce_sha_contex *hw_ctx) 25200565589SLin Jinhan { 25300565589SLin Jinhan if (!hw_ctx) 25400565589SLin Jinhan return; 25500565589SLin Jinhan 25600565589SLin Jinhan rkce_cma_free(hw_ctx->td); 25700565589SLin Jinhan rkce_cma_free(hw_ctx->td_buf); 25800565589SLin Jinhan free(hw_ctx); 25900565589SLin Jinhan } 26000565589SLin Jinhan 26100565589SLin Jinhan static int rk_sha_init(struct udevice *dev, sha_context *ctx, 26200565589SLin Jinhan u8 *key, u32 key_len, bool is_hmac) 26300565589SLin Jinhan { 26400565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev); 26500565589SLin Jinhan struct rkce_sha_contex *hash_ctx = NULL; 26600565589SLin Jinhan u32 ce_algo = 0; 26700565589SLin Jinhan int ret = 0; 26800565589SLin Jinhan 26900565589SLin Jinhan if ((ctx->algo & priv->capability) == 0) 27000565589SLin Jinhan return -ENOSYS; 27100565589SLin Jinhan 27200565589SLin Jinhan if (priv->hash_ctx) 27300565589SLin Jinhan return -EFAULT; 27400565589SLin Jinhan 2758f7f431fSTroy Lin rk_crypto_soft_reset(dev, RKCE_RESET_HASH); 27600565589SLin Jinhan 27700565589SLin Jinhan hash_ctx = rkce_sha_ctx_alloc(); 27800565589SLin Jinhan if (!hash_ctx) 27900565589SLin Jinhan return -ENOMEM; 28000565589SLin Jinhan 28100565589SLin Jinhan ret = rkce_init_hash_td(hash_ctx->td, hash_ctx->td_buf); 28200565589SLin Jinhan if (ret) 28300565589SLin Jinhan goto exit; 28400565589SLin Jinhan 28500565589SLin Jinhan ce_algo = rk_get_cemode(rk_hash_map, ARRAY_SIZE(rk_hash_map), ctx->algo); 28600565589SLin Jinhan 28700565589SLin Jinhan hash_ctx->ctrl.td_type = RKCE_TD_TYPE_HASH; 28800565589SLin Jinhan hash_ctx->ctrl.hw_pad_en = 1; 28900565589SLin Jinhan hash_ctx->ctrl.first_pkg = 1; 29000565589SLin Jinhan hash_ctx->ctrl.last_pkg = 0; 29100565589SLin Jinhan hash_ctx->ctrl.hash_algo = ce_algo; 29200565589SLin Jinhan hash_ctx->ctrl.hmac_en = is_hmac; 29300565589SLin Jinhan hash_ctx->ctrl.is_preemptible = 0; 29400565589SLin Jinhan hash_ctx->ctrl.int_en = 1; 29500565589SLin Jinhan 29600565589SLin Jinhan if (is_hmac) { 29700565589SLin Jinhan if (key_len > 64) { 29800565589SLin Jinhan ret = -EINVAL; 29900565589SLin Jinhan goto exit; 30000565589SLin Jinhan } 30100565589SLin Jinhan 30200565589SLin Jinhan memcpy(hash_ctx->td_buf->key, key, key_len); 30300565589SLin Jinhan } 30400565589SLin Jinhan 30500565589SLin Jinhan priv->hash_ctx = hash_ctx; 30600565589SLin Jinhan exit: 30700565589SLin Jinhan if (ret) { 30800565589SLin Jinhan rkce_sha_ctx_free(hash_ctx); 30900565589SLin Jinhan priv->hash_ctx = NULL; 31000565589SLin Jinhan } 31100565589SLin Jinhan 31200565589SLin Jinhan return ret; 31300565589SLin Jinhan } 31400565589SLin Jinhan 31500565589SLin Jinhan static int rk_sha_update(struct udevice *dev, u32 *input, u32 len, bool is_last) 31600565589SLin Jinhan { 31700565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev); 31800565589SLin Jinhan struct rkce_sha_contex *hash_ctx; 31900565589SLin Jinhan struct rkce_hash_td *td; 32000565589SLin Jinhan int ret = 0; 32100565589SLin Jinhan 32200565589SLin Jinhan if (!priv->hash_ctx) 32300565589SLin Jinhan return -EINVAL; 32400565589SLin Jinhan 32500565589SLin Jinhan if (!is_last && (!input || len == 0)) 32600565589SLin Jinhan return -EINVAL; 32700565589SLin Jinhan 32800565589SLin Jinhan hash_ctx = priv->hash_ctx; 32900565589SLin Jinhan td = hash_ctx->td; 33000565589SLin Jinhan 33100565589SLin Jinhan td->ctrl = hash_ctx->ctrl; 33200565589SLin Jinhan memset(&td->sg, 0x00, sizeof(*td->sg)); 33300565589SLin Jinhan 33400565589SLin Jinhan if (hash_ctx->ctrl.first_pkg == 1) 33500565589SLin Jinhan hash_ctx->ctrl.first_pkg = 0; 33600565589SLin Jinhan 33700565589SLin Jinhan if (is_last) { 33800565589SLin Jinhan td->ctrl.last_pkg = 1; 33900565589SLin Jinhan } else { 34000565589SLin Jinhan #ifdef CONFIG_ARM64 34100565589SLin Jinhan td->sg[0].src_addr_h = rkce_cma_virt2phys(input) >> 32; 34200565589SLin Jinhan #endif 34300565589SLin Jinhan td->sg[0].src_addr_l = rkce_cma_virt2phys(input) & 0xffffffff; 34400565589SLin Jinhan td->sg[0].src_size = len; 34500565589SLin Jinhan hash_ctx->length += len; 34600565589SLin Jinhan crypto_flush_cacheline((ulong)input, len); 34700565589SLin Jinhan } 34800565589SLin Jinhan 34900565589SLin Jinhan rk_crypto_enable_clk(dev); 35000565589SLin Jinhan 35100565589SLin Jinhan crypto_flush_cacheline((ulong)hash_ctx->td, sizeof(*hash_ctx->td)); 35200565589SLin Jinhan crypto_flush_cacheline((ulong)hash_ctx->td_buf, sizeof(*hash_ctx->td_buf)); 35300565589SLin Jinhan 35400565589SLin Jinhan ret = rkce_push_td_sync(priv->hardware, td, RKCE_HASH_TIMEOUT_MS); 35500565589SLin Jinhan if (ret) { 35600565589SLin Jinhan rkce_sha_ctx_free(hash_ctx); 35700565589SLin Jinhan priv->hash_ctx = NULL; 35800565589SLin Jinhan } 35900565589SLin Jinhan 36000565589SLin Jinhan rk_crypto_disable_clk(dev); 36100565589SLin Jinhan 36200565589SLin Jinhan return ret; 36300565589SLin Jinhan } 36400565589SLin Jinhan 36500565589SLin Jinhan static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx) 36600565589SLin Jinhan { 36700565589SLin Jinhan return rk_sha_init(dev, ctx, NULL, 0, false); 36800565589SLin Jinhan } 36900565589SLin Jinhan 37000565589SLin Jinhan static int rockchip_crypto_sha_update(struct udevice *dev, u32 *input, u32 len) 37100565589SLin Jinhan { 37200565589SLin Jinhan return rk_sha_update(dev, input, len, false); 37300565589SLin Jinhan } 37400565589SLin Jinhan 37500565589SLin Jinhan static int rockchip_crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output) 37600565589SLin Jinhan { 37700565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev); 37800565589SLin Jinhan struct rkce_sha_contex *hash_ctx = priv->hash_ctx; 37900565589SLin Jinhan u32 nbits; 38000565589SLin Jinhan int ret; 38100565589SLin Jinhan 38200565589SLin Jinhan if (!priv->hash_ctx) 38300565589SLin Jinhan return -EINVAL; 38400565589SLin Jinhan 38500565589SLin Jinhan nbits = crypto_algo_nbits(ctx->algo); 38600565589SLin Jinhan 38700565589SLin Jinhan if (hash_ctx->length != ctx->length) { 38800565589SLin Jinhan printf("total length(0x%08x) != init length(0x%08x)!\n", 38900565589SLin Jinhan hash_ctx->length, ctx->length); 39000565589SLin Jinhan ret = -EIO; 39100565589SLin Jinhan goto exit; 39200565589SLin Jinhan } 39300565589SLin Jinhan 39400565589SLin Jinhan ret = rk_sha_update(dev, NULL, 0, true); 39500565589SLin Jinhan if (ret == 0) 39600565589SLin Jinhan memcpy(output, hash_ctx->td_buf->hash, BITS2BYTE(nbits)); 39700565589SLin Jinhan 39800565589SLin Jinhan exit: 39900565589SLin Jinhan rkce_sha_ctx_free(hash_ctx); 40000565589SLin Jinhan priv->hash_ctx = NULL; 40100565589SLin Jinhan 40200565589SLin Jinhan return ret; 40300565589SLin Jinhan } 40400565589SLin Jinhan 40500565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC) 40600565589SLin Jinhan static int rockchip_crypto_hmac_init(struct udevice *dev, sha_context *ctx, u8 *key, u32 key_len) 40700565589SLin Jinhan { 40800565589SLin Jinhan return rk_sha_init(dev, ctx, key, key_len, true); 40900565589SLin Jinhan } 41000565589SLin Jinhan 41100565589SLin Jinhan static int rockchip_crypto_hmac_update(struct udevice *dev, u32 *input, u32 len) 41200565589SLin Jinhan { 41300565589SLin Jinhan return rockchip_crypto_sha_update(dev, input, len); 41400565589SLin Jinhan } 41500565589SLin Jinhan 41600565589SLin Jinhan static int rockchip_crypto_hmac_final(struct udevice *dev, sha_context *ctx, u8 *output) 41700565589SLin Jinhan { 41800565589SLin Jinhan return rockchip_crypto_sha_final(dev, ctx, output); 41900565589SLin Jinhan } 42000565589SLin Jinhan #endif 42100565589SLin Jinhan 42200565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER) 42300565589SLin Jinhan 42400565589SLin Jinhan static int hw_crypto_ccm128_setiv(u8 *iv_buf, u8 *nonce, u32 nlen, u32 mlen) 42500565589SLin Jinhan { 42600565589SLin Jinhan u32 L = iv_buf[0] & 7; /* the L parameter */ 42700565589SLin Jinhan 42800565589SLin Jinhan if (nlen < (14 - L)) 42900565589SLin Jinhan return -1; /* nonce is too short */ 43000565589SLin Jinhan 43100565589SLin Jinhan if (sizeof(mlen) == 8 && L >= 3) { 43200565589SLin Jinhan iv_buf[8] = mlen >> (56 % (sizeof(mlen) * 8)); 43300565589SLin Jinhan iv_buf[9] = mlen >> (48 % (sizeof(mlen) * 8)); 43400565589SLin Jinhan iv_buf[10] = mlen >> (40 % (sizeof(mlen) * 8)); 43500565589SLin Jinhan iv_buf[11] = mlen >> (32 % (sizeof(mlen) * 8)); 43600565589SLin Jinhan } 43700565589SLin Jinhan 43800565589SLin Jinhan iv_buf[12] = mlen >> 24; 43900565589SLin Jinhan iv_buf[13] = mlen >> 16; 44000565589SLin Jinhan iv_buf[14] = mlen >> 8; 44100565589SLin Jinhan iv_buf[15] = mlen; 44200565589SLin Jinhan 44300565589SLin Jinhan iv_buf[0] &= ~0x40; /* clear aad flag */ 44400565589SLin Jinhan memcpy(&iv_buf[1], nonce, 14 - L); 44500565589SLin Jinhan 44600565589SLin Jinhan return 0; 44700565589SLin Jinhan } 44800565589SLin Jinhan 44900565589SLin Jinhan static void hw_get_ccm_aad_padding(u32 aad_len, u8 *padding, u32 *padding_size) 45000565589SLin Jinhan { 45100565589SLin Jinhan u32 i = 0; 45200565589SLin Jinhan 45300565589SLin Jinhan if (aad_len == 0) { 45400565589SLin Jinhan *padding_size = 0; 45500565589SLin Jinhan return; 45600565589SLin Jinhan } 45700565589SLin Jinhan 45800565589SLin Jinhan if (aad_len < (0x10000 - 0x100)) { 45900565589SLin Jinhan i = 2; 46000565589SLin Jinhan } else if (sizeof(aad_len) == 8 && 46100565589SLin Jinhan aad_len >= (size_t)1 << (32 % (sizeof(aad_len) * 8))) { 46200565589SLin Jinhan i = 10; 46300565589SLin Jinhan } else { 46400565589SLin Jinhan i = 6; 46500565589SLin Jinhan } 46600565589SLin Jinhan 46700565589SLin Jinhan if (i == 2) { 46800565589SLin Jinhan padding[0] = aad_len >> 8; 46900565589SLin Jinhan padding[1] = aad_len; 47000565589SLin Jinhan } else if (i == 10) { 47100565589SLin Jinhan padding[0] = 0xFF; 47200565589SLin Jinhan padding[1] = 0xFF; 47300565589SLin Jinhan padding[2] = aad_len >> (56 % (sizeof(aad_len) * 8)); 47400565589SLin Jinhan padding[3] = aad_len >> (48 % (sizeof(aad_len) * 8)); 47500565589SLin Jinhan padding[4] = aad_len >> (40 % (sizeof(aad_len) * 8)); 47600565589SLin Jinhan padding[5] = aad_len >> (32 % (sizeof(aad_len) * 8)); 47700565589SLin Jinhan padding[6] = aad_len >> 24; 47800565589SLin Jinhan padding[7] = aad_len >> 16; 47900565589SLin Jinhan padding[8] = aad_len >> 8; 48000565589SLin Jinhan padding[9] = aad_len; 48100565589SLin Jinhan } else { 48200565589SLin Jinhan padding[0] = 0xFF; 48300565589SLin Jinhan padding[1] = 0xFE; 48400565589SLin Jinhan padding[2] = aad_len >> 24; 48500565589SLin Jinhan padding[3] = aad_len >> 16; 48600565589SLin Jinhan padding[4] = aad_len >> 8; 48700565589SLin Jinhan } 48800565589SLin Jinhan 48900565589SLin Jinhan *padding_size = i; 49000565589SLin Jinhan } 49100565589SLin Jinhan 49200565589SLin Jinhan static int hw_compose_ccm_aad_iv(u8 *aad_iv, u32 data_len, 49300565589SLin Jinhan u32 aad_len, u32 tag_size) 49400565589SLin Jinhan { 49500565589SLin Jinhan u32 L; /* the L parameter */ 49600565589SLin Jinhan u8 nonce[AES_BLOCK_SIZE]; 49700565589SLin Jinhan 49800565589SLin Jinhan L = aad_iv[0] & 7; 49900565589SLin Jinhan aad_iv[0] |= ((u8)(((tag_size - 2) / 2) & 7) << 3); 50000565589SLin Jinhan 50100565589SLin Jinhan if (sizeof(data_len) == 8 && L >= 3) { 50200565589SLin Jinhan aad_iv[8] = data_len >> (56 % (sizeof(data_len) * 8)); 50300565589SLin Jinhan aad_iv[9] = data_len >> (48 % (sizeof(data_len) * 8)); 50400565589SLin Jinhan aad_iv[10] = data_len >> (40 % (sizeof(data_len) * 8)); 50500565589SLin Jinhan aad_iv[11] = data_len >> (32 % (sizeof(data_len) * 8)); 50600565589SLin Jinhan } 50700565589SLin Jinhan 50800565589SLin Jinhan /* save nonce */ 50900565589SLin Jinhan memcpy(nonce, &aad_iv[1], 14 - L); 51000565589SLin Jinhan 51100565589SLin Jinhan aad_iv[12] = data_len >> 24; 51200565589SLin Jinhan aad_iv[13] = data_len >> 16; 51300565589SLin Jinhan aad_iv[14] = data_len >> 8; 51400565589SLin Jinhan aad_iv[15] = data_len; 51500565589SLin Jinhan 51600565589SLin Jinhan /* restore nonce */ 51700565589SLin Jinhan memcpy(&aad_iv[1], nonce, 14 - L); 51800565589SLin Jinhan 51900565589SLin Jinhan aad_iv[0] &= ~0x40; /* clear Adata flag */ 52000565589SLin Jinhan 52100565589SLin Jinhan if (aad_len) 52200565589SLin Jinhan aad_iv[0] |= 0x40; //set aad flag 52300565589SLin Jinhan 52400565589SLin Jinhan return 0; 52500565589SLin Jinhan } 52600565589SLin Jinhan 52700565589SLin Jinhan static void rkce_destroy_ccm_aad(u8 *new_aad) 52800565589SLin Jinhan { 52900565589SLin Jinhan rkce_cma_free(new_aad); 53000565589SLin Jinhan } 53100565589SLin Jinhan 53200565589SLin Jinhan static int rkce_build_ccm_aad(const u8 *aad, u32 aad_len, u32 data_len, 53300565589SLin Jinhan u8 *iv, u32 iv_len, 53400565589SLin Jinhan u8 **new_aad, u32 *new_aad_len, 53500565589SLin Jinhan u8 *new_iv, u32 *new_iv_len) 53600565589SLin Jinhan { 53700565589SLin Jinhan int ret = -RKCE_INVAL; 53800565589SLin Jinhan u32 L; 53900565589SLin Jinhan u8 nonce[AES_BLOCK_SIZE]; 54000565589SLin Jinhan u8 pad[AES_BLOCK_SIZE]; 54100565589SLin Jinhan u32 pad_size = 0; 54200565589SLin Jinhan u32 tag_len = AES_BLOCK_SIZE; 54300565589SLin Jinhan u8 *aad_tmp = NULL; 54400565589SLin Jinhan u32 aad_tmp_len = 0; 54500565589SLin Jinhan 54600565589SLin Jinhan memset(nonce, 0x00, sizeof(nonce)); 54700565589SLin Jinhan 54800565589SLin Jinhan L = 15 - iv_len; 54900565589SLin Jinhan nonce[0] = (L - 1) & 7; 55000565589SLin Jinhan ret = hw_crypto_ccm128_setiv(nonce, (u8 *)iv, iv_len, 0); 55100565589SLin Jinhan if (ret) 55200565589SLin Jinhan return ret; 55300565589SLin Jinhan 55400565589SLin Jinhan memcpy(new_iv, nonce, sizeof(nonce)); 55500565589SLin Jinhan *new_iv_len = sizeof(nonce); 55600565589SLin Jinhan 55700565589SLin Jinhan memset(pad, 0x00, sizeof(pad)); 55800565589SLin Jinhan hw_get_ccm_aad_padding(aad_len, pad, &pad_size); 55900565589SLin Jinhan 56000565589SLin Jinhan aad_tmp_len = aad_len + AES_BLOCK_SIZE + pad_size; 56100565589SLin Jinhan aad_tmp_len = ROUNDUP(aad_tmp_len, AES_BLOCK_SIZE); 56200565589SLin Jinhan 56300565589SLin Jinhan aad_tmp = rkce_cma_alloc(aad_tmp_len); 56400565589SLin Jinhan if (!aad_tmp) { 56500565589SLin Jinhan ret = -RKCE_NOMEM; 56600565589SLin Jinhan goto exit; 56700565589SLin Jinhan } 56800565589SLin Jinhan 56900565589SLin Jinhan /* clear last block */ 57000565589SLin Jinhan memset(aad_tmp + aad_tmp_len - AES_BLOCK_SIZE, 0x00, AES_BLOCK_SIZE); 57100565589SLin Jinhan memcpy(aad_tmp, nonce, sizeof(nonce)); 57200565589SLin Jinhan hw_compose_ccm_aad_iv(aad_tmp, data_len, aad_len, tag_len); 57300565589SLin Jinhan memcpy(aad_tmp + AES_BLOCK_SIZE, pad, pad_size); 57400565589SLin Jinhan 57500565589SLin Jinhan memcpy(aad_tmp + AES_BLOCK_SIZE + pad_size, aad, aad_len); 57600565589SLin Jinhan 57700565589SLin Jinhan *new_aad = aad_tmp; 57800565589SLin Jinhan *new_aad_len = aad_tmp_len; 57900565589SLin Jinhan 58000565589SLin Jinhan exit: 58100565589SLin Jinhan return ret; 58200565589SLin Jinhan } 58300565589SLin Jinhan 58400565589SLin Jinhan static void *rkce_cipher_ctx_alloc(void) 58500565589SLin Jinhan { 58600565589SLin Jinhan struct rkce_cipher_contex *hw_ctx; 58700565589SLin Jinhan 58800565589SLin Jinhan hw_ctx = malloc(sizeof(*hw_ctx)); 58900565589SLin Jinhan if (!hw_ctx) 59000565589SLin Jinhan return NULL; 59100565589SLin Jinhan 59200565589SLin Jinhan hw_ctx->td = rkce_cma_alloc(sizeof(struct rkce_symm_td)); 59300565589SLin Jinhan if (!hw_ctx->td) 59400565589SLin Jinhan goto error; 59500565589SLin Jinhan 59600565589SLin Jinhan memset(hw_ctx->td, 0x00, sizeof(struct rkce_symm_td)); 59700565589SLin Jinhan 59800565589SLin Jinhan hw_ctx->td_aad = rkce_cma_alloc(sizeof(struct rkce_symm_td)); 59900565589SLin Jinhan if (!hw_ctx->td_aad) 60000565589SLin Jinhan goto error; 60100565589SLin Jinhan 60200565589SLin Jinhan memset(hw_ctx->td_aad, 0x00, sizeof(struct rkce_symm_td)); 60300565589SLin Jinhan 60400565589SLin Jinhan hw_ctx->td_buf = rkce_cma_alloc(sizeof(struct rkce_symm_td_buf)); 60500565589SLin Jinhan if (!hw_ctx->td_buf) 60600565589SLin Jinhan goto error; 60700565589SLin Jinhan 60800565589SLin Jinhan memset(hw_ctx->td_buf, 0x00, sizeof(struct rkce_symm_td_buf)); 60900565589SLin Jinhan 61000565589SLin Jinhan return hw_ctx; 61100565589SLin Jinhan error: 61200565589SLin Jinhan rkce_cma_free(hw_ctx->td); 61300565589SLin Jinhan rkce_cma_free(hw_ctx->td_aad); 61400565589SLin Jinhan rkce_cma_free(hw_ctx->td_buf); 61500565589SLin Jinhan free(hw_ctx); 61600565589SLin Jinhan 61700565589SLin Jinhan return NULL; 61800565589SLin Jinhan } 61900565589SLin Jinhan 62000565589SLin Jinhan static void rkce_cipher_ctx_free(struct rkce_cipher_contex *hw_ctx) 62100565589SLin Jinhan { 62200565589SLin Jinhan if (!hw_ctx) 62300565589SLin Jinhan return; 62400565589SLin Jinhan 62500565589SLin Jinhan rkce_cma_free(hw_ctx->td); 62600565589SLin Jinhan rkce_cma_free(hw_ctx->td_aad); 62700565589SLin Jinhan rkce_cma_free(hw_ctx->td_buf); 62800565589SLin Jinhan free(hw_ctx); 62900565589SLin Jinhan } 63000565589SLin Jinhan 63100565589SLin Jinhan static void crypto_invalidate_cacheline(u32 addr, u32 size) 63200565589SLin Jinhan { 63300565589SLin Jinhan ulong alignment = CONFIG_SYS_CACHELINE_SIZE; 63400565589SLin Jinhan ulong aligned_input, aligned_len; 63500565589SLin Jinhan 63600565589SLin Jinhan if (!addr || !size) 63700565589SLin Jinhan return; 63800565589SLin Jinhan 63900565589SLin Jinhan /* Must invalidate dcache after crypto DMA write data region */ 64000565589SLin Jinhan aligned_input = round_down(addr, alignment); 64100565589SLin Jinhan aligned_len = round_up(size + (addr - aligned_input), alignment); 64200565589SLin Jinhan invalidate_dcache_range(aligned_input, aligned_input + aligned_len); 64300565589SLin Jinhan } 64400565589SLin Jinhan 64500565589SLin Jinhan static const struct rockchip_map rk_cipher_algo_map[] = { 64600565589SLin Jinhan {RK_MODE_ECB, RKCE_SYMM_MODE_ECB}, 64700565589SLin Jinhan {RK_MODE_CBC, RKCE_SYMM_MODE_CBC}, 64800565589SLin Jinhan {RK_MODE_CTS, RKCE_SYMM_MODE_CTS}, 64900565589SLin Jinhan {RK_MODE_CTR, RKCE_SYMM_MODE_CTR}, 65000565589SLin Jinhan {RK_MODE_CFB, RKCE_SYMM_MODE_CFB}, 65100565589SLin Jinhan {RK_MODE_OFB, RKCE_SYMM_MODE_OFB}, 65200565589SLin Jinhan {RK_MODE_XTS, RKCE_SYMM_MODE_XTS}, 65300565589SLin Jinhan {RK_MODE_CCM, RKCE_SYMM_MODE_CCM}, 65400565589SLin Jinhan {RK_MODE_GCM, RKCE_SYMM_MODE_GCM}, 65500565589SLin Jinhan {RK_MODE_CMAC, RKCE_SYMM_MODE_CMAC}, 65600565589SLin Jinhan {RK_MODE_CBC_MAC, RKCE_SYMM_MODE_CBC_MAC}, 65700565589SLin Jinhan }; 65800565589SLin Jinhan 65900565589SLin Jinhan static int rk_get_cipher_cemode(u32 algo, u32 mode, u32 *ce_algo, u32 *ce_mode) 66000565589SLin Jinhan { 66100565589SLin Jinhan u32 i; 66200565589SLin Jinhan 66300565589SLin Jinhan switch (algo) { 66400565589SLin Jinhan case CRYPTO_DES: 66500565589SLin Jinhan *ce_algo = RKCE_SYMM_ALGO_TDES; 66600565589SLin Jinhan break; 66700565589SLin Jinhan case CRYPTO_AES: 66800565589SLin Jinhan *ce_algo = RKCE_SYMM_ALGO_AES; 66900565589SLin Jinhan break; 67000565589SLin Jinhan case CRYPTO_SM4: 67100565589SLin Jinhan *ce_algo = RKCE_SYMM_ALGO_SM4; 67200565589SLin Jinhan break; 67300565589SLin Jinhan default: 67400565589SLin Jinhan return -EINVAL; 67500565589SLin Jinhan } 67600565589SLin Jinhan 67700565589SLin Jinhan for (i = 0; i < ARRAY_SIZE(rk_cipher_algo_map); i++) { 67800565589SLin Jinhan if (mode == rk_cipher_algo_map[i].crypto) { 67900565589SLin Jinhan *ce_mode = rk_cipher_algo_map[i].rkce; 68000565589SLin Jinhan return 0; 68100565589SLin Jinhan } 68200565589SLin Jinhan } 68300565589SLin Jinhan 68400565589SLin Jinhan return -EINVAL; 68500565589SLin Jinhan } 68600565589SLin Jinhan 68700565589SLin Jinhan u32 rk_get_td_keysize(u32 ce_algo, u32 ce_mode, u32 key_len) 68800565589SLin Jinhan { 68900565589SLin Jinhan u32 key_size = 0; 69000565589SLin Jinhan 69100565589SLin Jinhan if (ce_algo == RKCE_SYMM_ALGO_AES) { 69200565589SLin Jinhan if (key_len == AES_KEYSIZE_128) 69300565589SLin Jinhan key_size = RKCE_KEY_AES_128; 69400565589SLin Jinhan else if (key_len == AES_KEYSIZE_192) 69500565589SLin Jinhan key_size = RKCE_KEY_AES_192; 69600565589SLin Jinhan else if (key_len == AES_KEYSIZE_256) 69700565589SLin Jinhan key_size = RKCE_KEY_AES_256; 69800565589SLin Jinhan else 69900565589SLin Jinhan ; 70000565589SLin Jinhan } 70100565589SLin Jinhan 70200565589SLin Jinhan return key_size; 70300565589SLin Jinhan } 70400565589SLin Jinhan 70500565589SLin Jinhan int rk_set_symm_td_buf_key(struct rkce_symm_td_buf *td_buf, 70600565589SLin Jinhan u32 ce_algo, u32 ce_mode, cipher_context *ctx) 70700565589SLin Jinhan { 70800565589SLin Jinhan memset(td_buf->key1, 0x00, sizeof(td_buf->key1)); 70900565589SLin Jinhan memset(td_buf->key2, 0x00, sizeof(td_buf->key2)); 71000565589SLin Jinhan 71100565589SLin Jinhan if (ce_mode == RKCE_SYMM_MODE_XTS) { 71200565589SLin Jinhan memcpy(td_buf->key1, ctx->key, ctx->key_len); 71300565589SLin Jinhan memcpy(td_buf->key2, ctx->twk_key, ctx->key_len); 71400565589SLin Jinhan } else { 71500565589SLin Jinhan memcpy(td_buf->key1, ctx->key, ctx->key_len); 71600565589SLin Jinhan } 71700565589SLin Jinhan 71800565589SLin Jinhan if (ctx->key_len == DES_KEYSIZE * 2 && 71900565589SLin Jinhan (ce_algo == RKCE_SYMM_ALGO_DES || ce_algo == RKCE_SYMM_ALGO_TDES)) 72000565589SLin Jinhan memcpy(td_buf->key1 + DES_KEYSIZE * 2, td_buf->key1, DES_KEYSIZE); 72100565589SLin Jinhan 72200565589SLin Jinhan return 0; 72300565589SLin Jinhan } 72400565589SLin Jinhan 72500565589SLin Jinhan int rk_set_symm_td_sg(struct rkce_symm_td *td, 72600565589SLin Jinhan const u8 *in, u32 in_len, u8 *out, u32 out_len) 72700565589SLin Jinhan { 72800565589SLin Jinhan memset(td->sg, 0x00, sizeof(td->sg)); 72900565589SLin Jinhan 73000565589SLin Jinhan #ifdef CONFIG_ARM64 73100565589SLin Jinhan td->sg[0].src_addr_h = rkce_cma_virt2phys(in) >> 32; 73200565589SLin Jinhan #endif 73300565589SLin Jinhan td->sg[0].src_addr_l = rkce_cma_virt2phys(in) & 0xffffffff; 73400565589SLin Jinhan td->sg[0].src_size = in_len; 73500565589SLin Jinhan 73600565589SLin Jinhan if (out && out_len) { 73700565589SLin Jinhan #ifdef CONFIG_ARM64 73800565589SLin Jinhan td->sg[0].dst_addr_h = rkce_cma_virt2phys(out) >> 32; 73900565589SLin Jinhan #endif 74000565589SLin Jinhan td->sg[0].dst_addr_l = rkce_cma_virt2phys(out) & 0xffffffff; 74100565589SLin Jinhan td->sg[0].dst_size = out_len; 74200565589SLin Jinhan } 74300565589SLin Jinhan 74400565589SLin Jinhan td->next_task = 0; 74500565589SLin Jinhan 74600565589SLin Jinhan return 0; 74700565589SLin Jinhan } 74800565589SLin Jinhan 74900565589SLin Jinhan static int rk_crypto_cipher(struct udevice *dev, cipher_context *ctx, 75000565589SLin Jinhan const u8 *in, u8 *out, u32 len, bool enc, 75100565589SLin Jinhan const u8 *aad, u32 aad_len, u8 *tag) 75200565589SLin Jinhan { 75300565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev); 75400565589SLin Jinhan struct rkce_cipher_contex *hw_ctx = NULL; 75500565589SLin Jinhan u32 ce_algo = 0, ce_mode = 0; 7568f7f431fSTroy Lin bool use_otpkey = false; 75700565589SLin Jinhan int ret = 0; 75800565589SLin Jinhan 7598f7f431fSTroy Lin rk_crypto_soft_reset(dev, RKCE_RESET_SYMM); 7608f7f431fSTroy Lin 7618f7f431fSTroy Lin if (!ctx->key && ctx->key_len) 7628f7f431fSTroy Lin use_otpkey = true; 76300565589SLin Jinhan 76400565589SLin Jinhan ret = rk_get_cipher_cemode(ctx->algo, ctx->mode, &ce_algo, &ce_mode); 76500565589SLin Jinhan if (ret) 76600565589SLin Jinhan return ret; 76700565589SLin Jinhan 76800565589SLin Jinhan hw_ctx = rkce_cipher_ctx_alloc(); 76900565589SLin Jinhan if (!hw_ctx) 77000565589SLin Jinhan return -ENOMEM; 77100565589SLin Jinhan 77200565589SLin Jinhan rkce_init_symm_td(hw_ctx->td, hw_ctx->td_buf); 77300565589SLin Jinhan 77400565589SLin Jinhan hw_ctx->td->ctrl.td_type = RKCE_TD_TYPE_SYMM; 77500565589SLin Jinhan hw_ctx->td->ctrl.is_dec = !enc; 77600565589SLin Jinhan hw_ctx->td->ctrl.symm_algo = ce_algo; 77700565589SLin Jinhan hw_ctx->td->ctrl.symm_mode = ce_mode; 77800565589SLin Jinhan hw_ctx->td->ctrl.key_size = rk_get_td_keysize(ce_algo, ce_mode, ctx->key_len); 77900565589SLin Jinhan hw_ctx->td->ctrl.first_pkg = 1; 78000565589SLin Jinhan hw_ctx->td->ctrl.last_pkg = 1; 78100565589SLin Jinhan hw_ctx->td->ctrl.int_en = 1; 7828f7f431fSTroy Lin hw_ctx->td->ctrl.key_sel = use_otpkey ? RKCE_KEY_SEL_KT : RKCE_KEY_SEL_USER; 78300565589SLin Jinhan 78400565589SLin Jinhan memcpy(hw_ctx->td_buf->iv, ctx->iv, ctx->iv_len); 78500565589SLin Jinhan hw_ctx->td->ctrl.iv_len = ctx->iv_len; 78600565589SLin Jinhan 7878f7f431fSTroy Lin if (!use_otpkey) { 78800565589SLin Jinhan ret = rk_set_symm_td_buf_key(hw_ctx->td_buf, ce_algo, ce_mode, ctx); 78900565589SLin Jinhan if (ret) 79000565589SLin Jinhan goto exit; 7918f7f431fSTroy Lin } 79200565589SLin Jinhan 79300565589SLin Jinhan ret = rk_set_symm_td_sg(hw_ctx->td, in, len, out, len); 79400565589SLin Jinhan if (ret) 79500565589SLin Jinhan goto exit; 79600565589SLin Jinhan 79700565589SLin Jinhan if (ce_mode == RKCE_SYMM_MODE_CCM) { 79800565589SLin Jinhan u8 *new_aad = NULL; 79900565589SLin Jinhan u32 new_aad_len = 0, new_iv_len = 0; 80000565589SLin Jinhan 80100565589SLin Jinhan rkce_init_symm_td(hw_ctx->td_aad, hw_ctx->td_buf); 80200565589SLin Jinhan 80300565589SLin Jinhan ret = rkce_build_ccm_aad(aad, aad_len, len, 80400565589SLin Jinhan hw_ctx->td_buf->iv, ctx->iv_len, 80500565589SLin Jinhan &new_aad, &new_aad_len, 80600565589SLin Jinhan hw_ctx->td_buf->iv, &new_iv_len); 80700565589SLin Jinhan if (ret) 80800565589SLin Jinhan goto exit; 80900565589SLin Jinhan 81000565589SLin Jinhan ret = rk_set_symm_td_sg(hw_ctx->td_aad, new_aad, new_aad_len, NULL, 0); 81100565589SLin Jinhan if (ret) 81200565589SLin Jinhan goto exit; 81300565589SLin Jinhan 81400565589SLin Jinhan hw_ctx->td->ctrl.iv_len = new_iv_len; 81500565589SLin Jinhan 81600565589SLin Jinhan hw_ctx->td_buf->gcm_len.aad_len_l = new_aad_len; 81700565589SLin Jinhan 81800565589SLin Jinhan hw_ctx->td_aad->ctrl = hw_ctx->td->ctrl; 81900565589SLin Jinhan hw_ctx->td_aad->ctrl.is_aad = 1; 82000565589SLin Jinhan 82100565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_aad, sizeof(*hw_ctx->td_aad)); 82200565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_buf, sizeof(*hw_ctx->td_buf)); 82300565589SLin Jinhan crypto_flush_cacheline((ulong)new_aad, new_aad_len); 82400565589SLin Jinhan 82500565589SLin Jinhan rk_crypto_enable_clk(dev); 82600565589SLin Jinhan 82700565589SLin Jinhan ret = rkce_push_td_sync(priv->hardware, hw_ctx->td_aad, RKCE_SYMM_TIMEOUT_MS); 82800565589SLin Jinhan 82900565589SLin Jinhan rk_crypto_disable_clk(dev); 83000565589SLin Jinhan 83100565589SLin Jinhan rkce_destroy_ccm_aad(new_aad); 83200565589SLin Jinhan 83300565589SLin Jinhan if (ret) { 83400565589SLin Jinhan printf("CCM calc aad data failed.\n"); 83500565589SLin Jinhan goto exit; 83600565589SLin Jinhan } 83700565589SLin Jinhan } else if (ce_mode == RKCE_SYMM_MODE_GCM) { 83800565589SLin Jinhan rkce_init_symm_td(hw_ctx->td_aad, hw_ctx->td_buf); 83900565589SLin Jinhan 84000565589SLin Jinhan ret = rk_set_symm_td_sg(hw_ctx->td_aad, aad, aad_len, NULL, 0); 84100565589SLin Jinhan if (ret) 84200565589SLin Jinhan goto exit; 84300565589SLin Jinhan 84400565589SLin Jinhan hw_ctx->td_buf->gcm_len.aad_len_l = aad_len; 84500565589SLin Jinhan hw_ctx->td_buf->gcm_len.pc_len_l = len; 84600565589SLin Jinhan 84700565589SLin Jinhan hw_ctx->td_aad->ctrl = hw_ctx->td->ctrl; 84800565589SLin Jinhan hw_ctx->td_aad->ctrl.is_aad = 1; 84900565589SLin Jinhan 85000565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_aad, sizeof(*hw_ctx->td_aad)); 85100565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_buf, sizeof(*hw_ctx->td_buf)); 85200565589SLin Jinhan crypto_flush_cacheline((ulong)aad, aad_len); 85300565589SLin Jinhan 85400565589SLin Jinhan rk_crypto_enable_clk(dev); 85500565589SLin Jinhan 85600565589SLin Jinhan ret = rkce_push_td_sync(priv->hardware, hw_ctx->td_aad, RKCE_SYMM_TIMEOUT_MS); 85700565589SLin Jinhan 85800565589SLin Jinhan rk_crypto_disable_clk(dev); 85900565589SLin Jinhan if (ret) { 86000565589SLin Jinhan printf("GCM calc aad data failed.\n"); 86100565589SLin Jinhan goto exit; 86200565589SLin Jinhan } 86300565589SLin Jinhan } 86400565589SLin Jinhan 86500565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td, sizeof(*hw_ctx->td)); 86600565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_buf, sizeof(*hw_ctx->td_buf)); 86700565589SLin Jinhan crypto_flush_cacheline((ulong)in, len); 86800565589SLin Jinhan crypto_invalidate_cacheline((ulong)out, len); 86900565589SLin Jinhan 87000565589SLin Jinhan rk_crypto_enable_clk(dev); 87100565589SLin Jinhan 87200565589SLin Jinhan ret = rkce_push_td_sync(priv->hardware, hw_ctx->td, RKCE_SYMM_TIMEOUT_MS); 87300565589SLin Jinhan 87400565589SLin Jinhan crypto_invalidate_cacheline((ulong)out, len); 87500565589SLin Jinhan 87600565589SLin Jinhan rk_crypto_disable_clk(dev); 87700565589SLin Jinhan 87800565589SLin Jinhan if (tag) 87900565589SLin Jinhan memcpy(tag, hw_ctx->td_buf->tag, sizeof(hw_ctx->td_buf->tag)); 88000565589SLin Jinhan exit: 88100565589SLin Jinhan rkce_cipher_ctx_free(hw_ctx); 88200565589SLin Jinhan 88300565589SLin Jinhan return ret; 88400565589SLin Jinhan } 88500565589SLin Jinhan 88600565589SLin Jinhan static int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx, 88700565589SLin Jinhan const u8 *in, u8 *out, u32 len, bool enc) 88800565589SLin Jinhan { 88900565589SLin Jinhan return rk_crypto_cipher(dev, ctx, in, out, len, enc, NULL, 0, NULL); 89000565589SLin Jinhan } 89100565589SLin Jinhan 89200565589SLin Jinhan static int rockchip_crypto_mac(struct udevice *dev, cipher_context *ctx, 89300565589SLin Jinhan const u8 *in, u32 len, u8 *tag) 89400565589SLin Jinhan { 89500565589SLin Jinhan return rk_crypto_cipher(dev, ctx, in, NULL, len, true, NULL, 0, tag); 89600565589SLin Jinhan } 89700565589SLin Jinhan 89800565589SLin Jinhan static int rockchip_crypto_ae(struct udevice *dev, cipher_context *ctx, 89900565589SLin Jinhan const u8 *in, u32 len, const u8 *aad, u32 aad_len, 90000565589SLin Jinhan u8 *out, u8 *tag) 90100565589SLin Jinhan { 90200565589SLin Jinhan return rk_crypto_cipher(dev, ctx, in, out, len, true, aad, aad_len, tag); 90300565589SLin Jinhan } 90400565589SLin Jinhan 905*24a57c1cSLin Jinhan #if CONFIG_IS_ENABLED(DM_KEYLAD) 9068f7f431fSTroy Lin int rockchip_crypto_fw_cipher(struct udevice *dev, cipher_fw_context *ctx, 9078f7f431fSTroy Lin const u8 *in, u8 *out, u32 len, bool enc) 9088f7f431fSTroy Lin { 9098f7f431fSTroy Lin cipher_context cipher_ctx; 9108f7f431fSTroy Lin 9118f7f431fSTroy Lin memset(&cipher_ctx, 0x00, sizeof(cipher_ctx)); 9128f7f431fSTroy Lin 9138f7f431fSTroy Lin cipher_ctx.algo = ctx->algo; 9148f7f431fSTroy Lin cipher_ctx.mode = ctx->mode; 9158f7f431fSTroy Lin cipher_ctx.key_len = ctx->key_len; 9168f7f431fSTroy Lin cipher_ctx.iv = ctx->iv; 9178f7f431fSTroy Lin cipher_ctx.iv_len = ctx->iv_len; 9188f7f431fSTroy Lin 9198f7f431fSTroy Lin return rk_crypto_cipher(dev, &cipher_ctx, in, out, len, enc, NULL, 0, NULL); 9208f7f431fSTroy Lin } 9218f7f431fSTroy Lin 9228f7f431fSTroy Lin static ulong rockchip_get_keytable_addr(struct udevice *dev) 9238f7f431fSTroy Lin { 9248f7f431fSTroy Lin struct rockchip_crypto_priv *priv = dev_get_priv(dev); 9258f7f431fSTroy Lin ulong addr; 9268f7f431fSTroy Lin 9278f7f431fSTroy Lin rk_crypto_enable_clk(dev); 9288f7f431fSTroy Lin 9298f7f431fSTroy Lin addr = rkce_get_keytable_addr(priv->hardware); 9308f7f431fSTroy Lin 9318f7f431fSTroy Lin rk_crypto_disable_clk(dev); 9328f7f431fSTroy Lin 9338f7f431fSTroy Lin return addr; 9348f7f431fSTroy Lin } 935*24a57c1cSLin Jinhan #endif 9368f7f431fSTroy Lin 93700565589SLin Jinhan #endif 93800565589SLin Jinhan 93900565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA) 94000565589SLin Jinhan static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx, 94100565589SLin Jinhan u8 *sign, u8 *output) 94200565589SLin Jinhan { 94300565589SLin Jinhan struct mpa_num *mpa_m = NULL, *mpa_e = NULL, *mpa_n = NULL; 94400565589SLin Jinhan struct mpa_num *mpa_c = NULL, *mpa_result = NULL; 94500565589SLin Jinhan u32 n_bits, n_words; 94600565589SLin Jinhan int ret; 94700565589SLin Jinhan 94800565589SLin Jinhan if (!ctx) 94900565589SLin Jinhan return -EINVAL; 95000565589SLin Jinhan 95100565589SLin Jinhan if (ctx->algo != CRYPTO_RSA512 && 95200565589SLin Jinhan ctx->algo != CRYPTO_RSA1024 && 95300565589SLin Jinhan ctx->algo != CRYPTO_RSA2048 && 95400565589SLin Jinhan ctx->algo != CRYPTO_RSA3072 && 95500565589SLin Jinhan ctx->algo != CRYPTO_RSA4096) 95600565589SLin Jinhan return -EINVAL; 95700565589SLin Jinhan 95800565589SLin Jinhan n_bits = crypto_algo_nbits(ctx->algo); 95900565589SLin Jinhan n_words = BITS2WORD(n_bits); 96000565589SLin Jinhan 96100565589SLin Jinhan ret = rk_mpa_alloc(&mpa_m, sign, n_words); 96200565589SLin Jinhan if (ret) 96300565589SLin Jinhan goto exit; 96400565589SLin Jinhan 96500565589SLin Jinhan ret = rk_mpa_alloc(&mpa_e, ctx->e, n_words); 96600565589SLin Jinhan if (ret) 96700565589SLin Jinhan goto exit; 96800565589SLin Jinhan 96900565589SLin Jinhan ret = rk_mpa_alloc(&mpa_n, ctx->n, n_words); 97000565589SLin Jinhan if (ret) 97100565589SLin Jinhan goto exit; 97200565589SLin Jinhan 97300565589SLin Jinhan if (ctx->c) { 97400565589SLin Jinhan ret = rk_mpa_alloc(&mpa_c, ctx->c, n_words); 97500565589SLin Jinhan if (ret) 97600565589SLin Jinhan goto exit; 97700565589SLin Jinhan } 97800565589SLin Jinhan 97900565589SLin Jinhan ret = rk_mpa_alloc(&mpa_result, NULL, n_words); 98000565589SLin Jinhan if (ret) 98100565589SLin Jinhan goto exit; 98200565589SLin Jinhan 98300565589SLin Jinhan rk_crypto_enable_clk(dev); 98400565589SLin Jinhan ret = rk_exptmod_np(mpa_m, mpa_e, mpa_n, mpa_c, mpa_result); 98500565589SLin Jinhan if (!ret) 98600565589SLin Jinhan memcpy(output, mpa_result->d, BITS2BYTE(n_bits)); 98700565589SLin Jinhan rk_crypto_disable_clk(dev); 98800565589SLin Jinhan 98900565589SLin Jinhan exit: 99000565589SLin Jinhan rk_mpa_free(&mpa_m); 99100565589SLin Jinhan rk_mpa_free(&mpa_e); 99200565589SLin Jinhan rk_mpa_free(&mpa_n); 99300565589SLin Jinhan rk_mpa_free(&mpa_c); 99400565589SLin Jinhan rk_mpa_free(&mpa_result); 99500565589SLin Jinhan 99600565589SLin Jinhan return ret; 99700565589SLin Jinhan } 99800565589SLin Jinhan #endif 99900565589SLin Jinhan 100000565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC) 100100565589SLin Jinhan static int rockchip_crypto_ec_verify(struct udevice *dev, ec_key *ctx, 100200565589SLin Jinhan u8 *hash, u32 hash_len, u8 *sign) 100300565589SLin Jinhan { 100400565589SLin Jinhan struct mpa_num *bn_sign = NULL; 100500565589SLin Jinhan struct rk_ecp_point point_P, point_sign; 100600565589SLin Jinhan u32 n_bits, n_words; 100700565589SLin Jinhan int ret; 100800565589SLin Jinhan 100900565589SLin Jinhan if (!ctx) 101000565589SLin Jinhan return -EINVAL; 101100565589SLin Jinhan 101200565589SLin Jinhan if (ctx->algo != CRYPTO_SM2 && 101300565589SLin Jinhan ctx->algo != CRYPTO_ECC_192R1 && 101400565589SLin Jinhan ctx->algo != CRYPTO_ECC_224R1 && 101500565589SLin Jinhan ctx->algo != CRYPTO_ECC_256R1) 101600565589SLin Jinhan return -EINVAL; 101700565589SLin Jinhan 101800565589SLin Jinhan n_bits = crypto_algo_nbits(ctx->algo); 101900565589SLin Jinhan n_words = BITS2WORD(n_bits); 102000565589SLin Jinhan 102100565589SLin Jinhan ret = rk_mpa_alloc(&bn_sign, sign, n_words); 102200565589SLin Jinhan if (ret) 102300565589SLin Jinhan goto exit; 102400565589SLin Jinhan 102500565589SLin Jinhan ret = rk_mpa_alloc(&point_P.x, ctx->x, n_words); 102600565589SLin Jinhan ret |= rk_mpa_alloc(&point_P.y, ctx->y, n_words); 102700565589SLin Jinhan if (ret) 102800565589SLin Jinhan goto exit; 102900565589SLin Jinhan 103000565589SLin Jinhan ret = rk_mpa_alloc(&point_sign.x, sign, n_words); 103100565589SLin Jinhan ret |= rk_mpa_alloc(&point_sign.y, sign + WORD2BYTE(n_words), n_words); 103200565589SLin Jinhan if (ret) 103300565589SLin Jinhan goto exit; 103400565589SLin Jinhan 103500565589SLin Jinhan rk_crypto_enable_clk(dev); 103600565589SLin Jinhan ret = rockchip_ecc_verify(ctx->algo, hash, hash_len, &point_P, &point_sign); 103700565589SLin Jinhan rk_crypto_disable_clk(dev); 103800565589SLin Jinhan exit: 103900565589SLin Jinhan rk_mpa_free(&bn_sign); 104000565589SLin Jinhan rk_mpa_free(&point_P.x); 104100565589SLin Jinhan rk_mpa_free(&point_P.y); 104200565589SLin Jinhan rk_mpa_free(&point_sign.x); 104300565589SLin Jinhan rk_mpa_free(&point_sign.y); 104400565589SLin Jinhan 104500565589SLin Jinhan return ret; 104600565589SLin Jinhan } 104700565589SLin Jinhan #endif 104800565589SLin Jinhan 104936e17db4Stroy.lin static bool rockchip_crypto_is_secure(struct udevice *dev) 105036e17db4Stroy.lin { 105136e17db4Stroy.lin struct rockchip_crypto_priv *priv = dev_get_priv(dev); 105236e17db4Stroy.lin 105336e17db4Stroy.lin return priv->secure; 105436e17db4Stroy.lin } 105536e17db4Stroy.lin 105600565589SLin Jinhan static const struct dm_crypto_ops rockchip_crypto_ops = { 105700565589SLin Jinhan .capability = rockchip_crypto_capability, 105800565589SLin Jinhan .sha_init = rockchip_crypto_sha_init, 105900565589SLin Jinhan .sha_update = rockchip_crypto_sha_update, 106000565589SLin Jinhan .sha_final = rockchip_crypto_sha_final, 106100565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC) 106200565589SLin Jinhan .hmac_init = rockchip_crypto_hmac_init, 106300565589SLin Jinhan .hmac_update = rockchip_crypto_hmac_update, 106400565589SLin Jinhan .hmac_final = rockchip_crypto_hmac_final, 106500565589SLin Jinhan #endif 106600565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA) 106700565589SLin Jinhan .rsa_verify = rockchip_crypto_rsa_verify, 106800565589SLin Jinhan #endif 106900565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC) 107000565589SLin Jinhan .ec_verify = rockchip_crypto_ec_verify, 107100565589SLin Jinhan #endif 107200565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER) 107300565589SLin Jinhan .cipher_crypt = rockchip_crypto_cipher, 107400565589SLin Jinhan .cipher_mac = rockchip_crypto_mac, 107500565589SLin Jinhan .cipher_ae = rockchip_crypto_ae, 1076*24a57c1cSLin Jinhan 1077*24a57c1cSLin Jinhan #if CONFIG_IS_ENABLED(DM_KEYLAD) 10788f7f431fSTroy Lin .cipher_fw_crypt = rockchip_crypto_fw_cipher, 10798f7f431fSTroy Lin .keytable_addr = rockchip_get_keytable_addr, 108000565589SLin Jinhan #endif 108100565589SLin Jinhan 1082*24a57c1cSLin Jinhan #endif 1083*24a57c1cSLin Jinhan 108436e17db4Stroy.lin .is_secure = rockchip_crypto_is_secure, 108500565589SLin Jinhan }; 108600565589SLin Jinhan 108700565589SLin Jinhan /* 108800565589SLin Jinhan * Only use "clocks" to parse crypto clock id and use rockchip_get_clk(). 108900565589SLin Jinhan * Because we always add crypto node in U-Boot dts, when kernel dtb enabled : 109000565589SLin Jinhan * 109100565589SLin Jinhan * 1. There is cru phandle mismatch between U-Boot and kernel dtb; 109200565589SLin Jinhan * 2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property; 109300565589SLin Jinhan */ 109400565589SLin Jinhan static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev) 109500565589SLin Jinhan { 109600565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev); 109700565589SLin Jinhan int len, ret = -EINVAL; 109800565589SLin Jinhan 109900565589SLin Jinhan memset(priv, 0x00, sizeof(*priv)); 110000565589SLin Jinhan 110100565589SLin Jinhan priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev); 110200565589SLin Jinhan if (priv->reg == FDT_ADDR_T_NONE) 110300565589SLin Jinhan return -EINVAL; 110400565589SLin Jinhan 110500565589SLin Jinhan crypto_base = priv->reg; 110600565589SLin Jinhan 110736e17db4Stroy.lin priv->secure = dev_read_bool(dev, "secure"); 110836e17db4Stroy.lin priv->enabled = true; 110936e17db4Stroy.lin 111036e17db4Stroy.lin #if !defined(CONFIG_SPL_BUILD) 111136e17db4Stroy.lin /* uboot disabled secure crypto */ 111236e17db4Stroy.lin priv->enabled = !priv->secure; 111336e17db4Stroy.lin #endif 111436e17db4Stroy.lin if (!priv->enabled) 111536e17db4Stroy.lin return 0; 111636e17db4Stroy.lin 111700565589SLin Jinhan /* if there is no clocks in dts, just skip it */ 111800565589SLin Jinhan if (!dev_read_prop(dev, "clocks", &len)) { 111900565589SLin Jinhan printf("Can't find \"clocks\" property\n"); 112000565589SLin Jinhan return 0; 112100565589SLin Jinhan } 112200565589SLin Jinhan 112300565589SLin Jinhan priv->clocks = malloc(len); 112400565589SLin Jinhan if (!priv->clocks) 112500565589SLin Jinhan return -ENOMEM; 112600565589SLin Jinhan 112700565589SLin Jinhan priv->nclocks = len / (2 * sizeof(u32)); 112800565589SLin Jinhan if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks, 112900565589SLin Jinhan priv->nclocks)) { 113000565589SLin Jinhan printf("Can't read \"clocks\" property\n"); 113100565589SLin Jinhan ret = -EINVAL; 113200565589SLin Jinhan goto exit; 113300565589SLin Jinhan } 113400565589SLin Jinhan 113500565589SLin Jinhan if (dev_read_prop(dev, "clock-frequency", &len)) { 113600565589SLin Jinhan priv->frequencies = malloc(len); 113700565589SLin Jinhan if (!priv->frequencies) { 113800565589SLin Jinhan ret = -ENOMEM; 113900565589SLin Jinhan goto exit; 114000565589SLin Jinhan } 114100565589SLin Jinhan priv->freq_nclocks = len / sizeof(u32); 114200565589SLin Jinhan if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies, 114300565589SLin Jinhan priv->freq_nclocks)) { 114400565589SLin Jinhan printf("Can't read \"clock-frequency\" property\n"); 114500565589SLin Jinhan ret = -EINVAL; 114600565589SLin Jinhan goto exit; 114700565589SLin Jinhan } 114800565589SLin Jinhan } 114900565589SLin Jinhan 115000565589SLin Jinhan return 0; 115100565589SLin Jinhan exit: 115200565589SLin Jinhan if (priv->clocks) 115300565589SLin Jinhan free(priv->clocks); 115400565589SLin Jinhan 115500565589SLin Jinhan if (priv->frequencies) 115600565589SLin Jinhan free(priv->frequencies); 115700565589SLin Jinhan 115800565589SLin Jinhan return ret; 115900565589SLin Jinhan } 116000565589SLin Jinhan 116100565589SLin Jinhan static int rk_crypto_do_enable_clk(struct udevice *dev, int enable) 116200565589SLin Jinhan { 116300565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev); 116400565589SLin Jinhan struct clk clk; 116500565589SLin Jinhan int i, ret; 116600565589SLin Jinhan 116700565589SLin Jinhan for (i = 0; i < priv->nclocks; i++) { 116800565589SLin Jinhan ret = clk_get_by_index(dev, i, &clk); 116900565589SLin Jinhan if (ret < 0) { 117000565589SLin Jinhan printf("Failed to get clk index %d, ret=%d\n", i, ret); 117100565589SLin Jinhan return ret; 117200565589SLin Jinhan } 117300565589SLin Jinhan 117400565589SLin Jinhan if (enable) 117500565589SLin Jinhan ret = clk_enable(&clk); 117600565589SLin Jinhan else 117700565589SLin Jinhan ret = clk_disable(&clk); 117800565589SLin Jinhan if (ret < 0 && ret != -ENOSYS) { 117900565589SLin Jinhan printf("Failed to enable(%d) clk(%ld): ret=%d\n", 118000565589SLin Jinhan enable, clk.id, ret); 118100565589SLin Jinhan return ret; 118200565589SLin Jinhan } 118300565589SLin Jinhan } 118400565589SLin Jinhan 118500565589SLin Jinhan return 0; 118600565589SLin Jinhan } 118700565589SLin Jinhan 118800565589SLin Jinhan static int rk_crypto_enable_clk(struct udevice *dev) 118900565589SLin Jinhan { 119036e17db4Stroy.lin struct rockchip_crypto_priv *priv = dev_get_priv(dev); 119136e17db4Stroy.lin 119236e17db4Stroy.lin crypto_base = priv->reg; 119336e17db4Stroy.lin 119400565589SLin Jinhan return rk_crypto_do_enable_clk(dev, 1); 119500565589SLin Jinhan } 119600565589SLin Jinhan 119700565589SLin Jinhan static int rk_crypto_disable_clk(struct udevice *dev) 119800565589SLin Jinhan { 119936e17db4Stroy.lin crypto_base = 0; 120036e17db4Stroy.lin 120100565589SLin Jinhan return rk_crypto_do_enable_clk(dev, 0); 120200565589SLin Jinhan } 120300565589SLin Jinhan 120400565589SLin Jinhan static int rk_crypto_set_clk(struct udevice *dev) 120500565589SLin Jinhan { 120600565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev); 120700565589SLin Jinhan struct clk clk; 120800565589SLin Jinhan int i, ret; 120900565589SLin Jinhan 121000565589SLin Jinhan /* use standard "assigned-clock-rates" props */ 121100565589SLin Jinhan if (dev_read_size(dev, "assigned-clock-rates") > 0) 121200565589SLin Jinhan return clk_set_defaults(dev); 121300565589SLin Jinhan 121400565589SLin Jinhan /* use "clock-frequency" props */ 121500565589SLin Jinhan if (priv->freq_nclocks == 0) 121600565589SLin Jinhan return 0; 121700565589SLin Jinhan 121800565589SLin Jinhan for (i = 0; i < priv->freq_nclocks; i++) { 121900565589SLin Jinhan ret = clk_get_by_index(dev, i, &clk); 122000565589SLin Jinhan if (ret < 0) { 122100565589SLin Jinhan printf("Failed to get clk index %d, ret=%d\n", i, ret); 122200565589SLin Jinhan return ret; 122300565589SLin Jinhan } 122400565589SLin Jinhan ret = clk_set_rate(&clk, priv->frequencies[i]); 122500565589SLin Jinhan if (ret < 0) { 122600565589SLin Jinhan printf("%s: Failed to set clk(%ld): ret=%d\n", 122700565589SLin Jinhan __func__, clk.id, ret); 122800565589SLin Jinhan return ret; 122900565589SLin Jinhan } 123000565589SLin Jinhan } 123100565589SLin Jinhan 123200565589SLin Jinhan return 0; 123300565589SLin Jinhan } 123400565589SLin Jinhan 123500565589SLin Jinhan static int rockchip_crypto_probe(struct udevice *dev) 123600565589SLin Jinhan { 123700565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev); 123800565589SLin Jinhan int ret = 0; 123900565589SLin Jinhan 124036e17db4Stroy.lin if (!priv->enabled) 124136e17db4Stroy.lin return 0; 124236e17db4Stroy.lin 124300565589SLin Jinhan ret = rk_crypto_set_clk(dev); 124400565589SLin Jinhan if (ret) 124500565589SLin Jinhan return ret; 124600565589SLin Jinhan 124700565589SLin Jinhan rk_crypto_enable_clk(dev); 124800565589SLin Jinhan 124900565589SLin Jinhan priv->hardware = rkce_hardware_alloc((void *)priv->reg); 125000565589SLin Jinhan 125100565589SLin Jinhan if (!priv->hardware) { 125200565589SLin Jinhan ret = -ENOMEM; 125300565589SLin Jinhan goto exit; 125400565589SLin Jinhan } 125500565589SLin Jinhan 125600565589SLin Jinhan priv->capability = rockchip_crypto_capability(dev); 125700565589SLin Jinhan exit: 125800565589SLin Jinhan rk_crypto_disable_clk(dev); 125900565589SLin Jinhan 126000565589SLin Jinhan return ret; 126100565589SLin Jinhan } 126200565589SLin Jinhan 126300565589SLin Jinhan static const struct udevice_id rockchip_crypto_ids[] = { 126400565589SLin Jinhan { 126500565589SLin Jinhan .compatible = "rockchip,crypto-ce", 126600565589SLin Jinhan }, 126700565589SLin Jinhan { } 126800565589SLin Jinhan }; 126900565589SLin Jinhan 127000565589SLin Jinhan U_BOOT_DRIVER(rockchip_crypto_ce) = { 127100565589SLin Jinhan .name = "rockchip_crypto_ce", 127200565589SLin Jinhan .id = UCLASS_CRYPTO, 127300565589SLin Jinhan .of_match = rockchip_crypto_ids, 127400565589SLin Jinhan .ops = &rockchip_crypto_ops, 127500565589SLin Jinhan .probe = rockchip_crypto_probe, 127600565589SLin Jinhan .ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata, 127700565589SLin Jinhan .priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv), 127800565589SLin Jinhan }; 1279