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
rk_crypto_soft_reset(struct udevice * dev,uint32_t reset_sel)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
crypto_flush_cacheline(ulong addr,ulong size)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
crypto_invalidate_cacheline(uint32_t addr,uint32_t size)134*7358c157Stroy.lin static void crypto_invalidate_cacheline(uint32_t addr, uint32_t size)
135*7358c157Stroy.lin {
136*7358c157Stroy.lin ulong alignment = CONFIG_SYS_CACHELINE_SIZE;
137*7358c157Stroy.lin ulong aligned_input, aligned_len;
138*7358c157Stroy.lin
139*7358c157Stroy.lin if (!addr || !size)
140*7358c157Stroy.lin return;
141*7358c157Stroy.lin
142*7358c157Stroy.lin /* Must invalidate dcache after crypto DMA write data region */
143*7358c157Stroy.lin aligned_input = round_down(addr, alignment);
144*7358c157Stroy.lin aligned_len = round_up(size + (addr - aligned_input), alignment);
145*7358c157Stroy.lin invalidate_dcache_range(aligned_input, aligned_input + aligned_len);
146*7358c157Stroy.lin }
147*7358c157Stroy.lin
rk_get_cemode(const struct rockchip_map * map,u32 num,u32 algo)14800565589SLin Jinhan static u32 rk_get_cemode(const struct rockchip_map *map, u32 num, u32 algo)
14900565589SLin Jinhan {
15000565589SLin Jinhan u32 i, j;
15100565589SLin Jinhan struct {
15200565589SLin Jinhan const struct rockchip_map *map;
15300565589SLin Jinhan u32 num;
15400565589SLin Jinhan } map_tbl[] = {
15500565589SLin Jinhan {rk_hash_map, ARRAY_SIZE(rk_hash_map)},
15600565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
15700565589SLin Jinhan {rk_hmac_map, ARRAY_SIZE(rk_hmac_map)},
15800565589SLin Jinhan #endif
15900565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
16000565589SLin Jinhan {rk_cipher_map, ARRAY_SIZE(rk_cipher_map)},
16100565589SLin Jinhan #endif
16200565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
16300565589SLin Jinhan {rk_rsa_map, ARRAY_SIZE(rk_rsa_map)},
16400565589SLin Jinhan #endif
16500565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
16600565589SLin Jinhan {rk_ec_map, ARRAY_SIZE(rk_ec_map)},
16700565589SLin Jinhan #endif
16800565589SLin Jinhan };
16900565589SLin Jinhan
17000565589SLin Jinhan for (i = 0; i < ARRAY_SIZE(map_tbl); i++) {
17100565589SLin Jinhan const struct rockchip_map *map = map_tbl[i].map;
17200565589SLin Jinhan u32 num = map_tbl[i].num;
17300565589SLin Jinhan
17400565589SLin Jinhan for (j = 0; j < num; j++) {
17500565589SLin Jinhan if (map[j].crypto == algo)
17600565589SLin Jinhan return map[j].rkce;
17700565589SLin Jinhan }
17800565589SLin Jinhan }
17900565589SLin Jinhan
18000565589SLin Jinhan return 0;
18100565589SLin Jinhan }
18200565589SLin Jinhan
rk_load_map(struct rockchip_crypto_priv * priv,u32 algo_type,const struct rockchip_map * map,u32 num)18300565589SLin Jinhan static u32 rk_load_map(struct rockchip_crypto_priv *priv, u32 algo_type,
18400565589SLin Jinhan const struct rockchip_map *map, u32 num)
18500565589SLin Jinhan {
18600565589SLin Jinhan u32 i;
18700565589SLin Jinhan u32 capability = 0;
18800565589SLin Jinhan
18900565589SLin Jinhan for (i = 0; i < num; i++) {
19000565589SLin Jinhan if (rkce_hw_algo_valid(priv->hardware, algo_type, map[i].rkce, 0))
19100565589SLin Jinhan capability |= map[i].crypto;
19200565589SLin Jinhan }
19300565589SLin Jinhan
19400565589SLin Jinhan return capability;
19500565589SLin Jinhan }
19600565589SLin Jinhan
rockchip_crypto_capability(struct udevice * dev)19700565589SLin Jinhan static u32 rockchip_crypto_capability(struct udevice *dev)
19800565589SLin Jinhan {
19900565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
20000565589SLin Jinhan u32 cap = 0;
20100565589SLin Jinhan
20236e17db4Stroy.lin if (!priv->enabled)
20336e17db4Stroy.lin return 0;
20436e17db4Stroy.lin
20500565589SLin Jinhan if (priv->capability)
20600565589SLin Jinhan return priv->capability;
20700565589SLin Jinhan
20800565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_HASH,
20900565589SLin Jinhan rk_hash_map, ARRAY_SIZE(rk_hash_map));
21000565589SLin Jinhan
21100565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
21200565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_HMAC,
21300565589SLin Jinhan rk_hmac_map, ARRAY_SIZE(rk_hmac_map));
21400565589SLin Jinhan #endif
21500565589SLin Jinhan
21600565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
21700565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_CIPHER,
21800565589SLin Jinhan rk_cipher_map, ARRAY_SIZE(rk_cipher_map));
21900565589SLin Jinhan #endif
22000565589SLin Jinhan
22100565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
22200565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_ASYM, rk_rsa_map,
22300565589SLin Jinhan ARRAY_SIZE(rk_rsa_map));
22400565589SLin Jinhan #endif
22500565589SLin Jinhan
22600565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
22700565589SLin Jinhan cap |= rk_load_map(priv, RKCE_ALGO_TYPE_ASYM, rk_ec_map,
22800565589SLin Jinhan ARRAY_SIZE(rk_ec_map));
22900565589SLin Jinhan #endif
23000565589SLin Jinhan
23100565589SLin Jinhan return cap;
23200565589SLin Jinhan }
23300565589SLin Jinhan
rkce_sha_ctx_alloc(void)23400565589SLin Jinhan static void *rkce_sha_ctx_alloc(void)
23500565589SLin Jinhan {
23600565589SLin Jinhan struct rkce_sha_contex *hw_ctx;
23700565589SLin Jinhan
23800565589SLin Jinhan hw_ctx = malloc(sizeof(*hw_ctx));
23900565589SLin Jinhan if (!hw_ctx)
24000565589SLin Jinhan return NULL;
24100565589SLin Jinhan
24200565589SLin Jinhan memset(hw_ctx, 0x00, sizeof(*hw_ctx));
24300565589SLin Jinhan
24400565589SLin Jinhan hw_ctx->td = rkce_cma_alloc(sizeof(struct rkce_hash_td));
24500565589SLin Jinhan if (!hw_ctx->td)
24600565589SLin Jinhan goto error;
24700565589SLin Jinhan
24800565589SLin Jinhan memset(hw_ctx->td, 0x00, sizeof(struct rkce_hash_td));
24900565589SLin Jinhan
25000565589SLin Jinhan hw_ctx->td_buf = rkce_cma_alloc(sizeof(struct rkce_hash_td_buf));
25100565589SLin Jinhan if (!hw_ctx->td_buf)
25200565589SLin Jinhan goto error;
25300565589SLin Jinhan
25400565589SLin Jinhan memset(hw_ctx->td_buf, 0x00, sizeof(struct rkce_hash_td_buf));
25500565589SLin Jinhan
25600565589SLin Jinhan return hw_ctx;
25700565589SLin Jinhan error:
25800565589SLin Jinhan rkce_cma_free(hw_ctx->td);
25900565589SLin Jinhan rkce_cma_free(hw_ctx->td_buf);
26000565589SLin Jinhan free(hw_ctx);
26100565589SLin Jinhan
26200565589SLin Jinhan return NULL;
26300565589SLin Jinhan }
26400565589SLin Jinhan
rkce_sha_ctx_free(struct rkce_sha_contex * hw_ctx)26500565589SLin Jinhan static void rkce_sha_ctx_free(struct rkce_sha_contex *hw_ctx)
26600565589SLin Jinhan {
26700565589SLin Jinhan if (!hw_ctx)
26800565589SLin Jinhan return;
26900565589SLin Jinhan
27000565589SLin Jinhan rkce_cma_free(hw_ctx->td);
27100565589SLin Jinhan rkce_cma_free(hw_ctx->td_buf);
27200565589SLin Jinhan free(hw_ctx);
27300565589SLin Jinhan }
27400565589SLin Jinhan
rk_sha_init(struct udevice * dev,sha_context * ctx,u8 * key,u32 key_len,bool is_hmac)27500565589SLin Jinhan static int rk_sha_init(struct udevice *dev, sha_context *ctx,
27600565589SLin Jinhan u8 *key, u32 key_len, bool is_hmac)
27700565589SLin Jinhan {
27800565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
27900565589SLin Jinhan struct rkce_sha_contex *hash_ctx = NULL;
28000565589SLin Jinhan u32 ce_algo = 0;
28100565589SLin Jinhan int ret = 0;
28200565589SLin Jinhan
28300565589SLin Jinhan if ((ctx->algo & priv->capability) == 0)
28400565589SLin Jinhan return -ENOSYS;
28500565589SLin Jinhan
28600565589SLin Jinhan if (priv->hash_ctx)
28700565589SLin Jinhan return -EFAULT;
28800565589SLin Jinhan
2898f7f431fSTroy Lin rk_crypto_soft_reset(dev, RKCE_RESET_HASH);
29000565589SLin Jinhan
29100565589SLin Jinhan hash_ctx = rkce_sha_ctx_alloc();
29200565589SLin Jinhan if (!hash_ctx)
29300565589SLin Jinhan return -ENOMEM;
29400565589SLin Jinhan
29500565589SLin Jinhan ret = rkce_init_hash_td(hash_ctx->td, hash_ctx->td_buf);
29600565589SLin Jinhan if (ret)
29700565589SLin Jinhan goto exit;
29800565589SLin Jinhan
29900565589SLin Jinhan ce_algo = rk_get_cemode(rk_hash_map, ARRAY_SIZE(rk_hash_map), ctx->algo);
30000565589SLin Jinhan
30100565589SLin Jinhan hash_ctx->ctrl.td_type = RKCE_TD_TYPE_HASH;
30200565589SLin Jinhan hash_ctx->ctrl.hw_pad_en = 1;
30300565589SLin Jinhan hash_ctx->ctrl.first_pkg = 1;
30400565589SLin Jinhan hash_ctx->ctrl.last_pkg = 0;
30500565589SLin Jinhan hash_ctx->ctrl.hash_algo = ce_algo;
30600565589SLin Jinhan hash_ctx->ctrl.hmac_en = is_hmac;
30700565589SLin Jinhan hash_ctx->ctrl.is_preemptible = 0;
30800565589SLin Jinhan hash_ctx->ctrl.int_en = 1;
30900565589SLin Jinhan
31000565589SLin Jinhan if (is_hmac) {
31100565589SLin Jinhan if (key_len > 64) {
31200565589SLin Jinhan ret = -EINVAL;
31300565589SLin Jinhan goto exit;
31400565589SLin Jinhan }
31500565589SLin Jinhan
31600565589SLin Jinhan memcpy(hash_ctx->td_buf->key, key, key_len);
31700565589SLin Jinhan }
31800565589SLin Jinhan
31900565589SLin Jinhan priv->hash_ctx = hash_ctx;
32000565589SLin Jinhan exit:
32100565589SLin Jinhan if (ret) {
32200565589SLin Jinhan rkce_sha_ctx_free(hash_ctx);
32300565589SLin Jinhan priv->hash_ctx = NULL;
32400565589SLin Jinhan }
32500565589SLin Jinhan
32600565589SLin Jinhan return ret;
32700565589SLin Jinhan }
32800565589SLin Jinhan
rk_sha_update(struct udevice * dev,u32 * input,u32 len,bool is_last)32900565589SLin Jinhan static int rk_sha_update(struct udevice *dev, u32 *input, u32 len, bool is_last)
33000565589SLin Jinhan {
33100565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
33200565589SLin Jinhan struct rkce_sha_contex *hash_ctx;
33300565589SLin Jinhan struct rkce_hash_td *td;
33400565589SLin Jinhan int ret = 0;
33500565589SLin Jinhan
33600565589SLin Jinhan if (!priv->hash_ctx)
33700565589SLin Jinhan return -EINVAL;
33800565589SLin Jinhan
33900565589SLin Jinhan if (!is_last && (!input || len == 0))
34000565589SLin Jinhan return -EINVAL;
34100565589SLin Jinhan
34200565589SLin Jinhan hash_ctx = priv->hash_ctx;
34300565589SLin Jinhan td = hash_ctx->td;
34400565589SLin Jinhan
34500565589SLin Jinhan td->ctrl = hash_ctx->ctrl;
34600565589SLin Jinhan memset(&td->sg, 0x00, sizeof(*td->sg));
34700565589SLin Jinhan
34800565589SLin Jinhan if (hash_ctx->ctrl.first_pkg == 1)
34900565589SLin Jinhan hash_ctx->ctrl.first_pkg = 0;
35000565589SLin Jinhan
35100565589SLin Jinhan if (is_last) {
35200565589SLin Jinhan td->ctrl.last_pkg = 1;
35300565589SLin Jinhan } else {
35400565589SLin Jinhan #ifdef CONFIG_ARM64
35500565589SLin Jinhan td->sg[0].src_addr_h = rkce_cma_virt2phys(input) >> 32;
35600565589SLin Jinhan #endif
35700565589SLin Jinhan td->sg[0].src_addr_l = rkce_cma_virt2phys(input) & 0xffffffff;
35800565589SLin Jinhan td->sg[0].src_size = len;
35900565589SLin Jinhan hash_ctx->length += len;
36000565589SLin Jinhan crypto_flush_cacheline((ulong)input, len);
36100565589SLin Jinhan }
36200565589SLin Jinhan
36300565589SLin Jinhan rk_crypto_enable_clk(dev);
36400565589SLin Jinhan
36500565589SLin Jinhan crypto_flush_cacheline((ulong)hash_ctx->td, sizeof(*hash_ctx->td));
36600565589SLin Jinhan crypto_flush_cacheline((ulong)hash_ctx->td_buf, sizeof(*hash_ctx->td_buf));
36700565589SLin Jinhan
36800565589SLin Jinhan ret = rkce_push_td_sync(priv->hardware, td, RKCE_HASH_TIMEOUT_MS);
36900565589SLin Jinhan if (ret) {
37000565589SLin Jinhan rkce_sha_ctx_free(hash_ctx);
37100565589SLin Jinhan priv->hash_ctx = NULL;
37200565589SLin Jinhan }
37300565589SLin Jinhan
374*7358c157Stroy.lin crypto_invalidate_cacheline((ulong)hash_ctx->td_buf, sizeof(*hash_ctx->td_buf));
375*7358c157Stroy.lin
37600565589SLin Jinhan rk_crypto_disable_clk(dev);
37700565589SLin Jinhan
37800565589SLin Jinhan return ret;
37900565589SLin Jinhan }
38000565589SLin Jinhan
rockchip_crypto_sha_init(struct udevice * dev,sha_context * ctx)38100565589SLin Jinhan static int rockchip_crypto_sha_init(struct udevice *dev, sha_context *ctx)
38200565589SLin Jinhan {
38300565589SLin Jinhan return rk_sha_init(dev, ctx, NULL, 0, false);
38400565589SLin Jinhan }
38500565589SLin Jinhan
rockchip_crypto_sha_update(struct udevice * dev,u32 * input,u32 len)38600565589SLin Jinhan static int rockchip_crypto_sha_update(struct udevice *dev, u32 *input, u32 len)
38700565589SLin Jinhan {
38800565589SLin Jinhan return rk_sha_update(dev, input, len, false);
38900565589SLin Jinhan }
39000565589SLin Jinhan
rockchip_crypto_sha_final(struct udevice * dev,sha_context * ctx,u8 * output)39100565589SLin Jinhan static int rockchip_crypto_sha_final(struct udevice *dev, sha_context *ctx, u8 *output)
39200565589SLin Jinhan {
39300565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
39400565589SLin Jinhan struct rkce_sha_contex *hash_ctx = priv->hash_ctx;
39500565589SLin Jinhan u32 nbits;
39600565589SLin Jinhan int ret;
39700565589SLin Jinhan
39800565589SLin Jinhan if (!priv->hash_ctx)
39900565589SLin Jinhan return -EINVAL;
40000565589SLin Jinhan
40100565589SLin Jinhan nbits = crypto_algo_nbits(ctx->algo);
40200565589SLin Jinhan
40300565589SLin Jinhan if (hash_ctx->length != ctx->length) {
40400565589SLin Jinhan printf("total length(0x%08x) != init length(0x%08x)!\n",
40500565589SLin Jinhan hash_ctx->length, ctx->length);
40600565589SLin Jinhan ret = -EIO;
40700565589SLin Jinhan goto exit;
40800565589SLin Jinhan }
40900565589SLin Jinhan
41000565589SLin Jinhan ret = rk_sha_update(dev, NULL, 0, true);
41100565589SLin Jinhan if (ret == 0)
41200565589SLin Jinhan memcpy(output, hash_ctx->td_buf->hash, BITS2BYTE(nbits));
41300565589SLin Jinhan
41400565589SLin Jinhan exit:
41500565589SLin Jinhan rkce_sha_ctx_free(hash_ctx);
41600565589SLin Jinhan priv->hash_ctx = NULL;
41700565589SLin Jinhan
41800565589SLin Jinhan return ret;
41900565589SLin Jinhan }
42000565589SLin Jinhan
42100565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
rockchip_crypto_hmac_init(struct udevice * dev,sha_context * ctx,u8 * key,u32 key_len)42200565589SLin Jinhan static int rockchip_crypto_hmac_init(struct udevice *dev, sha_context *ctx, u8 *key, u32 key_len)
42300565589SLin Jinhan {
42400565589SLin Jinhan return rk_sha_init(dev, ctx, key, key_len, true);
42500565589SLin Jinhan }
42600565589SLin Jinhan
rockchip_crypto_hmac_update(struct udevice * dev,u32 * input,u32 len)42700565589SLin Jinhan static int rockchip_crypto_hmac_update(struct udevice *dev, u32 *input, u32 len)
42800565589SLin Jinhan {
42900565589SLin Jinhan return rockchip_crypto_sha_update(dev, input, len);
43000565589SLin Jinhan }
43100565589SLin Jinhan
rockchip_crypto_hmac_final(struct udevice * dev,sha_context * ctx,u8 * output)43200565589SLin Jinhan static int rockchip_crypto_hmac_final(struct udevice *dev, sha_context *ctx, u8 *output)
43300565589SLin Jinhan {
43400565589SLin Jinhan return rockchip_crypto_sha_final(dev, ctx, output);
43500565589SLin Jinhan }
43600565589SLin Jinhan #endif
43700565589SLin Jinhan
43800565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
43900565589SLin Jinhan
hw_crypto_ccm128_setiv(u8 * iv_buf,u8 * nonce,u32 nlen,u32 mlen)44000565589SLin Jinhan static int hw_crypto_ccm128_setiv(u8 *iv_buf, u8 *nonce, u32 nlen, u32 mlen)
44100565589SLin Jinhan {
44200565589SLin Jinhan u32 L = iv_buf[0] & 7; /* the L parameter */
44300565589SLin Jinhan
44400565589SLin Jinhan if (nlen < (14 - L))
44500565589SLin Jinhan return -1; /* nonce is too short */
44600565589SLin Jinhan
44700565589SLin Jinhan if (sizeof(mlen) == 8 && L >= 3) {
44800565589SLin Jinhan iv_buf[8] = mlen >> (56 % (sizeof(mlen) * 8));
44900565589SLin Jinhan iv_buf[9] = mlen >> (48 % (sizeof(mlen) * 8));
45000565589SLin Jinhan iv_buf[10] = mlen >> (40 % (sizeof(mlen) * 8));
45100565589SLin Jinhan iv_buf[11] = mlen >> (32 % (sizeof(mlen) * 8));
45200565589SLin Jinhan }
45300565589SLin Jinhan
45400565589SLin Jinhan iv_buf[12] = mlen >> 24;
45500565589SLin Jinhan iv_buf[13] = mlen >> 16;
45600565589SLin Jinhan iv_buf[14] = mlen >> 8;
45700565589SLin Jinhan iv_buf[15] = mlen;
45800565589SLin Jinhan
45900565589SLin Jinhan iv_buf[0] &= ~0x40; /* clear aad flag */
46000565589SLin Jinhan memcpy(&iv_buf[1], nonce, 14 - L);
46100565589SLin Jinhan
46200565589SLin Jinhan return 0;
46300565589SLin Jinhan }
46400565589SLin Jinhan
hw_get_ccm_aad_padding(u32 aad_len,u8 * padding,u32 * padding_size)46500565589SLin Jinhan static void hw_get_ccm_aad_padding(u32 aad_len, u8 *padding, u32 *padding_size)
46600565589SLin Jinhan {
46700565589SLin Jinhan u32 i = 0;
46800565589SLin Jinhan
46900565589SLin Jinhan if (aad_len == 0) {
47000565589SLin Jinhan *padding_size = 0;
47100565589SLin Jinhan return;
47200565589SLin Jinhan }
47300565589SLin Jinhan
47400565589SLin Jinhan if (aad_len < (0x10000 - 0x100)) {
47500565589SLin Jinhan i = 2;
47600565589SLin Jinhan } else if (sizeof(aad_len) == 8 &&
47700565589SLin Jinhan aad_len >= (size_t)1 << (32 % (sizeof(aad_len) * 8))) {
47800565589SLin Jinhan i = 10;
47900565589SLin Jinhan } else {
48000565589SLin Jinhan i = 6;
48100565589SLin Jinhan }
48200565589SLin Jinhan
48300565589SLin Jinhan if (i == 2) {
48400565589SLin Jinhan padding[0] = aad_len >> 8;
48500565589SLin Jinhan padding[1] = aad_len;
48600565589SLin Jinhan } else if (i == 10) {
48700565589SLin Jinhan padding[0] = 0xFF;
48800565589SLin Jinhan padding[1] = 0xFF;
48900565589SLin Jinhan padding[2] = aad_len >> (56 % (sizeof(aad_len) * 8));
49000565589SLin Jinhan padding[3] = aad_len >> (48 % (sizeof(aad_len) * 8));
49100565589SLin Jinhan padding[4] = aad_len >> (40 % (sizeof(aad_len) * 8));
49200565589SLin Jinhan padding[5] = aad_len >> (32 % (sizeof(aad_len) * 8));
49300565589SLin Jinhan padding[6] = aad_len >> 24;
49400565589SLin Jinhan padding[7] = aad_len >> 16;
49500565589SLin Jinhan padding[8] = aad_len >> 8;
49600565589SLin Jinhan padding[9] = aad_len;
49700565589SLin Jinhan } else {
49800565589SLin Jinhan padding[0] = 0xFF;
49900565589SLin Jinhan padding[1] = 0xFE;
50000565589SLin Jinhan padding[2] = aad_len >> 24;
50100565589SLin Jinhan padding[3] = aad_len >> 16;
50200565589SLin Jinhan padding[4] = aad_len >> 8;
50300565589SLin Jinhan }
50400565589SLin Jinhan
50500565589SLin Jinhan *padding_size = i;
50600565589SLin Jinhan }
50700565589SLin Jinhan
hw_compose_ccm_aad_iv(u8 * aad_iv,u32 data_len,u32 aad_len,u32 tag_size)50800565589SLin Jinhan static int hw_compose_ccm_aad_iv(u8 *aad_iv, u32 data_len,
50900565589SLin Jinhan u32 aad_len, u32 tag_size)
51000565589SLin Jinhan {
51100565589SLin Jinhan u32 L; /* the L parameter */
51200565589SLin Jinhan u8 nonce[AES_BLOCK_SIZE];
51300565589SLin Jinhan
51400565589SLin Jinhan L = aad_iv[0] & 7;
51500565589SLin Jinhan aad_iv[0] |= ((u8)(((tag_size - 2) / 2) & 7) << 3);
51600565589SLin Jinhan
51700565589SLin Jinhan if (sizeof(data_len) == 8 && L >= 3) {
51800565589SLin Jinhan aad_iv[8] = data_len >> (56 % (sizeof(data_len) * 8));
51900565589SLin Jinhan aad_iv[9] = data_len >> (48 % (sizeof(data_len) * 8));
52000565589SLin Jinhan aad_iv[10] = data_len >> (40 % (sizeof(data_len) * 8));
52100565589SLin Jinhan aad_iv[11] = data_len >> (32 % (sizeof(data_len) * 8));
52200565589SLin Jinhan }
52300565589SLin Jinhan
52400565589SLin Jinhan /* save nonce */
52500565589SLin Jinhan memcpy(nonce, &aad_iv[1], 14 - L);
52600565589SLin Jinhan
52700565589SLin Jinhan aad_iv[12] = data_len >> 24;
52800565589SLin Jinhan aad_iv[13] = data_len >> 16;
52900565589SLin Jinhan aad_iv[14] = data_len >> 8;
53000565589SLin Jinhan aad_iv[15] = data_len;
53100565589SLin Jinhan
53200565589SLin Jinhan /* restore nonce */
53300565589SLin Jinhan memcpy(&aad_iv[1], nonce, 14 - L);
53400565589SLin Jinhan
53500565589SLin Jinhan aad_iv[0] &= ~0x40; /* clear Adata flag */
53600565589SLin Jinhan
53700565589SLin Jinhan if (aad_len)
53800565589SLin Jinhan aad_iv[0] |= 0x40; //set aad flag
53900565589SLin Jinhan
54000565589SLin Jinhan return 0;
54100565589SLin Jinhan }
54200565589SLin Jinhan
rkce_destroy_ccm_aad(u8 * new_aad)54300565589SLin Jinhan static void rkce_destroy_ccm_aad(u8 *new_aad)
54400565589SLin Jinhan {
54500565589SLin Jinhan rkce_cma_free(new_aad);
54600565589SLin Jinhan }
54700565589SLin Jinhan
rkce_build_ccm_aad(const u8 * aad,u32 aad_len,u32 data_len,u8 * iv,u32 iv_len,u8 ** new_aad,u32 * new_aad_len,u8 * new_iv,u32 * new_iv_len)54800565589SLin Jinhan static int rkce_build_ccm_aad(const u8 *aad, u32 aad_len, u32 data_len,
54900565589SLin Jinhan u8 *iv, u32 iv_len,
55000565589SLin Jinhan u8 **new_aad, u32 *new_aad_len,
55100565589SLin Jinhan u8 *new_iv, u32 *new_iv_len)
55200565589SLin Jinhan {
55300565589SLin Jinhan int ret = -RKCE_INVAL;
55400565589SLin Jinhan u32 L;
55500565589SLin Jinhan u8 nonce[AES_BLOCK_SIZE];
55600565589SLin Jinhan u8 pad[AES_BLOCK_SIZE];
55700565589SLin Jinhan u32 pad_size = 0;
55800565589SLin Jinhan u32 tag_len = AES_BLOCK_SIZE;
55900565589SLin Jinhan u8 *aad_tmp = NULL;
56000565589SLin Jinhan u32 aad_tmp_len = 0;
56100565589SLin Jinhan
56200565589SLin Jinhan memset(nonce, 0x00, sizeof(nonce));
56300565589SLin Jinhan
56400565589SLin Jinhan L = 15 - iv_len;
56500565589SLin Jinhan nonce[0] = (L - 1) & 7;
56600565589SLin Jinhan ret = hw_crypto_ccm128_setiv(nonce, (u8 *)iv, iv_len, 0);
56700565589SLin Jinhan if (ret)
56800565589SLin Jinhan return ret;
56900565589SLin Jinhan
57000565589SLin Jinhan memcpy(new_iv, nonce, sizeof(nonce));
57100565589SLin Jinhan *new_iv_len = sizeof(nonce);
57200565589SLin Jinhan
57300565589SLin Jinhan memset(pad, 0x00, sizeof(pad));
57400565589SLin Jinhan hw_get_ccm_aad_padding(aad_len, pad, &pad_size);
57500565589SLin Jinhan
57600565589SLin Jinhan aad_tmp_len = aad_len + AES_BLOCK_SIZE + pad_size;
57700565589SLin Jinhan aad_tmp_len = ROUNDUP(aad_tmp_len, AES_BLOCK_SIZE);
57800565589SLin Jinhan
57900565589SLin Jinhan aad_tmp = rkce_cma_alloc(aad_tmp_len);
58000565589SLin Jinhan if (!aad_tmp) {
58100565589SLin Jinhan ret = -RKCE_NOMEM;
58200565589SLin Jinhan goto exit;
58300565589SLin Jinhan }
58400565589SLin Jinhan
58500565589SLin Jinhan /* clear last block */
58600565589SLin Jinhan memset(aad_tmp + aad_tmp_len - AES_BLOCK_SIZE, 0x00, AES_BLOCK_SIZE);
58700565589SLin Jinhan memcpy(aad_tmp, nonce, sizeof(nonce));
58800565589SLin Jinhan hw_compose_ccm_aad_iv(aad_tmp, data_len, aad_len, tag_len);
58900565589SLin Jinhan memcpy(aad_tmp + AES_BLOCK_SIZE, pad, pad_size);
59000565589SLin Jinhan
59100565589SLin Jinhan memcpy(aad_tmp + AES_BLOCK_SIZE + pad_size, aad, aad_len);
59200565589SLin Jinhan
59300565589SLin Jinhan *new_aad = aad_tmp;
59400565589SLin Jinhan *new_aad_len = aad_tmp_len;
59500565589SLin Jinhan
59600565589SLin Jinhan exit:
59700565589SLin Jinhan return ret;
59800565589SLin Jinhan }
59900565589SLin Jinhan
rkce_cipher_ctx_alloc(void)60000565589SLin Jinhan static void *rkce_cipher_ctx_alloc(void)
60100565589SLin Jinhan {
60200565589SLin Jinhan struct rkce_cipher_contex *hw_ctx;
60300565589SLin Jinhan
60400565589SLin Jinhan hw_ctx = malloc(sizeof(*hw_ctx));
60500565589SLin Jinhan if (!hw_ctx)
60600565589SLin Jinhan return NULL;
60700565589SLin Jinhan
60800565589SLin Jinhan hw_ctx->td = rkce_cma_alloc(sizeof(struct rkce_symm_td));
60900565589SLin Jinhan if (!hw_ctx->td)
61000565589SLin Jinhan goto error;
61100565589SLin Jinhan
61200565589SLin Jinhan memset(hw_ctx->td, 0x00, sizeof(struct rkce_symm_td));
61300565589SLin Jinhan
61400565589SLin Jinhan hw_ctx->td_aad = rkce_cma_alloc(sizeof(struct rkce_symm_td));
61500565589SLin Jinhan if (!hw_ctx->td_aad)
61600565589SLin Jinhan goto error;
61700565589SLin Jinhan
61800565589SLin Jinhan memset(hw_ctx->td_aad, 0x00, sizeof(struct rkce_symm_td));
61900565589SLin Jinhan
62000565589SLin Jinhan hw_ctx->td_buf = rkce_cma_alloc(sizeof(struct rkce_symm_td_buf));
62100565589SLin Jinhan if (!hw_ctx->td_buf)
62200565589SLin Jinhan goto error;
62300565589SLin Jinhan
62400565589SLin Jinhan memset(hw_ctx->td_buf, 0x00, sizeof(struct rkce_symm_td_buf));
62500565589SLin Jinhan
62600565589SLin Jinhan return hw_ctx;
62700565589SLin Jinhan error:
62800565589SLin Jinhan rkce_cma_free(hw_ctx->td);
62900565589SLin Jinhan rkce_cma_free(hw_ctx->td_aad);
63000565589SLin Jinhan rkce_cma_free(hw_ctx->td_buf);
63100565589SLin Jinhan free(hw_ctx);
63200565589SLin Jinhan
63300565589SLin Jinhan return NULL;
63400565589SLin Jinhan }
63500565589SLin Jinhan
rkce_cipher_ctx_free(struct rkce_cipher_contex * hw_ctx)63600565589SLin Jinhan static void rkce_cipher_ctx_free(struct rkce_cipher_contex *hw_ctx)
63700565589SLin Jinhan {
63800565589SLin Jinhan if (!hw_ctx)
63900565589SLin Jinhan return;
64000565589SLin Jinhan
64100565589SLin Jinhan rkce_cma_free(hw_ctx->td);
64200565589SLin Jinhan rkce_cma_free(hw_ctx->td_aad);
64300565589SLin Jinhan rkce_cma_free(hw_ctx->td_buf);
64400565589SLin Jinhan free(hw_ctx);
64500565589SLin Jinhan }
64600565589SLin Jinhan
64700565589SLin Jinhan static const struct rockchip_map rk_cipher_algo_map[] = {
64800565589SLin Jinhan {RK_MODE_ECB, RKCE_SYMM_MODE_ECB},
64900565589SLin Jinhan {RK_MODE_CBC, RKCE_SYMM_MODE_CBC},
65000565589SLin Jinhan {RK_MODE_CTS, RKCE_SYMM_MODE_CTS},
65100565589SLin Jinhan {RK_MODE_CTR, RKCE_SYMM_MODE_CTR},
65200565589SLin Jinhan {RK_MODE_CFB, RKCE_SYMM_MODE_CFB},
65300565589SLin Jinhan {RK_MODE_OFB, RKCE_SYMM_MODE_OFB},
65400565589SLin Jinhan {RK_MODE_XTS, RKCE_SYMM_MODE_XTS},
65500565589SLin Jinhan {RK_MODE_CCM, RKCE_SYMM_MODE_CCM},
65600565589SLin Jinhan {RK_MODE_GCM, RKCE_SYMM_MODE_GCM},
65700565589SLin Jinhan {RK_MODE_CMAC, RKCE_SYMM_MODE_CMAC},
65800565589SLin Jinhan {RK_MODE_CBC_MAC, RKCE_SYMM_MODE_CBC_MAC},
65900565589SLin Jinhan };
66000565589SLin Jinhan
rk_get_cipher_cemode(u32 algo,u32 mode,u32 * ce_algo,u32 * ce_mode)66100565589SLin Jinhan static int rk_get_cipher_cemode(u32 algo, u32 mode, u32 *ce_algo, u32 *ce_mode)
66200565589SLin Jinhan {
66300565589SLin Jinhan u32 i;
66400565589SLin Jinhan
66500565589SLin Jinhan switch (algo) {
66600565589SLin Jinhan case CRYPTO_DES:
66700565589SLin Jinhan *ce_algo = RKCE_SYMM_ALGO_TDES;
66800565589SLin Jinhan break;
66900565589SLin Jinhan case CRYPTO_AES:
67000565589SLin Jinhan *ce_algo = RKCE_SYMM_ALGO_AES;
67100565589SLin Jinhan break;
67200565589SLin Jinhan case CRYPTO_SM4:
67300565589SLin Jinhan *ce_algo = RKCE_SYMM_ALGO_SM4;
67400565589SLin Jinhan break;
67500565589SLin Jinhan default:
67600565589SLin Jinhan return -EINVAL;
67700565589SLin Jinhan }
67800565589SLin Jinhan
67900565589SLin Jinhan for (i = 0; i < ARRAY_SIZE(rk_cipher_algo_map); i++) {
68000565589SLin Jinhan if (mode == rk_cipher_algo_map[i].crypto) {
68100565589SLin Jinhan *ce_mode = rk_cipher_algo_map[i].rkce;
68200565589SLin Jinhan return 0;
68300565589SLin Jinhan }
68400565589SLin Jinhan }
68500565589SLin Jinhan
68600565589SLin Jinhan return -EINVAL;
68700565589SLin Jinhan }
68800565589SLin Jinhan
rk_get_td_keysize(u32 ce_algo,u32 ce_mode,u32 key_len)68900565589SLin Jinhan u32 rk_get_td_keysize(u32 ce_algo, u32 ce_mode, u32 key_len)
69000565589SLin Jinhan {
69100565589SLin Jinhan u32 key_size = 0;
69200565589SLin Jinhan
69300565589SLin Jinhan if (ce_algo == RKCE_SYMM_ALGO_AES) {
69400565589SLin Jinhan if (key_len == AES_KEYSIZE_128)
69500565589SLin Jinhan key_size = RKCE_KEY_AES_128;
69600565589SLin Jinhan else if (key_len == AES_KEYSIZE_192)
69700565589SLin Jinhan key_size = RKCE_KEY_AES_192;
69800565589SLin Jinhan else if (key_len == AES_KEYSIZE_256)
69900565589SLin Jinhan key_size = RKCE_KEY_AES_256;
70000565589SLin Jinhan else
70100565589SLin Jinhan ;
70200565589SLin Jinhan }
70300565589SLin Jinhan
70400565589SLin Jinhan return key_size;
70500565589SLin Jinhan }
70600565589SLin Jinhan
rk_set_symm_td_buf_key(struct rkce_symm_td_buf * td_buf,u32 ce_algo,u32 ce_mode,cipher_context * ctx)70700565589SLin Jinhan int rk_set_symm_td_buf_key(struct rkce_symm_td_buf *td_buf,
70800565589SLin Jinhan u32 ce_algo, u32 ce_mode, cipher_context *ctx)
70900565589SLin Jinhan {
71000565589SLin Jinhan memset(td_buf->key1, 0x00, sizeof(td_buf->key1));
71100565589SLin Jinhan memset(td_buf->key2, 0x00, sizeof(td_buf->key2));
71200565589SLin Jinhan
71300565589SLin Jinhan if (ce_mode == RKCE_SYMM_MODE_XTS) {
71400565589SLin Jinhan memcpy(td_buf->key1, ctx->key, ctx->key_len);
71500565589SLin Jinhan memcpy(td_buf->key2, ctx->twk_key, ctx->key_len);
71600565589SLin Jinhan } else {
71700565589SLin Jinhan memcpy(td_buf->key1, ctx->key, ctx->key_len);
71800565589SLin Jinhan }
71900565589SLin Jinhan
72000565589SLin Jinhan if (ctx->key_len == DES_KEYSIZE * 2 &&
72100565589SLin Jinhan (ce_algo == RKCE_SYMM_ALGO_DES || ce_algo == RKCE_SYMM_ALGO_TDES))
72200565589SLin Jinhan memcpy(td_buf->key1 + DES_KEYSIZE * 2, td_buf->key1, DES_KEYSIZE);
72300565589SLin Jinhan
72400565589SLin Jinhan return 0;
72500565589SLin Jinhan }
72600565589SLin Jinhan
rk_set_symm_td_sg(struct rkce_symm_td * td,const u8 * in,u32 in_len,u8 * out,u32 out_len)72700565589SLin Jinhan int rk_set_symm_td_sg(struct rkce_symm_td *td,
72800565589SLin Jinhan const u8 *in, u32 in_len, u8 *out, u32 out_len)
72900565589SLin Jinhan {
73000565589SLin Jinhan memset(td->sg, 0x00, sizeof(td->sg));
73100565589SLin Jinhan
73200565589SLin Jinhan #ifdef CONFIG_ARM64
73300565589SLin Jinhan td->sg[0].src_addr_h = rkce_cma_virt2phys(in) >> 32;
73400565589SLin Jinhan #endif
73500565589SLin Jinhan td->sg[0].src_addr_l = rkce_cma_virt2phys(in) & 0xffffffff;
73600565589SLin Jinhan td->sg[0].src_size = in_len;
73700565589SLin Jinhan
73800565589SLin Jinhan if (out && out_len) {
73900565589SLin Jinhan #ifdef CONFIG_ARM64
74000565589SLin Jinhan td->sg[0].dst_addr_h = rkce_cma_virt2phys(out) >> 32;
74100565589SLin Jinhan #endif
74200565589SLin Jinhan td->sg[0].dst_addr_l = rkce_cma_virt2phys(out) & 0xffffffff;
74300565589SLin Jinhan td->sg[0].dst_size = out_len;
74400565589SLin Jinhan }
74500565589SLin Jinhan
74600565589SLin Jinhan td->next_task = 0;
74700565589SLin Jinhan
74800565589SLin Jinhan return 0;
74900565589SLin Jinhan }
75000565589SLin Jinhan
rk_crypto_cipher(struct udevice * dev,cipher_context * ctx,const u8 * in,u8 * out,u32 len,bool enc,const u8 * aad,u32 aad_len,u8 * tag)75100565589SLin Jinhan static int rk_crypto_cipher(struct udevice *dev, cipher_context *ctx,
75200565589SLin Jinhan const u8 *in, u8 *out, u32 len, bool enc,
75300565589SLin Jinhan const u8 *aad, u32 aad_len, u8 *tag)
75400565589SLin Jinhan {
75500565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
75600565589SLin Jinhan struct rkce_cipher_contex *hw_ctx = NULL;
75700565589SLin Jinhan u32 ce_algo = 0, ce_mode = 0;
7588f7f431fSTroy Lin bool use_otpkey = false;
75900565589SLin Jinhan int ret = 0;
76000565589SLin Jinhan
7618f7f431fSTroy Lin rk_crypto_soft_reset(dev, RKCE_RESET_SYMM);
7628f7f431fSTroy Lin
7638f7f431fSTroy Lin if (!ctx->key && ctx->key_len)
7648f7f431fSTroy Lin use_otpkey = true;
76500565589SLin Jinhan
76600565589SLin Jinhan ret = rk_get_cipher_cemode(ctx->algo, ctx->mode, &ce_algo, &ce_mode);
76700565589SLin Jinhan if (ret)
76800565589SLin Jinhan return ret;
76900565589SLin Jinhan
77000565589SLin Jinhan hw_ctx = rkce_cipher_ctx_alloc();
77100565589SLin Jinhan if (!hw_ctx)
77200565589SLin Jinhan return -ENOMEM;
77300565589SLin Jinhan
77400565589SLin Jinhan rkce_init_symm_td(hw_ctx->td, hw_ctx->td_buf);
77500565589SLin Jinhan
77600565589SLin Jinhan hw_ctx->td->ctrl.td_type = RKCE_TD_TYPE_SYMM;
77700565589SLin Jinhan hw_ctx->td->ctrl.is_dec = !enc;
77800565589SLin Jinhan hw_ctx->td->ctrl.symm_algo = ce_algo;
77900565589SLin Jinhan hw_ctx->td->ctrl.symm_mode = ce_mode;
78000565589SLin Jinhan hw_ctx->td->ctrl.key_size = rk_get_td_keysize(ce_algo, ce_mode, ctx->key_len);
78100565589SLin Jinhan hw_ctx->td->ctrl.first_pkg = 1;
78200565589SLin Jinhan hw_ctx->td->ctrl.last_pkg = 1;
78300565589SLin Jinhan hw_ctx->td->ctrl.int_en = 1;
7848f7f431fSTroy Lin hw_ctx->td->ctrl.key_sel = use_otpkey ? RKCE_KEY_SEL_KT : RKCE_KEY_SEL_USER;
78500565589SLin Jinhan
78600565589SLin Jinhan memcpy(hw_ctx->td_buf->iv, ctx->iv, ctx->iv_len);
78700565589SLin Jinhan hw_ctx->td->ctrl.iv_len = ctx->iv_len;
78800565589SLin Jinhan
7898f7f431fSTroy Lin if (!use_otpkey) {
79000565589SLin Jinhan ret = rk_set_symm_td_buf_key(hw_ctx->td_buf, ce_algo, ce_mode, ctx);
79100565589SLin Jinhan if (ret)
79200565589SLin Jinhan goto exit;
7938f7f431fSTroy Lin }
79400565589SLin Jinhan
79500565589SLin Jinhan ret = rk_set_symm_td_sg(hw_ctx->td, in, len, out, len);
79600565589SLin Jinhan if (ret)
79700565589SLin Jinhan goto exit;
79800565589SLin Jinhan
79900565589SLin Jinhan if (ce_mode == RKCE_SYMM_MODE_CCM) {
80000565589SLin Jinhan u8 *new_aad = NULL;
80100565589SLin Jinhan u32 new_aad_len = 0, new_iv_len = 0;
80200565589SLin Jinhan
80300565589SLin Jinhan rkce_init_symm_td(hw_ctx->td_aad, hw_ctx->td_buf);
80400565589SLin Jinhan
80500565589SLin Jinhan ret = rkce_build_ccm_aad(aad, aad_len, len,
80600565589SLin Jinhan hw_ctx->td_buf->iv, ctx->iv_len,
80700565589SLin Jinhan &new_aad, &new_aad_len,
80800565589SLin Jinhan hw_ctx->td_buf->iv, &new_iv_len);
80900565589SLin Jinhan if (ret)
81000565589SLin Jinhan goto exit;
81100565589SLin Jinhan
81200565589SLin Jinhan ret = rk_set_symm_td_sg(hw_ctx->td_aad, new_aad, new_aad_len, NULL, 0);
81300565589SLin Jinhan if (ret)
81400565589SLin Jinhan goto exit;
81500565589SLin Jinhan
81600565589SLin Jinhan hw_ctx->td->ctrl.iv_len = new_iv_len;
81700565589SLin Jinhan
81800565589SLin Jinhan hw_ctx->td_buf->gcm_len.aad_len_l = new_aad_len;
81900565589SLin Jinhan
82000565589SLin Jinhan hw_ctx->td_aad->ctrl = hw_ctx->td->ctrl;
82100565589SLin Jinhan hw_ctx->td_aad->ctrl.is_aad = 1;
82200565589SLin Jinhan
82300565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_aad, sizeof(*hw_ctx->td_aad));
82400565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_buf, sizeof(*hw_ctx->td_buf));
82500565589SLin Jinhan crypto_flush_cacheline((ulong)new_aad, new_aad_len);
82600565589SLin Jinhan
82700565589SLin Jinhan rk_crypto_enable_clk(dev);
82800565589SLin Jinhan
82900565589SLin Jinhan ret = rkce_push_td_sync(priv->hardware, hw_ctx->td_aad, RKCE_SYMM_TIMEOUT_MS);
83000565589SLin Jinhan
831*7358c157Stroy.lin crypto_invalidate_cacheline((ulong)hw_ctx->td_buf, sizeof(*hw_ctx->td_buf));
832*7358c157Stroy.lin
83300565589SLin Jinhan rk_crypto_disable_clk(dev);
83400565589SLin Jinhan
83500565589SLin Jinhan rkce_destroy_ccm_aad(new_aad);
83600565589SLin Jinhan
83700565589SLin Jinhan if (ret) {
83800565589SLin Jinhan printf("CCM calc aad data failed.\n");
83900565589SLin Jinhan goto exit;
84000565589SLin Jinhan }
84100565589SLin Jinhan } else if (ce_mode == RKCE_SYMM_MODE_GCM) {
84200565589SLin Jinhan rkce_init_symm_td(hw_ctx->td_aad, hw_ctx->td_buf);
84300565589SLin Jinhan
84400565589SLin Jinhan ret = rk_set_symm_td_sg(hw_ctx->td_aad, aad, aad_len, NULL, 0);
84500565589SLin Jinhan if (ret)
84600565589SLin Jinhan goto exit;
84700565589SLin Jinhan
84800565589SLin Jinhan hw_ctx->td_buf->gcm_len.aad_len_l = aad_len;
84900565589SLin Jinhan hw_ctx->td_buf->gcm_len.pc_len_l = len;
85000565589SLin Jinhan
85100565589SLin Jinhan hw_ctx->td_aad->ctrl = hw_ctx->td->ctrl;
85200565589SLin Jinhan hw_ctx->td_aad->ctrl.is_aad = 1;
85300565589SLin Jinhan
85400565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_aad, sizeof(*hw_ctx->td_aad));
85500565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_buf, sizeof(*hw_ctx->td_buf));
85600565589SLin Jinhan crypto_flush_cacheline((ulong)aad, aad_len);
85700565589SLin Jinhan
85800565589SLin Jinhan rk_crypto_enable_clk(dev);
85900565589SLin Jinhan
86000565589SLin Jinhan ret = rkce_push_td_sync(priv->hardware, hw_ctx->td_aad, RKCE_SYMM_TIMEOUT_MS);
86100565589SLin Jinhan
862*7358c157Stroy.lin crypto_invalidate_cacheline((ulong)hw_ctx->td_buf, sizeof(*hw_ctx->td_buf));
863*7358c157Stroy.lin
86400565589SLin Jinhan rk_crypto_disable_clk(dev);
86500565589SLin Jinhan if (ret) {
86600565589SLin Jinhan printf("GCM calc aad data failed.\n");
86700565589SLin Jinhan goto exit;
86800565589SLin Jinhan }
86900565589SLin Jinhan }
87000565589SLin Jinhan
87100565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td, sizeof(*hw_ctx->td));
87200565589SLin Jinhan crypto_flush_cacheline((ulong)hw_ctx->td_buf, sizeof(*hw_ctx->td_buf));
87300565589SLin Jinhan crypto_flush_cacheline((ulong)in, len);
874*7358c157Stroy.lin if (in != out)
875*7358c157Stroy.lin crypto_flush_cacheline((ulong)out, len);
87600565589SLin Jinhan
87700565589SLin Jinhan rk_crypto_enable_clk(dev);
87800565589SLin Jinhan
87900565589SLin Jinhan ret = rkce_push_td_sync(priv->hardware, hw_ctx->td, RKCE_SYMM_TIMEOUT_MS);
88000565589SLin Jinhan
88100565589SLin Jinhan crypto_invalidate_cacheline((ulong)out, len);
882*7358c157Stroy.lin crypto_invalidate_cacheline((ulong)hw_ctx->td_buf, sizeof(*hw_ctx->td_buf));
88300565589SLin Jinhan
88400565589SLin Jinhan rk_crypto_disable_clk(dev);
88500565589SLin Jinhan
88600565589SLin Jinhan if (tag)
88700565589SLin Jinhan memcpy(tag, hw_ctx->td_buf->tag, sizeof(hw_ctx->td_buf->tag));
88800565589SLin Jinhan exit:
88900565589SLin Jinhan rkce_cipher_ctx_free(hw_ctx);
89000565589SLin Jinhan
89100565589SLin Jinhan return ret;
89200565589SLin Jinhan }
89300565589SLin Jinhan
rockchip_crypto_cipher(struct udevice * dev,cipher_context * ctx,const u8 * in,u8 * out,u32 len,bool enc)89400565589SLin Jinhan static int rockchip_crypto_cipher(struct udevice *dev, cipher_context *ctx,
89500565589SLin Jinhan const u8 *in, u8 *out, u32 len, bool enc)
89600565589SLin Jinhan {
89700565589SLin Jinhan return rk_crypto_cipher(dev, ctx, in, out, len, enc, NULL, 0, NULL);
89800565589SLin Jinhan }
89900565589SLin Jinhan
rockchip_crypto_mac(struct udevice * dev,cipher_context * ctx,const u8 * in,u32 len,u8 * tag)90000565589SLin Jinhan static int rockchip_crypto_mac(struct udevice *dev, cipher_context *ctx,
90100565589SLin Jinhan const u8 *in, u32 len, u8 *tag)
90200565589SLin Jinhan {
90300565589SLin Jinhan return rk_crypto_cipher(dev, ctx, in, NULL, len, true, NULL, 0, tag);
90400565589SLin Jinhan }
90500565589SLin Jinhan
rockchip_crypto_ae(struct udevice * dev,cipher_context * ctx,const u8 * in,u32 len,const u8 * aad,u32 aad_len,u8 * out,u8 * tag)90600565589SLin Jinhan static int rockchip_crypto_ae(struct udevice *dev, cipher_context *ctx,
90700565589SLin Jinhan const u8 *in, u32 len, const u8 *aad, u32 aad_len,
90800565589SLin Jinhan u8 *out, u8 *tag)
90900565589SLin Jinhan {
91000565589SLin Jinhan return rk_crypto_cipher(dev, ctx, in, out, len, true, aad, aad_len, tag);
91100565589SLin Jinhan }
91200565589SLin Jinhan
91324a57c1cSLin Jinhan #if CONFIG_IS_ENABLED(DM_KEYLAD)
rockchip_crypto_fw_cipher(struct udevice * dev,cipher_fw_context * ctx,const u8 * in,u8 * out,u32 len,bool enc)9148f7f431fSTroy Lin int rockchip_crypto_fw_cipher(struct udevice *dev, cipher_fw_context *ctx,
9158f7f431fSTroy Lin const u8 *in, u8 *out, u32 len, bool enc)
9168f7f431fSTroy Lin {
9178f7f431fSTroy Lin cipher_context cipher_ctx;
9188f7f431fSTroy Lin
9198f7f431fSTroy Lin memset(&cipher_ctx, 0x00, sizeof(cipher_ctx));
9208f7f431fSTroy Lin
9218f7f431fSTroy Lin cipher_ctx.algo = ctx->algo;
9228f7f431fSTroy Lin cipher_ctx.mode = ctx->mode;
9238f7f431fSTroy Lin cipher_ctx.key_len = ctx->key_len;
9248f7f431fSTroy Lin cipher_ctx.iv = ctx->iv;
9258f7f431fSTroy Lin cipher_ctx.iv_len = ctx->iv_len;
9268f7f431fSTroy Lin
9278f7f431fSTroy Lin return rk_crypto_cipher(dev, &cipher_ctx, in, out, len, enc, NULL, 0, NULL);
9288f7f431fSTroy Lin }
9298f7f431fSTroy Lin
rockchip_get_keytable_addr(struct udevice * dev)9308f7f431fSTroy Lin static ulong rockchip_get_keytable_addr(struct udevice *dev)
9318f7f431fSTroy Lin {
9328f7f431fSTroy Lin struct rockchip_crypto_priv *priv = dev_get_priv(dev);
9338f7f431fSTroy Lin ulong addr;
9348f7f431fSTroy Lin
9358f7f431fSTroy Lin rk_crypto_enable_clk(dev);
9368f7f431fSTroy Lin
9378f7f431fSTroy Lin addr = rkce_get_keytable_addr(priv->hardware);
9388f7f431fSTroy Lin
9398f7f431fSTroy Lin rk_crypto_disable_clk(dev);
9408f7f431fSTroy Lin
9418f7f431fSTroy Lin return addr;
9428f7f431fSTroy Lin }
94324a57c1cSLin Jinhan #endif
9448f7f431fSTroy Lin
94500565589SLin Jinhan #endif
94600565589SLin Jinhan
94700565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
rockchip_crypto_rsa_verify(struct udevice * dev,rsa_key * ctx,u8 * sign,u8 * output)94800565589SLin Jinhan static int rockchip_crypto_rsa_verify(struct udevice *dev, rsa_key *ctx,
94900565589SLin Jinhan u8 *sign, u8 *output)
95000565589SLin Jinhan {
95100565589SLin Jinhan struct mpa_num *mpa_m = NULL, *mpa_e = NULL, *mpa_n = NULL;
95200565589SLin Jinhan struct mpa_num *mpa_c = NULL, *mpa_result = NULL;
95300565589SLin Jinhan u32 n_bits, n_words;
95400565589SLin Jinhan int ret;
95500565589SLin Jinhan
95600565589SLin Jinhan if (!ctx)
95700565589SLin Jinhan return -EINVAL;
95800565589SLin Jinhan
95900565589SLin Jinhan if (ctx->algo != CRYPTO_RSA512 &&
96000565589SLin Jinhan ctx->algo != CRYPTO_RSA1024 &&
96100565589SLin Jinhan ctx->algo != CRYPTO_RSA2048 &&
96200565589SLin Jinhan ctx->algo != CRYPTO_RSA3072 &&
96300565589SLin Jinhan ctx->algo != CRYPTO_RSA4096)
96400565589SLin Jinhan return -EINVAL;
96500565589SLin Jinhan
96600565589SLin Jinhan n_bits = crypto_algo_nbits(ctx->algo);
96700565589SLin Jinhan n_words = BITS2WORD(n_bits);
96800565589SLin Jinhan
96900565589SLin Jinhan ret = rk_mpa_alloc(&mpa_m, sign, n_words);
97000565589SLin Jinhan if (ret)
97100565589SLin Jinhan goto exit;
97200565589SLin Jinhan
97300565589SLin Jinhan ret = rk_mpa_alloc(&mpa_e, ctx->e, n_words);
97400565589SLin Jinhan if (ret)
97500565589SLin Jinhan goto exit;
97600565589SLin Jinhan
97700565589SLin Jinhan ret = rk_mpa_alloc(&mpa_n, ctx->n, n_words);
97800565589SLin Jinhan if (ret)
97900565589SLin Jinhan goto exit;
98000565589SLin Jinhan
98100565589SLin Jinhan if (ctx->c) {
98200565589SLin Jinhan ret = rk_mpa_alloc(&mpa_c, ctx->c, n_words);
98300565589SLin Jinhan if (ret)
98400565589SLin Jinhan goto exit;
98500565589SLin Jinhan }
98600565589SLin Jinhan
98700565589SLin Jinhan ret = rk_mpa_alloc(&mpa_result, NULL, n_words);
98800565589SLin Jinhan if (ret)
98900565589SLin Jinhan goto exit;
99000565589SLin Jinhan
99100565589SLin Jinhan rk_crypto_enable_clk(dev);
99200565589SLin Jinhan ret = rk_exptmod_np(mpa_m, mpa_e, mpa_n, mpa_c, mpa_result);
99300565589SLin Jinhan if (!ret)
99400565589SLin Jinhan memcpy(output, mpa_result->d, BITS2BYTE(n_bits));
99500565589SLin Jinhan rk_crypto_disable_clk(dev);
99600565589SLin Jinhan
99700565589SLin Jinhan exit:
99800565589SLin Jinhan rk_mpa_free(&mpa_m);
99900565589SLin Jinhan rk_mpa_free(&mpa_e);
100000565589SLin Jinhan rk_mpa_free(&mpa_n);
100100565589SLin Jinhan rk_mpa_free(&mpa_c);
100200565589SLin Jinhan rk_mpa_free(&mpa_result);
100300565589SLin Jinhan
100400565589SLin Jinhan return ret;
100500565589SLin Jinhan }
100600565589SLin Jinhan #endif
100700565589SLin Jinhan
100800565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
rockchip_crypto_ec_verify(struct udevice * dev,ec_key * ctx,u8 * hash,u32 hash_len,u8 * sign)100900565589SLin Jinhan static int rockchip_crypto_ec_verify(struct udevice *dev, ec_key *ctx,
101000565589SLin Jinhan u8 *hash, u32 hash_len, u8 *sign)
101100565589SLin Jinhan {
101200565589SLin Jinhan struct mpa_num *bn_sign = NULL;
101300565589SLin Jinhan struct rk_ecp_point point_P, point_sign;
101400565589SLin Jinhan u32 n_bits, n_words;
101500565589SLin Jinhan int ret;
101600565589SLin Jinhan
101700565589SLin Jinhan if (!ctx)
101800565589SLin Jinhan return -EINVAL;
101900565589SLin Jinhan
102000565589SLin Jinhan if (ctx->algo != CRYPTO_SM2 &&
102100565589SLin Jinhan ctx->algo != CRYPTO_ECC_192R1 &&
102200565589SLin Jinhan ctx->algo != CRYPTO_ECC_224R1 &&
102300565589SLin Jinhan ctx->algo != CRYPTO_ECC_256R1)
102400565589SLin Jinhan return -EINVAL;
102500565589SLin Jinhan
102600565589SLin Jinhan n_bits = crypto_algo_nbits(ctx->algo);
102700565589SLin Jinhan n_words = BITS2WORD(n_bits);
102800565589SLin Jinhan
102900565589SLin Jinhan ret = rk_mpa_alloc(&bn_sign, sign, n_words);
103000565589SLin Jinhan if (ret)
103100565589SLin Jinhan goto exit;
103200565589SLin Jinhan
103300565589SLin Jinhan ret = rk_mpa_alloc(&point_P.x, ctx->x, n_words);
103400565589SLin Jinhan ret |= rk_mpa_alloc(&point_P.y, ctx->y, n_words);
103500565589SLin Jinhan if (ret)
103600565589SLin Jinhan goto exit;
103700565589SLin Jinhan
103800565589SLin Jinhan ret = rk_mpa_alloc(&point_sign.x, sign, n_words);
103900565589SLin Jinhan ret |= rk_mpa_alloc(&point_sign.y, sign + WORD2BYTE(n_words), n_words);
104000565589SLin Jinhan if (ret)
104100565589SLin Jinhan goto exit;
104200565589SLin Jinhan
104300565589SLin Jinhan rk_crypto_enable_clk(dev);
104400565589SLin Jinhan ret = rockchip_ecc_verify(ctx->algo, hash, hash_len, &point_P, &point_sign);
104500565589SLin Jinhan rk_crypto_disable_clk(dev);
104600565589SLin Jinhan exit:
104700565589SLin Jinhan rk_mpa_free(&bn_sign);
104800565589SLin Jinhan rk_mpa_free(&point_P.x);
104900565589SLin Jinhan rk_mpa_free(&point_P.y);
105000565589SLin Jinhan rk_mpa_free(&point_sign.x);
105100565589SLin Jinhan rk_mpa_free(&point_sign.y);
105200565589SLin Jinhan
105300565589SLin Jinhan return ret;
105400565589SLin Jinhan }
105500565589SLin Jinhan #endif
105600565589SLin Jinhan
rockchip_crypto_is_secure(struct udevice * dev)105736e17db4Stroy.lin static bool rockchip_crypto_is_secure(struct udevice *dev)
105836e17db4Stroy.lin {
105936e17db4Stroy.lin struct rockchip_crypto_priv *priv = dev_get_priv(dev);
106036e17db4Stroy.lin
106136e17db4Stroy.lin return priv->secure;
106236e17db4Stroy.lin }
106336e17db4Stroy.lin
106400565589SLin Jinhan static const struct dm_crypto_ops rockchip_crypto_ops = {
106500565589SLin Jinhan .capability = rockchip_crypto_capability,
106600565589SLin Jinhan .sha_init = rockchip_crypto_sha_init,
106700565589SLin Jinhan .sha_update = rockchip_crypto_sha_update,
106800565589SLin Jinhan .sha_final = rockchip_crypto_sha_final,
106900565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_HMAC)
107000565589SLin Jinhan .hmac_init = rockchip_crypto_hmac_init,
107100565589SLin Jinhan .hmac_update = rockchip_crypto_hmac_update,
107200565589SLin Jinhan .hmac_final = rockchip_crypto_hmac_final,
107300565589SLin Jinhan #endif
107400565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_RSA)
107500565589SLin Jinhan .rsa_verify = rockchip_crypto_rsa_verify,
107600565589SLin Jinhan #endif
107700565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_EC)
107800565589SLin Jinhan .ec_verify = rockchip_crypto_ec_verify,
107900565589SLin Jinhan #endif
108000565589SLin Jinhan #if CONFIG_IS_ENABLED(ROCKCHIP_CIPHER)
108100565589SLin Jinhan .cipher_crypt = rockchip_crypto_cipher,
108200565589SLin Jinhan .cipher_mac = rockchip_crypto_mac,
108300565589SLin Jinhan .cipher_ae = rockchip_crypto_ae,
108424a57c1cSLin Jinhan
108524a57c1cSLin Jinhan #if CONFIG_IS_ENABLED(DM_KEYLAD)
10868f7f431fSTroy Lin .cipher_fw_crypt = rockchip_crypto_fw_cipher,
10878f7f431fSTroy Lin .keytable_addr = rockchip_get_keytable_addr,
108800565589SLin Jinhan #endif
108900565589SLin Jinhan
109024a57c1cSLin Jinhan #endif
109124a57c1cSLin Jinhan
109236e17db4Stroy.lin .is_secure = rockchip_crypto_is_secure,
109300565589SLin Jinhan };
109400565589SLin Jinhan
109500565589SLin Jinhan /*
109600565589SLin Jinhan * Only use "clocks" to parse crypto clock id and use rockchip_get_clk().
109700565589SLin Jinhan * Because we always add crypto node in U-Boot dts, when kernel dtb enabled :
109800565589SLin Jinhan *
109900565589SLin Jinhan * 1. There is cru phandle mismatch between U-Boot and kernel dtb;
110000565589SLin Jinhan * 2. CONFIG_OF_SPL_REMOVE_PROPS removes clock property;
110100565589SLin Jinhan */
rockchip_crypto_ofdata_to_platdata(struct udevice * dev)110200565589SLin Jinhan static int rockchip_crypto_ofdata_to_platdata(struct udevice *dev)
110300565589SLin Jinhan {
110400565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
110500565589SLin Jinhan int len, ret = -EINVAL;
110600565589SLin Jinhan
110700565589SLin Jinhan memset(priv, 0x00, sizeof(*priv));
110800565589SLin Jinhan
110900565589SLin Jinhan priv->reg = (fdt_addr_t)dev_read_addr_ptr(dev);
111000565589SLin Jinhan if (priv->reg == FDT_ADDR_T_NONE)
111100565589SLin Jinhan return -EINVAL;
111200565589SLin Jinhan
111300565589SLin Jinhan crypto_base = priv->reg;
111400565589SLin Jinhan
111536e17db4Stroy.lin priv->secure = dev_read_bool(dev, "secure");
111636e17db4Stroy.lin priv->enabled = true;
111736e17db4Stroy.lin
111836e17db4Stroy.lin #if !defined(CONFIG_SPL_BUILD)
111936e17db4Stroy.lin /* uboot disabled secure crypto */
112036e17db4Stroy.lin priv->enabled = !priv->secure;
112136e17db4Stroy.lin #endif
112236e17db4Stroy.lin if (!priv->enabled)
112336e17db4Stroy.lin return 0;
112436e17db4Stroy.lin
112500565589SLin Jinhan /* if there is no clocks in dts, just skip it */
112600565589SLin Jinhan if (!dev_read_prop(dev, "clocks", &len)) {
112700565589SLin Jinhan printf("Can't find \"clocks\" property\n");
112800565589SLin Jinhan return 0;
112900565589SLin Jinhan }
113000565589SLin Jinhan
113100565589SLin Jinhan priv->clocks = malloc(len);
113200565589SLin Jinhan if (!priv->clocks)
113300565589SLin Jinhan return -ENOMEM;
113400565589SLin Jinhan
113500565589SLin Jinhan priv->nclocks = len / (2 * sizeof(u32));
113600565589SLin Jinhan if (dev_read_u32_array(dev, "clocks", (u32 *)priv->clocks,
113700565589SLin Jinhan priv->nclocks)) {
113800565589SLin Jinhan printf("Can't read \"clocks\" property\n");
113900565589SLin Jinhan ret = -EINVAL;
114000565589SLin Jinhan goto exit;
114100565589SLin Jinhan }
114200565589SLin Jinhan
114300565589SLin Jinhan if (dev_read_prop(dev, "clock-frequency", &len)) {
114400565589SLin Jinhan priv->frequencies = malloc(len);
114500565589SLin Jinhan if (!priv->frequencies) {
114600565589SLin Jinhan ret = -ENOMEM;
114700565589SLin Jinhan goto exit;
114800565589SLin Jinhan }
114900565589SLin Jinhan priv->freq_nclocks = len / sizeof(u32);
115000565589SLin Jinhan if (dev_read_u32_array(dev, "clock-frequency", priv->frequencies,
115100565589SLin Jinhan priv->freq_nclocks)) {
115200565589SLin Jinhan printf("Can't read \"clock-frequency\" property\n");
115300565589SLin Jinhan ret = -EINVAL;
115400565589SLin Jinhan goto exit;
115500565589SLin Jinhan }
115600565589SLin Jinhan }
115700565589SLin Jinhan
115800565589SLin Jinhan return 0;
115900565589SLin Jinhan exit:
116000565589SLin Jinhan if (priv->clocks)
116100565589SLin Jinhan free(priv->clocks);
116200565589SLin Jinhan
116300565589SLin Jinhan if (priv->frequencies)
116400565589SLin Jinhan free(priv->frequencies);
116500565589SLin Jinhan
116600565589SLin Jinhan return ret;
116700565589SLin Jinhan }
116800565589SLin Jinhan
rk_crypto_do_enable_clk(struct udevice * dev,int enable)116900565589SLin Jinhan static int rk_crypto_do_enable_clk(struct udevice *dev, int enable)
117000565589SLin Jinhan {
117100565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
117200565589SLin Jinhan struct clk clk;
117300565589SLin Jinhan int i, ret;
117400565589SLin Jinhan
117500565589SLin Jinhan for (i = 0; i < priv->nclocks; i++) {
117600565589SLin Jinhan ret = clk_get_by_index(dev, i, &clk);
117700565589SLin Jinhan if (ret < 0) {
117800565589SLin Jinhan printf("Failed to get clk index %d, ret=%d\n", i, ret);
117900565589SLin Jinhan return ret;
118000565589SLin Jinhan }
118100565589SLin Jinhan
118200565589SLin Jinhan if (enable)
118300565589SLin Jinhan ret = clk_enable(&clk);
118400565589SLin Jinhan else
118500565589SLin Jinhan ret = clk_disable(&clk);
118600565589SLin Jinhan if (ret < 0 && ret != -ENOSYS) {
1187f84a40b4SLin Jinhan debug("Failed to enable(%d) clk(%ld): ret=%d\n",
118800565589SLin Jinhan enable, clk.id, ret);
118900565589SLin Jinhan return ret;
119000565589SLin Jinhan }
119100565589SLin Jinhan }
119200565589SLin Jinhan
119300565589SLin Jinhan return 0;
119400565589SLin Jinhan }
119500565589SLin Jinhan
rk_crypto_enable_clk(struct udevice * dev)119600565589SLin Jinhan static int rk_crypto_enable_clk(struct udevice *dev)
119700565589SLin Jinhan {
119836e17db4Stroy.lin struct rockchip_crypto_priv *priv = dev_get_priv(dev);
119936e17db4Stroy.lin
120036e17db4Stroy.lin crypto_base = priv->reg;
120136e17db4Stroy.lin
120200565589SLin Jinhan return rk_crypto_do_enable_clk(dev, 1);
120300565589SLin Jinhan }
120400565589SLin Jinhan
rk_crypto_disable_clk(struct udevice * dev)120500565589SLin Jinhan static int rk_crypto_disable_clk(struct udevice *dev)
120600565589SLin Jinhan {
120736e17db4Stroy.lin crypto_base = 0;
120836e17db4Stroy.lin
120900565589SLin Jinhan return rk_crypto_do_enable_clk(dev, 0);
121000565589SLin Jinhan }
121100565589SLin Jinhan
rk_crypto_set_clk(struct udevice * dev)121200565589SLin Jinhan static int rk_crypto_set_clk(struct udevice *dev)
121300565589SLin Jinhan {
121400565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
121500565589SLin Jinhan struct clk clk;
121600565589SLin Jinhan int i, ret;
121700565589SLin Jinhan
121800565589SLin Jinhan /* use standard "assigned-clock-rates" props */
121900565589SLin Jinhan if (dev_read_size(dev, "assigned-clock-rates") > 0)
122000565589SLin Jinhan return clk_set_defaults(dev);
122100565589SLin Jinhan
122200565589SLin Jinhan /* use "clock-frequency" props */
122300565589SLin Jinhan if (priv->freq_nclocks == 0)
122400565589SLin Jinhan return 0;
122500565589SLin Jinhan
122600565589SLin Jinhan for (i = 0; i < priv->freq_nclocks; i++) {
122700565589SLin Jinhan ret = clk_get_by_index(dev, i, &clk);
122800565589SLin Jinhan if (ret < 0) {
122900565589SLin Jinhan printf("Failed to get clk index %d, ret=%d\n", i, ret);
123000565589SLin Jinhan return ret;
123100565589SLin Jinhan }
123200565589SLin Jinhan ret = clk_set_rate(&clk, priv->frequencies[i]);
123300565589SLin Jinhan if (ret < 0) {
123400565589SLin Jinhan printf("%s: Failed to set clk(%ld): ret=%d\n",
123500565589SLin Jinhan __func__, clk.id, ret);
123600565589SLin Jinhan return ret;
123700565589SLin Jinhan }
123800565589SLin Jinhan }
123900565589SLin Jinhan
124000565589SLin Jinhan return 0;
124100565589SLin Jinhan }
124200565589SLin Jinhan
rockchip_crypto_probe(struct udevice * dev)124300565589SLin Jinhan static int rockchip_crypto_probe(struct udevice *dev)
124400565589SLin Jinhan {
124500565589SLin Jinhan struct rockchip_crypto_priv *priv = dev_get_priv(dev);
124600565589SLin Jinhan int ret = 0;
124700565589SLin Jinhan
124836e17db4Stroy.lin if (!priv->enabled)
124936e17db4Stroy.lin return 0;
125036e17db4Stroy.lin
125100565589SLin Jinhan ret = rk_crypto_set_clk(dev);
125200565589SLin Jinhan if (ret)
125300565589SLin Jinhan return ret;
125400565589SLin Jinhan
125500565589SLin Jinhan rk_crypto_enable_clk(dev);
125600565589SLin Jinhan
125700565589SLin Jinhan priv->hardware = rkce_hardware_alloc((void *)priv->reg);
125800565589SLin Jinhan
125900565589SLin Jinhan if (!priv->hardware) {
126000565589SLin Jinhan ret = -ENOMEM;
126100565589SLin Jinhan goto exit;
126200565589SLin Jinhan }
126300565589SLin Jinhan
126400565589SLin Jinhan priv->capability = rockchip_crypto_capability(dev);
126500565589SLin Jinhan exit:
126600565589SLin Jinhan rk_crypto_disable_clk(dev);
126700565589SLin Jinhan
126800565589SLin Jinhan return ret;
126900565589SLin Jinhan }
127000565589SLin Jinhan
127100565589SLin Jinhan static const struct udevice_id rockchip_crypto_ids[] = {
127200565589SLin Jinhan {
127300565589SLin Jinhan .compatible = "rockchip,crypto-ce",
127400565589SLin Jinhan },
127500565589SLin Jinhan { }
127600565589SLin Jinhan };
127700565589SLin Jinhan
127800565589SLin Jinhan U_BOOT_DRIVER(rockchip_crypto_ce) = {
127900565589SLin Jinhan .name = "rockchip_crypto_ce",
128000565589SLin Jinhan .id = UCLASS_CRYPTO,
128100565589SLin Jinhan .of_match = rockchip_crypto_ids,
128200565589SLin Jinhan .ops = &rockchip_crypto_ops,
128300565589SLin Jinhan .probe = rockchip_crypto_probe,
128400565589SLin Jinhan .ofdata_to_platdata = rockchip_crypto_ofdata_to_platdata,
128500565589SLin Jinhan .priv_auto_alloc_size = sizeof(struct rockchip_crypto_priv),
128600565589SLin Jinhan };
1287