162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file is part of STM32 Crypto driver for Linux.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
662306a36Sopenharmony_ci * Author(s): Lionel DEBIEVE <lionel.debieve@st.com> for STMicroelectronics.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <crypto/engine.h>
1062306a36Sopenharmony_ci#include <crypto/internal/hash.h>
1162306a36Sopenharmony_ci#include <crypto/md5.h>
1262306a36Sopenharmony_ci#include <crypto/scatterwalk.h>
1362306a36Sopenharmony_ci#include <crypto/sha1.h>
1462306a36Sopenharmony_ci#include <crypto/sha2.h>
1562306a36Sopenharmony_ci#include <crypto/sha3.h>
1662306a36Sopenharmony_ci#include <linux/clk.h>
1762306a36Sopenharmony_ci#include <linux/delay.h>
1862306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1962306a36Sopenharmony_ci#include <linux/dmaengine.h>
2062306a36Sopenharmony_ci#include <linux/interrupt.h>
2162306a36Sopenharmony_ci#include <linux/iopoll.h>
2262306a36Sopenharmony_ci#include <linux/kernel.h>
2362306a36Sopenharmony_ci#include <linux/module.h>
2462306a36Sopenharmony_ci#include <linux/of.h>
2562306a36Sopenharmony_ci#include <linux/platform_device.h>
2662306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2762306a36Sopenharmony_ci#include <linux/reset.h>
2862306a36Sopenharmony_ci#include <linux/string.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#define HASH_CR				0x00
3162306a36Sopenharmony_ci#define HASH_DIN			0x04
3262306a36Sopenharmony_ci#define HASH_STR			0x08
3362306a36Sopenharmony_ci#define HASH_UX500_HREG(x)		(0x0c + ((x) * 0x04))
3462306a36Sopenharmony_ci#define HASH_IMR			0x20
3562306a36Sopenharmony_ci#define HASH_SR				0x24
3662306a36Sopenharmony_ci#define HASH_CSR(x)			(0x0F8 + ((x) * 0x04))
3762306a36Sopenharmony_ci#define HASH_HREG(x)			(0x310 + ((x) * 0x04))
3862306a36Sopenharmony_ci#define HASH_HWCFGR			0x3F0
3962306a36Sopenharmony_ci#define HASH_VER			0x3F4
4062306a36Sopenharmony_ci#define HASH_ID				0x3F8
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/* Control Register */
4362306a36Sopenharmony_ci#define HASH_CR_INIT			BIT(2)
4462306a36Sopenharmony_ci#define HASH_CR_DMAE			BIT(3)
4562306a36Sopenharmony_ci#define HASH_CR_DATATYPE_POS		4
4662306a36Sopenharmony_ci#define HASH_CR_MODE			BIT(6)
4762306a36Sopenharmony_ci#define HASH_CR_ALGO_POS		7
4862306a36Sopenharmony_ci#define HASH_CR_MDMAT			BIT(13)
4962306a36Sopenharmony_ci#define HASH_CR_DMAA			BIT(14)
5062306a36Sopenharmony_ci#define HASH_CR_LKEY			BIT(16)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/* Interrupt */
5362306a36Sopenharmony_ci#define HASH_DINIE			BIT(0)
5462306a36Sopenharmony_ci#define HASH_DCIE			BIT(1)
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* Interrupt Mask */
5762306a36Sopenharmony_ci#define HASH_MASK_CALC_COMPLETION	BIT(0)
5862306a36Sopenharmony_ci#define HASH_MASK_DATA_INPUT		BIT(1)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/* Status Flags */
6162306a36Sopenharmony_ci#define HASH_SR_DATA_INPUT_READY	BIT(0)
6262306a36Sopenharmony_ci#define HASH_SR_OUTPUT_READY		BIT(1)
6362306a36Sopenharmony_ci#define HASH_SR_DMA_ACTIVE		BIT(2)
6462306a36Sopenharmony_ci#define HASH_SR_BUSY			BIT(3)
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/* STR Register */
6762306a36Sopenharmony_ci#define HASH_STR_NBLW_MASK		GENMASK(4, 0)
6862306a36Sopenharmony_ci#define HASH_STR_DCAL			BIT(8)
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci/* HWCFGR Register */
7162306a36Sopenharmony_ci#define HASH_HWCFG_DMA_MASK		GENMASK(3, 0)
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* Context swap register */
7462306a36Sopenharmony_ci#define HASH_CSR_NB_SHA256_HMAC		54
7562306a36Sopenharmony_ci#define HASH_CSR_NB_SHA256		38
7662306a36Sopenharmony_ci#define HASH_CSR_NB_SHA512_HMAC		103
7762306a36Sopenharmony_ci#define HASH_CSR_NB_SHA512		91
7862306a36Sopenharmony_ci#define HASH_CSR_NB_SHA3_HMAC		88
7962306a36Sopenharmony_ci#define HASH_CSR_NB_SHA3		72
8062306a36Sopenharmony_ci#define HASH_CSR_NB_MAX			HASH_CSR_NB_SHA512_HMAC
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci#define HASH_FLAGS_INIT			BIT(0)
8362306a36Sopenharmony_ci#define HASH_FLAGS_OUTPUT_READY		BIT(1)
8462306a36Sopenharmony_ci#define HASH_FLAGS_CPU			BIT(2)
8562306a36Sopenharmony_ci#define HASH_FLAGS_DMA_ACTIVE		BIT(3)
8662306a36Sopenharmony_ci#define HASH_FLAGS_HMAC_INIT		BIT(4)
8762306a36Sopenharmony_ci#define HASH_FLAGS_HMAC_FINAL		BIT(5)
8862306a36Sopenharmony_ci#define HASH_FLAGS_HMAC_KEY		BIT(6)
8962306a36Sopenharmony_ci#define HASH_FLAGS_SHA3_MODE		BIT(7)
9062306a36Sopenharmony_ci#define HASH_FLAGS_FINAL		BIT(15)
9162306a36Sopenharmony_ci#define HASH_FLAGS_FINUP		BIT(16)
9262306a36Sopenharmony_ci#define HASH_FLAGS_ALGO_MASK		GENMASK(20, 17)
9362306a36Sopenharmony_ci#define HASH_FLAGS_ALGO_SHIFT		17
9462306a36Sopenharmony_ci#define HASH_FLAGS_ERRORS		BIT(21)
9562306a36Sopenharmony_ci#define HASH_FLAGS_EMPTY		BIT(22)
9662306a36Sopenharmony_ci#define HASH_FLAGS_HMAC			BIT(23)
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci#define HASH_OP_UPDATE			1
9962306a36Sopenharmony_ci#define HASH_OP_FINAL			2
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci#define HASH_BURST_LEVEL		4
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cienum stm32_hash_data_format {
10462306a36Sopenharmony_ci	HASH_DATA_32_BITS		= 0x0,
10562306a36Sopenharmony_ci	HASH_DATA_16_BITS		= 0x1,
10662306a36Sopenharmony_ci	HASH_DATA_8_BITS		= 0x2,
10762306a36Sopenharmony_ci	HASH_DATA_1_BIT			= 0x3
10862306a36Sopenharmony_ci};
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci#define HASH_BUFLEN			(SHA3_224_BLOCK_SIZE + 4)
11162306a36Sopenharmony_ci#define HASH_MAX_KEY_SIZE		(SHA512_BLOCK_SIZE * 8)
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cienum stm32_hash_algo {
11462306a36Sopenharmony_ci	HASH_SHA1			= 0,
11562306a36Sopenharmony_ci	HASH_MD5			= 1,
11662306a36Sopenharmony_ci	HASH_SHA224			= 2,
11762306a36Sopenharmony_ci	HASH_SHA256			= 3,
11862306a36Sopenharmony_ci	HASH_SHA3_224			= 4,
11962306a36Sopenharmony_ci	HASH_SHA3_256			= 5,
12062306a36Sopenharmony_ci	HASH_SHA3_384			= 6,
12162306a36Sopenharmony_ci	HASH_SHA3_512			= 7,
12262306a36Sopenharmony_ci	HASH_SHA384			= 12,
12362306a36Sopenharmony_ci	HASH_SHA512			= 15,
12462306a36Sopenharmony_ci};
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cienum ux500_hash_algo {
12762306a36Sopenharmony_ci	HASH_SHA256_UX500		= 0,
12862306a36Sopenharmony_ci	HASH_SHA1_UX500			= 1,
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci#define HASH_AUTOSUSPEND_DELAY		50
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistruct stm32_hash_ctx {
13462306a36Sopenharmony_ci	struct stm32_hash_dev	*hdev;
13562306a36Sopenharmony_ci	struct crypto_shash	*xtfm;
13662306a36Sopenharmony_ci	unsigned long		flags;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	u8			key[HASH_MAX_KEY_SIZE];
13962306a36Sopenharmony_ci	int			keylen;
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistruct stm32_hash_state {
14362306a36Sopenharmony_ci	u32			flags;
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	u16			bufcnt;
14662306a36Sopenharmony_ci	u16			blocklen;
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci	u8 buffer[HASH_BUFLEN] __aligned(4);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci	/* hash state */
15162306a36Sopenharmony_ci	u32			hw_context[3 + HASH_CSR_NB_MAX];
15262306a36Sopenharmony_ci};
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_cistruct stm32_hash_request_ctx {
15562306a36Sopenharmony_ci	struct stm32_hash_dev	*hdev;
15662306a36Sopenharmony_ci	unsigned long		op;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	u8 digest[SHA512_DIGEST_SIZE] __aligned(sizeof(u32));
15962306a36Sopenharmony_ci	size_t			digcnt;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	/* DMA */
16262306a36Sopenharmony_ci	struct scatterlist	*sg;
16362306a36Sopenharmony_ci	unsigned int		offset;
16462306a36Sopenharmony_ci	unsigned int		total;
16562306a36Sopenharmony_ci	struct scatterlist	sg_key;
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	dma_addr_t		dma_addr;
16862306a36Sopenharmony_ci	size_t			dma_ct;
16962306a36Sopenharmony_ci	int			nents;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	u8			data_type;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	struct stm32_hash_state state;
17462306a36Sopenharmony_ci};
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_cistruct stm32_hash_algs_info {
17762306a36Sopenharmony_ci	struct ahash_engine_alg	*algs_list;
17862306a36Sopenharmony_ci	size_t			size;
17962306a36Sopenharmony_ci};
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistruct stm32_hash_pdata {
18262306a36Sopenharmony_ci	const int				alg_shift;
18362306a36Sopenharmony_ci	const struct stm32_hash_algs_info	*algs_info;
18462306a36Sopenharmony_ci	size_t					algs_info_size;
18562306a36Sopenharmony_ci	bool					has_sr;
18662306a36Sopenharmony_ci	bool					has_mdmat;
18762306a36Sopenharmony_ci	bool					broken_emptymsg;
18862306a36Sopenharmony_ci	bool					ux500;
18962306a36Sopenharmony_ci};
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistruct stm32_hash_dev {
19262306a36Sopenharmony_ci	struct list_head	list;
19362306a36Sopenharmony_ci	struct device		*dev;
19462306a36Sopenharmony_ci	struct clk		*clk;
19562306a36Sopenharmony_ci	struct reset_control	*rst;
19662306a36Sopenharmony_ci	void __iomem		*io_base;
19762306a36Sopenharmony_ci	phys_addr_t		phys_base;
19862306a36Sopenharmony_ci	u32			dma_mode;
19962306a36Sopenharmony_ci	bool			polled;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	struct ahash_request	*req;
20262306a36Sopenharmony_ci	struct crypto_engine	*engine;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	unsigned long		flags;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	struct dma_chan		*dma_lch;
20762306a36Sopenharmony_ci	struct completion	dma_completion;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	const struct stm32_hash_pdata	*pdata;
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistruct stm32_hash_drv {
21362306a36Sopenharmony_ci	struct list_head	dev_list;
21462306a36Sopenharmony_ci	spinlock_t		lock; /* List protection access */
21562306a36Sopenharmony_ci};
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic struct stm32_hash_drv stm32_hash = {
21862306a36Sopenharmony_ci	.dev_list = LIST_HEAD_INIT(stm32_hash.dev_list),
21962306a36Sopenharmony_ci	.lock = __SPIN_LOCK_UNLOCKED(stm32_hash.lock),
22062306a36Sopenharmony_ci};
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic void stm32_hash_dma_callback(void *param);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic inline u32 stm32_hash_read(struct stm32_hash_dev *hdev, u32 offset)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	return readl_relaxed(hdev->io_base + offset);
22762306a36Sopenharmony_ci}
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_cistatic inline void stm32_hash_write(struct stm32_hash_dev *hdev,
23062306a36Sopenharmony_ci				    u32 offset, u32 value)
23162306a36Sopenharmony_ci{
23262306a36Sopenharmony_ci	writel_relaxed(value, hdev->io_base + offset);
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic inline int stm32_hash_wait_busy(struct stm32_hash_dev *hdev)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	u32 status;
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci	/* The Ux500 lacks the special status register, we poll the DCAL bit instead */
24062306a36Sopenharmony_ci	if (!hdev->pdata->has_sr)
24162306a36Sopenharmony_ci		return readl_relaxed_poll_timeout(hdev->io_base + HASH_STR, status,
24262306a36Sopenharmony_ci						  !(status & HASH_STR_DCAL), 10, 10000);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	return readl_relaxed_poll_timeout(hdev->io_base + HASH_SR, status,
24562306a36Sopenharmony_ci				   !(status & HASH_SR_BUSY), 10, 10000);
24662306a36Sopenharmony_ci}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_cistatic void stm32_hash_set_nblw(struct stm32_hash_dev *hdev, int length)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	u32 reg;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	reg = stm32_hash_read(hdev, HASH_STR);
25362306a36Sopenharmony_ci	reg &= ~(HASH_STR_NBLW_MASK);
25462306a36Sopenharmony_ci	reg |= (8U * ((length) % 4U));
25562306a36Sopenharmony_ci	stm32_hash_write(hdev, HASH_STR, reg);
25662306a36Sopenharmony_ci}
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic int stm32_hash_write_key(struct stm32_hash_dev *hdev)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req);
26162306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm);
26262306a36Sopenharmony_ci	u32 reg;
26362306a36Sopenharmony_ci	int keylen = ctx->keylen;
26462306a36Sopenharmony_ci	void *key = ctx->key;
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	if (keylen) {
26762306a36Sopenharmony_ci		stm32_hash_set_nblw(hdev, keylen);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci		while (keylen > 0) {
27062306a36Sopenharmony_ci			stm32_hash_write(hdev, HASH_DIN, *(u32 *)key);
27162306a36Sopenharmony_ci			keylen -= 4;
27262306a36Sopenharmony_ci			key += 4;
27362306a36Sopenharmony_ci		}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci		reg = stm32_hash_read(hdev, HASH_STR);
27662306a36Sopenharmony_ci		reg |= HASH_STR_DCAL;
27762306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_STR, reg);
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci		return -EINPROGRESS;
28062306a36Sopenharmony_ci	}
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	return 0;
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_cistatic void stm32_hash_write_ctrl(struct stm32_hash_dev *hdev)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req);
28862306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req);
28962306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm);
29062306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
29162306a36Sopenharmony_ci	u32 alg = (state->flags & HASH_FLAGS_ALGO_MASK) >> HASH_FLAGS_ALGO_SHIFT;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	u32 reg = HASH_CR_INIT;
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	if (!(hdev->flags & HASH_FLAGS_INIT)) {
29662306a36Sopenharmony_ci		if (hdev->pdata->ux500) {
29762306a36Sopenharmony_ci			reg |= ((alg & BIT(0)) << HASH_CR_ALGO_POS);
29862306a36Sopenharmony_ci		} else {
29962306a36Sopenharmony_ci			if (hdev->pdata->alg_shift == HASH_CR_ALGO_POS)
30062306a36Sopenharmony_ci				reg |= ((alg & BIT(1)) << 17) |
30162306a36Sopenharmony_ci				       ((alg & BIT(0)) << HASH_CR_ALGO_POS);
30262306a36Sopenharmony_ci			else
30362306a36Sopenharmony_ci				reg |= alg << hdev->pdata->alg_shift;
30462306a36Sopenharmony_ci		}
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci		reg |= (rctx->data_type << HASH_CR_DATATYPE_POS);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		if (state->flags & HASH_FLAGS_HMAC) {
30962306a36Sopenharmony_ci			hdev->flags |= HASH_FLAGS_HMAC;
31062306a36Sopenharmony_ci			reg |= HASH_CR_MODE;
31162306a36Sopenharmony_ci			if (ctx->keylen > crypto_ahash_blocksize(tfm))
31262306a36Sopenharmony_ci				reg |= HASH_CR_LKEY;
31362306a36Sopenharmony_ci		}
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci		if (!hdev->polled)
31662306a36Sopenharmony_ci			stm32_hash_write(hdev, HASH_IMR, HASH_DCIE);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_CR, reg);
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci		hdev->flags |= HASH_FLAGS_INIT;
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci		/*
32362306a36Sopenharmony_ci		 * After first block + 1 words are fill up,
32462306a36Sopenharmony_ci		 * we only need to fill 1 block to start partial computation
32562306a36Sopenharmony_ci		 */
32662306a36Sopenharmony_ci		rctx->state.blocklen -= sizeof(u32);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci		dev_dbg(hdev->dev, "Write Control %x\n", reg);
32962306a36Sopenharmony_ci	}
33062306a36Sopenharmony_ci}
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_cistatic void stm32_hash_append_sg(struct stm32_hash_request_ctx *rctx)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
33562306a36Sopenharmony_ci	size_t count;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	while ((state->bufcnt < state->blocklen) && rctx->total) {
33862306a36Sopenharmony_ci		count = min(rctx->sg->length - rctx->offset, rctx->total);
33962306a36Sopenharmony_ci		count = min_t(size_t, count, state->blocklen - state->bufcnt);
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci		if (count <= 0) {
34262306a36Sopenharmony_ci			if ((rctx->sg->length == 0) && !sg_is_last(rctx->sg)) {
34362306a36Sopenharmony_ci				rctx->sg = sg_next(rctx->sg);
34462306a36Sopenharmony_ci				continue;
34562306a36Sopenharmony_ci			} else {
34662306a36Sopenharmony_ci				break;
34762306a36Sopenharmony_ci			}
34862306a36Sopenharmony_ci		}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci		scatterwalk_map_and_copy(state->buffer + state->bufcnt,
35162306a36Sopenharmony_ci					 rctx->sg, rctx->offset, count, 0);
35262306a36Sopenharmony_ci
35362306a36Sopenharmony_ci		state->bufcnt += count;
35462306a36Sopenharmony_ci		rctx->offset += count;
35562306a36Sopenharmony_ci		rctx->total -= count;
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci		if (rctx->offset == rctx->sg->length) {
35862306a36Sopenharmony_ci			rctx->sg = sg_next(rctx->sg);
35962306a36Sopenharmony_ci			if (rctx->sg)
36062306a36Sopenharmony_ci				rctx->offset = 0;
36162306a36Sopenharmony_ci			else
36262306a36Sopenharmony_ci				rctx->total = 0;
36362306a36Sopenharmony_ci		}
36462306a36Sopenharmony_ci	}
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic int stm32_hash_xmit_cpu(struct stm32_hash_dev *hdev,
36862306a36Sopenharmony_ci			       const u8 *buf, size_t length, int final)
36962306a36Sopenharmony_ci{
37062306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req);
37162306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
37262306a36Sopenharmony_ci	unsigned int count, len32;
37362306a36Sopenharmony_ci	const u32 *buffer = (const u32 *)buf;
37462306a36Sopenharmony_ci	u32 reg;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	if (final) {
37762306a36Sopenharmony_ci		hdev->flags |= HASH_FLAGS_FINAL;
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci		/* Do not process empty messages if hw is buggy. */
38062306a36Sopenharmony_ci		if (!(hdev->flags & HASH_FLAGS_INIT) && !length &&
38162306a36Sopenharmony_ci		    hdev->pdata->broken_emptymsg) {
38262306a36Sopenharmony_ci			state->flags |= HASH_FLAGS_EMPTY;
38362306a36Sopenharmony_ci			return 0;
38462306a36Sopenharmony_ci		}
38562306a36Sopenharmony_ci	}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	len32 = DIV_ROUND_UP(length, sizeof(u32));
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	dev_dbg(hdev->dev, "%s: length: %zd, final: %x len32 %i\n",
39062306a36Sopenharmony_ci		__func__, length, final, len32);
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	hdev->flags |= HASH_FLAGS_CPU;
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	stm32_hash_write_ctrl(hdev);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	if (stm32_hash_wait_busy(hdev))
39762306a36Sopenharmony_ci		return -ETIMEDOUT;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	if ((hdev->flags & HASH_FLAGS_HMAC) &&
40062306a36Sopenharmony_ci	    (!(hdev->flags & HASH_FLAGS_HMAC_KEY))) {
40162306a36Sopenharmony_ci		hdev->flags |= HASH_FLAGS_HMAC_KEY;
40262306a36Sopenharmony_ci		stm32_hash_write_key(hdev);
40362306a36Sopenharmony_ci		if (stm32_hash_wait_busy(hdev))
40462306a36Sopenharmony_ci			return -ETIMEDOUT;
40562306a36Sopenharmony_ci	}
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci	for (count = 0; count < len32; count++)
40862306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_DIN, buffer[count]);
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci	if (final) {
41162306a36Sopenharmony_ci		if (stm32_hash_wait_busy(hdev))
41262306a36Sopenharmony_ci			return -ETIMEDOUT;
41362306a36Sopenharmony_ci
41462306a36Sopenharmony_ci		stm32_hash_set_nblw(hdev, length);
41562306a36Sopenharmony_ci		reg = stm32_hash_read(hdev, HASH_STR);
41662306a36Sopenharmony_ci		reg |= HASH_STR_DCAL;
41762306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_STR, reg);
41862306a36Sopenharmony_ci		if (hdev->flags & HASH_FLAGS_HMAC) {
41962306a36Sopenharmony_ci			if (stm32_hash_wait_busy(hdev))
42062306a36Sopenharmony_ci				return -ETIMEDOUT;
42162306a36Sopenharmony_ci			stm32_hash_write_key(hdev);
42262306a36Sopenharmony_ci		}
42362306a36Sopenharmony_ci		return -EINPROGRESS;
42462306a36Sopenharmony_ci	}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	return 0;
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_cistatic int hash_swap_reg(struct stm32_hash_request_ctx *rctx)
43062306a36Sopenharmony_ci{
43162306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	switch ((state->flags & HASH_FLAGS_ALGO_MASK) >>
43462306a36Sopenharmony_ci		HASH_FLAGS_ALGO_SHIFT) {
43562306a36Sopenharmony_ci	case HASH_MD5:
43662306a36Sopenharmony_ci	case HASH_SHA1:
43762306a36Sopenharmony_ci	case HASH_SHA224:
43862306a36Sopenharmony_ci	case HASH_SHA256:
43962306a36Sopenharmony_ci		if (state->flags & HASH_FLAGS_HMAC)
44062306a36Sopenharmony_ci			return HASH_CSR_NB_SHA256_HMAC;
44162306a36Sopenharmony_ci		else
44262306a36Sopenharmony_ci			return HASH_CSR_NB_SHA256;
44362306a36Sopenharmony_ci		break;
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci	case HASH_SHA384:
44662306a36Sopenharmony_ci	case HASH_SHA512:
44762306a36Sopenharmony_ci		if (state->flags & HASH_FLAGS_HMAC)
44862306a36Sopenharmony_ci			return HASH_CSR_NB_SHA512_HMAC;
44962306a36Sopenharmony_ci		else
45062306a36Sopenharmony_ci			return HASH_CSR_NB_SHA512;
45162306a36Sopenharmony_ci		break;
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci	case HASH_SHA3_224:
45462306a36Sopenharmony_ci	case HASH_SHA3_256:
45562306a36Sopenharmony_ci	case HASH_SHA3_384:
45662306a36Sopenharmony_ci	case HASH_SHA3_512:
45762306a36Sopenharmony_ci		if (state->flags & HASH_FLAGS_HMAC)
45862306a36Sopenharmony_ci			return HASH_CSR_NB_SHA3_HMAC;
45962306a36Sopenharmony_ci		else
46062306a36Sopenharmony_ci			return HASH_CSR_NB_SHA3;
46162306a36Sopenharmony_ci		break;
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	default:
46462306a36Sopenharmony_ci		return -EINVAL;
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci}
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_cistatic int stm32_hash_update_cpu(struct stm32_hash_dev *hdev)
46962306a36Sopenharmony_ci{
47062306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req);
47162306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
47262306a36Sopenharmony_ci	u32 *preg = state->hw_context;
47362306a36Sopenharmony_ci	int bufcnt, err = 0, final;
47462306a36Sopenharmony_ci	int i, swap_reg;
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	dev_dbg(hdev->dev, "%s flags %x\n", __func__, state->flags);
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	final = state->flags & HASH_FLAGS_FINAL;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	while ((rctx->total >= state->blocklen) ||
48162306a36Sopenharmony_ci	       (state->bufcnt + rctx->total >= state->blocklen)) {
48262306a36Sopenharmony_ci		stm32_hash_append_sg(rctx);
48362306a36Sopenharmony_ci		bufcnt = state->bufcnt;
48462306a36Sopenharmony_ci		state->bufcnt = 0;
48562306a36Sopenharmony_ci		err = stm32_hash_xmit_cpu(hdev, state->buffer, bufcnt, 0);
48662306a36Sopenharmony_ci		if (err)
48762306a36Sopenharmony_ci			return err;
48862306a36Sopenharmony_ci	}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	stm32_hash_append_sg(rctx);
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	if (final) {
49362306a36Sopenharmony_ci		bufcnt = state->bufcnt;
49462306a36Sopenharmony_ci		state->bufcnt = 0;
49562306a36Sopenharmony_ci		return stm32_hash_xmit_cpu(hdev, state->buffer, bufcnt, 1);
49662306a36Sopenharmony_ci	}
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	if (!(hdev->flags & HASH_FLAGS_INIT))
49962306a36Sopenharmony_ci		return 0;
50062306a36Sopenharmony_ci
50162306a36Sopenharmony_ci	if (stm32_hash_wait_busy(hdev))
50262306a36Sopenharmony_ci		return -ETIMEDOUT;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	swap_reg = hash_swap_reg(rctx);
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	if (!hdev->pdata->ux500)
50762306a36Sopenharmony_ci		*preg++ = stm32_hash_read(hdev, HASH_IMR);
50862306a36Sopenharmony_ci	*preg++ = stm32_hash_read(hdev, HASH_STR);
50962306a36Sopenharmony_ci	*preg++ = stm32_hash_read(hdev, HASH_CR);
51062306a36Sopenharmony_ci	for (i = 0; i < swap_reg; i++)
51162306a36Sopenharmony_ci		*preg++ = stm32_hash_read(hdev, HASH_CSR(i));
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	state->flags |= HASH_FLAGS_INIT;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	return err;
51662306a36Sopenharmony_ci}
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_cistatic int stm32_hash_xmit_dma(struct stm32_hash_dev *hdev,
51962306a36Sopenharmony_ci			       struct scatterlist *sg, int length, int mdma)
52062306a36Sopenharmony_ci{
52162306a36Sopenharmony_ci	struct dma_async_tx_descriptor *in_desc;
52262306a36Sopenharmony_ci	dma_cookie_t cookie;
52362306a36Sopenharmony_ci	u32 reg;
52462306a36Sopenharmony_ci	int err;
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci	in_desc = dmaengine_prep_slave_sg(hdev->dma_lch, sg, 1,
52762306a36Sopenharmony_ci					  DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT |
52862306a36Sopenharmony_ci					  DMA_CTRL_ACK);
52962306a36Sopenharmony_ci	if (!in_desc) {
53062306a36Sopenharmony_ci		dev_err(hdev->dev, "dmaengine_prep_slave error\n");
53162306a36Sopenharmony_ci		return -ENOMEM;
53262306a36Sopenharmony_ci	}
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	reinit_completion(&hdev->dma_completion);
53562306a36Sopenharmony_ci	in_desc->callback = stm32_hash_dma_callback;
53662306a36Sopenharmony_ci	in_desc->callback_param = hdev;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	hdev->flags |= HASH_FLAGS_FINAL;
53962306a36Sopenharmony_ci	hdev->flags |= HASH_FLAGS_DMA_ACTIVE;
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	reg = stm32_hash_read(hdev, HASH_CR);
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci	if (hdev->pdata->has_mdmat) {
54462306a36Sopenharmony_ci		if (mdma)
54562306a36Sopenharmony_ci			reg |= HASH_CR_MDMAT;
54662306a36Sopenharmony_ci		else
54762306a36Sopenharmony_ci			reg &= ~HASH_CR_MDMAT;
54862306a36Sopenharmony_ci	}
54962306a36Sopenharmony_ci	reg |= HASH_CR_DMAE;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	stm32_hash_write(hdev, HASH_CR, reg);
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	stm32_hash_set_nblw(hdev, length);
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	cookie = dmaengine_submit(in_desc);
55662306a36Sopenharmony_ci	err = dma_submit_error(cookie);
55762306a36Sopenharmony_ci	if (err)
55862306a36Sopenharmony_ci		return -ENOMEM;
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	dma_async_issue_pending(hdev->dma_lch);
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	if (!wait_for_completion_timeout(&hdev->dma_completion,
56362306a36Sopenharmony_ci					 msecs_to_jiffies(100)))
56462306a36Sopenharmony_ci		err = -ETIMEDOUT;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci	if (dma_async_is_tx_complete(hdev->dma_lch, cookie,
56762306a36Sopenharmony_ci				     NULL, NULL) != DMA_COMPLETE)
56862306a36Sopenharmony_ci		err = -ETIMEDOUT;
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	if (err) {
57162306a36Sopenharmony_ci		dev_err(hdev->dev, "DMA Error %i\n", err);
57262306a36Sopenharmony_ci		dmaengine_terminate_all(hdev->dma_lch);
57362306a36Sopenharmony_ci		return err;
57462306a36Sopenharmony_ci	}
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	return -EINPROGRESS;
57762306a36Sopenharmony_ci}
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_cistatic void stm32_hash_dma_callback(void *param)
58062306a36Sopenharmony_ci{
58162306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = param;
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci	complete(&hdev->dma_completion);
58462306a36Sopenharmony_ci}
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_cistatic int stm32_hash_hmac_dma_send(struct stm32_hash_dev *hdev)
58762306a36Sopenharmony_ci{
58862306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req);
58962306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(hdev->req);
59062306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm);
59162306a36Sopenharmony_ci	int err;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci	if (ctx->keylen < rctx->state.blocklen || hdev->dma_mode == 1) {
59462306a36Sopenharmony_ci		err = stm32_hash_write_key(hdev);
59562306a36Sopenharmony_ci		if (stm32_hash_wait_busy(hdev))
59662306a36Sopenharmony_ci			return -ETIMEDOUT;
59762306a36Sopenharmony_ci	} else {
59862306a36Sopenharmony_ci		if (!(hdev->flags & HASH_FLAGS_HMAC_KEY))
59962306a36Sopenharmony_ci			sg_init_one(&rctx->sg_key, ctx->key,
60062306a36Sopenharmony_ci				    ALIGN(ctx->keylen, sizeof(u32)));
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci		rctx->dma_ct = dma_map_sg(hdev->dev, &rctx->sg_key, 1,
60362306a36Sopenharmony_ci					  DMA_TO_DEVICE);
60462306a36Sopenharmony_ci		if (rctx->dma_ct == 0) {
60562306a36Sopenharmony_ci			dev_err(hdev->dev, "dma_map_sg error\n");
60662306a36Sopenharmony_ci			return -ENOMEM;
60762306a36Sopenharmony_ci		}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci		err = stm32_hash_xmit_dma(hdev, &rctx->sg_key, ctx->keylen, 0);
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci		dma_unmap_sg(hdev->dev, &rctx->sg_key, 1, DMA_TO_DEVICE);
61262306a36Sopenharmony_ci	}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	return err;
61562306a36Sopenharmony_ci}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_cistatic int stm32_hash_dma_init(struct stm32_hash_dev *hdev)
61862306a36Sopenharmony_ci{
61962306a36Sopenharmony_ci	struct dma_slave_config dma_conf;
62062306a36Sopenharmony_ci	struct dma_chan *chan;
62162306a36Sopenharmony_ci	int err;
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	memset(&dma_conf, 0, sizeof(dma_conf));
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	dma_conf.direction = DMA_MEM_TO_DEV;
62662306a36Sopenharmony_ci	dma_conf.dst_addr = hdev->phys_base + HASH_DIN;
62762306a36Sopenharmony_ci	dma_conf.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
62862306a36Sopenharmony_ci	dma_conf.src_maxburst = HASH_BURST_LEVEL;
62962306a36Sopenharmony_ci	dma_conf.dst_maxburst = HASH_BURST_LEVEL;
63062306a36Sopenharmony_ci	dma_conf.device_fc = false;
63162306a36Sopenharmony_ci
63262306a36Sopenharmony_ci	chan = dma_request_chan(hdev->dev, "in");
63362306a36Sopenharmony_ci	if (IS_ERR(chan))
63462306a36Sopenharmony_ci		return PTR_ERR(chan);
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	hdev->dma_lch = chan;
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ci	err = dmaengine_slave_config(hdev->dma_lch, &dma_conf);
63962306a36Sopenharmony_ci	if (err) {
64062306a36Sopenharmony_ci		dma_release_channel(hdev->dma_lch);
64162306a36Sopenharmony_ci		hdev->dma_lch = NULL;
64262306a36Sopenharmony_ci		dev_err(hdev->dev, "Couldn't configure DMA slave.\n");
64362306a36Sopenharmony_ci		return err;
64462306a36Sopenharmony_ci	}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	init_completion(&hdev->dma_completion);
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci	return 0;
64962306a36Sopenharmony_ci}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_cistatic int stm32_hash_dma_send(struct stm32_hash_dev *hdev)
65262306a36Sopenharmony_ci{
65362306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req);
65462306a36Sopenharmony_ci	u32 *buffer = (void *)rctx->state.buffer;
65562306a36Sopenharmony_ci	struct scatterlist sg[1], *tsg;
65662306a36Sopenharmony_ci	int err = 0, reg, ncp = 0;
65762306a36Sopenharmony_ci	unsigned int i, len = 0, bufcnt = 0;
65862306a36Sopenharmony_ci	bool is_last = false;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	rctx->sg = hdev->req->src;
66162306a36Sopenharmony_ci	rctx->total = hdev->req->nbytes;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	rctx->nents = sg_nents(rctx->sg);
66462306a36Sopenharmony_ci	if (rctx->nents < 0)
66562306a36Sopenharmony_ci		return -EINVAL;
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	stm32_hash_write_ctrl(hdev);
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	if (hdev->flags & HASH_FLAGS_HMAC) {
67062306a36Sopenharmony_ci		err = stm32_hash_hmac_dma_send(hdev);
67162306a36Sopenharmony_ci		if (err != -EINPROGRESS)
67262306a36Sopenharmony_ci			return err;
67362306a36Sopenharmony_ci	}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	for_each_sg(rctx->sg, tsg, rctx->nents, i) {
67662306a36Sopenharmony_ci		sg[0] = *tsg;
67762306a36Sopenharmony_ci		len = sg->length;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci		if (sg_is_last(sg) || (bufcnt + sg[0].length) >= rctx->total) {
68062306a36Sopenharmony_ci			sg->length = rctx->total - bufcnt;
68162306a36Sopenharmony_ci			is_last = true;
68262306a36Sopenharmony_ci			if (hdev->dma_mode == 1) {
68362306a36Sopenharmony_ci				len = (ALIGN(sg->length, 16) - 16);
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci				ncp = sg_pcopy_to_buffer(
68662306a36Sopenharmony_ci					rctx->sg, rctx->nents,
68762306a36Sopenharmony_ci					rctx->state.buffer, sg->length - len,
68862306a36Sopenharmony_ci					rctx->total - sg->length + len);
68962306a36Sopenharmony_ci
69062306a36Sopenharmony_ci				sg->length = len;
69162306a36Sopenharmony_ci			} else {
69262306a36Sopenharmony_ci				if (!(IS_ALIGNED(sg->length, sizeof(u32)))) {
69362306a36Sopenharmony_ci					len = sg->length;
69462306a36Sopenharmony_ci					sg->length = ALIGN(sg->length,
69562306a36Sopenharmony_ci							   sizeof(u32));
69662306a36Sopenharmony_ci				}
69762306a36Sopenharmony_ci			}
69862306a36Sopenharmony_ci		}
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci		rctx->dma_ct = dma_map_sg(hdev->dev, sg, 1,
70162306a36Sopenharmony_ci					  DMA_TO_DEVICE);
70262306a36Sopenharmony_ci		if (rctx->dma_ct == 0) {
70362306a36Sopenharmony_ci			dev_err(hdev->dev, "dma_map_sg error\n");
70462306a36Sopenharmony_ci			return -ENOMEM;
70562306a36Sopenharmony_ci		}
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_ci		err = stm32_hash_xmit_dma(hdev, sg, len, !is_last);
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci		bufcnt += sg[0].length;
71062306a36Sopenharmony_ci		dma_unmap_sg(hdev->dev, sg, 1, DMA_TO_DEVICE);
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci		if (err == -ENOMEM)
71362306a36Sopenharmony_ci			return err;
71462306a36Sopenharmony_ci		if (is_last)
71562306a36Sopenharmony_ci			break;
71662306a36Sopenharmony_ci	}
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	if (hdev->dma_mode == 1) {
71962306a36Sopenharmony_ci		if (stm32_hash_wait_busy(hdev))
72062306a36Sopenharmony_ci			return -ETIMEDOUT;
72162306a36Sopenharmony_ci		reg = stm32_hash_read(hdev, HASH_CR);
72262306a36Sopenharmony_ci		reg &= ~HASH_CR_DMAE;
72362306a36Sopenharmony_ci		reg |= HASH_CR_DMAA;
72462306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_CR, reg);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci		if (ncp) {
72762306a36Sopenharmony_ci			memset(buffer + ncp, 0,
72862306a36Sopenharmony_ci			       DIV_ROUND_UP(ncp, sizeof(u32)) - ncp);
72962306a36Sopenharmony_ci			writesl(hdev->io_base + HASH_DIN, buffer,
73062306a36Sopenharmony_ci				DIV_ROUND_UP(ncp, sizeof(u32)));
73162306a36Sopenharmony_ci		}
73262306a36Sopenharmony_ci		stm32_hash_set_nblw(hdev, ncp);
73362306a36Sopenharmony_ci		reg = stm32_hash_read(hdev, HASH_STR);
73462306a36Sopenharmony_ci		reg |= HASH_STR_DCAL;
73562306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_STR, reg);
73662306a36Sopenharmony_ci		err = -EINPROGRESS;
73762306a36Sopenharmony_ci	}
73862306a36Sopenharmony_ci
73962306a36Sopenharmony_ci	if (hdev->flags & HASH_FLAGS_HMAC) {
74062306a36Sopenharmony_ci		if (stm32_hash_wait_busy(hdev))
74162306a36Sopenharmony_ci			return -ETIMEDOUT;
74262306a36Sopenharmony_ci		err = stm32_hash_hmac_dma_send(hdev);
74362306a36Sopenharmony_ci	}
74462306a36Sopenharmony_ci
74562306a36Sopenharmony_ci	return err;
74662306a36Sopenharmony_ci}
74762306a36Sopenharmony_ci
74862306a36Sopenharmony_cistatic struct stm32_hash_dev *stm32_hash_find_dev(struct stm32_hash_ctx *ctx)
74962306a36Sopenharmony_ci{
75062306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = NULL, *tmp;
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci	spin_lock_bh(&stm32_hash.lock);
75362306a36Sopenharmony_ci	if (!ctx->hdev) {
75462306a36Sopenharmony_ci		list_for_each_entry(tmp, &stm32_hash.dev_list, list) {
75562306a36Sopenharmony_ci			hdev = tmp;
75662306a36Sopenharmony_ci			break;
75762306a36Sopenharmony_ci		}
75862306a36Sopenharmony_ci		ctx->hdev = hdev;
75962306a36Sopenharmony_ci	} else {
76062306a36Sopenharmony_ci		hdev = ctx->hdev;
76162306a36Sopenharmony_ci	}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	spin_unlock_bh(&stm32_hash.lock);
76462306a36Sopenharmony_ci
76562306a36Sopenharmony_ci	return hdev;
76662306a36Sopenharmony_ci}
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_cistatic bool stm32_hash_dma_aligned_data(struct ahash_request *req)
76962306a36Sopenharmony_ci{
77062306a36Sopenharmony_ci	struct scatterlist *sg;
77162306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
77262306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
77362306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
77462306a36Sopenharmony_ci	int i;
77562306a36Sopenharmony_ci
77662306a36Sopenharmony_ci	if (!hdev->dma_lch || req->nbytes <= rctx->state.blocklen)
77762306a36Sopenharmony_ci		return false;
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	if (sg_nents(req->src) > 1) {
78062306a36Sopenharmony_ci		if (hdev->dma_mode == 1)
78162306a36Sopenharmony_ci			return false;
78262306a36Sopenharmony_ci		for_each_sg(req->src, sg, sg_nents(req->src), i) {
78362306a36Sopenharmony_ci			if ((!IS_ALIGNED(sg->length, sizeof(u32))) &&
78462306a36Sopenharmony_ci			    (!sg_is_last(sg)))
78562306a36Sopenharmony_ci				return false;
78662306a36Sopenharmony_ci		}
78762306a36Sopenharmony_ci	}
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci	if (req->src->offset % 4)
79062306a36Sopenharmony_ci		return false;
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci	return true;
79362306a36Sopenharmony_ci}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_cistatic int stm32_hash_init(struct ahash_request *req)
79662306a36Sopenharmony_ci{
79762306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
79862306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm);
79962306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
80062306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
80162306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
80262306a36Sopenharmony_ci	bool sha3_mode = ctx->flags & HASH_FLAGS_SHA3_MODE;
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	rctx->hdev = hdev;
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	state->flags = HASH_FLAGS_CPU;
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	if (sha3_mode)
80962306a36Sopenharmony_ci		state->flags |= HASH_FLAGS_SHA3_MODE;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	rctx->digcnt = crypto_ahash_digestsize(tfm);
81262306a36Sopenharmony_ci	switch (rctx->digcnt) {
81362306a36Sopenharmony_ci	case MD5_DIGEST_SIZE:
81462306a36Sopenharmony_ci		state->flags |= HASH_MD5 << HASH_FLAGS_ALGO_SHIFT;
81562306a36Sopenharmony_ci		break;
81662306a36Sopenharmony_ci	case SHA1_DIGEST_SIZE:
81762306a36Sopenharmony_ci		if (hdev->pdata->ux500)
81862306a36Sopenharmony_ci			state->flags |= HASH_SHA1_UX500 << HASH_FLAGS_ALGO_SHIFT;
81962306a36Sopenharmony_ci		else
82062306a36Sopenharmony_ci			state->flags |= HASH_SHA1 << HASH_FLAGS_ALGO_SHIFT;
82162306a36Sopenharmony_ci		break;
82262306a36Sopenharmony_ci	case SHA224_DIGEST_SIZE:
82362306a36Sopenharmony_ci		if (sha3_mode)
82462306a36Sopenharmony_ci			state->flags |= HASH_SHA3_224 << HASH_FLAGS_ALGO_SHIFT;
82562306a36Sopenharmony_ci		else
82662306a36Sopenharmony_ci			state->flags |= HASH_SHA224 << HASH_FLAGS_ALGO_SHIFT;
82762306a36Sopenharmony_ci		break;
82862306a36Sopenharmony_ci	case SHA256_DIGEST_SIZE:
82962306a36Sopenharmony_ci		if (sha3_mode) {
83062306a36Sopenharmony_ci			state->flags |= HASH_SHA3_256 << HASH_FLAGS_ALGO_SHIFT;
83162306a36Sopenharmony_ci		} else {
83262306a36Sopenharmony_ci			if (hdev->pdata->ux500)
83362306a36Sopenharmony_ci				state->flags |= HASH_SHA256_UX500 << HASH_FLAGS_ALGO_SHIFT;
83462306a36Sopenharmony_ci			else
83562306a36Sopenharmony_ci				state->flags |= HASH_SHA256 << HASH_FLAGS_ALGO_SHIFT;
83662306a36Sopenharmony_ci		}
83762306a36Sopenharmony_ci		break;
83862306a36Sopenharmony_ci	case SHA384_DIGEST_SIZE:
83962306a36Sopenharmony_ci		if (sha3_mode)
84062306a36Sopenharmony_ci			state->flags |= HASH_SHA3_384 << HASH_FLAGS_ALGO_SHIFT;
84162306a36Sopenharmony_ci		else
84262306a36Sopenharmony_ci			state->flags |= HASH_SHA384 << HASH_FLAGS_ALGO_SHIFT;
84362306a36Sopenharmony_ci		break;
84462306a36Sopenharmony_ci	case SHA512_DIGEST_SIZE:
84562306a36Sopenharmony_ci		if (sha3_mode)
84662306a36Sopenharmony_ci			state->flags |= HASH_SHA3_512 << HASH_FLAGS_ALGO_SHIFT;
84762306a36Sopenharmony_ci		else
84862306a36Sopenharmony_ci			state->flags |= HASH_SHA512 << HASH_FLAGS_ALGO_SHIFT;
84962306a36Sopenharmony_ci		break;
85062306a36Sopenharmony_ci	default:
85162306a36Sopenharmony_ci		return -EINVAL;
85262306a36Sopenharmony_ci	}
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	rctx->state.bufcnt = 0;
85562306a36Sopenharmony_ci	rctx->state.blocklen = crypto_ahash_blocksize(tfm) + sizeof(u32);
85662306a36Sopenharmony_ci	if (rctx->state.blocklen > HASH_BUFLEN) {
85762306a36Sopenharmony_ci		dev_err(hdev->dev, "Error, block too large");
85862306a36Sopenharmony_ci		return -EINVAL;
85962306a36Sopenharmony_ci	}
86062306a36Sopenharmony_ci	rctx->total = 0;
86162306a36Sopenharmony_ci	rctx->offset = 0;
86262306a36Sopenharmony_ci	rctx->data_type = HASH_DATA_8_BITS;
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	if (ctx->flags & HASH_FLAGS_HMAC)
86562306a36Sopenharmony_ci		state->flags |= HASH_FLAGS_HMAC;
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	dev_dbg(hdev->dev, "%s Flags %x\n", __func__, state->flags);
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	return 0;
87062306a36Sopenharmony_ci}
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_cistatic int stm32_hash_update_req(struct stm32_hash_dev *hdev)
87362306a36Sopenharmony_ci{
87462306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req);
87562306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	if (!(state->flags & HASH_FLAGS_CPU))
87862306a36Sopenharmony_ci		return stm32_hash_dma_send(hdev);
87962306a36Sopenharmony_ci
88062306a36Sopenharmony_ci	return stm32_hash_update_cpu(hdev);
88162306a36Sopenharmony_ci}
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_cistatic int stm32_hash_final_req(struct stm32_hash_dev *hdev)
88462306a36Sopenharmony_ci{
88562306a36Sopenharmony_ci	struct ahash_request *req = hdev->req;
88662306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
88762306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
88862306a36Sopenharmony_ci	int buflen = state->bufcnt;
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	if (state->flags & HASH_FLAGS_FINUP)
89162306a36Sopenharmony_ci		return stm32_hash_update_req(hdev);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	state->bufcnt = 0;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	return stm32_hash_xmit_cpu(hdev, state->buffer, buflen, 1);
89662306a36Sopenharmony_ci}
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_cistatic void stm32_hash_emptymsg_fallback(struct ahash_request *req)
89962306a36Sopenharmony_ci{
90062306a36Sopenharmony_ci	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
90162306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_ahash_ctx(ahash);
90262306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
90362306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = rctx->hdev;
90462306a36Sopenharmony_ci	int ret;
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	dev_dbg(hdev->dev, "use fallback message size 0 key size %d\n",
90762306a36Sopenharmony_ci		ctx->keylen);
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	if (!ctx->xtfm) {
91062306a36Sopenharmony_ci		dev_err(hdev->dev, "no fallback engine\n");
91162306a36Sopenharmony_ci		return;
91262306a36Sopenharmony_ci	}
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	if (ctx->keylen) {
91562306a36Sopenharmony_ci		ret = crypto_shash_setkey(ctx->xtfm, ctx->key, ctx->keylen);
91662306a36Sopenharmony_ci		if (ret) {
91762306a36Sopenharmony_ci			dev_err(hdev->dev, "failed to set key ret=%d\n", ret);
91862306a36Sopenharmony_ci			return;
91962306a36Sopenharmony_ci		}
92062306a36Sopenharmony_ci	}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	ret = crypto_shash_tfm_digest(ctx->xtfm, NULL, 0, rctx->digest);
92362306a36Sopenharmony_ci	if (ret)
92462306a36Sopenharmony_ci		dev_err(hdev->dev, "shash digest error\n");
92562306a36Sopenharmony_ci}
92662306a36Sopenharmony_ci
92762306a36Sopenharmony_cistatic void stm32_hash_copy_hash(struct ahash_request *req)
92862306a36Sopenharmony_ci{
92962306a36Sopenharmony_ci	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
93062306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
93162306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
93262306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = rctx->hdev;
93362306a36Sopenharmony_ci	__be32 *hash = (void *)rctx->digest;
93462306a36Sopenharmony_ci	unsigned int i, hashsize;
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	if (hdev->pdata->broken_emptymsg && (state->flags & HASH_FLAGS_EMPTY))
93762306a36Sopenharmony_ci		return stm32_hash_emptymsg_fallback(req);
93862306a36Sopenharmony_ci
93962306a36Sopenharmony_ci	hashsize = crypto_ahash_digestsize(tfm);
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	for (i = 0; i < hashsize / sizeof(u32); i++) {
94262306a36Sopenharmony_ci		if (hdev->pdata->ux500)
94362306a36Sopenharmony_ci			hash[i] = cpu_to_be32(stm32_hash_read(hdev,
94462306a36Sopenharmony_ci					      HASH_UX500_HREG(i)));
94562306a36Sopenharmony_ci		else
94662306a36Sopenharmony_ci			hash[i] = cpu_to_be32(stm32_hash_read(hdev,
94762306a36Sopenharmony_ci					      HASH_HREG(i)));
94862306a36Sopenharmony_ci	}
94962306a36Sopenharmony_ci}
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_cistatic int stm32_hash_finish(struct ahash_request *req)
95262306a36Sopenharmony_ci{
95362306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
95462306a36Sopenharmony_ci	u32 reg;
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci	reg = stm32_hash_read(rctx->hdev, HASH_SR);
95762306a36Sopenharmony_ci	reg &= ~HASH_SR_OUTPUT_READY;
95862306a36Sopenharmony_ci	stm32_hash_write(rctx->hdev, HASH_SR, reg);
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	if (!req->result)
96162306a36Sopenharmony_ci		return -EINVAL;
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_ci	memcpy(req->result, rctx->digest, rctx->digcnt);
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	return 0;
96662306a36Sopenharmony_ci}
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_cistatic void stm32_hash_finish_req(struct ahash_request *req, int err)
96962306a36Sopenharmony_ci{
97062306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
97162306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = rctx->hdev;
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	if (!err && (HASH_FLAGS_FINAL & hdev->flags)) {
97462306a36Sopenharmony_ci		stm32_hash_copy_hash(req);
97562306a36Sopenharmony_ci		err = stm32_hash_finish(req);
97662306a36Sopenharmony_ci	}
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci	pm_runtime_mark_last_busy(hdev->dev);
97962306a36Sopenharmony_ci	pm_runtime_put_autosuspend(hdev->dev);
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci	crypto_finalize_hash_request(hdev->engine, req, err);
98262306a36Sopenharmony_ci}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_cistatic int stm32_hash_handle_queue(struct stm32_hash_dev *hdev,
98562306a36Sopenharmony_ci				   struct ahash_request *req)
98662306a36Sopenharmony_ci{
98762306a36Sopenharmony_ci	return crypto_transfer_hash_request_to_engine(hdev->engine, req);
98862306a36Sopenharmony_ci}
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_cistatic int stm32_hash_one_request(struct crypto_engine *engine, void *areq)
99162306a36Sopenharmony_ci{
99262306a36Sopenharmony_ci	struct ahash_request *req = container_of(areq, struct ahash_request,
99362306a36Sopenharmony_ci						 base);
99462306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
99562306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
99662306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
99762306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
99862306a36Sopenharmony_ci	int swap_reg;
99962306a36Sopenharmony_ci	int err = 0;
100062306a36Sopenharmony_ci
100162306a36Sopenharmony_ci	if (!hdev)
100262306a36Sopenharmony_ci		return -ENODEV;
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci	dev_dbg(hdev->dev, "processing new req, op: %lu, nbytes %d\n",
100562306a36Sopenharmony_ci		rctx->op, req->nbytes);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	pm_runtime_get_sync(hdev->dev);
100862306a36Sopenharmony_ci
100962306a36Sopenharmony_ci	hdev->req = req;
101062306a36Sopenharmony_ci	hdev->flags = 0;
101162306a36Sopenharmony_ci	swap_reg = hash_swap_reg(rctx);
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	if (state->flags & HASH_FLAGS_INIT) {
101462306a36Sopenharmony_ci		u32 *preg = rctx->state.hw_context;
101562306a36Sopenharmony_ci		u32 reg;
101662306a36Sopenharmony_ci		int i;
101762306a36Sopenharmony_ci
101862306a36Sopenharmony_ci		if (!hdev->pdata->ux500)
101962306a36Sopenharmony_ci			stm32_hash_write(hdev, HASH_IMR, *preg++);
102062306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_STR, *preg++);
102162306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_CR, *preg);
102262306a36Sopenharmony_ci		reg = *preg++ | HASH_CR_INIT;
102362306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_CR, reg);
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_ci		for (i = 0; i < swap_reg; i++)
102662306a36Sopenharmony_ci			stm32_hash_write(hdev, HASH_CSR(i), *preg++);
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci		hdev->flags |= HASH_FLAGS_INIT;
102962306a36Sopenharmony_ci
103062306a36Sopenharmony_ci		if (state->flags & HASH_FLAGS_HMAC)
103162306a36Sopenharmony_ci			hdev->flags |= HASH_FLAGS_HMAC |
103262306a36Sopenharmony_ci				       HASH_FLAGS_HMAC_KEY;
103362306a36Sopenharmony_ci	}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	if (rctx->op == HASH_OP_UPDATE)
103662306a36Sopenharmony_ci		err = stm32_hash_update_req(hdev);
103762306a36Sopenharmony_ci	else if (rctx->op == HASH_OP_FINAL)
103862306a36Sopenharmony_ci		err = stm32_hash_final_req(hdev);
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	/* If we have an IRQ, wait for that, else poll for completion */
104162306a36Sopenharmony_ci	if (err == -EINPROGRESS && hdev->polled) {
104262306a36Sopenharmony_ci		if (stm32_hash_wait_busy(hdev))
104362306a36Sopenharmony_ci			err = -ETIMEDOUT;
104462306a36Sopenharmony_ci		else {
104562306a36Sopenharmony_ci			hdev->flags |= HASH_FLAGS_OUTPUT_READY;
104662306a36Sopenharmony_ci			err = 0;
104762306a36Sopenharmony_ci		}
104862306a36Sopenharmony_ci	}
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	if (err != -EINPROGRESS)
105162306a36Sopenharmony_ci	/* done task will not finish it, so do it here */
105262306a36Sopenharmony_ci		stm32_hash_finish_req(req, err);
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_ci	return 0;
105562306a36Sopenharmony_ci}
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_cistatic int stm32_hash_enqueue(struct ahash_request *req, unsigned int op)
105862306a36Sopenharmony_ci{
105962306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
106062306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_tfm_ctx(req->base.tfm);
106162306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = ctx->hdev;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	rctx->op = op;
106462306a36Sopenharmony_ci
106562306a36Sopenharmony_ci	return stm32_hash_handle_queue(hdev, req);
106662306a36Sopenharmony_ci}
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_cistatic int stm32_hash_update(struct ahash_request *req)
106962306a36Sopenharmony_ci{
107062306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
107162306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_ci	if (!req->nbytes || !(state->flags & HASH_FLAGS_CPU))
107462306a36Sopenharmony_ci		return 0;
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	rctx->total = req->nbytes;
107762306a36Sopenharmony_ci	rctx->sg = req->src;
107862306a36Sopenharmony_ci	rctx->offset = 0;
107962306a36Sopenharmony_ci
108062306a36Sopenharmony_ci	if ((state->bufcnt + rctx->total < state->blocklen)) {
108162306a36Sopenharmony_ci		stm32_hash_append_sg(rctx);
108262306a36Sopenharmony_ci		return 0;
108362306a36Sopenharmony_ci	}
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci	return stm32_hash_enqueue(req, HASH_OP_UPDATE);
108662306a36Sopenharmony_ci}
108762306a36Sopenharmony_ci
108862306a36Sopenharmony_cistatic int stm32_hash_final(struct ahash_request *req)
108962306a36Sopenharmony_ci{
109062306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
109162306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
109262306a36Sopenharmony_ci
109362306a36Sopenharmony_ci	state->flags |= HASH_FLAGS_FINAL;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	return stm32_hash_enqueue(req, HASH_OP_FINAL);
109662306a36Sopenharmony_ci}
109762306a36Sopenharmony_ci
109862306a36Sopenharmony_cistatic int stm32_hash_finup(struct ahash_request *req)
109962306a36Sopenharmony_ci{
110062306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
110162306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_ahash_ctx(crypto_ahash_reqtfm(req));
110262306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
110362306a36Sopenharmony_ci	struct stm32_hash_state *state = &rctx->state;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	if (!req->nbytes)
110662306a36Sopenharmony_ci		goto out;
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	state->flags |= HASH_FLAGS_FINUP;
110962306a36Sopenharmony_ci	rctx->total = req->nbytes;
111062306a36Sopenharmony_ci	rctx->sg = req->src;
111162306a36Sopenharmony_ci	rctx->offset = 0;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	if (hdev->dma_lch && stm32_hash_dma_aligned_data(req))
111462306a36Sopenharmony_ci		state->flags &= ~HASH_FLAGS_CPU;
111562306a36Sopenharmony_ci
111662306a36Sopenharmony_ciout:
111762306a36Sopenharmony_ci	return stm32_hash_final(req);
111862306a36Sopenharmony_ci}
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_cistatic int stm32_hash_digest(struct ahash_request *req)
112162306a36Sopenharmony_ci{
112262306a36Sopenharmony_ci	return stm32_hash_init(req) ?: stm32_hash_finup(req);
112362306a36Sopenharmony_ci}
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_cistatic int stm32_hash_export(struct ahash_request *req, void *out)
112662306a36Sopenharmony_ci{
112762306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	memcpy(out, &rctx->state, sizeof(rctx->state));
113062306a36Sopenharmony_ci
113162306a36Sopenharmony_ci	return 0;
113262306a36Sopenharmony_ci}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_cistatic int stm32_hash_import(struct ahash_request *req, const void *in)
113562306a36Sopenharmony_ci{
113662306a36Sopenharmony_ci	struct stm32_hash_request_ctx *rctx = ahash_request_ctx(req);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	stm32_hash_init(req);
113962306a36Sopenharmony_ci	memcpy(&rctx->state, in, sizeof(rctx->state));
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	return 0;
114262306a36Sopenharmony_ci}
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_cistatic int stm32_hash_setkey(struct crypto_ahash *tfm,
114562306a36Sopenharmony_ci			     const u8 *key, unsigned int keylen)
114662306a36Sopenharmony_ci{
114762306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_ahash_ctx(tfm);
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci	if (keylen <= HASH_MAX_KEY_SIZE) {
115062306a36Sopenharmony_ci		memcpy(ctx->key, key, keylen);
115162306a36Sopenharmony_ci		ctx->keylen = keylen;
115262306a36Sopenharmony_ci	} else {
115362306a36Sopenharmony_ci		return -ENOMEM;
115462306a36Sopenharmony_ci	}
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	return 0;
115762306a36Sopenharmony_ci}
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_cistatic int stm32_hash_init_fallback(struct crypto_tfm *tfm)
116062306a36Sopenharmony_ci{
116162306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm);
116262306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = stm32_hash_find_dev(ctx);
116362306a36Sopenharmony_ci	const char *name = crypto_tfm_alg_name(tfm);
116462306a36Sopenharmony_ci	struct crypto_shash *xtfm;
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	/* The fallback is only needed on Ux500 */
116762306a36Sopenharmony_ci	if (!hdev->pdata->ux500)
116862306a36Sopenharmony_ci		return 0;
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_ci	xtfm = crypto_alloc_shash(name, 0, CRYPTO_ALG_NEED_FALLBACK);
117162306a36Sopenharmony_ci	if (IS_ERR(xtfm)) {
117262306a36Sopenharmony_ci		dev_err(hdev->dev, "failed to allocate %s fallback\n",
117362306a36Sopenharmony_ci			name);
117462306a36Sopenharmony_ci		return PTR_ERR(xtfm);
117562306a36Sopenharmony_ci	}
117662306a36Sopenharmony_ci	dev_info(hdev->dev, "allocated %s fallback\n", name);
117762306a36Sopenharmony_ci	ctx->xtfm = xtfm;
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	return 0;
118062306a36Sopenharmony_ci}
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_cistatic int stm32_hash_cra_init_algs(struct crypto_tfm *tfm, u32 algs_flags)
118362306a36Sopenharmony_ci{
118462306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm);
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	crypto_ahash_set_reqsize(__crypto_ahash_cast(tfm),
118762306a36Sopenharmony_ci				 sizeof(struct stm32_hash_request_ctx));
118862306a36Sopenharmony_ci
118962306a36Sopenharmony_ci	ctx->keylen = 0;
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	if (algs_flags)
119262306a36Sopenharmony_ci		ctx->flags |= algs_flags;
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	return stm32_hash_init_fallback(tfm);
119562306a36Sopenharmony_ci}
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_cistatic int stm32_hash_cra_init(struct crypto_tfm *tfm)
119862306a36Sopenharmony_ci{
119962306a36Sopenharmony_ci	return stm32_hash_cra_init_algs(tfm, 0);
120062306a36Sopenharmony_ci}
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_cistatic int stm32_hash_cra_hmac_init(struct crypto_tfm *tfm)
120362306a36Sopenharmony_ci{
120462306a36Sopenharmony_ci	return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_HMAC);
120562306a36Sopenharmony_ci}
120662306a36Sopenharmony_ci
120762306a36Sopenharmony_cistatic int stm32_hash_cra_sha3_init(struct crypto_tfm *tfm)
120862306a36Sopenharmony_ci{
120962306a36Sopenharmony_ci	return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE);
121062306a36Sopenharmony_ci}
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_cistatic int stm32_hash_cra_sha3_hmac_init(struct crypto_tfm *tfm)
121362306a36Sopenharmony_ci{
121462306a36Sopenharmony_ci	return stm32_hash_cra_init_algs(tfm, HASH_FLAGS_SHA3_MODE |
121562306a36Sopenharmony_ci					HASH_FLAGS_HMAC);
121662306a36Sopenharmony_ci}
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_cistatic void stm32_hash_cra_exit(struct crypto_tfm *tfm)
122062306a36Sopenharmony_ci{
122162306a36Sopenharmony_ci	struct stm32_hash_ctx *ctx = crypto_tfm_ctx(tfm);
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_ci	if (ctx->xtfm)
122462306a36Sopenharmony_ci		crypto_free_shash(ctx->xtfm);
122562306a36Sopenharmony_ci}
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_cistatic irqreturn_t stm32_hash_irq_thread(int irq, void *dev_id)
122862306a36Sopenharmony_ci{
122962306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = dev_id;
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci	if (HASH_FLAGS_CPU & hdev->flags) {
123262306a36Sopenharmony_ci		if (HASH_FLAGS_OUTPUT_READY & hdev->flags) {
123362306a36Sopenharmony_ci			hdev->flags &= ~HASH_FLAGS_OUTPUT_READY;
123462306a36Sopenharmony_ci			goto finish;
123562306a36Sopenharmony_ci		}
123662306a36Sopenharmony_ci	} else if (HASH_FLAGS_DMA_ACTIVE & hdev->flags) {
123762306a36Sopenharmony_ci		hdev->flags &= ~HASH_FLAGS_DMA_ACTIVE;
123862306a36Sopenharmony_ci			goto finish;
123962306a36Sopenharmony_ci	}
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci	return IRQ_HANDLED;
124262306a36Sopenharmony_ci
124362306a36Sopenharmony_cifinish:
124462306a36Sopenharmony_ci	/* Finish current request */
124562306a36Sopenharmony_ci	stm32_hash_finish_req(hdev->req, 0);
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	return IRQ_HANDLED;
124862306a36Sopenharmony_ci}
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_cistatic irqreturn_t stm32_hash_irq_handler(int irq, void *dev_id)
125162306a36Sopenharmony_ci{
125262306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = dev_id;
125362306a36Sopenharmony_ci	u32 reg;
125462306a36Sopenharmony_ci
125562306a36Sopenharmony_ci	reg = stm32_hash_read(hdev, HASH_SR);
125662306a36Sopenharmony_ci	if (reg & HASH_SR_OUTPUT_READY) {
125762306a36Sopenharmony_ci		hdev->flags |= HASH_FLAGS_OUTPUT_READY;
125862306a36Sopenharmony_ci		/* Disable IT*/
125962306a36Sopenharmony_ci		stm32_hash_write(hdev, HASH_IMR, 0);
126062306a36Sopenharmony_ci		return IRQ_WAKE_THREAD;
126162306a36Sopenharmony_ci	}
126262306a36Sopenharmony_ci
126362306a36Sopenharmony_ci	return IRQ_NONE;
126462306a36Sopenharmony_ci}
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_cistatic struct ahash_engine_alg algs_md5[] = {
126762306a36Sopenharmony_ci	{
126862306a36Sopenharmony_ci		.base.init = stm32_hash_init,
126962306a36Sopenharmony_ci		.base.update = stm32_hash_update,
127062306a36Sopenharmony_ci		.base.final = stm32_hash_final,
127162306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
127262306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
127362306a36Sopenharmony_ci		.base.export = stm32_hash_export,
127462306a36Sopenharmony_ci		.base.import = stm32_hash_import,
127562306a36Sopenharmony_ci		.base.halg = {
127662306a36Sopenharmony_ci			.digestsize = MD5_DIGEST_SIZE,
127762306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
127862306a36Sopenharmony_ci			.base = {
127962306a36Sopenharmony_ci				.cra_name = "md5",
128062306a36Sopenharmony_ci				.cra_driver_name = "stm32-md5",
128162306a36Sopenharmony_ci				.cra_priority = 200,
128262306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
128362306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
128462306a36Sopenharmony_ci				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
128562306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
128662306a36Sopenharmony_ci				.cra_alignmask = 3,
128762306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_init,
128862306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
128962306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
129062306a36Sopenharmony_ci			}
129162306a36Sopenharmony_ci		},
129262306a36Sopenharmony_ci		.op = {
129362306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
129462306a36Sopenharmony_ci		},
129562306a36Sopenharmony_ci	},
129662306a36Sopenharmony_ci	{
129762306a36Sopenharmony_ci		.base.init = stm32_hash_init,
129862306a36Sopenharmony_ci		.base.update = stm32_hash_update,
129962306a36Sopenharmony_ci		.base.final = stm32_hash_final,
130062306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
130162306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
130262306a36Sopenharmony_ci		.base.export = stm32_hash_export,
130362306a36Sopenharmony_ci		.base.import = stm32_hash_import,
130462306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
130562306a36Sopenharmony_ci		.base.halg = {
130662306a36Sopenharmony_ci			.digestsize = MD5_DIGEST_SIZE,
130762306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
130862306a36Sopenharmony_ci			.base = {
130962306a36Sopenharmony_ci				.cra_name = "hmac(md5)",
131062306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-md5",
131162306a36Sopenharmony_ci				.cra_priority = 200,
131262306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
131362306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
131462306a36Sopenharmony_ci				.cra_blocksize = MD5_HMAC_BLOCK_SIZE,
131562306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
131662306a36Sopenharmony_ci				.cra_alignmask = 3,
131762306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_hmac_init,
131862306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
131962306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
132062306a36Sopenharmony_ci			}
132162306a36Sopenharmony_ci		},
132262306a36Sopenharmony_ci		.op = {
132362306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
132462306a36Sopenharmony_ci		},
132562306a36Sopenharmony_ci	}
132662306a36Sopenharmony_ci};
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha1[] = {
132962306a36Sopenharmony_ci	{
133062306a36Sopenharmony_ci		.base.init = stm32_hash_init,
133162306a36Sopenharmony_ci		.base.update = stm32_hash_update,
133262306a36Sopenharmony_ci		.base.final = stm32_hash_final,
133362306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
133462306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
133562306a36Sopenharmony_ci		.base.export = stm32_hash_export,
133662306a36Sopenharmony_ci		.base.import = stm32_hash_import,
133762306a36Sopenharmony_ci		.base.halg = {
133862306a36Sopenharmony_ci			.digestsize = SHA1_DIGEST_SIZE,
133962306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
134062306a36Sopenharmony_ci			.base = {
134162306a36Sopenharmony_ci				.cra_name = "sha1",
134262306a36Sopenharmony_ci				.cra_driver_name = "stm32-sha1",
134362306a36Sopenharmony_ci				.cra_priority = 200,
134462306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
134562306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
134662306a36Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
134762306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
134862306a36Sopenharmony_ci				.cra_alignmask = 3,
134962306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_init,
135062306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
135162306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
135262306a36Sopenharmony_ci			}
135362306a36Sopenharmony_ci		},
135462306a36Sopenharmony_ci		.op = {
135562306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
135662306a36Sopenharmony_ci		},
135762306a36Sopenharmony_ci	},
135862306a36Sopenharmony_ci	{
135962306a36Sopenharmony_ci		.base.init = stm32_hash_init,
136062306a36Sopenharmony_ci		.base.update = stm32_hash_update,
136162306a36Sopenharmony_ci		.base.final = stm32_hash_final,
136262306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
136362306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
136462306a36Sopenharmony_ci		.base.export = stm32_hash_export,
136562306a36Sopenharmony_ci		.base.import = stm32_hash_import,
136662306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
136762306a36Sopenharmony_ci		.base.halg = {
136862306a36Sopenharmony_ci			.digestsize = SHA1_DIGEST_SIZE,
136962306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
137062306a36Sopenharmony_ci			.base = {
137162306a36Sopenharmony_ci				.cra_name = "hmac(sha1)",
137262306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-sha1",
137362306a36Sopenharmony_ci				.cra_priority = 200,
137462306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
137562306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
137662306a36Sopenharmony_ci				.cra_blocksize = SHA1_BLOCK_SIZE,
137762306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
137862306a36Sopenharmony_ci				.cra_alignmask = 3,
137962306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_hmac_init,
138062306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
138162306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
138262306a36Sopenharmony_ci			}
138362306a36Sopenharmony_ci		},
138462306a36Sopenharmony_ci		.op = {
138562306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
138662306a36Sopenharmony_ci		},
138762306a36Sopenharmony_ci	},
138862306a36Sopenharmony_ci};
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha224[] = {
139162306a36Sopenharmony_ci	{
139262306a36Sopenharmony_ci		.base.init = stm32_hash_init,
139362306a36Sopenharmony_ci		.base.update = stm32_hash_update,
139462306a36Sopenharmony_ci		.base.final = stm32_hash_final,
139562306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
139662306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
139762306a36Sopenharmony_ci		.base.export = stm32_hash_export,
139862306a36Sopenharmony_ci		.base.import = stm32_hash_import,
139962306a36Sopenharmony_ci		.base.halg = {
140062306a36Sopenharmony_ci			.digestsize = SHA224_DIGEST_SIZE,
140162306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
140262306a36Sopenharmony_ci			.base = {
140362306a36Sopenharmony_ci				.cra_name = "sha224",
140462306a36Sopenharmony_ci				.cra_driver_name = "stm32-sha224",
140562306a36Sopenharmony_ci				.cra_priority = 200,
140662306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
140762306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
140862306a36Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
140962306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
141062306a36Sopenharmony_ci				.cra_alignmask = 3,
141162306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_init,
141262306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
141362306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
141462306a36Sopenharmony_ci			}
141562306a36Sopenharmony_ci		},
141662306a36Sopenharmony_ci		.op = {
141762306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
141862306a36Sopenharmony_ci		},
141962306a36Sopenharmony_ci	},
142062306a36Sopenharmony_ci	{
142162306a36Sopenharmony_ci		.base.init = stm32_hash_init,
142262306a36Sopenharmony_ci		.base.update = stm32_hash_update,
142362306a36Sopenharmony_ci		.base.final = stm32_hash_final,
142462306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
142562306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
142662306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
142762306a36Sopenharmony_ci		.base.export = stm32_hash_export,
142862306a36Sopenharmony_ci		.base.import = stm32_hash_import,
142962306a36Sopenharmony_ci		.base.halg = {
143062306a36Sopenharmony_ci			.digestsize = SHA224_DIGEST_SIZE,
143162306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
143262306a36Sopenharmony_ci			.base = {
143362306a36Sopenharmony_ci				.cra_name = "hmac(sha224)",
143462306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-sha224",
143562306a36Sopenharmony_ci				.cra_priority = 200,
143662306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
143762306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
143862306a36Sopenharmony_ci				.cra_blocksize = SHA224_BLOCK_SIZE,
143962306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
144062306a36Sopenharmony_ci				.cra_alignmask = 3,
144162306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_hmac_init,
144262306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
144362306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
144462306a36Sopenharmony_ci			}
144562306a36Sopenharmony_ci		},
144662306a36Sopenharmony_ci		.op = {
144762306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
144862306a36Sopenharmony_ci		},
144962306a36Sopenharmony_ci	},
145062306a36Sopenharmony_ci};
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha256[] = {
145362306a36Sopenharmony_ci	{
145462306a36Sopenharmony_ci		.base.init = stm32_hash_init,
145562306a36Sopenharmony_ci		.base.update = stm32_hash_update,
145662306a36Sopenharmony_ci		.base.final = stm32_hash_final,
145762306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
145862306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
145962306a36Sopenharmony_ci		.base.export = stm32_hash_export,
146062306a36Sopenharmony_ci		.base.import = stm32_hash_import,
146162306a36Sopenharmony_ci		.base.halg = {
146262306a36Sopenharmony_ci			.digestsize = SHA256_DIGEST_SIZE,
146362306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
146462306a36Sopenharmony_ci			.base = {
146562306a36Sopenharmony_ci				.cra_name = "sha256",
146662306a36Sopenharmony_ci				.cra_driver_name = "stm32-sha256",
146762306a36Sopenharmony_ci				.cra_priority = 200,
146862306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
146962306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
147062306a36Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
147162306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
147262306a36Sopenharmony_ci				.cra_alignmask = 3,
147362306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_init,
147462306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
147562306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
147662306a36Sopenharmony_ci			}
147762306a36Sopenharmony_ci		},
147862306a36Sopenharmony_ci		.op = {
147962306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
148062306a36Sopenharmony_ci		},
148162306a36Sopenharmony_ci	},
148262306a36Sopenharmony_ci	{
148362306a36Sopenharmony_ci		.base.init = stm32_hash_init,
148462306a36Sopenharmony_ci		.base.update = stm32_hash_update,
148562306a36Sopenharmony_ci		.base.final = stm32_hash_final,
148662306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
148762306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
148862306a36Sopenharmony_ci		.base.export = stm32_hash_export,
148962306a36Sopenharmony_ci		.base.import = stm32_hash_import,
149062306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
149162306a36Sopenharmony_ci		.base.halg = {
149262306a36Sopenharmony_ci			.digestsize = SHA256_DIGEST_SIZE,
149362306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
149462306a36Sopenharmony_ci			.base = {
149562306a36Sopenharmony_ci				.cra_name = "hmac(sha256)",
149662306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-sha256",
149762306a36Sopenharmony_ci				.cra_priority = 200,
149862306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
149962306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
150062306a36Sopenharmony_ci				.cra_blocksize = SHA256_BLOCK_SIZE,
150162306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
150262306a36Sopenharmony_ci				.cra_alignmask = 3,
150362306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_hmac_init,
150462306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
150562306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
150662306a36Sopenharmony_ci			}
150762306a36Sopenharmony_ci		},
150862306a36Sopenharmony_ci		.op = {
150962306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
151062306a36Sopenharmony_ci		},
151162306a36Sopenharmony_ci	},
151262306a36Sopenharmony_ci};
151362306a36Sopenharmony_ci
151462306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha384_sha512[] = {
151562306a36Sopenharmony_ci	{
151662306a36Sopenharmony_ci		.base.init = stm32_hash_init,
151762306a36Sopenharmony_ci		.base.update = stm32_hash_update,
151862306a36Sopenharmony_ci		.base.final = stm32_hash_final,
151962306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
152062306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
152162306a36Sopenharmony_ci		.base.export = stm32_hash_export,
152262306a36Sopenharmony_ci		.base.import = stm32_hash_import,
152362306a36Sopenharmony_ci		.base.halg = {
152462306a36Sopenharmony_ci			.digestsize = SHA384_DIGEST_SIZE,
152562306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
152662306a36Sopenharmony_ci			.base = {
152762306a36Sopenharmony_ci				.cra_name = "sha384",
152862306a36Sopenharmony_ci				.cra_driver_name = "stm32-sha384",
152962306a36Sopenharmony_ci				.cra_priority = 200,
153062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
153162306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
153262306a36Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
153362306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
153462306a36Sopenharmony_ci				.cra_alignmask = 3,
153562306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_init,
153662306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
153762306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
153862306a36Sopenharmony_ci			}
153962306a36Sopenharmony_ci		},
154062306a36Sopenharmony_ci		.op = {
154162306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
154262306a36Sopenharmony_ci		},
154362306a36Sopenharmony_ci	},
154462306a36Sopenharmony_ci	{
154562306a36Sopenharmony_ci		.base.init = stm32_hash_init,
154662306a36Sopenharmony_ci		.base.update = stm32_hash_update,
154762306a36Sopenharmony_ci		.base.final = stm32_hash_final,
154862306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
154962306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
155062306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
155162306a36Sopenharmony_ci		.base.export = stm32_hash_export,
155262306a36Sopenharmony_ci		.base.import = stm32_hash_import,
155362306a36Sopenharmony_ci		.base.halg = {
155462306a36Sopenharmony_ci			.digestsize = SHA384_DIGEST_SIZE,
155562306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
155662306a36Sopenharmony_ci			.base = {
155762306a36Sopenharmony_ci				.cra_name = "hmac(sha384)",
155862306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-sha384",
155962306a36Sopenharmony_ci				.cra_priority = 200,
156062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
156162306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
156262306a36Sopenharmony_ci				.cra_blocksize = SHA384_BLOCK_SIZE,
156362306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
156462306a36Sopenharmony_ci				.cra_alignmask = 3,
156562306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_hmac_init,
156662306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
156762306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
156862306a36Sopenharmony_ci			}
156962306a36Sopenharmony_ci		},
157062306a36Sopenharmony_ci		.op = {
157162306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
157262306a36Sopenharmony_ci		},
157362306a36Sopenharmony_ci	},
157462306a36Sopenharmony_ci	{
157562306a36Sopenharmony_ci		.base.init = stm32_hash_init,
157662306a36Sopenharmony_ci		.base.update = stm32_hash_update,
157762306a36Sopenharmony_ci		.base.final = stm32_hash_final,
157862306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
157962306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
158062306a36Sopenharmony_ci		.base.export = stm32_hash_export,
158162306a36Sopenharmony_ci		.base.import = stm32_hash_import,
158262306a36Sopenharmony_ci		.base.halg = {
158362306a36Sopenharmony_ci			.digestsize = SHA512_DIGEST_SIZE,
158462306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
158562306a36Sopenharmony_ci			.base = {
158662306a36Sopenharmony_ci				.cra_name = "sha512",
158762306a36Sopenharmony_ci				.cra_driver_name = "stm32-sha512",
158862306a36Sopenharmony_ci				.cra_priority = 200,
158962306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
159062306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
159162306a36Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
159262306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
159362306a36Sopenharmony_ci				.cra_alignmask = 3,
159462306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_init,
159562306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
159662306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
159762306a36Sopenharmony_ci			}
159862306a36Sopenharmony_ci		},
159962306a36Sopenharmony_ci		.op = {
160062306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
160162306a36Sopenharmony_ci		},
160262306a36Sopenharmony_ci	},
160362306a36Sopenharmony_ci	{
160462306a36Sopenharmony_ci		.base.init = stm32_hash_init,
160562306a36Sopenharmony_ci		.base.update = stm32_hash_update,
160662306a36Sopenharmony_ci		.base.final = stm32_hash_final,
160762306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
160862306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
160962306a36Sopenharmony_ci		.base.export = stm32_hash_export,
161062306a36Sopenharmony_ci		.base.import = stm32_hash_import,
161162306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
161262306a36Sopenharmony_ci		.base.halg = {
161362306a36Sopenharmony_ci			.digestsize = SHA512_DIGEST_SIZE,
161462306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
161562306a36Sopenharmony_ci			.base = {
161662306a36Sopenharmony_ci				.cra_name = "hmac(sha512)",
161762306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-sha512",
161862306a36Sopenharmony_ci				.cra_priority = 200,
161962306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
162062306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
162162306a36Sopenharmony_ci				.cra_blocksize = SHA512_BLOCK_SIZE,
162262306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
162362306a36Sopenharmony_ci				.cra_alignmask = 3,
162462306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_hmac_init,
162562306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
162662306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
162762306a36Sopenharmony_ci			}
162862306a36Sopenharmony_ci		},
162962306a36Sopenharmony_ci		.op = {
163062306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
163162306a36Sopenharmony_ci		},
163262306a36Sopenharmony_ci	},
163362306a36Sopenharmony_ci};
163462306a36Sopenharmony_ci
163562306a36Sopenharmony_cistatic struct ahash_engine_alg algs_sha3[] = {
163662306a36Sopenharmony_ci	{
163762306a36Sopenharmony_ci		.base.init = stm32_hash_init,
163862306a36Sopenharmony_ci		.base.update = stm32_hash_update,
163962306a36Sopenharmony_ci		.base.final = stm32_hash_final,
164062306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
164162306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
164262306a36Sopenharmony_ci		.base.export = stm32_hash_export,
164362306a36Sopenharmony_ci		.base.import = stm32_hash_import,
164462306a36Sopenharmony_ci		.base.halg = {
164562306a36Sopenharmony_ci			.digestsize = SHA3_224_DIGEST_SIZE,
164662306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
164762306a36Sopenharmony_ci			.base = {
164862306a36Sopenharmony_ci				.cra_name = "sha3-224",
164962306a36Sopenharmony_ci				.cra_driver_name = "stm32-sha3-224",
165062306a36Sopenharmony_ci				.cra_priority = 200,
165162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
165262306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
165362306a36Sopenharmony_ci				.cra_blocksize = SHA3_224_BLOCK_SIZE,
165462306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
165562306a36Sopenharmony_ci				.cra_alignmask = 3,
165662306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_sha3_init,
165762306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
165862306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
165962306a36Sopenharmony_ci			}
166062306a36Sopenharmony_ci		},
166162306a36Sopenharmony_ci		.op = {
166262306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
166362306a36Sopenharmony_ci		},
166462306a36Sopenharmony_ci	},
166562306a36Sopenharmony_ci	{
166662306a36Sopenharmony_ci		.base.init = stm32_hash_init,
166762306a36Sopenharmony_ci		.base.update = stm32_hash_update,
166862306a36Sopenharmony_ci		.base.final = stm32_hash_final,
166962306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
167062306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
167162306a36Sopenharmony_ci		.base.export = stm32_hash_export,
167262306a36Sopenharmony_ci		.base.import = stm32_hash_import,
167362306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
167462306a36Sopenharmony_ci		.base.halg = {
167562306a36Sopenharmony_ci			.digestsize = SHA3_224_DIGEST_SIZE,
167662306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
167762306a36Sopenharmony_ci			.base = {
167862306a36Sopenharmony_ci				.cra_name = "hmac(sha3-224)",
167962306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-sha3-224",
168062306a36Sopenharmony_ci				.cra_priority = 200,
168162306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
168262306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
168362306a36Sopenharmony_ci				.cra_blocksize = SHA3_224_BLOCK_SIZE,
168462306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
168562306a36Sopenharmony_ci				.cra_alignmask = 3,
168662306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_sha3_hmac_init,
168762306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
168862306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
168962306a36Sopenharmony_ci			}
169062306a36Sopenharmony_ci		},
169162306a36Sopenharmony_ci		.op = {
169262306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
169362306a36Sopenharmony_ci		},
169462306a36Sopenharmony_ci	},
169562306a36Sopenharmony_ci	{
169662306a36Sopenharmony_ci		.base.init = stm32_hash_init,
169762306a36Sopenharmony_ci		.base.update = stm32_hash_update,
169862306a36Sopenharmony_ci		.base.final = stm32_hash_final,
169962306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
170062306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
170162306a36Sopenharmony_ci		.base.export = stm32_hash_export,
170262306a36Sopenharmony_ci		.base.import = stm32_hash_import,
170362306a36Sopenharmony_ci		.base.halg = {
170462306a36Sopenharmony_ci			.digestsize = SHA3_256_DIGEST_SIZE,
170562306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
170662306a36Sopenharmony_ci			.base = {
170762306a36Sopenharmony_ci				.cra_name = "sha3-256",
170862306a36Sopenharmony_ci				.cra_driver_name = "stm32-sha3-256",
170962306a36Sopenharmony_ci				.cra_priority = 200,
171062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
171162306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
171262306a36Sopenharmony_ci				.cra_blocksize = SHA3_256_BLOCK_SIZE,
171362306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
171462306a36Sopenharmony_ci				.cra_alignmask = 3,
171562306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_sha3_init,
171662306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
171762306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
171862306a36Sopenharmony_ci			}
171962306a36Sopenharmony_ci		},
172062306a36Sopenharmony_ci		.op = {
172162306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
172262306a36Sopenharmony_ci		},
172362306a36Sopenharmony_ci	},
172462306a36Sopenharmony_ci	{
172562306a36Sopenharmony_ci		.base.init = stm32_hash_init,
172662306a36Sopenharmony_ci		.base.update = stm32_hash_update,
172762306a36Sopenharmony_ci		.base.final = stm32_hash_final,
172862306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
172962306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
173062306a36Sopenharmony_ci		.base.export = stm32_hash_export,
173162306a36Sopenharmony_ci		.base.import = stm32_hash_import,
173262306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
173362306a36Sopenharmony_ci		.base.halg = {
173462306a36Sopenharmony_ci			.digestsize = SHA3_256_DIGEST_SIZE,
173562306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
173662306a36Sopenharmony_ci			.base = {
173762306a36Sopenharmony_ci				.cra_name = "hmac(sha3-256)",
173862306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-sha3-256",
173962306a36Sopenharmony_ci				.cra_priority = 200,
174062306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
174162306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
174262306a36Sopenharmony_ci				.cra_blocksize = SHA3_256_BLOCK_SIZE,
174362306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
174462306a36Sopenharmony_ci				.cra_alignmask = 3,
174562306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_sha3_hmac_init,
174662306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
174762306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
174862306a36Sopenharmony_ci			}
174962306a36Sopenharmony_ci		},
175062306a36Sopenharmony_ci		.op = {
175162306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
175262306a36Sopenharmony_ci		},
175362306a36Sopenharmony_ci	},
175462306a36Sopenharmony_ci	{
175562306a36Sopenharmony_ci		.base.init = stm32_hash_init,
175662306a36Sopenharmony_ci		.base.update = stm32_hash_update,
175762306a36Sopenharmony_ci		.base.final = stm32_hash_final,
175862306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
175962306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
176062306a36Sopenharmony_ci		.base.export = stm32_hash_export,
176162306a36Sopenharmony_ci		.base.import = stm32_hash_import,
176262306a36Sopenharmony_ci		.base.halg = {
176362306a36Sopenharmony_ci			.digestsize = SHA3_384_DIGEST_SIZE,
176462306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
176562306a36Sopenharmony_ci			.base = {
176662306a36Sopenharmony_ci				.cra_name = "sha3-384",
176762306a36Sopenharmony_ci				.cra_driver_name = "stm32-sha3-384",
176862306a36Sopenharmony_ci				.cra_priority = 200,
176962306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
177062306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
177162306a36Sopenharmony_ci				.cra_blocksize = SHA3_384_BLOCK_SIZE,
177262306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
177362306a36Sopenharmony_ci				.cra_alignmask = 3,
177462306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_sha3_init,
177562306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
177662306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
177762306a36Sopenharmony_ci			}
177862306a36Sopenharmony_ci		},
177962306a36Sopenharmony_ci		.op = {
178062306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
178162306a36Sopenharmony_ci		},
178262306a36Sopenharmony_ci	},
178362306a36Sopenharmony_ci	{
178462306a36Sopenharmony_ci		.base.init = stm32_hash_init,
178562306a36Sopenharmony_ci		.base.update = stm32_hash_update,
178662306a36Sopenharmony_ci		.base.final = stm32_hash_final,
178762306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
178862306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
178962306a36Sopenharmony_ci		.base.export = stm32_hash_export,
179062306a36Sopenharmony_ci		.base.import = stm32_hash_import,
179162306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
179262306a36Sopenharmony_ci		.base.halg = {
179362306a36Sopenharmony_ci			.digestsize = SHA3_384_DIGEST_SIZE,
179462306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
179562306a36Sopenharmony_ci			.base = {
179662306a36Sopenharmony_ci				.cra_name = "hmac(sha3-384)",
179762306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-sha3-384",
179862306a36Sopenharmony_ci				.cra_priority = 200,
179962306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
180062306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
180162306a36Sopenharmony_ci				.cra_blocksize = SHA3_384_BLOCK_SIZE,
180262306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
180362306a36Sopenharmony_ci				.cra_alignmask = 3,
180462306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_sha3_hmac_init,
180562306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
180662306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
180762306a36Sopenharmony_ci			}
180862306a36Sopenharmony_ci		},
180962306a36Sopenharmony_ci		.op = {
181062306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
181162306a36Sopenharmony_ci		},
181262306a36Sopenharmony_ci	},
181362306a36Sopenharmony_ci	{
181462306a36Sopenharmony_ci		.base.init = stm32_hash_init,
181562306a36Sopenharmony_ci		.base.update = stm32_hash_update,
181662306a36Sopenharmony_ci		.base.final = stm32_hash_final,
181762306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
181862306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
181962306a36Sopenharmony_ci		.base.export = stm32_hash_export,
182062306a36Sopenharmony_ci		.base.import = stm32_hash_import,
182162306a36Sopenharmony_ci		.base.halg = {
182262306a36Sopenharmony_ci			.digestsize = SHA3_512_DIGEST_SIZE,
182362306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
182462306a36Sopenharmony_ci			.base = {
182562306a36Sopenharmony_ci				.cra_name = "sha3-512",
182662306a36Sopenharmony_ci				.cra_driver_name = "stm32-sha3-512",
182762306a36Sopenharmony_ci				.cra_priority = 200,
182862306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
182962306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
183062306a36Sopenharmony_ci				.cra_blocksize = SHA3_512_BLOCK_SIZE,
183162306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
183262306a36Sopenharmony_ci				.cra_alignmask = 3,
183362306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_sha3_init,
183462306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
183562306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
183662306a36Sopenharmony_ci			}
183762306a36Sopenharmony_ci		},
183862306a36Sopenharmony_ci		.op = {
183962306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
184062306a36Sopenharmony_ci		},
184162306a36Sopenharmony_ci	},
184262306a36Sopenharmony_ci	{
184362306a36Sopenharmony_ci		.base.init = stm32_hash_init,
184462306a36Sopenharmony_ci		.base.update = stm32_hash_update,
184562306a36Sopenharmony_ci		.base.final = stm32_hash_final,
184662306a36Sopenharmony_ci		.base.finup = stm32_hash_finup,
184762306a36Sopenharmony_ci		.base.digest = stm32_hash_digest,
184862306a36Sopenharmony_ci		.base.export = stm32_hash_export,
184962306a36Sopenharmony_ci		.base.import = stm32_hash_import,
185062306a36Sopenharmony_ci		.base.setkey = stm32_hash_setkey,
185162306a36Sopenharmony_ci		.base.halg = {
185262306a36Sopenharmony_ci			.digestsize = SHA3_512_DIGEST_SIZE,
185362306a36Sopenharmony_ci			.statesize = sizeof(struct stm32_hash_state),
185462306a36Sopenharmony_ci			.base = {
185562306a36Sopenharmony_ci				.cra_name = "hmac(sha3-512)",
185662306a36Sopenharmony_ci				.cra_driver_name = "stm32-hmac-sha3-512",
185762306a36Sopenharmony_ci				.cra_priority = 200,
185862306a36Sopenharmony_ci				.cra_flags = CRYPTO_ALG_ASYNC |
185962306a36Sopenharmony_ci					CRYPTO_ALG_KERN_DRIVER_ONLY,
186062306a36Sopenharmony_ci				.cra_blocksize = SHA3_512_BLOCK_SIZE,
186162306a36Sopenharmony_ci				.cra_ctxsize = sizeof(struct stm32_hash_ctx),
186262306a36Sopenharmony_ci				.cra_alignmask = 3,
186362306a36Sopenharmony_ci				.cra_init = stm32_hash_cra_sha3_hmac_init,
186462306a36Sopenharmony_ci				.cra_exit = stm32_hash_cra_exit,
186562306a36Sopenharmony_ci				.cra_module = THIS_MODULE,
186662306a36Sopenharmony_ci			}
186762306a36Sopenharmony_ci		},
186862306a36Sopenharmony_ci		.op = {
186962306a36Sopenharmony_ci			.do_one_request = stm32_hash_one_request,
187062306a36Sopenharmony_ci		},
187162306a36Sopenharmony_ci	}
187262306a36Sopenharmony_ci};
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_cistatic int stm32_hash_register_algs(struct stm32_hash_dev *hdev)
187562306a36Sopenharmony_ci{
187662306a36Sopenharmony_ci	unsigned int i, j;
187762306a36Sopenharmony_ci	int err;
187862306a36Sopenharmony_ci
187962306a36Sopenharmony_ci	for (i = 0; i < hdev->pdata->algs_info_size; i++) {
188062306a36Sopenharmony_ci		for (j = 0; j < hdev->pdata->algs_info[i].size; j++) {
188162306a36Sopenharmony_ci			err = crypto_engine_register_ahash(
188262306a36Sopenharmony_ci				&hdev->pdata->algs_info[i].algs_list[j]);
188362306a36Sopenharmony_ci			if (err)
188462306a36Sopenharmony_ci				goto err_algs;
188562306a36Sopenharmony_ci		}
188662306a36Sopenharmony_ci	}
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ci	return 0;
188962306a36Sopenharmony_cierr_algs:
189062306a36Sopenharmony_ci	dev_err(hdev->dev, "Algo %d : %d failed\n", i, j);
189162306a36Sopenharmony_ci	for (; i--; ) {
189262306a36Sopenharmony_ci		for (; j--;)
189362306a36Sopenharmony_ci			crypto_engine_unregister_ahash(
189462306a36Sopenharmony_ci				&hdev->pdata->algs_info[i].algs_list[j]);
189562306a36Sopenharmony_ci	}
189662306a36Sopenharmony_ci
189762306a36Sopenharmony_ci	return err;
189862306a36Sopenharmony_ci}
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_cistatic int stm32_hash_unregister_algs(struct stm32_hash_dev *hdev)
190162306a36Sopenharmony_ci{
190262306a36Sopenharmony_ci	unsigned int i, j;
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci	for (i = 0; i < hdev->pdata->algs_info_size; i++) {
190562306a36Sopenharmony_ci		for (j = 0; j < hdev->pdata->algs_info[i].size; j++)
190662306a36Sopenharmony_ci			crypto_engine_unregister_ahash(
190762306a36Sopenharmony_ci				&hdev->pdata->algs_info[i].algs_list[j]);
190862306a36Sopenharmony_ci	}
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	return 0;
191162306a36Sopenharmony_ci}
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_cistatic struct stm32_hash_algs_info stm32_hash_algs_info_ux500[] = {
191462306a36Sopenharmony_ci	{
191562306a36Sopenharmony_ci		.algs_list	= algs_sha1,
191662306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha1),
191762306a36Sopenharmony_ci	},
191862306a36Sopenharmony_ci	{
191962306a36Sopenharmony_ci		.algs_list	= algs_sha256,
192062306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha256),
192162306a36Sopenharmony_ci	},
192262306a36Sopenharmony_ci};
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_cistatic const struct stm32_hash_pdata stm32_hash_pdata_ux500 = {
192562306a36Sopenharmony_ci	.alg_shift	= 7,
192662306a36Sopenharmony_ci	.algs_info	= stm32_hash_algs_info_ux500,
192762306a36Sopenharmony_ci	.algs_info_size	= ARRAY_SIZE(stm32_hash_algs_info_ux500),
192862306a36Sopenharmony_ci	.broken_emptymsg = true,
192962306a36Sopenharmony_ci	.ux500		= true,
193062306a36Sopenharmony_ci};
193162306a36Sopenharmony_ci
193262306a36Sopenharmony_cistatic struct stm32_hash_algs_info stm32_hash_algs_info_stm32f4[] = {
193362306a36Sopenharmony_ci	{
193462306a36Sopenharmony_ci		.algs_list	= algs_md5,
193562306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_md5),
193662306a36Sopenharmony_ci	},
193762306a36Sopenharmony_ci	{
193862306a36Sopenharmony_ci		.algs_list	= algs_sha1,
193962306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha1),
194062306a36Sopenharmony_ci	},
194162306a36Sopenharmony_ci};
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_cistatic const struct stm32_hash_pdata stm32_hash_pdata_stm32f4 = {
194462306a36Sopenharmony_ci	.alg_shift	= 7,
194562306a36Sopenharmony_ci	.algs_info	= stm32_hash_algs_info_stm32f4,
194662306a36Sopenharmony_ci	.algs_info_size	= ARRAY_SIZE(stm32_hash_algs_info_stm32f4),
194762306a36Sopenharmony_ci	.has_sr		= true,
194862306a36Sopenharmony_ci	.has_mdmat	= true,
194962306a36Sopenharmony_ci};
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_cistatic struct stm32_hash_algs_info stm32_hash_algs_info_stm32f7[] = {
195262306a36Sopenharmony_ci	{
195362306a36Sopenharmony_ci		.algs_list	= algs_md5,
195462306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_md5),
195562306a36Sopenharmony_ci	},
195662306a36Sopenharmony_ci	{
195762306a36Sopenharmony_ci		.algs_list	= algs_sha1,
195862306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha1),
195962306a36Sopenharmony_ci	},
196062306a36Sopenharmony_ci	{
196162306a36Sopenharmony_ci		.algs_list	= algs_sha224,
196262306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha224),
196362306a36Sopenharmony_ci	},
196462306a36Sopenharmony_ci	{
196562306a36Sopenharmony_ci		.algs_list	= algs_sha256,
196662306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha256),
196762306a36Sopenharmony_ci	},
196862306a36Sopenharmony_ci};
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_cistatic const struct stm32_hash_pdata stm32_hash_pdata_stm32f7 = {
197162306a36Sopenharmony_ci	.alg_shift	= 7,
197262306a36Sopenharmony_ci	.algs_info	= stm32_hash_algs_info_stm32f7,
197362306a36Sopenharmony_ci	.algs_info_size	= ARRAY_SIZE(stm32_hash_algs_info_stm32f7),
197462306a36Sopenharmony_ci	.has_sr		= true,
197562306a36Sopenharmony_ci	.has_mdmat	= true,
197662306a36Sopenharmony_ci};
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_cistatic struct stm32_hash_algs_info stm32_hash_algs_info_stm32mp13[] = {
197962306a36Sopenharmony_ci	{
198062306a36Sopenharmony_ci		.algs_list	= algs_sha1,
198162306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha1),
198262306a36Sopenharmony_ci	},
198362306a36Sopenharmony_ci	{
198462306a36Sopenharmony_ci		.algs_list	= algs_sha224,
198562306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha224),
198662306a36Sopenharmony_ci	},
198762306a36Sopenharmony_ci	{
198862306a36Sopenharmony_ci		.algs_list	= algs_sha256,
198962306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha256),
199062306a36Sopenharmony_ci	},
199162306a36Sopenharmony_ci	{
199262306a36Sopenharmony_ci		.algs_list	= algs_sha384_sha512,
199362306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha384_sha512),
199462306a36Sopenharmony_ci	},
199562306a36Sopenharmony_ci	{
199662306a36Sopenharmony_ci		.algs_list	= algs_sha3,
199762306a36Sopenharmony_ci		.size		= ARRAY_SIZE(algs_sha3),
199862306a36Sopenharmony_ci	},
199962306a36Sopenharmony_ci};
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_cistatic const struct stm32_hash_pdata stm32_hash_pdata_stm32mp13 = {
200262306a36Sopenharmony_ci	.alg_shift	= 17,
200362306a36Sopenharmony_ci	.algs_info	= stm32_hash_algs_info_stm32mp13,
200462306a36Sopenharmony_ci	.algs_info_size	= ARRAY_SIZE(stm32_hash_algs_info_stm32mp13),
200562306a36Sopenharmony_ci	.has_sr		= true,
200662306a36Sopenharmony_ci	.has_mdmat	= true,
200762306a36Sopenharmony_ci};
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_cistatic const struct of_device_id stm32_hash_of_match[] = {
201062306a36Sopenharmony_ci	{ .compatible = "stericsson,ux500-hash", .data = &stm32_hash_pdata_ux500 },
201162306a36Sopenharmony_ci	{ .compatible = "st,stm32f456-hash", .data = &stm32_hash_pdata_stm32f4 },
201262306a36Sopenharmony_ci	{ .compatible = "st,stm32f756-hash", .data = &stm32_hash_pdata_stm32f7 },
201362306a36Sopenharmony_ci	{ .compatible = "st,stm32mp13-hash", .data = &stm32_hash_pdata_stm32mp13 },
201462306a36Sopenharmony_ci	{},
201562306a36Sopenharmony_ci};
201662306a36Sopenharmony_ci
201762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, stm32_hash_of_match);
201862306a36Sopenharmony_ci
201962306a36Sopenharmony_cistatic int stm32_hash_get_of_match(struct stm32_hash_dev *hdev,
202062306a36Sopenharmony_ci				   struct device *dev)
202162306a36Sopenharmony_ci{
202262306a36Sopenharmony_ci	hdev->pdata = of_device_get_match_data(dev);
202362306a36Sopenharmony_ci	if (!hdev->pdata) {
202462306a36Sopenharmony_ci		dev_err(dev, "no compatible OF match\n");
202562306a36Sopenharmony_ci		return -EINVAL;
202662306a36Sopenharmony_ci	}
202762306a36Sopenharmony_ci
202862306a36Sopenharmony_ci	return 0;
202962306a36Sopenharmony_ci}
203062306a36Sopenharmony_ci
203162306a36Sopenharmony_cistatic int stm32_hash_probe(struct platform_device *pdev)
203262306a36Sopenharmony_ci{
203362306a36Sopenharmony_ci	struct stm32_hash_dev *hdev;
203462306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
203562306a36Sopenharmony_ci	struct resource *res;
203662306a36Sopenharmony_ci	int ret, irq;
203762306a36Sopenharmony_ci
203862306a36Sopenharmony_ci	hdev = devm_kzalloc(dev, sizeof(*hdev), GFP_KERNEL);
203962306a36Sopenharmony_ci	if (!hdev)
204062306a36Sopenharmony_ci		return -ENOMEM;
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci	hdev->io_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
204362306a36Sopenharmony_ci	if (IS_ERR(hdev->io_base))
204462306a36Sopenharmony_ci		return PTR_ERR(hdev->io_base);
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_ci	hdev->phys_base = res->start;
204762306a36Sopenharmony_ci
204862306a36Sopenharmony_ci	ret = stm32_hash_get_of_match(hdev, dev);
204962306a36Sopenharmony_ci	if (ret)
205062306a36Sopenharmony_ci		return ret;
205162306a36Sopenharmony_ci
205262306a36Sopenharmony_ci	irq = platform_get_irq_optional(pdev, 0);
205362306a36Sopenharmony_ci	if (irq < 0 && irq != -ENXIO)
205462306a36Sopenharmony_ci		return irq;
205562306a36Sopenharmony_ci
205662306a36Sopenharmony_ci	if (irq > 0) {
205762306a36Sopenharmony_ci		ret = devm_request_threaded_irq(dev, irq,
205862306a36Sopenharmony_ci						stm32_hash_irq_handler,
205962306a36Sopenharmony_ci						stm32_hash_irq_thread,
206062306a36Sopenharmony_ci						IRQF_ONESHOT,
206162306a36Sopenharmony_ci						dev_name(dev), hdev);
206262306a36Sopenharmony_ci		if (ret) {
206362306a36Sopenharmony_ci			dev_err(dev, "Cannot grab IRQ\n");
206462306a36Sopenharmony_ci			return ret;
206562306a36Sopenharmony_ci		}
206662306a36Sopenharmony_ci	} else {
206762306a36Sopenharmony_ci		dev_info(dev, "No IRQ, use polling mode\n");
206862306a36Sopenharmony_ci		hdev->polled = true;
206962306a36Sopenharmony_ci	}
207062306a36Sopenharmony_ci
207162306a36Sopenharmony_ci	hdev->clk = devm_clk_get(&pdev->dev, NULL);
207262306a36Sopenharmony_ci	if (IS_ERR(hdev->clk))
207362306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(hdev->clk),
207462306a36Sopenharmony_ci				     "failed to get clock for hash\n");
207562306a36Sopenharmony_ci
207662306a36Sopenharmony_ci	ret = clk_prepare_enable(hdev->clk);
207762306a36Sopenharmony_ci	if (ret) {
207862306a36Sopenharmony_ci		dev_err(dev, "failed to enable hash clock (%d)\n", ret);
207962306a36Sopenharmony_ci		return ret;
208062306a36Sopenharmony_ci	}
208162306a36Sopenharmony_ci
208262306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(dev, HASH_AUTOSUSPEND_DELAY);
208362306a36Sopenharmony_ci	pm_runtime_use_autosuspend(dev);
208462306a36Sopenharmony_ci
208562306a36Sopenharmony_ci	pm_runtime_get_noresume(dev);
208662306a36Sopenharmony_ci	pm_runtime_set_active(dev);
208762306a36Sopenharmony_ci	pm_runtime_enable(dev);
208862306a36Sopenharmony_ci
208962306a36Sopenharmony_ci	hdev->rst = devm_reset_control_get(&pdev->dev, NULL);
209062306a36Sopenharmony_ci	if (IS_ERR(hdev->rst)) {
209162306a36Sopenharmony_ci		if (PTR_ERR(hdev->rst) == -EPROBE_DEFER) {
209262306a36Sopenharmony_ci			ret = -EPROBE_DEFER;
209362306a36Sopenharmony_ci			goto err_reset;
209462306a36Sopenharmony_ci		}
209562306a36Sopenharmony_ci	} else {
209662306a36Sopenharmony_ci		reset_control_assert(hdev->rst);
209762306a36Sopenharmony_ci		udelay(2);
209862306a36Sopenharmony_ci		reset_control_deassert(hdev->rst);
209962306a36Sopenharmony_ci	}
210062306a36Sopenharmony_ci
210162306a36Sopenharmony_ci	hdev->dev = dev;
210262306a36Sopenharmony_ci
210362306a36Sopenharmony_ci	platform_set_drvdata(pdev, hdev);
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	ret = stm32_hash_dma_init(hdev);
210662306a36Sopenharmony_ci	switch (ret) {
210762306a36Sopenharmony_ci	case 0:
210862306a36Sopenharmony_ci		break;
210962306a36Sopenharmony_ci	case -ENOENT:
211062306a36Sopenharmony_ci	case -ENODEV:
211162306a36Sopenharmony_ci		dev_info(dev, "DMA mode not available\n");
211262306a36Sopenharmony_ci		break;
211362306a36Sopenharmony_ci	default:
211462306a36Sopenharmony_ci		dev_err(dev, "DMA init error %d\n", ret);
211562306a36Sopenharmony_ci		goto err_dma;
211662306a36Sopenharmony_ci	}
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_ci	spin_lock(&stm32_hash.lock);
211962306a36Sopenharmony_ci	list_add_tail(&hdev->list, &stm32_hash.dev_list);
212062306a36Sopenharmony_ci	spin_unlock(&stm32_hash.lock);
212162306a36Sopenharmony_ci
212262306a36Sopenharmony_ci	/* Initialize crypto engine */
212362306a36Sopenharmony_ci	hdev->engine = crypto_engine_alloc_init(dev, 1);
212462306a36Sopenharmony_ci	if (!hdev->engine) {
212562306a36Sopenharmony_ci		ret = -ENOMEM;
212662306a36Sopenharmony_ci		goto err_engine;
212762306a36Sopenharmony_ci	}
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci	ret = crypto_engine_start(hdev->engine);
213062306a36Sopenharmony_ci	if (ret)
213162306a36Sopenharmony_ci		goto err_engine_start;
213262306a36Sopenharmony_ci
213362306a36Sopenharmony_ci	if (hdev->pdata->ux500)
213462306a36Sopenharmony_ci		/* FIXME: implement DMA mode for Ux500 */
213562306a36Sopenharmony_ci		hdev->dma_mode = 0;
213662306a36Sopenharmony_ci	else
213762306a36Sopenharmony_ci		hdev->dma_mode = stm32_hash_read(hdev, HASH_HWCFGR) & HASH_HWCFG_DMA_MASK;
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_ci	/* Register algos */
214062306a36Sopenharmony_ci	ret = stm32_hash_register_algs(hdev);
214162306a36Sopenharmony_ci	if (ret)
214262306a36Sopenharmony_ci		goto err_algs;
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci	dev_info(dev, "Init HASH done HW ver %x DMA mode %u\n",
214562306a36Sopenharmony_ci		 stm32_hash_read(hdev, HASH_VER), hdev->dma_mode);
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci	pm_runtime_put_sync(dev);
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci	return 0;
215062306a36Sopenharmony_ci
215162306a36Sopenharmony_cierr_algs:
215262306a36Sopenharmony_cierr_engine_start:
215362306a36Sopenharmony_ci	crypto_engine_exit(hdev->engine);
215462306a36Sopenharmony_cierr_engine:
215562306a36Sopenharmony_ci	spin_lock(&stm32_hash.lock);
215662306a36Sopenharmony_ci	list_del(&hdev->list);
215762306a36Sopenharmony_ci	spin_unlock(&stm32_hash.lock);
215862306a36Sopenharmony_cierr_dma:
215962306a36Sopenharmony_ci	if (hdev->dma_lch)
216062306a36Sopenharmony_ci		dma_release_channel(hdev->dma_lch);
216162306a36Sopenharmony_cierr_reset:
216262306a36Sopenharmony_ci	pm_runtime_disable(dev);
216362306a36Sopenharmony_ci	pm_runtime_put_noidle(dev);
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci	clk_disable_unprepare(hdev->clk);
216662306a36Sopenharmony_ci
216762306a36Sopenharmony_ci	return ret;
216862306a36Sopenharmony_ci}
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_cistatic void stm32_hash_remove(struct platform_device *pdev)
217162306a36Sopenharmony_ci{
217262306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = platform_get_drvdata(pdev);
217362306a36Sopenharmony_ci	int ret;
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_ci	ret = pm_runtime_get_sync(hdev->dev);
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci	stm32_hash_unregister_algs(hdev);
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci	crypto_engine_exit(hdev->engine);
218062306a36Sopenharmony_ci
218162306a36Sopenharmony_ci	spin_lock(&stm32_hash.lock);
218262306a36Sopenharmony_ci	list_del(&hdev->list);
218362306a36Sopenharmony_ci	spin_unlock(&stm32_hash.lock);
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_ci	if (hdev->dma_lch)
218662306a36Sopenharmony_ci		dma_release_channel(hdev->dma_lch);
218762306a36Sopenharmony_ci
218862306a36Sopenharmony_ci	pm_runtime_disable(hdev->dev);
218962306a36Sopenharmony_ci	pm_runtime_put_noidle(hdev->dev);
219062306a36Sopenharmony_ci
219162306a36Sopenharmony_ci	if (ret >= 0)
219262306a36Sopenharmony_ci		clk_disable_unprepare(hdev->clk);
219362306a36Sopenharmony_ci}
219462306a36Sopenharmony_ci
219562306a36Sopenharmony_ci#ifdef CONFIG_PM
219662306a36Sopenharmony_cistatic int stm32_hash_runtime_suspend(struct device *dev)
219762306a36Sopenharmony_ci{
219862306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = dev_get_drvdata(dev);
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci	clk_disable_unprepare(hdev->clk);
220162306a36Sopenharmony_ci
220262306a36Sopenharmony_ci	return 0;
220362306a36Sopenharmony_ci}
220462306a36Sopenharmony_ci
220562306a36Sopenharmony_cistatic int stm32_hash_runtime_resume(struct device *dev)
220662306a36Sopenharmony_ci{
220762306a36Sopenharmony_ci	struct stm32_hash_dev *hdev = dev_get_drvdata(dev);
220862306a36Sopenharmony_ci	int ret;
220962306a36Sopenharmony_ci
221062306a36Sopenharmony_ci	ret = clk_prepare_enable(hdev->clk);
221162306a36Sopenharmony_ci	if (ret) {
221262306a36Sopenharmony_ci		dev_err(hdev->dev, "Failed to prepare_enable clock\n");
221362306a36Sopenharmony_ci		return ret;
221462306a36Sopenharmony_ci	}
221562306a36Sopenharmony_ci
221662306a36Sopenharmony_ci	return 0;
221762306a36Sopenharmony_ci}
221862306a36Sopenharmony_ci#endif
221962306a36Sopenharmony_ci
222062306a36Sopenharmony_cistatic const struct dev_pm_ops stm32_hash_pm_ops = {
222162306a36Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
222262306a36Sopenharmony_ci				pm_runtime_force_resume)
222362306a36Sopenharmony_ci	SET_RUNTIME_PM_OPS(stm32_hash_runtime_suspend,
222462306a36Sopenharmony_ci			   stm32_hash_runtime_resume, NULL)
222562306a36Sopenharmony_ci};
222662306a36Sopenharmony_ci
222762306a36Sopenharmony_cistatic struct platform_driver stm32_hash_driver = {
222862306a36Sopenharmony_ci	.probe		= stm32_hash_probe,
222962306a36Sopenharmony_ci	.remove_new	= stm32_hash_remove,
223062306a36Sopenharmony_ci	.driver		= {
223162306a36Sopenharmony_ci		.name	= "stm32-hash",
223262306a36Sopenharmony_ci		.pm = &stm32_hash_pm_ops,
223362306a36Sopenharmony_ci		.of_match_table	= stm32_hash_of_match,
223462306a36Sopenharmony_ci	}
223562306a36Sopenharmony_ci};
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_cimodule_platform_driver(stm32_hash_driver);
223862306a36Sopenharmony_ci
223962306a36Sopenharmony_ciMODULE_DESCRIPTION("STM32 SHA1/SHA2/SHA3 & MD5 (HMAC) hw accelerator driver");
224062306a36Sopenharmony_ciMODULE_AUTHOR("Lionel Debieve <lionel.debieve@st.com>");
224162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
2242