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