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/caam.mk b/drivers/nxp/crypto/caam/caam.mk
new file mode 100644
index 0000000..548c7b1
--- /dev/null
+++ b/drivers/nxp/crypto/caam/caam.mk
@@ -0,0 +1,28 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+ifeq (${ADD_CAAM},)
+
+ADD_CAAM		:= 1
+CAAM_DRIVER_PATH	:= drivers/nxp/crypto/caam
+
+CAAM_DRIVER_SOURCES	+=  $(wildcard $(CAAM_DRIVER_PATH)/src/*.c)
+
+PLAT_INCLUDES		+= -I$(CAAM_DRIVER_PATH)/include
+
+ifeq (${BL_COMM_CRYPTO_NEEDED},yes)
+BL_COMMON_SOURCES	+= ${CAAM_DRIVER_SOURCES}
+else
+ifeq (${BL2_CRYPTO_NEEDED},yes)
+BL2_SOURCES		+= ${CAAM_DRIVER_SOURCES}
+endif
+ifeq (${BL31_CRYPTO_NEEDED},yes)
+BL31_SOURCES		+= ${CAAM_DRIVER_SOURCES}
+endif
+endif
+
+endif
diff --git a/drivers/nxp/crypto/caam/include/caam.h b/drivers/nxp/crypto/caam/include/caam.h
new file mode 100644
index 0000000..580e133
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/caam.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_H
+#define CAAM_H
+
+#include "caam_io.h"
+#include "sec_jr_driver.h"
+
+
+/* Job ring 3 is reserved for usage by sec firmware */
+#define DEFAULT_JR	3
+
+#if defined(CONFIG_CHASSIS_3_2) || defined(CONFIG_CHASSIS_2)
+#define CAAM_JR0_OFFSET			0x10000
+#define CAAM_JR1_OFFSET			0x20000
+#define CAAM_JR2_OFFSET			0x30000
+#define CAAM_JR3_OFFSET			0x40000
+#endif
+
+enum sig_alg {
+	RSA,
+	ECC
+};
+
+/* This function does basic SEC Initialization */
+int sec_init(uintptr_t nxp_caam_addr);
+int config_sec_block(void);
+uintptr_t get_caam_addr(void);
+
+/* This function is used to submit jobs to JR */
+int run_descriptor_jr(struct job_descriptor *desc);
+
+/* This function is used to instatiate the HW RNG is already not instantiated */
+int hw_rng_instantiate(void);
+
+/* This function is used to return random bytes of byte_len from HW RNG */
+int get_rand_bytes_hw(uint8_t *bytes, int byte_len);
+
+/* This function is used to set the hw unique key from HW CAAM */
+int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size);
+
+/* This function is used to fetch random number from
+ * CAAM of length either of 4 bytes or 8 bytes depending
+ * rngWidth value.
+ */
+unsigned long long get_random(int rngWidth);
+
+#endif /* CAAM_H */
diff --git a/drivers/nxp/crypto/caam/include/caam_io.h b/drivers/nxp/crypto/caam/include/caam_io.h
new file mode 100644
index 0000000..4fdb04d
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/caam_io.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_IO_H
+#define CAAM_IO_H
+
+#include <endian.h>
+#include <lib/mmio.h>
+
+typedef unsigned long long phys_addr_t;
+typedef unsigned long long phys_size_t;
+
+/* Return higher 32 bits of physical address */
+#define PHYS_ADDR_HI(phys_addr) \
+	    (uint32_t)(((uint64_t)phys_addr) >> 32)
+
+/* Return lower 32 bits of physical address */
+#define PHYS_ADDR_LO(phys_addr) \
+	    (uint32_t)(((uint64_t)phys_addr) & 0xFFFFFFFF)
+
+#ifdef NXP_SEC_BE
+#define sec_in32(a)	bswap32(mmio_read_32((uintptr_t)(a)))
+#define sec_out32(a, v)	mmio_write_32((uintptr_t)(a), bswap32(v))
+#define sec_in64(addr)  (					\
+	((uint64_t)sec_in32((uintptr_t)(addr)) << 32) |	\
+	(sec_in32(((uintptr_t)(addr)) + 4)))
+#define sec_out64(addr, val) ({					\
+	sec_out32(((uintptr_t)(addr)), (uint32_t)((val) >> 32));	\
+	sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)(val)); })
+#elif defined(NXP_SEC_LE)
+#define sec_in32(a)	mmio_read_32((uintptr_t)(a))
+#define sec_out32(a, v)	mmio_write_32((uintptr_t)(a), (v))
+#define sec_in64(addr)	(					\
+	((uint64_t)sec_in32((uintptr_t)(addr) + 4) << 32) |	\
+	(sec_in32((uintptr_t)(addr))))
+#define sec_out64(addr, val) ({						\
+	sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)((val) >> 32));	\
+	sec_out32(((uintptr_t)(addr)), (uint32_t)(val)); })
+#else
+#error Please define CCSR SEC register endianness
+#endif
+
+static inline void *ptov(phys_addr_t *ptr)
+{
+	return (void *)ptr;
+}
+
+static inline phys_addr_t *vtop(void *ptr)
+{
+	return (phys_addr_t *)ptr;
+}
+#endif /* CAAM_IO_H */
diff --git a/drivers/nxp/crypto/caam/include/hash.h b/drivers/nxp/crypto/caam/include/hash.h
new file mode 100644
index 0000000..946087d
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/hash.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __HASH_H__
+#define __HASH_H__
+
+#include <stdbool.h>
+
+/* List of hash algorithms */
+enum hash_algo {
+	SHA1 = 0,
+	SHA256
+};
+
+/* number of bytes in the SHA256-256 digest */
+#define SHA256_DIGEST_SIZE 32
+
+/*
+ * number of words in the digest - Digest is kept internally
+ * as 8 32-bit words
+ */
+#define _SHA256_DIGEST_LENGTH 8
+
+/*
+ * block length - A block, treated as a sequence of
+ * 32-bit words
+ */
+#define SHA256_BLOCK_LENGTH 16
+
+/* number of bytes in the block */
+#define SHA256_DATA_SIZE 64
+
+#define MAX_SG		12
+
+struct sg_entry {
+#if defined(NXP_SEC_LE)
+	uint32_t addr_lo;	/* Memory Address - lo */
+	uint32_t addr_hi;	/* Memory Address of start of buffer - hi */
+#else
+	uint32_t addr_hi;	/* Memory Address of start of buffer - hi */
+	uint32_t addr_lo;	/* Memory Address - lo */
+#endif
+
+	uint32_t len_flag;	/* Length of the data in the frame */
+#define SG_ENTRY_LENGTH_MASK	0x3FFFFFFF
+#define SG_ENTRY_EXTENSION_BIT	0x80000000
+#define SG_ENTRY_FINAL_BIT	0x40000000
+	uint32_t bpid_offset;
+#define SG_ENTRY_BPID_MASK	0x00FF0000
+#define SG_ENTRY_BPID_SHIFT	16
+#define SG_ENTRY_OFFSET_MASK	0x00001FFF
+#define SG_ENTRY_OFFSET_SHIFT	0
+};
+
+/*
+ * SHA256-256 context
+ * contain the following fields
+ * State
+ * count low
+ * count high
+ * block data buffer
+ * index to the buffer
+ */
+struct hash_ctx {
+	struct sg_entry sg_tbl[MAX_SG];
+	uint32_t hash_desc[64];
+	uint8_t hash[SHA256_DIGEST_SIZE];
+	uint32_t sg_num;
+	uint32_t len;
+	uint8_t *data;
+	enum hash_algo algo;
+	bool active;
+};
+
+int hash_init(enum hash_algo algo, void **ctx);
+int hash_update(enum hash_algo algo, void *context, void *data_ptr,
+		unsigned int data_len);
+int hash_final(enum hash_algo algo, void *context, void *hash_ptr,
+	       unsigned int hash_len);
+
+#endif
diff --git a/drivers/nxp/crypto/caam/include/jobdesc.h b/drivers/nxp/crypto/caam/include/jobdesc.h
new file mode 100644
index 0000000..5921f7b
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/jobdesc.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __JOBDESC_H
+#define __JOBDESC_H
+
+#include <rsa.h>
+
+#define DESC_LEN_MASK		0x7f
+#define DESC_START_SHIFT	16
+
+#define KEY_BLOB_SIZE 32
+#define MAC_SIZE 16
+
+#define KEY_IDNFR_SZ_BYTES 16
+#define CLASS_SHIFT 25
+#define CLASS_2	(0x02 << CLASS_SHIFT)
+
+#define CMD_SHIFT		27
+#define CMD_OPERATION		(U(0x10) << CMD_SHIFT)
+
+#define OP_TYPE_SHIFT		24
+#define OP_TYPE_ENCAP_PROTOCOL	(0x07 << OP_TYPE_SHIFT)
+
+/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */
+#define OP_PCLID_SHIFT		16
+#define OP_PCLID_BLOB		(0x0d << OP_PCLID_SHIFT)
+
+#define BLOB_PROTO_INFO		 0x00000002
+
+uint32_t desc_length(uint32_t *desc);
+
+int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle,
+		      uint32_t *add_inp, uint32_t add_ip_len,
+		      uint8_t *out_data, uint32_t len);
+
+int cnstr_rng_instantiate_jobdesc(uint32_t *desc);
+
+/* Construct descriptor to generate hw key blob */
+int cnstr_hw_encap_blob_jobdesc(uint32_t *desc,
+				uint8_t *key_idnfr, uint32_t key_sz,
+				uint32_t key_class, uint8_t *plain_txt,
+				uint32_t in_sz, uint8_t *enc_blob,
+				uint32_t out_sz, uint32_t operation);
+
+void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz,
+			uint8_t *digest);
+
+void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
+			       struct pk_in_params *pkin, uint8_t *out,
+			       uint32_t out_siz);
+#endif
diff --git a/drivers/nxp/crypto/caam/include/jr_driver_config.h b/drivers/nxp/crypto/caam/include/jr_driver_config.h
new file mode 100644
index 0000000..f25c42e
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/jr_driver_config.h
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _JR_DRIVER_CONFIG_H_
+#define _JR_DRIVER_CONFIG_H_
+
+/* Helper defines  */
+
+ /* Define used for setting a flag on  */
+#define  ON  1
+ /* Define used for setting a flag off  */
+#define  OFF 0
+
+ /* SEC is configured to start work in polling mode,  */
+#define SEC_STARTUP_POLLING_MODE     0
+/*
+ * SEC is configured to start work in interrupt mode,
+ *  when configured for NAPI notification style.
+ */
+#define SEC_STARTUP_INTERRUPT_MODE   1
+
+/*
+ * SEC driver will use ONLY interrupts to receive notifications
+ * for processed packets from SEC engine hardware.
+ */
+#define SEC_NOTIFICATION_TYPE_IRQ   1
+/*
+ * SEC driver will use ONLY polling to receive notifications
+ * for processed packets from SEC engine hardware.
+ */
+#define SEC_NOTIFICATION_TYPE_POLL  2
+
+/*
+ * Determines how SEC user space driver will receive notifications
+ * for processed packets from SEC engine.
+ * Valid values are: #SEC_NOTIFICATION_TYPE_POLL, #SEC_NOTIFICATION_TYPE_IRQ
+ */
+#define SEC_NOTIFICATION_TYPE   SEC_NOTIFICATION_TYPE_POLL
+
+ /* Maximum number of job rings supported by SEC hardware  */
+#define MAX_SEC_JOB_RINGS         1
+
+/*
+ * Size of cryptographic context that is used directly in communicating
+ *  with SEC device.
+ *  SEC device works only with physical addresses. This is the maximum size
+ *  for a SEC descriptor ( = 64 words).
+ */
+
+#define SEC_CRYPTO_DESCRIPTOR_SIZE  256
+
+/*
+ * Size of job descriptor submitted to SEC device for each packet to be
+ *  processed.
+ *  Job descriptor contains 3 DMA address pointers:
+ *      - to shared descriptor, to input buffer and to output buffer.
+ *  The job descriptor contains other SEC specific commands as well:
+ *      - HEADER command, SEQ IN PTR command SEQ OUT PTR command and opaque
+ *        data, each measuring 4 bytes.
+ *  Job descriptor size, depending on physical address representation:
+ *      - 32 bit - size is 28 bytes - cacheline-aligned size is 64 bytes
+ *      - 36 bit - size is 40 bytes - cacheline-aligned size is 64 bytes
+ *  @note: Job descriptor must be cacheline-aligned to ensure efficient memory
+ *  access.
+ *  @note: If other format is used for job descriptor, then the size must be
+ *  revised.
+ */
+
+#define SEC_JOB_DESCRIPTOR_SIZE		64
+
+/*
+ * Size of one entry in the input ring of a job ring.
+ *  Input ring contains pointers to job descriptors.
+ *  The memory used for an input ring and output ring must be physically
+ *  contiguous.
+ */
+
+#define SEC_JOB_INPUT_RING_ENTRY_SIZE	sizeof(phys_addr_t)
+
+/*
+ * Size of one entry in the output ring of a job ring.
+ *  Output ring entry is a pointer to a job descriptor followed by a 4 byte
+ *  status word.
+ *  The memory used for an input ring and output ring must be physically
+ *  contiguous.
+ *  @note If desired to use also the optional SEQ OUT indication in output
+ *  ring entries, then 4 more bytes must be added to the size.
+ */
+
+#define SEC_JOB_OUTPUT_RING_ENTRY_SIZE	(SEC_JOB_INPUT_RING_ENTRY_SIZE + 4)
+
+ /* DMA memory required for an input ring of a job ring.  */
+#define SEC_DMA_MEM_INPUT_RING_SIZE	\
+		((SEC_JOB_INPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE))
+
+/*
+ * DMA memory required for an output ring of a job ring.
+ *  Required extra 4 byte for status word per each entry.
+ */
+#define SEC_DMA_MEM_OUTPUT_RING_SIZE	\
+		((SEC_JOB_OUTPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE))
+
+ /* DMA memory required for descriptors of a job ring.  */
+#define SEC_DMA_MEM_DESCRIPTORS		\
+		((SEC_CRYPTO_DESCRIPTOR_SIZE)*(SEC_JOB_RING_SIZE))
+
+ /* DMA memory required for a job ring, including both input output rings.  */
+#define SEC_DMA_MEM_JOB_RING_SIZE	\
+		((SEC_DMA_MEM_INPUT_RING_SIZE) +	\
+		(SEC_DMA_MEM_OUTPUT_RING_SIZE))
+
+/*
+ * When calling sec_init() UA will provide an area of virtual memory
+ *  of size #SEC_DMA_MEMORY_SIZE to be  used internally by the driver
+ *  to allocate data (like SEC descriptors) that needs to be passed to
+ *  SEC device in physical addressing and later on retrieved from SEC device.
+ *  At initialization the UA provides specialized ptov/vtop functions/macros to
+ *  translate addresses allocated from this memory area.
+ */
+#define SEC_DMA_MEMORY_SIZE		\
+		((SEC_DMA_MEM_JOB_RING_SIZE) * (MAX_SEC_JOB_RINGS))
+
+/*
+ * SEC DEVICE related configuration.
+
+ * Enable/Disable logging support at compile time.
+ * Valid values:
+ * ON - enable logging
+ * OFF - disable logging
+ * The messages are logged at stdout.
+ */
+
+#define SEC_DRIVER_LOGGING OFF
+
+/*
+ * Configure logging level at compile time.
+ * Valid values:
+ * SEC_DRIVER_LOG_ERROR - log only errors
+ * SEC_DRIVER_LOG_INFO  - log errors and info messages
+ * SEC_DRIVER_LOG_DEBUG - log errors, info and debug messages
+ */
+
+#define SEC_DRIVER_LOGGING_LEVEL SEC_DRIVER_LOG_DEBUG
+
+/*
+ * SEC JOB RING related configuration.
+
+ * Configure the size of the JOB RING.
+ * The maximum size of the ring is hardware limited to 1024.
+ * However the number of packets in flight in a time interval of
+ * 1ms can be calculated
+ * from the traffic rate (Mbps) and packet size.
+ * Here it was considered a packet size of 40 bytes.
+ * @note Round up to nearest power of 2 for optimized update
+ * of producer/consumer indexes of each job ring
+ * \todo Should set to 750, according to the calculation above, but
+ * the JR size must be power of 2, thus the next closest value must
+ * be chosen (i.e. 512 since 1024 is not available)
+ * For firmware choose this to be 16
+ */
+
+#define SEC_JOB_RING_SIZE    16
+
+/*
+ * Interrupt coalescing related configuration.
+ * NOTE: SEC hardware enabled interrupt
+ * coalescing is not supported on SEC version 3.1!
+ * SEC version 4.4 has support for interrupt
+ * coalescing.
+ */
+
+#if SEC_NOTIFICATION_TYPE != SEC_NOTIFICATION_TYPE_POLL
+
+#define SEC_INT_COALESCING_ENABLE   ON
+/*
+ * Interrupt Coalescing Descriptor Count Threshold.
+ * While interrupt coalescing is enabled (ICEN=1), this value determines
+ * how many Descriptors are completed before raising an interrupt.
+ * Valid values for this field are from 0 to 255.
+ * Note that a value of 1 functionally defeats the advantages of interrupt
+ * coalescing since the threshold value is reached each time that a
+ * Job Descriptor is completed. A value of 0 is treated in the same
+ * manner as a value of 1.
+ *
+ */
+#define SEC_INTERRUPT_COALESCING_DESCRIPTOR_COUNT_THRESH  10
+
+/*
+ * Interrupt Coalescing Timer Threshold.
+ * While interrupt coalescing is enabled (ICEN=1), this value determines the
+ * maximum amount of time after processing a Descriptor before raising an
+ * interrupt.
+ * The threshold value is represented in units equal to 64 CAAM interface
+ * clocks. Valid values for this field are from 1 to 65535.
+ * A value of 0 results in behavior identical to that when interrupt
+ * coalescing is disabled.
+ */
+#define SEC_INTERRUPT_COALESCING_TIMER_THRESH  100
+#endif /* SEC_NOTIFICATION_TYPE_POLL  */
+
+#endif /* _JR_DRIVER_CONFIG_H_  */
diff --git a/drivers/nxp/crypto/caam/include/rsa.h b/drivers/nxp/crypto/caam/include/rsa.h
new file mode 100644
index 0000000..bd5dc71
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/rsa.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _RSA_H__
+#define _RSA_H__
+
+/* RSA key size defines */
+#define RSA_4K_KEY_SZ       4096
+#define RSA_4K_KEY_SZ_BYTES (RSA_4K_KEY_SZ/8)
+#define RSA_2K_KEY_SZ       2048
+#define RSA_2K_KEY_SZ_BYTES (RSA_2K_KEY_SZ/8)
+#define RSA_1K_KEY_SZ       1024
+#define RSA_1K_KEY_SZ_BYTES (RSA_1K_KEY_SZ/8)
+
+#define SHA256_BYTES        (256/8)
+
+struct pk_in_params {
+	uint8_t *e;
+	uint32_t e_siz;
+	uint8_t *n;
+	uint32_t n_siz;
+	uint8_t *a;
+	uint32_t a_siz;
+	uint8_t *b;
+	uint32_t b_siz;
+};
+
+struct rsa_context {
+	struct pk_in_params pkin;
+};
+
+int rsa_verify_signature(void *hash_ptr, unsigned int hash_len,
+			 void *sig_ptr, unsigned int sig_len,
+			 void *pk_ptr, unsigned int pk_len);
+
+#endif
diff --git a/drivers/nxp/crypto/caam/include/sec_hw_specific.h b/drivers/nxp/crypto/caam/include/sec_hw_specific.h
new file mode 100644
index 0000000..a82a1a0
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/sec_hw_specific.h
@@ -0,0 +1,506 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _SEC_HW_SPECIFIC_H_
+#define _SEC_HW_SPECIFIC_H_
+
+#include "caam.h"
+#include "sec_jr_driver.h"
+
+ /* DEFINES AND MACROS */
+
+/* Used to retry resetting a job ring in SEC hardware. */
+#define SEC_TIMEOUT 100000
+
+/*
+ * Offset to the registers of a job ring.
+ *Is different for each job ring.
+ */
+#define CHAN_BASE(jr)   ((phys_addr_t)(jr)->register_base_addr)
+
+#define unlikely(x)	 __builtin_expect(!!(x), 0)
+
+#define SEC_JOB_RING_IS_FULL(pi, ci, ring_max_size, ring_threshold)    \
+	((((pi) + 1 + ((ring_max_size) - (ring_threshold))) &	\
+	  (ring_max_size - 1))  == ((ci)))
+
+#define SEC_CIRCULAR_COUNTER(x, max)   (((x) + 1) & (max - 1))
+
+ /* Struct representing various job ring registers */
+struct jobring_regs {
+#ifdef NXP_SEC_BE
+	unsigned int irba_h;
+	unsigned int irba_l;
+#else
+	unsigned int irba_l;
+	unsigned int irba_h;
+#endif
+	unsigned int rsvd1;
+	unsigned int irs;
+	unsigned int rsvd2;
+	unsigned int irsa;
+	unsigned int rsvd3;
+	unsigned int irja;
+#ifdef NXP_SEC_BE
+	unsigned int orba_h;
+	unsigned int orba_l;
+#else
+	unsigned int orba_l;
+	unsigned int orba_h;
+#endif
+	unsigned int rsvd4;
+	unsigned int ors;
+	unsigned int rsvd5;
+	unsigned int orjr;
+	unsigned int rsvd6;
+	unsigned int orsf;
+	unsigned int rsvd7;
+	unsigned int jrsta;
+	unsigned int rsvd8;
+	unsigned int jrint;
+	unsigned int jrcfg0;
+	unsigned int jrcfg1;
+	unsigned int rsvd9;
+	unsigned int irri;
+	unsigned int rsvd10;
+	unsigned int orwi;
+	unsigned int rsvd11;
+	unsigned int jrcr;
+};
+
+ /* Offsets representing common SEC Registers */
+#define SEC_REG_MCFGR_OFFSET		0x0004
+#define SEC_REG_SCFGR_OFFSET		0x000C
+#define SEC_REG_JR0ICIDR_MS_OFFSET	0x0010
+#define SEC_REG_JR0ICIDR_LS_OFFSET	0x0014
+#define SEC_REG_JR1ICIDR_MS_OFFSET	0x0018
+#define SEC_REG_JR1ICIDR_LS_OFFSET	0x001C
+#define SEC_REG_JR2ICIDR_MS_OFFSET	0x0020
+#define SEC_REG_JR2ICIDR_LS_OFFSET	0x0024
+#define SEC_REG_JR3ICIDR_MS_OFFSET	0x0028
+#define SEC_REG_JR3ICIDR_LS_OFFSET	0x002C
+#define SEC_REG_JRSTARTR_OFFSET		0x005C
+#define SEC_REG_CTPR_MS_OFFSET		0x0FA8
+
+ /* Offsets  representing various RNG registers */
+#define RNG_REG_RTMCTL_OFFSET		0x0600
+#define RNG_REG_RTSDCTL_OFFSET		0x0610
+#define RNG_REG_RTFRQMIN_OFFSET		0x0618
+#define RNG_REG_RTFRQMAX_OFFSET		0x061C
+#define RNG_REG_RDSTA_OFFSET		0x06C0
+#define ALG_AAI_SH_SHIFT		4
+
+ /* SEC Registers Bitmasks */
+#define	MCFGR_PS_SHIFT			16
+#define	MCFGR_AWCACHE_SHIFT			 8
+#define	MCFGR_AWCACHE_MASK	(0xF << MCFGR_AWCACHE_SHIFT)
+#define	MCFGR_ARCACHE_SHIFT			12
+#define	MCFGR_ARCACHE_MASK	(0xF << MCFGR_ARCACHE_SHIFT)
+
+#define SCFGR_RNGSH0		0x00000200
+#define	SCFGR_VIRT_EN		0x00008000
+
+#define JRICID_MS_LICID		0x80000000
+#define JRICID_MS_LAMTD		0x00020000
+#define JRICID_MS_AMTDT		0x00010000
+#define JRICID_MS_TZ		0x00008000
+#define JRICID_LS_SDID_MASK	0x00000FFF
+#define JRICID_LS_NSEQID_MASK	0x0FFF0000
+#define JRICID_LS_NSEQID_SHIFT		16
+#define JRICID_LS_SEQID_MASK	0x00000FFF
+
+#define JRSTARTR_STARTJR0	0x00000001
+#define JRSTARTR_STARTJR1	0x00000002
+#define JRSTARTR_STARTJR2	0x00000004
+#define JRSTARTR_STARTJR3	0x00000008
+
+#define CTPR_VIRT_EN_POR	0x00000002
+#define CTPR_VIRT_EN_INC	0x00000001
+
+ /* RNG RDSTA bitmask */
+#define RNG_STATE0_HANDLE_INSTANTIATED	0x00000001
+#define RTMCTL_PRGM 0x00010000	/* 1 -> program mode, 0 -> run mode */
+ /* use von Neumann data in both entropy shifter and statistical checker */
+#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC	 0
+ /* use raw data in both entropy shifter and statistical checker */
+#define RTMCTL_SAMP_MODE_RAW_ES_SC			 1
+ /* use von Neumann data in entropy shifter, raw data in statistical checker */
+#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_RAW_SC 2
+ /* invalid combination */
+#define RTMCTL_SAMP_MODE_INVALID			   3
+#define RTSDCTL_ENT_DLY_MIN	3200
+#define RTSDCTL_ENT_DLY_MAX	12800
+#define RTSDCTL_ENT_DLY_SHIFT	16
+#define RTSDCTL_ENT_DLY_MASK	(U(0xffff) << RTSDCTL_ENT_DLY_SHIFT)
+#define RTFRQMAX_DISABLE	   (1 << 20)
+
+ /* Constants for error handling on job ring */
+#define JR_REG_JRINT_ERR_TYPE_SHIFT	8
+#define JR_REG_JRINT_ERR_ORWI_SHIFT	16
+#define JR_REG_JRINIT_JRE_SHIFT			1
+
+#define JRINT_JRE			(1 << JR_REG_JRINIT_JRE_SHIFT)
+#define JRINT_ERR_WRITE_STATUS		(1 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_BAD_INPUT_BASE	(3 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_BAD_OUTPUT_BASE	(4 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_WRITE_2_IRBA		(5 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_WRITE_2_ORBA		(6 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_RES_B4_HALT		(7 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_REM_TOO_MANY		(8 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_ADD_TOO_MANY		(9 << JR_REG_JRINT_ERR_TYPE_SHIFT)
+#define JRINT_ERR_HALT_MASK		0x0C
+#define JRINT_ERR_HALT_INPROGRESS	0x04
+#define JRINT_ERR_HALT_COMPLETE		0x08
+
+#define JR_REG_JRCR_VAL_RESET		0x00000001
+
+#define JR_REG_JRCFG_LO_ICTT_SHIFT	0x10
+#define JR_REG_JRCFG_LO_ICDCT_SHIFT	0x08
+#define JR_REG_JRCFG_LO_ICEN_EN		0x02
+#define JR_REG_JRCFG_LO_IMSK_EN		0x01
+
+ /* Constants for Descriptor Processing errors */
+#define SEC_HW_ERR_SSRC_NO_SRC			0x00
+#define SEC_HW_ERR_SSRC_CCB_ERR			0x02
+#define SEC_HW_ERR_SSRC_JMP_HALT_U	0x03
+#define SEC_HW_ERR_SSRC_DECO		0x04
+#define SEC_HW_ERR_SSRC_JR		0x06
+#define SEC_HW_ERR_SSRC_JMP_HALT_COND   0x07
+
+#define SEC_HW_ERR_DECO_HFN_THRESHOLD   0xF1
+#define SEC_HW_ERR_CCB_ICV_CHECK_FAIL   0x0A
+
+ /* Macros for extracting error codes for the job ring */
+
+#define JR_REG_JRINT_ERR_TYPE_EXTRACT(value)			\
+				((value) & 0x00000F00)
+
+#define JR_REG_JRINT_ERR_ORWI_EXTRACT(value)			\
+				(((value) & 0x3FFF0000) >>	\
+				 JR_REG_JRINT_ERR_ORWI_SHIFT)
+
+#define JR_REG_JRINT_JRE_EXTRACT(value)				\
+				((value) & JRINT_JRE)
+
+ /* Macros for manipulating JR registers */
+typedef union {
+	uint64_t m_whole;
+	struct {
+#ifdef NXP_SEC_BE
+		uint32_t high;
+		uint32_t low;
+#else
+		uint32_t low;
+		uint32_t high;
+#endif
+	} m_halves;
+} ptr_addr_t;
+
+#if defined(CONFIG_PHYS_64BIT)
+#define sec_read_addr(a)		sec_in64((a))
+#define sec_write_addr(a, v)	sec_out64((a), (v))
+#else
+#define sec_read_addr(a)		sec_in32((a))
+#define sec_write_addr(a, v)		sec_out32((a), (v))
+#endif
+
+#define JR_REG(name, jr)	(CHAN_BASE(jr) + JR_REG_##name##_OFFSET)
+#define JR_REG_LO(name, jr)	(CHAN_BASE(jr) + JR_REG_##name##_OFFSET_LO)
+
+#define GET_JR_REG(name, jr)	(sec_in32(JR_REG(name, (jr))))
+#define GET_JR_REG_LO(name, jr)	(sec_in32(JR_REG_LO(name, (jr))))
+
+#define SET_JR_REG(name, jr, val)		\
+		(sec_out32(JR_REG(name, (jr)), (val)))
+
+#define SET_JR_REG_LO(name, jr, val)	\
+		(sec_out32(JR_REG_LO(name, (jr)), (val)))
+
+ /* STRUCTURES AND OTHER TYPEDEFS */
+ /*  Lists the possible states for a job ring. */
+typedef enum sec_job_ring_state_e {
+	SEC_JOB_RING_STATE_STARTED,	/* Job ring is initialized */
+	SEC_JOB_RING_STATE_RESET,	/* Job ring reset is in progres */
+} sec_job_ring_state_t;
+
+struct sec_job_ring_t {
+	/*
+	 * Consumer index for job ring (jobs array).
+	 * @note: cidx and pidx are accessed from
+	 * different threads.
+	 * Place the cidx and pidx inside the structure
+	 *  so that they lay on different cachelines, to
+	 * avoid false sharing between threads when the
+	 * threads run on different cores!
+	 */
+	uint32_t cidx;
+
+	/* Producer index for job ring (jobs array) */
+	uint32_t pidx;
+
+	/*  Ring of input descriptors. Size of array is power of 2 to allow
+	 * fast update of producer/consumer indexes with  bitwise operations.
+	 */
+	phys_addr_t *input_ring;
+
+	/*  Ring of output descriptors. */
+	struct sec_outring_entry *output_ring;
+
+	/* The file descriptor used for polling for interrupts notifications */
+	uint32_t irq_fd;
+
+	/* Model used by SEC Driver to receive  notifications from SEC.
+	 *  Can be either of the three:
+	 * #SEC_NOTIFICATION_TYPE_IRQ or
+	 * #SEC_NOTIFICATION_TYPE_POLL
+	 */
+	uint32_t jr_mode;
+	/* Base address for SEC's register memory for this job ring. */
+	void *register_base_addr;
+	/* notifies if coelescing is enabled for the job ring */
+	uint8_t coalescing_en;
+	/* The state of this job ring */
+	sec_job_ring_state_t jr_state;
+};
+
+ /* Forward structure declaration */
+typedef struct sec_job_ring_t sec_job_ring_t;
+
+struct sec_outring_entry {
+	phys_addr_t desc;	/* Pointer to completed descriptor */
+	uint32_t status;	/* Status for completed descriptor */
+} __packed;
+
+ /* Lists the states possible for the SEC user space driver. */
+typedef enum sec_driver_state_e {
+	SEC_DRIVER_STATE_IDLE,	/*< Driver not initialized */
+	SEC_DRIVER_STATE_STARTED,	/*< Driver initialized and */
+	SEC_DRIVER_STATE_RELEASE,	/*< Driver release is in progress */
+} sec_driver_state_t;
+
+ /* Union describing the possible error codes that */
+ /* can be set in the descriptor status word */
+
+union hw_error_code {
+	uint32_t error;
+	union {
+		struct {
+			uint32_t ssrc:4;
+			uint32_t ssed_val:28;
+		} __packed value;
+		struct {
+			uint32_t ssrc:4;
+			uint32_t res:28;
+		} __packed no_status_src;
+		struct {
+			uint32_t ssrc:4;
+			uint32_t jmp:1;
+			uint32_t res:11;
+			uint32_t desc_idx:8;
+			uint32_t cha_id:4;
+			uint32_t err_id:4;
+		} __packed ccb_status_src;
+		struct {
+			uint32_t ssrc:4;
+			uint32_t jmp:1;
+			uint32_t res:11;
+			uint32_t desc_idx:8;
+			uint32_t offset:8;
+		} __packed jmp_halt_user_src;
+		struct {
+			uint32_t ssrc:4;
+			uint32_t jmp:1;
+			uint32_t res:11;
+			uint32_t desc_idx:8;
+			uint32_t desc_err:8;
+		} __packed deco_src;
+		struct {
+			uint32_t ssrc:4;
+			uint32_t res:17;
+			uint32_t naddr:3;
+			uint32_t desc_err:8;
+		} __packed jr_src;
+		struct {
+			uint32_t ssrc:4;
+			uint32_t jmp:1;
+			uint32_t res:11;
+			uint32_t desc_idx:8;
+			uint32_t cond:8;
+		} __packed jmp_halt_cond_src;
+	} __packed error_desc;
+} __packed;
+
+ /* FUNCTION PROTOTYPES */
+
+/*
+ * @brief Initialize a job ring/channel in SEC device.
+ * Write configuration register/s to properly initialize a job ring.
+ *
+ * @param [in] job_ring     The job ring
+ *
+ * @retval 0 for success
+ * @retval other for error
+ */
+int hw_reset_job_ring(sec_job_ring_t *job_ring);
+
+/*
+ * @brief Reset a job ring/channel in SEC device.
+ * Write configuration register/s to reset a job ring.
+ *
+ * @param [in] job_ring     The job ring
+ *
+ * @retval 0 for success
+ * @retval -1 in case job ring reset failed
+ */
+int hw_shutdown_job_ring(sec_job_ring_t *job_ring);
+
+/*
+ * @brief Handle a job ring/channel error in SEC device.
+ * Identify the error type and clear error bits if required.
+ *
+ * @param [in]  job_ring    The job ring
+ * @param [in]  sec_error_code  error code as first read from SEC engine
+ */
+
+void hw_handle_job_ring_error(sec_job_ring_t *job_ring,
+			      uint32_t sec_error_code);
+/*
+ * @brief Handle a job ring error in the device.
+ * Identify the error type and printout a explanatory
+ * messages.
+ *
+ * @param [in]  job_ring    The job ring
+ *
+ */
+
+int hw_job_ring_error(sec_job_ring_t *job_ring);
+
+/* @brief Set interrupt coalescing parameters on the Job Ring.
+ * @param [in]  job_ring       The job ring
+ * @param [in]  irq_coalesing_timer
+ *                             Interrupt coalescing timer threshold.
+ *                     This value determines the maximum
+ *                     amount of time after processing a descriptor
+ *                     before raising an interrupt.
+ * @param [in]  irq_coalescing_count
+ *                             Interrupt coalescing count threshold.
+ *                     This value determines how many descriptors
+ *                     are completed before raising an interrupt.
+ */
+
+int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring,
+				     uint16_t irq_coalescing_timer,
+				     uint8_t irq_coalescing_count);
+
+/* @brief Enable interrupt coalescing on a job ring
+ * @param [in]  job_ring       The job ring
+ */
+
+int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring);
+
+/*
+ * @brief Disable interrupt coalescing on a job ring
+ * @param [in]  job_ring       The job ring
+ */
+
+int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring);
+
+/*
+ * @brief Poll the HW for already processed jobs in the JR
+ * and notify the available jobs to UA.
+ *
+ * @param [in]  job_ring            The job ring to poll.
+ * @param [in]  limit               The maximum number of jobs to notify.
+ *                                  If set to negative value, all available
+ *                                  jobs are notified.
+ *
+ * @retval >=0 for No of jobs notified to UA.
+ * @retval -1 for error
+ */
+
+int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit);
+
+/* @brief Poll the HW for already processed jobs in the JR
+ * and silently discard the available jobs or notify them to UA
+ * with indicated error code.
+
+ * @param [in,out]  job_ring        The job ring to poll.
+ * @param [in]  do_notify           Can be #TRUE or #FALSE.
+ *                                 Indicates if descriptors to be discarded
+ *                                  or notified to UA with given error_code.
+ * @param [in]  error_code          The detailed SEC error code.
+ * @param [out] notified_descs        Number of notified descriptors.
+ *                                 Can be NULL if do_notify is #FALSE
+ */
+void hw_flush_job_ring(struct sec_job_ring_t *job_ring,
+		       uint32_t do_notify,
+		       uint32_t error_code, uint32_t *notified_descs);
+
+/*
+ * @brief Flush job rings of any processed descs.
+ * The processed descs are silently dropped,
+ *  WITHOUT being notified to UA.
+ */
+void flush_job_rings(void);
+
+/*
+ * @brief Handle desc that generated error in SEC engine.
+ * Identify the exact type of error and handle the error.
+ * Depending on the error type, the job ring could be reset.
+ * All descs that are submitted for processing on this job ring
+ * are notified to User Application with error status and detailed error code.
+
+ * @param [in]  job_ring            Job ring
+ * @param [in]  sec_error_code      Error code read from job ring's Channel
+ *                                 Status Register
+ * @param [out] notified_descs      Number of notified descs. Can be NULL if
+ *                                 do_notify is #FALSE
+ * @param [out] do_driver_shutdown  If set to #TRUE, then UA is returned code
+ *                                 #SEC_PROCESSING_ERROR
+ *                                  which is indication that UA must call
+ *                                  sec_release() after this.
+ */
+void sec_handle_desc_error(struct sec_job_ring_t *job_ring,
+			   uint32_t sec_error_code,
+			   uint32_t *notified_descs,
+			   uint32_t *do_driver_shutdown);
+
+/*
+ * @brief Release the software and hardware resources tied to a job ring.
+ * @param [in] job_ring The job ring
+ * @retval  0 for success
+ * @retval  -1 for error
+ */
+int shutdown_job_ring(struct sec_job_ring_t *job_ring);
+
+/*
+ * @brief Enable irqs on associated job ring.
+ * @param [in] job_ring The job ring
+ * @retval  0 for success
+ * @retval  -1 for error
+ */
+int jr_enable_irqs(struct sec_job_ring_t *job_ring);
+
+/*
+ * @brief Disable irqs on associated job ring.
+ * @param [in] job_ring The job ring
+ * @retval  0 for success
+ * @retval  -1 for error
+ */
+int jr_disable_irqs(struct sec_job_ring_t *job_ring);
+
+ /*
+  * IRJA - Input Ring Jobs Added Register shows
+  * how many new jobs were added to the Input Ring.
+  */
+static inline void hw_enqueue_desc_on_job_ring(struct jobring_regs *regs,
+					       int num)
+{
+	sec_out32(&regs->irja, num);
+}
+
+#endif /* _SEC_HW_SPECIFIC_H_ */
diff --git a/drivers/nxp/crypto/caam/include/sec_jr_driver.h b/drivers/nxp/crypto/caam/include/sec_jr_driver.h
new file mode 100644
index 0000000..1381eab
--- /dev/null
+++ b/drivers/nxp/crypto/caam/include/sec_jr_driver.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef _JR_DRIVER_H_
+#define _JR_DRIVER_H_
+
+#include "jr_driver_config.h"
+
+/* The maximum size of a SEC descriptor, in WORDs (32 bits). */
+#define MAX_DESC_SIZE_WORDS		64
+
+#define CAAM_TIMEOUT   200000	/* ms */
+
+/* Return codes for JR user space driver APIs */
+typedef enum sec_return_code_e {
+	SEC_SUCCESS = 0,
+	SEC_INVALID_INPUT_PARAM,
+	SEC_OUT_OF_MEMORY,
+	SEC_DESCRIPTOR_IN_FLIGHT,
+	SEC_LAST_DESCRIPTOR_IN_FLIGHT,
+	SEC_PROCESSING_ERROR,
+	SEC_DESC_PROCESSING_ERROR,
+	SEC_JR_IS_FULL,
+	SEC_DRIVER_RELEASE_IN_PROGRESS,
+	SEC_DRIVER_ALREADY_INITIALIZED,
+	SEC_DRIVER_NOT_INITIALIZED,
+	SEC_JOB_RING_RESET_IN_PROGRESS,
+	SEC_RESET_ENGINE_FAILED,
+	SEC_ENABLE_IRQS_FAILED,
+	SEC_DISABLE_IRQS_FAILED,
+	SEC_RETURN_CODE_MAX_VALUE,
+} sec_return_code_t;
+
+/* STRUCTURES AND OTHER TYPEDEFS */
+
+/*
+ * @brief Function called by JR User Space driver to notify every processed
+ *         descriptor.
+ *
+ * Callback provided by the User Application.
+ * Callback is invoked by JR User Space driver for each descriptor processed by
+ * SEC
+ * @param [in] status          Status word indicating processing result for
+ *                                this descriptor.
+ * @param [in] arg               Opaque data passed by User Application
+ *                                It is opaque from JR driver's point of view.
+ * @param [in] job_ring           The job ring handle on which the processed
+ *                               descriptor word was enqueued
+ */
+typedef void (*user_callback) (uint32_t *desc, uint32_t status,
+			       void *arg, void *job_ring);
+
+/*
+ * Structure encompassing a job descriptor which is to be processed
+ * by SEC. User should also initialise this structure with the callback
+ * function pointer which will be called by driver after recieving proccessed
+ * descriptor from SEC. User data is also passed in this data structure which
+ * will be sent as an argument to the user callback function.
+ */
+struct job_descriptor {
+	uint32_t desc[MAX_DESC_SIZE_WORDS];
+	void *arg;
+	user_callback callback;
+};
+
+/*
+ * @brief Initialize the JR User Space driver.
+ * This function will handle initialization of sec library
+ * along with registering platform specific callbacks,
+ * as well as local data initialization.
+ * Call once during application startup.
+ * @note Global SEC initialization is done in SEC kernel driver.
+ * @note The hardware IDs of the initialized Job Rings are opaque to the UA.
+ * The exact Job Rings used by this library are decided between SEC user
+ * space driver and SEC kernel driver. A static partitioning of Job Rings is
+ * assumed, configured in DTS(device tree specification) file.
+ * @param [in] platform_cb     Registering the platform specific
+ *                             callbacks with driver
+ * @retval ::0                 for successful execution
+ * @retval ::-1                failure
+ */
+int sec_jr_lib_init(void);
+
+/*
+ * @brief Initialize the software and hardware resources tied to a job ring.
+ * @param [in] jr_mode;        Model to be used by SEC Driver to receive
+ *                             notifications from SEC.  Can be either
+ *                             SEC_NOTIFICATION_TYPE_IRQ or
+ *                             SEC_NOTIFICATION_TYPE_POLL
+ * @param [in] irq_coalescing_timer This value determines the maximum
+ *                                     amount of time after processing a
+ *                                     descriptor before raising an interrupt.
+ * @param [in] irq_coalescing_count This value determines how many
+ *                                     descriptors are completed before
+ *                                     raising an interrupt.
+ * @param [in] reg_base_addr   The job ring base address register
+ * @param [in] irq_id          The job ring interrupt identification number.
+ * @retval  job_ring_handle for successful job ring configuration
+ * @retval  NULL on error
+ */
+void *init_job_ring(uint8_t jr_mode,
+		    uint16_t irq_coalescing_timer,
+		    uint8_t irq_coalescing_count,
+		    void *reg_base_addr, uint32_t irq_id);
+
+/*
+ * @brief Release the resources used by the JR User Space driver.
+ * Reset and release SEC's job rings indicated by the User Application at
+ * init_job_ring() and free any memory allocated internally.
+ * Call once during application tear down.
+ * @note In case there are any descriptors in-flight (descriptors received by
+ * JR driver for processing and for which no response was yet provided to UA),
+ * the descriptors are discarded without any notifications to User Application.
+ * @retval ::0                 is returned for a successful execution
+ * @retval ::-1                is returned if JR driver release is in progress
+ */
+int sec_release(void);
+
+/*
+ * @brief Submit a descriptor for SEC processing.
+ * This function creates a "job" which is meant to instruct SEC HW
+ * to perform the processing on the input buffer. The "job" is enqueued
+ * in the Job Ring associated. The function will return after the "job"
+ * enqueue is finished. The function will not wait for SEC to
+ * start or/and finish the "job" processing.
+ * After the processing is finished the SEC HW writes the processing result
+ * to the provided output buffer.
+ * The Caller must poll JR driver using jr_dequeue()
+ * to receive notifications of the processing completion
+ * status. The notifications are received by caller by means of callback
+ * (see ::user_callback).
+ * @param [in]  job_ring_handle   The handle of the job ring on which
+ *                                descriptor is to be enqueued
+ * @param [in]  job_descriptor    The job descriptor structure of type
+ *                                struct job_descriptor. This structure
+ *                                should be filled with job descriptor along
+ *                                with callback function to be called after
+ *                                processing of descriptor and some
+ *                                opaque data passed to be passed to the
+ *                                callback function
+ *
+ * @retval ::0                 is returned for successful execution
+ * @retval ::-1                is returned if there is some enqueue failure
+ */
+int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr);
+
+/*
+ * @brief Polls for available descriptors processed by SEC on a specific
+ * Job Ring
+ * This function polls the SEC Job Rings and delivers processed descriptors
+ * Each processed descriptor has a user_callback registered.
+ * This user_callback is invoked for each processed descriptor.
+ * The polling is stopped when "limit" descriptors are notified or when
+ * there are no more descriptors to notify.
+ * @note The dequeue_jr() API cannot be called from within a user_callback
+ * function
+ * @param [in]  job_ring_handle    The Job Ring handle.
+ * @param [in]  limit              This value represents the maximum number
+ *                                 of processed descriptors that can be
+ *                                 notified API call on this Job Ring.
+ *                                 Note that fewer descriptors may be notified
+ *                                 if enough processed descriptors are not
+ *                                 available.
+ *                                 If limit has a negative value, then all
+ *                                 ready descriptors will be notified.
+ *
+ * @retval :: >=0                  is returned where retval is the total
+ *                                 Number of descriptors notified
+ *                                 during this function call.
+ * @retval :: -1                   is returned in case of some error
+ */
+int dequeue_jr(void *job_ring_handle, int32_t limit);
+
+#endif /* _JR_DRIVER_H_  */
diff --git a/drivers/nxp/crypto/caam/src/auth/auth.mk b/drivers/nxp/crypto/caam/src/auth/auth.mk
new file mode 100644
index 0000000..d1f8c75
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/auth/auth.mk
@@ -0,0 +1,12 @@
+#
+# Copyright 2018-2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#
+
+SEC_DRIVERS_PATH	:=	drivers/nxp/crypto/caam
+
+ifeq (${TRUSTED_BOARD_BOOT},1)
+AUTH_SOURCES +=  $(wildcard $(SEC_DRIVERS_PATH)/src/auth/*.c)
+endif
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;
+}
diff --git a/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c b/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c
new file mode 100644
index 0000000..646e981
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include <string.h>
+
+#include "caam.h"
+#include <common/debug.h>
+#include <drivers/auth/crypto_mod.h>
+
+#include "hash.h"
+#include "rsa.h"
+
+#define LIB_NAME		"NXP crypto"
+
+/*
+ * Initialize the library and export the descriptor
+ */
+static void init(void)
+{
+	/* Initialize NXP crypto library`:*/
+	NOTICE("Initializing & configuring SEC block.\n");
+
+	if (config_sec_block() < 0) {
+		ERROR("Init & config failure for caam.\n");
+	}
+}
+
+/*
+ * Verify a signature.
+ *
+ * For IMG_PLAT - data points to a PKCS#1.5 encoded HASH
+ * sig_alg will be RSA or ECC
+ * Parameters are passed using the DER encoding format following the ASN.1
+ * structures detailed above.
+ */
+static int verify_signature(void *data_ptr, unsigned int data_len,
+			    void *sig_ptr, unsigned int sig_len,
+			    void *sign_alg, unsigned int sig_alg_len,
+			    void *pk_ptr, unsigned int pk_len)
+{
+	int ret = CRYPTO_SUCCESS;
+
+	enum sig_alg alg = *(enum sig_alg *)sign_alg;
+
+	switch (alg) {
+	case RSA:
+		NOTICE("Verifying RSA\n");
+		ret = rsa_verify_signature(data_ptr, data_len, sig_ptr, sig_len,
+					   pk_ptr, pk_len);
+		break;
+	case ECC:
+	default:
+		ret = CRYPTO_ERR_SIGNATURE;
+		break;
+	}
+
+	if (ret != 0) {
+		ERROR("RSA verification Failed\n");
+	}
+	return ret;
+
+}
+
+/*
+ * Match a hash
+ *
+ * Digest info is passed as a table of SHA-26 hashes and digest_info_len
+ * is number of entries in the table
+ * This implementation is very specific to the CSF header parser ROTPK
+ * comparison.
+ */
+static int verify_hash(void *data_ptr, unsigned int data_len,
+		       void *digest_info_ptr, unsigned int digest_info_len)
+{
+	void *ctx = NULL;
+	int i = 0, ret = 0;
+	enum hash_algo algo = SHA256;
+	uint8_t hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE) = {0};
+	uint32_t digest_size = SHA256_BYTES;
+	uint8_t *hash_tbl = digest_info_ptr;
+
+	NOTICE("Verifying hash\n");
+	ret = hash_init(algo, &ctx);
+	if (ret != 0) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	/* Update hash with that of SRK table */
+	ret = hash_update(algo, ctx, data_ptr, data_len);
+	if (ret != 0) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	/* Copy hash at destination buffer */
+	ret = hash_final(algo, ctx, hash, digest_size);
+	if (ret != 0) {
+		return CRYPTO_ERR_HASH;
+	}
+
+	VERBOSE("%s Calculated hash\n", __func__);
+	for (i = 0; i < SHA256_BYTES/4; i++) {
+		VERBOSE("%x\n", *((uint32_t *)hash + i));
+	}
+
+	for (i = 0; i < digest_info_len; i++) {
+		if (memcmp(hash, (hash_tbl + (i * digest_size)),
+			   digest_size) == 0) {
+			return CRYPTO_SUCCESS;
+		}
+	}
+
+	return CRYPTO_ERR_HASH;
+}
+
+/*
+ * Register crypto library descriptor
+ */
+REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
diff --git a/drivers/nxp/crypto/caam/src/auth/rsa.c b/drivers/nxp/crypto/caam/src/auth/rsa.c
new file mode 100644
index 0000000..0c44462
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/auth/rsa.c
@@ -0,0 +1,179 @@
+/*
+ * 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 "jobdesc.h"
+#include "rsa.h"
+#include "sec_hw_specific.h"
+
+/* This array contains DER value for SHA-256 */
+static const uint8_t hash_identifier[] = {
+	0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60,
+	0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
+	0x04, 0x20
+};
+
+static void rsa_done(uint32_t *desc, uint32_t status, void *arg,
+		     void *job_ring)
+{
+	INFO("RSA Desc SUCCESS with status %x\n", status);
+}
+
+static int rsa_public_verif_sec(uint8_t *sign, uint8_t *to,
+				uint8_t *rsa_pub_key, uint32_t klen)
+{
+	int ret = 0;
+	struct rsa_context ctx __aligned(CACHE_WRITEBACK_GRANULE);
+	struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE);
+
+	jobdesc.arg = NULL;
+	jobdesc.callback = rsa_done;
+
+	memset(&ctx, 0, sizeof(struct rsa_context));
+
+	ctx.pkin.a = sign;
+	ctx.pkin.a_siz = klen;
+	ctx.pkin.n = rsa_pub_key;
+	ctx.pkin.n_siz = klen;
+	ctx.pkin.e = rsa_pub_key + klen;
+	ctx.pkin.e_siz = klen;
+
+	cnstr_jobdesc_pkha_rsaexp(jobdesc.desc, &ctx.pkin, to, klen);
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+	flush_dcache_range((uintptr_t)sign, klen);
+	flush_dcache_range((uintptr_t)rsa_pub_key, 2 * klen);
+	flush_dcache_range((uintptr_t)&ctx.pkin, sizeof(ctx.pkin));
+	inv_dcache_range((uintptr_t)to, klen);
+
+	dmbsy();
+	dsbsy();
+	isb();
+#endif
+
+	/* Finally, generate the requested random data bytes */
+	ret = run_descriptor_jr(&jobdesc);
+	if (ret != 0) {
+		ERROR("Error in running descriptor\n");
+		ret = -1;
+	}
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+	inv_dcache_range((uintptr_t)to, klen);
+	dmbsy();
+	dsbsy();
+	isb();
+#endif
+	return ret;
+}
+
+/*
+ * Construct encoded hash EM' wrt PKCSv1.5. This function calculates the
+ * pointers for padding, DER value and hash. And finally, constructs EM'
+ * which includes hash of complete CSF header and ESBC image. If SG flag
+ * is on, hash of SG table and entries is also included.
+ */
+static int construct_img_encoded_hash_second(uint8_t *hash, uint8_t hash_len,
+					     uint8_t *encoded_hash_second,
+					     unsigned int key_len)
+{
+	/*
+	 * RSA PKCSv1.5 encoding format for encoded message is below
+	 * EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash
+	 * PS is Padding String
+	 * DER is DER value for SHA-256
+	 * Hash is SHA-256 hash
+	 * *********************************************************
+	 * representative points to first byte of EM initially and is
+	 * filled with 0x0
+	 * representative is incremented by 1 and second byte is filled
+	 * with 0x1
+	 * padding points to third byte of EM
+	 * digest points to full length of EM - 32 bytes
+	 * hash_id (DER value) points to 19 bytes before pDigest
+	 * separator is one byte which separates padding and DER
+	 */
+
+	unsigned int len;
+	uint8_t *representative;
+	uint8_t *padding, *digest;
+	uint8_t *hash_id, *separator;
+	int i;
+	int ret = 0;
+
+	if (hash_len != SHA256_BYTES) {
+		return -1;
+	}
+
+	/* Key length = Modulus length */
+	len = (key_len / 2U) - 1U;
+	representative = encoded_hash_second;
+	representative[0] = 0U;
+	representative[1] = 1U;	/* block type 1 */
+
+	padding = &representative[2];
+	digest = &representative[1] + len - 32;
+	hash_id = digest - sizeof(hash_identifier);
+	separator = hash_id - 1;
+
+	/* fill padding area pointed by padding with 0xff */
+	memset(padding, 0xff, separator - padding);
+
+	/* fill byte pointed by separator */
+	*separator = 0U;
+
+	/* fill SHA-256 DER value  pointed by HashId */
+	memcpy(hash_id, hash_identifier, sizeof(hash_identifier));
+
+	/* fill hash pointed by Digest */
+	for (i = 0; i < SHA256_BYTES; i++) {
+		digest[i] = hash[i];
+	}
+
+	return ret;
+}
+
+int rsa_verify_signature(void *hash_ptr, unsigned int hash_len,
+			 void *sig_ptr, unsigned int sig_len,
+			 void *pk_ptr, unsigned int pk_len)
+{
+	uint8_t img_encoded_hash_second[RSA_4K_KEY_SZ_BYTES];
+	uint8_t encoded_hash[RSA_4K_KEY_SZ_BYTES] __aligned(CACHE_WRITEBACK_GRANULE);
+	int ret = 0;
+
+	ret = construct_img_encoded_hash_second(hash_ptr, hash_len,
+						img_encoded_hash_second,
+						pk_len);
+	if (ret != 0) {
+		ERROR("Encoded Hash Failure\n");
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	ret = rsa_public_verif_sec(sig_ptr, encoded_hash, pk_ptr, pk_len / 2);
+	if (ret != 0) {
+		ERROR("RSA signature Failure\n");
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	ret = memcmp(img_encoded_hash_second, encoded_hash, sig_len);
+	if (ret != 0) {
+		ERROR("Comparison Failure\n");
+		return CRYPTO_ERR_SIGNATURE;
+	}
+
+	return CRYPTO_SUCCESS;
+}
diff --git a/drivers/nxp/crypto/caam/src/caam.c b/drivers/nxp/crypto/caam/src/caam.c
new file mode 100644
index 0000000..e594f7b
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/caam.c
@@ -0,0 +1,339 @@
+/*
+ * 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 "jobdesc.h"
+#include "sec_hw_specific.h"
+
+static uintptr_t g_nxp_caam_addr;
+static void *job_ring;
+
+uintptr_t get_caam_addr(void)
+{
+	if (g_nxp_caam_addr == 0) {
+		ERROR("Sec Init is not done.\n");
+		panic();
+	}
+	return g_nxp_caam_addr;
+}
+
+/* This function sets the TZ bit for the Job ring number passed as @num */
+static void config_tz(int num)
+{
+	uint32_t jricid;
+
+	/* Setting TZ bit of job ring */
+	switch (num) {
+	case 0:
+		jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET);
+		sec_out32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET,
+			  jricid | JRICID_MS_TZ);
+		break;
+	case 1:
+		jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET);
+		sec_out32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET,
+			  jricid | JRICID_MS_TZ);
+		break;
+	case 2:
+		jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET);
+		sec_out32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET,
+			  jricid | JRICID_MS_TZ);
+		break;
+	case 3:
+		jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET);
+		sec_out32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET,
+			  jricid | JRICID_MS_TZ);
+		break;
+	default:
+		break;
+	}
+}
+
+/* This function checks if Virtualization is enabled for JR and
+ * accordingly sets the bot for starting JR<num> in JRSTARTR register
+ */
+static inline void start_jr(int num)
+{
+	uint32_t ctpr = sec_in32((g_nxp_caam_addr + SEC_REG_CTPR_MS_OFFSET));
+	uint32_t tmp = sec_in32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET));
+	uint32_t scfgr = sec_in32((g_nxp_caam_addr + SEC_REG_SCFGR_OFFSET));
+	bool start = false;
+
+	if ((ctpr & CTPR_VIRT_EN_INC) != 0U) {
+		if (((ctpr & CTPR_VIRT_EN_POR) != 0U) ||
+		    ((scfgr & SCFGR_VIRT_EN) != 0U)) {
+			start = true;
+		}
+	} else {
+		if ((ctpr & CTPR_VIRT_EN_POR) != 0U) {
+			start = true;
+		}
+	}
+
+	if (start == true) {
+		switch (num) {
+		case 0:
+			tmp |= JRSTARTR_STARTJR0;
+			break;
+		case 1:
+			tmp |= JRSTARTR_STARTJR1;
+			break;
+		case 2:
+			tmp |= JRSTARTR_STARTJR2;
+			break;
+		case 3:
+			tmp |= JRSTARTR_STARTJR3;
+			break;
+		default:
+			break;
+		}
+	}
+	sec_out32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET), tmp);
+}
+
+/* This functions configures the Job Ring
+ * JR3 is reserved for use by Secure world
+ */
+static int configure_jr(int num)
+{
+	int ret;
+	void *reg_base_addr;
+
+	switch (num) {
+	case 0:
+		reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR0_OFFSET);
+		break;
+	case 1:
+		reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR1_OFFSET);
+		break;
+	case 2:
+		reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR2_OFFSET);
+		break;
+	case 3:
+		reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR3_OFFSET);
+		break;
+	default:
+		break;
+	}
+
+	/* Initialize the JR library */
+	ret = sec_jr_lib_init();
+	if (ret != 0) {
+		ERROR("Error in sec_jr_lib_init");
+		return -1;
+	}
+
+	start_jr(num);
+
+	/* Do HW configuration of the JR */
+	job_ring = init_job_ring(SEC_NOTIFICATION_TYPE_POLL, 0, 0,
+				 reg_base_addr, 0);
+
+	if (job_ring == NULL) {
+		ERROR("Error in init_job_ring");
+		return -1;
+	}
+
+	return ret;
+}
+
+/* TBD - Configures and locks the ICID values for various JR */
+static inline void configure_icid(void)
+{
+}
+
+/* TBD configures the TZ settings of RTIC */
+static inline void configure_rtic(void)
+{
+}
+
+int sec_init(uintptr_t nxp_caam_addr)
+{
+	g_nxp_caam_addr = nxp_caam_addr;
+	return config_sec_block();
+}
+
+/* This function configure SEC block:
+ * - It does basic parameter setting
+ * - Configures the default Job ring assigned to TZ /secure world
+ * - Instantiates the RNG
+ */
+int config_sec_block(void)
+{
+	int ret = 0;
+	uint32_t mcfgr;
+
+	if (g_nxp_caam_addr == 0) {
+		ERROR("Sec Init is not done.\n");
+		return -1;
+	} else if (job_ring != NULL) {
+		NOTICE("Sec is already initialized and configured.\n");
+		return ret;
+	}
+
+	mcfgr = sec_in32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET);
+
+	/* Modify CAAM Read/Write attributes
+	 * AXI Write - Cacheable, WB and WA
+	 * AXI Read - Cacheable, RA
+	 */
+#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS2088A)
+	mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0xb << MCFGR_AWCACHE_SHIFT);
+	mcfgr = (mcfgr & ~MCFGR_ARCACHE_MASK) | (0x6 << MCFGR_ARCACHE_SHIFT);
+#else
+	mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0x2 << MCFGR_AWCACHE_SHIFT);
+#endif
+
+	/* Set PS bit to 1 */
+#ifdef CONFIG_PHYS_64BIT
+	mcfgr |= (1 << MCFGR_PS_SHIFT);
+#endif
+	sec_out32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET, mcfgr);
+
+	/* Asssign ICID to all Job rings and lock them for usage */
+	configure_icid();
+
+	/* Configure the RTIC */
+	configure_rtic();
+
+	/* Configure the default JR for usage */
+	ret = configure_jr(DEFAULT_JR);
+	if (ret != 0) {
+		ERROR("\nFSL_JR: configuration failure\n");
+		return -1;
+	}
+	/* Do TZ configuration of default JR for sec firmware */
+	config_tz(DEFAULT_JR);
+
+#ifdef CONFIG_RNG_INIT
+	/* Instantiate the RNG */
+	ret = hw_rng_instantiate();
+	if (ret != 0) {
+		ERROR("\nRNG Instantiation failure\n");
+		return -1;
+	}
+#endif
+
+	return ret;
+}
+
+/* This function is used for sumbitting job to the Job Ring
+ * [param] [in] - jobdesc to be submitted
+ * Return - -1 in case of error and 0 in case of SUCCESS
+ */
+int run_descriptor_jr(struct job_descriptor *jobdesc)
+{
+	int i = 0, ret = 0;
+	uint32_t *desc_addr = jobdesc->desc;
+	uint32_t desc_len = desc_length(jobdesc->desc);
+	uint32_t desc_word;
+
+	for (i = 0; i < desc_len; i++) {
+		desc_word = desc_addr[i];
+		VERBOSE("%x\n", desc_word);
+		sec_out32((uint32_t *)&desc_addr[i], desc_word);
+	}
+	dsb();
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+	flush_dcache_range((uintptr_t)desc_addr, desc_len * 4);
+	dmbsy();
+	dsbsy();
+	isb();
+#endif
+
+	ret = enq_jr_desc(job_ring, jobdesc);
+	if (ret == 0) {
+		VERBOSE("JR enqueue done...\n");
+	} else {
+		ERROR("Error in Enqueue\n");
+		return ret;
+	}
+
+	VERBOSE("Dequeue in progress");
+
+	ret = dequeue_jr(job_ring, -1);
+	if (ret >= 0) {
+		VERBOSE("Dequeue of %x desc success\n", ret);
+		ret = 0;
+	} else {
+		ERROR("deq_ret %x\n", ret);
+		ret = -1;
+	}
+
+	return ret;
+}
+
+/* this function returns a random number using HW RNG Algo
+ * In case of failure, random number returned is 0
+ * prngWidth = 0 - 32 bit random number
+ * prngWidth > 0 means 64 bit random number
+ */
+unsigned long long get_random(int rngWidth)
+{
+	unsigned long long result = 0;
+	uint8_t rand_byte[64] __aligned(CACHE_WRITEBACK_GRANULE);
+	uint8_t rand_byte_swp[8];
+	int bytes = 0;
+	int i = 0;
+	int ret = 0;
+
+#ifdef CAAM_TEST
+	rand_byte[0] = U(0x12);
+	rand_byte[1] = U(0x34);
+	rand_byte[2] = U(0x56);
+	rand_byte[3] = U(0x78);
+	rand_byte[4] = U(0x9a);
+	rand_byte[5] = U(0xbc);
+	rand_byte[6] = U(0xde);
+	rand_byte[7] = U(0xf1);
+#endif
+
+	if (rngWidth == 0U) {
+		bytes = 4;
+	} else {
+		bytes = 8;
+	}
+
+	memset(rand_byte, 0, 64);
+
+	ret = get_rand_bytes_hw(rand_byte, bytes);
+
+	for (i = 0; i < bytes; i++) {
+		if (ret != 0) {
+			/* Return 0 in case of failure */
+			rand_byte_swp[i] = 0;
+		} else {
+			rand_byte_swp[i] = rand_byte[bytes - i - 1];
+			result = (result << 8) | rand_byte_swp[i];
+		}
+	}
+
+	INFO("result %llx\n", result);
+
+	return result;
+
+} /* _get_RNG() */
+
+unsigned int _get_hw_unq_key(uint64_t hw_key_phy_addr, unsigned int size)
+{
+	int ret = 0;
+	uint8_t *hw_key = (uint8_t *) ptov((phys_addr_t *) hw_key_phy_addr);
+
+	ret = get_hw_unq_key_blob_hw(hw_key, size);
+
+	return ret;
+}
diff --git a/drivers/nxp/crypto/caam/src/hw_key_blob.c b/drivers/nxp/crypto/caam/src/hw_key_blob.c
new file mode 100644
index 0000000..0720695
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/hw_key_blob.c
@@ -0,0 +1,81 @@
+/*
+ * 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 "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "sec_hw_specific.h"
+
+
+/* Callback function after Instantiation decsriptor is submitted to SEC
+ */
+static void blob_done(uint32_t *desc, uint32_t status, void *arg,
+		      void *job_ring)
+{
+	INFO("Blob Desc SUCCESS with status %x\n", status);
+}
+
+/* @brief Submit descriptor to create blob
+ * @retval 0 on success
+ * @retval -1 on error
+ */
+int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size)
+{
+	int ret = 0;
+	int i = 0;
+
+	uint32_t key_sz = KEY_IDNFR_SZ_BYTES;
+	uint8_t key_data[KEY_IDNFR_SZ_BYTES];
+	uint8_t in_data[16];
+	uint8_t out_data[16 + KEY_BLOB_SIZE + MAC_SIZE];
+	struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE);
+	struct job_descriptor *jobdesc = &desc;
+	uint32_t in_sz = 16U;
+
+	/* Output blob will have 32 bytes key blob in beginning and
+	 * 16 byte HMAC identifier at end of data blob
+	 */
+	uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE;
+
+	uint32_t operation = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL |
+	    OP_PCLID_BLOB | BLOB_PROTO_INFO;
+
+	memset(key_data, 0xff, KEY_IDNFR_SZ_BYTES);
+	memset(in_data, 0x00, in_sz);
+	memset(out_data, 0x00, in_sz);
+
+	jobdesc->arg = NULL;
+	jobdesc->callback = blob_done;
+
+	INFO("\nGenerating Master Key Verification Blob.\n");
+
+	/* Create the hw_rng descriptor */
+	ret = cnstr_hw_encap_blob_jobdesc(jobdesc->desc, key_data, key_sz,
+					  CLASS_2, in_data, in_sz, out_data,
+					  out_sz, operation);
+
+	/* Finally, generate the blob. */
+	ret = run_descriptor_jr(jobdesc);
+	if (ret != 0) {
+		ERROR("Error in running hw unq key blob descriptor\n");
+		return -1;
+	}
+	/* Copying alternate bytes of the Master Key Verification Blob.
+	 */
+	for (i = 0; i < size; i++) {
+		hw_key[i] = out_data[2 * i];
+	}
+
+	return ret;
+}
diff --git a/drivers/nxp/crypto/caam/src/jobdesc.c b/drivers/nxp/crypto/caam/src/jobdesc.c
new file mode 100644
index 0000000..9c235af
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/jobdesc.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright 2017-2020 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "rsa.h"
+#include "sec_hw_specific.h"
+
+
+/* Return Length of desctiptr from first word */
+uint32_t desc_length(uint32_t *desc)
+{
+	return desc[0] & DESC_LEN_MASK;
+}
+
+/*Update start index in first word of descriptor */
+void desc_update_start_index(uint32_t *desc, uint32_t index)
+{
+	desc[0] |= (index << DESC_START_SHIFT);
+}
+
+/* Initialize the descriptor */
+void desc_init(uint32_t *desc)
+{
+	*desc = 0;
+}
+
+/* Add word in the descriptor and increment the length */
+void desc_add_word(uint32_t *desc, uint32_t word)
+{
+	uint32_t len = desc_length(desc);
+
+	/* Add Word at Last */
+	uint32_t *last = desc + len;
+	*last = word;
+
+	/* Increase the length */
+	desc[0] += 1;
+}
+
+/* Add Pointer to the descriptor */
+void desc_add_ptr(uint32_t *desc, phys_addr_t *ptr)
+{
+	uint32_t len = desc_length(desc);
+
+	/* Add Word at Last */
+	phys_addr_t *last = (phys_addr_t *) (desc + len);
+
+#ifdef CONFIG_PHYS_64BIT
+	ptr_addr_t *ptr_addr = (ptr_addr_t *) last;
+
+	ptr_addr->m_halves.high = PHYS_ADDR_HI(ptr);
+	ptr_addr->m_halves.low = PHYS_ADDR_LO(ptr);
+#else
+	*last = ptr;
+#endif
+
+	/* Increase the length */
+	desc[0] += (uint32_t) (sizeof(phys_addr_t) / sizeof(uint32_t));
+}
+
+/* Descriptor to generate Random words */
+int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle,
+		      uint32_t *add_inp, uint32_t add_ip_len,
+		      uint8_t *out_data, uint32_t len)
+{
+	phys_addr_t *phys_addr_out = vtop(out_data);
+
+	/* Current descriptor support only 64K length */
+	if (len > U(0xffff))
+		return -1;
+	/* Additional Input not supported by current descriptor */
+	if (add_ip_len > 0U)
+		return -1;
+
+	VERBOSE("Constructing descriptor\n");
+	desc_init(desc);
+	/* Class1 Alg Operation,RNG Optype, Generate */
+	desc_add_word(desc, U(0xb0800000));
+	desc_add_word(desc, U(0x82500000) | (state_handle << ALG_AAI_SH_SHIFT));
+	desc_add_word(desc, U(0x60340000) | len);
+	desc_add_ptr(desc, phys_addr_out);
+
+	return 0;
+
+}
+
+/* Construct descriptor to instantiate RNG */
+int cnstr_rng_instantiate_jobdesc(uint32_t *desc)
+{
+	desc_init(desc);
+	desc_add_word(desc, U(0xb0800000));
+	/* Class1 Alg Operation,RNG Optype, Instantiate */
+	desc_add_word(desc, U(0x82500004));
+	/* Wait for done */
+	desc_add_word(desc, U(0xa2000001));
+	/*Load to clear written */
+	desc_add_word(desc, U(0x10880004));
+	/*Pri Mode Reg clear */
+	desc_add_word(desc, U(0x00000001));
+	/* Generate secure keys */
+	desc_add_word(desc, U(0x82501000));
+
+	return 0;
+}
+
+/* Construct descriptor to generate hw key blob */
+int cnstr_hw_encap_blob_jobdesc(uint32_t *desc,
+				uint8_t *key_idnfr, uint32_t key_sz,
+				uint32_t key_class, uint8_t *plain_txt,
+				uint32_t in_sz, uint8_t *enc_blob,
+				uint32_t out_sz, uint32_t operation)
+{
+	phys_addr_t *phys_key_idnfr, *phys_addr_in, *phys_addr_out;
+	int i = 0;
+
+	phys_key_idnfr = vtop((void *)key_idnfr);
+	phys_addr_in = vtop((void *)plain_txt);
+	phys_addr_out = vtop((void *)enc_blob);
+
+	desc_init(desc);
+
+	desc_add_word(desc, U(0xb0800000));
+
+	/* Key Identifier */
+	desc_add_word(desc, (key_class | key_sz));
+	desc_add_ptr(desc, phys_key_idnfr);
+
+	/* Source Address */
+	desc_add_word(desc, U(0xf0400000));
+	desc_add_ptr(desc, phys_addr_in);
+
+	/* In Size = 0x10 */
+	desc_add_word(desc, in_sz);
+
+	/* Out Address */
+	desc_add_word(desc, U(0xf8400000));
+	desc_add_ptr(desc, phys_addr_out);
+
+	/* Out Size = 0x10 */
+	desc_add_word(desc, out_sz);
+
+	/* Operation */
+	desc_add_word(desc, operation);
+
+	for (i = 0; i < 15; i++)
+		VERBOSE("desc word %x\n", desc[i]);
+
+	return 0;
+}
+
+/***************************************************************************
+ * Function	: inline_cnstr_jobdesc_pkha_rsaexp
+ * Arguments	: desc - Pointer to Descriptor
+ *		  pkin - Pointer to Input Params
+ *		  out - Pointer to Output
+ *		  out_siz - Output Size
+ * Return	: Void
+ * Description	: Creates the descriptor for PKHA RSA
+ ***************************************************************************/
+void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc,
+			       struct pk_in_params *pkin, uint8_t *out,
+			       uint32_t out_siz)
+{
+	phys_addr_t *ptr_addr_e, *ptr_addr_a, *ptr_addr_n, *ptr_addr_out;
+
+	ptr_addr_e = vtop((void *)(pkin->e));
+	ptr_addr_a = vtop((void *)(pkin->a));
+	ptr_addr_n = vtop((void *)(pkin->n));
+	ptr_addr_out = vtop((void *)(out));
+
+	desc_init(desc);
+	desc_add_word(desc, U(0xb0800000));
+	desc_add_word(desc, U(0x02010000) | pkin->e_siz);
+	desc_add_ptr(desc, ptr_addr_e);
+	desc_add_word(desc, U(0x220c0000) | pkin->a_siz);
+	desc_add_ptr(desc, ptr_addr_a);
+	desc_add_word(desc, U(0x22080000) | pkin->n_siz);
+	desc_add_ptr(desc, ptr_addr_n);
+	desc_add_word(desc, U(0x81800006));
+	desc_add_word(desc, U(0x620d0000) | out_siz);
+	desc_add_ptr(desc, ptr_addr_out);
+}
+
+/***************************************************************************
+ * Function	: inline_cnstr_jobdesc_sha256
+ * Arguments	: desc - Pointer to Descriptor
+ *		  msg - Pointer to SG Table
+ *		  msgsz - Size of SG Table
+ *		  digest - Pointer to Output Digest
+ * Return	: Void
+ * Description	: Creates the descriptor for SHA256 HASH calculation
+ ***************************************************************************/
+void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz,
+			uint8_t *digest)
+{
+	/* SHA 256 , output is of length 32 words */
+	phys_addr_t *ptr_addr_in, *ptr_addr_out;
+
+	ptr_addr_in = (void *)vtop(msg);
+	ptr_addr_out = (void *)vtop(digest);
+
+	desc_init(desc);
+	desc_add_word(desc, U(0xb0800000));
+
+	/* Operation Command
+	 * OP_TYPE_CLASS2_ALG | OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HASH |
+	 * OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT | OP_ALG_ICV_OFF)
+	 */
+	desc_add_word(desc, U(0x8443000d));
+
+	if (msgsz > U(0xffff)) {
+		desc_add_word(desc, U(0x25540000));	/* FIFO Load */
+		desc_add_ptr(desc, ptr_addr_in);	/* Pointer to msg */
+		desc_add_word(desc, msgsz);	/* Size */
+		desc_add_word(desc, U(0x54200020));	/* FIFO Store */
+		desc_add_ptr(desc, ptr_addr_out);	/* Pointer to Result */
+	} else {
+		desc_add_word(desc, U(0x25140000) | msgsz);
+		desc_add_ptr(desc, ptr_addr_in);
+		desc_add_word(desc, U(0x54200020));
+		desc_add_ptr(desc, ptr_addr_out);
+	}
+
+}
diff --git a/drivers/nxp/crypto/caam/src/rng.c b/drivers/nxp/crypto/caam/src/rng.c
new file mode 100644
index 0000000..0b9d87d
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/rng.c
@@ -0,0 +1,251 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <arch_helpers.h>
+#include "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "sec_hw_specific.h"
+
+
+/* Callback function after Instantiation decsriptor is submitted to SEC */
+static void rng_done(uint32_t *desc, uint32_t status, void *arg,
+		     void *job_ring)
+{
+	INFO("RNG Desc SUCCESS with status %x\n", status);
+}
+
+/* Is the HW RNG instantiated?
+ * Return code:
+ * 0 - Not in the instantiated state
+ * 1 - In the instantiated state
+ * state_handle - 0 for SH0, 1 for SH1
+ */
+static int is_hw_rng_instantiated(uint32_t *state_handle)
+{
+	int ret_code = 0;
+	uint32_t rdsta;
+
+	rdsta = sec_in32(get_caam_addr() + RNG_REG_RDSTA_OFFSET);
+
+	 /*Check if either of the two state handles has been instantiated */
+	if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) {
+		*state_handle = 0;
+		ret_code = 1;
+	} else if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) {
+		*state_handle = 1;
+		ret_code = 1;
+	}
+
+	return ret_code;
+}
+
+/* @brief Kick the TRNG block of the RNG HW Engine
+ * @param [in] ent_delay       Entropy delay to be used
+ *        By default, the TRNG runs for 200 clocks per sample;
+ *        1200 clocks per sample generates better entropy.
+ * @retval 0 on success
+ * @retval -1 on error
+ */
+static void kick_trng(int ent_delay)
+{
+	uint32_t val;
+
+	/* put RNG4 into program mode */
+	val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET);
+	val = val | RTMCTL_PRGM;
+	sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val);
+
+	/* rtsdctl bits 0-15 contain "Entropy Delay, which defines the
+	 *  length (in system clocks) of each Entropy sample taken
+	 */
+	val = sec_in32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET);
+	val = (val & ~RTSDCTL_ENT_DLY_MASK) |
+	    (ent_delay << RTSDCTL_ENT_DLY_SHIFT);
+	sec_out32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET, val);
+	/* min. freq. count, equal to 1/4 of the entropy sample length */
+	sec_out32(get_caam_addr() + RNG_REG_RTFRQMIN_OFFSET, ent_delay >> 2);
+	/* disable maximum frequency count */
+	sec_out32(get_caam_addr() + RNG_REG_RTFRQMAX_OFFSET, RTFRQMAX_DISABLE);
+
+	/* select raw sampling in both entropy shifter
+	 *  and statistical checker
+	 */
+	val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET);
+	val = val | RTMCTL_SAMP_MODE_RAW_ES_SC;
+	sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val);
+
+	/* put RNG4 into run mode */
+	val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET);
+	val = val & ~RTMCTL_PRGM;
+	sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val);
+}
+
+/* @brief Submit descriptor to instantiate the RNG
+ * @retval 0 on success
+ * @retval -1 on error
+ */
+static int instantiate_rng(void)
+{
+	int ret = 0;
+	struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE);
+	struct job_descriptor *jobdesc = &desc;
+
+	jobdesc->arg = NULL;
+	jobdesc->callback = rng_done;
+
+	/* create the hw_rng descriptor */
+	cnstr_rng_instantiate_jobdesc(jobdesc->desc);
+
+	/* Finally, generate the requested random data bytes */
+	ret = run_descriptor_jr(jobdesc);
+	if (ret != 0) {
+		ERROR("Error in running descriptor\n");
+		ret = -1;
+	}
+	return ret;
+}
+
+/* Generate Random Data using HW RNG
+ * Parameters:
+ * uint8_t* add_input   - user specified optional input byte array
+ * uint32_t add_input_len - number of bytes of additional input
+ * uint8_t* out                   - user specified output byte array
+ * uint32_t out_len       - number of bytes to store in output byte array
+ * Return code:
+ * 0 - SUCCESS
+ * -1 - ERROR
+ */
+static int
+hw_rng_generate(uint32_t *add_input, uint32_t add_input_len,
+		uint8_t *out, uint32_t out_len, uint32_t state_handle)
+{
+	int ret = 0;
+	struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE);
+	struct job_descriptor *jobdesc = &desc;
+
+	jobdesc->arg = NULL;
+	jobdesc->callback = rng_done;
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+	inv_dcache_range((uintptr_t)out, out_len);
+	dmbsy();
+#endif
+
+	/* create the hw_rng descriptor */
+	ret = cnstr_rng_jobdesc(jobdesc->desc, state_handle,
+				add_input, add_input_len, out, out_len);
+	if (ret != 0) {
+		ERROR("Descriptor construction failed\n");
+		ret = -1;
+		goto out;
+	}
+	/* Finally, generate the requested random data bytes */
+	ret = run_descriptor_jr(jobdesc);
+	if (ret != 0) {
+		ERROR("Error in running descriptor\n");
+		ret = -1;
+	}
+
+out:
+	return ret;
+}
+
+/* this function instantiates the rng
+ *
+ * Return code:
+ *  0 - All is well
+ * <0 - Error occurred somewhere
+ */
+int hw_rng_instantiate(void)
+{
+	int ret = 0;
+	int ent_delay = RTSDCTL_ENT_DLY_MIN;
+	uint32_t state_handle;
+
+	ret = is_hw_rng_instantiated(&state_handle);
+	if (ret != 0) {
+		NOTICE("RNG already instantiated\n");
+		return 0;
+	}
+	do {
+		kick_trng(ent_delay);
+		ent_delay += 400;
+		/*if instantiate_rng(...) fails, the loop will rerun
+		 *and the kick_trng(...) function will modify the
+		 *upper and lower limits of the entropy sampling
+		 *interval, leading to a sucessful initialization of
+		 */
+		ret = instantiate_rng();
+	} while ((ret == -1) && (ent_delay < RTSDCTL_ENT_DLY_MAX));
+	if (ret != 0) {
+		ERROR("RNG: Failed to instantiate RNG\n");
+		return ret;
+	}
+
+	NOTICE("RNG: INSTANTIATED\n");
+
+	/* Enable RDB bit so that RNG works faster */
+	// sec_setbits32(&sec->scfgr, SEC_SCFGR_RDBENABLE);
+
+	return ret;
+}
+
+/* Generate random bytes, and stuff them into the bytes buffer
+ *
+ * If the HW RNG has not already been instantiated,
+ *  it will be instantiated before data is generated.
+ *
+ * Parameters:
+ * uint8_t* bytes  - byte buffer large enough to hold the requested random date
+ * int byte_len - number of random bytes to generate
+ *
+ * Return code:
+ *  0 - All is well
+ *  ~0 - Error occurred somewhere
+ */
+int get_rand_bytes_hw(uint8_t *bytes, int byte_len)
+{
+	int ret_code = 0;
+	uint32_t state_handle;
+
+	/* If this is the first time this routine is called,
+	 *  then the hash_drbg will not already be instantiated.
+	 * Therefore, before generating data, instantiate the hash_drbg
+	 */
+	ret_code = is_hw_rng_instantiated(&state_handle);
+	if (ret_code == 0) {
+		INFO("Instantiating the HW RNG\n");
+
+		/* Instantiate the hw RNG */
+		ret_code = hw_rng_instantiate();
+		if (ret_code != 0) {
+			ERROR("HW RNG Instantiate failed\n");
+			return ret_code;
+		}
+	}
+	/* If  HW RNG is still not instantiated, something must have gone wrong,
+	 * it must be in the error state, we will not generate any random data
+	 */
+	if (is_hw_rng_instantiated(&state_handle) == 0) {
+		ERROR("HW RNG is in an Error state, and cannot be used\n");
+		return -1;
+	}
+	/* Generate a random 256-bit value, as 32 bytes */
+	ret_code = hw_rng_generate(0, 0, bytes, byte_len, state_handle);
+	if (ret_code != 0) {
+		ERROR("HW RNG Generate failed\n");
+		return ret_code;
+	}
+
+	return ret_code;
+}
diff --git a/drivers/nxp/crypto/caam/src/sec_hw_specific.c b/drivers/nxp/crypto/caam/src/sec_hw_specific.c
new file mode 100644
index 0000000..92b7762
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/sec_hw_specific.c
@@ -0,0 +1,635 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <arch_helpers.h>
+#include "caam.h"
+#include <common/debug.h>
+#include "jobdesc.h"
+#include "sec_hw_specific.h"
+
+
+/* Job rings used for communication with SEC HW */
+extern struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS];
+
+/* The current state of SEC user space driver */
+extern volatile sec_driver_state_t g_driver_state;
+
+/* The number of job rings used by SEC user space driver */
+extern int g_job_rings_no;
+
+/* LOCAL FUNCTIONS */
+static inline void hw_set_input_ring_start_addr(struct jobring_regs *regs,
+						phys_addr_t *start_addr)
+{
+#if defined(CONFIG_PHYS_64BIT)
+	sec_out32(&regs->irba_h, PHYS_ADDR_HI(start_addr));
+#else
+	sec_out32(&regs->irba_h, 0);
+#endif
+	sec_out32(&regs->irba_l, PHYS_ADDR_LO(start_addr));
+}
+
+static inline void hw_set_output_ring_start_addr(struct jobring_regs *regs,
+						 phys_addr_t *start_addr)
+{
+#if defined(CONFIG_PHYS_64BIT)
+	sec_out32(&regs->orba_h, PHYS_ADDR_HI(start_addr));
+#else
+	sec_out32(&regs->orba_h, 0);
+#endif
+	sec_out32(&regs->orba_l, PHYS_ADDR_LO(start_addr));
+}
+
+/* ORJR - Output Ring Jobs Removed Register shows how many jobs were
+ * removed from the Output Ring for processing by software. This is done after
+ * the software has processed the entries.
+ */
+static inline void hw_remove_entries(sec_job_ring_t *jr, int num)
+{
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)jr->register_base_addr;
+
+	sec_out32(&regs->orjr, num);
+}
+
+/* IRSA - Input Ring Slots Available register holds the number of entries in
+ * the Job Ring's input ring. Once a job is enqueued, the value returned is
+ * decremented by the hardware by the number of jobs enqueued.
+ */
+static inline int hw_get_available_slots(sec_job_ring_t *jr)
+{
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)jr->register_base_addr;
+
+	return sec_in32(&regs->irsa);
+}
+
+/* ORSFR - Output Ring Slots Full register holds the number of jobs which were
+ * processed by the SEC and can be retrieved by the software. Once a job has
+ * been processed by software, the user will call hw_remove_one_entry in order
+ * to notify the SEC that the entry was processed
+ */
+static inline int hw_get_no_finished_jobs(sec_job_ring_t *jr)
+{
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)jr->register_base_addr;
+
+	return sec_in32(&regs->orsf);
+}
+
+/* @brief Process Jump Halt Condition related errors
+ * @param [in]  error_code The error code in the descriptor status word
+ */
+static inline void hw_handle_jmp_halt_cond_err(union hw_error_code error_code)
+{
+	ERROR("JMP %x\n", error_code.error_desc.jmp_halt_cond_src.jmp);
+	ERROR("Descriptor Index: %d\n",
+	      error_code.error_desc.jmp_halt_cond_src.desc_idx);
+	ERROR(" Condition %x\n", error_code.error_desc.jmp_halt_cond_src.cond);
+}
+
+/* @brief Process DECO related errors
+ * @param [in]  error_code      The error code in the descriptor status word
+ */
+static inline void hw_handle_deco_err(union hw_error_code error_code)
+{
+	ERROR("JMP %x\n", error_code.error_desc.deco_src.jmp);
+	ERROR("Descriptor Index: 0x%x",
+	      error_code.error_desc.deco_src.desc_idx);
+
+	switch (error_code.error_desc.deco_src.desc_err) {
+	case SEC_HW_ERR_DECO_HFN_THRESHOLD:
+		WARN(" Descriptor completed but exceeds the Threshold");
+		break;
+	default:
+		ERROR("Error 0x%04x not implemented",
+		      error_code.error_desc.deco_src.desc_err);
+		break;
+	}
+}
+
+/* @brief Process  Jump Halt User Status related errors
+ * @param [in]  error_code      The error code in the descriptor status word
+ */
+static inline void hw_handle_jmp_halt_user_err(union hw_error_code error_code)
+{
+	WARN(" Not implemented");
+}
+
+/* @brief Process CCB related errors
+ * @param [in]  error_code      The error code in the descriptor status word
+ */
+static inline void hw_handle_ccb_err(union hw_error_code hw_error_code)
+{
+	WARN(" Not implemented");
+}
+
+/* @brief Process Job Ring related errors
+ * @param [in]  error_code      The error code in the descriptor status word
+ */
+static inline void hw_handle_jr_err(union hw_error_code hw_error_code)
+{
+	WARN(" Not implemented");
+}
+
+/* GLOBAL FUNCTIONS */
+
+int hw_reset_job_ring(sec_job_ring_t *job_ring)
+{
+	int ret = 0;
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)job_ring->register_base_addr;
+
+	/* First reset the job ring in hw */
+	ret = hw_shutdown_job_ring(job_ring);
+	if (ret != 0) {
+		ERROR("Failed resetting job ring in hardware");
+		return ret;
+	}
+	/* In order to have the HW JR in a workable state
+	 *after a reset, I need to re-write the input
+	 * queue size, input start address, output queue
+	 * size and output start address
+	 * Write the JR input queue size to the HW register
+	 */
+	sec_out32(&regs->irs, SEC_JOB_RING_SIZE);
+
+	/* Write the JR output queue size to the HW register */
+	sec_out32(&regs->ors, SEC_JOB_RING_SIZE);
+
+	/* Write the JR input queue start address */
+	hw_set_input_ring_start_addr(regs, vtop(job_ring->input_ring));
+
+	/* Write the JR output queue start address */
+	hw_set_output_ring_start_addr(regs, vtop(job_ring->output_ring));
+
+	return 0;
+}
+
+int hw_shutdown_job_ring(sec_job_ring_t *job_ring)
+{
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)job_ring->register_base_addr;
+	unsigned int timeout = SEC_TIMEOUT;
+	uint32_t tmp = 0U;
+
+	VERBOSE("Resetting Job ring\n");
+
+	/*
+	 * Mask interrupts since we are going to poll
+	 * for reset completion status
+	 * Also, at POR, interrupts are ENABLED on a JR, thus
+	 * this is the point where I can disable them without
+	 * changing the code logic too much
+	 */
+
+	jr_disable_irqs(job_ring);
+
+	/* initiate flush (required prior to reset) */
+	sec_out32(&regs->jrcr, JR_REG_JRCR_VAL_RESET);
+
+	/* dummy read */
+	tmp = sec_in32(&regs->jrcr);
+
+	do {
+		tmp = sec_in32(&regs->jrint);
+	} while (((tmp & JRINT_ERR_HALT_MASK) ==
+		  JRINT_ERR_HALT_INPROGRESS) && ((--timeout) != 0U));
+
+	if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE ||
+	    timeout == 0U) {
+		ERROR("Failed to flush hw job ring %x\n %u", tmp, timeout);
+		/* unmask interrupts */
+		if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+			jr_enable_irqs(job_ring);
+		}
+		return -1;
+	}
+	/* Initiate reset */
+	timeout = SEC_TIMEOUT;
+	sec_out32(&regs->jrcr, JR_REG_JRCR_VAL_RESET);
+
+	do {
+		tmp = sec_in32(&regs->jrcr);
+	} while (((tmp & JR_REG_JRCR_VAL_RESET) != 0U) &&
+		 ((--timeout) != 0U));
+
+	if (timeout == 0U) {
+		ERROR("Failed to reset hw job ring\n");
+		/* unmask interrupts */
+		if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+			jr_enable_irqs(job_ring);
+		}
+		return -1;
+	}
+	/* unmask interrupts */
+	if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+		jr_enable_irqs(job_ring);
+	}
+	return 0;
+
+}
+
+void hw_handle_job_ring_error(sec_job_ring_t *job_ring, uint32_t error_code)
+{
+	union hw_error_code hw_err_code;
+
+	hw_err_code.error = error_code;
+
+	switch (hw_err_code.error_desc.value.ssrc) {
+	case SEC_HW_ERR_SSRC_NO_SRC:
+		INFO("No Status Source ");
+		break;
+	case SEC_HW_ERR_SSRC_CCB_ERR:
+		INFO("CCB Status Source");
+		hw_handle_ccb_err(hw_err_code);
+		break;
+	case SEC_HW_ERR_SSRC_JMP_HALT_U:
+		INFO("Jump Halt User Status Source");
+		hw_handle_jmp_halt_user_err(hw_err_code);
+		break;
+	case SEC_HW_ERR_SSRC_DECO:
+		INFO("DECO Status Source");
+		hw_handle_deco_err(hw_err_code);
+		break;
+	case SEC_HW_ERR_SSRC_JR:
+		INFO("Job Ring Status Source");
+		hw_handle_jr_err(hw_err_code);
+		break;
+	case SEC_HW_ERR_SSRC_JMP_HALT_COND:
+		INFO("Jump Halt Condition Codes");
+		hw_handle_jmp_halt_cond_err(hw_err_code);
+		break;
+	default:
+		INFO("Unknown SSRC");
+		break;
+	}
+}
+
+int hw_job_ring_error(sec_job_ring_t *job_ring)
+{
+	uint32_t jrint_error_code;
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)job_ring->register_base_addr;
+
+	if (JR_REG_JRINT_JRE_EXTRACT(sec_in32(&regs->jrint)) == 0) {
+		return 0;
+	}
+
+	jrint_error_code =
+	    JR_REG_JRINT_ERR_TYPE_EXTRACT(sec_in32(&regs->jrint));
+	switch (jrint_error_code) {
+	case JRINT_ERR_WRITE_STATUS:
+		ERROR("Error writing status to Output Ring ");
+		break;
+	case JRINT_ERR_BAD_INPUT_BASE:
+		ERROR("Bad Input Ring Base (not on a 4-byte boundary)\n");
+		break;
+	case JRINT_ERR_BAD_OUTPUT_BASE:
+		ERROR("Bad Output Ring Base (not on a 4-byte boundary)\n");
+		break;
+	case JRINT_ERR_WRITE_2_IRBA:
+		ERROR("Invalid write to Input Ring Base Address Register\n");
+		break;
+	case JRINT_ERR_WRITE_2_ORBA:
+		ERROR("Invalid write to Output Ring Base Address Register\n");
+		break;
+	case JRINT_ERR_RES_B4_HALT:
+		ERROR("Job Ring released before Job Ring is halted\n");
+		break;
+	case JRINT_ERR_REM_TOO_MANY:
+		ERROR("Removed too many jobs from job ring\n");
+		break;
+	case JRINT_ERR_ADD_TOO_MANY:
+		ERROR("Added too many jobs on job ring\n");
+		break;
+	default:
+		ERROR("Unknown SEC JR Error :%d\n", jrint_error_code);
+		break;
+	}
+	return jrint_error_code;
+}
+
+int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring,
+				     uint16_t irq_coalescing_timer,
+				     uint8_t irq_coalescing_count)
+{
+	uint32_t reg_val = 0U;
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)job_ring->register_base_addr;
+
+	/* Set descriptor count coalescing */
+	reg_val |= (irq_coalescing_count << JR_REG_JRCFG_LO_ICDCT_SHIFT);
+
+	/* Set coalescing timer value */
+	reg_val |= (irq_coalescing_timer << JR_REG_JRCFG_LO_ICTT_SHIFT);
+
+	/* Update parameters in HW */
+	sec_out32(&regs->jrcfg1, reg_val);
+
+	VERBOSE("Set coalescing params on jr\n");
+
+	return 0;
+}
+
+int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring)
+{
+	uint32_t reg_val = 0U;
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)job_ring->register_base_addr;
+
+	/* Get the current value of the register */
+	reg_val = sec_in32(&regs->jrcfg1);
+
+	/* Enable coalescing */
+	reg_val |= JR_REG_JRCFG_LO_ICEN_EN;
+
+	/* Write in hw */
+	sec_out32(&regs->jrcfg1, reg_val);
+
+	VERBOSE("Enabled coalescing on jr\n");
+
+	return 0;
+}
+
+int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring)
+{
+	uint32_t reg_val = 0U;
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)job_ring->register_base_addr;
+
+	/* Get the current value of the register */
+	reg_val = sec_in32(&regs->jrcfg1);
+
+	/* Disable coalescing */
+	reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN;
+
+	/* Write in hw */
+	sec_out32(&regs->jrcfg1, reg_val);
+
+	VERBOSE("Disabled coalescing on jr");
+
+	return 0;
+
+}
+
+void hw_flush_job_ring(struct sec_job_ring_t *job_ring,
+		       uint32_t do_notify,
+		       uint32_t error_code, uint32_t *notified_descs)
+{
+	int32_t jobs_no_to_discard = 0;
+	int32_t discarded_descs_no = 0;
+	int32_t number_of_jobs_available = 0;
+
+	VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx);
+	VERBOSE("error code %x\n", error_code);
+	VERBOSE("Notify_desc = %d\n", do_notify);
+
+	number_of_jobs_available = hw_get_no_finished_jobs(job_ring);
+
+	/* Discard all jobs */
+	jobs_no_to_discard = number_of_jobs_available;
+
+	VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx);
+	VERBOSE("Discarding desc = %d\n", jobs_no_to_discard);
+
+	while (jobs_no_to_discard > discarded_descs_no) {
+		discarded_descs_no++;
+		/* Now increment the consumer index for the current job ring,
+		 * AFTER saving job in temporary location!
+		 * Increment the consumer index for the current job ring
+		 */
+
+		job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx,
+						      SEC_JOB_RING_SIZE);
+
+		hw_remove_entries(job_ring, 1);
+	}
+
+	if (do_notify == true) {
+		if (notified_descs == NULL) {
+			return;
+		}
+		*notified_descs = discarded_descs_no;
+	}
+}
+
+/* return >0 in case of success
+ *  -1 in case of error from SEC block
+ *  0 in case job not yet processed by SEC
+ *   or  Descriptor returned is NULL after dequeue
+ */
+int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit)
+{
+	int32_t jobs_no_to_notify = 0;
+	int32_t number_of_jobs_available = 0;
+	int32_t notified_descs_no = 0;
+	uint32_t error_descs_no = 0U;
+	uint32_t sec_error_code = 0U;
+	uint32_t do_driver_shutdown = false;
+	phys_addr_t *fnptr, *arg_addr;
+	user_callback usercall = NULL;
+	uint8_t *current_desc;
+	void *arg;
+	uintptr_t current_desc_addr;
+	phys_addr_t current_desc_loc;
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+	inv_dcache_range((uintptr_t)job_ring->register_base_addr, sizeof(struct jobring_regs));
+	dmbsy();
+#endif
+
+	/* check here if any JR error that cannot be written
+	 * in the output status word has occurred
+	 */
+	sec_error_code = hw_job_ring_error(job_ring);
+	if (unlikely(sec_error_code) != 0) {
+		ERROR("Error here itself %x\n", sec_error_code);
+		return -1;
+	}
+	/* Compute the number of notifications that need to be raised to UA
+	 * If limit < 0 -> notify all done jobs
+	 * If limit > total number of done jobs -> notify all done jobs
+	 * If limit = 0 -> error
+	 * If limit > 0 && limit < total number of done jobs -> notify a number
+	 * of done jobs equal with limit
+	 */
+
+	/*compute the number of jobs available in the job ring based on the
+	 * producer and consumer index values.
+	 */
+
+	number_of_jobs_available = hw_get_no_finished_jobs(job_ring);
+	jobs_no_to_notify = (limit < 0 || limit > number_of_jobs_available) ?
+	    number_of_jobs_available : limit;
+	VERBOSE("JR - pi %d, ci %d, ", job_ring->pidx, job_ring->cidx);
+	VERBOSE("Jobs submitted %d", number_of_jobs_available);
+	VERBOSE("Jobs to notify %d\n", jobs_no_to_notify);
+
+	while (jobs_no_to_notify > notified_descs_no) {
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+		inv_dcache_range(
+			(uintptr_t)(&job_ring->output_ring[job_ring->cidx]),
+			sizeof(struct sec_outring_entry));
+		dmbsy();
+#endif
+
+		/* Get job status here */
+		sec_error_code =
+		    sec_in32(&(job_ring->output_ring[job_ring->cidx].status));
+
+		/* Get completed descriptor
+		 */
+		current_desc_loc = (uintptr_t)
+		    &job_ring->output_ring[job_ring->cidx].desc;
+		current_desc_addr = sec_read_addr(current_desc_loc);
+
+		current_desc = ptov((phys_addr_t *) current_desc_addr);
+		if (current_desc == 0) {
+			ERROR("No descriptor returned from SEC");
+			assert(current_desc);
+			return 0;
+		}
+		/* now increment the consumer index for the current job ring,
+		 * AFTER saving job in temporary location!
+		 */
+		job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx,
+						      SEC_JOB_RING_SIZE);
+
+		if (sec_error_code != 0) {
+			ERROR("desc at cidx %d\n ", job_ring->cidx);
+			ERROR("generated error %x\n", sec_error_code);
+
+			sec_handle_desc_error(job_ring,
+					      sec_error_code,
+					      &error_descs_no,
+					      &do_driver_shutdown);
+			hw_remove_entries(job_ring, 1);
+
+			return -1;
+		}
+		/* Signal that the job has been processed & the slot is free */
+		hw_remove_entries(job_ring, 1);
+		notified_descs_no++;
+
+		arg_addr = (phys_addr_t *) (current_desc +
+				(MAX_DESC_SIZE_WORDS * sizeof(uint32_t)));
+
+		fnptr = (phys_addr_t *) (current_desc +
+					(MAX_DESC_SIZE_WORDS * sizeof(uint32_t)
+					+  sizeof(void *)));
+
+		arg = (void *)*(arg_addr);
+		if (*fnptr != 0) {
+			VERBOSE("Callback Function called\n");
+			usercall = (user_callback) *(fnptr);
+			(*usercall) ((uint32_t *) current_desc,
+				     sec_error_code, arg, job_ring);
+		}
+	}
+
+	return notified_descs_no;
+}
+
+void sec_handle_desc_error(sec_job_ring_t *job_ring,
+			   uint32_t sec_error_code,
+			   uint32_t *notified_descs,
+			   uint32_t *do_driver_shutdown)
+{
+	/* Analyze the SEC error on this job ring */
+	hw_handle_job_ring_error(job_ring, sec_error_code);
+}
+
+void flush_job_rings(void)
+{
+	struct sec_job_ring_t *job_ring = NULL;
+	int i = 0;
+
+	for (i = 0; i < g_job_rings_no; i++) {
+		job_ring = &g_job_rings[i];
+		/* Producer index is frozen. If consumer index is not equal
+		 * with producer index, then we have descs to flush.
+		 */
+		while (job_ring->pidx != job_ring->cidx) {
+			hw_flush_job_ring(job_ring, false, 0,	/* no error */
+					  NULL);
+		}
+	}
+}
+
+int shutdown_job_ring(struct sec_job_ring_t *job_ring)
+{
+	int ret = 0;
+
+	ret = hw_shutdown_job_ring(job_ring);
+	if (ret != 0) {
+		ERROR("Failed to shutdown hardware job ring\n");
+		return ret;
+	}
+
+	if (job_ring->coalescing_en != 0) {
+		hw_job_ring_disable_coalescing(job_ring);
+	}
+
+	if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+		ret = jr_disable_irqs(job_ring);
+		if (ret != 0) {
+			ERROR("Failed to disable irqs for job ring");
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int jr_enable_irqs(struct sec_job_ring_t *job_ring)
+{
+	uint32_t reg_val = 0U;
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)job_ring->register_base_addr;
+
+	/* Get the current value of the register */
+	reg_val = sec_in32(&regs->jrcfg1);
+
+	/* Enable interrupts by disabling interrupt masking*/
+	reg_val &= ~JR_REG_JRCFG_LO_IMSK_EN;
+
+	/* Update parameters in HW */
+	sec_out32(&regs->jrcfg1, reg_val);
+
+	VERBOSE("Enable interrupts on JR\n");
+
+	return 0;
+}
+
+int jr_disable_irqs(struct sec_job_ring_t *job_ring)
+{
+	uint32_t reg_val = 0U;
+	struct jobring_regs *regs =
+	    (struct jobring_regs *)job_ring->register_base_addr;
+
+	/* Get the current value of the register */
+	reg_val = sec_in32(&regs->jrcfg1);
+
+	/* Disable interrupts by enabling interrupt masking*/
+	reg_val |= JR_REG_JRCFG_LO_IMSK_EN;
+
+	/* Update parameters in HW */
+	sec_out32(&regs->jrcfg1, reg_val);
+
+	VERBOSE("Disable interrupts on JR\n");
+
+	return 0;
+}
diff --git a/drivers/nxp/crypto/caam/src/sec_jr_driver.c b/drivers/nxp/crypto/caam/src/sec_jr_driver.c
new file mode 100644
index 0000000..1fe7007
--- /dev/null
+++ b/drivers/nxp/crypto/caam/src/sec_jr_driver.c
@@ -0,0 +1,241 @@
+/*
+ * 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 "jobdesc.h"
+#include "nxp_timer.h"
+#include "sec_hw_specific.h"
+#include "sec_jr_driver.h"
+
+
+/* Job rings used for communication with SEC HW  */
+struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS];
+
+/* The current state of SEC user space driver */
+volatile sec_driver_state_t g_driver_state = SEC_DRIVER_STATE_IDLE;
+
+int g_job_rings_no;
+
+uint8_t ip_ring[SEC_DMA_MEM_INPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE);
+uint8_t op_ring[SEC_DMA_MEM_OUTPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE);
+
+void *init_job_ring(uint8_t jr_mode,
+		    uint16_t irq_coalescing_timer,
+		    uint8_t irq_coalescing_count,
+		    void *reg_base_addr, uint32_t irq_id)
+{
+	struct sec_job_ring_t *job_ring = &g_job_rings[g_job_rings_no++];
+	int ret = 0;
+
+	job_ring->register_base_addr = reg_base_addr;
+	job_ring->jr_mode = jr_mode;
+	job_ring->irq_fd = irq_id;
+
+	job_ring->input_ring = vtop(ip_ring);
+	memset(job_ring->input_ring, 0, SEC_DMA_MEM_INPUT_RING_SIZE);
+
+	job_ring->output_ring = (struct sec_outring_entry *)vtop(op_ring);
+	memset(job_ring->output_ring, 0, SEC_DMA_MEM_OUTPUT_RING_SIZE);
+
+	dsb();
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+	flush_dcache_range((uintptr_t)(job_ring->input_ring),
+				       SEC_DMA_MEM_INPUT_RING_SIZE),
+	flush_dcache_range((uintptr_t)(job_ring->output_ring),
+				       SEC_DMA_MEM_OUTPUT_RING_SIZE),
+
+	dmbsy();
+#endif
+	/* Reset job ring in SEC hw and configure job ring registers */
+	ret = hw_reset_job_ring(job_ring);
+	if (ret != 0) {
+		ERROR("Failed to reset hardware job ring\n");
+		return NULL;
+	}
+
+	if (jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
+		/* Enable IRQ if driver work sin interrupt mode */
+		ERROR("Enabling DONE IRQ generation on job ring\n");
+		ret = jr_enable_irqs(job_ring);
+		if (ret != 0) {
+			ERROR("Failed to enable irqs for job ring\n");
+			return NULL;
+		}
+	}
+	if ((irq_coalescing_timer != 0) || (irq_coalescing_count != 0)) {
+		hw_job_ring_set_coalescing_param(job_ring,
+						 irq_coalescing_timer,
+						 irq_coalescing_count);
+
+		hw_job_ring_enable_coalescing(job_ring);
+		job_ring->coalescing_en = 1;
+	}
+
+	job_ring->jr_state = SEC_JOB_RING_STATE_STARTED;
+
+	return job_ring;
+}
+
+int sec_release(void)
+{
+	int i;
+
+	/* Validate driver state */
+	if (g_driver_state == SEC_DRIVER_STATE_RELEASE) {
+		ERROR("Driver release is already in progress");
+		return SEC_DRIVER_RELEASE_IN_PROGRESS;
+	}
+	/* Update driver state */
+	g_driver_state = SEC_DRIVER_STATE_RELEASE;
+
+	/* If any descriptors in flight , poll and wait
+	 * until all descriptors are received and silently discarded.
+	 */
+
+	flush_job_rings();
+
+	for (i = 0; i < g_job_rings_no; i++) {
+		shutdown_job_ring(&g_job_rings[i]);
+	}
+	g_job_rings_no = 0;
+	g_driver_state = SEC_DRIVER_STATE_IDLE;
+
+	return SEC_SUCCESS;
+}
+
+int sec_jr_lib_init(void)
+{
+	/* Validate driver state */
+	if (g_driver_state != SEC_DRIVER_STATE_IDLE) {
+		ERROR("Driver already initialized\n");
+		return 0;
+	}
+
+	memset(g_job_rings, 0, sizeof(g_job_rings));
+	g_job_rings_no = 0;
+
+	/* Update driver state */
+	g_driver_state = SEC_DRIVER_STATE_STARTED;
+	return 0;
+}
+
+int dequeue_jr(void *job_ring_handle, int32_t limit)
+{
+	int ret = 0;
+	int notified_descs_no = 0;
+	struct sec_job_ring_t *job_ring = (sec_job_ring_t *) job_ring_handle;
+	uint64_t start_time;
+
+	/* Validate driver state */
+	if (g_driver_state != SEC_DRIVER_STATE_STARTED) {
+		ERROR("Driver release in progress or driver not initialized\n");
+		return -1;
+	}
+
+	/* Validate input arguments */
+	if (job_ring == NULL) {
+		ERROR("job_ring_handle is NULL\n");
+		return -1;
+	}
+	if (((limit == 0) || (limit > SEC_JOB_RING_SIZE))) {
+		ERROR("Invalid limit parameter configuration\n");
+		return -1;
+	}
+
+	VERBOSE("JR Polling limit[%d]\n", limit);
+
+	/* Poll job ring
+	 * If limit < 0 -> poll JR until no more notifications are available.
+	 * If limit > 0 -> poll JR until limit is reached.
+	 */
+
+	start_time = get_timer_val(0);
+
+	while (notified_descs_no == 0) {
+		/* Run hw poll job ring */
+		notified_descs_no = hw_poll_job_ring(job_ring, limit);
+		if (notified_descs_no < 0) {
+			ERROR("Error polling SEC engine job ring ");
+			return notified_descs_no;
+		}
+		VERBOSE("Jobs notified[%d]. ", notified_descs_no);
+
+		if (get_timer_val(start_time) >= CAAM_TIMEOUT) {
+			break;
+		}
+	}
+
+	if (job_ring->jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
+
+		/* Always enable IRQ generation when in pure IRQ mode */
+		ret = jr_enable_irqs(job_ring);
+		if (ret != 0) {
+			ERROR("Failed to enable irqs for job ring");
+			return ret;
+		}
+	}
+	return notified_descs_no;
+}
+
+int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr)
+{
+	struct sec_job_ring_t *job_ring;
+
+	job_ring = (struct sec_job_ring_t *)job_ring_handle;
+
+	/* Validate driver state */
+	if (g_driver_state != SEC_DRIVER_STATE_STARTED) {
+		ERROR("Driver release in progress or driver not initialized\n");
+		return -1;
+	}
+
+	/* Check job ring state */
+	if (job_ring->jr_state != SEC_JOB_RING_STATE_STARTED) {
+		ERROR("Job ring is currently resetting\n");
+		return -1;
+	}
+
+	if (SEC_JOB_RING_IS_FULL(job_ring->pidx, job_ring->cidx,
+				 SEC_JOB_RING_SIZE, SEC_JOB_RING_SIZE)) {
+		ERROR("Job ring is full\n");
+		return -1;
+	}
+
+	/* Set ptr in input ring to current descriptor  */
+	sec_write_addr(&job_ring->input_ring[job_ring->pidx],
+		       (phys_addr_t) vtop(jobdescr->desc));
+
+	dsb();
+
+#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2)
+	flush_dcache_range((uintptr_t)(&job_ring->input_ring[job_ring->pidx]),
+			   sizeof(phys_addr_t));
+
+	inv_dcache_range((uintptr_t)(&job_ring->output_ring[job_ring->cidx]),
+			   sizeof(struct sec_outring_entry));
+	dmbsy();
+#endif
+	/* Notify HW that a new job is enqueued  */
+	hw_enqueue_desc_on_job_ring(
+			(struct jobring_regs *)job_ring->register_base_addr, 1);
+
+	/* increment the producer index for the current job ring */
+	job_ring->pidx = SEC_CIRCULAR_COUNTER(job_ring->pidx,
+					      SEC_JOB_RING_SIZE);
+
+	return 0;
+}