162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2021 Aspeed Technology Inc.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include "aspeed-hace.h"
762306a36Sopenharmony_ci#include <crypto/engine.h>
862306a36Sopenharmony_ci#include <crypto/hmac.h>
962306a36Sopenharmony_ci#include <crypto/internal/hash.h>
1062306a36Sopenharmony_ci#include <crypto/scatterwalk.h>
1162306a36Sopenharmony_ci#include <crypto/sha1.h>
1262306a36Sopenharmony_ci#include <crypto/sha2.h>
1362306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1462306a36Sopenharmony_ci#include <linux/err.h>
1562306a36Sopenharmony_ci#include <linux/io.h>
1662306a36Sopenharmony_ci#include <linux/kernel.h>
1762306a36Sopenharmony_ci#include <linux/string.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#ifdef CONFIG_CRYPTO_DEV_ASPEED_DEBUG
2062306a36Sopenharmony_ci#define AHASH_DBG(h, fmt, ...)	\
2162306a36Sopenharmony_ci	dev_info((h)->dev, "%s() " fmt, __func__, ##__VA_ARGS__)
2262306a36Sopenharmony_ci#else
2362306a36Sopenharmony_ci#define AHASH_DBG(h, fmt, ...)	\
2462306a36Sopenharmony_ci	dev_dbg((h)->dev, "%s() " fmt, __func__, ##__VA_ARGS__)
2562306a36Sopenharmony_ci#endif
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci/* Initialization Vectors for SHA-family */
2862306a36Sopenharmony_cistatic const __be32 sha1_iv[8] = {
2962306a36Sopenharmony_ci	cpu_to_be32(SHA1_H0), cpu_to_be32(SHA1_H1),
3062306a36Sopenharmony_ci	cpu_to_be32(SHA1_H2), cpu_to_be32(SHA1_H3),
3162306a36Sopenharmony_ci	cpu_to_be32(SHA1_H4), 0, 0, 0
3262306a36Sopenharmony_ci};
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_cistatic const __be32 sha224_iv[8] = {
3562306a36Sopenharmony_ci	cpu_to_be32(SHA224_H0), cpu_to_be32(SHA224_H1),
3662306a36Sopenharmony_ci	cpu_to_be32(SHA224_H2), cpu_to_be32(SHA224_H3),
3762306a36Sopenharmony_ci	cpu_to_be32(SHA224_H4), cpu_to_be32(SHA224_H5),
3862306a36Sopenharmony_ci	cpu_to_be32(SHA224_H6), cpu_to_be32(SHA224_H7),
3962306a36Sopenharmony_ci};
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic const __be32 sha256_iv[8] = {
4262306a36Sopenharmony_ci	cpu_to_be32(SHA256_H0), cpu_to_be32(SHA256_H1),
4362306a36Sopenharmony_ci	cpu_to_be32(SHA256_H2), cpu_to_be32(SHA256_H3),
4462306a36Sopenharmony_ci	cpu_to_be32(SHA256_H4), cpu_to_be32(SHA256_H5),
4562306a36Sopenharmony_ci	cpu_to_be32(SHA256_H6), cpu_to_be32(SHA256_H7),
4662306a36Sopenharmony_ci};
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic const __be64 sha384_iv[8] = {
4962306a36Sopenharmony_ci	cpu_to_be64(SHA384_H0), cpu_to_be64(SHA384_H1),
5062306a36Sopenharmony_ci	cpu_to_be64(SHA384_H2), cpu_to_be64(SHA384_H3),
5162306a36Sopenharmony_ci	cpu_to_be64(SHA384_H4), cpu_to_be64(SHA384_H5),
5262306a36Sopenharmony_ci	cpu_to_be64(SHA384_H6), cpu_to_be64(SHA384_H7)
5362306a36Sopenharmony_ci};
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic const __be64 sha512_iv[8] = {
5662306a36Sopenharmony_ci	cpu_to_be64(SHA512_H0), cpu_to_be64(SHA512_H1),
5762306a36Sopenharmony_ci	cpu_to_be64(SHA512_H2), cpu_to_be64(SHA512_H3),
5862306a36Sopenharmony_ci	cpu_to_be64(SHA512_H4), cpu_to_be64(SHA512_H5),
5962306a36Sopenharmony_ci	cpu_to_be64(SHA512_H6), cpu_to_be64(SHA512_H7)
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci/* The purpose of this padding is to ensure that the padded message is a
6362306a36Sopenharmony_ci * multiple of 512 bits (SHA1/SHA224/SHA256) or 1024 bits (SHA384/SHA512).
6462306a36Sopenharmony_ci * The bit "1" is appended at the end of the message followed by
6562306a36Sopenharmony_ci * "padlen-1" zero bits. Then a 64 bits block (SHA1/SHA224/SHA256) or
6662306a36Sopenharmony_ci * 128 bits block (SHA384/SHA512) equals to the message length in bits
6762306a36Sopenharmony_ci * is appended.
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci * For SHA1/SHA224/SHA256, padlen is calculated as followed:
7062306a36Sopenharmony_ci *  - if message length < 56 bytes then padlen = 56 - message length
7162306a36Sopenharmony_ci *  - else padlen = 64 + 56 - message length
7262306a36Sopenharmony_ci *
7362306a36Sopenharmony_ci * For SHA384/SHA512, padlen is calculated as followed:
7462306a36Sopenharmony_ci *  - if message length < 112 bytes then padlen = 112 - message length
7562306a36Sopenharmony_ci *  - else padlen = 128 + 112 - message length
7662306a36Sopenharmony_ci */
7762306a36Sopenharmony_cistatic void aspeed_ahash_fill_padding(struct aspeed_hace_dev *hace_dev,
7862306a36Sopenharmony_ci				      struct aspeed_sham_reqctx *rctx)
7962306a36Sopenharmony_ci{
8062306a36Sopenharmony_ci	unsigned int index, padlen;
8162306a36Sopenharmony_ci	__be64 bits[2];
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "rctx flags:0x%x\n", (u32)rctx->flags);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	switch (rctx->flags & SHA_FLAGS_MASK) {
8662306a36Sopenharmony_ci	case SHA_FLAGS_SHA1:
8762306a36Sopenharmony_ci	case SHA_FLAGS_SHA224:
8862306a36Sopenharmony_ci	case SHA_FLAGS_SHA256:
8962306a36Sopenharmony_ci		bits[0] = cpu_to_be64(rctx->digcnt[0] << 3);
9062306a36Sopenharmony_ci		index = rctx->bufcnt & 0x3f;
9162306a36Sopenharmony_ci		padlen = (index < 56) ? (56 - index) : ((64 + 56) - index);
9262306a36Sopenharmony_ci		*(rctx->buffer + rctx->bufcnt) = 0x80;
9362306a36Sopenharmony_ci		memset(rctx->buffer + rctx->bufcnt + 1, 0, padlen - 1);
9462306a36Sopenharmony_ci		memcpy(rctx->buffer + rctx->bufcnt + padlen, bits, 8);
9562306a36Sopenharmony_ci		rctx->bufcnt += padlen + 8;
9662306a36Sopenharmony_ci		break;
9762306a36Sopenharmony_ci	default:
9862306a36Sopenharmony_ci		bits[1] = cpu_to_be64(rctx->digcnt[0] << 3);
9962306a36Sopenharmony_ci		bits[0] = cpu_to_be64(rctx->digcnt[1] << 3 |
10062306a36Sopenharmony_ci				      rctx->digcnt[0] >> 61);
10162306a36Sopenharmony_ci		index = rctx->bufcnt & 0x7f;
10262306a36Sopenharmony_ci		padlen = (index < 112) ? (112 - index) : ((128 + 112) - index);
10362306a36Sopenharmony_ci		*(rctx->buffer + rctx->bufcnt) = 0x80;
10462306a36Sopenharmony_ci		memset(rctx->buffer + rctx->bufcnt + 1, 0, padlen - 1);
10562306a36Sopenharmony_ci		memcpy(rctx->buffer + rctx->bufcnt + padlen, bits, 16);
10662306a36Sopenharmony_ci		rctx->bufcnt += padlen + 16;
10762306a36Sopenharmony_ci		break;
10862306a36Sopenharmony_ci	}
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/*
11262306a36Sopenharmony_ci * Prepare DMA buffer before hardware engine
11362306a36Sopenharmony_ci * processing.
11462306a36Sopenharmony_ci */
11562306a36Sopenharmony_cistatic int aspeed_ahash_dma_prepare(struct aspeed_hace_dev *hace_dev)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
11862306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
11962306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
12062306a36Sopenharmony_ci	int length, remain;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	length = rctx->total + rctx->bufcnt;
12362306a36Sopenharmony_ci	remain = length % rctx->block_size;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "length:0x%x, remain:0x%x\n", length, remain);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (rctx->bufcnt)
12862306a36Sopenharmony_ci		memcpy(hash_engine->ahash_src_addr, rctx->buffer, rctx->bufcnt);
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	if (rctx->total + rctx->bufcnt < ASPEED_CRYPTO_SRC_DMA_BUF_LEN) {
13162306a36Sopenharmony_ci		scatterwalk_map_and_copy(hash_engine->ahash_src_addr +
13262306a36Sopenharmony_ci					 rctx->bufcnt, rctx->src_sg,
13362306a36Sopenharmony_ci					 rctx->offset, rctx->total - remain, 0);
13462306a36Sopenharmony_ci		rctx->offset += rctx->total - remain;
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_ci	} else {
13762306a36Sopenharmony_ci		dev_warn(hace_dev->dev, "Hash data length is too large\n");
13862306a36Sopenharmony_ci		return -EINVAL;
13962306a36Sopenharmony_ci	}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	scatterwalk_map_and_copy(rctx->buffer, rctx->src_sg,
14262306a36Sopenharmony_ci				 rctx->offset, remain, 0);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	rctx->bufcnt = remain;
14562306a36Sopenharmony_ci	rctx->digest_dma_addr = dma_map_single(hace_dev->dev, rctx->digest,
14662306a36Sopenharmony_ci					       SHA512_DIGEST_SIZE,
14762306a36Sopenharmony_ci					       DMA_BIDIRECTIONAL);
14862306a36Sopenharmony_ci	if (dma_mapping_error(hace_dev->dev, rctx->digest_dma_addr)) {
14962306a36Sopenharmony_ci		dev_warn(hace_dev->dev, "dma_map() rctx digest error\n");
15062306a36Sopenharmony_ci		return -ENOMEM;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	hash_engine->src_length = length - remain;
15462306a36Sopenharmony_ci	hash_engine->src_dma = hash_engine->ahash_src_dma_addr;
15562306a36Sopenharmony_ci	hash_engine->digest_dma = rctx->digest_dma_addr;
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	return 0;
15862306a36Sopenharmony_ci}
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci/*
16162306a36Sopenharmony_ci * Prepare DMA buffer as SG list buffer before
16262306a36Sopenharmony_ci * hardware engine processing.
16362306a36Sopenharmony_ci */
16462306a36Sopenharmony_cistatic int aspeed_ahash_dma_prepare_sg(struct aspeed_hace_dev *hace_dev)
16562306a36Sopenharmony_ci{
16662306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
16762306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
16862306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
16962306a36Sopenharmony_ci	struct aspeed_sg_list *src_list;
17062306a36Sopenharmony_ci	struct scatterlist *s;
17162306a36Sopenharmony_ci	int length, remain, sg_len, i;
17262306a36Sopenharmony_ci	int rc = 0;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	remain = (rctx->total + rctx->bufcnt) % rctx->block_size;
17562306a36Sopenharmony_ci	length = rctx->total + rctx->bufcnt - remain;
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "%s:0x%x, %s:%zu, %s:0x%x, %s:0x%x\n",
17862306a36Sopenharmony_ci		  "rctx total", rctx->total, "bufcnt", rctx->bufcnt,
17962306a36Sopenharmony_ci		  "length", length, "remain", remain);
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci	sg_len = dma_map_sg(hace_dev->dev, rctx->src_sg, rctx->src_nents,
18262306a36Sopenharmony_ci			    DMA_TO_DEVICE);
18362306a36Sopenharmony_ci	if (!sg_len) {
18462306a36Sopenharmony_ci		dev_warn(hace_dev->dev, "dma_map_sg() src error\n");
18562306a36Sopenharmony_ci		rc = -ENOMEM;
18662306a36Sopenharmony_ci		goto end;
18762306a36Sopenharmony_ci	}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	src_list = (struct aspeed_sg_list *)hash_engine->ahash_src_addr;
19062306a36Sopenharmony_ci	rctx->digest_dma_addr = dma_map_single(hace_dev->dev, rctx->digest,
19162306a36Sopenharmony_ci					       SHA512_DIGEST_SIZE,
19262306a36Sopenharmony_ci					       DMA_BIDIRECTIONAL);
19362306a36Sopenharmony_ci	if (dma_mapping_error(hace_dev->dev, rctx->digest_dma_addr)) {
19462306a36Sopenharmony_ci		dev_warn(hace_dev->dev, "dma_map() rctx digest error\n");
19562306a36Sopenharmony_ci		rc = -ENOMEM;
19662306a36Sopenharmony_ci		goto free_src_sg;
19762306a36Sopenharmony_ci	}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	if (rctx->bufcnt != 0) {
20062306a36Sopenharmony_ci		u32 phy_addr;
20162306a36Sopenharmony_ci		u32 len;
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci		rctx->buffer_dma_addr = dma_map_single(hace_dev->dev,
20462306a36Sopenharmony_ci						       rctx->buffer,
20562306a36Sopenharmony_ci						       rctx->block_size * 2,
20662306a36Sopenharmony_ci						       DMA_TO_DEVICE);
20762306a36Sopenharmony_ci		if (dma_mapping_error(hace_dev->dev, rctx->buffer_dma_addr)) {
20862306a36Sopenharmony_ci			dev_warn(hace_dev->dev, "dma_map() rctx buffer error\n");
20962306a36Sopenharmony_ci			rc = -ENOMEM;
21062306a36Sopenharmony_ci			goto free_rctx_digest;
21162306a36Sopenharmony_ci		}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci		phy_addr = rctx->buffer_dma_addr;
21462306a36Sopenharmony_ci		len = rctx->bufcnt;
21562306a36Sopenharmony_ci		length -= len;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci		/* Last sg list */
21862306a36Sopenharmony_ci		if (length == 0)
21962306a36Sopenharmony_ci			len |= HASH_SG_LAST_LIST;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci		src_list[0].phy_addr = cpu_to_le32(phy_addr);
22262306a36Sopenharmony_ci		src_list[0].len = cpu_to_le32(len);
22362306a36Sopenharmony_ci		src_list++;
22462306a36Sopenharmony_ci	}
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	if (length != 0) {
22762306a36Sopenharmony_ci		for_each_sg(rctx->src_sg, s, sg_len, i) {
22862306a36Sopenharmony_ci			u32 phy_addr = sg_dma_address(s);
22962306a36Sopenharmony_ci			u32 len = sg_dma_len(s);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci			if (length > len)
23262306a36Sopenharmony_ci				length -= len;
23362306a36Sopenharmony_ci			else {
23462306a36Sopenharmony_ci				/* Last sg list */
23562306a36Sopenharmony_ci				len = length;
23662306a36Sopenharmony_ci				len |= HASH_SG_LAST_LIST;
23762306a36Sopenharmony_ci				length = 0;
23862306a36Sopenharmony_ci			}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci			src_list[i].phy_addr = cpu_to_le32(phy_addr);
24162306a36Sopenharmony_ci			src_list[i].len = cpu_to_le32(len);
24262306a36Sopenharmony_ci		}
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	if (length != 0) {
24662306a36Sopenharmony_ci		rc = -EINVAL;
24762306a36Sopenharmony_ci		goto free_rctx_buffer;
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	rctx->offset = rctx->total - remain;
25162306a36Sopenharmony_ci	hash_engine->src_length = rctx->total + rctx->bufcnt - remain;
25262306a36Sopenharmony_ci	hash_engine->src_dma = hash_engine->ahash_src_dma_addr;
25362306a36Sopenharmony_ci	hash_engine->digest_dma = rctx->digest_dma_addr;
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	return 0;
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_cifree_rctx_buffer:
25862306a36Sopenharmony_ci	if (rctx->bufcnt != 0)
25962306a36Sopenharmony_ci		dma_unmap_single(hace_dev->dev, rctx->buffer_dma_addr,
26062306a36Sopenharmony_ci				 rctx->block_size * 2, DMA_TO_DEVICE);
26162306a36Sopenharmony_cifree_rctx_digest:
26262306a36Sopenharmony_ci	dma_unmap_single(hace_dev->dev, rctx->digest_dma_addr,
26362306a36Sopenharmony_ci			 SHA512_DIGEST_SIZE, DMA_BIDIRECTIONAL);
26462306a36Sopenharmony_cifree_src_sg:
26562306a36Sopenharmony_ci	dma_unmap_sg(hace_dev->dev, rctx->src_sg, rctx->src_nents,
26662306a36Sopenharmony_ci		     DMA_TO_DEVICE);
26762306a36Sopenharmony_ciend:
26862306a36Sopenharmony_ci	return rc;
26962306a36Sopenharmony_ci}
27062306a36Sopenharmony_ci
27162306a36Sopenharmony_cistatic int aspeed_ahash_complete(struct aspeed_hace_dev *hace_dev)
27262306a36Sopenharmony_ci{
27362306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
27462306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "\n");
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	hash_engine->flags &= ~CRYPTO_FLAGS_BUSY;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	crypto_finalize_hash_request(hace_dev->crypt_engine_hash, req, 0);
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	return 0;
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci/*
28662306a36Sopenharmony_ci * Copy digest to the corresponding request result.
28762306a36Sopenharmony_ci * This function will be called at final() stage.
28862306a36Sopenharmony_ci */
28962306a36Sopenharmony_cistatic int aspeed_ahash_transfer(struct aspeed_hace_dev *hace_dev)
29062306a36Sopenharmony_ci{
29162306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
29262306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
29362306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "\n");
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	dma_unmap_single(hace_dev->dev, rctx->digest_dma_addr,
29862306a36Sopenharmony_ci			 SHA512_DIGEST_SIZE, DMA_BIDIRECTIONAL);
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	dma_unmap_single(hace_dev->dev, rctx->buffer_dma_addr,
30162306a36Sopenharmony_ci			 rctx->block_size * 2, DMA_TO_DEVICE);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	memcpy(req->result, rctx->digest, rctx->digsize);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	return aspeed_ahash_complete(hace_dev);
30662306a36Sopenharmony_ci}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci/*
30962306a36Sopenharmony_ci * Trigger hardware engines to do the math.
31062306a36Sopenharmony_ci */
31162306a36Sopenharmony_cistatic int aspeed_hace_ahash_trigger(struct aspeed_hace_dev *hace_dev,
31262306a36Sopenharmony_ci				     aspeed_hace_fn_t resume)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
31562306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
31662306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "src_dma:%pad, digest_dma:%pad, length:%zu\n",
31962306a36Sopenharmony_ci		  &hash_engine->src_dma, &hash_engine->digest_dma,
32062306a36Sopenharmony_ci		  hash_engine->src_length);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	rctx->cmd |= HASH_CMD_INT_ENABLE;
32362306a36Sopenharmony_ci	hash_engine->resume = resume;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	ast_hace_write(hace_dev, hash_engine->src_dma, ASPEED_HACE_HASH_SRC);
32662306a36Sopenharmony_ci	ast_hace_write(hace_dev, hash_engine->digest_dma,
32762306a36Sopenharmony_ci		       ASPEED_HACE_HASH_DIGEST_BUFF);
32862306a36Sopenharmony_ci	ast_hace_write(hace_dev, hash_engine->digest_dma,
32962306a36Sopenharmony_ci		       ASPEED_HACE_HASH_KEY_BUFF);
33062306a36Sopenharmony_ci	ast_hace_write(hace_dev, hash_engine->src_length,
33162306a36Sopenharmony_ci		       ASPEED_HACE_HASH_DATA_LEN);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/* Memory barrier to ensure all data setup before engine starts */
33462306a36Sopenharmony_ci	mb();
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	ast_hace_write(hace_dev, rctx->cmd, ASPEED_HACE_HASH_CMD);
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	return -EINPROGRESS;
33962306a36Sopenharmony_ci}
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci/*
34262306a36Sopenharmony_ci * HMAC resume aims to do the second pass produces
34362306a36Sopenharmony_ci * the final HMAC code derived from the inner hash
34462306a36Sopenharmony_ci * result and the outer key.
34562306a36Sopenharmony_ci */
34662306a36Sopenharmony_cistatic int aspeed_ahash_hmac_resume(struct aspeed_hace_dev *hace_dev)
34762306a36Sopenharmony_ci{
34862306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
34962306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
35062306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
35162306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
35262306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_ahash_ctx(tfm);
35362306a36Sopenharmony_ci	struct aspeed_sha_hmac_ctx *bctx = tctx->base;
35462306a36Sopenharmony_ci	int rc = 0;
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "\n");
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	dma_unmap_single(hace_dev->dev, rctx->digest_dma_addr,
35962306a36Sopenharmony_ci			 SHA512_DIGEST_SIZE, DMA_BIDIRECTIONAL);
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci	dma_unmap_single(hace_dev->dev, rctx->buffer_dma_addr,
36262306a36Sopenharmony_ci			 rctx->block_size * 2, DMA_TO_DEVICE);
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	/* o key pad + hash sum 1 */
36562306a36Sopenharmony_ci	memcpy(rctx->buffer, bctx->opad, rctx->block_size);
36662306a36Sopenharmony_ci	memcpy(rctx->buffer + rctx->block_size, rctx->digest, rctx->digsize);
36762306a36Sopenharmony_ci
36862306a36Sopenharmony_ci	rctx->bufcnt = rctx->block_size + rctx->digsize;
36962306a36Sopenharmony_ci	rctx->digcnt[0] = rctx->block_size + rctx->digsize;
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	aspeed_ahash_fill_padding(hace_dev, rctx);
37262306a36Sopenharmony_ci	memcpy(rctx->digest, rctx->sha_iv, rctx->ivsize);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	rctx->digest_dma_addr = dma_map_single(hace_dev->dev, rctx->digest,
37562306a36Sopenharmony_ci					       SHA512_DIGEST_SIZE,
37662306a36Sopenharmony_ci					       DMA_BIDIRECTIONAL);
37762306a36Sopenharmony_ci	if (dma_mapping_error(hace_dev->dev, rctx->digest_dma_addr)) {
37862306a36Sopenharmony_ci		dev_warn(hace_dev->dev, "dma_map() rctx digest error\n");
37962306a36Sopenharmony_ci		rc = -ENOMEM;
38062306a36Sopenharmony_ci		goto end;
38162306a36Sopenharmony_ci	}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	rctx->buffer_dma_addr = dma_map_single(hace_dev->dev, rctx->buffer,
38462306a36Sopenharmony_ci					       rctx->block_size * 2,
38562306a36Sopenharmony_ci					       DMA_TO_DEVICE);
38662306a36Sopenharmony_ci	if (dma_mapping_error(hace_dev->dev, rctx->buffer_dma_addr)) {
38762306a36Sopenharmony_ci		dev_warn(hace_dev->dev, "dma_map() rctx buffer error\n");
38862306a36Sopenharmony_ci		rc = -ENOMEM;
38962306a36Sopenharmony_ci		goto free_rctx_digest;
39062306a36Sopenharmony_ci	}
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	hash_engine->src_dma = rctx->buffer_dma_addr;
39362306a36Sopenharmony_ci	hash_engine->src_length = rctx->bufcnt;
39462306a36Sopenharmony_ci	hash_engine->digest_dma = rctx->digest_dma_addr;
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	return aspeed_hace_ahash_trigger(hace_dev, aspeed_ahash_transfer);
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_cifree_rctx_digest:
39962306a36Sopenharmony_ci	dma_unmap_single(hace_dev->dev, rctx->digest_dma_addr,
40062306a36Sopenharmony_ci			 SHA512_DIGEST_SIZE, DMA_BIDIRECTIONAL);
40162306a36Sopenharmony_ciend:
40262306a36Sopenharmony_ci	return rc;
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_cistatic int aspeed_ahash_req_final(struct aspeed_hace_dev *hace_dev)
40662306a36Sopenharmony_ci{
40762306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
40862306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
40962306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
41062306a36Sopenharmony_ci	int rc = 0;
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "\n");
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci	aspeed_ahash_fill_padding(hace_dev, rctx);
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	rctx->digest_dma_addr = dma_map_single(hace_dev->dev,
41762306a36Sopenharmony_ci					       rctx->digest,
41862306a36Sopenharmony_ci					       SHA512_DIGEST_SIZE,
41962306a36Sopenharmony_ci					       DMA_BIDIRECTIONAL);
42062306a36Sopenharmony_ci	if (dma_mapping_error(hace_dev->dev, rctx->digest_dma_addr)) {
42162306a36Sopenharmony_ci		dev_warn(hace_dev->dev, "dma_map() rctx digest error\n");
42262306a36Sopenharmony_ci		rc = -ENOMEM;
42362306a36Sopenharmony_ci		goto end;
42462306a36Sopenharmony_ci	}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	rctx->buffer_dma_addr = dma_map_single(hace_dev->dev,
42762306a36Sopenharmony_ci					       rctx->buffer,
42862306a36Sopenharmony_ci					       rctx->block_size * 2,
42962306a36Sopenharmony_ci					       DMA_TO_DEVICE);
43062306a36Sopenharmony_ci	if (dma_mapping_error(hace_dev->dev, rctx->buffer_dma_addr)) {
43162306a36Sopenharmony_ci		dev_warn(hace_dev->dev, "dma_map() rctx buffer error\n");
43262306a36Sopenharmony_ci		rc = -ENOMEM;
43362306a36Sopenharmony_ci		goto free_rctx_digest;
43462306a36Sopenharmony_ci	}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	hash_engine->src_dma = rctx->buffer_dma_addr;
43762306a36Sopenharmony_ci	hash_engine->src_length = rctx->bufcnt;
43862306a36Sopenharmony_ci	hash_engine->digest_dma = rctx->digest_dma_addr;
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	if (rctx->flags & SHA_FLAGS_HMAC)
44162306a36Sopenharmony_ci		return aspeed_hace_ahash_trigger(hace_dev,
44262306a36Sopenharmony_ci						 aspeed_ahash_hmac_resume);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	return aspeed_hace_ahash_trigger(hace_dev, aspeed_ahash_transfer);
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_cifree_rctx_digest:
44762306a36Sopenharmony_ci	dma_unmap_single(hace_dev->dev, rctx->digest_dma_addr,
44862306a36Sopenharmony_ci			 SHA512_DIGEST_SIZE, DMA_BIDIRECTIONAL);
44962306a36Sopenharmony_ciend:
45062306a36Sopenharmony_ci	return rc;
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_cistatic int aspeed_ahash_update_resume_sg(struct aspeed_hace_dev *hace_dev)
45462306a36Sopenharmony_ci{
45562306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
45662306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
45762306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "\n");
46062306a36Sopenharmony_ci
46162306a36Sopenharmony_ci	dma_unmap_sg(hace_dev->dev, rctx->src_sg, rctx->src_nents,
46262306a36Sopenharmony_ci		     DMA_TO_DEVICE);
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	if (rctx->bufcnt != 0)
46562306a36Sopenharmony_ci		dma_unmap_single(hace_dev->dev, rctx->buffer_dma_addr,
46662306a36Sopenharmony_ci				 rctx->block_size * 2,
46762306a36Sopenharmony_ci				 DMA_TO_DEVICE);
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	dma_unmap_single(hace_dev->dev, rctx->digest_dma_addr,
47062306a36Sopenharmony_ci			 SHA512_DIGEST_SIZE, DMA_BIDIRECTIONAL);
47162306a36Sopenharmony_ci
47262306a36Sopenharmony_ci	scatterwalk_map_and_copy(rctx->buffer, rctx->src_sg, rctx->offset,
47362306a36Sopenharmony_ci				 rctx->total - rctx->offset, 0);
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	rctx->bufcnt = rctx->total - rctx->offset;
47662306a36Sopenharmony_ci	rctx->cmd &= ~HASH_CMD_HASH_SRC_SG_CTRL;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	if (rctx->flags & SHA_FLAGS_FINUP)
47962306a36Sopenharmony_ci		return aspeed_ahash_req_final(hace_dev);
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	return aspeed_ahash_complete(hace_dev);
48262306a36Sopenharmony_ci}
48362306a36Sopenharmony_ci
48462306a36Sopenharmony_cistatic int aspeed_ahash_update_resume(struct aspeed_hace_dev *hace_dev)
48562306a36Sopenharmony_ci{
48662306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
48762306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
48862306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "\n");
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	dma_unmap_single(hace_dev->dev, rctx->digest_dma_addr,
49362306a36Sopenharmony_ci			 SHA512_DIGEST_SIZE, DMA_BIDIRECTIONAL);
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	if (rctx->flags & SHA_FLAGS_FINUP)
49662306a36Sopenharmony_ci		return aspeed_ahash_req_final(hace_dev);
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	return aspeed_ahash_complete(hace_dev);
49962306a36Sopenharmony_ci}
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_cistatic int aspeed_ahash_req_update(struct aspeed_hace_dev *hace_dev)
50262306a36Sopenharmony_ci{
50362306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine = &hace_dev->hash_engine;
50462306a36Sopenharmony_ci	struct ahash_request *req = hash_engine->req;
50562306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
50662306a36Sopenharmony_ci	aspeed_hace_fn_t resume;
50762306a36Sopenharmony_ci	int ret;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "\n");
51062306a36Sopenharmony_ci
51162306a36Sopenharmony_ci	if (hace_dev->version == AST2600_VERSION) {
51262306a36Sopenharmony_ci		rctx->cmd |= HASH_CMD_HASH_SRC_SG_CTRL;
51362306a36Sopenharmony_ci		resume = aspeed_ahash_update_resume_sg;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	} else {
51662306a36Sopenharmony_ci		resume = aspeed_ahash_update_resume;
51762306a36Sopenharmony_ci	}
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_ci	ret = hash_engine->dma_prepare(hace_dev);
52062306a36Sopenharmony_ci	if (ret)
52162306a36Sopenharmony_ci		return ret;
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	return aspeed_hace_ahash_trigger(hace_dev, resume);
52462306a36Sopenharmony_ci}
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_cistatic int aspeed_hace_hash_handle_queue(struct aspeed_hace_dev *hace_dev,
52762306a36Sopenharmony_ci				  struct ahash_request *req)
52862306a36Sopenharmony_ci{
52962306a36Sopenharmony_ci	return crypto_transfer_hash_request_to_engine(
53062306a36Sopenharmony_ci			hace_dev->crypt_engine_hash, req);
53162306a36Sopenharmony_ci}
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_cistatic int aspeed_ahash_do_request(struct crypto_engine *engine, void *areq)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
53662306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
53762306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
53862306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_ahash_ctx(tfm);
53962306a36Sopenharmony_ci	struct aspeed_hace_dev *hace_dev = tctx->hace_dev;
54062306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine;
54162306a36Sopenharmony_ci	int ret = 0;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	hash_engine = &hace_dev->hash_engine;
54462306a36Sopenharmony_ci	hash_engine->flags |= CRYPTO_FLAGS_BUSY;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	if (rctx->op == SHA_OP_UPDATE)
54762306a36Sopenharmony_ci		ret = aspeed_ahash_req_update(hace_dev);
54862306a36Sopenharmony_ci	else if (rctx->op == SHA_OP_FINAL)
54962306a36Sopenharmony_ci		ret = aspeed_ahash_req_final(hace_dev);
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	if (ret != -EINPROGRESS)
55262306a36Sopenharmony_ci		return ret;
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	return 0;
55562306a36Sopenharmony_ci}
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_cistatic void aspeed_ahash_prepare_request(struct crypto_engine *engine,
55862306a36Sopenharmony_ci					 void *areq)
55962306a36Sopenharmony_ci{
56062306a36Sopenharmony_ci	struct ahash_request *req = ahash_request_cast(areq);
56162306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
56262306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_ahash_ctx(tfm);
56362306a36Sopenharmony_ci	struct aspeed_hace_dev *hace_dev = tctx->hace_dev;
56462306a36Sopenharmony_ci	struct aspeed_engine_hash *hash_engine;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	hash_engine = &hace_dev->hash_engine;
56762306a36Sopenharmony_ci	hash_engine->req = req;
56862306a36Sopenharmony_ci
56962306a36Sopenharmony_ci	if (hace_dev->version == AST2600_VERSION)
57062306a36Sopenharmony_ci		hash_engine->dma_prepare = aspeed_ahash_dma_prepare_sg;
57162306a36Sopenharmony_ci	else
57262306a36Sopenharmony_ci		hash_engine->dma_prepare = aspeed_ahash_dma_prepare;
57362306a36Sopenharmony_ci}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_cistatic int aspeed_ahash_do_one(struct crypto_engine *engine, void *areq)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	aspeed_ahash_prepare_request(engine, areq);
57862306a36Sopenharmony_ci	return aspeed_ahash_do_request(engine, areq);
57962306a36Sopenharmony_ci}
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_cistatic int aspeed_sham_update(struct ahash_request *req)
58262306a36Sopenharmony_ci{
58362306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
58462306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
58562306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_ahash_ctx(tfm);
58662306a36Sopenharmony_ci	struct aspeed_hace_dev *hace_dev = tctx->hace_dev;
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "req->nbytes: %d\n", req->nbytes);
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_ci	rctx->total = req->nbytes;
59162306a36Sopenharmony_ci	rctx->src_sg = req->src;
59262306a36Sopenharmony_ci	rctx->offset = 0;
59362306a36Sopenharmony_ci	rctx->src_nents = sg_nents(req->src);
59462306a36Sopenharmony_ci	rctx->op = SHA_OP_UPDATE;
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	rctx->digcnt[0] += rctx->total;
59762306a36Sopenharmony_ci	if (rctx->digcnt[0] < rctx->total)
59862306a36Sopenharmony_ci		rctx->digcnt[1]++;
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	if (rctx->bufcnt + rctx->total < rctx->block_size) {
60162306a36Sopenharmony_ci		scatterwalk_map_and_copy(rctx->buffer + rctx->bufcnt,
60262306a36Sopenharmony_ci					 rctx->src_sg, rctx->offset,
60362306a36Sopenharmony_ci					 rctx->total, 0);
60462306a36Sopenharmony_ci		rctx->bufcnt += rctx->total;
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci		return 0;
60762306a36Sopenharmony_ci	}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	return aspeed_hace_hash_handle_queue(hace_dev, req);
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cistatic int aspeed_sham_shash_digest(struct crypto_shash *tfm, u32 flags,
61362306a36Sopenharmony_ci				    const u8 *data, unsigned int len, u8 *out)
61462306a36Sopenharmony_ci{
61562306a36Sopenharmony_ci	SHASH_DESC_ON_STACK(shash, tfm);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	shash->tfm = tfm;
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	return crypto_shash_digest(shash, data, len, out);
62062306a36Sopenharmony_ci}
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_cistatic int aspeed_sham_final(struct ahash_request *req)
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
62562306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
62662306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_ahash_ctx(tfm);
62762306a36Sopenharmony_ci	struct aspeed_hace_dev *hace_dev = tctx->hace_dev;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "req->nbytes:%d, rctx->total:%d\n",
63062306a36Sopenharmony_ci		  req->nbytes, rctx->total);
63162306a36Sopenharmony_ci	rctx->op = SHA_OP_FINAL;
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci	return aspeed_hace_hash_handle_queue(hace_dev, req);
63462306a36Sopenharmony_ci}
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_cistatic int aspeed_sham_finup(struct ahash_request *req)
63762306a36Sopenharmony_ci{
63862306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
63962306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
64062306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_ahash_ctx(tfm);
64162306a36Sopenharmony_ci	struct aspeed_hace_dev *hace_dev = tctx->hace_dev;
64262306a36Sopenharmony_ci	int rc1, rc2;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "req->nbytes: %d\n", req->nbytes);
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	rctx->flags |= SHA_FLAGS_FINUP;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	rc1 = aspeed_sham_update(req);
64962306a36Sopenharmony_ci	if (rc1 == -EINPROGRESS || rc1 == -EBUSY)
65062306a36Sopenharmony_ci		return rc1;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	/*
65362306a36Sopenharmony_ci	 * final() has to be always called to cleanup resources
65462306a36Sopenharmony_ci	 * even if update() failed, except EINPROGRESS
65562306a36Sopenharmony_ci	 */
65662306a36Sopenharmony_ci	rc2 = aspeed_sham_final(req);
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ci	return rc1 ? : rc2;
65962306a36Sopenharmony_ci}
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_cistatic int aspeed_sham_init(struct ahash_request *req)
66262306a36Sopenharmony_ci{
66362306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
66462306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
66562306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_ahash_ctx(tfm);
66662306a36Sopenharmony_ci	struct aspeed_hace_dev *hace_dev = tctx->hace_dev;
66762306a36Sopenharmony_ci	struct aspeed_sha_hmac_ctx *bctx = tctx->base;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "%s: digest size:%d\n",
67062306a36Sopenharmony_ci		  crypto_tfm_alg_name(&tfm->base),
67162306a36Sopenharmony_ci		  crypto_ahash_digestsize(tfm));
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci	rctx->cmd = HASH_CMD_ACC_MODE;
67462306a36Sopenharmony_ci	rctx->flags = 0;
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	switch (crypto_ahash_digestsize(tfm)) {
67762306a36Sopenharmony_ci	case SHA1_DIGEST_SIZE:
67862306a36Sopenharmony_ci		rctx->cmd |= HASH_CMD_SHA1 | HASH_CMD_SHA_SWAP;
67962306a36Sopenharmony_ci		rctx->flags |= SHA_FLAGS_SHA1;
68062306a36Sopenharmony_ci		rctx->digsize = SHA1_DIGEST_SIZE;
68162306a36Sopenharmony_ci		rctx->block_size = SHA1_BLOCK_SIZE;
68262306a36Sopenharmony_ci		rctx->sha_iv = sha1_iv;
68362306a36Sopenharmony_ci		rctx->ivsize = 32;
68462306a36Sopenharmony_ci		memcpy(rctx->digest, sha1_iv, rctx->ivsize);
68562306a36Sopenharmony_ci		break;
68662306a36Sopenharmony_ci	case SHA224_DIGEST_SIZE:
68762306a36Sopenharmony_ci		rctx->cmd |= HASH_CMD_SHA224 | HASH_CMD_SHA_SWAP;
68862306a36Sopenharmony_ci		rctx->flags |= SHA_FLAGS_SHA224;
68962306a36Sopenharmony_ci		rctx->digsize = SHA224_DIGEST_SIZE;
69062306a36Sopenharmony_ci		rctx->block_size = SHA224_BLOCK_SIZE;
69162306a36Sopenharmony_ci		rctx->sha_iv = sha224_iv;
69262306a36Sopenharmony_ci		rctx->ivsize = 32;
69362306a36Sopenharmony_ci		memcpy(rctx->digest, sha224_iv, rctx->ivsize);
69462306a36Sopenharmony_ci		break;
69562306a36Sopenharmony_ci	case SHA256_DIGEST_SIZE:
69662306a36Sopenharmony_ci		rctx->cmd |= HASH_CMD_SHA256 | HASH_CMD_SHA_SWAP;
69762306a36Sopenharmony_ci		rctx->flags |= SHA_FLAGS_SHA256;
69862306a36Sopenharmony_ci		rctx->digsize = SHA256_DIGEST_SIZE;
69962306a36Sopenharmony_ci		rctx->block_size = SHA256_BLOCK_SIZE;
70062306a36Sopenharmony_ci		rctx->sha_iv = sha256_iv;
70162306a36Sopenharmony_ci		rctx->ivsize = 32;
70262306a36Sopenharmony_ci		memcpy(rctx->digest, sha256_iv, rctx->ivsize);
70362306a36Sopenharmony_ci		break;
70462306a36Sopenharmony_ci	case SHA384_DIGEST_SIZE:
70562306a36Sopenharmony_ci		rctx->cmd |= HASH_CMD_SHA512_SER | HASH_CMD_SHA384 |
70662306a36Sopenharmony_ci			     HASH_CMD_SHA_SWAP;
70762306a36Sopenharmony_ci		rctx->flags |= SHA_FLAGS_SHA384;
70862306a36Sopenharmony_ci		rctx->digsize = SHA384_DIGEST_SIZE;
70962306a36Sopenharmony_ci		rctx->block_size = SHA384_BLOCK_SIZE;
71062306a36Sopenharmony_ci		rctx->sha_iv = (const __be32 *)sha384_iv;
71162306a36Sopenharmony_ci		rctx->ivsize = 64;
71262306a36Sopenharmony_ci		memcpy(rctx->digest, sha384_iv, rctx->ivsize);
71362306a36Sopenharmony_ci		break;
71462306a36Sopenharmony_ci	case SHA512_DIGEST_SIZE:
71562306a36Sopenharmony_ci		rctx->cmd |= HASH_CMD_SHA512_SER | HASH_CMD_SHA512 |
71662306a36Sopenharmony_ci			     HASH_CMD_SHA_SWAP;
71762306a36Sopenharmony_ci		rctx->flags |= SHA_FLAGS_SHA512;
71862306a36Sopenharmony_ci		rctx->digsize = SHA512_DIGEST_SIZE;
71962306a36Sopenharmony_ci		rctx->block_size = SHA512_BLOCK_SIZE;
72062306a36Sopenharmony_ci		rctx->sha_iv = (const __be32 *)sha512_iv;
72162306a36Sopenharmony_ci		rctx->ivsize = 64;
72262306a36Sopenharmony_ci		memcpy(rctx->digest, sha512_iv, rctx->ivsize);
72362306a36Sopenharmony_ci		break;
72462306a36Sopenharmony_ci	default:
72562306a36Sopenharmony_ci		dev_warn(tctx->hace_dev->dev, "digest size %d not support\n",
72662306a36Sopenharmony_ci			 crypto_ahash_digestsize(tfm));
72762306a36Sopenharmony_ci		return -EINVAL;
72862306a36Sopenharmony_ci	}
72962306a36Sopenharmony_ci
73062306a36Sopenharmony_ci	rctx->bufcnt = 0;
73162306a36Sopenharmony_ci	rctx->total = 0;
73262306a36Sopenharmony_ci	rctx->digcnt[0] = 0;
73362306a36Sopenharmony_ci	rctx->digcnt[1] = 0;
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	/* HMAC init */
73662306a36Sopenharmony_ci	if (tctx->flags & SHA_FLAGS_HMAC) {
73762306a36Sopenharmony_ci		rctx->digcnt[0] = rctx->block_size;
73862306a36Sopenharmony_ci		rctx->bufcnt = rctx->block_size;
73962306a36Sopenharmony_ci		memcpy(rctx->buffer, bctx->ipad, rctx->block_size);
74062306a36Sopenharmony_ci		rctx->flags |= SHA_FLAGS_HMAC;
74162306a36Sopenharmony_ci	}
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	return 0;
74462306a36Sopenharmony_ci}
74562306a36Sopenharmony_ci
74662306a36Sopenharmony_cistatic int aspeed_sham_digest(struct ahash_request *req)
74762306a36Sopenharmony_ci{
74862306a36Sopenharmony_ci	return aspeed_sham_init(req) ? : aspeed_sham_finup(req);
74962306a36Sopenharmony_ci}
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_cistatic int aspeed_sham_setkey(struct crypto_ahash *tfm, const u8 *key,
75262306a36Sopenharmony_ci			      unsigned int keylen)
75362306a36Sopenharmony_ci{
75462306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_ahash_ctx(tfm);
75562306a36Sopenharmony_ci	struct aspeed_hace_dev *hace_dev = tctx->hace_dev;
75662306a36Sopenharmony_ci	struct aspeed_sha_hmac_ctx *bctx = tctx->base;
75762306a36Sopenharmony_ci	int ds = crypto_shash_digestsize(bctx->shash);
75862306a36Sopenharmony_ci	int bs = crypto_shash_blocksize(bctx->shash);
75962306a36Sopenharmony_ci	int err = 0;
76062306a36Sopenharmony_ci	int i;
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "%s: keylen:%d\n", crypto_tfm_alg_name(&tfm->base),
76362306a36Sopenharmony_ci		  keylen);
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	if (keylen > bs) {
76662306a36Sopenharmony_ci		err = aspeed_sham_shash_digest(bctx->shash,
76762306a36Sopenharmony_ci					       crypto_shash_get_flags(bctx->shash),
76862306a36Sopenharmony_ci					       key, keylen, bctx->ipad);
76962306a36Sopenharmony_ci		if (err)
77062306a36Sopenharmony_ci			return err;
77162306a36Sopenharmony_ci		keylen = ds;
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci	} else {
77462306a36Sopenharmony_ci		memcpy(bctx->ipad, key, keylen);
77562306a36Sopenharmony_ci	}
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	memset(bctx->ipad + keylen, 0, bs - keylen);
77862306a36Sopenharmony_ci	memcpy(bctx->opad, bctx->ipad, bs);
77962306a36Sopenharmony_ci
78062306a36Sopenharmony_ci	for (i = 0; i < bs; i++) {
78162306a36Sopenharmony_ci		bctx->ipad[i] ^= HMAC_IPAD_VALUE;
78262306a36Sopenharmony_ci		bctx->opad[i] ^= HMAC_OPAD_VALUE;
78362306a36Sopenharmony_ci	}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_ci	return err;
78662306a36Sopenharmony_ci}
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_cistatic int aspeed_sham_cra_init(struct crypto_tfm *tfm)
78962306a36Sopenharmony_ci{
79062306a36Sopenharmony_ci	struct ahash_alg *alg = __crypto_ahash_alg(tfm->__crt_alg);
79162306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_tfm_ctx(tfm);
79262306a36Sopenharmony_ci	struct aspeed_hace_alg *ast_alg;
79362306a36Sopenharmony_ci
79462306a36Sopenharmony_ci	ast_alg = container_of(alg, struct aspeed_hace_alg, alg.ahash.base);
79562306a36Sopenharmony_ci	tctx->hace_dev = ast_alg->hace_dev;
79662306a36Sopenharmony_ci	tctx->flags = 0;
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
79962306a36Sopenharmony_ci				 sizeof(struct aspeed_sham_reqctx));
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci	if (ast_alg->alg_base) {
80262306a36Sopenharmony_ci		/* hmac related */
80362306a36Sopenharmony_ci		struct aspeed_sha_hmac_ctx *bctx = tctx->base;
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci		tctx->flags |= SHA_FLAGS_HMAC;
80662306a36Sopenharmony_ci		bctx->shash = crypto_alloc_shash(ast_alg->alg_base, 0,
80762306a36Sopenharmony_ci						 CRYPTO_ALG_NEED_FALLBACK);
80862306a36Sopenharmony_ci		if (IS_ERR(bctx->shash)) {
80962306a36Sopenharmony_ci			dev_warn(ast_alg->hace_dev->dev,
81062306a36Sopenharmony_ci				 "base driver '%s' could not be loaded.\n",
81162306a36Sopenharmony_ci				 ast_alg->alg_base);
81262306a36Sopenharmony_ci			return PTR_ERR(bctx->shash);
81362306a36Sopenharmony_ci		}
81462306a36Sopenharmony_ci	}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci	return 0;
81762306a36Sopenharmony_ci}
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_cistatic void aspeed_sham_cra_exit(struct crypto_tfm *tfm)
82062306a36Sopenharmony_ci{
82162306a36Sopenharmony_ci	struct aspeed_sham_ctx *tctx = crypto_tfm_ctx(tfm);
82262306a36Sopenharmony_ci	struct aspeed_hace_dev *hace_dev = tctx->hace_dev;
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "%s\n", crypto_tfm_alg_name(tfm));
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	if (tctx->flags & SHA_FLAGS_HMAC) {
82762306a36Sopenharmony_ci		struct aspeed_sha_hmac_ctx *bctx = tctx->base;
82862306a36Sopenharmony_ci
82962306a36Sopenharmony_ci		crypto_free_shash(bctx->shash);
83062306a36Sopenharmony_ci	}
83162306a36Sopenharmony_ci}
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_cistatic int aspeed_sham_export(struct ahash_request *req, void *out)
83462306a36Sopenharmony_ci{
83562306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	memcpy(out, rctx, sizeof(*rctx));
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	return 0;
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistatic int aspeed_sham_import(struct ahash_request *req, const void *in)
84362306a36Sopenharmony_ci{
84462306a36Sopenharmony_ci	struct aspeed_sham_reqctx *rctx = ahash_request_ctx(req);
84562306a36Sopenharmony_ci
84662306a36Sopenharmony_ci	memcpy(rctx, in, sizeof(*rctx));
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	return 0;
84962306a36Sopenharmony_ci}
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_cistatic struct aspeed_hace_alg aspeed_ahash_algs[] = {
85262306a36Sopenharmony_ci	{
85362306a36Sopenharmony_ci		.alg.ahash.base = {
85462306a36Sopenharmony_ci			.init	= aspeed_sham_init,
85562306a36Sopenharmony_ci			.update	= aspeed_sham_update,
85662306a36Sopenharmony_ci			.final	= aspeed_sham_final,
85762306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
85862306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
85962306a36Sopenharmony_ci			.export	= aspeed_sham_export,
86062306a36Sopenharmony_ci			.import	= aspeed_sham_import,
86162306a36Sopenharmony_ci			.halg = {
86262306a36Sopenharmony_ci				.digestsize = SHA1_DIGEST_SIZE,
86362306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
86462306a36Sopenharmony_ci				.base = {
86562306a36Sopenharmony_ci					.cra_name		= "sha1",
86662306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-sha1",
86762306a36Sopenharmony_ci					.cra_priority		= 300,
86862306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
86962306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
87062306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
87162306a36Sopenharmony_ci					.cra_blocksize		= SHA1_BLOCK_SIZE,
87262306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx),
87362306a36Sopenharmony_ci					.cra_alignmask		= 0,
87462306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
87562306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
87662306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
87762306a36Sopenharmony_ci				}
87862306a36Sopenharmony_ci			}
87962306a36Sopenharmony_ci		},
88062306a36Sopenharmony_ci		.alg.ahash.op = {
88162306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
88262306a36Sopenharmony_ci		},
88362306a36Sopenharmony_ci	},
88462306a36Sopenharmony_ci	{
88562306a36Sopenharmony_ci		.alg.ahash.base = {
88662306a36Sopenharmony_ci			.init	= aspeed_sham_init,
88762306a36Sopenharmony_ci			.update	= aspeed_sham_update,
88862306a36Sopenharmony_ci			.final	= aspeed_sham_final,
88962306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
89062306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
89162306a36Sopenharmony_ci			.export	= aspeed_sham_export,
89262306a36Sopenharmony_ci			.import	= aspeed_sham_import,
89362306a36Sopenharmony_ci			.halg = {
89462306a36Sopenharmony_ci				.digestsize = SHA256_DIGEST_SIZE,
89562306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
89662306a36Sopenharmony_ci				.base = {
89762306a36Sopenharmony_ci					.cra_name		= "sha256",
89862306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-sha256",
89962306a36Sopenharmony_ci					.cra_priority		= 300,
90062306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
90162306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
90262306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
90362306a36Sopenharmony_ci					.cra_blocksize		= SHA256_BLOCK_SIZE,
90462306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx),
90562306a36Sopenharmony_ci					.cra_alignmask		= 0,
90662306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
90762306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
90862306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
90962306a36Sopenharmony_ci				}
91062306a36Sopenharmony_ci			}
91162306a36Sopenharmony_ci		},
91262306a36Sopenharmony_ci		.alg.ahash.op = {
91362306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
91462306a36Sopenharmony_ci		},
91562306a36Sopenharmony_ci	},
91662306a36Sopenharmony_ci	{
91762306a36Sopenharmony_ci		.alg.ahash.base = {
91862306a36Sopenharmony_ci			.init	= aspeed_sham_init,
91962306a36Sopenharmony_ci			.update	= aspeed_sham_update,
92062306a36Sopenharmony_ci			.final	= aspeed_sham_final,
92162306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
92262306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
92362306a36Sopenharmony_ci			.export	= aspeed_sham_export,
92462306a36Sopenharmony_ci			.import	= aspeed_sham_import,
92562306a36Sopenharmony_ci			.halg = {
92662306a36Sopenharmony_ci				.digestsize = SHA224_DIGEST_SIZE,
92762306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
92862306a36Sopenharmony_ci				.base = {
92962306a36Sopenharmony_ci					.cra_name		= "sha224",
93062306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-sha224",
93162306a36Sopenharmony_ci					.cra_priority		= 300,
93262306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
93362306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
93462306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
93562306a36Sopenharmony_ci					.cra_blocksize		= SHA224_BLOCK_SIZE,
93662306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx),
93762306a36Sopenharmony_ci					.cra_alignmask		= 0,
93862306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
93962306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
94062306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
94162306a36Sopenharmony_ci				}
94262306a36Sopenharmony_ci			}
94362306a36Sopenharmony_ci		},
94462306a36Sopenharmony_ci		.alg.ahash.op = {
94562306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
94662306a36Sopenharmony_ci		},
94762306a36Sopenharmony_ci	},
94862306a36Sopenharmony_ci	{
94962306a36Sopenharmony_ci		.alg_base = "sha1",
95062306a36Sopenharmony_ci		.alg.ahash.base = {
95162306a36Sopenharmony_ci			.init	= aspeed_sham_init,
95262306a36Sopenharmony_ci			.update	= aspeed_sham_update,
95362306a36Sopenharmony_ci			.final	= aspeed_sham_final,
95462306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
95562306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
95662306a36Sopenharmony_ci			.setkey	= aspeed_sham_setkey,
95762306a36Sopenharmony_ci			.export	= aspeed_sham_export,
95862306a36Sopenharmony_ci			.import	= aspeed_sham_import,
95962306a36Sopenharmony_ci			.halg = {
96062306a36Sopenharmony_ci				.digestsize = SHA1_DIGEST_SIZE,
96162306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
96262306a36Sopenharmony_ci				.base = {
96362306a36Sopenharmony_ci					.cra_name		= "hmac(sha1)",
96462306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-hmac-sha1",
96562306a36Sopenharmony_ci					.cra_priority		= 300,
96662306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
96762306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
96862306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
96962306a36Sopenharmony_ci					.cra_blocksize		= SHA1_BLOCK_SIZE,
97062306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx) +
97162306a36Sopenharmony_ci								sizeof(struct aspeed_sha_hmac_ctx),
97262306a36Sopenharmony_ci					.cra_alignmask		= 0,
97362306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
97462306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
97562306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
97662306a36Sopenharmony_ci				}
97762306a36Sopenharmony_ci			}
97862306a36Sopenharmony_ci		},
97962306a36Sopenharmony_ci		.alg.ahash.op = {
98062306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
98162306a36Sopenharmony_ci		},
98262306a36Sopenharmony_ci	},
98362306a36Sopenharmony_ci	{
98462306a36Sopenharmony_ci		.alg_base = "sha224",
98562306a36Sopenharmony_ci		.alg.ahash.base = {
98662306a36Sopenharmony_ci			.init	= aspeed_sham_init,
98762306a36Sopenharmony_ci			.update	= aspeed_sham_update,
98862306a36Sopenharmony_ci			.final	= aspeed_sham_final,
98962306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
99062306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
99162306a36Sopenharmony_ci			.setkey	= aspeed_sham_setkey,
99262306a36Sopenharmony_ci			.export	= aspeed_sham_export,
99362306a36Sopenharmony_ci			.import	= aspeed_sham_import,
99462306a36Sopenharmony_ci			.halg = {
99562306a36Sopenharmony_ci				.digestsize = SHA224_DIGEST_SIZE,
99662306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
99762306a36Sopenharmony_ci				.base = {
99862306a36Sopenharmony_ci					.cra_name		= "hmac(sha224)",
99962306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-hmac-sha224",
100062306a36Sopenharmony_ci					.cra_priority		= 300,
100162306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
100262306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
100362306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
100462306a36Sopenharmony_ci					.cra_blocksize		= SHA224_BLOCK_SIZE,
100562306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx) +
100662306a36Sopenharmony_ci								sizeof(struct aspeed_sha_hmac_ctx),
100762306a36Sopenharmony_ci					.cra_alignmask		= 0,
100862306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
100962306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
101062306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
101162306a36Sopenharmony_ci				}
101262306a36Sopenharmony_ci			}
101362306a36Sopenharmony_ci		},
101462306a36Sopenharmony_ci		.alg.ahash.op = {
101562306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
101662306a36Sopenharmony_ci		},
101762306a36Sopenharmony_ci	},
101862306a36Sopenharmony_ci	{
101962306a36Sopenharmony_ci		.alg_base = "sha256",
102062306a36Sopenharmony_ci		.alg.ahash.base = {
102162306a36Sopenharmony_ci			.init	= aspeed_sham_init,
102262306a36Sopenharmony_ci			.update	= aspeed_sham_update,
102362306a36Sopenharmony_ci			.final	= aspeed_sham_final,
102462306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
102562306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
102662306a36Sopenharmony_ci			.setkey	= aspeed_sham_setkey,
102762306a36Sopenharmony_ci			.export	= aspeed_sham_export,
102862306a36Sopenharmony_ci			.import	= aspeed_sham_import,
102962306a36Sopenharmony_ci			.halg = {
103062306a36Sopenharmony_ci				.digestsize = SHA256_DIGEST_SIZE,
103162306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
103262306a36Sopenharmony_ci				.base = {
103362306a36Sopenharmony_ci					.cra_name		= "hmac(sha256)",
103462306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-hmac-sha256",
103562306a36Sopenharmony_ci					.cra_priority		= 300,
103662306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
103762306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
103862306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
103962306a36Sopenharmony_ci					.cra_blocksize		= SHA256_BLOCK_SIZE,
104062306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx) +
104162306a36Sopenharmony_ci								sizeof(struct aspeed_sha_hmac_ctx),
104262306a36Sopenharmony_ci					.cra_alignmask		= 0,
104362306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
104462306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
104562306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
104662306a36Sopenharmony_ci				}
104762306a36Sopenharmony_ci			}
104862306a36Sopenharmony_ci		},
104962306a36Sopenharmony_ci		.alg.ahash.op = {
105062306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
105162306a36Sopenharmony_ci		},
105262306a36Sopenharmony_ci	},
105362306a36Sopenharmony_ci};
105462306a36Sopenharmony_ci
105562306a36Sopenharmony_cistatic struct aspeed_hace_alg aspeed_ahash_algs_g6[] = {
105662306a36Sopenharmony_ci	{
105762306a36Sopenharmony_ci		.alg.ahash.base = {
105862306a36Sopenharmony_ci			.init	= aspeed_sham_init,
105962306a36Sopenharmony_ci			.update	= aspeed_sham_update,
106062306a36Sopenharmony_ci			.final	= aspeed_sham_final,
106162306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
106262306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
106362306a36Sopenharmony_ci			.export	= aspeed_sham_export,
106462306a36Sopenharmony_ci			.import	= aspeed_sham_import,
106562306a36Sopenharmony_ci			.halg = {
106662306a36Sopenharmony_ci				.digestsize = SHA384_DIGEST_SIZE,
106762306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
106862306a36Sopenharmony_ci				.base = {
106962306a36Sopenharmony_ci					.cra_name		= "sha384",
107062306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-sha384",
107162306a36Sopenharmony_ci					.cra_priority		= 300,
107262306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
107362306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
107462306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
107562306a36Sopenharmony_ci					.cra_blocksize		= SHA384_BLOCK_SIZE,
107662306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx),
107762306a36Sopenharmony_ci					.cra_alignmask		= 0,
107862306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
107962306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
108062306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
108162306a36Sopenharmony_ci				}
108262306a36Sopenharmony_ci			}
108362306a36Sopenharmony_ci		},
108462306a36Sopenharmony_ci		.alg.ahash.op = {
108562306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
108662306a36Sopenharmony_ci		},
108762306a36Sopenharmony_ci	},
108862306a36Sopenharmony_ci	{
108962306a36Sopenharmony_ci		.alg.ahash.base = {
109062306a36Sopenharmony_ci			.init	= aspeed_sham_init,
109162306a36Sopenharmony_ci			.update	= aspeed_sham_update,
109262306a36Sopenharmony_ci			.final	= aspeed_sham_final,
109362306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
109462306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
109562306a36Sopenharmony_ci			.export	= aspeed_sham_export,
109662306a36Sopenharmony_ci			.import	= aspeed_sham_import,
109762306a36Sopenharmony_ci			.halg = {
109862306a36Sopenharmony_ci				.digestsize = SHA512_DIGEST_SIZE,
109962306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
110062306a36Sopenharmony_ci				.base = {
110162306a36Sopenharmony_ci					.cra_name		= "sha512",
110262306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-sha512",
110362306a36Sopenharmony_ci					.cra_priority		= 300,
110462306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
110562306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
110662306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
110762306a36Sopenharmony_ci					.cra_blocksize		= SHA512_BLOCK_SIZE,
110862306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx),
110962306a36Sopenharmony_ci					.cra_alignmask		= 0,
111062306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
111162306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
111262306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
111362306a36Sopenharmony_ci				}
111462306a36Sopenharmony_ci			}
111562306a36Sopenharmony_ci		},
111662306a36Sopenharmony_ci		.alg.ahash.op = {
111762306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
111862306a36Sopenharmony_ci		},
111962306a36Sopenharmony_ci	},
112062306a36Sopenharmony_ci	{
112162306a36Sopenharmony_ci		.alg_base = "sha384",
112262306a36Sopenharmony_ci		.alg.ahash.base = {
112362306a36Sopenharmony_ci			.init	= aspeed_sham_init,
112462306a36Sopenharmony_ci			.update	= aspeed_sham_update,
112562306a36Sopenharmony_ci			.final	= aspeed_sham_final,
112662306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
112762306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
112862306a36Sopenharmony_ci			.setkey	= aspeed_sham_setkey,
112962306a36Sopenharmony_ci			.export	= aspeed_sham_export,
113062306a36Sopenharmony_ci			.import	= aspeed_sham_import,
113162306a36Sopenharmony_ci			.halg = {
113262306a36Sopenharmony_ci				.digestsize = SHA384_DIGEST_SIZE,
113362306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
113462306a36Sopenharmony_ci				.base = {
113562306a36Sopenharmony_ci					.cra_name		= "hmac(sha384)",
113662306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-hmac-sha384",
113762306a36Sopenharmony_ci					.cra_priority		= 300,
113862306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
113962306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
114062306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
114162306a36Sopenharmony_ci					.cra_blocksize		= SHA384_BLOCK_SIZE,
114262306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx) +
114362306a36Sopenharmony_ci								sizeof(struct aspeed_sha_hmac_ctx),
114462306a36Sopenharmony_ci					.cra_alignmask		= 0,
114562306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
114662306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
114762306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
114862306a36Sopenharmony_ci				}
114962306a36Sopenharmony_ci			}
115062306a36Sopenharmony_ci		},
115162306a36Sopenharmony_ci		.alg.ahash.op = {
115262306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
115362306a36Sopenharmony_ci		},
115462306a36Sopenharmony_ci	},
115562306a36Sopenharmony_ci	{
115662306a36Sopenharmony_ci		.alg_base = "sha512",
115762306a36Sopenharmony_ci		.alg.ahash.base = {
115862306a36Sopenharmony_ci			.init	= aspeed_sham_init,
115962306a36Sopenharmony_ci			.update	= aspeed_sham_update,
116062306a36Sopenharmony_ci			.final	= aspeed_sham_final,
116162306a36Sopenharmony_ci			.finup	= aspeed_sham_finup,
116262306a36Sopenharmony_ci			.digest	= aspeed_sham_digest,
116362306a36Sopenharmony_ci			.setkey	= aspeed_sham_setkey,
116462306a36Sopenharmony_ci			.export	= aspeed_sham_export,
116562306a36Sopenharmony_ci			.import	= aspeed_sham_import,
116662306a36Sopenharmony_ci			.halg = {
116762306a36Sopenharmony_ci				.digestsize = SHA512_DIGEST_SIZE,
116862306a36Sopenharmony_ci				.statesize = sizeof(struct aspeed_sham_reqctx),
116962306a36Sopenharmony_ci				.base = {
117062306a36Sopenharmony_ci					.cra_name		= "hmac(sha512)",
117162306a36Sopenharmony_ci					.cra_driver_name	= "aspeed-hmac-sha512",
117262306a36Sopenharmony_ci					.cra_priority		= 300,
117362306a36Sopenharmony_ci					.cra_flags		= CRYPTO_ALG_TYPE_AHASH |
117462306a36Sopenharmony_ci								  CRYPTO_ALG_ASYNC |
117562306a36Sopenharmony_ci								  CRYPTO_ALG_KERN_DRIVER_ONLY,
117662306a36Sopenharmony_ci					.cra_blocksize		= SHA512_BLOCK_SIZE,
117762306a36Sopenharmony_ci					.cra_ctxsize		= sizeof(struct aspeed_sham_ctx) +
117862306a36Sopenharmony_ci								sizeof(struct aspeed_sha_hmac_ctx),
117962306a36Sopenharmony_ci					.cra_alignmask		= 0,
118062306a36Sopenharmony_ci					.cra_module		= THIS_MODULE,
118162306a36Sopenharmony_ci					.cra_init		= aspeed_sham_cra_init,
118262306a36Sopenharmony_ci					.cra_exit		= aspeed_sham_cra_exit,
118362306a36Sopenharmony_ci				}
118462306a36Sopenharmony_ci			}
118562306a36Sopenharmony_ci		},
118662306a36Sopenharmony_ci		.alg.ahash.op = {
118762306a36Sopenharmony_ci			.do_one_request = aspeed_ahash_do_one,
118862306a36Sopenharmony_ci		},
118962306a36Sopenharmony_ci	},
119062306a36Sopenharmony_ci};
119162306a36Sopenharmony_ci
119262306a36Sopenharmony_civoid aspeed_unregister_hace_hash_algs(struct aspeed_hace_dev *hace_dev)
119362306a36Sopenharmony_ci{
119462306a36Sopenharmony_ci	int i;
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(aspeed_ahash_algs); i++)
119762306a36Sopenharmony_ci		crypto_engine_unregister_ahash(&aspeed_ahash_algs[i].alg.ahash);
119862306a36Sopenharmony_ci
119962306a36Sopenharmony_ci	if (hace_dev->version != AST2600_VERSION)
120062306a36Sopenharmony_ci		return;
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(aspeed_ahash_algs_g6); i++)
120362306a36Sopenharmony_ci		crypto_engine_unregister_ahash(&aspeed_ahash_algs_g6[i].alg.ahash);
120462306a36Sopenharmony_ci}
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_civoid aspeed_register_hace_hash_algs(struct aspeed_hace_dev *hace_dev)
120762306a36Sopenharmony_ci{
120862306a36Sopenharmony_ci	int rc, i;
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	AHASH_DBG(hace_dev, "\n");
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(aspeed_ahash_algs); i++) {
121362306a36Sopenharmony_ci		aspeed_ahash_algs[i].hace_dev = hace_dev;
121462306a36Sopenharmony_ci		rc = crypto_engine_register_ahash(&aspeed_ahash_algs[i].alg.ahash);
121562306a36Sopenharmony_ci		if (rc) {
121662306a36Sopenharmony_ci			AHASH_DBG(hace_dev, "Failed to register %s\n",
121762306a36Sopenharmony_ci				  aspeed_ahash_algs[i].alg.ahash.base.halg.base.cra_name);
121862306a36Sopenharmony_ci		}
121962306a36Sopenharmony_ci	}
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_ci	if (hace_dev->version != AST2600_VERSION)
122262306a36Sopenharmony_ci		return;
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(aspeed_ahash_algs_g6); i++) {
122562306a36Sopenharmony_ci		aspeed_ahash_algs_g6[i].hace_dev = hace_dev;
122662306a36Sopenharmony_ci		rc = crypto_engine_register_ahash(&aspeed_ahash_algs_g6[i].alg.ahash);
122762306a36Sopenharmony_ci		if (rc) {
122862306a36Sopenharmony_ci			AHASH_DBG(hace_dev, "Failed to register %s\n",
122962306a36Sopenharmony_ci				  aspeed_ahash_algs_g6[i].alg.ahash.base.halg.base.cra_name);
123062306a36Sopenharmony_ci		}
123162306a36Sopenharmony_ci	}
123262306a36Sopenharmony_ci}
1233