18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Cryptographic API.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Driver for EIP97 SHA1/SHA2(HMAC) acceleration.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (c) 2016 Ryder Lee <ryder.lee@mediatek.com>
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Some ideas are from atmel-sha.c and omap-sham.c drivers.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <crypto/hmac.h>
138c2ecf20Sopenharmony_ci#include <crypto/sha.h>
148c2ecf20Sopenharmony_ci#include "mtk-platform.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci#define SHA_ALIGN_MSK		(sizeof(u32) - 1)
178c2ecf20Sopenharmony_ci#define SHA_QUEUE_SIZE		512
188c2ecf20Sopenharmony_ci#define SHA_BUF_SIZE		((u32)PAGE_SIZE)
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci#define SHA_OP_UPDATE		1
218c2ecf20Sopenharmony_ci#define SHA_OP_FINAL		2
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#define SHA_DATA_LEN_MSK	cpu_to_le32(GENMASK(16, 0))
248c2ecf20Sopenharmony_ci#define SHA_MAX_DIGEST_BUF_SIZE	32
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* SHA command token */
278c2ecf20Sopenharmony_ci#define SHA_CT_SIZE		5
288c2ecf20Sopenharmony_ci#define SHA_CT_CTRL_HDR		cpu_to_le32(0x02220000)
298c2ecf20Sopenharmony_ci#define SHA_CMD0		cpu_to_le32(0x03020000)
308c2ecf20Sopenharmony_ci#define SHA_CMD1		cpu_to_le32(0x21060000)
318c2ecf20Sopenharmony_ci#define SHA_CMD2		cpu_to_le32(0xe0e63802)
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/* SHA transform information */
348c2ecf20Sopenharmony_ci#define SHA_TFM_HASH		cpu_to_le32(0x2 << 0)
358c2ecf20Sopenharmony_ci#define SHA_TFM_SIZE(x)		cpu_to_le32((x) << 8)
368c2ecf20Sopenharmony_ci#define SHA_TFM_START		cpu_to_le32(0x1 << 4)
378c2ecf20Sopenharmony_ci#define SHA_TFM_CONTINUE	cpu_to_le32(0x1 << 5)
388c2ecf20Sopenharmony_ci#define SHA_TFM_HASH_STORE	cpu_to_le32(0x1 << 19)
398c2ecf20Sopenharmony_ci#define SHA_TFM_SHA1		cpu_to_le32(0x2 << 23)
408c2ecf20Sopenharmony_ci#define SHA_TFM_SHA256		cpu_to_le32(0x3 << 23)
418c2ecf20Sopenharmony_ci#define SHA_TFM_SHA224		cpu_to_le32(0x4 << 23)
428c2ecf20Sopenharmony_ci#define SHA_TFM_SHA512		cpu_to_le32(0x5 << 23)
438c2ecf20Sopenharmony_ci#define SHA_TFM_SHA384		cpu_to_le32(0x6 << 23)
448c2ecf20Sopenharmony_ci#define SHA_TFM_DIGEST(x)	cpu_to_le32(((x) & GENMASK(3, 0)) << 24)
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci/* SHA flags */
478c2ecf20Sopenharmony_ci#define SHA_FLAGS_BUSY		BIT(0)
488c2ecf20Sopenharmony_ci#define	SHA_FLAGS_FINAL		BIT(1)
498c2ecf20Sopenharmony_ci#define SHA_FLAGS_FINUP		BIT(2)
508c2ecf20Sopenharmony_ci#define SHA_FLAGS_SG		BIT(3)
518c2ecf20Sopenharmony_ci#define SHA_FLAGS_ALGO_MSK	GENMASK(8, 4)
528c2ecf20Sopenharmony_ci#define SHA_FLAGS_SHA1		BIT(4)
538c2ecf20Sopenharmony_ci#define SHA_FLAGS_SHA224	BIT(5)
548c2ecf20Sopenharmony_ci#define SHA_FLAGS_SHA256	BIT(6)
558c2ecf20Sopenharmony_ci#define SHA_FLAGS_SHA384	BIT(7)
568c2ecf20Sopenharmony_ci#define SHA_FLAGS_SHA512	BIT(8)
578c2ecf20Sopenharmony_ci#define SHA_FLAGS_HMAC		BIT(9)
588c2ecf20Sopenharmony_ci#define SHA_FLAGS_PAD		BIT(10)
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/**
618c2ecf20Sopenharmony_ci * mtk_sha_info - hardware information of AES
628c2ecf20Sopenharmony_ci * @cmd:	command token, hardware instruction
638c2ecf20Sopenharmony_ci * @tfm:	transform state of cipher algorithm.
648c2ecf20Sopenharmony_ci * @state:	contains keys and initial vectors.
658c2ecf20Sopenharmony_ci *
668c2ecf20Sopenharmony_ci */
678c2ecf20Sopenharmony_cistruct mtk_sha_info {
688c2ecf20Sopenharmony_ci	__le32 ctrl[2];
698c2ecf20Sopenharmony_ci	__le32 cmd[3];
708c2ecf20Sopenharmony_ci	__le32 tfm[2];
718c2ecf20Sopenharmony_ci	__le32 digest[SHA_MAX_DIGEST_BUF_SIZE];
728c2ecf20Sopenharmony_ci};
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistruct mtk_sha_reqctx {
758c2ecf20Sopenharmony_ci	struct mtk_sha_info info;
768c2ecf20Sopenharmony_ci	unsigned long flags;
778c2ecf20Sopenharmony_ci	unsigned long op;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	u64 digcnt;
808c2ecf20Sopenharmony_ci	size_t bufcnt;
818c2ecf20Sopenharmony_ci	dma_addr_t dma_addr;
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	__le32 ct_hdr;
848c2ecf20Sopenharmony_ci	u32 ct_size;
858c2ecf20Sopenharmony_ci	dma_addr_t ct_dma;
868c2ecf20Sopenharmony_ci	dma_addr_t tfm_dma;
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci	/* Walk state */
898c2ecf20Sopenharmony_ci	struct scatterlist *sg;
908c2ecf20Sopenharmony_ci	u32 offset;	/* Offset in current sg */
918c2ecf20Sopenharmony_ci	u32 total;	/* Total request */
928c2ecf20Sopenharmony_ci	size_t ds;
938c2ecf20Sopenharmony_ci	size_t bs;
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci	u8 *buffer;
968c2ecf20Sopenharmony_ci};
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistruct mtk_sha_hmac_ctx {
998c2ecf20Sopenharmony_ci	struct crypto_shash	*shash;
1008c2ecf20Sopenharmony_ci	u8 ipad[SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
1018c2ecf20Sopenharmony_ci	u8 opad[SHA512_BLOCK_SIZE] __aligned(sizeof(u32));
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistruct mtk_sha_ctx {
1058c2ecf20Sopenharmony_ci	struct mtk_cryp *cryp;
1068c2ecf20Sopenharmony_ci	unsigned long flags;
1078c2ecf20Sopenharmony_ci	u8 id;
1088c2ecf20Sopenharmony_ci	u8 buf[SHA_BUF_SIZE] __aligned(sizeof(u32));
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	struct mtk_sha_hmac_ctx	base[];
1118c2ecf20Sopenharmony_ci};
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_cistruct mtk_sha_drv {
1148c2ecf20Sopenharmony_ci	struct list_head dev_list;
1158c2ecf20Sopenharmony_ci	/* Device list lock */
1168c2ecf20Sopenharmony_ci	spinlock_t lock;
1178c2ecf20Sopenharmony_ci};
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_cistatic struct mtk_sha_drv mtk_sha = {
1208c2ecf20Sopenharmony_ci	.dev_list = LIST_HEAD_INIT(mtk_sha.dev_list),
1218c2ecf20Sopenharmony_ci	.lock = __SPIN_LOCK_UNLOCKED(mtk_sha.lock),
1228c2ecf20Sopenharmony_ci};
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_cistatic int mtk_sha_handle_queue(struct mtk_cryp *cryp, u8 id,
1258c2ecf20Sopenharmony_ci				struct ahash_request *req);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic inline u32 mtk_sha_read(struct mtk_cryp *cryp, u32 offset)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	return readl_relaxed(cryp->base + offset);
1308c2ecf20Sopenharmony_ci}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_cistatic inline void mtk_sha_write(struct mtk_cryp *cryp,
1338c2ecf20Sopenharmony_ci				 u32 offset, u32 value)
1348c2ecf20Sopenharmony_ci{
1358c2ecf20Sopenharmony_ci	writel_relaxed(value, cryp->base + offset);
1368c2ecf20Sopenharmony_ci}
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_cistatic inline void mtk_sha_ring_shift(struct mtk_ring *ring,
1398c2ecf20Sopenharmony_ci				      struct mtk_desc **cmd_curr,
1408c2ecf20Sopenharmony_ci				      struct mtk_desc **res_curr,
1418c2ecf20Sopenharmony_ci				      int *count)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	*cmd_curr = ring->cmd_next++;
1448c2ecf20Sopenharmony_ci	*res_curr = ring->res_next++;
1458c2ecf20Sopenharmony_ci	(*count)++;
1468c2ecf20Sopenharmony_ci
1478c2ecf20Sopenharmony_ci	if (ring->cmd_next == ring->cmd_base + MTK_DESC_NUM) {
1488c2ecf20Sopenharmony_ci		ring->cmd_next = ring->cmd_base;
1498c2ecf20Sopenharmony_ci		ring->res_next = ring->res_base;
1508c2ecf20Sopenharmony_ci	}
1518c2ecf20Sopenharmony_ci}
1528c2ecf20Sopenharmony_ci
1538c2ecf20Sopenharmony_cistatic struct mtk_cryp *mtk_sha_find_dev(struct mtk_sha_ctx *tctx)
1548c2ecf20Sopenharmony_ci{
1558c2ecf20Sopenharmony_ci	struct mtk_cryp *cryp = NULL;
1568c2ecf20Sopenharmony_ci	struct mtk_cryp *tmp;
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci	spin_lock_bh(&mtk_sha.lock);
1598c2ecf20Sopenharmony_ci	if (!tctx->cryp) {
1608c2ecf20Sopenharmony_ci		list_for_each_entry(tmp, &mtk_sha.dev_list, sha_list) {
1618c2ecf20Sopenharmony_ci			cryp = tmp;
1628c2ecf20Sopenharmony_ci			break;
1638c2ecf20Sopenharmony_ci		}
1648c2ecf20Sopenharmony_ci		tctx->cryp = cryp;
1658c2ecf20Sopenharmony_ci	} else {
1668c2ecf20Sopenharmony_ci		cryp = tctx->cryp;
1678c2ecf20Sopenharmony_ci	}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	/*
1708c2ecf20Sopenharmony_ci	 * Assign record id to tfm in round-robin fashion, and this
1718c2ecf20Sopenharmony_ci	 * will help tfm to bind  to corresponding descriptor rings.
1728c2ecf20Sopenharmony_ci	 */
1738c2ecf20Sopenharmony_ci	tctx->id = cryp->rec;
1748c2ecf20Sopenharmony_ci	cryp->rec = !cryp->rec;
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci	spin_unlock_bh(&mtk_sha.lock);
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ci	return cryp;
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic int mtk_sha_append_sg(struct mtk_sha_reqctx *ctx)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	size_t count;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	while ((ctx->bufcnt < SHA_BUF_SIZE) && ctx->total) {
1868c2ecf20Sopenharmony_ci		count = min(ctx->sg->length - ctx->offset, ctx->total);
1878c2ecf20Sopenharmony_ci		count = min(count, SHA_BUF_SIZE - ctx->bufcnt);
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci		if (count <= 0) {
1908c2ecf20Sopenharmony_ci			/*
1918c2ecf20Sopenharmony_ci			 * Check if count <= 0 because the buffer is full or
1928c2ecf20Sopenharmony_ci			 * because the sg length is 0. In the latest case,
1938c2ecf20Sopenharmony_ci			 * check if there is another sg in the list, a 0 length
1948c2ecf20Sopenharmony_ci			 * sg doesn't necessarily mean the end of the sg list.
1958c2ecf20Sopenharmony_ci			 */
1968c2ecf20Sopenharmony_ci			if ((ctx->sg->length == 0) && !sg_is_last(ctx->sg)) {
1978c2ecf20Sopenharmony_ci				ctx->sg = sg_next(ctx->sg);
1988c2ecf20Sopenharmony_ci				continue;
1998c2ecf20Sopenharmony_ci			} else {
2008c2ecf20Sopenharmony_ci				break;
2018c2ecf20Sopenharmony_ci			}
2028c2ecf20Sopenharmony_ci		}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci		scatterwalk_map_and_copy(ctx->buffer + ctx->bufcnt, ctx->sg,
2058c2ecf20Sopenharmony_ci					 ctx->offset, count, 0);
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci		ctx->bufcnt += count;
2088c2ecf20Sopenharmony_ci		ctx->offset += count;
2098c2ecf20Sopenharmony_ci		ctx->total -= count;
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci		if (ctx->offset == ctx->sg->length) {
2128c2ecf20Sopenharmony_ci			ctx->sg = sg_next(ctx->sg);
2138c2ecf20Sopenharmony_ci			if (ctx->sg)
2148c2ecf20Sopenharmony_ci				ctx->offset = 0;
2158c2ecf20Sopenharmony_ci			else
2168c2ecf20Sopenharmony_ci				ctx->total = 0;
2178c2ecf20Sopenharmony_ci		}
2188c2ecf20Sopenharmony_ci	}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci	return 0;
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci/*
2248c2ecf20Sopenharmony_ci * The purpose of this padding is to ensure that the padded message is a
2258c2ecf20Sopenharmony_ci * multiple of 512 bits (SHA1/SHA224/SHA256) or 1024 bits (SHA384/SHA512).
2268c2ecf20Sopenharmony_ci * The bit "1" is appended at the end of the message followed by
2278c2ecf20Sopenharmony_ci * "padlen-1" zero bits. Then a 64 bits block (SHA1/SHA224/SHA256) or
2288c2ecf20Sopenharmony_ci * 128 bits block (SHA384/SHA512) equals to the message length in bits
2298c2ecf20Sopenharmony_ci * is appended.
2308c2ecf20Sopenharmony_ci *
2318c2ecf20Sopenharmony_ci * For SHA1/SHA224/SHA256, padlen is calculated as followed:
2328c2ecf20Sopenharmony_ci *  - if message length < 56 bytes then padlen = 56 - message length
2338c2ecf20Sopenharmony_ci *  - else padlen = 64 + 56 - message length
2348c2ecf20Sopenharmony_ci *
2358c2ecf20Sopenharmony_ci * For SHA384/SHA512, padlen is calculated as followed:
2368c2ecf20Sopenharmony_ci *  - if message length < 112 bytes then padlen = 112 - message length
2378c2ecf20Sopenharmony_ci *  - else padlen = 128 + 112 - message length
2388c2ecf20Sopenharmony_ci */
2398c2ecf20Sopenharmony_cistatic void mtk_sha_fill_padding(struct mtk_sha_reqctx *ctx, u32 len)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	u32 index, padlen;
2428c2ecf20Sopenharmony_ci	__be64 bits[2];
2438c2ecf20Sopenharmony_ci	u64 size = ctx->digcnt;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	size += ctx->bufcnt;
2468c2ecf20Sopenharmony_ci	size += len;
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	bits[1] = cpu_to_be64(size << 3);
2498c2ecf20Sopenharmony_ci	bits[0] = cpu_to_be64(size >> 61);
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	switch (ctx->flags & SHA_FLAGS_ALGO_MSK) {
2528c2ecf20Sopenharmony_ci	case SHA_FLAGS_SHA384:
2538c2ecf20Sopenharmony_ci	case SHA_FLAGS_SHA512:
2548c2ecf20Sopenharmony_ci		index = ctx->bufcnt & 0x7f;
2558c2ecf20Sopenharmony_ci		padlen = (index < 112) ? (112 - index) : ((128 + 112) - index);
2568c2ecf20Sopenharmony_ci		*(ctx->buffer + ctx->bufcnt) = 0x80;
2578c2ecf20Sopenharmony_ci		memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1);
2588c2ecf20Sopenharmony_ci		memcpy(ctx->buffer + ctx->bufcnt + padlen, bits, 16);
2598c2ecf20Sopenharmony_ci		ctx->bufcnt += padlen + 16;
2608c2ecf20Sopenharmony_ci		ctx->flags |= SHA_FLAGS_PAD;
2618c2ecf20Sopenharmony_ci		break;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	default:
2648c2ecf20Sopenharmony_ci		index = ctx->bufcnt & 0x3f;
2658c2ecf20Sopenharmony_ci		padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
2668c2ecf20Sopenharmony_ci		*(ctx->buffer + ctx->bufcnt) = 0x80;
2678c2ecf20Sopenharmony_ci		memset(ctx->buffer + ctx->bufcnt + 1, 0, padlen - 1);
2688c2ecf20Sopenharmony_ci		memcpy(ctx->buffer + ctx->bufcnt + padlen, &bits[1], 8);
2698c2ecf20Sopenharmony_ci		ctx->bufcnt += padlen + 8;
2708c2ecf20Sopenharmony_ci		ctx->flags |= SHA_FLAGS_PAD;
2718c2ecf20Sopenharmony_ci		break;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci/* Initialize basic transform information of SHA */
2768c2ecf20Sopenharmony_cistatic void mtk_sha_info_init(struct mtk_sha_reqctx *ctx)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	struct mtk_sha_info *info = &ctx->info;
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	ctx->ct_hdr = SHA_CT_CTRL_HDR;
2818c2ecf20Sopenharmony_ci	ctx->ct_size = SHA_CT_SIZE;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	info->tfm[0] = SHA_TFM_HASH | SHA_TFM_SIZE(SIZE_IN_WORDS(ctx->ds));
2848c2ecf20Sopenharmony_ci
2858c2ecf20Sopenharmony_ci	switch (ctx->flags & SHA_FLAGS_ALGO_MSK) {
2868c2ecf20Sopenharmony_ci	case SHA_FLAGS_SHA1:
2878c2ecf20Sopenharmony_ci		info->tfm[0] |= SHA_TFM_SHA1;
2888c2ecf20Sopenharmony_ci		break;
2898c2ecf20Sopenharmony_ci	case SHA_FLAGS_SHA224:
2908c2ecf20Sopenharmony_ci		info->tfm[0] |= SHA_TFM_SHA224;
2918c2ecf20Sopenharmony_ci		break;
2928c2ecf20Sopenharmony_ci	case SHA_FLAGS_SHA256:
2938c2ecf20Sopenharmony_ci		info->tfm[0] |= SHA_TFM_SHA256;
2948c2ecf20Sopenharmony_ci		break;
2958c2ecf20Sopenharmony_ci	case SHA_FLAGS_SHA384:
2968c2ecf20Sopenharmony_ci		info->tfm[0] |= SHA_TFM_SHA384;
2978c2ecf20Sopenharmony_ci		break;
2988c2ecf20Sopenharmony_ci	case SHA_FLAGS_SHA512:
2998c2ecf20Sopenharmony_ci		info->tfm[0] |= SHA_TFM_SHA512;
3008c2ecf20Sopenharmony_ci		break;
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci	default:
3038c2ecf20Sopenharmony_ci		/* Should not happen... */
3048c2ecf20Sopenharmony_ci		return;
3058c2ecf20Sopenharmony_ci	}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci	info->tfm[1] = SHA_TFM_HASH_STORE;
3088c2ecf20Sopenharmony_ci	info->ctrl[0] = info->tfm[0] | SHA_TFM_CONTINUE | SHA_TFM_START;
3098c2ecf20Sopenharmony_ci	info->ctrl[1] = info->tfm[1];
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	info->cmd[0] = SHA_CMD0;
3128c2ecf20Sopenharmony_ci	info->cmd[1] = SHA_CMD1;
3138c2ecf20Sopenharmony_ci	info->cmd[2] = SHA_CMD2 | SHA_TFM_DIGEST(SIZE_IN_WORDS(ctx->ds));
3148c2ecf20Sopenharmony_ci}
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci/*
3178c2ecf20Sopenharmony_ci * Update input data length field of transform information and
3188c2ecf20Sopenharmony_ci * map it to DMA region.
3198c2ecf20Sopenharmony_ci */
3208c2ecf20Sopenharmony_cistatic int mtk_sha_info_update(struct mtk_cryp *cryp,
3218c2ecf20Sopenharmony_ci			       struct mtk_sha_rec *sha,
3228c2ecf20Sopenharmony_ci			       size_t len1, size_t len2)
3238c2ecf20Sopenharmony_ci{
3248c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
3258c2ecf20Sopenharmony_ci	struct mtk_sha_info *info = &ctx->info;
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	ctx->ct_hdr &= ~SHA_DATA_LEN_MSK;
3288c2ecf20Sopenharmony_ci	ctx->ct_hdr |= cpu_to_le32(len1 + len2);
3298c2ecf20Sopenharmony_ci	info->cmd[0] &= ~SHA_DATA_LEN_MSK;
3308c2ecf20Sopenharmony_ci	info->cmd[0] |= cpu_to_le32(len1 + len2);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	/* Setting SHA_TFM_START only for the first iteration */
3338c2ecf20Sopenharmony_ci	if (ctx->digcnt)
3348c2ecf20Sopenharmony_ci		info->ctrl[0] &= ~SHA_TFM_START;
3358c2ecf20Sopenharmony_ci
3368c2ecf20Sopenharmony_ci	ctx->digcnt += len1;
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci	ctx->ct_dma = dma_map_single(cryp->dev, info, sizeof(*info),
3398c2ecf20Sopenharmony_ci				     DMA_BIDIRECTIONAL);
3408c2ecf20Sopenharmony_ci	if (unlikely(dma_mapping_error(cryp->dev, ctx->ct_dma))) {
3418c2ecf20Sopenharmony_ci		dev_err(cryp->dev, "dma %zu bytes error\n", sizeof(*info));
3428c2ecf20Sopenharmony_ci		return -EINVAL;
3438c2ecf20Sopenharmony_ci	}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci	ctx->tfm_dma = ctx->ct_dma + sizeof(info->ctrl) + sizeof(info->cmd);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	return 0;
3488c2ecf20Sopenharmony_ci}
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci/*
3518c2ecf20Sopenharmony_ci * Because of hardware limitation, we must pre-calculate the inner
3528c2ecf20Sopenharmony_ci * and outer digest that need to be processed firstly by engine, then
3538c2ecf20Sopenharmony_ci * apply the result digest to the input message. These complex hashing
3548c2ecf20Sopenharmony_ci * procedures limits HMAC performance, so we use fallback SW encoding.
3558c2ecf20Sopenharmony_ci */
3568c2ecf20Sopenharmony_cistatic int mtk_sha_finish_hmac(struct ahash_request *req)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	struct mtk_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
3598c2ecf20Sopenharmony_ci	struct mtk_sha_hmac_ctx *bctx = tctx->base;
3608c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	SHASH_DESC_ON_STACK(shash, bctx->shash);
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	shash->tfm = bctx->shash;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	return crypto_shash_init(shash) ?:
3678c2ecf20Sopenharmony_ci	       crypto_shash_update(shash, bctx->opad, ctx->bs) ?:
3688c2ecf20Sopenharmony_ci	       crypto_shash_finup(shash, req->result, ctx->ds, req->result);
3698c2ecf20Sopenharmony_ci}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci/* Initialize request context */
3728c2ecf20Sopenharmony_cistatic int mtk_sha_init(struct ahash_request *req)
3738c2ecf20Sopenharmony_ci{
3748c2ecf20Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
3758c2ecf20Sopenharmony_ci	struct mtk_sha_ctx *tctx = crypto_ahash_ctx(tfm);
3768c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	ctx->flags = 0;
3798c2ecf20Sopenharmony_ci	ctx->ds = crypto_ahash_digestsize(tfm);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	switch (ctx->ds) {
3828c2ecf20Sopenharmony_ci	case SHA1_DIGEST_SIZE:
3838c2ecf20Sopenharmony_ci		ctx->flags |= SHA_FLAGS_SHA1;
3848c2ecf20Sopenharmony_ci		ctx->bs = SHA1_BLOCK_SIZE;
3858c2ecf20Sopenharmony_ci		break;
3868c2ecf20Sopenharmony_ci	case SHA224_DIGEST_SIZE:
3878c2ecf20Sopenharmony_ci		ctx->flags |= SHA_FLAGS_SHA224;
3888c2ecf20Sopenharmony_ci		ctx->bs = SHA224_BLOCK_SIZE;
3898c2ecf20Sopenharmony_ci		break;
3908c2ecf20Sopenharmony_ci	case SHA256_DIGEST_SIZE:
3918c2ecf20Sopenharmony_ci		ctx->flags |= SHA_FLAGS_SHA256;
3928c2ecf20Sopenharmony_ci		ctx->bs = SHA256_BLOCK_SIZE;
3938c2ecf20Sopenharmony_ci		break;
3948c2ecf20Sopenharmony_ci	case SHA384_DIGEST_SIZE:
3958c2ecf20Sopenharmony_ci		ctx->flags |= SHA_FLAGS_SHA384;
3968c2ecf20Sopenharmony_ci		ctx->bs = SHA384_BLOCK_SIZE;
3978c2ecf20Sopenharmony_ci		break;
3988c2ecf20Sopenharmony_ci	case SHA512_DIGEST_SIZE:
3998c2ecf20Sopenharmony_ci		ctx->flags |= SHA_FLAGS_SHA512;
4008c2ecf20Sopenharmony_ci		ctx->bs = SHA512_BLOCK_SIZE;
4018c2ecf20Sopenharmony_ci		break;
4028c2ecf20Sopenharmony_ci	default:
4038c2ecf20Sopenharmony_ci		return -EINVAL;
4048c2ecf20Sopenharmony_ci	}
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci	ctx->bufcnt = 0;
4078c2ecf20Sopenharmony_ci	ctx->digcnt = 0;
4088c2ecf20Sopenharmony_ci	ctx->buffer = tctx->buf;
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	if (tctx->flags & SHA_FLAGS_HMAC) {
4118c2ecf20Sopenharmony_ci		struct mtk_sha_hmac_ctx *bctx = tctx->base;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci		memcpy(ctx->buffer, bctx->ipad, ctx->bs);
4148c2ecf20Sopenharmony_ci		ctx->bufcnt = ctx->bs;
4158c2ecf20Sopenharmony_ci		ctx->flags |= SHA_FLAGS_HMAC;
4168c2ecf20Sopenharmony_ci	}
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	return 0;
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_cistatic int mtk_sha_xmit(struct mtk_cryp *cryp, struct mtk_sha_rec *sha,
4228c2ecf20Sopenharmony_ci			dma_addr_t addr1, size_t len1,
4238c2ecf20Sopenharmony_ci			dma_addr_t addr2, size_t len2)
4248c2ecf20Sopenharmony_ci{
4258c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
4268c2ecf20Sopenharmony_ci	struct mtk_ring *ring = cryp->ring[sha->id];
4278c2ecf20Sopenharmony_ci	struct mtk_desc *cmd, *res;
4288c2ecf20Sopenharmony_ci	int err, count = 0;
4298c2ecf20Sopenharmony_ci
4308c2ecf20Sopenharmony_ci	err = mtk_sha_info_update(cryp, sha, len1, len2);
4318c2ecf20Sopenharmony_ci	if (err)
4328c2ecf20Sopenharmony_ci		return err;
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	/* Fill in the command/result descriptors */
4358c2ecf20Sopenharmony_ci	mtk_sha_ring_shift(ring, &cmd, &res, &count);
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	res->hdr = MTK_DESC_FIRST | MTK_DESC_BUF_LEN(len1);
4388c2ecf20Sopenharmony_ci	cmd->hdr = MTK_DESC_FIRST | MTK_DESC_BUF_LEN(len1) |
4398c2ecf20Sopenharmony_ci		   MTK_DESC_CT_LEN(ctx->ct_size);
4408c2ecf20Sopenharmony_ci	cmd->buf = cpu_to_le32(addr1);
4418c2ecf20Sopenharmony_ci	cmd->ct = cpu_to_le32(ctx->ct_dma);
4428c2ecf20Sopenharmony_ci	cmd->ct_hdr = ctx->ct_hdr;
4438c2ecf20Sopenharmony_ci	cmd->tfm = cpu_to_le32(ctx->tfm_dma);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	if (len2) {
4468c2ecf20Sopenharmony_ci		mtk_sha_ring_shift(ring, &cmd, &res, &count);
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci		res->hdr = MTK_DESC_BUF_LEN(len2);
4498c2ecf20Sopenharmony_ci		cmd->hdr = MTK_DESC_BUF_LEN(len2);
4508c2ecf20Sopenharmony_ci		cmd->buf = cpu_to_le32(addr2);
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	cmd->hdr |= MTK_DESC_LAST;
4548c2ecf20Sopenharmony_ci	res->hdr |= MTK_DESC_LAST;
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	/*
4578c2ecf20Sopenharmony_ci	 * Make sure that all changes to the DMA ring are done before we
4588c2ecf20Sopenharmony_ci	 * start engine.
4598c2ecf20Sopenharmony_ci	 */
4608c2ecf20Sopenharmony_ci	wmb();
4618c2ecf20Sopenharmony_ci	/* Start DMA transfer */
4628c2ecf20Sopenharmony_ci	mtk_sha_write(cryp, RDR_PREP_COUNT(sha->id), MTK_DESC_CNT(count));
4638c2ecf20Sopenharmony_ci	mtk_sha_write(cryp, CDR_PREP_COUNT(sha->id), MTK_DESC_CNT(count));
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	return -EINPROGRESS;
4668c2ecf20Sopenharmony_ci}
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_cistatic int mtk_sha_dma_map(struct mtk_cryp *cryp,
4698c2ecf20Sopenharmony_ci			   struct mtk_sha_rec *sha,
4708c2ecf20Sopenharmony_ci			   struct mtk_sha_reqctx *ctx,
4718c2ecf20Sopenharmony_ci			   size_t count)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	ctx->dma_addr = dma_map_single(cryp->dev, ctx->buffer,
4748c2ecf20Sopenharmony_ci				       SHA_BUF_SIZE, DMA_TO_DEVICE);
4758c2ecf20Sopenharmony_ci	if (unlikely(dma_mapping_error(cryp->dev, ctx->dma_addr))) {
4768c2ecf20Sopenharmony_ci		dev_err(cryp->dev, "dma map error\n");
4778c2ecf20Sopenharmony_ci		return -EINVAL;
4788c2ecf20Sopenharmony_ci	}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	ctx->flags &= ~SHA_FLAGS_SG;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_ci	return mtk_sha_xmit(cryp, sha, ctx->dma_addr, count, 0, 0);
4838c2ecf20Sopenharmony_ci}
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_cistatic int mtk_sha_update_slow(struct mtk_cryp *cryp,
4868c2ecf20Sopenharmony_ci			       struct mtk_sha_rec *sha)
4878c2ecf20Sopenharmony_ci{
4888c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
4898c2ecf20Sopenharmony_ci	size_t count;
4908c2ecf20Sopenharmony_ci	u32 final;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	mtk_sha_append_sg(ctx);
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total;
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_ci	dev_dbg(cryp->dev, "slow: bufcnt: %zu\n", ctx->bufcnt);
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci	if (final) {
4998c2ecf20Sopenharmony_ci		sha->flags |= SHA_FLAGS_FINAL;
5008c2ecf20Sopenharmony_ci		mtk_sha_fill_padding(ctx, 0);
5018c2ecf20Sopenharmony_ci	}
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci	if (final || (ctx->bufcnt == SHA_BUF_SIZE && ctx->total)) {
5048c2ecf20Sopenharmony_ci		count = ctx->bufcnt;
5058c2ecf20Sopenharmony_ci		ctx->bufcnt = 0;
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci		return mtk_sha_dma_map(cryp, sha, ctx, count);
5088c2ecf20Sopenharmony_ci	}
5098c2ecf20Sopenharmony_ci	return 0;
5108c2ecf20Sopenharmony_ci}
5118c2ecf20Sopenharmony_ci
5128c2ecf20Sopenharmony_cistatic int mtk_sha_update_start(struct mtk_cryp *cryp,
5138c2ecf20Sopenharmony_ci				struct mtk_sha_rec *sha)
5148c2ecf20Sopenharmony_ci{
5158c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
5168c2ecf20Sopenharmony_ci	u32 len, final, tail;
5178c2ecf20Sopenharmony_ci	struct scatterlist *sg;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	if (!ctx->total)
5208c2ecf20Sopenharmony_ci		return 0;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	if (ctx->bufcnt || ctx->offset)
5238c2ecf20Sopenharmony_ci		return mtk_sha_update_slow(cryp, sha);
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_ci	sg = ctx->sg;
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci	if (!IS_ALIGNED(sg->offset, sizeof(u32)))
5288c2ecf20Sopenharmony_ci		return mtk_sha_update_slow(cryp, sha);
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	if (!sg_is_last(sg) && !IS_ALIGNED(sg->length, ctx->bs))
5318c2ecf20Sopenharmony_ci		/* size is not ctx->bs aligned */
5328c2ecf20Sopenharmony_ci		return mtk_sha_update_slow(cryp, sha);
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	len = min(ctx->total, sg->length);
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci	if (sg_is_last(sg)) {
5378c2ecf20Sopenharmony_ci		if (!(ctx->flags & SHA_FLAGS_FINUP)) {
5388c2ecf20Sopenharmony_ci			/* not last sg must be ctx->bs aligned */
5398c2ecf20Sopenharmony_ci			tail = len & (ctx->bs - 1);
5408c2ecf20Sopenharmony_ci			len -= tail;
5418c2ecf20Sopenharmony_ci		}
5428c2ecf20Sopenharmony_ci	}
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	ctx->total -= len;
5458c2ecf20Sopenharmony_ci	ctx->offset = len; /* offset where to start slow */
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	final = (ctx->flags & SHA_FLAGS_FINUP) && !ctx->total;
5488c2ecf20Sopenharmony_ci
5498c2ecf20Sopenharmony_ci	/* Add padding */
5508c2ecf20Sopenharmony_ci	if (final) {
5518c2ecf20Sopenharmony_ci		size_t count;
5528c2ecf20Sopenharmony_ci
5538c2ecf20Sopenharmony_ci		tail = len & (ctx->bs - 1);
5548c2ecf20Sopenharmony_ci		len -= tail;
5558c2ecf20Sopenharmony_ci		ctx->total += tail;
5568c2ecf20Sopenharmony_ci		ctx->offset = len; /* offset where to start slow */
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci		sg = ctx->sg;
5598c2ecf20Sopenharmony_ci		mtk_sha_append_sg(ctx);
5608c2ecf20Sopenharmony_ci		mtk_sha_fill_padding(ctx, len);
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci		ctx->dma_addr = dma_map_single(cryp->dev, ctx->buffer,
5638c2ecf20Sopenharmony_ci					       SHA_BUF_SIZE, DMA_TO_DEVICE);
5648c2ecf20Sopenharmony_ci		if (unlikely(dma_mapping_error(cryp->dev, ctx->dma_addr))) {
5658c2ecf20Sopenharmony_ci			dev_err(cryp->dev, "dma map bytes error\n");
5668c2ecf20Sopenharmony_ci			return -EINVAL;
5678c2ecf20Sopenharmony_ci		}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci		sha->flags |= SHA_FLAGS_FINAL;
5708c2ecf20Sopenharmony_ci		count = ctx->bufcnt;
5718c2ecf20Sopenharmony_ci		ctx->bufcnt = 0;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci		if (len == 0) {
5748c2ecf20Sopenharmony_ci			ctx->flags &= ~SHA_FLAGS_SG;
5758c2ecf20Sopenharmony_ci			return mtk_sha_xmit(cryp, sha, ctx->dma_addr,
5768c2ecf20Sopenharmony_ci					    count, 0, 0);
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci		} else {
5798c2ecf20Sopenharmony_ci			ctx->sg = sg;
5808c2ecf20Sopenharmony_ci			if (!dma_map_sg(cryp->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
5818c2ecf20Sopenharmony_ci				dev_err(cryp->dev, "dma_map_sg error\n");
5828c2ecf20Sopenharmony_ci				return -EINVAL;
5838c2ecf20Sopenharmony_ci			}
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci			ctx->flags |= SHA_FLAGS_SG;
5868c2ecf20Sopenharmony_ci			return mtk_sha_xmit(cryp, sha, sg_dma_address(ctx->sg),
5878c2ecf20Sopenharmony_ci					    len, ctx->dma_addr, count);
5888c2ecf20Sopenharmony_ci		}
5898c2ecf20Sopenharmony_ci	}
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	if (!dma_map_sg(cryp->dev, ctx->sg, 1, DMA_TO_DEVICE)) {
5928c2ecf20Sopenharmony_ci		dev_err(cryp->dev, "dma_map_sg  error\n");
5938c2ecf20Sopenharmony_ci		return -EINVAL;
5948c2ecf20Sopenharmony_ci	}
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	ctx->flags |= SHA_FLAGS_SG;
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_ci	return mtk_sha_xmit(cryp, sha, sg_dma_address(ctx->sg),
5998c2ecf20Sopenharmony_ci			    len, 0, 0);
6008c2ecf20Sopenharmony_ci}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_cistatic int mtk_sha_final_req(struct mtk_cryp *cryp,
6038c2ecf20Sopenharmony_ci			     struct mtk_sha_rec *sha)
6048c2ecf20Sopenharmony_ci{
6058c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
6068c2ecf20Sopenharmony_ci	size_t count;
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	mtk_sha_fill_padding(ctx, 0);
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	sha->flags |= SHA_FLAGS_FINAL;
6118c2ecf20Sopenharmony_ci	count = ctx->bufcnt;
6128c2ecf20Sopenharmony_ci	ctx->bufcnt = 0;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	return mtk_sha_dma_map(cryp, sha, ctx, count);
6158c2ecf20Sopenharmony_ci}
6168c2ecf20Sopenharmony_ci
6178c2ecf20Sopenharmony_ci/* Copy ready hash (+ finalize hmac) */
6188c2ecf20Sopenharmony_cistatic int mtk_sha_finish(struct ahash_request *req)
6198c2ecf20Sopenharmony_ci{
6208c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
6218c2ecf20Sopenharmony_ci	__le32 *digest = ctx->info.digest;
6228c2ecf20Sopenharmony_ci	u32 *result = (u32 *)req->result;
6238c2ecf20Sopenharmony_ci	int i;
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci	/* Get the hash from the digest buffer */
6268c2ecf20Sopenharmony_ci	for (i = 0; i < SIZE_IN_WORDS(ctx->ds); i++)
6278c2ecf20Sopenharmony_ci		result[i] = le32_to_cpu(digest[i]);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ci	if (ctx->flags & SHA_FLAGS_HMAC)
6308c2ecf20Sopenharmony_ci		return mtk_sha_finish_hmac(req);
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	return 0;
6338c2ecf20Sopenharmony_ci}
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_cistatic void mtk_sha_finish_req(struct mtk_cryp *cryp,
6368c2ecf20Sopenharmony_ci			       struct mtk_sha_rec *sha,
6378c2ecf20Sopenharmony_ci			       int err)
6388c2ecf20Sopenharmony_ci{
6398c2ecf20Sopenharmony_ci	if (likely(!err && (SHA_FLAGS_FINAL & sha->flags)))
6408c2ecf20Sopenharmony_ci		err = mtk_sha_finish(sha->req);
6418c2ecf20Sopenharmony_ci
6428c2ecf20Sopenharmony_ci	sha->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL);
6438c2ecf20Sopenharmony_ci
6448c2ecf20Sopenharmony_ci	sha->req->base.complete(&sha->req->base, err);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	/* Handle new request */
6478c2ecf20Sopenharmony_ci	tasklet_schedule(&sha->queue_task);
6488c2ecf20Sopenharmony_ci}
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_cistatic int mtk_sha_handle_queue(struct mtk_cryp *cryp, u8 id,
6518c2ecf20Sopenharmony_ci				struct ahash_request *req)
6528c2ecf20Sopenharmony_ci{
6538c2ecf20Sopenharmony_ci	struct mtk_sha_rec *sha = cryp->sha[id];
6548c2ecf20Sopenharmony_ci	struct crypto_async_request *async_req, *backlog;
6558c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx;
6568c2ecf20Sopenharmony_ci	unsigned long flags;
6578c2ecf20Sopenharmony_ci	int err = 0, ret = 0;
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci	spin_lock_irqsave(&sha->lock, flags);
6608c2ecf20Sopenharmony_ci	if (req)
6618c2ecf20Sopenharmony_ci		ret = ahash_enqueue_request(&sha->queue, req);
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	if (SHA_FLAGS_BUSY & sha->flags) {
6648c2ecf20Sopenharmony_ci		spin_unlock_irqrestore(&sha->lock, flags);
6658c2ecf20Sopenharmony_ci		return ret;
6668c2ecf20Sopenharmony_ci	}
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	backlog = crypto_get_backlog(&sha->queue);
6698c2ecf20Sopenharmony_ci	async_req = crypto_dequeue_request(&sha->queue);
6708c2ecf20Sopenharmony_ci	if (async_req)
6718c2ecf20Sopenharmony_ci		sha->flags |= SHA_FLAGS_BUSY;
6728c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&sha->lock, flags);
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	if (!async_req)
6758c2ecf20Sopenharmony_ci		return ret;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	if (backlog)
6788c2ecf20Sopenharmony_ci		backlog->complete(backlog, -EINPROGRESS);
6798c2ecf20Sopenharmony_ci
6808c2ecf20Sopenharmony_ci	req = ahash_request_cast(async_req);
6818c2ecf20Sopenharmony_ci	ctx = ahash_request_ctx(req);
6828c2ecf20Sopenharmony_ci
6838c2ecf20Sopenharmony_ci	sha->req = req;
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	mtk_sha_info_init(ctx);
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	if (ctx->op == SHA_OP_UPDATE) {
6888c2ecf20Sopenharmony_ci		err = mtk_sha_update_start(cryp, sha);
6898c2ecf20Sopenharmony_ci		if (err != -EINPROGRESS && (ctx->flags & SHA_FLAGS_FINUP))
6908c2ecf20Sopenharmony_ci			/* No final() after finup() */
6918c2ecf20Sopenharmony_ci			err = mtk_sha_final_req(cryp, sha);
6928c2ecf20Sopenharmony_ci	} else if (ctx->op == SHA_OP_FINAL) {
6938c2ecf20Sopenharmony_ci		err = mtk_sha_final_req(cryp, sha);
6948c2ecf20Sopenharmony_ci	}
6958c2ecf20Sopenharmony_ci
6968c2ecf20Sopenharmony_ci	if (unlikely(err != -EINPROGRESS))
6978c2ecf20Sopenharmony_ci		/* Task will not finish it, so do it here */
6988c2ecf20Sopenharmony_ci		mtk_sha_finish_req(cryp, sha, err);
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	return ret;
7018c2ecf20Sopenharmony_ci}
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_cistatic int mtk_sha_enqueue(struct ahash_request *req, u32 op)
7048c2ecf20Sopenharmony_ci{
7058c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
7068c2ecf20Sopenharmony_ci	struct mtk_sha_ctx *tctx = crypto_tfm_ctx(req->base.tfm);
7078c2ecf20Sopenharmony_ci
7088c2ecf20Sopenharmony_ci	ctx->op = op;
7098c2ecf20Sopenharmony_ci
7108c2ecf20Sopenharmony_ci	return mtk_sha_handle_queue(tctx->cryp, tctx->id, req);
7118c2ecf20Sopenharmony_ci}
7128c2ecf20Sopenharmony_ci
7138c2ecf20Sopenharmony_cistatic void mtk_sha_unmap(struct mtk_cryp *cryp, struct mtk_sha_rec *sha)
7148c2ecf20Sopenharmony_ci{
7158c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(sha->req);
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci	dma_unmap_single(cryp->dev, ctx->ct_dma, sizeof(ctx->info),
7188c2ecf20Sopenharmony_ci			 DMA_BIDIRECTIONAL);
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci	if (ctx->flags & SHA_FLAGS_SG) {
7218c2ecf20Sopenharmony_ci		dma_unmap_sg(cryp->dev, ctx->sg, 1, DMA_TO_DEVICE);
7228c2ecf20Sopenharmony_ci		if (ctx->sg->length == ctx->offset) {
7238c2ecf20Sopenharmony_ci			ctx->sg = sg_next(ctx->sg);
7248c2ecf20Sopenharmony_ci			if (ctx->sg)
7258c2ecf20Sopenharmony_ci				ctx->offset = 0;
7268c2ecf20Sopenharmony_ci		}
7278c2ecf20Sopenharmony_ci		if (ctx->flags & SHA_FLAGS_PAD) {
7288c2ecf20Sopenharmony_ci			dma_unmap_single(cryp->dev, ctx->dma_addr,
7298c2ecf20Sopenharmony_ci					 SHA_BUF_SIZE, DMA_TO_DEVICE);
7308c2ecf20Sopenharmony_ci		}
7318c2ecf20Sopenharmony_ci	} else
7328c2ecf20Sopenharmony_ci		dma_unmap_single(cryp->dev, ctx->dma_addr,
7338c2ecf20Sopenharmony_ci				 SHA_BUF_SIZE, DMA_TO_DEVICE);
7348c2ecf20Sopenharmony_ci}
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_cistatic void mtk_sha_complete(struct mtk_cryp *cryp,
7378c2ecf20Sopenharmony_ci			     struct mtk_sha_rec *sha)
7388c2ecf20Sopenharmony_ci{
7398c2ecf20Sopenharmony_ci	int err = 0;
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_ci	err = mtk_sha_update_start(cryp, sha);
7428c2ecf20Sopenharmony_ci	if (err != -EINPROGRESS)
7438c2ecf20Sopenharmony_ci		mtk_sha_finish_req(cryp, sha, err);
7448c2ecf20Sopenharmony_ci}
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_cistatic int mtk_sha_update(struct ahash_request *req)
7478c2ecf20Sopenharmony_ci{
7488c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
7498c2ecf20Sopenharmony_ci
7508c2ecf20Sopenharmony_ci	ctx->total = req->nbytes;
7518c2ecf20Sopenharmony_ci	ctx->sg = req->src;
7528c2ecf20Sopenharmony_ci	ctx->offset = 0;
7538c2ecf20Sopenharmony_ci
7548c2ecf20Sopenharmony_ci	if ((ctx->bufcnt + ctx->total < SHA_BUF_SIZE) &&
7558c2ecf20Sopenharmony_ci	    !(ctx->flags & SHA_FLAGS_FINUP))
7568c2ecf20Sopenharmony_ci		return mtk_sha_append_sg(ctx);
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci	return mtk_sha_enqueue(req, SHA_OP_UPDATE);
7598c2ecf20Sopenharmony_ci}
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_cistatic int mtk_sha_final(struct ahash_request *req)
7628c2ecf20Sopenharmony_ci{
7638c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci	ctx->flags |= SHA_FLAGS_FINUP;
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	if (ctx->flags & SHA_FLAGS_PAD)
7688c2ecf20Sopenharmony_ci		return mtk_sha_finish(req);
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_ci	return mtk_sha_enqueue(req, SHA_OP_FINAL);
7718c2ecf20Sopenharmony_ci}
7728c2ecf20Sopenharmony_ci
7738c2ecf20Sopenharmony_cistatic int mtk_sha_finup(struct ahash_request *req)
7748c2ecf20Sopenharmony_ci{
7758c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
7768c2ecf20Sopenharmony_ci	int err1, err2;
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_ci	ctx->flags |= SHA_FLAGS_FINUP;
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	err1 = mtk_sha_update(req);
7818c2ecf20Sopenharmony_ci	if (err1 == -EINPROGRESS ||
7828c2ecf20Sopenharmony_ci	    (err1 == -EBUSY && (ahash_request_flags(req) &
7838c2ecf20Sopenharmony_ci				CRYPTO_TFM_REQ_MAY_BACKLOG)))
7848c2ecf20Sopenharmony_ci		return err1;
7858c2ecf20Sopenharmony_ci	/*
7868c2ecf20Sopenharmony_ci	 * final() has to be always called to cleanup resources
7878c2ecf20Sopenharmony_ci	 * even if update() failed
7888c2ecf20Sopenharmony_ci	 */
7898c2ecf20Sopenharmony_ci	err2 = mtk_sha_final(req);
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci	return err1 ?: err2;
7928c2ecf20Sopenharmony_ci}
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_cistatic int mtk_sha_digest(struct ahash_request *req)
7958c2ecf20Sopenharmony_ci{
7968c2ecf20Sopenharmony_ci	return mtk_sha_init(req) ?: mtk_sha_finup(req);
7978c2ecf20Sopenharmony_ci}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_cistatic int mtk_sha_setkey(struct crypto_ahash *tfm, const u8 *key,
8008c2ecf20Sopenharmony_ci			  u32 keylen)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	struct mtk_sha_ctx *tctx = crypto_ahash_ctx(tfm);
8038c2ecf20Sopenharmony_ci	struct mtk_sha_hmac_ctx *bctx = tctx->base;
8048c2ecf20Sopenharmony_ci	size_t bs = crypto_shash_blocksize(bctx->shash);
8058c2ecf20Sopenharmony_ci	size_t ds = crypto_shash_digestsize(bctx->shash);
8068c2ecf20Sopenharmony_ci	int err, i;
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	if (keylen > bs) {
8098c2ecf20Sopenharmony_ci		err = crypto_shash_tfm_digest(bctx->shash, key, keylen,
8108c2ecf20Sopenharmony_ci					      bctx->ipad);
8118c2ecf20Sopenharmony_ci		if (err)
8128c2ecf20Sopenharmony_ci			return err;
8138c2ecf20Sopenharmony_ci		keylen = ds;
8148c2ecf20Sopenharmony_ci	} else {
8158c2ecf20Sopenharmony_ci		memcpy(bctx->ipad, key, keylen);
8168c2ecf20Sopenharmony_ci	}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	memset(bctx->ipad + keylen, 0, bs - keylen);
8198c2ecf20Sopenharmony_ci	memcpy(bctx->opad, bctx->ipad, bs);
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci	for (i = 0; i < bs; i++) {
8228c2ecf20Sopenharmony_ci		bctx->ipad[i] ^= HMAC_IPAD_VALUE;
8238c2ecf20Sopenharmony_ci		bctx->opad[i] ^= HMAC_OPAD_VALUE;
8248c2ecf20Sopenharmony_ci	}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	return 0;
8278c2ecf20Sopenharmony_ci}
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_cistatic int mtk_sha_export(struct ahash_request *req, void *out)
8308c2ecf20Sopenharmony_ci{
8318c2ecf20Sopenharmony_ci	const struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	memcpy(out, ctx, sizeof(*ctx));
8348c2ecf20Sopenharmony_ci	return 0;
8358c2ecf20Sopenharmony_ci}
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_cistatic int mtk_sha_import(struct ahash_request *req, const void *in)
8388c2ecf20Sopenharmony_ci{
8398c2ecf20Sopenharmony_ci	struct mtk_sha_reqctx *ctx = ahash_request_ctx(req);
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	memcpy(ctx, in, sizeof(*ctx));
8428c2ecf20Sopenharmony_ci	return 0;
8438c2ecf20Sopenharmony_ci}
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_cistatic int mtk_sha_cra_init_alg(struct crypto_tfm *tfm,
8468c2ecf20Sopenharmony_ci				const char *alg_base)
8478c2ecf20Sopenharmony_ci{
8488c2ecf20Sopenharmony_ci	struct mtk_sha_ctx *tctx = crypto_tfm_ctx(tfm);
8498c2ecf20Sopenharmony_ci	struct mtk_cryp *cryp = NULL;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	cryp = mtk_sha_find_dev(tctx);
8528c2ecf20Sopenharmony_ci	if (!cryp)
8538c2ecf20Sopenharmony_ci		return -ENODEV;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
8568c2ecf20Sopenharmony_ci				 sizeof(struct mtk_sha_reqctx));
8578c2ecf20Sopenharmony_ci
8588c2ecf20Sopenharmony_ci	if (alg_base) {
8598c2ecf20Sopenharmony_ci		struct mtk_sha_hmac_ctx *bctx = tctx->base;
8608c2ecf20Sopenharmony_ci
8618c2ecf20Sopenharmony_ci		tctx->flags |= SHA_FLAGS_HMAC;
8628c2ecf20Sopenharmony_ci		bctx->shash = crypto_alloc_shash(alg_base, 0,
8638c2ecf20Sopenharmony_ci					CRYPTO_ALG_NEED_FALLBACK);
8648c2ecf20Sopenharmony_ci		if (IS_ERR(bctx->shash)) {
8658c2ecf20Sopenharmony_ci			pr_err("base driver %s could not be loaded.\n",
8668c2ecf20Sopenharmony_ci			       alg_base);
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci			return PTR_ERR(bctx->shash);
8698c2ecf20Sopenharmony_ci		}
8708c2ecf20Sopenharmony_ci	}
8718c2ecf20Sopenharmony_ci	return 0;
8728c2ecf20Sopenharmony_ci}
8738c2ecf20Sopenharmony_ci
8748c2ecf20Sopenharmony_cistatic int mtk_sha_cra_init(struct crypto_tfm *tfm)
8758c2ecf20Sopenharmony_ci{
8768c2ecf20Sopenharmony_ci	return mtk_sha_cra_init_alg(tfm, NULL);
8778c2ecf20Sopenharmony_ci}
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_cistatic int mtk_sha_cra_sha1_init(struct crypto_tfm *tfm)
8808c2ecf20Sopenharmony_ci{
8818c2ecf20Sopenharmony_ci	return mtk_sha_cra_init_alg(tfm, "sha1");
8828c2ecf20Sopenharmony_ci}
8838c2ecf20Sopenharmony_ci
8848c2ecf20Sopenharmony_cistatic int mtk_sha_cra_sha224_init(struct crypto_tfm *tfm)
8858c2ecf20Sopenharmony_ci{
8868c2ecf20Sopenharmony_ci	return mtk_sha_cra_init_alg(tfm, "sha224");
8878c2ecf20Sopenharmony_ci}
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_cistatic int mtk_sha_cra_sha256_init(struct crypto_tfm *tfm)
8908c2ecf20Sopenharmony_ci{
8918c2ecf20Sopenharmony_ci	return mtk_sha_cra_init_alg(tfm, "sha256");
8928c2ecf20Sopenharmony_ci}
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_cistatic int mtk_sha_cra_sha384_init(struct crypto_tfm *tfm)
8958c2ecf20Sopenharmony_ci{
8968c2ecf20Sopenharmony_ci	return mtk_sha_cra_init_alg(tfm, "sha384");
8978c2ecf20Sopenharmony_ci}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_cistatic int mtk_sha_cra_sha512_init(struct crypto_tfm *tfm)
9008c2ecf20Sopenharmony_ci{
9018c2ecf20Sopenharmony_ci	return mtk_sha_cra_init_alg(tfm, "sha512");
9028c2ecf20Sopenharmony_ci}
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_cistatic void mtk_sha_cra_exit(struct crypto_tfm *tfm)
9058c2ecf20Sopenharmony_ci{
9068c2ecf20Sopenharmony_ci	struct mtk_sha_ctx *tctx = crypto_tfm_ctx(tfm);
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	if (tctx->flags & SHA_FLAGS_HMAC) {
9098c2ecf20Sopenharmony_ci		struct mtk_sha_hmac_ctx *bctx = tctx->base;
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_ci		crypto_free_shash(bctx->shash);
9128c2ecf20Sopenharmony_ci	}
9138c2ecf20Sopenharmony_ci}
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_cistatic struct ahash_alg algs_sha1_sha224_sha256[] = {
9168c2ecf20Sopenharmony_ci{
9178c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
9188c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
9198c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
9208c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
9218c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
9228c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
9238c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
9248c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA1_DIGEST_SIZE,
9258c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
9268c2ecf20Sopenharmony_ci	.halg.base	= {
9278c2ecf20Sopenharmony_ci		.cra_name		= "sha1",
9288c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-sha1",
9298c2ecf20Sopenharmony_ci		.cra_priority		= 400,
9308c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC,
9318c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA1_BLOCK_SIZE,
9328c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx),
9338c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
9348c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
9358c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_init,
9368c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
9378c2ecf20Sopenharmony_ci	}
9388c2ecf20Sopenharmony_ci},
9398c2ecf20Sopenharmony_ci{
9408c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
9418c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
9428c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
9438c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
9448c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
9458c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
9468c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
9478c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA224_DIGEST_SIZE,
9488c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
9498c2ecf20Sopenharmony_ci	.halg.base	= {
9508c2ecf20Sopenharmony_ci		.cra_name		= "sha224",
9518c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-sha224",
9528c2ecf20Sopenharmony_ci		.cra_priority		= 400,
9538c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC,
9548c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA224_BLOCK_SIZE,
9558c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx),
9568c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
9578c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
9588c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_init,
9598c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
9608c2ecf20Sopenharmony_ci	}
9618c2ecf20Sopenharmony_ci},
9628c2ecf20Sopenharmony_ci{
9638c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
9648c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
9658c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
9668c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
9678c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
9688c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
9698c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
9708c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA256_DIGEST_SIZE,
9718c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
9728c2ecf20Sopenharmony_ci	.halg.base	= {
9738c2ecf20Sopenharmony_ci		.cra_name		= "sha256",
9748c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-sha256",
9758c2ecf20Sopenharmony_ci		.cra_priority		= 400,
9768c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC,
9778c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA256_BLOCK_SIZE,
9788c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx),
9798c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
9808c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
9818c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_init,
9828c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
9838c2ecf20Sopenharmony_ci	}
9848c2ecf20Sopenharmony_ci},
9858c2ecf20Sopenharmony_ci{
9868c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
9878c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
9888c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
9898c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
9908c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
9918c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
9928c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
9938c2ecf20Sopenharmony_ci	.setkey		= mtk_sha_setkey,
9948c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA1_DIGEST_SIZE,
9958c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
9968c2ecf20Sopenharmony_ci	.halg.base	= {
9978c2ecf20Sopenharmony_ci		.cra_name		= "hmac(sha1)",
9988c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-hmac-sha1",
9998c2ecf20Sopenharmony_ci		.cra_priority		= 400,
10008c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC |
10018c2ecf20Sopenharmony_ci					  CRYPTO_ALG_NEED_FALLBACK,
10028c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA1_BLOCK_SIZE,
10038c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx) +
10048c2ecf20Sopenharmony_ci					sizeof(struct mtk_sha_hmac_ctx),
10058c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
10068c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
10078c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_sha1_init,
10088c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
10098c2ecf20Sopenharmony_ci	}
10108c2ecf20Sopenharmony_ci},
10118c2ecf20Sopenharmony_ci{
10128c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
10138c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
10148c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
10158c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
10168c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
10178c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
10188c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
10198c2ecf20Sopenharmony_ci	.setkey		= mtk_sha_setkey,
10208c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA224_DIGEST_SIZE,
10218c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
10228c2ecf20Sopenharmony_ci	.halg.base	= {
10238c2ecf20Sopenharmony_ci		.cra_name		= "hmac(sha224)",
10248c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-hmac-sha224",
10258c2ecf20Sopenharmony_ci		.cra_priority		= 400,
10268c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC |
10278c2ecf20Sopenharmony_ci					  CRYPTO_ALG_NEED_FALLBACK,
10288c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA224_BLOCK_SIZE,
10298c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx) +
10308c2ecf20Sopenharmony_ci					sizeof(struct mtk_sha_hmac_ctx),
10318c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
10328c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
10338c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_sha224_init,
10348c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
10358c2ecf20Sopenharmony_ci	}
10368c2ecf20Sopenharmony_ci},
10378c2ecf20Sopenharmony_ci{
10388c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
10398c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
10408c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
10418c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
10428c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
10438c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
10448c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
10458c2ecf20Sopenharmony_ci	.setkey		= mtk_sha_setkey,
10468c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA256_DIGEST_SIZE,
10478c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
10488c2ecf20Sopenharmony_ci	.halg.base	= {
10498c2ecf20Sopenharmony_ci		.cra_name		= "hmac(sha256)",
10508c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-hmac-sha256",
10518c2ecf20Sopenharmony_ci		.cra_priority		= 400,
10528c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC |
10538c2ecf20Sopenharmony_ci					  CRYPTO_ALG_NEED_FALLBACK,
10548c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA256_BLOCK_SIZE,
10558c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx) +
10568c2ecf20Sopenharmony_ci					sizeof(struct mtk_sha_hmac_ctx),
10578c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
10588c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
10598c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_sha256_init,
10608c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
10618c2ecf20Sopenharmony_ci	}
10628c2ecf20Sopenharmony_ci},
10638c2ecf20Sopenharmony_ci};
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_cistatic struct ahash_alg algs_sha384_sha512[] = {
10668c2ecf20Sopenharmony_ci{
10678c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
10688c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
10698c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
10708c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
10718c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
10728c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
10738c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
10748c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA384_DIGEST_SIZE,
10758c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
10768c2ecf20Sopenharmony_ci	.halg.base	= {
10778c2ecf20Sopenharmony_ci		.cra_name		= "sha384",
10788c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-sha384",
10798c2ecf20Sopenharmony_ci		.cra_priority		= 400,
10808c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC,
10818c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA384_BLOCK_SIZE,
10828c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx),
10838c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
10848c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
10858c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_init,
10868c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
10878c2ecf20Sopenharmony_ci	}
10888c2ecf20Sopenharmony_ci},
10898c2ecf20Sopenharmony_ci{
10908c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
10918c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
10928c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
10938c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
10948c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
10958c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
10968c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
10978c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA512_DIGEST_SIZE,
10988c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
10998c2ecf20Sopenharmony_ci	.halg.base	= {
11008c2ecf20Sopenharmony_ci		.cra_name		= "sha512",
11018c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-sha512",
11028c2ecf20Sopenharmony_ci		.cra_priority		= 400,
11038c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC,
11048c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA512_BLOCK_SIZE,
11058c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx),
11068c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
11078c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
11088c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_init,
11098c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
11108c2ecf20Sopenharmony_ci	}
11118c2ecf20Sopenharmony_ci},
11128c2ecf20Sopenharmony_ci{
11138c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
11148c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
11158c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
11168c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
11178c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
11188c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
11198c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
11208c2ecf20Sopenharmony_ci	.setkey		= mtk_sha_setkey,
11218c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA384_DIGEST_SIZE,
11228c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
11238c2ecf20Sopenharmony_ci	.halg.base	= {
11248c2ecf20Sopenharmony_ci		.cra_name		= "hmac(sha384)",
11258c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-hmac-sha384",
11268c2ecf20Sopenharmony_ci		.cra_priority		= 400,
11278c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC |
11288c2ecf20Sopenharmony_ci					  CRYPTO_ALG_NEED_FALLBACK,
11298c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA384_BLOCK_SIZE,
11308c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx) +
11318c2ecf20Sopenharmony_ci					sizeof(struct mtk_sha_hmac_ctx),
11328c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
11338c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
11348c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_sha384_init,
11358c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
11368c2ecf20Sopenharmony_ci	}
11378c2ecf20Sopenharmony_ci},
11388c2ecf20Sopenharmony_ci{
11398c2ecf20Sopenharmony_ci	.init		= mtk_sha_init,
11408c2ecf20Sopenharmony_ci	.update		= mtk_sha_update,
11418c2ecf20Sopenharmony_ci	.final		= mtk_sha_final,
11428c2ecf20Sopenharmony_ci	.finup		= mtk_sha_finup,
11438c2ecf20Sopenharmony_ci	.digest		= mtk_sha_digest,
11448c2ecf20Sopenharmony_ci	.export		= mtk_sha_export,
11458c2ecf20Sopenharmony_ci	.import		= mtk_sha_import,
11468c2ecf20Sopenharmony_ci	.setkey		= mtk_sha_setkey,
11478c2ecf20Sopenharmony_ci	.halg.digestsize	= SHA512_DIGEST_SIZE,
11488c2ecf20Sopenharmony_ci	.halg.statesize = sizeof(struct mtk_sha_reqctx),
11498c2ecf20Sopenharmony_ci	.halg.base	= {
11508c2ecf20Sopenharmony_ci		.cra_name		= "hmac(sha512)",
11518c2ecf20Sopenharmony_ci		.cra_driver_name	= "mtk-hmac-sha512",
11528c2ecf20Sopenharmony_ci		.cra_priority		= 400,
11538c2ecf20Sopenharmony_ci		.cra_flags		= CRYPTO_ALG_ASYNC |
11548c2ecf20Sopenharmony_ci					  CRYPTO_ALG_NEED_FALLBACK,
11558c2ecf20Sopenharmony_ci		.cra_blocksize		= SHA512_BLOCK_SIZE,
11568c2ecf20Sopenharmony_ci		.cra_ctxsize		= sizeof(struct mtk_sha_ctx) +
11578c2ecf20Sopenharmony_ci					sizeof(struct mtk_sha_hmac_ctx),
11588c2ecf20Sopenharmony_ci		.cra_alignmask		= SHA_ALIGN_MSK,
11598c2ecf20Sopenharmony_ci		.cra_module		= THIS_MODULE,
11608c2ecf20Sopenharmony_ci		.cra_init		= mtk_sha_cra_sha512_init,
11618c2ecf20Sopenharmony_ci		.cra_exit		= mtk_sha_cra_exit,
11628c2ecf20Sopenharmony_ci	}
11638c2ecf20Sopenharmony_ci},
11648c2ecf20Sopenharmony_ci};
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_cistatic void mtk_sha_queue_task(unsigned long data)
11678c2ecf20Sopenharmony_ci{
11688c2ecf20Sopenharmony_ci	struct mtk_sha_rec *sha = (struct mtk_sha_rec *)data;
11698c2ecf20Sopenharmony_ci
11708c2ecf20Sopenharmony_ci	mtk_sha_handle_queue(sha->cryp, sha->id - MTK_RING2, NULL);
11718c2ecf20Sopenharmony_ci}
11728c2ecf20Sopenharmony_ci
11738c2ecf20Sopenharmony_cistatic void mtk_sha_done_task(unsigned long data)
11748c2ecf20Sopenharmony_ci{
11758c2ecf20Sopenharmony_ci	struct mtk_sha_rec *sha = (struct mtk_sha_rec *)data;
11768c2ecf20Sopenharmony_ci	struct mtk_cryp *cryp = sha->cryp;
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_ci	mtk_sha_unmap(cryp, sha);
11798c2ecf20Sopenharmony_ci	mtk_sha_complete(cryp, sha);
11808c2ecf20Sopenharmony_ci}
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_cistatic irqreturn_t mtk_sha_irq(int irq, void *dev_id)
11838c2ecf20Sopenharmony_ci{
11848c2ecf20Sopenharmony_ci	struct mtk_sha_rec *sha = (struct mtk_sha_rec *)dev_id;
11858c2ecf20Sopenharmony_ci	struct mtk_cryp *cryp = sha->cryp;
11868c2ecf20Sopenharmony_ci	u32 val = mtk_sha_read(cryp, RDR_STAT(sha->id));
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	mtk_sha_write(cryp, RDR_STAT(sha->id), val);
11898c2ecf20Sopenharmony_ci
11908c2ecf20Sopenharmony_ci	if (likely((SHA_FLAGS_BUSY & sha->flags))) {
11918c2ecf20Sopenharmony_ci		mtk_sha_write(cryp, RDR_PROC_COUNT(sha->id), MTK_CNT_RST);
11928c2ecf20Sopenharmony_ci		mtk_sha_write(cryp, RDR_THRESH(sha->id),
11938c2ecf20Sopenharmony_ci			      MTK_RDR_PROC_THRESH | MTK_RDR_PROC_MODE);
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci		tasklet_schedule(&sha->done_task);
11968c2ecf20Sopenharmony_ci	} else {
11978c2ecf20Sopenharmony_ci		dev_warn(cryp->dev, "SHA interrupt when no active requests.\n");
11988c2ecf20Sopenharmony_ci	}
11998c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
12008c2ecf20Sopenharmony_ci}
12018c2ecf20Sopenharmony_ci
12028c2ecf20Sopenharmony_ci/*
12038c2ecf20Sopenharmony_ci * The purpose of two SHA records is used to get extra performance.
12048c2ecf20Sopenharmony_ci * It is similar to mtk_aes_record_init().
12058c2ecf20Sopenharmony_ci */
12068c2ecf20Sopenharmony_cistatic int mtk_sha_record_init(struct mtk_cryp *cryp)
12078c2ecf20Sopenharmony_ci{
12088c2ecf20Sopenharmony_ci	struct mtk_sha_rec **sha = cryp->sha;
12098c2ecf20Sopenharmony_ci	int i, err = -ENOMEM;
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_ci	for (i = 0; i < MTK_REC_NUM; i++) {
12128c2ecf20Sopenharmony_ci		sha[i] = kzalloc(sizeof(**sha), GFP_KERNEL);
12138c2ecf20Sopenharmony_ci		if (!sha[i])
12148c2ecf20Sopenharmony_ci			goto err_cleanup;
12158c2ecf20Sopenharmony_ci
12168c2ecf20Sopenharmony_ci		sha[i]->cryp = cryp;
12178c2ecf20Sopenharmony_ci
12188c2ecf20Sopenharmony_ci		spin_lock_init(&sha[i]->lock);
12198c2ecf20Sopenharmony_ci		crypto_init_queue(&sha[i]->queue, SHA_QUEUE_SIZE);
12208c2ecf20Sopenharmony_ci
12218c2ecf20Sopenharmony_ci		tasklet_init(&sha[i]->queue_task, mtk_sha_queue_task,
12228c2ecf20Sopenharmony_ci			     (unsigned long)sha[i]);
12238c2ecf20Sopenharmony_ci		tasklet_init(&sha[i]->done_task, mtk_sha_done_task,
12248c2ecf20Sopenharmony_ci			     (unsigned long)sha[i]);
12258c2ecf20Sopenharmony_ci	}
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	/* Link to ring2 and ring3 respectively */
12288c2ecf20Sopenharmony_ci	sha[0]->id = MTK_RING2;
12298c2ecf20Sopenharmony_ci	sha[1]->id = MTK_RING3;
12308c2ecf20Sopenharmony_ci
12318c2ecf20Sopenharmony_ci	cryp->rec = 1;
12328c2ecf20Sopenharmony_ci
12338c2ecf20Sopenharmony_ci	return 0;
12348c2ecf20Sopenharmony_ci
12358c2ecf20Sopenharmony_cierr_cleanup:
12368c2ecf20Sopenharmony_ci	for (; i--; )
12378c2ecf20Sopenharmony_ci		kfree(sha[i]);
12388c2ecf20Sopenharmony_ci	return err;
12398c2ecf20Sopenharmony_ci}
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_cistatic void mtk_sha_record_free(struct mtk_cryp *cryp)
12428c2ecf20Sopenharmony_ci{
12438c2ecf20Sopenharmony_ci	int i;
12448c2ecf20Sopenharmony_ci
12458c2ecf20Sopenharmony_ci	for (i = 0; i < MTK_REC_NUM; i++) {
12468c2ecf20Sopenharmony_ci		tasklet_kill(&cryp->sha[i]->done_task);
12478c2ecf20Sopenharmony_ci		tasklet_kill(&cryp->sha[i]->queue_task);
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci		kfree(cryp->sha[i]);
12508c2ecf20Sopenharmony_ci	}
12518c2ecf20Sopenharmony_ci}
12528c2ecf20Sopenharmony_ci
12538c2ecf20Sopenharmony_cistatic void mtk_sha_unregister_algs(void)
12548c2ecf20Sopenharmony_ci{
12558c2ecf20Sopenharmony_ci	int i;
12568c2ecf20Sopenharmony_ci
12578c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(algs_sha1_sha224_sha256); i++)
12588c2ecf20Sopenharmony_ci		crypto_unregister_ahash(&algs_sha1_sha224_sha256[i]);
12598c2ecf20Sopenharmony_ci
12608c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(algs_sha384_sha512); i++)
12618c2ecf20Sopenharmony_ci		crypto_unregister_ahash(&algs_sha384_sha512[i]);
12628c2ecf20Sopenharmony_ci}
12638c2ecf20Sopenharmony_ci
12648c2ecf20Sopenharmony_cistatic int mtk_sha_register_algs(void)
12658c2ecf20Sopenharmony_ci{
12668c2ecf20Sopenharmony_ci	int err, i;
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(algs_sha1_sha224_sha256); i++) {
12698c2ecf20Sopenharmony_ci		err = crypto_register_ahash(&algs_sha1_sha224_sha256[i]);
12708c2ecf20Sopenharmony_ci		if (err)
12718c2ecf20Sopenharmony_ci			goto err_sha_224_256_algs;
12728c2ecf20Sopenharmony_ci	}
12738c2ecf20Sopenharmony_ci
12748c2ecf20Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(algs_sha384_sha512); i++) {
12758c2ecf20Sopenharmony_ci		err = crypto_register_ahash(&algs_sha384_sha512[i]);
12768c2ecf20Sopenharmony_ci		if (err)
12778c2ecf20Sopenharmony_ci			goto err_sha_384_512_algs;
12788c2ecf20Sopenharmony_ci	}
12798c2ecf20Sopenharmony_ci
12808c2ecf20Sopenharmony_ci	return 0;
12818c2ecf20Sopenharmony_ci
12828c2ecf20Sopenharmony_cierr_sha_384_512_algs:
12838c2ecf20Sopenharmony_ci	for (; i--; )
12848c2ecf20Sopenharmony_ci		crypto_unregister_ahash(&algs_sha384_sha512[i]);
12858c2ecf20Sopenharmony_ci	i = ARRAY_SIZE(algs_sha1_sha224_sha256);
12868c2ecf20Sopenharmony_cierr_sha_224_256_algs:
12878c2ecf20Sopenharmony_ci	for (; i--; )
12888c2ecf20Sopenharmony_ci		crypto_unregister_ahash(&algs_sha1_sha224_sha256[i]);
12898c2ecf20Sopenharmony_ci
12908c2ecf20Sopenharmony_ci	return err;
12918c2ecf20Sopenharmony_ci}
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_ciint mtk_hash_alg_register(struct mtk_cryp *cryp)
12948c2ecf20Sopenharmony_ci{
12958c2ecf20Sopenharmony_ci	int err;
12968c2ecf20Sopenharmony_ci
12978c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&cryp->sha_list);
12988c2ecf20Sopenharmony_ci
12998c2ecf20Sopenharmony_ci	/* Initialize two hash records */
13008c2ecf20Sopenharmony_ci	err = mtk_sha_record_init(cryp);
13018c2ecf20Sopenharmony_ci	if (err)
13028c2ecf20Sopenharmony_ci		goto err_record;
13038c2ecf20Sopenharmony_ci
13048c2ecf20Sopenharmony_ci	err = devm_request_irq(cryp->dev, cryp->irq[MTK_RING2], mtk_sha_irq,
13058c2ecf20Sopenharmony_ci			       0, "mtk-sha", cryp->sha[0]);
13068c2ecf20Sopenharmony_ci	if (err) {
13078c2ecf20Sopenharmony_ci		dev_err(cryp->dev, "unable to request sha irq0.\n");
13088c2ecf20Sopenharmony_ci		goto err_res;
13098c2ecf20Sopenharmony_ci	}
13108c2ecf20Sopenharmony_ci
13118c2ecf20Sopenharmony_ci	err = devm_request_irq(cryp->dev, cryp->irq[MTK_RING3], mtk_sha_irq,
13128c2ecf20Sopenharmony_ci			       0, "mtk-sha", cryp->sha[1]);
13138c2ecf20Sopenharmony_ci	if (err) {
13148c2ecf20Sopenharmony_ci		dev_err(cryp->dev, "unable to request sha irq1.\n");
13158c2ecf20Sopenharmony_ci		goto err_res;
13168c2ecf20Sopenharmony_ci	}
13178c2ecf20Sopenharmony_ci
13188c2ecf20Sopenharmony_ci	/* Enable ring2 and ring3 interrupt for hash */
13198c2ecf20Sopenharmony_ci	mtk_sha_write(cryp, AIC_ENABLE_SET(MTK_RING2), MTK_IRQ_RDR2);
13208c2ecf20Sopenharmony_ci	mtk_sha_write(cryp, AIC_ENABLE_SET(MTK_RING3), MTK_IRQ_RDR3);
13218c2ecf20Sopenharmony_ci
13228c2ecf20Sopenharmony_ci	spin_lock(&mtk_sha.lock);
13238c2ecf20Sopenharmony_ci	list_add_tail(&cryp->sha_list, &mtk_sha.dev_list);
13248c2ecf20Sopenharmony_ci	spin_unlock(&mtk_sha.lock);
13258c2ecf20Sopenharmony_ci
13268c2ecf20Sopenharmony_ci	err = mtk_sha_register_algs();
13278c2ecf20Sopenharmony_ci	if (err)
13288c2ecf20Sopenharmony_ci		goto err_algs;
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	return 0;
13318c2ecf20Sopenharmony_ci
13328c2ecf20Sopenharmony_cierr_algs:
13338c2ecf20Sopenharmony_ci	spin_lock(&mtk_sha.lock);
13348c2ecf20Sopenharmony_ci	list_del(&cryp->sha_list);
13358c2ecf20Sopenharmony_ci	spin_unlock(&mtk_sha.lock);
13368c2ecf20Sopenharmony_cierr_res:
13378c2ecf20Sopenharmony_ci	mtk_sha_record_free(cryp);
13388c2ecf20Sopenharmony_cierr_record:
13398c2ecf20Sopenharmony_ci
13408c2ecf20Sopenharmony_ci	dev_err(cryp->dev, "mtk-sha initialization failed.\n");
13418c2ecf20Sopenharmony_ci	return err;
13428c2ecf20Sopenharmony_ci}
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_civoid mtk_hash_alg_release(struct mtk_cryp *cryp)
13458c2ecf20Sopenharmony_ci{
13468c2ecf20Sopenharmony_ci	spin_lock(&mtk_sha.lock);
13478c2ecf20Sopenharmony_ci	list_del(&cryp->sha_list);
13488c2ecf20Sopenharmony_ci	spin_unlock(&mtk_sha.lock);
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	mtk_sha_unregister_algs();
13518c2ecf20Sopenharmony_ci	mtk_sha_record_free(cryp);
13528c2ecf20Sopenharmony_ci}
1353