xref: /linux/drivers/crypto/ccree/cc_hash.c (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
163893811SGilad Ben-Yossef // SPDX-License-Identifier: GPL-2.0
203963caeSGilad Ben-Yossef /* Copyright (C) 2012-2019 ARM Limited (or its affiliates). */
363893811SGilad Ben-Yossef 
463893811SGilad Ben-Yossef #include <linux/kernel.h>
563893811SGilad Ben-Yossef #include <linux/module.h>
663893811SGilad Ben-Yossef #include <crypto/algapi.h>
763893811SGilad Ben-Yossef #include <crypto/hash.h>
863893811SGilad Ben-Yossef #include <crypto/md5.h>
9927574e0SYael Chemla #include <crypto/sm3.h>
1063893811SGilad Ben-Yossef #include <crypto/internal/hash.h>
1163893811SGilad Ben-Yossef 
1263893811SGilad Ben-Yossef #include "cc_driver.h"
1363893811SGilad Ben-Yossef #include "cc_request_mgr.h"
1463893811SGilad Ben-Yossef #include "cc_buffer_mgr.h"
1563893811SGilad Ben-Yossef #include "cc_hash.h"
1663893811SGilad Ben-Yossef #include "cc_sram_mgr.h"
1763893811SGilad Ben-Yossef 
1863893811SGilad Ben-Yossef #define CC_MAX_HASH_SEQ_LEN 12
1963893811SGilad Ben-Yossef #define CC_MAX_OPAD_KEYS_SIZE CC_MAX_HASH_BLCK_SIZE
20927574e0SYael Chemla #define CC_SM3_HASH_LEN_SIZE 8
2163893811SGilad Ben-Yossef 
2263893811SGilad Ben-Yossef struct cc_hash_handle {
231a895f1dSGeert Uytterhoeven 	u32 digest_len_sram_addr;	/* const value in SRAM*/
241a895f1dSGeert Uytterhoeven 	u32 larval_digest_sram_addr;   /* const value in SRAM */
2563893811SGilad Ben-Yossef 	struct list_head hash_list;
2663893811SGilad Ben-Yossef };
2763893811SGilad Ben-Yossef 
28e55d8a75SHans de Goede static const u32 cc_digest_len_init[] = {
2963893811SGilad Ben-Yossef 	0x00000040, 0x00000000, 0x00000000, 0x00000000 };
30e55d8a75SHans de Goede static const u32 cc_md5_init[] = {
3163893811SGilad Ben-Yossef 	SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 };
32e55d8a75SHans de Goede static const u32 cc_sha1_init[] = {
3363893811SGilad Ben-Yossef 	SHA1_H4, SHA1_H3, SHA1_H2, SHA1_H1, SHA1_H0 };
34e55d8a75SHans de Goede static const u32 cc_sha224_init[] = {
3563893811SGilad Ben-Yossef 	SHA224_H7, SHA224_H6, SHA224_H5, SHA224_H4,
3663893811SGilad Ben-Yossef 	SHA224_H3, SHA224_H2, SHA224_H1, SHA224_H0 };
37e55d8a75SHans de Goede static const u32 cc_sha256_init[] = {
3863893811SGilad Ben-Yossef 	SHA256_H7, SHA256_H6, SHA256_H5, SHA256_H4,
3963893811SGilad Ben-Yossef 	SHA256_H3, SHA256_H2, SHA256_H1, SHA256_H0 };
40e55d8a75SHans de Goede static const u32 cc_digest_len_sha512_init[] = {
4163893811SGilad Ben-Yossef 	0x00000080, 0x00000000, 0x00000000, 0x00000000 };
42f08b5850SGeert Uytterhoeven 
43f08b5850SGeert Uytterhoeven /*
44f08b5850SGeert Uytterhoeven  * Due to the way the HW works, every double word in the SHA384 and SHA512
45f08b5850SGeert Uytterhoeven  * larval hashes must be stored in hi/lo order
46f08b5850SGeert Uytterhoeven  */
47f08b5850SGeert Uytterhoeven #define hilo(x)	upper_32_bits(x), lower_32_bits(x)
48f08b5850SGeert Uytterhoeven static const u32 cc_sha384_init[] = {
49f08b5850SGeert Uytterhoeven 	hilo(SHA384_H7), hilo(SHA384_H6), hilo(SHA384_H5), hilo(SHA384_H4),
50f08b5850SGeert Uytterhoeven 	hilo(SHA384_H3), hilo(SHA384_H2), hilo(SHA384_H1), hilo(SHA384_H0) };
51f08b5850SGeert Uytterhoeven static const u32 cc_sha512_init[] = {
52f08b5850SGeert Uytterhoeven 	hilo(SHA512_H7), hilo(SHA512_H6), hilo(SHA512_H5), hilo(SHA512_H4),
53f08b5850SGeert Uytterhoeven 	hilo(SHA512_H3), hilo(SHA512_H2), hilo(SHA512_H1), hilo(SHA512_H0) };
54f08b5850SGeert Uytterhoeven 
55e55d8a75SHans de Goede static const u32 cc_sm3_init[] = {
56927574e0SYael Chemla 	SM3_IVH, SM3_IVG, SM3_IVF, SM3_IVE,
57927574e0SYael Chemla 	SM3_IVD, SM3_IVC, SM3_IVB, SM3_IVA };
5863893811SGilad Ben-Yossef 
5963893811SGilad Ben-Yossef static void cc_setup_xcbc(struct ahash_request *areq, struct cc_hw_desc desc[],
6063893811SGilad Ben-Yossef 			  unsigned int *seq_size);
6163893811SGilad Ben-Yossef 
6263893811SGilad Ben-Yossef static void cc_setup_cmac(struct ahash_request *areq, struct cc_hw_desc desc[],
6363893811SGilad Ben-Yossef 			  unsigned int *seq_size);
6463893811SGilad Ben-Yossef 
6563893811SGilad Ben-Yossef static const void *cc_larval_digest(struct device *dev, u32 mode);
6663893811SGilad Ben-Yossef 
6763893811SGilad Ben-Yossef struct cc_hash_alg {
6863893811SGilad Ben-Yossef 	struct list_head entry;
6963893811SGilad Ben-Yossef 	int hash_mode;
7063893811SGilad Ben-Yossef 	int hw_mode;
7163893811SGilad Ben-Yossef 	int inter_digestsize;
7263893811SGilad Ben-Yossef 	struct cc_drvdata *drvdata;
7363893811SGilad Ben-Yossef 	struct ahash_alg ahash_alg;
7463893811SGilad Ben-Yossef };
7563893811SGilad Ben-Yossef 
7663893811SGilad Ben-Yossef struct hash_key_req_ctx {
7763893811SGilad Ben-Yossef 	u32 keylen;
7863893811SGilad Ben-Yossef 	dma_addr_t key_dma_addr;
79874e1637SGilad Ben-Yossef 	u8 *key;
8063893811SGilad Ben-Yossef };
8163893811SGilad Ben-Yossef 
8263893811SGilad Ben-Yossef /* hash per-session context */
8363893811SGilad Ben-Yossef struct cc_hash_ctx {
8463893811SGilad Ben-Yossef 	struct cc_drvdata *drvdata;
8563893811SGilad Ben-Yossef 	/* holds the origin digest; the digest after "setkey" if HMAC,*
8663893811SGilad Ben-Yossef 	 * the initial digest if HASH.
8763893811SGilad Ben-Yossef 	 */
8863893811SGilad Ben-Yossef 	u8 digest_buff[CC_MAX_HASH_DIGEST_SIZE]  ____cacheline_aligned;
8963893811SGilad Ben-Yossef 	u8 opad_tmp_keys_buff[CC_MAX_OPAD_KEYS_SIZE]  ____cacheline_aligned;
9063893811SGilad Ben-Yossef 
9163893811SGilad Ben-Yossef 	dma_addr_t opad_tmp_keys_dma_addr  ____cacheline_aligned;
9263893811SGilad Ben-Yossef 	dma_addr_t digest_buff_dma_addr;
9363893811SGilad Ben-Yossef 	/* use for hmac with key large then mode block size */
9463893811SGilad Ben-Yossef 	struct hash_key_req_ctx key_params;
9563893811SGilad Ben-Yossef 	int hash_mode;
9663893811SGilad Ben-Yossef 	int hw_mode;
9763893811SGilad Ben-Yossef 	int inter_digestsize;
98f1e52fd0SYael Chemla 	unsigned int hash_len;
9963893811SGilad Ben-Yossef 	struct completion setkey_comp;
10063893811SGilad Ben-Yossef 	bool is_hmac;
10163893811SGilad Ben-Yossef };
10263893811SGilad Ben-Yossef 
10363893811SGilad Ben-Yossef static void cc_set_desc(struct ahash_req_ctx *areq_ctx, struct cc_hash_ctx *ctx,
10463893811SGilad Ben-Yossef 			unsigned int flow_mode, struct cc_hw_desc desc[],
10563893811SGilad Ben-Yossef 			bool is_not_last_data, unsigned int *seq_size);
10663893811SGilad Ben-Yossef 
cc_set_endianity(u32 mode,struct cc_hw_desc * desc)10763893811SGilad Ben-Yossef static void cc_set_endianity(u32 mode, struct cc_hw_desc *desc)
10863893811SGilad Ben-Yossef {
10963893811SGilad Ben-Yossef 	if (mode == DRV_HASH_MD5 || mode == DRV_HASH_SHA384 ||
11063893811SGilad Ben-Yossef 	    mode == DRV_HASH_SHA512) {
11163893811SGilad Ben-Yossef 		set_bytes_swap(desc, 1);
11263893811SGilad Ben-Yossef 	} else {
11363893811SGilad Ben-Yossef 		set_cipher_config0(desc, HASH_DIGEST_RESULT_LITTLE_ENDIAN);
11463893811SGilad Ben-Yossef 	}
11563893811SGilad Ben-Yossef }
11663893811SGilad Ben-Yossef 
cc_map_result(struct device * dev,struct ahash_req_ctx * state,unsigned int digestsize)11763893811SGilad Ben-Yossef static int cc_map_result(struct device *dev, struct ahash_req_ctx *state,
11863893811SGilad Ben-Yossef 			 unsigned int digestsize)
11963893811SGilad Ben-Yossef {
12063893811SGilad Ben-Yossef 	state->digest_result_dma_addr =
12163893811SGilad Ben-Yossef 		dma_map_single(dev, state->digest_result_buff,
12263893811SGilad Ben-Yossef 			       digestsize, DMA_BIDIRECTIONAL);
12363893811SGilad Ben-Yossef 	if (dma_mapping_error(dev, state->digest_result_dma_addr)) {
12463893811SGilad Ben-Yossef 		dev_err(dev, "Mapping digest result buffer %u B for DMA failed\n",
12563893811SGilad Ben-Yossef 			digestsize);
12663893811SGilad Ben-Yossef 		return -ENOMEM;
12763893811SGilad Ben-Yossef 	}
12863893811SGilad Ben-Yossef 	dev_dbg(dev, "Mapped digest result buffer %u B at va=%pK to dma=%pad\n",
12963893811SGilad Ben-Yossef 		digestsize, state->digest_result_buff,
13063893811SGilad Ben-Yossef 		&state->digest_result_dma_addr);
13163893811SGilad Ben-Yossef 
13263893811SGilad Ben-Yossef 	return 0;
13363893811SGilad Ben-Yossef }
13463893811SGilad Ben-Yossef 
cc_init_req(struct device * dev,struct ahash_req_ctx * state,struct cc_hash_ctx * ctx)13563893811SGilad Ben-Yossef static void cc_init_req(struct device *dev, struct ahash_req_ctx *state,
13663893811SGilad Ben-Yossef 			struct cc_hash_ctx *ctx)
13763893811SGilad Ben-Yossef {
13863893811SGilad Ben-Yossef 	bool is_hmac = ctx->is_hmac;
13963893811SGilad Ben-Yossef 
14063893811SGilad Ben-Yossef 	memset(state, 0, sizeof(*state));
14163893811SGilad Ben-Yossef 
14263893811SGilad Ben-Yossef 	if (is_hmac) {
14363893811SGilad Ben-Yossef 		if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC &&
14463893811SGilad Ben-Yossef 		    ctx->hw_mode != DRV_CIPHER_CMAC) {
14563893811SGilad Ben-Yossef 			dma_sync_single_for_cpu(dev, ctx->digest_buff_dma_addr,
14663893811SGilad Ben-Yossef 						ctx->inter_digestsize,
14763893811SGilad Ben-Yossef 						DMA_BIDIRECTIONAL);
14863893811SGilad Ben-Yossef 
14963893811SGilad Ben-Yossef 			memcpy(state->digest_buff, ctx->digest_buff,
15063893811SGilad Ben-Yossef 			       ctx->inter_digestsize);
15163893811SGilad Ben-Yossef 			if (ctx->hash_mode == DRV_HASH_SHA512 ||
15263893811SGilad Ben-Yossef 			    ctx->hash_mode == DRV_HASH_SHA384)
15363893811SGilad Ben-Yossef 				memcpy(state->digest_bytes_len,
154e55d8a75SHans de Goede 				       cc_digest_len_sha512_init,
155f1e52fd0SYael Chemla 				       ctx->hash_len);
15663893811SGilad Ben-Yossef 			else
157e55d8a75SHans de Goede 				memcpy(state->digest_bytes_len,
158e55d8a75SHans de Goede 				       cc_digest_len_init,
159f1e52fd0SYael Chemla 				       ctx->hash_len);
16063893811SGilad Ben-Yossef 		}
16163893811SGilad Ben-Yossef 
16263893811SGilad Ben-Yossef 		if (ctx->hash_mode != DRV_HASH_NULL) {
16363893811SGilad Ben-Yossef 			dma_sync_single_for_cpu(dev,
16463893811SGilad Ben-Yossef 						ctx->opad_tmp_keys_dma_addr,
16563893811SGilad Ben-Yossef 						ctx->inter_digestsize,
16663893811SGilad Ben-Yossef 						DMA_BIDIRECTIONAL);
16763893811SGilad Ben-Yossef 			memcpy(state->opad_digest_buff,
16863893811SGilad Ben-Yossef 			       ctx->opad_tmp_keys_buff, ctx->inter_digestsize);
16963893811SGilad Ben-Yossef 		}
17063893811SGilad Ben-Yossef 	} else { /*hash*/
17163893811SGilad Ben-Yossef 		/* Copy the initial digests if hash flow. */
17263893811SGilad Ben-Yossef 		const void *larval = cc_larval_digest(dev, ctx->hash_mode);
17363893811SGilad Ben-Yossef 
17463893811SGilad Ben-Yossef 		memcpy(state->digest_buff, larval, ctx->inter_digestsize);
17563893811SGilad Ben-Yossef 	}
17663893811SGilad Ben-Yossef }
17763893811SGilad Ben-Yossef 
cc_map_req(struct device * dev,struct ahash_req_ctx * state,struct cc_hash_ctx * ctx)17863893811SGilad Ben-Yossef static int cc_map_req(struct device *dev, struct ahash_req_ctx *state,
17963893811SGilad Ben-Yossef 		      struct cc_hash_ctx *ctx)
18063893811SGilad Ben-Yossef {
18163893811SGilad Ben-Yossef 	bool is_hmac = ctx->is_hmac;
18263893811SGilad Ben-Yossef 
18363893811SGilad Ben-Yossef 	state->digest_buff_dma_addr =
18463893811SGilad Ben-Yossef 		dma_map_single(dev, state->digest_buff,
18563893811SGilad Ben-Yossef 			       ctx->inter_digestsize, DMA_BIDIRECTIONAL);
18663893811SGilad Ben-Yossef 	if (dma_mapping_error(dev, state->digest_buff_dma_addr)) {
18763893811SGilad Ben-Yossef 		dev_err(dev, "Mapping digest len %d B at va=%pK for DMA failed\n",
18863893811SGilad Ben-Yossef 			ctx->inter_digestsize, state->digest_buff);
18963893811SGilad Ben-Yossef 		return -EINVAL;
19063893811SGilad Ben-Yossef 	}
19163893811SGilad Ben-Yossef 	dev_dbg(dev, "Mapped digest %d B at va=%pK to dma=%pad\n",
19263893811SGilad Ben-Yossef 		ctx->inter_digestsize, state->digest_buff,
19363893811SGilad Ben-Yossef 		&state->digest_buff_dma_addr);
19463893811SGilad Ben-Yossef 
19563893811SGilad Ben-Yossef 	if (ctx->hw_mode != DRV_CIPHER_XCBC_MAC) {
19663893811SGilad Ben-Yossef 		state->digest_bytes_len_dma_addr =
19763893811SGilad Ben-Yossef 			dma_map_single(dev, state->digest_bytes_len,
19827b3b22dSGilad Ben-Yossef 				       HASH_MAX_LEN_SIZE, DMA_BIDIRECTIONAL);
19963893811SGilad Ben-Yossef 		if (dma_mapping_error(dev, state->digest_bytes_len_dma_addr)) {
20063893811SGilad Ben-Yossef 			dev_err(dev, "Mapping digest len %u B at va=%pK for DMA failed\n",
20127b3b22dSGilad Ben-Yossef 				HASH_MAX_LEN_SIZE, state->digest_bytes_len);
20263893811SGilad Ben-Yossef 			goto unmap_digest_buf;
20363893811SGilad Ben-Yossef 		}
20463893811SGilad Ben-Yossef 		dev_dbg(dev, "Mapped digest len %u B at va=%pK to dma=%pad\n",
20527b3b22dSGilad Ben-Yossef 			HASH_MAX_LEN_SIZE, state->digest_bytes_len,
20663893811SGilad Ben-Yossef 			&state->digest_bytes_len_dma_addr);
20763893811SGilad Ben-Yossef 	}
20863893811SGilad Ben-Yossef 
20963893811SGilad Ben-Yossef 	if (is_hmac && ctx->hash_mode != DRV_HASH_NULL) {
21063893811SGilad Ben-Yossef 		state->opad_digest_dma_addr =
21163893811SGilad Ben-Yossef 			dma_map_single(dev, state->opad_digest_buff,
21263893811SGilad Ben-Yossef 				       ctx->inter_digestsize,
21363893811SGilad Ben-Yossef 				       DMA_BIDIRECTIONAL);
21463893811SGilad Ben-Yossef 		if (dma_mapping_error(dev, state->opad_digest_dma_addr)) {
21563893811SGilad Ben-Yossef 			dev_err(dev, "Mapping opad digest %d B at va=%pK for DMA failed\n",
21663893811SGilad Ben-Yossef 				ctx->inter_digestsize,
21763893811SGilad Ben-Yossef 				state->opad_digest_buff);
21863893811SGilad Ben-Yossef 			goto unmap_digest_len;
21963893811SGilad Ben-Yossef 		}
22063893811SGilad Ben-Yossef 		dev_dbg(dev, "Mapped opad digest %d B at va=%pK to dma=%pad\n",
22163893811SGilad Ben-Yossef 			ctx->inter_digestsize, state->opad_digest_buff,
22263893811SGilad Ben-Yossef 			&state->opad_digest_dma_addr);
22363893811SGilad Ben-Yossef 	}
22463893811SGilad Ben-Yossef 
22563893811SGilad Ben-Yossef 	return 0;
22663893811SGilad Ben-Yossef 
22763893811SGilad Ben-Yossef unmap_digest_len:
22863893811SGilad Ben-Yossef 	if (state->digest_bytes_len_dma_addr) {
22963893811SGilad Ben-Yossef 		dma_unmap_single(dev, state->digest_bytes_len_dma_addr,
23027b3b22dSGilad Ben-Yossef 				 HASH_MAX_LEN_SIZE, DMA_BIDIRECTIONAL);
23163893811SGilad Ben-Yossef 		state->digest_bytes_len_dma_addr = 0;
23263893811SGilad Ben-Yossef 	}
23363893811SGilad Ben-Yossef unmap_digest_buf:
23463893811SGilad Ben-Yossef 	if (state->digest_buff_dma_addr) {
23563893811SGilad Ben-Yossef 		dma_unmap_single(dev, state->digest_buff_dma_addr,
23663893811SGilad Ben-Yossef 				 ctx->inter_digestsize, DMA_BIDIRECTIONAL);
23763893811SGilad Ben-Yossef 		state->digest_buff_dma_addr = 0;
23863893811SGilad Ben-Yossef 	}
23963893811SGilad Ben-Yossef 
24063893811SGilad Ben-Yossef 	return -EINVAL;
24163893811SGilad Ben-Yossef }
24263893811SGilad Ben-Yossef 
cc_unmap_req(struct device * dev,struct ahash_req_ctx * state,struct cc_hash_ctx * ctx)24363893811SGilad Ben-Yossef static void cc_unmap_req(struct device *dev, struct ahash_req_ctx *state,
24463893811SGilad Ben-Yossef 			 struct cc_hash_ctx *ctx)
24563893811SGilad Ben-Yossef {
24663893811SGilad Ben-Yossef 	if (state->digest_buff_dma_addr) {
24763893811SGilad Ben-Yossef 		dma_unmap_single(dev, state->digest_buff_dma_addr,
24863893811SGilad Ben-Yossef 				 ctx->inter_digestsize, DMA_BIDIRECTIONAL);
24963893811SGilad Ben-Yossef 		dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n",
25063893811SGilad Ben-Yossef 			&state->digest_buff_dma_addr);
25163893811SGilad Ben-Yossef 		state->digest_buff_dma_addr = 0;
25263893811SGilad Ben-Yossef 	}
25363893811SGilad Ben-Yossef 	if (state->digest_bytes_len_dma_addr) {
25463893811SGilad Ben-Yossef 		dma_unmap_single(dev, state->digest_bytes_len_dma_addr,
25527b3b22dSGilad Ben-Yossef 				 HASH_MAX_LEN_SIZE, DMA_BIDIRECTIONAL);
25663893811SGilad Ben-Yossef 		dev_dbg(dev, "Unmapped digest-bytes-len buffer: digest_bytes_len_dma_addr=%pad\n",
25763893811SGilad Ben-Yossef 			&state->digest_bytes_len_dma_addr);
25863893811SGilad Ben-Yossef 		state->digest_bytes_len_dma_addr = 0;
25963893811SGilad Ben-Yossef 	}
26063893811SGilad Ben-Yossef 	if (state->opad_digest_dma_addr) {
26163893811SGilad Ben-Yossef 		dma_unmap_single(dev, state->opad_digest_dma_addr,
26263893811SGilad Ben-Yossef 				 ctx->inter_digestsize, DMA_BIDIRECTIONAL);
26363893811SGilad Ben-Yossef 		dev_dbg(dev, "Unmapped opad-digest: opad_digest_dma_addr=%pad\n",
26463893811SGilad Ben-Yossef 			&state->opad_digest_dma_addr);
26563893811SGilad Ben-Yossef 		state->opad_digest_dma_addr = 0;
26663893811SGilad Ben-Yossef 	}
26763893811SGilad Ben-Yossef }
26863893811SGilad Ben-Yossef 
cc_unmap_result(struct device * dev,struct ahash_req_ctx * state,unsigned int digestsize,u8 * result)26963893811SGilad Ben-Yossef static void cc_unmap_result(struct device *dev, struct ahash_req_ctx *state,
27063893811SGilad Ben-Yossef 			    unsigned int digestsize, u8 *result)
27163893811SGilad Ben-Yossef {
27263893811SGilad Ben-Yossef 	if (state->digest_result_dma_addr) {
27363893811SGilad Ben-Yossef 		dma_unmap_single(dev, state->digest_result_dma_addr, digestsize,
27463893811SGilad Ben-Yossef 				 DMA_BIDIRECTIONAL);
27563893811SGilad Ben-Yossef 		dev_dbg(dev, "unmpa digest result buffer va (%pK) pa (%pad) len %u\n",
27663893811SGilad Ben-Yossef 			state->digest_result_buff,
27763893811SGilad Ben-Yossef 			&state->digest_result_dma_addr, digestsize);
27863893811SGilad Ben-Yossef 		memcpy(result, state->digest_result_buff, digestsize);
27963893811SGilad Ben-Yossef 	}
28063893811SGilad Ben-Yossef 	state->digest_result_dma_addr = 0;
28163893811SGilad Ben-Yossef }
28263893811SGilad Ben-Yossef 
cc_update_complete(struct device * dev,void * cc_req,int err)28363893811SGilad Ben-Yossef static void cc_update_complete(struct device *dev, void *cc_req, int err)
28463893811SGilad Ben-Yossef {
28563893811SGilad Ben-Yossef 	struct ahash_request *req = (struct ahash_request *)cc_req;
286*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
28763893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
288*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
28963893811SGilad Ben-Yossef 
29063893811SGilad Ben-Yossef 	dev_dbg(dev, "req=%pK\n", req);
29163893811SGilad Ben-Yossef 
292a108f931SGilad Ben-Yossef 	if (err != -EINPROGRESS) {
293a108f931SGilad Ben-Yossef 		/* Not a BACKLOG notification */
29463893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, req->src, false);
29563893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
296a108f931SGilad Ben-Yossef 	}
297a108f931SGilad Ben-Yossef 
298151ded73SGilad Ben-Yossef 	ahash_request_complete(req, err);
29963893811SGilad Ben-Yossef }
30063893811SGilad Ben-Yossef 
cc_digest_complete(struct device * dev,void * cc_req,int err)30163893811SGilad Ben-Yossef static void cc_digest_complete(struct device *dev, void *cc_req, int err)
30263893811SGilad Ben-Yossef {
30363893811SGilad Ben-Yossef 	struct ahash_request *req = (struct ahash_request *)cc_req;
304*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
30563893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
306*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
30763893811SGilad Ben-Yossef 	u32 digestsize = crypto_ahash_digestsize(tfm);
30863893811SGilad Ben-Yossef 
30963893811SGilad Ben-Yossef 	dev_dbg(dev, "req=%pK\n", req);
31063893811SGilad Ben-Yossef 
311a108f931SGilad Ben-Yossef 	if (err != -EINPROGRESS) {
312a108f931SGilad Ben-Yossef 		/* Not a BACKLOG notification */
31363893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, req->src, false);
31463893811SGilad Ben-Yossef 		cc_unmap_result(dev, state, digestsize, req->result);
31563893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
316a108f931SGilad Ben-Yossef 	}
317a108f931SGilad Ben-Yossef 
318151ded73SGilad Ben-Yossef 	ahash_request_complete(req, err);
31963893811SGilad Ben-Yossef }
32063893811SGilad Ben-Yossef 
cc_hash_complete(struct device * dev,void * cc_req,int err)32163893811SGilad Ben-Yossef static void cc_hash_complete(struct device *dev, void *cc_req, int err)
32263893811SGilad Ben-Yossef {
32363893811SGilad Ben-Yossef 	struct ahash_request *req = (struct ahash_request *)cc_req;
324*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
32563893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
326*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
32763893811SGilad Ben-Yossef 	u32 digestsize = crypto_ahash_digestsize(tfm);
32863893811SGilad Ben-Yossef 
32963893811SGilad Ben-Yossef 	dev_dbg(dev, "req=%pK\n", req);
33063893811SGilad Ben-Yossef 
331a108f931SGilad Ben-Yossef 	if (err != -EINPROGRESS) {
332a108f931SGilad Ben-Yossef 		/* Not a BACKLOG notification */
33363893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, req->src, false);
33463893811SGilad Ben-Yossef 		cc_unmap_result(dev, state, digestsize, req->result);
33563893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
336a108f931SGilad Ben-Yossef 	}
337a108f931SGilad Ben-Yossef 
338151ded73SGilad Ben-Yossef 	ahash_request_complete(req, err);
33963893811SGilad Ben-Yossef }
34063893811SGilad Ben-Yossef 
cc_fin_result(struct cc_hw_desc * desc,struct ahash_request * req,int idx)34163893811SGilad Ben-Yossef static int cc_fin_result(struct cc_hw_desc *desc, struct ahash_request *req,
34263893811SGilad Ben-Yossef 			 int idx)
34363893811SGilad Ben-Yossef {
344*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
34563893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
346*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
34763893811SGilad Ben-Yossef 	u32 digestsize = crypto_ahash_digestsize(tfm);
34863893811SGilad Ben-Yossef 
34963893811SGilad Ben-Yossef 	/* Get final MAC result */
35063893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
35118a1dc1fSYael Chemla 	set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode);
35263893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx], state->digest_result_dma_addr, digestsize,
35363893811SGilad Ben-Yossef 		      NS_BIT, 1);
35427b3b22dSGilad Ben-Yossef 	set_queue_last_ind(ctx->drvdata, &desc[idx]);
35563893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_HASH_to_DOUT);
35663893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
35763893811SGilad Ben-Yossef 	set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
35863893811SGilad Ben-Yossef 	cc_set_endianity(ctx->hash_mode, &desc[idx]);
35963893811SGilad Ben-Yossef 	idx++;
36063893811SGilad Ben-Yossef 
36163893811SGilad Ben-Yossef 	return idx;
36263893811SGilad Ben-Yossef }
36363893811SGilad Ben-Yossef 
cc_fin_hmac(struct cc_hw_desc * desc,struct ahash_request * req,int idx)36463893811SGilad Ben-Yossef static int cc_fin_hmac(struct cc_hw_desc *desc, struct ahash_request *req,
36563893811SGilad Ben-Yossef 		       int idx)
36663893811SGilad Ben-Yossef {
367*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
36863893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
369*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
37063893811SGilad Ben-Yossef 	u32 digestsize = crypto_ahash_digestsize(tfm);
37163893811SGilad Ben-Yossef 
37263893811SGilad Ben-Yossef 	/* store the hash digest result in the context */
37363893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
37463893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], ctx->hw_mode);
37563893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx], state->digest_buff_dma_addr, digestsize,
37663893811SGilad Ben-Yossef 		      NS_BIT, 0);
37763893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_HASH_to_DOUT);
37863893811SGilad Ben-Yossef 	cc_set_endianity(ctx->hash_mode, &desc[idx]);
37963893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
38063893811SGilad Ben-Yossef 	idx++;
38163893811SGilad Ben-Yossef 
38263893811SGilad Ben-Yossef 	/* Loading hash opad xor key state */
38363893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
38463893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], ctx->hw_mode);
38563893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI, state->opad_digest_dma_addr,
38663893811SGilad Ben-Yossef 		     ctx->inter_digestsize, NS_BIT);
38763893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_HASH);
38863893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
38963893811SGilad Ben-Yossef 	idx++;
39063893811SGilad Ben-Yossef 
39163893811SGilad Ben-Yossef 	/* Load the hash current length */
39263893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
39363893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], ctx->hw_mode);
39463893811SGilad Ben-Yossef 	set_din_sram(&desc[idx],
39563893811SGilad Ben-Yossef 		     cc_digest_len_addr(ctx->drvdata, ctx->hash_mode),
396f1e52fd0SYael Chemla 		     ctx->hash_len);
39763893811SGilad Ben-Yossef 	set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
39863893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_HASH);
39963893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
40063893811SGilad Ben-Yossef 	idx++;
40163893811SGilad Ben-Yossef 
40263893811SGilad Ben-Yossef 	/* Memory Barrier: wait for IPAD/OPAD axi write to complete */
40363893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
40463893811SGilad Ben-Yossef 	set_din_no_dma(&desc[idx], 0, 0xfffff0);
40563893811SGilad Ben-Yossef 	set_dout_no_dma(&desc[idx], 0, 0, 1);
40663893811SGilad Ben-Yossef 	idx++;
40763893811SGilad Ben-Yossef 
40863893811SGilad Ben-Yossef 	/* Perform HASH update */
40963893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
41063893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
41163893811SGilad Ben-Yossef 		     digestsize, NS_BIT);
41263893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], DIN_HASH);
41363893811SGilad Ben-Yossef 	idx++;
41463893811SGilad Ben-Yossef 
41563893811SGilad Ben-Yossef 	return idx;
41663893811SGilad Ben-Yossef }
41763893811SGilad Ben-Yossef 
cc_hash_digest(struct ahash_request * req)41863893811SGilad Ben-Yossef static int cc_hash_digest(struct ahash_request *req)
41963893811SGilad Ben-Yossef {
420*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
42163893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
422*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
42363893811SGilad Ben-Yossef 	u32 digestsize = crypto_ahash_digestsize(tfm);
42463893811SGilad Ben-Yossef 	struct scatterlist *src = req->src;
42563893811SGilad Ben-Yossef 	unsigned int nbytes = req->nbytes;
42663893811SGilad Ben-Yossef 	u8 *result = req->result;
42763893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
42863893811SGilad Ben-Yossef 	bool is_hmac = ctx->is_hmac;
42963893811SGilad Ben-Yossef 	struct cc_crypto_req cc_req = {};
43063893811SGilad Ben-Yossef 	struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
4311a895f1dSGeert Uytterhoeven 	u32 larval_digest_addr;
43263893811SGilad Ben-Yossef 	int idx = 0;
43363893811SGilad Ben-Yossef 	int rc = 0;
43463893811SGilad Ben-Yossef 	gfp_t flags = cc_gfp_flags(&req->base);
43563893811SGilad Ben-Yossef 
43663893811SGilad Ben-Yossef 	dev_dbg(dev, "===== %s-digest (%d) ====\n", is_hmac ? "hmac" : "hash",
43763893811SGilad Ben-Yossef 		nbytes);
43863893811SGilad Ben-Yossef 
43963893811SGilad Ben-Yossef 	cc_init_req(dev, state, ctx);
44063893811SGilad Ben-Yossef 
44163893811SGilad Ben-Yossef 	if (cc_map_req(dev, state, ctx)) {
44263893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_source() failed\n");
44363893811SGilad Ben-Yossef 		return -ENOMEM;
44463893811SGilad Ben-Yossef 	}
44563893811SGilad Ben-Yossef 
44663893811SGilad Ben-Yossef 	if (cc_map_result(dev, state, digestsize)) {
44763893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_digest() failed\n");
44863893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
44963893811SGilad Ben-Yossef 		return -ENOMEM;
45063893811SGilad Ben-Yossef 	}
45163893811SGilad Ben-Yossef 
45263893811SGilad Ben-Yossef 	if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, 1,
45363893811SGilad Ben-Yossef 				      flags)) {
45463893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_request_final() failed\n");
45563893811SGilad Ben-Yossef 		cc_unmap_result(dev, state, digestsize, result);
45663893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
45763893811SGilad Ben-Yossef 		return -ENOMEM;
45863893811SGilad Ben-Yossef 	}
45963893811SGilad Ben-Yossef 
46063893811SGilad Ben-Yossef 	/* Setup request structure */
46163893811SGilad Ben-Yossef 	cc_req.user_cb = cc_digest_complete;
46263893811SGilad Ben-Yossef 	cc_req.user_arg = req;
46363893811SGilad Ben-Yossef 
46463893811SGilad Ben-Yossef 	/* If HMAC then load hash IPAD xor key, if HASH then load initial
46563893811SGilad Ben-Yossef 	 * digest
46663893811SGilad Ben-Yossef 	 */
46763893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
46818a1dc1fSYael Chemla 	set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode);
46963893811SGilad Ben-Yossef 	if (is_hmac) {
47063893811SGilad Ben-Yossef 		set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
47163893811SGilad Ben-Yossef 			     ctx->inter_digestsize, NS_BIT);
47263893811SGilad Ben-Yossef 	} else {
473e431cc04SGeert Uytterhoeven 		larval_digest_addr = cc_larval_digest_addr(ctx->drvdata,
474e431cc04SGeert Uytterhoeven 							   ctx->hash_mode);
47563893811SGilad Ben-Yossef 		set_din_sram(&desc[idx], larval_digest_addr,
47663893811SGilad Ben-Yossef 			     ctx->inter_digestsize);
47763893811SGilad Ben-Yossef 	}
47863893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_HASH);
47963893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
48063893811SGilad Ben-Yossef 	idx++;
48163893811SGilad Ben-Yossef 
48263893811SGilad Ben-Yossef 	/* Load the hash current length */
48363893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
48418a1dc1fSYael Chemla 	set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode);
48563893811SGilad Ben-Yossef 
48663893811SGilad Ben-Yossef 	if (is_hmac) {
48763893811SGilad Ben-Yossef 		set_din_type(&desc[idx], DMA_DLLI,
48827b3b22dSGilad Ben-Yossef 			     state->digest_bytes_len_dma_addr,
489f1e52fd0SYael Chemla 			     ctx->hash_len, NS_BIT);
49063893811SGilad Ben-Yossef 	} else {
491f1e52fd0SYael Chemla 		set_din_const(&desc[idx], 0, ctx->hash_len);
49263893811SGilad Ben-Yossef 		if (nbytes)
49363893811SGilad Ben-Yossef 			set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
49463893811SGilad Ben-Yossef 		else
49563893811SGilad Ben-Yossef 			set_cipher_do(&desc[idx], DO_PAD);
49663893811SGilad Ben-Yossef 	}
49763893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_HASH);
49863893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
49963893811SGilad Ben-Yossef 	idx++;
50063893811SGilad Ben-Yossef 
50163893811SGilad Ben-Yossef 	cc_set_desc(state, ctx, DIN_HASH, desc, false, &idx);
50263893811SGilad Ben-Yossef 
50363893811SGilad Ben-Yossef 	if (is_hmac) {
50463893811SGilad Ben-Yossef 		/* HW last hash block padding (aka. "DO_PAD") */
50563893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
50663893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], ctx->hw_mode);
50763893811SGilad Ben-Yossef 		set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
508f1e52fd0SYael Chemla 			      ctx->hash_len, NS_BIT, 0);
50963893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], S_HASH_to_DOUT);
51063893811SGilad Ben-Yossef 		set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
51163893811SGilad Ben-Yossef 		set_cipher_do(&desc[idx], DO_PAD);
51263893811SGilad Ben-Yossef 		idx++;
51363893811SGilad Ben-Yossef 
51463893811SGilad Ben-Yossef 		idx = cc_fin_hmac(desc, req, idx);
51563893811SGilad Ben-Yossef 	}
51663893811SGilad Ben-Yossef 
51763893811SGilad Ben-Yossef 	idx = cc_fin_result(desc, req, idx);
51863893811SGilad Ben-Yossef 
51963893811SGilad Ben-Yossef 	rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
52063893811SGilad Ben-Yossef 	if (rc != -EINPROGRESS && rc != -EBUSY) {
52163893811SGilad Ben-Yossef 		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
52263893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, src, true);
52363893811SGilad Ben-Yossef 		cc_unmap_result(dev, state, digestsize, result);
52463893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
52563893811SGilad Ben-Yossef 	}
52663893811SGilad Ben-Yossef 	return rc;
52763893811SGilad Ben-Yossef }
52863893811SGilad Ben-Yossef 
cc_restore_hash(struct cc_hw_desc * desc,struct cc_hash_ctx * ctx,struct ahash_req_ctx * state,unsigned int idx)52963893811SGilad Ben-Yossef static int cc_restore_hash(struct cc_hw_desc *desc, struct cc_hash_ctx *ctx,
53063893811SGilad Ben-Yossef 			   struct ahash_req_ctx *state, unsigned int idx)
53163893811SGilad Ben-Yossef {
53263893811SGilad Ben-Yossef 	/* Restore hash digest */
53363893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
53418a1dc1fSYael Chemla 	set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode);
53563893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
53663893811SGilad Ben-Yossef 		     ctx->inter_digestsize, NS_BIT);
53763893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_HASH);
53863893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
53963893811SGilad Ben-Yossef 	idx++;
54063893811SGilad Ben-Yossef 
54163893811SGilad Ben-Yossef 	/* Restore hash current length */
54263893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
54318a1dc1fSYael Chemla 	set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode);
54463893811SGilad Ben-Yossef 	set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
54563893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI, state->digest_bytes_len_dma_addr,
546f1e52fd0SYael Chemla 		     ctx->hash_len, NS_BIT);
54763893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_HASH);
54863893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
54963893811SGilad Ben-Yossef 	idx++;
55063893811SGilad Ben-Yossef 
55163893811SGilad Ben-Yossef 	cc_set_desc(state, ctx, DIN_HASH, desc, false, &idx);
55263893811SGilad Ben-Yossef 
55363893811SGilad Ben-Yossef 	return idx;
55463893811SGilad Ben-Yossef }
55563893811SGilad Ben-Yossef 
cc_hash_update(struct ahash_request * req)55663893811SGilad Ben-Yossef static int cc_hash_update(struct ahash_request *req)
55763893811SGilad Ben-Yossef {
558*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
55963893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
560*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
56163893811SGilad Ben-Yossef 	unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base);
56263893811SGilad Ben-Yossef 	struct scatterlist *src = req->src;
56363893811SGilad Ben-Yossef 	unsigned int nbytes = req->nbytes;
56463893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
56563893811SGilad Ben-Yossef 	struct cc_crypto_req cc_req = {};
56663893811SGilad Ben-Yossef 	struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
56763893811SGilad Ben-Yossef 	u32 idx = 0;
56863893811SGilad Ben-Yossef 	int rc;
56963893811SGilad Ben-Yossef 	gfp_t flags = cc_gfp_flags(&req->base);
57063893811SGilad Ben-Yossef 
57163893811SGilad Ben-Yossef 	dev_dbg(dev, "===== %s-update (%d) ====\n", ctx->is_hmac ?
57263893811SGilad Ben-Yossef 		"hmac" : "hash", nbytes);
57363893811SGilad Ben-Yossef 
57463893811SGilad Ben-Yossef 	if (nbytes == 0) {
57563893811SGilad Ben-Yossef 		/* no real updates required */
57663893811SGilad Ben-Yossef 		return 0;
57763893811SGilad Ben-Yossef 	}
57863893811SGilad Ben-Yossef 
57963893811SGilad Ben-Yossef 	rc = cc_map_hash_request_update(ctx->drvdata, state, src, nbytes,
58063893811SGilad Ben-Yossef 					block_size, flags);
58163893811SGilad Ben-Yossef 	if (rc) {
58263893811SGilad Ben-Yossef 		if (rc == 1) {
58363893811SGilad Ben-Yossef 			dev_dbg(dev, " data size not require HW update %x\n",
58463893811SGilad Ben-Yossef 				nbytes);
58563893811SGilad Ben-Yossef 			/* No hardware updates are required */
58663893811SGilad Ben-Yossef 			return 0;
58763893811SGilad Ben-Yossef 		}
58863893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_request_update() failed\n");
58963893811SGilad Ben-Yossef 		return -ENOMEM;
59063893811SGilad Ben-Yossef 	}
59163893811SGilad Ben-Yossef 
59263893811SGilad Ben-Yossef 	if (cc_map_req(dev, state, ctx)) {
59363893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_source() failed\n");
59463893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, src, true);
59563893811SGilad Ben-Yossef 		return -EINVAL;
59663893811SGilad Ben-Yossef 	}
59763893811SGilad Ben-Yossef 
59863893811SGilad Ben-Yossef 	/* Setup request structure */
59963893811SGilad Ben-Yossef 	cc_req.user_cb = cc_update_complete;
60063893811SGilad Ben-Yossef 	cc_req.user_arg = req;
60163893811SGilad Ben-Yossef 
60263893811SGilad Ben-Yossef 	idx = cc_restore_hash(desc, ctx, state, idx);
60363893811SGilad Ben-Yossef 
60463893811SGilad Ben-Yossef 	/* store the hash digest result in context */
60563893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
60618a1dc1fSYael Chemla 	set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode);
60763893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
60863893811SGilad Ben-Yossef 		      ctx->inter_digestsize, NS_BIT, 0);
60963893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_HASH_to_DOUT);
61063893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
61163893811SGilad Ben-Yossef 	idx++;
61263893811SGilad Ben-Yossef 
61363893811SGilad Ben-Yossef 	/* store current hash length in context */
61463893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
61518a1dc1fSYael Chemla 	set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode);
61663893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr,
617f1e52fd0SYael Chemla 		      ctx->hash_len, NS_BIT, 1);
61827b3b22dSGilad Ben-Yossef 	set_queue_last_ind(ctx->drvdata, &desc[idx]);
61963893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_HASH_to_DOUT);
62063893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
62163893811SGilad Ben-Yossef 	idx++;
62263893811SGilad Ben-Yossef 
62363893811SGilad Ben-Yossef 	rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
62463893811SGilad Ben-Yossef 	if (rc != -EINPROGRESS && rc != -EBUSY) {
62563893811SGilad Ben-Yossef 		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
62663893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, src, true);
62763893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
62863893811SGilad Ben-Yossef 	}
62963893811SGilad Ben-Yossef 	return rc;
63063893811SGilad Ben-Yossef }
63163893811SGilad Ben-Yossef 
cc_do_finup(struct ahash_request * req,bool update)63226497e72SHadar Gat static int cc_do_finup(struct ahash_request *req, bool update)
63363893811SGilad Ben-Yossef {
634*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
63563893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
636*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
63763893811SGilad Ben-Yossef 	u32 digestsize = crypto_ahash_digestsize(tfm);
63863893811SGilad Ben-Yossef 	struct scatterlist *src = req->src;
63963893811SGilad Ben-Yossef 	unsigned int nbytes = req->nbytes;
64063893811SGilad Ben-Yossef 	u8 *result = req->result;
64163893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
64263893811SGilad Ben-Yossef 	bool is_hmac = ctx->is_hmac;
64363893811SGilad Ben-Yossef 	struct cc_crypto_req cc_req = {};
64463893811SGilad Ben-Yossef 	struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
64563893811SGilad Ben-Yossef 	unsigned int idx = 0;
64663893811SGilad Ben-Yossef 	int rc;
64763893811SGilad Ben-Yossef 	gfp_t flags = cc_gfp_flags(&req->base);
64863893811SGilad Ben-Yossef 
64926497e72SHadar Gat 	dev_dbg(dev, "===== %s-%s (%d) ====\n", is_hmac ? "hmac" : "hash",
65026497e72SHadar Gat 		update ? "finup" : "final", nbytes);
65163893811SGilad Ben-Yossef 
65263893811SGilad Ben-Yossef 	if (cc_map_req(dev, state, ctx)) {
65363893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_source() failed\n");
65463893811SGilad Ben-Yossef 		return -EINVAL;
65563893811SGilad Ben-Yossef 	}
65663893811SGilad Ben-Yossef 
65726497e72SHadar Gat 	if (cc_map_hash_request_final(ctx->drvdata, state, src, nbytes, update,
65863893811SGilad Ben-Yossef 				      flags)) {
65963893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_request_final() failed\n");
66063893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
66163893811SGilad Ben-Yossef 		return -ENOMEM;
66263893811SGilad Ben-Yossef 	}
66363893811SGilad Ben-Yossef 	if (cc_map_result(dev, state, digestsize)) {
66463893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_digest() failed\n");
66563893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, src, true);
66663893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
66763893811SGilad Ben-Yossef 		return -ENOMEM;
66863893811SGilad Ben-Yossef 	}
66963893811SGilad Ben-Yossef 
67063893811SGilad Ben-Yossef 	/* Setup request structure */
67163893811SGilad Ben-Yossef 	cc_req.user_cb = cc_hash_complete;
67263893811SGilad Ben-Yossef 	cc_req.user_arg = req;
67363893811SGilad Ben-Yossef 
67463893811SGilad Ben-Yossef 	idx = cc_restore_hash(desc, ctx, state, idx);
67563893811SGilad Ben-Yossef 
67626497e72SHadar Gat 	/* Pad the hash */
67763893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
67863893811SGilad Ben-Yossef 	set_cipher_do(&desc[idx], DO_PAD);
67918a1dc1fSYael Chemla 	set_hash_cipher_mode(&desc[idx], ctx->hw_mode, ctx->hash_mode);
68063893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx], state->digest_bytes_len_dma_addr,
681f1e52fd0SYael Chemla 		      ctx->hash_len, NS_BIT, 0);
68263893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_WRITE_STATE1);
68363893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_HASH_to_DOUT);
68463893811SGilad Ben-Yossef 	idx++;
68563893811SGilad Ben-Yossef 
68663893811SGilad Ben-Yossef 	if (is_hmac)
68763893811SGilad Ben-Yossef 		idx = cc_fin_hmac(desc, req, idx);
68863893811SGilad Ben-Yossef 
68963893811SGilad Ben-Yossef 	idx = cc_fin_result(desc, req, idx);
69063893811SGilad Ben-Yossef 
69163893811SGilad Ben-Yossef 	rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
69263893811SGilad Ben-Yossef 	if (rc != -EINPROGRESS && rc != -EBUSY) {
69363893811SGilad Ben-Yossef 		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
69463893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, src, true);
69563893811SGilad Ben-Yossef 		cc_unmap_result(dev, state, digestsize, result);
69663893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
69763893811SGilad Ben-Yossef 	}
69863893811SGilad Ben-Yossef 	return rc;
69963893811SGilad Ben-Yossef }
70063893811SGilad Ben-Yossef 
cc_hash_finup(struct ahash_request * req)70126497e72SHadar Gat static int cc_hash_finup(struct ahash_request *req)
70226497e72SHadar Gat {
70326497e72SHadar Gat 	return cc_do_finup(req, true);
70426497e72SHadar Gat }
70526497e72SHadar Gat 
70626497e72SHadar Gat 
cc_hash_final(struct ahash_request * req)70726497e72SHadar Gat static int cc_hash_final(struct ahash_request *req)
70826497e72SHadar Gat {
70926497e72SHadar Gat 	return cc_do_finup(req, false);
71026497e72SHadar Gat }
71126497e72SHadar Gat 
cc_hash_init(struct ahash_request * req)71263893811SGilad Ben-Yossef static int cc_hash_init(struct ahash_request *req)
71363893811SGilad Ben-Yossef {
714*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
71563893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
716*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
71763893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
71863893811SGilad Ben-Yossef 
71963893811SGilad Ben-Yossef 	dev_dbg(dev, "===== init (%d) ====\n", req->nbytes);
72063893811SGilad Ben-Yossef 
72163893811SGilad Ben-Yossef 	cc_init_req(dev, state, ctx);
72263893811SGilad Ben-Yossef 
72363893811SGilad Ben-Yossef 	return 0;
72463893811SGilad Ben-Yossef }
72563893811SGilad Ben-Yossef 
cc_hash_setkey(struct crypto_ahash * ahash,const u8 * key,unsigned int keylen)72663893811SGilad Ben-Yossef static int cc_hash_setkey(struct crypto_ahash *ahash, const u8 *key,
72763893811SGilad Ben-Yossef 			  unsigned int keylen)
72863893811SGilad Ben-Yossef {
72963893811SGilad Ben-Yossef 	unsigned int hmac_pad_const[2] = { HMAC_IPAD_CONST, HMAC_OPAD_CONST };
73063893811SGilad Ben-Yossef 	struct cc_crypto_req cc_req = {};
73163893811SGilad Ben-Yossef 	struct cc_hash_ctx *ctx = NULL;
73263893811SGilad Ben-Yossef 	int blocksize = 0;
73363893811SGilad Ben-Yossef 	int digestsize = 0;
73463893811SGilad Ben-Yossef 	int i, idx = 0, rc = 0;
73563893811SGilad Ben-Yossef 	struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
7361a895f1dSGeert Uytterhoeven 	u32 larval_addr;
73763893811SGilad Ben-Yossef 	struct device *dev;
73863893811SGilad Ben-Yossef 
739*07547fa7SHerbert Xu 	ctx = crypto_ahash_ctx_dma(ahash);
74063893811SGilad Ben-Yossef 	dev = drvdata_to_dev(ctx->drvdata);
74163893811SGilad Ben-Yossef 	dev_dbg(dev, "start keylen: %d", keylen);
74263893811SGilad Ben-Yossef 
74363893811SGilad Ben-Yossef 	blocksize = crypto_tfm_alg_blocksize(&ahash->base);
74463893811SGilad Ben-Yossef 	digestsize = crypto_ahash_digestsize(ahash);
74563893811SGilad Ben-Yossef 
74663893811SGilad Ben-Yossef 	larval_addr = cc_larval_digest_addr(ctx->drvdata, ctx->hash_mode);
74763893811SGilad Ben-Yossef 
74863893811SGilad Ben-Yossef 	/* The keylen value distinguishes HASH in case keylen is ZERO bytes,
74963893811SGilad Ben-Yossef 	 * any NON-ZERO value utilizes HMAC flow
75063893811SGilad Ben-Yossef 	 */
75163893811SGilad Ben-Yossef 	ctx->key_params.keylen = keylen;
75263893811SGilad Ben-Yossef 	ctx->key_params.key_dma_addr = 0;
75363893811SGilad Ben-Yossef 	ctx->is_hmac = true;
754874e1637SGilad Ben-Yossef 	ctx->key_params.key = NULL;
75563893811SGilad Ben-Yossef 
75663893811SGilad Ben-Yossef 	if (keylen) {
757874e1637SGilad Ben-Yossef 		ctx->key_params.key = kmemdup(key, keylen, GFP_KERNEL);
758874e1637SGilad Ben-Yossef 		if (!ctx->key_params.key)
759874e1637SGilad Ben-Yossef 			return -ENOMEM;
760874e1637SGilad Ben-Yossef 
76163893811SGilad Ben-Yossef 		ctx->key_params.key_dma_addr =
762f4274eecSGeert Uytterhoeven 			dma_map_single(dev, ctx->key_params.key, keylen,
763874e1637SGilad Ben-Yossef 				       DMA_TO_DEVICE);
76463893811SGilad Ben-Yossef 		if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) {
76563893811SGilad Ben-Yossef 			dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
766874e1637SGilad Ben-Yossef 				ctx->key_params.key, keylen);
767453431a5SWaiman Long 			kfree_sensitive(ctx->key_params.key);
76863893811SGilad Ben-Yossef 			return -ENOMEM;
76963893811SGilad Ben-Yossef 		}
77063893811SGilad Ben-Yossef 		dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n",
77163893811SGilad Ben-Yossef 			&ctx->key_params.key_dma_addr, ctx->key_params.keylen);
77263893811SGilad Ben-Yossef 
77363893811SGilad Ben-Yossef 		if (keylen > blocksize) {
77463893811SGilad Ben-Yossef 			/* Load hash initial state */
77563893811SGilad Ben-Yossef 			hw_desc_init(&desc[idx]);
77663893811SGilad Ben-Yossef 			set_cipher_mode(&desc[idx], ctx->hw_mode);
77763893811SGilad Ben-Yossef 			set_din_sram(&desc[idx], larval_addr,
77863893811SGilad Ben-Yossef 				     ctx->inter_digestsize);
77963893811SGilad Ben-Yossef 			set_flow_mode(&desc[idx], S_DIN_to_HASH);
78063893811SGilad Ben-Yossef 			set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
78163893811SGilad Ben-Yossef 			idx++;
78263893811SGilad Ben-Yossef 
78363893811SGilad Ben-Yossef 			/* Load the hash current length*/
78463893811SGilad Ben-Yossef 			hw_desc_init(&desc[idx]);
78563893811SGilad Ben-Yossef 			set_cipher_mode(&desc[idx], ctx->hw_mode);
786f1e52fd0SYael Chemla 			set_din_const(&desc[idx], 0, ctx->hash_len);
78763893811SGilad Ben-Yossef 			set_cipher_config1(&desc[idx], HASH_PADDING_ENABLED);
78863893811SGilad Ben-Yossef 			set_flow_mode(&desc[idx], S_DIN_to_HASH);
78963893811SGilad Ben-Yossef 			set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
79063893811SGilad Ben-Yossef 			idx++;
79163893811SGilad Ben-Yossef 
79263893811SGilad Ben-Yossef 			hw_desc_init(&desc[idx]);
79363893811SGilad Ben-Yossef 			set_din_type(&desc[idx], DMA_DLLI,
79463893811SGilad Ben-Yossef 				     ctx->key_params.key_dma_addr, keylen,
79563893811SGilad Ben-Yossef 				     NS_BIT);
79663893811SGilad Ben-Yossef 			set_flow_mode(&desc[idx], DIN_HASH);
79763893811SGilad Ben-Yossef 			idx++;
79863893811SGilad Ben-Yossef 
79963893811SGilad Ben-Yossef 			/* Get hashed key */
80063893811SGilad Ben-Yossef 			hw_desc_init(&desc[idx]);
80163893811SGilad Ben-Yossef 			set_cipher_mode(&desc[idx], ctx->hw_mode);
80263893811SGilad Ben-Yossef 			set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
80363893811SGilad Ben-Yossef 				      digestsize, NS_BIT, 0);
80463893811SGilad Ben-Yossef 			set_flow_mode(&desc[idx], S_HASH_to_DOUT);
80563893811SGilad Ben-Yossef 			set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
80663893811SGilad Ben-Yossef 			set_cipher_config1(&desc[idx], HASH_PADDING_DISABLED);
80763893811SGilad Ben-Yossef 			cc_set_endianity(ctx->hash_mode, &desc[idx]);
80863893811SGilad Ben-Yossef 			idx++;
80963893811SGilad Ben-Yossef 
81063893811SGilad Ben-Yossef 			hw_desc_init(&desc[idx]);
81163893811SGilad Ben-Yossef 			set_din_const(&desc[idx], 0, (blocksize - digestsize));
81263893811SGilad Ben-Yossef 			set_flow_mode(&desc[idx], BYPASS);
81363893811SGilad Ben-Yossef 			set_dout_dlli(&desc[idx],
81463893811SGilad Ben-Yossef 				      (ctx->opad_tmp_keys_dma_addr +
81563893811SGilad Ben-Yossef 				       digestsize),
81663893811SGilad Ben-Yossef 				      (blocksize - digestsize), NS_BIT, 0);
81763893811SGilad Ben-Yossef 			idx++;
81863893811SGilad Ben-Yossef 		} else {
81963893811SGilad Ben-Yossef 			hw_desc_init(&desc[idx]);
82063893811SGilad Ben-Yossef 			set_din_type(&desc[idx], DMA_DLLI,
82163893811SGilad Ben-Yossef 				     ctx->key_params.key_dma_addr, keylen,
82263893811SGilad Ben-Yossef 				     NS_BIT);
82363893811SGilad Ben-Yossef 			set_flow_mode(&desc[idx], BYPASS);
82463893811SGilad Ben-Yossef 			set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
82563893811SGilad Ben-Yossef 				      keylen, NS_BIT, 0);
82663893811SGilad Ben-Yossef 			idx++;
82763893811SGilad Ben-Yossef 
82863893811SGilad Ben-Yossef 			if ((blocksize - keylen)) {
82963893811SGilad Ben-Yossef 				hw_desc_init(&desc[idx]);
83063893811SGilad Ben-Yossef 				set_din_const(&desc[idx], 0,
83163893811SGilad Ben-Yossef 					      (blocksize - keylen));
83263893811SGilad Ben-Yossef 				set_flow_mode(&desc[idx], BYPASS);
83363893811SGilad Ben-Yossef 				set_dout_dlli(&desc[idx],
83463893811SGilad Ben-Yossef 					      (ctx->opad_tmp_keys_dma_addr +
83563893811SGilad Ben-Yossef 					       keylen), (blocksize - keylen),
83663893811SGilad Ben-Yossef 					      NS_BIT, 0);
83763893811SGilad Ben-Yossef 				idx++;
83863893811SGilad Ben-Yossef 			}
83963893811SGilad Ben-Yossef 		}
84063893811SGilad Ben-Yossef 	} else {
84163893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
84263893811SGilad Ben-Yossef 		set_din_const(&desc[idx], 0, blocksize);
84363893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], BYPASS);
84463893811SGilad Ben-Yossef 		set_dout_dlli(&desc[idx], (ctx->opad_tmp_keys_dma_addr),
84563893811SGilad Ben-Yossef 			      blocksize, NS_BIT, 0);
84663893811SGilad Ben-Yossef 		idx++;
84763893811SGilad Ben-Yossef 	}
84863893811SGilad Ben-Yossef 
84963893811SGilad Ben-Yossef 	rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx);
85063893811SGilad Ben-Yossef 	if (rc) {
85163893811SGilad Ben-Yossef 		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
85263893811SGilad Ben-Yossef 		goto out;
85363893811SGilad Ben-Yossef 	}
85463893811SGilad Ben-Yossef 
85563893811SGilad Ben-Yossef 	/* calc derived HMAC key */
85663893811SGilad Ben-Yossef 	for (idx = 0, i = 0; i < 2; i++) {
85763893811SGilad Ben-Yossef 		/* Load hash initial state */
85863893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
85963893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], ctx->hw_mode);
86063893811SGilad Ben-Yossef 		set_din_sram(&desc[idx], larval_addr, ctx->inter_digestsize);
86163893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], S_DIN_to_HASH);
86263893811SGilad Ben-Yossef 		set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
86363893811SGilad Ben-Yossef 		idx++;
86463893811SGilad Ben-Yossef 
86563893811SGilad Ben-Yossef 		/* Load the hash current length*/
86663893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
86763893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], ctx->hw_mode);
868f1e52fd0SYael Chemla 		set_din_const(&desc[idx], 0, ctx->hash_len);
86963893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], S_DIN_to_HASH);
87063893811SGilad Ben-Yossef 		set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
87163893811SGilad Ben-Yossef 		idx++;
87263893811SGilad Ben-Yossef 
87363893811SGilad Ben-Yossef 		/* Prepare ipad key */
87463893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
87563893811SGilad Ben-Yossef 		set_xor_val(&desc[idx], hmac_pad_const[i]);
87663893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], ctx->hw_mode);
87763893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], S_DIN_to_HASH);
87863893811SGilad Ben-Yossef 		set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
87963893811SGilad Ben-Yossef 		idx++;
88063893811SGilad Ben-Yossef 
88163893811SGilad Ben-Yossef 		/* Perform HASH update */
88263893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
88363893811SGilad Ben-Yossef 		set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr,
88463893811SGilad Ben-Yossef 			     blocksize, NS_BIT);
88563893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], ctx->hw_mode);
88663893811SGilad Ben-Yossef 		set_xor_active(&desc[idx]);
88763893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], DIN_HASH);
88863893811SGilad Ben-Yossef 		idx++;
88963893811SGilad Ben-Yossef 
89063893811SGilad Ben-Yossef 		/* Get the IPAD/OPAD xor key (Note, IPAD is the initial digest
89163893811SGilad Ben-Yossef 		 * of the first HASH "update" state)
89263893811SGilad Ben-Yossef 		 */
89363893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
89463893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], ctx->hw_mode);
89563893811SGilad Ben-Yossef 		if (i > 0) /* Not first iteration */
89663893811SGilad Ben-Yossef 			set_dout_dlli(&desc[idx], ctx->opad_tmp_keys_dma_addr,
89763893811SGilad Ben-Yossef 				      ctx->inter_digestsize, NS_BIT, 0);
89863893811SGilad Ben-Yossef 		else /* First iteration */
89963893811SGilad Ben-Yossef 			set_dout_dlli(&desc[idx], ctx->digest_buff_dma_addr,
90063893811SGilad Ben-Yossef 				      ctx->inter_digestsize, NS_BIT, 0);
90163893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], S_HASH_to_DOUT);
90263893811SGilad Ben-Yossef 		set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
90363893811SGilad Ben-Yossef 		idx++;
90463893811SGilad Ben-Yossef 	}
90563893811SGilad Ben-Yossef 
90663893811SGilad Ben-Yossef 	rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx);
90763893811SGilad Ben-Yossef 
90863893811SGilad Ben-Yossef out:
90963893811SGilad Ben-Yossef 	if (ctx->key_params.key_dma_addr) {
91063893811SGilad Ben-Yossef 		dma_unmap_single(dev, ctx->key_params.key_dma_addr,
91163893811SGilad Ben-Yossef 				 ctx->key_params.keylen, DMA_TO_DEVICE);
91263893811SGilad Ben-Yossef 		dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n",
91363893811SGilad Ben-Yossef 			&ctx->key_params.key_dma_addr, ctx->key_params.keylen);
91463893811SGilad Ben-Yossef 	}
915874e1637SGilad Ben-Yossef 
916453431a5SWaiman Long 	kfree_sensitive(ctx->key_params.key);
917874e1637SGilad Ben-Yossef 
91863893811SGilad Ben-Yossef 	return rc;
91963893811SGilad Ben-Yossef }
92063893811SGilad Ben-Yossef 
cc_xcbc_setkey(struct crypto_ahash * ahash,const u8 * key,unsigned int keylen)92163893811SGilad Ben-Yossef static int cc_xcbc_setkey(struct crypto_ahash *ahash,
92263893811SGilad Ben-Yossef 			  const u8 *key, unsigned int keylen)
92363893811SGilad Ben-Yossef {
92463893811SGilad Ben-Yossef 	struct cc_crypto_req cc_req = {};
925*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
92663893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
92763893811SGilad Ben-Yossef 	int rc = 0;
92863893811SGilad Ben-Yossef 	unsigned int idx = 0;
92963893811SGilad Ben-Yossef 	struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
93063893811SGilad Ben-Yossef 
93163893811SGilad Ben-Yossef 	dev_dbg(dev, "===== setkey (%d) ====\n", keylen);
93263893811SGilad Ben-Yossef 
93363893811SGilad Ben-Yossef 	switch (keylen) {
93463893811SGilad Ben-Yossef 	case AES_KEYSIZE_128:
93563893811SGilad Ben-Yossef 	case AES_KEYSIZE_192:
93663893811SGilad Ben-Yossef 	case AES_KEYSIZE_256:
93763893811SGilad Ben-Yossef 		break;
93863893811SGilad Ben-Yossef 	default:
93963893811SGilad Ben-Yossef 		return -EINVAL;
94063893811SGilad Ben-Yossef 	}
94163893811SGilad Ben-Yossef 
94263893811SGilad Ben-Yossef 	ctx->key_params.keylen = keylen;
94363893811SGilad Ben-Yossef 
944874e1637SGilad Ben-Yossef 	ctx->key_params.key = kmemdup(key, keylen, GFP_KERNEL);
945874e1637SGilad Ben-Yossef 	if (!ctx->key_params.key)
946874e1637SGilad Ben-Yossef 		return -ENOMEM;
947874e1637SGilad Ben-Yossef 
94863893811SGilad Ben-Yossef 	ctx->key_params.key_dma_addr =
949874e1637SGilad Ben-Yossef 		dma_map_single(dev, ctx->key_params.key, keylen, DMA_TO_DEVICE);
95063893811SGilad Ben-Yossef 	if (dma_mapping_error(dev, ctx->key_params.key_dma_addr)) {
95163893811SGilad Ben-Yossef 		dev_err(dev, "Mapping key va=0x%p len=%u for DMA failed\n",
95263893811SGilad Ben-Yossef 			key, keylen);
953453431a5SWaiman Long 		kfree_sensitive(ctx->key_params.key);
95463893811SGilad Ben-Yossef 		return -ENOMEM;
95563893811SGilad Ben-Yossef 	}
95663893811SGilad Ben-Yossef 	dev_dbg(dev, "mapping key-buffer: key_dma_addr=%pad keylen=%u\n",
95763893811SGilad Ben-Yossef 		&ctx->key_params.key_dma_addr, ctx->key_params.keylen);
95863893811SGilad Ben-Yossef 
95963893811SGilad Ben-Yossef 	ctx->is_hmac = true;
96063893811SGilad Ben-Yossef 	/* 1. Load the AES key */
96163893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
96263893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI, ctx->key_params.key_dma_addr,
96363893811SGilad Ben-Yossef 		     keylen, NS_BIT);
96463893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
96563893811SGilad Ben-Yossef 	set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_ENCRYPT);
96663893811SGilad Ben-Yossef 	set_key_size_aes(&desc[idx], keylen);
96763893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_AES);
96863893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
96963893811SGilad Ben-Yossef 	idx++;
97063893811SGilad Ben-Yossef 
97163893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
97263893811SGilad Ben-Yossef 	set_din_const(&desc[idx], 0x01010101, CC_AES_128_BIT_KEY_SIZE);
97363893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], DIN_AES_DOUT);
97463893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx],
97563893811SGilad Ben-Yossef 		      (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K1_OFFSET),
97663893811SGilad Ben-Yossef 		      CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
97763893811SGilad Ben-Yossef 	idx++;
97863893811SGilad Ben-Yossef 
97963893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
98063893811SGilad Ben-Yossef 	set_din_const(&desc[idx], 0x02020202, CC_AES_128_BIT_KEY_SIZE);
98163893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], DIN_AES_DOUT);
98263893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx],
98363893811SGilad Ben-Yossef 		      (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K2_OFFSET),
98463893811SGilad Ben-Yossef 		      CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
98563893811SGilad Ben-Yossef 	idx++;
98663893811SGilad Ben-Yossef 
98763893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
98863893811SGilad Ben-Yossef 	set_din_const(&desc[idx], 0x03030303, CC_AES_128_BIT_KEY_SIZE);
98963893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], DIN_AES_DOUT);
99063893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx],
99163893811SGilad Ben-Yossef 		      (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K3_OFFSET),
99263893811SGilad Ben-Yossef 		      CC_AES_128_BIT_KEY_SIZE, NS_BIT, 0);
99363893811SGilad Ben-Yossef 	idx++;
99463893811SGilad Ben-Yossef 
99563893811SGilad Ben-Yossef 	rc = cc_send_sync_request(ctx->drvdata, &cc_req, desc, idx);
99663893811SGilad Ben-Yossef 
99763893811SGilad Ben-Yossef 	dma_unmap_single(dev, ctx->key_params.key_dma_addr,
99863893811SGilad Ben-Yossef 			 ctx->key_params.keylen, DMA_TO_DEVICE);
99963893811SGilad Ben-Yossef 	dev_dbg(dev, "Unmapped key-buffer: key_dma_addr=%pad keylen=%u\n",
100063893811SGilad Ben-Yossef 		&ctx->key_params.key_dma_addr, ctx->key_params.keylen);
100163893811SGilad Ben-Yossef 
1002453431a5SWaiman Long 	kfree_sensitive(ctx->key_params.key);
1003874e1637SGilad Ben-Yossef 
100463893811SGilad Ben-Yossef 	return rc;
100563893811SGilad Ben-Yossef }
100663893811SGilad Ben-Yossef 
cc_cmac_setkey(struct crypto_ahash * ahash,const u8 * key,unsigned int keylen)100763893811SGilad Ben-Yossef static int cc_cmac_setkey(struct crypto_ahash *ahash,
100863893811SGilad Ben-Yossef 			  const u8 *key, unsigned int keylen)
100963893811SGilad Ben-Yossef {
1010*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
101163893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
101263893811SGilad Ben-Yossef 
101363893811SGilad Ben-Yossef 	dev_dbg(dev, "===== setkey (%d) ====\n", keylen);
101463893811SGilad Ben-Yossef 
101563893811SGilad Ben-Yossef 	ctx->is_hmac = true;
101663893811SGilad Ben-Yossef 
101763893811SGilad Ben-Yossef 	switch (keylen) {
101863893811SGilad Ben-Yossef 	case AES_KEYSIZE_128:
101963893811SGilad Ben-Yossef 	case AES_KEYSIZE_192:
102063893811SGilad Ben-Yossef 	case AES_KEYSIZE_256:
102163893811SGilad Ben-Yossef 		break;
102263893811SGilad Ben-Yossef 	default:
102363893811SGilad Ben-Yossef 		return -EINVAL;
102463893811SGilad Ben-Yossef 	}
102563893811SGilad Ben-Yossef 
102663893811SGilad Ben-Yossef 	ctx->key_params.keylen = keylen;
102763893811SGilad Ben-Yossef 
102863893811SGilad Ben-Yossef 	/* STAT_PHASE_1: Copy key to ctx */
102963893811SGilad Ben-Yossef 
103063893811SGilad Ben-Yossef 	dma_sync_single_for_cpu(dev, ctx->opad_tmp_keys_dma_addr,
103163893811SGilad Ben-Yossef 				keylen, DMA_TO_DEVICE);
103263893811SGilad Ben-Yossef 
103363893811SGilad Ben-Yossef 	memcpy(ctx->opad_tmp_keys_buff, key, keylen);
103463893811SGilad Ben-Yossef 	if (keylen == 24) {
103563893811SGilad Ben-Yossef 		memset(ctx->opad_tmp_keys_buff + 24, 0,
103663893811SGilad Ben-Yossef 		       CC_AES_KEY_SIZE_MAX - 24);
103763893811SGilad Ben-Yossef 	}
103863893811SGilad Ben-Yossef 
103963893811SGilad Ben-Yossef 	dma_sync_single_for_device(dev, ctx->opad_tmp_keys_dma_addr,
104063893811SGilad Ben-Yossef 				   keylen, DMA_TO_DEVICE);
104163893811SGilad Ben-Yossef 
104263893811SGilad Ben-Yossef 	ctx->key_params.keylen = keylen;
104363893811SGilad Ben-Yossef 
104463893811SGilad Ben-Yossef 	return 0;
104563893811SGilad Ben-Yossef }
104663893811SGilad Ben-Yossef 
cc_free_ctx(struct cc_hash_ctx * ctx)104763893811SGilad Ben-Yossef static void cc_free_ctx(struct cc_hash_ctx *ctx)
104863893811SGilad Ben-Yossef {
104963893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
105063893811SGilad Ben-Yossef 
105163893811SGilad Ben-Yossef 	if (ctx->digest_buff_dma_addr) {
105263893811SGilad Ben-Yossef 		dma_unmap_single(dev, ctx->digest_buff_dma_addr,
105363893811SGilad Ben-Yossef 				 sizeof(ctx->digest_buff), DMA_BIDIRECTIONAL);
105463893811SGilad Ben-Yossef 		dev_dbg(dev, "Unmapped digest-buffer: digest_buff_dma_addr=%pad\n",
105563893811SGilad Ben-Yossef 			&ctx->digest_buff_dma_addr);
105663893811SGilad Ben-Yossef 		ctx->digest_buff_dma_addr = 0;
105763893811SGilad Ben-Yossef 	}
105863893811SGilad Ben-Yossef 	if (ctx->opad_tmp_keys_dma_addr) {
105963893811SGilad Ben-Yossef 		dma_unmap_single(dev, ctx->opad_tmp_keys_dma_addr,
106063893811SGilad Ben-Yossef 				 sizeof(ctx->opad_tmp_keys_buff),
106163893811SGilad Ben-Yossef 				 DMA_BIDIRECTIONAL);
106263893811SGilad Ben-Yossef 		dev_dbg(dev, "Unmapped opad-digest: opad_tmp_keys_dma_addr=%pad\n",
106363893811SGilad Ben-Yossef 			&ctx->opad_tmp_keys_dma_addr);
106463893811SGilad Ben-Yossef 		ctx->opad_tmp_keys_dma_addr = 0;
106563893811SGilad Ben-Yossef 	}
106663893811SGilad Ben-Yossef 
106763893811SGilad Ben-Yossef 	ctx->key_params.keylen = 0;
106863893811SGilad Ben-Yossef }
106963893811SGilad Ben-Yossef 
cc_alloc_ctx(struct cc_hash_ctx * ctx)107063893811SGilad Ben-Yossef static int cc_alloc_ctx(struct cc_hash_ctx *ctx)
107163893811SGilad Ben-Yossef {
107263893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
107363893811SGilad Ben-Yossef 
107463893811SGilad Ben-Yossef 	ctx->key_params.keylen = 0;
107563893811SGilad Ben-Yossef 
107663893811SGilad Ben-Yossef 	ctx->digest_buff_dma_addr =
1077f4274eecSGeert Uytterhoeven 		dma_map_single(dev, ctx->digest_buff, sizeof(ctx->digest_buff),
1078f4274eecSGeert Uytterhoeven 			       DMA_BIDIRECTIONAL);
107963893811SGilad Ben-Yossef 	if (dma_mapping_error(dev, ctx->digest_buff_dma_addr)) {
108063893811SGilad Ben-Yossef 		dev_err(dev, "Mapping digest len %zu B at va=%pK for DMA failed\n",
108163893811SGilad Ben-Yossef 			sizeof(ctx->digest_buff), ctx->digest_buff);
108263893811SGilad Ben-Yossef 		goto fail;
108363893811SGilad Ben-Yossef 	}
108463893811SGilad Ben-Yossef 	dev_dbg(dev, "Mapped digest %zu B at va=%pK to dma=%pad\n",
108563893811SGilad Ben-Yossef 		sizeof(ctx->digest_buff), ctx->digest_buff,
108663893811SGilad Ben-Yossef 		&ctx->digest_buff_dma_addr);
108763893811SGilad Ben-Yossef 
108863893811SGilad Ben-Yossef 	ctx->opad_tmp_keys_dma_addr =
1089f4274eecSGeert Uytterhoeven 		dma_map_single(dev, ctx->opad_tmp_keys_buff,
109063893811SGilad Ben-Yossef 			       sizeof(ctx->opad_tmp_keys_buff),
109163893811SGilad Ben-Yossef 			       DMA_BIDIRECTIONAL);
109263893811SGilad Ben-Yossef 	if (dma_mapping_error(dev, ctx->opad_tmp_keys_dma_addr)) {
109363893811SGilad Ben-Yossef 		dev_err(dev, "Mapping opad digest %zu B at va=%pK for DMA failed\n",
109463893811SGilad Ben-Yossef 			sizeof(ctx->opad_tmp_keys_buff),
109563893811SGilad Ben-Yossef 			ctx->opad_tmp_keys_buff);
109663893811SGilad Ben-Yossef 		goto fail;
109763893811SGilad Ben-Yossef 	}
109863893811SGilad Ben-Yossef 	dev_dbg(dev, "Mapped opad_tmp_keys %zu B at va=%pK to dma=%pad\n",
109963893811SGilad Ben-Yossef 		sizeof(ctx->opad_tmp_keys_buff), ctx->opad_tmp_keys_buff,
110063893811SGilad Ben-Yossef 		&ctx->opad_tmp_keys_dma_addr);
110163893811SGilad Ben-Yossef 
110263893811SGilad Ben-Yossef 	ctx->is_hmac = false;
110363893811SGilad Ben-Yossef 	return 0;
110463893811SGilad Ben-Yossef 
110563893811SGilad Ben-Yossef fail:
110663893811SGilad Ben-Yossef 	cc_free_ctx(ctx);
110763893811SGilad Ben-Yossef 	return -ENOMEM;
110863893811SGilad Ben-Yossef }
110963893811SGilad Ben-Yossef 
cc_get_hash_len(struct crypto_tfm * tfm)1110f1e52fd0SYael Chemla static int cc_get_hash_len(struct crypto_tfm *tfm)
1111f1e52fd0SYael Chemla {
1112*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_tfm_ctx_dma(tfm);
1113f1e52fd0SYael Chemla 
1114927574e0SYael Chemla 	if (ctx->hash_mode == DRV_HASH_SM3)
1115927574e0SYael Chemla 		return CC_SM3_HASH_LEN_SIZE;
1116927574e0SYael Chemla 	else
1117f1e52fd0SYael Chemla 		return cc_get_default_hash_len(ctx->drvdata);
1118f1e52fd0SYael Chemla }
1119f1e52fd0SYael Chemla 
cc_cra_init(struct crypto_tfm * tfm)112063893811SGilad Ben-Yossef static int cc_cra_init(struct crypto_tfm *tfm)
112163893811SGilad Ben-Yossef {
1122*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_tfm_ctx_dma(tfm);
112363893811SGilad Ben-Yossef 	struct hash_alg_common *hash_alg_common =
112463893811SGilad Ben-Yossef 		container_of(tfm->__crt_alg, struct hash_alg_common, base);
112563893811SGilad Ben-Yossef 	struct ahash_alg *ahash_alg =
112663893811SGilad Ben-Yossef 		container_of(hash_alg_common, struct ahash_alg, halg);
112763893811SGilad Ben-Yossef 	struct cc_hash_alg *cc_alg =
112863893811SGilad Ben-Yossef 			container_of(ahash_alg, struct cc_hash_alg, ahash_alg);
112963893811SGilad Ben-Yossef 
1130*07547fa7SHerbert Xu 	crypto_ahash_set_reqsize_dma(__crypto_ahash_cast(tfm),
113163893811SGilad Ben-Yossef 				     sizeof(struct ahash_req_ctx));
113263893811SGilad Ben-Yossef 
113363893811SGilad Ben-Yossef 	ctx->hash_mode = cc_alg->hash_mode;
113463893811SGilad Ben-Yossef 	ctx->hw_mode = cc_alg->hw_mode;
113563893811SGilad Ben-Yossef 	ctx->inter_digestsize = cc_alg->inter_digestsize;
113663893811SGilad Ben-Yossef 	ctx->drvdata = cc_alg->drvdata;
1137f1e52fd0SYael Chemla 	ctx->hash_len = cc_get_hash_len(tfm);
113863893811SGilad Ben-Yossef 	return cc_alloc_ctx(ctx);
113963893811SGilad Ben-Yossef }
114063893811SGilad Ben-Yossef 
cc_cra_exit(struct crypto_tfm * tfm)114163893811SGilad Ben-Yossef static void cc_cra_exit(struct crypto_tfm *tfm)
114263893811SGilad Ben-Yossef {
1143*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_tfm_ctx_dma(tfm);
114463893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
114563893811SGilad Ben-Yossef 
114663893811SGilad Ben-Yossef 	dev_dbg(dev, "cc_cra_exit");
114763893811SGilad Ben-Yossef 	cc_free_ctx(ctx);
114863893811SGilad Ben-Yossef }
114963893811SGilad Ben-Yossef 
cc_mac_update(struct ahash_request * req)115063893811SGilad Ben-Yossef static int cc_mac_update(struct ahash_request *req)
115163893811SGilad Ben-Yossef {
1152*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
115363893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
1154*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
115563893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
115663893811SGilad Ben-Yossef 	unsigned int block_size = crypto_tfm_alg_blocksize(&tfm->base);
115763893811SGilad Ben-Yossef 	struct cc_crypto_req cc_req = {};
115863893811SGilad Ben-Yossef 	struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
115963893811SGilad Ben-Yossef 	int rc;
116063893811SGilad Ben-Yossef 	u32 idx = 0;
116163893811SGilad Ben-Yossef 	gfp_t flags = cc_gfp_flags(&req->base);
116263893811SGilad Ben-Yossef 
116363893811SGilad Ben-Yossef 	if (req->nbytes == 0) {
116463893811SGilad Ben-Yossef 		/* no real updates required */
116563893811SGilad Ben-Yossef 		return 0;
116663893811SGilad Ben-Yossef 	}
116763893811SGilad Ben-Yossef 
116863893811SGilad Ben-Yossef 	state->xcbc_count++;
116963893811SGilad Ben-Yossef 
117063893811SGilad Ben-Yossef 	rc = cc_map_hash_request_update(ctx->drvdata, state, req->src,
117163893811SGilad Ben-Yossef 					req->nbytes, block_size, flags);
117263893811SGilad Ben-Yossef 	if (rc) {
117363893811SGilad Ben-Yossef 		if (rc == 1) {
117463893811SGilad Ben-Yossef 			dev_dbg(dev, " data size not require HW update %x\n",
117563893811SGilad Ben-Yossef 				req->nbytes);
117663893811SGilad Ben-Yossef 			/* No hardware updates are required */
117763893811SGilad Ben-Yossef 			return 0;
117863893811SGilad Ben-Yossef 		}
117963893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_request_update() failed\n");
118063893811SGilad Ben-Yossef 		return -ENOMEM;
118163893811SGilad Ben-Yossef 	}
118263893811SGilad Ben-Yossef 
118363893811SGilad Ben-Yossef 	if (cc_map_req(dev, state, ctx)) {
118463893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_source() failed\n");
118563893811SGilad Ben-Yossef 		return -EINVAL;
118663893811SGilad Ben-Yossef 	}
118763893811SGilad Ben-Yossef 
118863893811SGilad Ben-Yossef 	if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC)
118963893811SGilad Ben-Yossef 		cc_setup_xcbc(req, desc, &idx);
119063893811SGilad Ben-Yossef 	else
119163893811SGilad Ben-Yossef 		cc_setup_cmac(req, desc, &idx);
119263893811SGilad Ben-Yossef 
119363893811SGilad Ben-Yossef 	cc_set_desc(state, ctx, DIN_AES_DOUT, desc, true, &idx);
119463893811SGilad Ben-Yossef 
119563893811SGilad Ben-Yossef 	/* store the hash digest result in context */
119663893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
119763893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], ctx->hw_mode);
119863893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
119963893811SGilad Ben-Yossef 		      ctx->inter_digestsize, NS_BIT, 1);
120027b3b22dSGilad Ben-Yossef 	set_queue_last_ind(ctx->drvdata, &desc[idx]);
120163893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_AES_to_DOUT);
120263893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
120363893811SGilad Ben-Yossef 	idx++;
120463893811SGilad Ben-Yossef 
120563893811SGilad Ben-Yossef 	/* Setup request structure */
1206f4274eecSGeert Uytterhoeven 	cc_req.user_cb = cc_update_complete;
1207f4274eecSGeert Uytterhoeven 	cc_req.user_arg = req;
120863893811SGilad Ben-Yossef 
120963893811SGilad Ben-Yossef 	rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
121063893811SGilad Ben-Yossef 	if (rc != -EINPROGRESS && rc != -EBUSY) {
121163893811SGilad Ben-Yossef 		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
121263893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, req->src, true);
121363893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
121463893811SGilad Ben-Yossef 	}
121563893811SGilad Ben-Yossef 	return rc;
121663893811SGilad Ben-Yossef }
121763893811SGilad Ben-Yossef 
cc_mac_final(struct ahash_request * req)121863893811SGilad Ben-Yossef static int cc_mac_final(struct ahash_request *req)
121963893811SGilad Ben-Yossef {
1220*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
122163893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
1222*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
122363893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
122463893811SGilad Ben-Yossef 	struct cc_crypto_req cc_req = {};
122563893811SGilad Ben-Yossef 	struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
122663893811SGilad Ben-Yossef 	int idx = 0;
122763893811SGilad Ben-Yossef 	int rc = 0;
122863893811SGilad Ben-Yossef 	u32 key_size, key_len;
122963893811SGilad Ben-Yossef 	u32 digestsize = crypto_ahash_digestsize(tfm);
123063893811SGilad Ben-Yossef 	gfp_t flags = cc_gfp_flags(&req->base);
123163893811SGilad Ben-Yossef 	u32 rem_cnt = *cc_hash_buf_cnt(state);
123263893811SGilad Ben-Yossef 
123363893811SGilad Ben-Yossef 	if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
123463893811SGilad Ben-Yossef 		key_size = CC_AES_128_BIT_KEY_SIZE;
123563893811SGilad Ben-Yossef 		key_len  = CC_AES_128_BIT_KEY_SIZE;
123663893811SGilad Ben-Yossef 	} else {
123763893811SGilad Ben-Yossef 		key_size = (ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE :
123863893811SGilad Ben-Yossef 			ctx->key_params.keylen;
123963893811SGilad Ben-Yossef 		key_len =  ctx->key_params.keylen;
124063893811SGilad Ben-Yossef 	}
124163893811SGilad Ben-Yossef 
124263893811SGilad Ben-Yossef 	dev_dbg(dev, "===== final  xcbc reminder (%d) ====\n", rem_cnt);
124363893811SGilad Ben-Yossef 
124463893811SGilad Ben-Yossef 	if (cc_map_req(dev, state, ctx)) {
124563893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_source() failed\n");
124663893811SGilad Ben-Yossef 		return -EINVAL;
124763893811SGilad Ben-Yossef 	}
124863893811SGilad Ben-Yossef 
124963893811SGilad Ben-Yossef 	if (cc_map_hash_request_final(ctx->drvdata, state, req->src,
125063893811SGilad Ben-Yossef 				      req->nbytes, 0, flags)) {
125163893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_request_final() failed\n");
125263893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
125363893811SGilad Ben-Yossef 		return -ENOMEM;
125463893811SGilad Ben-Yossef 	}
125563893811SGilad Ben-Yossef 
125663893811SGilad Ben-Yossef 	if (cc_map_result(dev, state, digestsize)) {
125763893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_digest() failed\n");
125863893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, req->src, true);
125963893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
126063893811SGilad Ben-Yossef 		return -ENOMEM;
126163893811SGilad Ben-Yossef 	}
126263893811SGilad Ben-Yossef 
126363893811SGilad Ben-Yossef 	/* Setup request structure */
1264f4274eecSGeert Uytterhoeven 	cc_req.user_cb = cc_hash_complete;
1265f4274eecSGeert Uytterhoeven 	cc_req.user_arg = req;
126663893811SGilad Ben-Yossef 
126763893811SGilad Ben-Yossef 	if (state->xcbc_count && rem_cnt == 0) {
126863893811SGilad Ben-Yossef 		/* Load key for ECB decryption */
126963893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
127063893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], DRV_CIPHER_ECB);
127163893811SGilad Ben-Yossef 		set_cipher_config0(&desc[idx], DRV_CRYPTO_DIRECTION_DECRYPT);
127263893811SGilad Ben-Yossef 		set_din_type(&desc[idx], DMA_DLLI,
127363893811SGilad Ben-Yossef 			     (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K1_OFFSET),
127463893811SGilad Ben-Yossef 			     key_size, NS_BIT);
127563893811SGilad Ben-Yossef 		set_key_size_aes(&desc[idx], key_len);
127663893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], S_DIN_to_AES);
127763893811SGilad Ben-Yossef 		set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
127863893811SGilad Ben-Yossef 		idx++;
127963893811SGilad Ben-Yossef 
128063893811SGilad Ben-Yossef 		/* Initiate decryption of block state to previous
128163893811SGilad Ben-Yossef 		 * block_state-XOR-M[n]
128263893811SGilad Ben-Yossef 		 */
128363893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
128463893811SGilad Ben-Yossef 		set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
128563893811SGilad Ben-Yossef 			     CC_AES_BLOCK_SIZE, NS_BIT);
128663893811SGilad Ben-Yossef 		set_dout_dlli(&desc[idx], state->digest_buff_dma_addr,
128763893811SGilad Ben-Yossef 			      CC_AES_BLOCK_SIZE, NS_BIT, 0);
128863893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], DIN_AES_DOUT);
128963893811SGilad Ben-Yossef 		idx++;
129063893811SGilad Ben-Yossef 
129163893811SGilad Ben-Yossef 		/* Memory Barrier: wait for axi write to complete */
129263893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
129363893811SGilad Ben-Yossef 		set_din_no_dma(&desc[idx], 0, 0xfffff0);
129463893811SGilad Ben-Yossef 		set_dout_no_dma(&desc[idx], 0, 0, 1);
129563893811SGilad Ben-Yossef 		idx++;
129663893811SGilad Ben-Yossef 	}
129763893811SGilad Ben-Yossef 
129863893811SGilad Ben-Yossef 	if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC)
129963893811SGilad Ben-Yossef 		cc_setup_xcbc(req, desc, &idx);
130063893811SGilad Ben-Yossef 	else
130163893811SGilad Ben-Yossef 		cc_setup_cmac(req, desc, &idx);
130263893811SGilad Ben-Yossef 
130363893811SGilad Ben-Yossef 	if (state->xcbc_count == 0) {
130463893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
130563893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], ctx->hw_mode);
130663893811SGilad Ben-Yossef 		set_key_size_aes(&desc[idx], key_len);
130763893811SGilad Ben-Yossef 		set_cmac_size0_mode(&desc[idx]);
130863893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], S_DIN_to_AES);
130963893811SGilad Ben-Yossef 		idx++;
131063893811SGilad Ben-Yossef 	} else if (rem_cnt > 0) {
131163893811SGilad Ben-Yossef 		cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
131263893811SGilad Ben-Yossef 	} else {
131363893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
131463893811SGilad Ben-Yossef 		set_din_const(&desc[idx], 0x00, CC_AES_BLOCK_SIZE);
131563893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], DIN_AES_DOUT);
131663893811SGilad Ben-Yossef 		idx++;
131763893811SGilad Ben-Yossef 	}
131863893811SGilad Ben-Yossef 
131963893811SGilad Ben-Yossef 	/* Get final MAC result */
132063893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
132163893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
132263893811SGilad Ben-Yossef 		      digestsize, NS_BIT, 1);
132327b3b22dSGilad Ben-Yossef 	set_queue_last_ind(ctx->drvdata, &desc[idx]);
132463893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_AES_to_DOUT);
132563893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
132663893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], ctx->hw_mode);
132763893811SGilad Ben-Yossef 	idx++;
132863893811SGilad Ben-Yossef 
132963893811SGilad Ben-Yossef 	rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
133063893811SGilad Ben-Yossef 	if (rc != -EINPROGRESS && rc != -EBUSY) {
133163893811SGilad Ben-Yossef 		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
133263893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, req->src, true);
133363893811SGilad Ben-Yossef 		cc_unmap_result(dev, state, digestsize, req->result);
133463893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
133563893811SGilad Ben-Yossef 	}
133663893811SGilad Ben-Yossef 	return rc;
133763893811SGilad Ben-Yossef }
133863893811SGilad Ben-Yossef 
cc_mac_finup(struct ahash_request * req)133963893811SGilad Ben-Yossef static int cc_mac_finup(struct ahash_request *req)
134063893811SGilad Ben-Yossef {
1341*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
134263893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
1343*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
134463893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
134563893811SGilad Ben-Yossef 	struct cc_crypto_req cc_req = {};
134663893811SGilad Ben-Yossef 	struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
134763893811SGilad Ben-Yossef 	int idx = 0;
134863893811SGilad Ben-Yossef 	int rc = 0;
134963893811SGilad Ben-Yossef 	u32 key_len = 0;
135063893811SGilad Ben-Yossef 	u32 digestsize = crypto_ahash_digestsize(tfm);
135163893811SGilad Ben-Yossef 	gfp_t flags = cc_gfp_flags(&req->base);
135263893811SGilad Ben-Yossef 
135363893811SGilad Ben-Yossef 	dev_dbg(dev, "===== finup xcbc(%d) ====\n", req->nbytes);
135463893811SGilad Ben-Yossef 	if (state->xcbc_count > 0 && req->nbytes == 0) {
135563893811SGilad Ben-Yossef 		dev_dbg(dev, "No data to update. Call to fdx_mac_final\n");
135663893811SGilad Ben-Yossef 		return cc_mac_final(req);
135763893811SGilad Ben-Yossef 	}
135863893811SGilad Ben-Yossef 
135963893811SGilad Ben-Yossef 	if (cc_map_req(dev, state, ctx)) {
136063893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_source() failed\n");
136163893811SGilad Ben-Yossef 		return -EINVAL;
136263893811SGilad Ben-Yossef 	}
136363893811SGilad Ben-Yossef 
136463893811SGilad Ben-Yossef 	if (cc_map_hash_request_final(ctx->drvdata, state, req->src,
136563893811SGilad Ben-Yossef 				      req->nbytes, 1, flags)) {
136663893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_request_final() failed\n");
136763893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
136863893811SGilad Ben-Yossef 		return -ENOMEM;
136963893811SGilad Ben-Yossef 	}
137063893811SGilad Ben-Yossef 	if (cc_map_result(dev, state, digestsize)) {
137163893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_digest() failed\n");
137263893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, req->src, true);
137363893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
137463893811SGilad Ben-Yossef 		return -ENOMEM;
137563893811SGilad Ben-Yossef 	}
137663893811SGilad Ben-Yossef 
137763893811SGilad Ben-Yossef 	/* Setup request structure */
1378f4274eecSGeert Uytterhoeven 	cc_req.user_cb = cc_hash_complete;
1379f4274eecSGeert Uytterhoeven 	cc_req.user_arg = req;
138063893811SGilad Ben-Yossef 
138163893811SGilad Ben-Yossef 	if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
138263893811SGilad Ben-Yossef 		key_len = CC_AES_128_BIT_KEY_SIZE;
138363893811SGilad Ben-Yossef 		cc_setup_xcbc(req, desc, &idx);
138463893811SGilad Ben-Yossef 	} else {
138563893811SGilad Ben-Yossef 		key_len = ctx->key_params.keylen;
138663893811SGilad Ben-Yossef 		cc_setup_cmac(req, desc, &idx);
138763893811SGilad Ben-Yossef 	}
138863893811SGilad Ben-Yossef 
138963893811SGilad Ben-Yossef 	if (req->nbytes == 0) {
139063893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
139163893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], ctx->hw_mode);
139263893811SGilad Ben-Yossef 		set_key_size_aes(&desc[idx], key_len);
139363893811SGilad Ben-Yossef 		set_cmac_size0_mode(&desc[idx]);
139463893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], S_DIN_to_AES);
139563893811SGilad Ben-Yossef 		idx++;
139663893811SGilad Ben-Yossef 	} else {
139763893811SGilad Ben-Yossef 		cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
139863893811SGilad Ben-Yossef 	}
139963893811SGilad Ben-Yossef 
140063893811SGilad Ben-Yossef 	/* Get final MAC result */
140163893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
140263893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
140363893811SGilad Ben-Yossef 		      digestsize, NS_BIT, 1);
140427b3b22dSGilad Ben-Yossef 	set_queue_last_ind(ctx->drvdata, &desc[idx]);
140563893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_AES_to_DOUT);
140663893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
140763893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], ctx->hw_mode);
140863893811SGilad Ben-Yossef 	idx++;
140963893811SGilad Ben-Yossef 
141063893811SGilad Ben-Yossef 	rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
141163893811SGilad Ben-Yossef 	if (rc != -EINPROGRESS && rc != -EBUSY) {
141263893811SGilad Ben-Yossef 		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
141363893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, req->src, true);
141463893811SGilad Ben-Yossef 		cc_unmap_result(dev, state, digestsize, req->result);
141563893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
141663893811SGilad Ben-Yossef 	}
141763893811SGilad Ben-Yossef 	return rc;
141863893811SGilad Ben-Yossef }
141963893811SGilad Ben-Yossef 
cc_mac_digest(struct ahash_request * req)142063893811SGilad Ben-Yossef static int cc_mac_digest(struct ahash_request *req)
142163893811SGilad Ben-Yossef {
1422*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
142363893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
1424*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
142563893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
142663893811SGilad Ben-Yossef 	u32 digestsize = crypto_ahash_digestsize(tfm);
142763893811SGilad Ben-Yossef 	struct cc_crypto_req cc_req = {};
142863893811SGilad Ben-Yossef 	struct cc_hw_desc desc[CC_MAX_HASH_SEQ_LEN];
142963893811SGilad Ben-Yossef 	u32 key_len;
143063893811SGilad Ben-Yossef 	unsigned int idx = 0;
143163893811SGilad Ben-Yossef 	int rc;
143263893811SGilad Ben-Yossef 	gfp_t flags = cc_gfp_flags(&req->base);
143363893811SGilad Ben-Yossef 
143463893811SGilad Ben-Yossef 	dev_dbg(dev, "===== -digest mac (%d) ====\n",  req->nbytes);
143563893811SGilad Ben-Yossef 
143663893811SGilad Ben-Yossef 	cc_init_req(dev, state, ctx);
143763893811SGilad Ben-Yossef 
143863893811SGilad Ben-Yossef 	if (cc_map_req(dev, state, ctx)) {
143963893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_source() failed\n");
144063893811SGilad Ben-Yossef 		return -ENOMEM;
144163893811SGilad Ben-Yossef 	}
144263893811SGilad Ben-Yossef 	if (cc_map_result(dev, state, digestsize)) {
144363893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_digest() failed\n");
144463893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
144563893811SGilad Ben-Yossef 		return -ENOMEM;
144663893811SGilad Ben-Yossef 	}
144763893811SGilad Ben-Yossef 
144863893811SGilad Ben-Yossef 	if (cc_map_hash_request_final(ctx->drvdata, state, req->src,
144963893811SGilad Ben-Yossef 				      req->nbytes, 1, flags)) {
145063893811SGilad Ben-Yossef 		dev_err(dev, "map_ahash_request_final() failed\n");
145163893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
145263893811SGilad Ben-Yossef 		return -ENOMEM;
145363893811SGilad Ben-Yossef 	}
145463893811SGilad Ben-Yossef 
145563893811SGilad Ben-Yossef 	/* Setup request structure */
1456f4274eecSGeert Uytterhoeven 	cc_req.user_cb = cc_digest_complete;
1457f4274eecSGeert Uytterhoeven 	cc_req.user_arg = req;
145863893811SGilad Ben-Yossef 
145963893811SGilad Ben-Yossef 	if (ctx->hw_mode == DRV_CIPHER_XCBC_MAC) {
146063893811SGilad Ben-Yossef 		key_len = CC_AES_128_BIT_KEY_SIZE;
146163893811SGilad Ben-Yossef 		cc_setup_xcbc(req, desc, &idx);
146263893811SGilad Ben-Yossef 	} else {
146363893811SGilad Ben-Yossef 		key_len = ctx->key_params.keylen;
146463893811SGilad Ben-Yossef 		cc_setup_cmac(req, desc, &idx);
146563893811SGilad Ben-Yossef 	}
146663893811SGilad Ben-Yossef 
146763893811SGilad Ben-Yossef 	if (req->nbytes == 0) {
146863893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
146963893811SGilad Ben-Yossef 		set_cipher_mode(&desc[idx], ctx->hw_mode);
147063893811SGilad Ben-Yossef 		set_key_size_aes(&desc[idx], key_len);
147163893811SGilad Ben-Yossef 		set_cmac_size0_mode(&desc[idx]);
147263893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], S_DIN_to_AES);
147363893811SGilad Ben-Yossef 		idx++;
147463893811SGilad Ben-Yossef 	} else {
147563893811SGilad Ben-Yossef 		cc_set_desc(state, ctx, DIN_AES_DOUT, desc, false, &idx);
147663893811SGilad Ben-Yossef 	}
147763893811SGilad Ben-Yossef 
147863893811SGilad Ben-Yossef 	/* Get final MAC result */
147963893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
148063893811SGilad Ben-Yossef 	set_dout_dlli(&desc[idx], state->digest_result_dma_addr,
148163893811SGilad Ben-Yossef 		      CC_AES_BLOCK_SIZE, NS_BIT, 1);
148227b3b22dSGilad Ben-Yossef 	set_queue_last_ind(ctx->drvdata, &desc[idx]);
148363893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_AES_to_DOUT);
148463893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_WRITE_STATE0);
148563893811SGilad Ben-Yossef 	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
148663893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], ctx->hw_mode);
148763893811SGilad Ben-Yossef 	idx++;
148863893811SGilad Ben-Yossef 
148963893811SGilad Ben-Yossef 	rc = cc_send_request(ctx->drvdata, &cc_req, desc, idx, &req->base);
149063893811SGilad Ben-Yossef 	if (rc != -EINPROGRESS && rc != -EBUSY) {
149163893811SGilad Ben-Yossef 		dev_err(dev, "send_request() failed (rc=%d)\n", rc);
149263893811SGilad Ben-Yossef 		cc_unmap_hash_request(dev, state, req->src, true);
149363893811SGilad Ben-Yossef 		cc_unmap_result(dev, state, digestsize, req->result);
149463893811SGilad Ben-Yossef 		cc_unmap_req(dev, state, ctx);
149563893811SGilad Ben-Yossef 	}
149663893811SGilad Ben-Yossef 	return rc;
149763893811SGilad Ben-Yossef }
149863893811SGilad Ben-Yossef 
cc_hash_export(struct ahash_request * req,void * out)149963893811SGilad Ben-Yossef static int cc_hash_export(struct ahash_request *req, void *out)
150063893811SGilad Ben-Yossef {
150163893811SGilad Ben-Yossef 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1502*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
1503*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
150463893811SGilad Ben-Yossef 	u8 *curr_buff = cc_hash_buf(state);
150563893811SGilad Ben-Yossef 	u32 curr_buff_cnt = *cc_hash_buf_cnt(state);
150663893811SGilad Ben-Yossef 	const u32 tmp = CC_EXPORT_MAGIC;
150763893811SGilad Ben-Yossef 
150863893811SGilad Ben-Yossef 	memcpy(out, &tmp, sizeof(u32));
150963893811SGilad Ben-Yossef 	out += sizeof(u32);
151063893811SGilad Ben-Yossef 
151163893811SGilad Ben-Yossef 	memcpy(out, state->digest_buff, ctx->inter_digestsize);
151263893811SGilad Ben-Yossef 	out += ctx->inter_digestsize;
151363893811SGilad Ben-Yossef 
1514f1e52fd0SYael Chemla 	memcpy(out, state->digest_bytes_len, ctx->hash_len);
1515f1e52fd0SYael Chemla 	out += ctx->hash_len;
151663893811SGilad Ben-Yossef 
151763893811SGilad Ben-Yossef 	memcpy(out, &curr_buff_cnt, sizeof(u32));
151863893811SGilad Ben-Yossef 	out += sizeof(u32);
151963893811SGilad Ben-Yossef 
152063893811SGilad Ben-Yossef 	memcpy(out, curr_buff, curr_buff_cnt);
152163893811SGilad Ben-Yossef 
152263893811SGilad Ben-Yossef 	return 0;
152363893811SGilad Ben-Yossef }
152463893811SGilad Ben-Yossef 
cc_hash_import(struct ahash_request * req,const void * in)152563893811SGilad Ben-Yossef static int cc_hash_import(struct ahash_request *req, const void *in)
152663893811SGilad Ben-Yossef {
152763893811SGilad Ben-Yossef 	struct crypto_ahash *ahash = crypto_ahash_reqtfm(req);
1528*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(ahash);
152963893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
1530*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(req);
153163893811SGilad Ben-Yossef 	u32 tmp;
153263893811SGilad Ben-Yossef 
153363893811SGilad Ben-Yossef 	memcpy(&tmp, in, sizeof(u32));
153463893811SGilad Ben-Yossef 	if (tmp != CC_EXPORT_MAGIC)
153563893811SGilad Ben-Yossef 		return -EINVAL;
153663893811SGilad Ben-Yossef 	in += sizeof(u32);
153763893811SGilad Ben-Yossef 
153863893811SGilad Ben-Yossef 	cc_init_req(dev, state, ctx);
153963893811SGilad Ben-Yossef 
154063893811SGilad Ben-Yossef 	memcpy(state->digest_buff, in, ctx->inter_digestsize);
154163893811SGilad Ben-Yossef 	in += ctx->inter_digestsize;
154263893811SGilad Ben-Yossef 
1543f1e52fd0SYael Chemla 	memcpy(state->digest_bytes_len, in, ctx->hash_len);
1544f1e52fd0SYael Chemla 	in += ctx->hash_len;
154563893811SGilad Ben-Yossef 
154663893811SGilad Ben-Yossef 	/* Sanity check the data as much as possible */
154763893811SGilad Ben-Yossef 	memcpy(&tmp, in, sizeof(u32));
154863893811SGilad Ben-Yossef 	if (tmp > CC_MAX_HASH_BLCK_SIZE)
154963893811SGilad Ben-Yossef 		return -EINVAL;
155063893811SGilad Ben-Yossef 	in += sizeof(u32);
155163893811SGilad Ben-Yossef 
155263893811SGilad Ben-Yossef 	state->buf_cnt[0] = tmp;
155363893811SGilad Ben-Yossef 	memcpy(state->buffers[0], in, tmp);
155463893811SGilad Ben-Yossef 
155563893811SGilad Ben-Yossef 	return 0;
155663893811SGilad Ben-Yossef }
155763893811SGilad Ben-Yossef 
155863893811SGilad Ben-Yossef struct cc_hash_template {
155963893811SGilad Ben-Yossef 	char name[CRYPTO_MAX_ALG_NAME];
156063893811SGilad Ben-Yossef 	char driver_name[CRYPTO_MAX_ALG_NAME];
156163893811SGilad Ben-Yossef 	char mac_name[CRYPTO_MAX_ALG_NAME];
156263893811SGilad Ben-Yossef 	char mac_driver_name[CRYPTO_MAX_ALG_NAME];
156363893811SGilad Ben-Yossef 	unsigned int blocksize;
1564927574e0SYael Chemla 	bool is_mac;
156563893811SGilad Ben-Yossef 	bool synchronize;
156663893811SGilad Ben-Yossef 	struct ahash_alg template_ahash;
156763893811SGilad Ben-Yossef 	int hash_mode;
156863893811SGilad Ben-Yossef 	int hw_mode;
156963893811SGilad Ben-Yossef 	int inter_digestsize;
157063893811SGilad Ben-Yossef 	struct cc_drvdata *drvdata;
157127b3b22dSGilad Ben-Yossef 	u32 min_hw_rev;
15721c876a90SGilad Ben-Yossef 	enum cc_std_body std_body;
157363893811SGilad Ben-Yossef };
157463893811SGilad Ben-Yossef 
157563893811SGilad Ben-Yossef #define CC_STATE_SIZE(_x) \
157627b3b22dSGilad Ben-Yossef 	((_x) + HASH_MAX_LEN_SIZE + CC_MAX_HASH_BLCK_SIZE + (2 * sizeof(u32)))
157763893811SGilad Ben-Yossef 
157863893811SGilad Ben-Yossef /* hash descriptors */
157963893811SGilad Ben-Yossef static struct cc_hash_template driver_hash[] = {
158063893811SGilad Ben-Yossef 	//Asynchronize hash template
158163893811SGilad Ben-Yossef 	{
158263893811SGilad Ben-Yossef 		.name = "sha1",
158363893811SGilad Ben-Yossef 		.driver_name = "sha1-ccree",
158463893811SGilad Ben-Yossef 		.mac_name = "hmac(sha1)",
158563893811SGilad Ben-Yossef 		.mac_driver_name = "hmac-sha1-ccree",
158663893811SGilad Ben-Yossef 		.blocksize = SHA1_BLOCK_SIZE,
1587927574e0SYael Chemla 		.is_mac = true,
158863893811SGilad Ben-Yossef 		.synchronize = false,
158963893811SGilad Ben-Yossef 		.template_ahash = {
159063893811SGilad Ben-Yossef 			.init = cc_hash_init,
159163893811SGilad Ben-Yossef 			.update = cc_hash_update,
159263893811SGilad Ben-Yossef 			.final = cc_hash_final,
159363893811SGilad Ben-Yossef 			.finup = cc_hash_finup,
159463893811SGilad Ben-Yossef 			.digest = cc_hash_digest,
159563893811SGilad Ben-Yossef 			.export = cc_hash_export,
159663893811SGilad Ben-Yossef 			.import = cc_hash_import,
159763893811SGilad Ben-Yossef 			.setkey = cc_hash_setkey,
159863893811SGilad Ben-Yossef 			.halg = {
159963893811SGilad Ben-Yossef 				.digestsize = SHA1_DIGEST_SIZE,
160063893811SGilad Ben-Yossef 				.statesize = CC_STATE_SIZE(SHA1_DIGEST_SIZE),
160163893811SGilad Ben-Yossef 			},
160263893811SGilad Ben-Yossef 		},
160363893811SGilad Ben-Yossef 		.hash_mode = DRV_HASH_SHA1,
160463893811SGilad Ben-Yossef 		.hw_mode = DRV_HASH_HW_SHA1,
160563893811SGilad Ben-Yossef 		.inter_digestsize = SHA1_DIGEST_SIZE,
160627b3b22dSGilad Ben-Yossef 		.min_hw_rev = CC_HW_REV_630,
16071c876a90SGilad Ben-Yossef 		.std_body = CC_STD_NIST,
160863893811SGilad Ben-Yossef 	},
160963893811SGilad Ben-Yossef 	{
161063893811SGilad Ben-Yossef 		.name = "sha256",
161163893811SGilad Ben-Yossef 		.driver_name = "sha256-ccree",
161263893811SGilad Ben-Yossef 		.mac_name = "hmac(sha256)",
161363893811SGilad Ben-Yossef 		.mac_driver_name = "hmac-sha256-ccree",
161463893811SGilad Ben-Yossef 		.blocksize = SHA256_BLOCK_SIZE,
1615927574e0SYael Chemla 		.is_mac = true,
161663893811SGilad Ben-Yossef 		.template_ahash = {
161763893811SGilad Ben-Yossef 			.init = cc_hash_init,
161863893811SGilad Ben-Yossef 			.update = cc_hash_update,
161963893811SGilad Ben-Yossef 			.final = cc_hash_final,
162063893811SGilad Ben-Yossef 			.finup = cc_hash_finup,
162163893811SGilad Ben-Yossef 			.digest = cc_hash_digest,
162263893811SGilad Ben-Yossef 			.export = cc_hash_export,
162363893811SGilad Ben-Yossef 			.import = cc_hash_import,
162463893811SGilad Ben-Yossef 			.setkey = cc_hash_setkey,
162563893811SGilad Ben-Yossef 			.halg = {
162663893811SGilad Ben-Yossef 				.digestsize = SHA256_DIGEST_SIZE,
162763893811SGilad Ben-Yossef 				.statesize = CC_STATE_SIZE(SHA256_DIGEST_SIZE)
162863893811SGilad Ben-Yossef 			},
162963893811SGilad Ben-Yossef 		},
163063893811SGilad Ben-Yossef 		.hash_mode = DRV_HASH_SHA256,
163163893811SGilad Ben-Yossef 		.hw_mode = DRV_HASH_HW_SHA256,
163263893811SGilad Ben-Yossef 		.inter_digestsize = SHA256_DIGEST_SIZE,
163327b3b22dSGilad Ben-Yossef 		.min_hw_rev = CC_HW_REV_630,
16341c876a90SGilad Ben-Yossef 		.std_body = CC_STD_NIST,
163563893811SGilad Ben-Yossef 	},
163663893811SGilad Ben-Yossef 	{
163763893811SGilad Ben-Yossef 		.name = "sha224",
163863893811SGilad Ben-Yossef 		.driver_name = "sha224-ccree",
163963893811SGilad Ben-Yossef 		.mac_name = "hmac(sha224)",
164063893811SGilad Ben-Yossef 		.mac_driver_name = "hmac-sha224-ccree",
164163893811SGilad Ben-Yossef 		.blocksize = SHA224_BLOCK_SIZE,
1642927574e0SYael Chemla 		.is_mac = true,
164363893811SGilad Ben-Yossef 		.template_ahash = {
164463893811SGilad Ben-Yossef 			.init = cc_hash_init,
164563893811SGilad Ben-Yossef 			.update = cc_hash_update,
164663893811SGilad Ben-Yossef 			.final = cc_hash_final,
164763893811SGilad Ben-Yossef 			.finup = cc_hash_finup,
164863893811SGilad Ben-Yossef 			.digest = cc_hash_digest,
164963893811SGilad Ben-Yossef 			.export = cc_hash_export,
165063893811SGilad Ben-Yossef 			.import = cc_hash_import,
165163893811SGilad Ben-Yossef 			.setkey = cc_hash_setkey,
165263893811SGilad Ben-Yossef 			.halg = {
165363893811SGilad Ben-Yossef 				.digestsize = SHA224_DIGEST_SIZE,
1654f3df82b4SGilad Ben-Yossef 				.statesize = CC_STATE_SIZE(SHA256_DIGEST_SIZE),
165563893811SGilad Ben-Yossef 			},
165663893811SGilad Ben-Yossef 		},
165763893811SGilad Ben-Yossef 		.hash_mode = DRV_HASH_SHA224,
165863893811SGilad Ben-Yossef 		.hw_mode = DRV_HASH_HW_SHA256,
165963893811SGilad Ben-Yossef 		.inter_digestsize = SHA256_DIGEST_SIZE,
166027b3b22dSGilad Ben-Yossef 		.min_hw_rev = CC_HW_REV_630,
16611c876a90SGilad Ben-Yossef 		.std_body = CC_STD_NIST,
166263893811SGilad Ben-Yossef 	},
166363893811SGilad Ben-Yossef 	{
166463893811SGilad Ben-Yossef 		.name = "sha384",
166563893811SGilad Ben-Yossef 		.driver_name = "sha384-ccree",
166663893811SGilad Ben-Yossef 		.mac_name = "hmac(sha384)",
166763893811SGilad Ben-Yossef 		.mac_driver_name = "hmac-sha384-ccree",
166863893811SGilad Ben-Yossef 		.blocksize = SHA384_BLOCK_SIZE,
1669927574e0SYael Chemla 		.is_mac = true,
167063893811SGilad Ben-Yossef 		.template_ahash = {
167163893811SGilad Ben-Yossef 			.init = cc_hash_init,
167263893811SGilad Ben-Yossef 			.update = cc_hash_update,
167363893811SGilad Ben-Yossef 			.final = cc_hash_final,
167463893811SGilad Ben-Yossef 			.finup = cc_hash_finup,
167563893811SGilad Ben-Yossef 			.digest = cc_hash_digest,
167663893811SGilad Ben-Yossef 			.export = cc_hash_export,
167763893811SGilad Ben-Yossef 			.import = cc_hash_import,
167863893811SGilad Ben-Yossef 			.setkey = cc_hash_setkey,
167963893811SGilad Ben-Yossef 			.halg = {
168063893811SGilad Ben-Yossef 				.digestsize = SHA384_DIGEST_SIZE,
1681f3df82b4SGilad Ben-Yossef 				.statesize = CC_STATE_SIZE(SHA512_DIGEST_SIZE),
168263893811SGilad Ben-Yossef 			},
168363893811SGilad Ben-Yossef 		},
168463893811SGilad Ben-Yossef 		.hash_mode = DRV_HASH_SHA384,
168563893811SGilad Ben-Yossef 		.hw_mode = DRV_HASH_HW_SHA512,
168663893811SGilad Ben-Yossef 		.inter_digestsize = SHA512_DIGEST_SIZE,
168727b3b22dSGilad Ben-Yossef 		.min_hw_rev = CC_HW_REV_712,
16881c876a90SGilad Ben-Yossef 		.std_body = CC_STD_NIST,
168963893811SGilad Ben-Yossef 	},
169063893811SGilad Ben-Yossef 	{
169163893811SGilad Ben-Yossef 		.name = "sha512",
169263893811SGilad Ben-Yossef 		.driver_name = "sha512-ccree",
169363893811SGilad Ben-Yossef 		.mac_name = "hmac(sha512)",
169463893811SGilad Ben-Yossef 		.mac_driver_name = "hmac-sha512-ccree",
169563893811SGilad Ben-Yossef 		.blocksize = SHA512_BLOCK_SIZE,
1696927574e0SYael Chemla 		.is_mac = true,
169763893811SGilad Ben-Yossef 		.template_ahash = {
169863893811SGilad Ben-Yossef 			.init = cc_hash_init,
169963893811SGilad Ben-Yossef 			.update = cc_hash_update,
170063893811SGilad Ben-Yossef 			.final = cc_hash_final,
170163893811SGilad Ben-Yossef 			.finup = cc_hash_finup,
170263893811SGilad Ben-Yossef 			.digest = cc_hash_digest,
170363893811SGilad Ben-Yossef 			.export = cc_hash_export,
170463893811SGilad Ben-Yossef 			.import = cc_hash_import,
170563893811SGilad Ben-Yossef 			.setkey = cc_hash_setkey,
170663893811SGilad Ben-Yossef 			.halg = {
170763893811SGilad Ben-Yossef 				.digestsize = SHA512_DIGEST_SIZE,
170863893811SGilad Ben-Yossef 				.statesize = CC_STATE_SIZE(SHA512_DIGEST_SIZE),
170963893811SGilad Ben-Yossef 			},
171063893811SGilad Ben-Yossef 		},
171163893811SGilad Ben-Yossef 		.hash_mode = DRV_HASH_SHA512,
171263893811SGilad Ben-Yossef 		.hw_mode = DRV_HASH_HW_SHA512,
171363893811SGilad Ben-Yossef 		.inter_digestsize = SHA512_DIGEST_SIZE,
171427b3b22dSGilad Ben-Yossef 		.min_hw_rev = CC_HW_REV_712,
17151c876a90SGilad Ben-Yossef 		.std_body = CC_STD_NIST,
171663893811SGilad Ben-Yossef 	},
171763893811SGilad Ben-Yossef 	{
171863893811SGilad Ben-Yossef 		.name = "md5",
171963893811SGilad Ben-Yossef 		.driver_name = "md5-ccree",
172063893811SGilad Ben-Yossef 		.mac_name = "hmac(md5)",
172163893811SGilad Ben-Yossef 		.mac_driver_name = "hmac-md5-ccree",
172263893811SGilad Ben-Yossef 		.blocksize = MD5_HMAC_BLOCK_SIZE,
1723927574e0SYael Chemla 		.is_mac = true,
172463893811SGilad Ben-Yossef 		.template_ahash = {
172563893811SGilad Ben-Yossef 			.init = cc_hash_init,
172663893811SGilad Ben-Yossef 			.update = cc_hash_update,
172763893811SGilad Ben-Yossef 			.final = cc_hash_final,
172863893811SGilad Ben-Yossef 			.finup = cc_hash_finup,
172963893811SGilad Ben-Yossef 			.digest = cc_hash_digest,
173063893811SGilad Ben-Yossef 			.export = cc_hash_export,
173163893811SGilad Ben-Yossef 			.import = cc_hash_import,
173263893811SGilad Ben-Yossef 			.setkey = cc_hash_setkey,
173363893811SGilad Ben-Yossef 			.halg = {
173463893811SGilad Ben-Yossef 				.digestsize = MD5_DIGEST_SIZE,
173563893811SGilad Ben-Yossef 				.statesize = CC_STATE_SIZE(MD5_DIGEST_SIZE),
173663893811SGilad Ben-Yossef 			},
173763893811SGilad Ben-Yossef 		},
173863893811SGilad Ben-Yossef 		.hash_mode = DRV_HASH_MD5,
173963893811SGilad Ben-Yossef 		.hw_mode = DRV_HASH_HW_MD5,
174063893811SGilad Ben-Yossef 		.inter_digestsize = MD5_DIGEST_SIZE,
174127b3b22dSGilad Ben-Yossef 		.min_hw_rev = CC_HW_REV_630,
17421c876a90SGilad Ben-Yossef 		.std_body = CC_STD_NIST,
174363893811SGilad Ben-Yossef 	},
174463893811SGilad Ben-Yossef 	{
1745927574e0SYael Chemla 		.name = "sm3",
1746927574e0SYael Chemla 		.driver_name = "sm3-ccree",
1747927574e0SYael Chemla 		.blocksize = SM3_BLOCK_SIZE,
1748927574e0SYael Chemla 		.is_mac = false,
1749927574e0SYael Chemla 		.template_ahash = {
1750927574e0SYael Chemla 			.init = cc_hash_init,
1751927574e0SYael Chemla 			.update = cc_hash_update,
1752927574e0SYael Chemla 			.final = cc_hash_final,
1753927574e0SYael Chemla 			.finup = cc_hash_finup,
1754927574e0SYael Chemla 			.digest = cc_hash_digest,
1755927574e0SYael Chemla 			.export = cc_hash_export,
1756927574e0SYael Chemla 			.import = cc_hash_import,
1757927574e0SYael Chemla 			.setkey = cc_hash_setkey,
1758927574e0SYael Chemla 			.halg = {
1759927574e0SYael Chemla 				.digestsize = SM3_DIGEST_SIZE,
1760927574e0SYael Chemla 				.statesize = CC_STATE_SIZE(SM3_DIGEST_SIZE),
1761927574e0SYael Chemla 			},
1762927574e0SYael Chemla 		},
1763927574e0SYael Chemla 		.hash_mode = DRV_HASH_SM3,
1764927574e0SYael Chemla 		.hw_mode = DRV_HASH_HW_SM3,
1765927574e0SYael Chemla 		.inter_digestsize = SM3_DIGEST_SIZE,
1766927574e0SYael Chemla 		.min_hw_rev = CC_HW_REV_713,
17671c876a90SGilad Ben-Yossef 		.std_body = CC_STD_OSCCA,
1768927574e0SYael Chemla 	},
1769927574e0SYael Chemla 	{
177063893811SGilad Ben-Yossef 		.mac_name = "xcbc(aes)",
177163893811SGilad Ben-Yossef 		.mac_driver_name = "xcbc-aes-ccree",
177263893811SGilad Ben-Yossef 		.blocksize = AES_BLOCK_SIZE,
1773927574e0SYael Chemla 		.is_mac = true,
177463893811SGilad Ben-Yossef 		.template_ahash = {
177563893811SGilad Ben-Yossef 			.init = cc_hash_init,
177663893811SGilad Ben-Yossef 			.update = cc_mac_update,
177763893811SGilad Ben-Yossef 			.final = cc_mac_final,
177863893811SGilad Ben-Yossef 			.finup = cc_mac_finup,
177963893811SGilad Ben-Yossef 			.digest = cc_mac_digest,
178063893811SGilad Ben-Yossef 			.setkey = cc_xcbc_setkey,
178163893811SGilad Ben-Yossef 			.export = cc_hash_export,
178263893811SGilad Ben-Yossef 			.import = cc_hash_import,
178363893811SGilad Ben-Yossef 			.halg = {
178463893811SGilad Ben-Yossef 				.digestsize = AES_BLOCK_SIZE,
178563893811SGilad Ben-Yossef 				.statesize = CC_STATE_SIZE(AES_BLOCK_SIZE),
178663893811SGilad Ben-Yossef 			},
178763893811SGilad Ben-Yossef 		},
178863893811SGilad Ben-Yossef 		.hash_mode = DRV_HASH_NULL,
178963893811SGilad Ben-Yossef 		.hw_mode = DRV_CIPHER_XCBC_MAC,
179063893811SGilad Ben-Yossef 		.inter_digestsize = AES_BLOCK_SIZE,
179127b3b22dSGilad Ben-Yossef 		.min_hw_rev = CC_HW_REV_630,
17921c876a90SGilad Ben-Yossef 		.std_body = CC_STD_NIST,
179363893811SGilad Ben-Yossef 	},
179463893811SGilad Ben-Yossef 	{
179563893811SGilad Ben-Yossef 		.mac_name = "cmac(aes)",
179663893811SGilad Ben-Yossef 		.mac_driver_name = "cmac-aes-ccree",
179763893811SGilad Ben-Yossef 		.blocksize = AES_BLOCK_SIZE,
1798927574e0SYael Chemla 		.is_mac = true,
179963893811SGilad Ben-Yossef 		.template_ahash = {
180063893811SGilad Ben-Yossef 			.init = cc_hash_init,
180163893811SGilad Ben-Yossef 			.update = cc_mac_update,
180263893811SGilad Ben-Yossef 			.final = cc_mac_final,
180363893811SGilad Ben-Yossef 			.finup = cc_mac_finup,
180463893811SGilad Ben-Yossef 			.digest = cc_mac_digest,
180563893811SGilad Ben-Yossef 			.setkey = cc_cmac_setkey,
180663893811SGilad Ben-Yossef 			.export = cc_hash_export,
180763893811SGilad Ben-Yossef 			.import = cc_hash_import,
180863893811SGilad Ben-Yossef 			.halg = {
180963893811SGilad Ben-Yossef 				.digestsize = AES_BLOCK_SIZE,
181063893811SGilad Ben-Yossef 				.statesize = CC_STATE_SIZE(AES_BLOCK_SIZE),
181163893811SGilad Ben-Yossef 			},
181263893811SGilad Ben-Yossef 		},
181363893811SGilad Ben-Yossef 		.hash_mode = DRV_HASH_NULL,
181463893811SGilad Ben-Yossef 		.hw_mode = DRV_CIPHER_CMAC,
181563893811SGilad Ben-Yossef 		.inter_digestsize = AES_BLOCK_SIZE,
181627b3b22dSGilad Ben-Yossef 		.min_hw_rev = CC_HW_REV_630,
18171c876a90SGilad Ben-Yossef 		.std_body = CC_STD_NIST,
181863893811SGilad Ben-Yossef 	},
181963893811SGilad Ben-Yossef };
182063893811SGilad Ben-Yossef 
cc_alloc_hash_alg(struct cc_hash_template * template,struct device * dev,bool keyed)182163893811SGilad Ben-Yossef static struct cc_hash_alg *cc_alloc_hash_alg(struct cc_hash_template *template,
182263893811SGilad Ben-Yossef 					     struct device *dev, bool keyed)
182363893811SGilad Ben-Yossef {
182463893811SGilad Ben-Yossef 	struct cc_hash_alg *t_crypto_alg;
182563893811SGilad Ben-Yossef 	struct crypto_alg *alg;
182663893811SGilad Ben-Yossef 	struct ahash_alg *halg;
182763893811SGilad Ben-Yossef 
182891fc6c7bSGeert Uytterhoeven 	t_crypto_alg = devm_kzalloc(dev, sizeof(*t_crypto_alg), GFP_KERNEL);
182963893811SGilad Ben-Yossef 	if (!t_crypto_alg)
183063893811SGilad Ben-Yossef 		return ERR_PTR(-ENOMEM);
183163893811SGilad Ben-Yossef 
183263893811SGilad Ben-Yossef 	t_crypto_alg->ahash_alg = template->template_ahash;
183363893811SGilad Ben-Yossef 	halg = &t_crypto_alg->ahash_alg;
183463893811SGilad Ben-Yossef 	alg = &halg->halg.base;
183563893811SGilad Ben-Yossef 
183663893811SGilad Ben-Yossef 	if (keyed) {
183763893811SGilad Ben-Yossef 		snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
183863893811SGilad Ben-Yossef 			 template->mac_name);
183963893811SGilad Ben-Yossef 		snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
184063893811SGilad Ben-Yossef 			 template->mac_driver_name);
184163893811SGilad Ben-Yossef 	} else {
184263893811SGilad Ben-Yossef 		halg->setkey = NULL;
184363893811SGilad Ben-Yossef 		snprintf(alg->cra_name, CRYPTO_MAX_ALG_NAME, "%s",
184463893811SGilad Ben-Yossef 			 template->name);
184563893811SGilad Ben-Yossef 		snprintf(alg->cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
184663893811SGilad Ben-Yossef 			 template->driver_name);
184763893811SGilad Ben-Yossef 	}
184863893811SGilad Ben-Yossef 	alg->cra_module = THIS_MODULE;
1849*07547fa7SHerbert Xu 	alg->cra_ctxsize = sizeof(struct cc_hash_ctx) + crypto_dma_padding();
185063893811SGilad Ben-Yossef 	alg->cra_priority = CC_CRA_PRIO;
185163893811SGilad Ben-Yossef 	alg->cra_blocksize = template->blocksize;
185263893811SGilad Ben-Yossef 	alg->cra_alignmask = 0;
185363893811SGilad Ben-Yossef 	alg->cra_exit = cc_cra_exit;
185463893811SGilad Ben-Yossef 
185563893811SGilad Ben-Yossef 	alg->cra_init = cc_cra_init;
18566a38f622SEric Biggers 	alg->cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_KERN_DRIVER_ONLY;
185763893811SGilad Ben-Yossef 
185863893811SGilad Ben-Yossef 	t_crypto_alg->hash_mode = template->hash_mode;
185963893811SGilad Ben-Yossef 	t_crypto_alg->hw_mode = template->hw_mode;
186063893811SGilad Ben-Yossef 	t_crypto_alg->inter_digestsize = template->inter_digestsize;
186163893811SGilad Ben-Yossef 
186263893811SGilad Ben-Yossef 	return t_crypto_alg;
186363893811SGilad Ben-Yossef }
186463893811SGilad Ben-Yossef 
cc_init_copy_sram(struct cc_drvdata * drvdata,const u32 * data,unsigned int size,u32 * sram_buff_ofs)186508884316SGeert Uytterhoeven static int cc_init_copy_sram(struct cc_drvdata *drvdata, const u32 *data,
186608884316SGeert Uytterhoeven 			     unsigned int size, u32 *sram_buff_ofs)
186708884316SGeert Uytterhoeven {
186808884316SGeert Uytterhoeven 	struct cc_hw_desc larval_seq[CC_DIGEST_SIZE_MAX / sizeof(u32)];
186908884316SGeert Uytterhoeven 	unsigned int larval_seq_len = 0;
187008884316SGeert Uytterhoeven 	int rc;
187108884316SGeert Uytterhoeven 
187208884316SGeert Uytterhoeven 	cc_set_sram_desc(data, *sram_buff_ofs, size / sizeof(*data),
187308884316SGeert Uytterhoeven 			 larval_seq, &larval_seq_len);
187408884316SGeert Uytterhoeven 	rc = send_request_init(drvdata, larval_seq, larval_seq_len);
187508884316SGeert Uytterhoeven 	if (rc)
187608884316SGeert Uytterhoeven 		return rc;
187708884316SGeert Uytterhoeven 
187808884316SGeert Uytterhoeven 	*sram_buff_ofs += size;
187908884316SGeert Uytterhoeven 	return 0;
188008884316SGeert Uytterhoeven }
188108884316SGeert Uytterhoeven 
cc_init_hash_sram(struct cc_drvdata * drvdata)188263893811SGilad Ben-Yossef int cc_init_hash_sram(struct cc_drvdata *drvdata)
188363893811SGilad Ben-Yossef {
188463893811SGilad Ben-Yossef 	struct cc_hash_handle *hash_handle = drvdata->hash_handle;
18851a895f1dSGeert Uytterhoeven 	u32 sram_buff_ofs = hash_handle->digest_len_sram_addr;
188627b3b22dSGilad Ben-Yossef 	bool large_sha_supported = (drvdata->hw_rev >= CC_HW_REV_712);
1887927574e0SYael Chemla 	bool sm3_supported = (drvdata->hw_rev >= CC_HW_REV_713);
188863893811SGilad Ben-Yossef 	int rc = 0;
188963893811SGilad Ben-Yossef 
189063893811SGilad Ben-Yossef 	/* Copy-to-sram digest-len */
189108884316SGeert Uytterhoeven 	rc = cc_init_copy_sram(drvdata, cc_digest_len_init,
189208884316SGeert Uytterhoeven 			       sizeof(cc_digest_len_init), &sram_buff_ofs);
189363893811SGilad Ben-Yossef 	if (rc)
189463893811SGilad Ben-Yossef 		goto init_digest_const_err;
189563893811SGilad Ben-Yossef 
189627b3b22dSGilad Ben-Yossef 	if (large_sha_supported) {
189763893811SGilad Ben-Yossef 		/* Copy-to-sram digest-len for sha384/512 */
189808884316SGeert Uytterhoeven 		rc = cc_init_copy_sram(drvdata, cc_digest_len_sha512_init,
189908884316SGeert Uytterhoeven 				       sizeof(cc_digest_len_sha512_init),
190008884316SGeert Uytterhoeven 				       &sram_buff_ofs);
190163893811SGilad Ben-Yossef 		if (rc)
190263893811SGilad Ben-Yossef 			goto init_digest_const_err;
190327b3b22dSGilad Ben-Yossef 	}
190463893811SGilad Ben-Yossef 
190563893811SGilad Ben-Yossef 	/* The initial digests offset */
190663893811SGilad Ben-Yossef 	hash_handle->larval_digest_sram_addr = sram_buff_ofs;
190763893811SGilad Ben-Yossef 
190863893811SGilad Ben-Yossef 	/* Copy-to-sram initial SHA* digests */
190908884316SGeert Uytterhoeven 	rc = cc_init_copy_sram(drvdata, cc_md5_init, sizeof(cc_md5_init),
191008884316SGeert Uytterhoeven 			       &sram_buff_ofs);
191163893811SGilad Ben-Yossef 	if (rc)
191263893811SGilad Ben-Yossef 		goto init_digest_const_err;
191363893811SGilad Ben-Yossef 
191408884316SGeert Uytterhoeven 	rc = cc_init_copy_sram(drvdata, cc_sha1_init, sizeof(cc_sha1_init),
191508884316SGeert Uytterhoeven 			       &sram_buff_ofs);
191663893811SGilad Ben-Yossef 	if (rc)
191763893811SGilad Ben-Yossef 		goto init_digest_const_err;
191863893811SGilad Ben-Yossef 
191908884316SGeert Uytterhoeven 	rc = cc_init_copy_sram(drvdata, cc_sha224_init, sizeof(cc_sha224_init),
192008884316SGeert Uytterhoeven 			       &sram_buff_ofs);
192163893811SGilad Ben-Yossef 	if (rc)
192263893811SGilad Ben-Yossef 		goto init_digest_const_err;
192363893811SGilad Ben-Yossef 
192408884316SGeert Uytterhoeven 	rc = cc_init_copy_sram(drvdata, cc_sha256_init, sizeof(cc_sha256_init),
192508884316SGeert Uytterhoeven 			       &sram_buff_ofs);
192663893811SGilad Ben-Yossef 	if (rc)
192763893811SGilad Ben-Yossef 		goto init_digest_const_err;
192863893811SGilad Ben-Yossef 
1929927574e0SYael Chemla 	if (sm3_supported) {
193008884316SGeert Uytterhoeven 		rc = cc_init_copy_sram(drvdata, cc_sm3_init,
193108884316SGeert Uytterhoeven 				       sizeof(cc_sm3_init), &sram_buff_ofs);
1932927574e0SYael Chemla 		if (rc)
1933927574e0SYael Chemla 			goto init_digest_const_err;
1934927574e0SYael Chemla 	}
1935927574e0SYael Chemla 
193627b3b22dSGilad Ben-Yossef 	if (large_sha_supported) {
193708884316SGeert Uytterhoeven 		rc = cc_init_copy_sram(drvdata, cc_sha384_init,
193808884316SGeert Uytterhoeven 				       sizeof(cc_sha384_init), &sram_buff_ofs);
193963893811SGilad Ben-Yossef 		if (rc)
194063893811SGilad Ben-Yossef 			goto init_digest_const_err;
194163893811SGilad Ben-Yossef 
194208884316SGeert Uytterhoeven 		rc = cc_init_copy_sram(drvdata, cc_sha512_init,
194308884316SGeert Uytterhoeven 				       sizeof(cc_sha512_init), &sram_buff_ofs);
194463893811SGilad Ben-Yossef 		if (rc)
194563893811SGilad Ben-Yossef 			goto init_digest_const_err;
194627b3b22dSGilad Ben-Yossef 	}
194763893811SGilad Ben-Yossef 
194863893811SGilad Ben-Yossef init_digest_const_err:
194963893811SGilad Ben-Yossef 	return rc;
195063893811SGilad Ben-Yossef }
195163893811SGilad Ben-Yossef 
cc_hash_alloc(struct cc_drvdata * drvdata)195263893811SGilad Ben-Yossef int cc_hash_alloc(struct cc_drvdata *drvdata)
195363893811SGilad Ben-Yossef {
195463893811SGilad Ben-Yossef 	struct cc_hash_handle *hash_handle;
19551a895f1dSGeert Uytterhoeven 	u32 sram_buff;
195663893811SGilad Ben-Yossef 	u32 sram_size_to_alloc;
195763893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(drvdata);
195863893811SGilad Ben-Yossef 	int rc = 0;
195963893811SGilad Ben-Yossef 	int alg;
196063893811SGilad Ben-Yossef 
196191fc6c7bSGeert Uytterhoeven 	hash_handle = devm_kzalloc(dev, sizeof(*hash_handle), GFP_KERNEL);
196263893811SGilad Ben-Yossef 	if (!hash_handle)
196363893811SGilad Ben-Yossef 		return -ENOMEM;
196463893811SGilad Ben-Yossef 
196563893811SGilad Ben-Yossef 	INIT_LIST_HEAD(&hash_handle->hash_list);
196663893811SGilad Ben-Yossef 	drvdata->hash_handle = hash_handle;
196763893811SGilad Ben-Yossef 
1968e55d8a75SHans de Goede 	sram_size_to_alloc = sizeof(cc_digest_len_init) +
1969e55d8a75SHans de Goede 			sizeof(cc_md5_init) +
1970e55d8a75SHans de Goede 			sizeof(cc_sha1_init) +
1971e55d8a75SHans de Goede 			sizeof(cc_sha224_init) +
1972e55d8a75SHans de Goede 			sizeof(cc_sha256_init);
197363893811SGilad Ben-Yossef 
1974927574e0SYael Chemla 	if (drvdata->hw_rev >= CC_HW_REV_713)
1975e55d8a75SHans de Goede 		sram_size_to_alloc += sizeof(cc_sm3_init);
1976927574e0SYael Chemla 
197727b3b22dSGilad Ben-Yossef 	if (drvdata->hw_rev >= CC_HW_REV_712)
1978e55d8a75SHans de Goede 		sram_size_to_alloc += sizeof(cc_digest_len_sha512_init) +
1979e55d8a75SHans de Goede 			sizeof(cc_sha384_init) + sizeof(cc_sha512_init);
198027b3b22dSGilad Ben-Yossef 
198163893811SGilad Ben-Yossef 	sram_buff = cc_sram_alloc(drvdata, sram_size_to_alloc);
198263893811SGilad Ben-Yossef 	if (sram_buff == NULL_SRAM_ADDR) {
198363893811SGilad Ben-Yossef 		rc = -ENOMEM;
198463893811SGilad Ben-Yossef 		goto fail;
198563893811SGilad Ben-Yossef 	}
198663893811SGilad Ben-Yossef 
198763893811SGilad Ben-Yossef 	/* The initial digest-len offset */
198863893811SGilad Ben-Yossef 	hash_handle->digest_len_sram_addr = sram_buff;
198963893811SGilad Ben-Yossef 
199063893811SGilad Ben-Yossef 	/*must be set before the alg registration as it is being used there*/
199163893811SGilad Ben-Yossef 	rc = cc_init_hash_sram(drvdata);
199263893811SGilad Ben-Yossef 	if (rc) {
199363893811SGilad Ben-Yossef 		dev_err(dev, "Init digest CONST failed (rc=%d)\n", rc);
199463893811SGilad Ben-Yossef 		goto fail;
199563893811SGilad Ben-Yossef 	}
199663893811SGilad Ben-Yossef 
199763893811SGilad Ben-Yossef 	/* ahash registration */
199863893811SGilad Ben-Yossef 	for (alg = 0; alg < ARRAY_SIZE(driver_hash); alg++) {
199963893811SGilad Ben-Yossef 		struct cc_hash_alg *t_alg;
200063893811SGilad Ben-Yossef 		int hw_mode = driver_hash[alg].hw_mode;
200163893811SGilad Ben-Yossef 
20021c876a90SGilad Ben-Yossef 		/* Check that the HW revision and variants are suitable */
20031c876a90SGilad Ben-Yossef 		if ((driver_hash[alg].min_hw_rev > drvdata->hw_rev) ||
20041c876a90SGilad Ben-Yossef 		    !(drvdata->std_bodies & driver_hash[alg].std_body))
200527b3b22dSGilad Ben-Yossef 			continue;
20061c876a90SGilad Ben-Yossef 
2007927574e0SYael Chemla 		if (driver_hash[alg].is_mac) {
200863893811SGilad Ben-Yossef 			/* register hmac version */
200963893811SGilad Ben-Yossef 			t_alg = cc_alloc_hash_alg(&driver_hash[alg], dev, true);
201063893811SGilad Ben-Yossef 			if (IS_ERR(t_alg)) {
201163893811SGilad Ben-Yossef 				rc = PTR_ERR(t_alg);
201263893811SGilad Ben-Yossef 				dev_err(dev, "%s alg allocation failed\n",
201363893811SGilad Ben-Yossef 					driver_hash[alg].driver_name);
201463893811SGilad Ben-Yossef 				goto fail;
201563893811SGilad Ben-Yossef 			}
201663893811SGilad Ben-Yossef 			t_alg->drvdata = drvdata;
201763893811SGilad Ben-Yossef 
201863893811SGilad Ben-Yossef 			rc = crypto_register_ahash(&t_alg->ahash_alg);
201963893811SGilad Ben-Yossef 			if (rc) {
202063893811SGilad Ben-Yossef 				dev_err(dev, "%s alg registration failed\n",
202163893811SGilad Ben-Yossef 					driver_hash[alg].driver_name);
202263893811SGilad Ben-Yossef 				goto fail;
202363893811SGilad Ben-Yossef 			}
2024ff4d719aSGeert Uytterhoeven 
2025ff4d719aSGeert Uytterhoeven 			list_add_tail(&t_alg->entry, &hash_handle->hash_list);
2026927574e0SYael Chemla 		}
202763893811SGilad Ben-Yossef 		if (hw_mode == DRV_CIPHER_XCBC_MAC ||
202863893811SGilad Ben-Yossef 		    hw_mode == DRV_CIPHER_CMAC)
202963893811SGilad Ben-Yossef 			continue;
203063893811SGilad Ben-Yossef 
203163893811SGilad Ben-Yossef 		/* register hash version */
203263893811SGilad Ben-Yossef 		t_alg = cc_alloc_hash_alg(&driver_hash[alg], dev, false);
203363893811SGilad Ben-Yossef 		if (IS_ERR(t_alg)) {
203463893811SGilad Ben-Yossef 			rc = PTR_ERR(t_alg);
203563893811SGilad Ben-Yossef 			dev_err(dev, "%s alg allocation failed\n",
203663893811SGilad Ben-Yossef 				driver_hash[alg].driver_name);
203763893811SGilad Ben-Yossef 			goto fail;
203863893811SGilad Ben-Yossef 		}
203963893811SGilad Ben-Yossef 		t_alg->drvdata = drvdata;
204063893811SGilad Ben-Yossef 
204163893811SGilad Ben-Yossef 		rc = crypto_register_ahash(&t_alg->ahash_alg);
204263893811SGilad Ben-Yossef 		if (rc) {
204363893811SGilad Ben-Yossef 			dev_err(dev, "%s alg registration failed\n",
204463893811SGilad Ben-Yossef 				driver_hash[alg].driver_name);
204563893811SGilad Ben-Yossef 			goto fail;
204663893811SGilad Ben-Yossef 		}
2047ff4d719aSGeert Uytterhoeven 
2048ff4d719aSGeert Uytterhoeven 		list_add_tail(&t_alg->entry, &hash_handle->hash_list);
204963893811SGilad Ben-Yossef 	}
205063893811SGilad Ben-Yossef 
205163893811SGilad Ben-Yossef 	return 0;
205263893811SGilad Ben-Yossef 
205363893811SGilad Ben-Yossef fail:
205491fc6c7bSGeert Uytterhoeven 	cc_hash_free(drvdata);
205563893811SGilad Ben-Yossef 	return rc;
205663893811SGilad Ben-Yossef }
205763893811SGilad Ben-Yossef 
cc_hash_free(struct cc_drvdata * drvdata)205863893811SGilad Ben-Yossef int cc_hash_free(struct cc_drvdata *drvdata)
205963893811SGilad Ben-Yossef {
206063893811SGilad Ben-Yossef 	struct cc_hash_alg *t_hash_alg, *hash_n;
206163893811SGilad Ben-Yossef 	struct cc_hash_handle *hash_handle = drvdata->hash_handle;
206263893811SGilad Ben-Yossef 
206391fc6c7bSGeert Uytterhoeven 	list_for_each_entry_safe(t_hash_alg, hash_n, &hash_handle->hash_list,
206491fc6c7bSGeert Uytterhoeven 				 entry) {
206563893811SGilad Ben-Yossef 		crypto_unregister_ahash(&t_hash_alg->ahash_alg);
206663893811SGilad Ben-Yossef 		list_del(&t_hash_alg->entry);
206763893811SGilad Ben-Yossef 	}
206863893811SGilad Ben-Yossef 
206963893811SGilad Ben-Yossef 	return 0;
207063893811SGilad Ben-Yossef }
207163893811SGilad Ben-Yossef 
cc_setup_xcbc(struct ahash_request * areq,struct cc_hw_desc desc[],unsigned int * seq_size)207263893811SGilad Ben-Yossef static void cc_setup_xcbc(struct ahash_request *areq, struct cc_hw_desc desc[],
207363893811SGilad Ben-Yossef 			  unsigned int *seq_size)
207463893811SGilad Ben-Yossef {
207563893811SGilad Ben-Yossef 	unsigned int idx = *seq_size;
2076*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(areq);
207763893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2078*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
207963893811SGilad Ben-Yossef 
208063893811SGilad Ben-Yossef 	/* Setup XCBC MAC K1 */
208163893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
208263893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI, (ctx->opad_tmp_keys_dma_addr +
208363893811SGilad Ben-Yossef 					    XCBC_MAC_K1_OFFSET),
208463893811SGilad Ben-Yossef 		     CC_AES_128_BIT_KEY_SIZE, NS_BIT);
208563893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
208618a1dc1fSYael Chemla 	set_hash_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC, ctx->hash_mode);
208763893811SGilad Ben-Yossef 	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
208863893811SGilad Ben-Yossef 	set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
208963893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_AES);
209063893811SGilad Ben-Yossef 	idx++;
209163893811SGilad Ben-Yossef 
209263893811SGilad Ben-Yossef 	/* Setup XCBC MAC K2 */
209363893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
209463893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI,
209563893811SGilad Ben-Yossef 		     (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K2_OFFSET),
209663893811SGilad Ben-Yossef 		     CC_AES_128_BIT_KEY_SIZE, NS_BIT);
209763893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_STATE1);
209863893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
209963893811SGilad Ben-Yossef 	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
210063893811SGilad Ben-Yossef 	set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
210163893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_AES);
210263893811SGilad Ben-Yossef 	idx++;
210363893811SGilad Ben-Yossef 
210463893811SGilad Ben-Yossef 	/* Setup XCBC MAC K3 */
210563893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
210663893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI,
210763893811SGilad Ben-Yossef 		     (ctx->opad_tmp_keys_dma_addr + XCBC_MAC_K3_OFFSET),
210863893811SGilad Ben-Yossef 		     CC_AES_128_BIT_KEY_SIZE, NS_BIT);
210963893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_STATE2);
211063893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
211163893811SGilad Ben-Yossef 	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
211263893811SGilad Ben-Yossef 	set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
211363893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_AES);
211463893811SGilad Ben-Yossef 	idx++;
211563893811SGilad Ben-Yossef 
211663893811SGilad Ben-Yossef 	/* Loading MAC state */
211763893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
211863893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
211963893811SGilad Ben-Yossef 		     CC_AES_BLOCK_SIZE, NS_BIT);
212063893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
212163893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], DRV_CIPHER_XCBC_MAC);
212263893811SGilad Ben-Yossef 	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
212363893811SGilad Ben-Yossef 	set_key_size_aes(&desc[idx], CC_AES_128_BIT_KEY_SIZE);
212463893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_AES);
212563893811SGilad Ben-Yossef 	idx++;
212663893811SGilad Ben-Yossef 	*seq_size = idx;
212763893811SGilad Ben-Yossef }
212863893811SGilad Ben-Yossef 
cc_setup_cmac(struct ahash_request * areq,struct cc_hw_desc desc[],unsigned int * seq_size)212963893811SGilad Ben-Yossef static void cc_setup_cmac(struct ahash_request *areq, struct cc_hw_desc desc[],
213063893811SGilad Ben-Yossef 			  unsigned int *seq_size)
213163893811SGilad Ben-Yossef {
213263893811SGilad Ben-Yossef 	unsigned int idx = *seq_size;
2133*07547fa7SHerbert Xu 	struct ahash_req_ctx *state = ahash_request_ctx_dma(areq);
213463893811SGilad Ben-Yossef 	struct crypto_ahash *tfm = crypto_ahash_reqtfm(areq);
2135*07547fa7SHerbert Xu 	struct cc_hash_ctx *ctx = crypto_ahash_ctx_dma(tfm);
213663893811SGilad Ben-Yossef 
213763893811SGilad Ben-Yossef 	/* Setup CMAC Key */
213863893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
213963893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI, ctx->opad_tmp_keys_dma_addr,
214063893811SGilad Ben-Yossef 		     ((ctx->key_params.keylen == 24) ? AES_MAX_KEY_SIZE :
214163893811SGilad Ben-Yossef 		      ctx->key_params.keylen), NS_BIT);
214263893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_KEY0);
214363893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
214463893811SGilad Ben-Yossef 	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
214563893811SGilad Ben-Yossef 	set_key_size_aes(&desc[idx], ctx->key_params.keylen);
214663893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_AES);
214763893811SGilad Ben-Yossef 	idx++;
214863893811SGilad Ben-Yossef 
214963893811SGilad Ben-Yossef 	/* Load MAC state */
215063893811SGilad Ben-Yossef 	hw_desc_init(&desc[idx]);
215163893811SGilad Ben-Yossef 	set_din_type(&desc[idx], DMA_DLLI, state->digest_buff_dma_addr,
215263893811SGilad Ben-Yossef 		     CC_AES_BLOCK_SIZE, NS_BIT);
215363893811SGilad Ben-Yossef 	set_setup_mode(&desc[idx], SETUP_LOAD_STATE0);
215463893811SGilad Ben-Yossef 	set_cipher_mode(&desc[idx], DRV_CIPHER_CMAC);
215563893811SGilad Ben-Yossef 	set_cipher_config0(&desc[idx], DESC_DIRECTION_ENCRYPT_ENCRYPT);
215663893811SGilad Ben-Yossef 	set_key_size_aes(&desc[idx], ctx->key_params.keylen);
215763893811SGilad Ben-Yossef 	set_flow_mode(&desc[idx], S_DIN_to_AES);
215863893811SGilad Ben-Yossef 	idx++;
215963893811SGilad Ben-Yossef 	*seq_size = idx;
216063893811SGilad Ben-Yossef }
216163893811SGilad Ben-Yossef 
cc_set_desc(struct ahash_req_ctx * areq_ctx,struct cc_hash_ctx * ctx,unsigned int flow_mode,struct cc_hw_desc desc[],bool is_not_last_data,unsigned int * seq_size)216263893811SGilad Ben-Yossef static void cc_set_desc(struct ahash_req_ctx *areq_ctx,
216363893811SGilad Ben-Yossef 			struct cc_hash_ctx *ctx, unsigned int flow_mode,
216463893811SGilad Ben-Yossef 			struct cc_hw_desc desc[], bool is_not_last_data,
216563893811SGilad Ben-Yossef 			unsigned int *seq_size)
216663893811SGilad Ben-Yossef {
216763893811SGilad Ben-Yossef 	unsigned int idx = *seq_size;
216863893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(ctx->drvdata);
216963893811SGilad Ben-Yossef 
217063893811SGilad Ben-Yossef 	if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_DLLI) {
217163893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
217263893811SGilad Ben-Yossef 		set_din_type(&desc[idx], DMA_DLLI,
217363893811SGilad Ben-Yossef 			     sg_dma_address(areq_ctx->curr_sg),
217463893811SGilad Ben-Yossef 			     areq_ctx->curr_sg->length, NS_BIT);
217563893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], flow_mode);
217663893811SGilad Ben-Yossef 		idx++;
217763893811SGilad Ben-Yossef 	} else {
217863893811SGilad Ben-Yossef 		if (areq_ctx->data_dma_buf_type == CC_DMA_BUF_NULL) {
217963893811SGilad Ben-Yossef 			dev_dbg(dev, " NULL mode\n");
218063893811SGilad Ben-Yossef 			/* nothing to build */
218163893811SGilad Ben-Yossef 			return;
218263893811SGilad Ben-Yossef 		}
218363893811SGilad Ben-Yossef 		/* bypass */
218463893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
218563893811SGilad Ben-Yossef 		set_din_type(&desc[idx], DMA_DLLI,
218663893811SGilad Ben-Yossef 			     areq_ctx->mlli_params.mlli_dma_addr,
218763893811SGilad Ben-Yossef 			     areq_ctx->mlli_params.mlli_len, NS_BIT);
218863893811SGilad Ben-Yossef 		set_dout_sram(&desc[idx], ctx->drvdata->mlli_sram_addr,
218963893811SGilad Ben-Yossef 			      areq_ctx->mlli_params.mlli_len);
219063893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], BYPASS);
219163893811SGilad Ben-Yossef 		idx++;
219263893811SGilad Ben-Yossef 		/* process */
219363893811SGilad Ben-Yossef 		hw_desc_init(&desc[idx]);
219463893811SGilad Ben-Yossef 		set_din_type(&desc[idx], DMA_MLLI,
219563893811SGilad Ben-Yossef 			     ctx->drvdata->mlli_sram_addr,
219663893811SGilad Ben-Yossef 			     areq_ctx->mlli_nents, NS_BIT);
219763893811SGilad Ben-Yossef 		set_flow_mode(&desc[idx], flow_mode);
219863893811SGilad Ben-Yossef 		idx++;
219963893811SGilad Ben-Yossef 	}
220063893811SGilad Ben-Yossef 	if (is_not_last_data)
220163893811SGilad Ben-Yossef 		set_din_not_last_indication(&desc[(idx - 1)]);
220263893811SGilad Ben-Yossef 	/* return updated desc sequence size */
220363893811SGilad Ben-Yossef 	*seq_size = idx;
220463893811SGilad Ben-Yossef }
220563893811SGilad Ben-Yossef 
cc_larval_digest(struct device * dev,u32 mode)220663893811SGilad Ben-Yossef static const void *cc_larval_digest(struct device *dev, u32 mode)
220763893811SGilad Ben-Yossef {
220863893811SGilad Ben-Yossef 	switch (mode) {
220963893811SGilad Ben-Yossef 	case DRV_HASH_MD5:
2210e55d8a75SHans de Goede 		return cc_md5_init;
221163893811SGilad Ben-Yossef 	case DRV_HASH_SHA1:
2212e55d8a75SHans de Goede 		return cc_sha1_init;
221363893811SGilad Ben-Yossef 	case DRV_HASH_SHA224:
2214e55d8a75SHans de Goede 		return cc_sha224_init;
221563893811SGilad Ben-Yossef 	case DRV_HASH_SHA256:
2216e55d8a75SHans de Goede 		return cc_sha256_init;
221763893811SGilad Ben-Yossef 	case DRV_HASH_SHA384:
2218e55d8a75SHans de Goede 		return cc_sha384_init;
221963893811SGilad Ben-Yossef 	case DRV_HASH_SHA512:
2220e55d8a75SHans de Goede 		return cc_sha512_init;
2221927574e0SYael Chemla 	case DRV_HASH_SM3:
2222e55d8a75SHans de Goede 		return cc_sm3_init;
222363893811SGilad Ben-Yossef 	default:
222463893811SGilad Ben-Yossef 		dev_err(dev, "Invalid hash mode (%d)\n", mode);
2225e55d8a75SHans de Goede 		return cc_md5_init;
222663893811SGilad Ben-Yossef 	}
222763893811SGilad Ben-Yossef }
222863893811SGilad Ben-Yossef 
2229dc16c9f7SGeert Uytterhoeven /**
2230dc16c9f7SGeert Uytterhoeven  * cc_larval_digest_addr() - Get the address of the initial digest in SRAM
223163893811SGilad Ben-Yossef  * according to the given hash mode
223263893811SGilad Ben-Yossef  *
2233dc16c9f7SGeert Uytterhoeven  * @drvdata: Associated device driver context
2234dc16c9f7SGeert Uytterhoeven  * @mode: The Hash mode. Supported modes: MD5/SHA1/SHA224/SHA256
223563893811SGilad Ben-Yossef  *
2236dc16c9f7SGeert Uytterhoeven  * Return:
2237dc16c9f7SGeert Uytterhoeven  * The address of the initial digest in SRAM
223863893811SGilad Ben-Yossef  */
cc_larval_digest_addr(void * drvdata,u32 mode)22391a895f1dSGeert Uytterhoeven u32 cc_larval_digest_addr(void *drvdata, u32 mode)
224063893811SGilad Ben-Yossef {
224163893811SGilad Ben-Yossef 	struct cc_drvdata *_drvdata = (struct cc_drvdata *)drvdata;
224263893811SGilad Ben-Yossef 	struct cc_hash_handle *hash_handle = _drvdata->hash_handle;
224363893811SGilad Ben-Yossef 	struct device *dev = drvdata_to_dev(_drvdata);
2244927574e0SYael Chemla 	bool sm3_supported = (_drvdata->hw_rev >= CC_HW_REV_713);
22451a895f1dSGeert Uytterhoeven 	u32 addr;
224663893811SGilad Ben-Yossef 
224763893811SGilad Ben-Yossef 	switch (mode) {
224863893811SGilad Ben-Yossef 	case DRV_HASH_NULL:
224963893811SGilad Ben-Yossef 		break; /*Ignore*/
225063893811SGilad Ben-Yossef 	case DRV_HASH_MD5:
225163893811SGilad Ben-Yossef 		return (hash_handle->larval_digest_sram_addr);
225263893811SGilad Ben-Yossef 	case DRV_HASH_SHA1:
225363893811SGilad Ben-Yossef 		return (hash_handle->larval_digest_sram_addr +
2254e55d8a75SHans de Goede 			sizeof(cc_md5_init));
225563893811SGilad Ben-Yossef 	case DRV_HASH_SHA224:
225663893811SGilad Ben-Yossef 		return (hash_handle->larval_digest_sram_addr +
2257e55d8a75SHans de Goede 			sizeof(cc_md5_init) +
2258e55d8a75SHans de Goede 			sizeof(cc_sha1_init));
225963893811SGilad Ben-Yossef 	case DRV_HASH_SHA256:
226063893811SGilad Ben-Yossef 		return (hash_handle->larval_digest_sram_addr +
2261e55d8a75SHans de Goede 			sizeof(cc_md5_init) +
2262e55d8a75SHans de Goede 			sizeof(cc_sha1_init) +
2263e55d8a75SHans de Goede 			sizeof(cc_sha224_init));
2264927574e0SYael Chemla 	case DRV_HASH_SM3:
226563893811SGilad Ben-Yossef 		return (hash_handle->larval_digest_sram_addr +
2266e55d8a75SHans de Goede 			sizeof(cc_md5_init) +
2267e55d8a75SHans de Goede 			sizeof(cc_sha1_init) +
2268e55d8a75SHans de Goede 			sizeof(cc_sha224_init) +
2269e55d8a75SHans de Goede 			sizeof(cc_sha256_init));
2270927574e0SYael Chemla 	case DRV_HASH_SHA384:
2271927574e0SYael Chemla 		addr = (hash_handle->larval_digest_sram_addr +
2272e55d8a75SHans de Goede 			sizeof(cc_md5_init) +
2273e55d8a75SHans de Goede 			sizeof(cc_sha1_init) +
2274e55d8a75SHans de Goede 			sizeof(cc_sha224_init) +
2275e55d8a75SHans de Goede 			sizeof(cc_sha256_init));
2276927574e0SYael Chemla 		if (sm3_supported)
2277e55d8a75SHans de Goede 			addr += sizeof(cc_sm3_init);
2278927574e0SYael Chemla 		return addr;
227963893811SGilad Ben-Yossef 	case DRV_HASH_SHA512:
2280927574e0SYael Chemla 		addr = (hash_handle->larval_digest_sram_addr +
2281e55d8a75SHans de Goede 			sizeof(cc_md5_init) +
2282e55d8a75SHans de Goede 			sizeof(cc_sha1_init) +
2283e55d8a75SHans de Goede 			sizeof(cc_sha224_init) +
2284e55d8a75SHans de Goede 			sizeof(cc_sha256_init) +
2285e55d8a75SHans de Goede 			sizeof(cc_sha384_init));
2286927574e0SYael Chemla 		if (sm3_supported)
2287e55d8a75SHans de Goede 			addr += sizeof(cc_sm3_init);
2288927574e0SYael Chemla 		return addr;
228963893811SGilad Ben-Yossef 	default:
229063893811SGilad Ben-Yossef 		dev_err(dev, "Invalid hash mode (%d)\n", mode);
229163893811SGilad Ben-Yossef 	}
229263893811SGilad Ben-Yossef 
229363893811SGilad Ben-Yossef 	/*This is valid wrong value to avoid kernel crash*/
229463893811SGilad Ben-Yossef 	return hash_handle->larval_digest_sram_addr;
229563893811SGilad Ben-Yossef }
229663893811SGilad Ben-Yossef 
cc_digest_len_addr(void * drvdata,u32 mode)22971a895f1dSGeert Uytterhoeven u32 cc_digest_len_addr(void *drvdata, u32 mode)
229863893811SGilad Ben-Yossef {
229963893811SGilad Ben-Yossef 	struct cc_drvdata *_drvdata = (struct cc_drvdata *)drvdata;
230063893811SGilad Ben-Yossef 	struct cc_hash_handle *hash_handle = _drvdata->hash_handle;
23011a895f1dSGeert Uytterhoeven 	u32 digest_len_addr = hash_handle->digest_len_sram_addr;
230263893811SGilad Ben-Yossef 
230363893811SGilad Ben-Yossef 	switch (mode) {
230463893811SGilad Ben-Yossef 	case DRV_HASH_SHA1:
230563893811SGilad Ben-Yossef 	case DRV_HASH_SHA224:
230663893811SGilad Ben-Yossef 	case DRV_HASH_SHA256:
230763893811SGilad Ben-Yossef 	case DRV_HASH_MD5:
230863893811SGilad Ben-Yossef 		return digest_len_addr;
230963893811SGilad Ben-Yossef 	case DRV_HASH_SHA384:
231063893811SGilad Ben-Yossef 	case DRV_HASH_SHA512:
2311e55d8a75SHans de Goede 		return  digest_len_addr + sizeof(cc_digest_len_init);
231263893811SGilad Ben-Yossef 	default:
231363893811SGilad Ben-Yossef 		return digest_len_addr; /*to avoid kernel crash*/
231463893811SGilad Ben-Yossef 	}
231563893811SGilad Ben-Yossef }
2316