From 9df731a176aab8e03b984b681b1bea01ccff6644 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 06 Nov 2023 07:23:06 +0000 Subject: [PATCH] rk3568 rt uboot init --- u-boot/drivers/crypto/rockchip/crypto_v2.c | 226 +++++++++++++++++++++++++++++++++++++++++--------------- 1 files changed, 166 insertions(+), 60 deletions(-) diff --git a/u-boot/drivers/crypto/rockchip/crypto_v2.c b/u-boot/drivers/crypto/rockchip/crypto_v2.c index 86226fe..e2135a7 100644 --- a/u-boot/drivers/crypto/rockchip/crypto_v2.c +++ b/u-boot/drivers/crypto/rockchip/crypto_v2.c @@ -8,6 +8,7 @@ #include <crypto.h> #include <dm.h> #include <asm/io.h> +#include <clk-uclass.h> #include <asm/arch/hardware.h> #include <asm/arch/clock.h> #include <rockchip/crypto_hash_cache.h> @@ -54,6 +55,7 @@ char *clocks; u32 *frequencies; u32 nclocks; + u32 freq_nclocks; u32 length; struct rk_hash_ctx *hw_ctx; struct rk_crypto_soc_data *soc_data; @@ -217,6 +219,43 @@ for (i = 0; i < tag_len / 4; i++, chn_base += 4) word2byte_be(crypto_read(chn_base), tag + 4 * i); +} + +static int rk_crypto_do_enable_clk(struct udevice *dev, int enable) +{ + struct rockchip_crypto_priv *priv = dev_get_priv(dev); + struct clk clk; + int i, ret; + + for (i = 0; i < priv->nclocks; i++) { + ret = clk_get_by_index(dev, i, &clk); + if (ret < 0) { + printf("Failed to get clk index %d, ret=%d\n", i, ret); + return ret; + } + + if (enable) + ret = clk_enable(&clk); + else + ret = clk_disable(&clk); + if (ret < 0 && ret != -ENOSYS) { + printf("Failed to enable(%d) clk(%ld): ret=%d\n", + enable, clk.id, ret); + return ret; + } + } + + return 0; +} + +static int rk_crypto_enable_clk(struct udevice *dev) +{ + return rk_crypto_do_enable_clk(dev, 1); +} + +static int rk_crypto_disable_clk(struct udevice *dev) +{ + return rk_crypto_do_enable_clk(dev, 0); } static u32 crypto_v3_dynamic_cap(void) @@ -397,7 +436,7 @@ if (!(*started_flag)) { lli->user_define |= - (LLI_USER_STRING_START | LLI_USER_CPIHER_START); + (LLI_USER_STRING_START | LLI_USER_CIPHER_START); crypto_write((u32)virt_to_phys(lli), CRYPTO_DMA_LLI_ADDR); crypto_write((CRYPTO_HASH_ENABLE << CRYPTO_WRITE_MASK_SHIFT) | CRYPTO_HASH_ENABLE, CRYPTO_HASH_CTL); @@ -520,6 +559,7 @@ { struct rockchip_crypto_priv *priv = dev_get_priv(dev); struct rk_hash_ctx *hash_ctx = priv->hw_ctx; + int ret = 0; if (!ctx) return -EINVAL; @@ -535,7 +575,12 @@ if (!hash_ctx->hash_cache) return -EFAULT; - return rk_hash_init(hash_ctx, ctx->algo); + rk_crypto_enable_clk(dev); + ret = rk_hash_init(hash_ctx, ctx->algo); + if (ret) + rk_crypto_disable_clk(dev); + + return ret; } static int rockchip_crypto_sha_update(struct udevice *dev, @@ -545,8 +590,10 @@ int ret, i; u8 *p; - if (!len) - return -EINVAL; + if (!len) { + ret = -EINVAL; + goto exit; + } p = (u8 *)input; @@ -560,6 +607,9 @@ ret = rk_hash_update(priv->hw_ctx, p, len % HASH_UPDATE_LIMIT); exit: + if (ret) + rk_crypto_disable_clk(dev); + return ret; } @@ -583,6 +633,8 @@ exit: hw_hash_clean_ctx(priv->hw_ctx); + rk_crypto_disable_clk(dev); + return ret; } @@ -614,6 +666,7 @@ { struct rockchip_crypto_priv *priv = dev_get_priv(dev); struct rk_hash_ctx *hash_ctx = priv->hw_ctx; + int ret = 0; if (!ctx) return -EINVAL; @@ -629,7 +682,12 @@ if (!hash_ctx->hash_cache) return -EFAULT; - return rk_hmac_init(priv->hw_ctx, ctx->algo, key, key_len); + rk_crypto_enable_clk(dev); + ret = rk_hmac_init(priv->hw_ctx, ctx->algo, key, key_len); + if (ret) + rk_crypto_disable_clk(dev); + + return ret; } static int rockchip_crypto_hmac_update(struct udevice *dev, @@ -763,6 +821,11 @@ { u32 i; + if (aad_len == 0) { + *padding_size = 0; + return; + } + i = aad_len < (0x10000 - 0x100) ? 2 : 6; if (i == 2) { @@ -779,7 +842,7 @@ *padding_size = i; } -static int ccm_compose_aad_iv(u8 *aad_iv, u32 data_len, u32 tag_size) +static int ccm_compose_aad_iv(u8 *aad_iv, u32 data_len, u32 aad_len, u32 tag_size) { aad_iv[0] |= ((u8)(((tag_size - 2) / 2) & 7) << 3); @@ -788,7 +851,8 @@ aad_iv[14] = (u8)(data_len >> 8); aad_iv[15] = (u8)data_len; - aad_iv[0] |= 0x40; //set aad flag + if (aad_len) + aad_iv[0] |= 0x40; //set aad flag return 0; } @@ -925,12 +989,14 @@ data_desc->dma_ctrl |= LLI_DMA_CTRL_DST_DONE; } + data_desc->user_define = LLI_USER_CIPHER_START | + LLI_USER_STRING_START | + LLI_USER_STRING_LAST | + (key_chn << 4); + crypto_write((u32)virt_to_phys(data_desc), CRYPTO_DMA_LLI_ADDR); + if (rk_mode == RK_MODE_CCM || rk_mode == RK_MODE_GCM) { u32 aad_tmp_len = 0; - - data_desc->user_define = LLI_USER_STRING_START | - LLI_USER_STRING_LAST | - (key_chn << 4); aad_desc = align_malloc(sizeof(*aad_desc), LLI_ADDR_ALIGN_SIZE); if (!aad_desc) @@ -938,7 +1004,7 @@ memset(aad_desc, 0x00, sizeof(*aad_desc)); aad_desc->next_addr = (u32)virt_to_phys(data_desc); - aad_desc->user_define = LLI_USER_CPIHER_START | + aad_desc->user_define = LLI_USER_CIPHER_START | LLI_USER_STRING_START | LLI_USER_STRING_LAST | LLI_USER_STRING_AAD | @@ -958,12 +1024,15 @@ if (!aad_tmp) goto exit; - /* read iv data from reg */ - get_iv_reg(key_chn, aad_tmp, AES_BLOCK_SIZE); - ccm_compose_aad_iv(aad_tmp, tmp_len, tag_len); - memcpy(aad_tmp + AES_BLOCK_SIZE, padding, padding_size); + /* clear last block */ memset(aad_tmp + aad_tmp_len - AES_BLOCK_SIZE, 0x00, AES_BLOCK_SIZE); + + /* read iv data from reg */ + get_iv_reg(key_chn, aad_tmp, AES_BLOCK_SIZE); + ccm_compose_aad_iv(aad_tmp, tmp_len, aad_len, tag_len); + memcpy(aad_tmp + AES_BLOCK_SIZE, padding, padding_size); + memcpy(aad_tmp + AES_BLOCK_SIZE + padding_size, aad, aad_len); } else { @@ -985,15 +1054,15 @@ aad_desc->src_addr = (u32)virt_to_phys(aad_tmp); aad_desc->src_len = aad_tmp_len; - crypto_write((u32)virt_to_phys(aad_desc), CRYPTO_DMA_LLI_ADDR); - cache_op_inner(DCACHE_AREA_CLEAN, aad_tmp, aad_tmp_len); - cache_op_inner(DCACHE_AREA_CLEAN, aad_desc, sizeof(*aad_desc)); - } else { - data_desc->user_define = LLI_USER_CPIHER_START | - LLI_USER_STRING_START | - LLI_USER_STRING_LAST | - (key_chn << 4); - crypto_write((u32)virt_to_phys(data_desc), CRYPTO_DMA_LLI_ADDR); + + if (aad_tmp_len) { + data_desc->user_define = LLI_USER_STRING_START | + LLI_USER_STRING_LAST | + (key_chn << 4); + crypto_write((u32)virt_to_phys(aad_desc), CRYPTO_DMA_LLI_ADDR); + cache_op_inner(DCACHE_AREA_CLEAN, aad_tmp, aad_tmp_len); + cache_op_inner(DCACHE_AREA_CLEAN, aad_desc, sizeof(*aad_desc)); + } } cache_op_inner(DCACHE_AREA_CLEAN, data_desc, sizeof(*data_desc)); @@ -1175,21 +1244,29 @@ int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx, const u8 *in, u8 *out, u32 len, bool enc) { + int ret; + + rk_crypto_enable_clk(dev); + switch (ctx->algo) { case CRYPTO_DES: - return rk_crypto_des(dev, ctx->mode, ctx->key, ctx->key_len, - ctx->iv, in, out, len, enc); + ret = rk_crypto_des(dev, ctx->mode, ctx->key, ctx->key_len, + ctx->iv, in, out, len, enc); case CRYPTO_AES: - return rk_crypto_aes(dev, ctx->mode, - ctx->key, ctx->twk_key, ctx->key_len, - ctx->iv, ctx->iv_len, in, out, len, enc); + ret = rk_crypto_aes(dev, ctx->mode, + ctx->key, ctx->twk_key, ctx->key_len, + ctx->iv, ctx->iv_len, in, out, len, enc); case CRYPTO_SM4: - return rk_crypto_sm4(dev, ctx->mode, - ctx->key, ctx->twk_key, ctx->key_len, - ctx->iv, ctx->iv_len, in, out, len, enc); + ret = rk_crypto_sm4(dev, ctx->mode, + ctx->key, ctx->twk_key, ctx->key_len, + ctx->iv, ctx->iv_len, in, out, len, enc); default: - return -EINVAL; + ret = -EINVAL; } + + rk_crypto_disable_clk(dev); + + return ret; } int rk_crypto_mac(struct udevice *dev, u32 algo, u32 mode, @@ -1223,8 +1300,16 @@ int rockchip_crypto_mac(struct udevice *dev, cipher_context *ctx, const u8 *in, u32 len, u8 *tag) { - return rk_crypto_mac(dev, ctx->algo, ctx->mode, - ctx->key, ctx->key_len, in, len, tag); + int ret = 0; + + rk_crypto_enable_clk(dev); + + ret = rk_crypto_mac(dev, ctx->algo, ctx->mode, + ctx->key, ctx->key_len, in, len, tag); + + rk_crypto_disable_clk(dev); + + return ret; } int rk_crypto_ae(struct udevice *dev, u32 algo, u32 mode, @@ -1236,6 +1321,9 @@ int ret; if (!IS_AE_MODE(rk_mode)) + return -EINVAL; + + if (len == 0) return -EINVAL; if (algo != CRYPTO_AES && algo != CRYPTO_SM4) @@ -1261,9 +1349,17 @@ u8 *out, u8 *tag) { - return rk_crypto_ae(dev, ctx->algo, ctx->mode, ctx->key, ctx->key_len, - ctx->iv, ctx->iv_len, in, len, - aad, aad_len, out, tag); + int ret = 0; + + rk_crypto_enable_clk(dev); + + ret = rk_crypto_ae(dev, ctx->algo, ctx->mode, ctx->key, ctx->key_len, + ctx->iv, ctx->iv_len, in, len, + aad, aad_len, out, tag); + + rk_crypto_disable_clk(dev); + + return ret; } #endif @@ -1312,9 +1408,11 @@ if (ret) goto exit; + rk_crypto_enable_clk(dev); ret = rk_exptmod_np(mpa_m, mpa_e, mpa_n, mpa_c, mpa_result); if (!ret) memcpy(output, mpa_result->d, BITS2BYTE(n_bits)); + rk_crypto_disable_clk(dev); exit: rk_mpa_free(&mpa_m); @@ -1378,7 +1476,7 @@ if (!priv->clocks) return -ENOMEM; - priv->nclocks = len / sizeof(u32); + priv->nclocks = len / (2 * sizeof(u32)); if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks, priv->nclocks)) { printf("Can't read \"clocks\" property\n"); @@ -1386,24 +1484,19 @@ goto exit; } - if (!dev_read_prop(dev, "clock-frequency", &len)) { - printf("Can't find \"clock-frequency\" property\n"); - ret = -EINVAL; - goto exit; - } - - priv->frequencies = malloc(len); - if (!priv->frequencies) { - ret = -ENOMEM; - goto exit; - } - - priv->nclocks = len / sizeof(u32); - if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies, - priv->nclocks)) { - printf("Can't read \"clock-frequency\" property\n"); - ret = -EINVAL; - goto exit; + if (dev_read_prop(dev, "clock-frequency", &len)) { + priv->frequencies = malloc(len); + if (!priv->frequencies) { + ret = -ENOMEM; + goto exit; + } + priv->freq_nclocks = len / sizeof(u32); + if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies, + priv->freq_nclocks)) { + printf("Can't read \"clock-frequency\" property\n"); + ret = -EINVAL; + goto exit; + } } return 0; @@ -1423,10 +1516,15 @@ struct clk clk; int i, ret; - if (!priv->clocks && priv->nclocks == 0) + /* use standard "assigned-clock-rates" props */ + if (dev_read_size(dev, "assigned-clock-rates") > 0) + return clk_set_defaults(dev); + + /* use "clock-frequency" props */ + if (priv->freq_nclocks == 0) return 0; - for (i = 0; i < priv->nclocks; i++) { + for (i = 0; i < priv->freq_nclocks; i++) { ret = clk_get_by_index(dev, i, &clk); if (ret < 0) { printf("Failed to get clk index %d, ret=%d\n", i, ret); @@ -1465,7 +1563,11 @@ if (ret) return ret; + rk_crypto_enable_clk(dev); + hw_crypto_reset(); + + rk_crypto_disable_clk(dev); return 0; } @@ -1557,6 +1659,10 @@ .compatible = "rockchip,crypto-v3", .data = (ulong)&soc_data_cryptov3 }, + { + .compatible = "rockchip,crypto-v4", + .data = (ulong)&soc_data_cryptov3 /* reuse crypto v3 config */ + }, { } }; -- Gitblit v1.6.2