nxp:driver for crypto h/w accelerator caam

NXP has hardware crypto accelerator called CAAM.
- Work with Job ring
- Jobs are submitted to CAAM in the form of 64 word
  descriptor.

Signed-off-by: Ruchika Gupta <ruchika.gupta@nxp.com>
Signed-off-by: Pankaj Gupta <pankaj.gupta@nxp.com>
Change-Id: I02bcfce68143b8630e1833a74c4b126972f4323d
diff --git a/drivers/nxp/crypto/caam/src/auth/hash.c b/drivers/nxp/crypto/caam/src/auth/hash.c
new file mode 100644
index 0000000..1665df1
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/auth/hash.c
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <arch_helpers.h>
+#include "caam.h"
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+
+#include "hash.h"
+#include "jobdesc.h"
+#include "sec_hw_specific.h"
+
+/* Since no Allocator is available . Taking a global static ctx.
+ * This would mean that only one active ctx can be there at a time.
+ */
+
+static struct hash_ctx glbl_ctx;
+
+static void hash_done(uint32_t *desc, uint32_t status, void *arg,
+		      void *job_ring)
+{
+	INFO("Hash Desc SUCCESS with status %x\n", status);
+}
+
+/***************************************************************************
+ * Function	: hash_init
+ * Arguments	: ctx - SHA context
+ * Return	: init,
+ * Description	: This function initializes the context for SHA calculation
+ ***************************************************************************/
+int hash_init(enum hash_algo algo, void **ctx)
+{
+	if (glbl_ctx.active == false) {
+		memset(&glbl_ctx, 0, sizeof(struct hash_ctx));
+		glbl_ctx.active = true;
+		glbl_ctx.algo = algo;
+		*ctx = &glbl_ctx;
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+/***************************************************************************
+ * Function	: hash_update
+ * Arguments	: ctx - SHA context
+ *		  buffer - Data
+ *		  length - Length
+ * Return	: -1 on error
+ *		  0 on SUCCESS
+ * Description	: This function creates SG entry of the data provided
+ ***************************************************************************/
+int hash_update(enum hash_algo algo, void *context, void *data_ptr,
+		unsigned int data_len)
+{
+	struct hash_ctx *ctx = context;
+	/* MAX_SG would be MAX_SG_ENTRIES + key + hdr + sg table */
+	if (ctx->sg_num >= MAX_SG) {
+		ERROR("Reached limit for calling %s\n", __func__);
+		ctx->active = false;
+		return -EINVAL;
+
+	}
+
+	if (ctx->algo != algo) {
+		ERROR("ctx for algo not correct\n");
+		ctx->active = false;
+		return -EINVAL;
+	}
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+	flush_dcache_range((uintptr_t)data_ptr, data_len);
+	dmbsy();
+#endif
+
+#ifdef CONFIG_PHYS_64BIT
+	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi,
+		  (uint32_t) ((uintptr_t) data_ptr >> 32));
+#else
+	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0);
+#endif
+	sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uintptr_t) data_ptr);
+
+	sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag,
+		  (data_len & SG_ENTRY_LENGTH_MASK));
+
+	ctx->sg_num++;
+
+	ctx->len += data_len;
+
+	return 0;
+}
+
+/***************************************************************************
+ * Function	: hash_final
+ * Arguments	: ctx - SHA context
+ * Return	: SUCCESS or FAILURE
+ * Description	: This function sets the final bit and enqueues the decriptor
+ ***************************************************************************/
+int hash_final(enum hash_algo algo, void *context, void *hash_ptr,
+	       unsigned int hash_len)
+{
+	int ret = 0;
+	struct hash_ctx *ctx = context;
+	uint32_t final = 0U;
+
+	struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE);
+
+	jobdesc.arg = NULL;
+	jobdesc.callback = hash_done;
+
+	if (ctx->algo != algo) {
+		ERROR("ctx for algo not correct\n");
+		ctx->active = false;
+		return -EINVAL;
+	}
+
+	final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) |
+	    SG_ENTRY_FINAL_BIT;
+	sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final);
+
+	dsb();
+
+	/* create the hw_rng descriptor */
+	cnstr_hash_jobdesc(jobdesc.desc, (uint8_t *) ctx->sg_tbl,
+			   ctx->len, hash_ptr);
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+	flush_dcache_range((uintptr_t)ctx->sg_tbl,
+			   (sizeof(struct sg_entry) * MAX_SG));
+	inv_dcache_range((uintptr_t)hash_ptr, hash_len);
+
+	dmbsy();
+#endif
+
+	/* Finally, generate the requested random data bytes */
+	ret = run_descriptor_jr(&jobdesc);
+	if (ret != 0) {
+		ERROR("Error in running descriptor\n");
+		ret = -1;
+	}
+	ctx->active = false;
+	return ret;
+}