From: Hemant Agrawal <hemant.agra...@nxp.com>

Signed-off-by: Gagandeep Singh <g.si...@nxp.com>
Signed-off-by: Hemant Agrawal <hemant.agra...@nxp.com>
---
 drivers/crypto/caam_jr/Makefile              |   6 +
 drivers/crypto/caam_jr/caam_jr.c             | 329 +++++++++++-
 drivers/crypto/caam_jr/caam_jr_config.h      | 207 ++++++++
 drivers/crypto/caam_jr/caam_jr_hw.c          | 365 ++++++++++++++
 drivers/crypto/caam_jr/caam_jr_hw_specific.h | 503 +++++++++++++++++++
 drivers/crypto/caam_jr/caam_jr_pvt.h         | 285 +++++++++++
 drivers/crypto/caam_jr/caam_jr_uio.c         | 491 ++++++++++++++++++
 drivers/crypto/caam_jr/meson.build           |   5 +-
 8 files changed, 2188 insertions(+), 3 deletions(-)
 create mode 100644 drivers/crypto/caam_jr/caam_jr_config.h
 create mode 100644 drivers/crypto/caam_jr/caam_jr_hw.c
 create mode 100644 drivers/crypto/caam_jr/caam_jr_hw_specific.h
 create mode 100644 drivers/crypto/caam_jr/caam_jr_pvt.h
 create mode 100644 drivers/crypto/caam_jr/caam_jr_uio.c

diff --git a/drivers/crypto/caam_jr/Makefile b/drivers/crypto/caam_jr/Makefile
index 46d752af7..8b863b4af 100644
--- a/drivers/crypto/caam_jr/Makefile
+++ b/drivers/crypto/caam_jr/Makefile
@@ -19,7 +19,10 @@ CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
 endif
 
+CFLAGS += -I$(RTE_SDK)/drivers/bus/dpaa/include
 CFLAGS += -I$(RTE_SDK)/drivers/crypto/caam_jr
+#sharing the hw flib headers from dpaa2_sec pmd
+CFLAGS += -I$(RTE_SDK)/drivers/crypto/dpaa2_sec/
 CFLAGS += -I$(RTE_SDK)/lib/librte_eal/common/include
 CFLAGS += -I$(RTE_SDK)/lib/librte_eal/linuxapp/eal
 
@@ -30,11 +33,14 @@ EXPORT_MAP := rte_pmd_caam_jr_version.map
 LIBABIVER := 1
 
 # library source files
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_CAAM_JR) += caam_jr_hw.c
+SRCS-$(CONFIG_RTE_LIBRTE_PMD_CAAM_JR) += caam_jr_uio.c
 SRCS-$(CONFIG_RTE_LIBRTE_PMD_CAAM_JR) += caam_jr.c
 # library dependencies
 
 LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool -lrte_ring
 LDLIBS += -lrte_cryptodev
+LDLIBS += -lrte_bus_dpaa
 LDLIBS += -lrte_bus_vdev
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/crypto/caam_jr/caam_jr.c b/drivers/crypto/caam_jr/caam_jr.c
index 68779cba5..9d5f5b79b 100644
--- a/drivers/crypto/caam_jr/caam_jr.c
+++ b/drivers/crypto/caam_jr/caam_jr.c
@@ -16,13 +16,146 @@
 #include <rte_malloc.h>
 #include <rte_security_driver.h>
 #include <rte_hexdump.h>
+#include <caam_jr_config.h>
 
+/* RTA header files */
+#include <hw/desc/common.h>
+#include <of.h>
+#include <caam_jr_hw_specific.h>
+#include <caam_jr_pvt.h>
 #include <caam_jr_log.h>
 
 #define CRYPTODEV_NAME_CAAM_JR_PMD     crypto_caam_jr
 static uint8_t cryptodev_driver_id;
 int caam_jr_logtype;
 
+enum rta_sec_era rta_sec_era;
+
+/* Lists the states possible for the SEC user space driver. */
+enum sec_driver_state_e {
+       SEC_DRIVER_STATE_IDLE,          /* Driver not initialized */
+       SEC_DRIVER_STATE_STARTED,       /* Driver initialized and can be used*/
+       SEC_DRIVER_STATE_RELEASE,       /* Driver release is in progress */
+};
+
+/* Job rings used for communication with SEC HW */
+static struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS];
+
+/* The current state of SEC user space driver */
+static enum sec_driver_state_e g_driver_state = SEC_DRIVER_STATE_IDLE;
+
+/* The number of job rings used by SEC user space driver */
+static int g_job_rings_no;
+static int g_job_rings_max;
+
+/* @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 are to be discarded
+ *                                  or notified to UA with given error_code.
+ * @param [out] notified_descs    Number of notified descriptors. Can be NULL
+ *                                     if do_notify is #FALSE
+ */
+static void hw_flush_job_ring(struct sec_job_ring_t *job_ring,
+                             uint32_t do_notify,
+                             uint32_t *notified_descs)
+{
+       int32_t jobs_no_to_discard = 0;
+       int32_t discarded_descs_no = 0;
+
+       CAAM_JR_DEBUG("Jr[%p] pi[%d] ci[%d].Flushing jr notify desc=[%d]",
+               job_ring, job_ring->pidx, job_ring->cidx, do_notify);
+
+       jobs_no_to_discard = hw_get_no_finished_jobs(job_ring);
+
+       /* Discard all jobs */
+       CAAM_JR_DEBUG("Jr[%p] pi[%d] ci[%d].Discarding %d descs",
+                 job_ring, job_ring->pidx, job_ring->cidx,
+                 jobs_no_to_discard);
+
+       while (jobs_no_to_discard > discarded_descs_no) {
+               /* Get completed descriptor */
+#if 0
+               /*TODO if we want to do something with desc*/
+               /* Since the memory is contigous, then P2V translation is a
+                * mere addition to the base descriptor physical address
+                */
+               current_desc = job_ring->output_ring[job_ring->cidx].desc;
+#endif
+
+               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) {
+               ASSERT(notified_descs != NULL);
+               *notified_descs = discarded_descs_no;
+       }
+}
+
+
+/* @brief Flush job rings of any processed descs.
+ * The processed descs are silently dropped,
+ * WITHOUT being notified to UA.
+ */
+static void close_job_ring(struct sec_job_ring_t *job_ring)
+{
+       if (job_ring->irq_fd) {
+               /* 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, NULL);
+
+               /* free the uio job ring */
+               free_job_ring(job_ring->irq_fd);
+               job_ring->irq_fd = 0;
+               caam_jr_dma_free(job_ring->input_ring);
+               caam_jr_dma_free(job_ring->output_ring);
+
+               g_job_rings_no--;
+
+       }
+}
+
+/** @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
+ */
+static int shutdown_job_ring(struct sec_job_ring_t *job_ring)
+{
+       int ret = 0;
+
+       ASSERT(job_ring != NULL);
+       ret = hw_shutdown_job_ring(job_ring);
+       SEC_ASSERT(ret == 0, ret,
+               "Failed to shutdown hardware job ring %p",
+               job_ring);
+
+       if (job_ring->coalescing_en)
+               hw_job_ring_disable_coalescing(job_ring);
+
+       if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+               ret = caam_jr_disable_irqs(job_ring->irq_fd);
+               SEC_ASSERT(ret == 0, ret,
+               "Failed to disable irqs for job ring %p",
+               job_ring);
+       }
+
+       return ret;
+}
 
 /*
  * @brief Release the resources used by the SEC user space driver.
@@ -42,31 +175,195 @@ int caam_jr_logtype;
 static int
 caam_jr_dev_uninit(struct rte_cryptodev *dev)
 {
+       struct sec_job_ring_t *internals;
 
        if (dev == NULL)
                return -ENODEV;
 
+       internals = dev->data->dev_private;
+       rte_free(dev->security_ctx);
+
+
+       /* If any descriptors in flight , poll and wait
+        * until all descriptors are received and silently discarded.
+        */
+       if (internals) {
+               shutdown_job_ring(internals);
+               close_job_ring(internals);
+               rte_mempool_free(internals->ctx_pool);
+       }
 
        CAAM_JR_INFO("Closing DPAA_SEC device %s", dev->data->name);
 
+       /* last caam jr instance) */
+       if (g_job_rings_no == 0)
+               g_driver_state = SEC_DRIVER_STATE_IDLE;
 
-       return 0;
+       return SEC_SUCCESS;
 }
 
+/* @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
+ *                             of the three: #SEC_NOTIFICATION_TYPE_NAPI
+ *                             #SEC_NOTIFICATION_TYPE_IRQ or
+ *                             #SEC_NOTIFICATION_TYPE_POLL
+ * @param [in] NAPI_mode       The NAPI work mode to configure a job ring at
+ *                             startup. Used only when #SEC_NOTIFICATION_TYPE
+ *                             is set to #SEC_NOTIFICATION_TYPE_NAPI.
+ * @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
+ *
+ */
+static void *
+init_job_ring(void *reg_base_addr, uint32_t irq_id)
+{
+       struct sec_job_ring_t *job_ring = NULL;
+       int i, ret = 0;
+       int jr_mode = SEC_NOTIFICATION_TYPE_POLL;
+       int napi_mode = 0;
+       int irq_coalescing_timer = 0;
+       int irq_coalescing_count = 0;
+
+       for (i = 0; i < MAX_SEC_JOB_RINGS; i++) {
+               if (g_job_rings[i].irq_fd == 0) {
+                       job_ring = &g_job_rings[i];
+                       g_job_rings_no++;
+                       break;
+               }
+       }
+       if (job_ring == NULL) {
+               CAAM_JR_ERR("No free job ring\n");
+               return NULL;
+       }
+
+       job_ring->register_base_addr = reg_base_addr;
+       job_ring->jr_mode = jr_mode;
+       job_ring->napi_mode = 0;
+       job_ring->irq_fd = irq_id;
+
+       /* Allocate mem for input and output ring */
+
+       /* Allocate memory for input ring */
+       job_ring->input_ring = caam_jr_dma_mem_alloc(L1_CACHE_BYTES,
+                               SEC_DMA_MEM_INPUT_RING_SIZE);
+       memset(job_ring->input_ring, 0, SEC_DMA_MEM_INPUT_RING_SIZE);
+
+       /* Allocate memory for output ring */
+       job_ring->output_ring = caam_jr_dma_mem_alloc(L1_CACHE_BYTES,
+                               SEC_DMA_MEM_OUTPUT_RING_SIZE);
+       memset(job_ring->output_ring, 0, SEC_DMA_MEM_OUTPUT_RING_SIZE);
+
+       /* Reset job ring in SEC hw and configure job ring registers */
+       ret = hw_reset_job_ring(job_ring);
+       if (ret != 0) {
+               CAAM_JR_ERR("Failed to reset hardware job ring");
+               goto cleanup;
+       }
+
+       if (jr_mode == SEC_NOTIFICATION_TYPE_NAPI) {
+       /* When SEC US driver works in NAPI mode, the UA can select
+        * if the driver starts with IRQs on or off.
+        */
+               if (napi_mode == SEC_STARTUP_INTERRUPT_MODE) {
+                       CAAM_JR_INFO("Enabling DONE IRQ generationon job ring - 
%p",
+                               job_ring);
+                       ret = caam_jr_enable_irqs(job_ring->irq_fd);
+                       if (ret != 0) {
+                               CAAM_JR_ERR("Failed to enable irqs for job 
ring");
+                               goto cleanup;
+                       }
+               }
+       } else if (jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
+       /* When SEC US driver works in pure interrupt mode,
+        * IRQ's are always enabled.
+        */
+               CAAM_JR_INFO("Enabling DONE IRQ generation on job ring - %p",
+                        job_ring);
+               ret = caam_jr_enable_irqs(job_ring->irq_fd);
+               if (ret != 0) {
+                       CAAM_JR_ERR("Failed to enable irqs for job ring");
+                       goto cleanup;
+               }
+       }
+       if (irq_coalescing_timer || irq_coalescing_count) {
+               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;
+       job_ring->max_nb_queue_pairs = RTE_CAAM_MAX_NB_SEC_QPS;
+       job_ring->max_nb_sessions = RTE_CAAM_JR_PMD_MAX_NB_SESSIONS;
+
+       return job_ring;
+cleanup:
+       caam_jr_dma_free(job_ring->output_ring);
+       caam_jr_dma_free(job_ring->input_ring);
+       return NULL;
+}
+
+
 static int
 caam_jr_dev_init(const char *name,
                         struct rte_vdev_device *vdev,
                         struct rte_cryptodev_pmd_init_params *init_params)
 {
        struct rte_cryptodev *dev;
+       struct uio_job_ring *job_ring;
+       char str[RTE_CRYPTODEV_NAME_MAX_LEN];
 
        PMD_INIT_FUNC_TRACE();
 
+       /* Validate driver state */
+       if (g_driver_state == SEC_DRIVER_STATE_IDLE) {
+               g_job_rings_max = sec_configure();
+               if (!g_job_rings_max) {
+                       CAAM_JR_ERR("No job ring detected on UIO !!!!");
+                       return -1;
+               }
+               /* Update driver state */
+               g_driver_state = SEC_DRIVER_STATE_STARTED;
+       }
+
+       if (g_job_rings_no >= g_job_rings_max) {
+               CAAM_JR_ERR("No more job rings available max=%d!!!!",
+                               g_job_rings_max);
+               return -1;
+       }
+
+       job_ring = config_job_ring();
+       if (job_ring == NULL) {
+               CAAM_JR_ERR("failed to create job ring");
+               goto init_error;
+       }
+
+       snprintf(str, sizeof(str), "caam_jr%d", job_ring->jr_id);
+
        dev = rte_cryptodev_pmd_create(name, &vdev->device, init_params);
        if (dev == NULL) {
                CAAM_JR_ERR("failed to create cryptodev vdev");
                goto cleanup;
        }
+       /*TODO free it during teardown*/
+       dev->data->dev_private = init_job_ring(job_ring->register_base_addr,
+                                               job_ring->uio_fd);
+
+       if (!dev->data->dev_private) {
+               CAAM_JR_ERR("Ring memory allocation failed\n");
+               goto cleanup2;
+       }
 
        dev->driver_id = cryptodev_driver_id;
        dev->dev_ops = NULL;
@@ -84,7 +381,12 @@ caam_jr_dev_init(const char *name,
 
        return 0;
 
+cleanup2:
+       caam_jr_dev_uninit(dev);
+       rte_cryptodev_pmd_release_device(dev);
 cleanup:
+       free_job_ring(job_ring->uio_fd);
+init_error:
        CAAM_JR_ERR("driver %s: cryptodev_caam_jr_create failed",
                        init_params->name);
 
@@ -97,7 +399,7 @@ cryptodev_caam_jr_probe(struct rte_vdev_device *vdev)
 {
        struct rte_cryptodev_pmd_init_params init_params = {
                "",
-               128,
+               sizeof(struct sec_job_ring_t),
                rte_socket_id(),
                RTE_CRYPTODEV_PMD_DEFAULT_MAX_NB_QUEUE_PAIRS
        };
@@ -111,6 +413,29 @@ cryptodev_caam_jr_probe(struct rte_vdev_device *vdev)
        input_args = rte_vdev_device_args(vdev);
        rte_cryptodev_pmd_parse_input_args(&init_params, input_args);
 
+       /* if sec device version is not configured */
+       if (!rta_get_sec_era()) {
+               const struct device_node *caam_node;
+
+               for_each_compatible_node(caam_node, NULL, "fsl,sec-v4.0") {
+                       const uint32_t *prop = of_get_property(caam_node,
+                                       "fsl,sec-era",
+                                       NULL);
+                       if (prop) {
+                               rta_set_sec_era(
+                                       INTL_SEC_ERA(cpu_to_caam32(*prop)));
+                               break;
+                       }
+               }
+       }
+#ifdef RTE_LIBRTE_PMD_CAAM_JR_BE
+       if (rta_get_sec_era() > RTA_SEC_ERA_8) {
+               RTE_LOG(ERR, PMD,
+               "CAAM is compiled in BE mode for device with sec era > 8???\n");
+               return -EINVAL;
+       }
+#endif
+
        return caam_jr_dev_init(name, vdev, &init_params);
 }
 
diff --git a/drivers/crypto/caam_jr/caam_jr_config.h 
b/drivers/crypto/caam_jr/caam_jr_config.h
new file mode 100644
index 000000000..e7855cee6
--- /dev/null
+++ b/drivers/crypto/caam_jr/caam_jr_config.h
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017-2018 NXP
+ */
+
+#ifndef CAAM_JR_CONFIG_H
+#define CAAM_JR_CONFIG_H
+
+#include <rte_byteorder.h>
+
+#ifdef RTE_LIBRTE_PMD_CAAM_JR_BE
+#define CAAM_BYTE_ORDER __BIG_ENDIAN
+#else
+#define CAAM_BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+#define CORE_BYTE_ORDER __BIG_ENDIAN
+#else
+#define CORE_BYTE_ORDER __LITTLE_ENDIAN
+#endif
+
+typedef uint64_t       dma_addr_t;
+
+#if CORE_BYTE_ORDER != CAAM_BYTE_ORDER
+
+#define cpu_to_caam64 rte_cpu_to_be_64
+#define cpu_to_caam32 rte_cpu_to_be_32
+#else
+#define cpu_to_caam64
+#define cpu_to_caam32
+
+#endif
+
+/*
+ * SEC is configured to start work in polling mode,
+ * when configured for NAPI notification style.
+ */
+#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 NAPI model to receive notifications
+ * for processed packets from SEC engine hardware:
+ * - IRQ for low traffic
+ * - polling for high traffic.
+ */
+#define SEC_NOTIFICATION_TYPE_NAPI  0
+/*
+ * 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
+
+/*
+ * SEC USER SPACE DRIVER related configuration.
+ */
+
+/*
+ * 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
+ * and #SEC_NOTIFICATION_TYPE_NAPI.
+ */
+#define SEC_NOTIFICATION_TYPE   SEC_NOTIFICATION_TYPE_POLL
+
+/* Maximum number of job rings supported by SEC hardware */
+#define MAX_SEC_JOB_RINGS         4
+
+/* Maximum number of QP per job ring */
+#define RTE_CAAM_MAX_NB_SEC_QPS    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(dma_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 a job ring, including both input and 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))
+
+#define L1_CACHE_BYTES 64
+
+/* SEC JOB RING related configuration. */
+
+/*
+ * Configure the size of the JOB RING.
+ * The maximum size of the ring in 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 64 bytes.
+ *
+ * @note Round up to nearest power of 2 for optimized update
+ * of producer/consumer indexes of each job ring
+ */
+#define SEC_JOB_RING_SIZE     512
+
+/*
+ * 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   1
+/*
+ * 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 /* CAAM_JR_CONFIG_H */
diff --git a/drivers/crypto/caam_jr/caam_jr_hw.c 
b/drivers/crypto/caam_jr/caam_jr_hw.c
new file mode 100644
index 000000000..5baac95f8
--- /dev/null
+++ b/drivers/crypto/caam_jr/caam_jr_hw.c
@@ -0,0 +1,365 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017-2018 NXP
+ */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <rte_common.h>
+#include <rte_memory.h>
+#include <rte_malloc.h>
+#include <rte_crypto.h>
+#include <rte_security.h>
+#include <caam_jr_config.h>
+
+/* RTA header files */
+#include <hw/desc/common.h>
+#include <hw/desc/algo.h>
+#include <hw/desc/ipsec.h>
+
+#include <caam_jr_hw_specific.h>
+#include <caam_jr_pvt.h>
+#include <caam_jr_log.h>
+
+/* Used to retry resetting a job ring in SEC hardware. */
+#define SEC_TIMEOUT 100000
+
+/* @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) {
+       CAAM_JR_DEBUG("JMP: %d, Descriptor Index: 0x%x, Condition: 0x%x",
+                       error_code.error_desc.jmp_halt_cond_src.jmp,
+                       error_code.error_desc.jmp_halt_cond_src.desc_idx,
+                       error_code.error_desc.jmp_halt_cond_src.cond);
+       (void)error_code;
+}
+
+/* @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) {
+       CAAM_JR_DEBUG("JMP: %d, Descriptor Index: 0x%x",
+                       error_code.error_desc.deco_src.jmp,
+                       error_code.error_desc.deco_src.desc_idx);
+
+       switch (error_code.error_desc.deco_src.desc_err) {
+       case SEC_HW_ERR_DECO_HFN_THRESHOLD:
+               CAAM_JR_DEBUG(" Warning: Descriptor completed normally,"
+                       "but 3GPP HFN matches or exceeds the Threshold ");
+               break;
+       default:
+               CAAM_JR_DEBUG("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 __rte_unused)
+{
+       CAAM_JR_DEBUG(" 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 __rte_unused)
+{
+       CAAM_JR_DEBUG(" 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 __rte_unused)
+{
+       CAAM_JR_DEBUG(" Not implemented");
+}
+
+int hw_reset_job_ring(struct sec_job_ring_t *job_ring)
+{
+       int ret = 0;
+
+       ASSERT(job_ring->register_base_addr != NULL);
+
+       /* First reset the job ring in hw */
+       ret = hw_shutdown_job_ring(job_ring);
+       SEC_ASSERT(ret == 0, ret, "Failed resetting job ring in hardware");
+
+       /* 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 */
+       hw_set_input_ring_size(job_ring, SEC_JOB_RING_SIZE);
+
+       /* Write the JR output queue size to the HW register */
+       hw_set_output_ring_size(job_ring, SEC_JOB_RING_SIZE);
+
+       /* Write the JR input queue start address */
+       hw_set_input_ring_start_addr(job_ring,
+                       caam_jr_dma_vtop(job_ring->input_ring));
+       CAAM_JR_DEBUG(" Set input ring base address to : Virtual: 0x%" PRIx64
+                     ",Physical: 0x%" PRIx64 ", Read from HW: 0x%" PRIx64,
+                     (uint64_t)(uintptr_t)job_ring->input_ring,
+                     caam_jr_dma_vtop(job_ring->input_ring),
+                     hw_get_inp_queue_base(job_ring));
+
+       /* Write the JR output queue start address */
+       hw_set_output_ring_start_addr(job_ring,
+                       caam_jr_dma_vtop(job_ring->output_ring));
+       CAAM_JR_DEBUG(" Set output ring base address to: Virtual: 0x%" PRIx64
+                     ",Physical: 0x%" PRIx64 ", Read from HW: 0x%" PRIx64,
+                     (uint64_t)(uintptr_t)job_ring->output_ring,
+                     caam_jr_dma_vtop(job_ring->output_ring),
+                     hw_get_out_queue_base(job_ring));
+       return ret;
+}
+
+int hw_shutdown_job_ring(struct sec_job_ring_t *job_ring)
+{
+       unsigned int timeout = SEC_TIMEOUT;
+       uint32_t tmp = 0;
+       int usleep_interval = 10;
+
+       if (job_ring->register_base_addr == NULL) {
+               CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
+                       job_ring);
+               return 0;
+       }
+
+       CAAM_JR_INFO("Resetting Job ring %p", job_ring);
+
+       /*
+        * 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
+        */
+       caam_jr_disable_irqs(job_ring->irq_fd);
+
+       /* initiate flush (required prior to reset) */
+       SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
+
+       /* dummy read */
+       tmp = GET_JR_REG(JRCR, job_ring);
+
+       do {
+               tmp = GET_JR_REG(JRINT, job_ring);
+               usleep(usleep_interval);
+       } while (((tmp & JRINT_ERR_HALT_MASK) ==
+                       JRINT_ERR_HALT_INPROGRESS) && --timeout);
+
+       CAAM_JR_INFO("JRINT is %x", tmp);
+
+       if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE ||
+               timeout == 0) {
+               CAAM_JR_ERR("0x%x, %d", tmp, timeout);
+               /* unmask interrupts */
+               if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
+                       caam_jr_enable_irqs(job_ring->irq_fd);
+               return -1;
+       }
+
+       /* Initiate reset */
+       timeout = SEC_TIMEOUT;
+       SET_JR_REG(JRCR, job_ring, JR_REG_JRCR_VAL_RESET);
+
+       do {
+               tmp = GET_JR_REG(JRCR, job_ring);
+               usleep(usleep_interval);
+       } while ((tmp & JR_REG_JRCR_VAL_RESET) && --timeout);
+
+       CAAM_JR_DEBUG("JRCR is %x", tmp);
+
+       if (timeout == 0) {
+               CAAM_JR_ERR("Failed to reset hw job ring %p", job_ring);
+               /* unmask interrupts */
+               if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
+                       caam_jr_enable_irqs(job_ring->irq_fd);
+               return -1;
+       }
+       /* unmask interrupts */
+       if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL)
+               caam_jr_enable_irqs(job_ring->irq_fd);
+       return 0;
+
+}
+
+void hw_handle_job_ring_error(struct sec_job_ring_t *job_ring __rte_unused,
+                       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:
+               ASSERT(hw_err_code.error_desc.no_status_src.res == 0);
+               CAAM_JR_ERR("No Status Source ");
+               break;
+       case SEC_HW_ERR_SSRC_CCB_ERR:
+               CAAM_JR_ERR("CCB Status Source");
+               hw_handle_ccb_err(hw_err_code);
+               break;
+       case SEC_HW_ERR_SSRC_JMP_HALT_U:
+               CAAM_JR_ERR("Jump Halt User Status Source");
+               hw_handle_jmp_halt_user_err(hw_err_code);
+               break;
+       case SEC_HW_ERR_SSRC_DECO:
+               CAAM_JR_ERR("DECO Status Source");
+               hw_handle_deco_err(hw_err_code);
+               break;
+       case SEC_HW_ERR_SSRC_JR:
+               CAAM_JR_ERR("Job Ring Status Source");
+               hw_handle_jr_err(hw_err_code);
+               break;
+       case SEC_HW_ERR_SSRC_JMP_HALT_COND:
+               CAAM_JR_ERR("Jump Halt Condition Codes");
+               hw_handle_jmp_halt_cond_err(hw_err_code);
+               break;
+       default:
+               ASSERT(0);
+               CAAM_JR_ERR("Unknown SSRC");
+               break;
+       }
+}
+
+void hw_job_ring_error_print(struct sec_job_ring_t *job_ring, int code)
+{
+       switch (code) {
+       case JRINT_ERR_WRITE_STATUS:
+               CAAM_JR_ERR("Error writing status to Output Ring ");
+               break;
+       case JRINT_ERR_BAD_INPUT_BASE:
+               CAAM_JR_ERR(
+               "Bad Input Ring Base (%p) (not on a 4-byte boundary) ",
+               (void *)job_ring);
+               break;
+       case JRINT_ERR_BAD_OUTPUT_BASE:
+               CAAM_JR_ERR(
+               "Bad Output Ring Base (%p) (not on a 4-byte boundary) ",
+               (void *)job_ring);
+               break;
+       case JRINT_ERR_WRITE_2_IRBA:
+               CAAM_JR_ERR(
+               "Invalid write to Input Ring Base Address Register ");
+               break;
+       case JRINT_ERR_WRITE_2_ORBA:
+               CAAM_JR_ERR(
+               "Invalid write to Output Ring Base Address Register ");
+               break;
+       case JRINT_ERR_RES_B4_HALT:
+               CAAM_JR_ERR(
+               "Job Ring [%p] released before Job Ring is halted",
+               (void *)job_ring);
+               break;
+       case JRINT_ERR_REM_TOO_MANY:
+               CAAM_JR_ERR("Removed too many jobs from job ring [%p]",
+                       (void *)job_ring);
+               break;
+       case JRINT_ERR_ADD_TOO_MANY:
+               CAAM_JR_ERR("Added too many jobs on job ring [%p]", job_ring);
+               break;
+       default:
+               CAAM_JR_ERR(" Unknown SEC JR Error :%d",
+                               code);
+               break;
+       }
+}
+
+int hw_job_ring_set_coalescing_param(struct sec_job_ring_t *job_ring,
+                               uint16_t irq_coalescing_timer,
+                               uint8_t irq_coalescing_count)
+{
+       uint32_t reg_val = 0;
+
+       ASSERT(job_ring != NULL);
+
+       if (job_ring->register_base_addr == NULL) {
+               CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
+                       job_ring);
+               return -1;
+       }
+       /* 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 */
+       SET_JR_REG_LO(JRCFG, job_ring, reg_val);
+
+       CAAM_JR_DEBUG("Set coalescing params on jr %p timer:%d, desc count: %d",
+                       job_ring, irq_coalescing_timer, irq_coalescing_timer);
+
+       return 0;
+}
+
+int hw_job_ring_enable_coalescing(struct sec_job_ring_t *job_ring)
+{
+       uint32_t reg_val = 0;
+
+       ASSERT(job_ring != NULL);
+       if (job_ring->register_base_addr == NULL) {
+               CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
+                       job_ring);
+               return -1;
+       }
+
+       /* Get the current value of the register */
+       reg_val = GET_JR_REG_LO(JRCFG, job_ring);
+
+       /* Enable coalescing */
+       reg_val |= JR_REG_JRCFG_LO_ICEN_EN;
+
+       /* Write in hw */
+       SET_JR_REG_LO(JRCFG, job_ring, reg_val);
+
+       CAAM_JR_DEBUG("Enabled coalescing on jr %p ",
+                       job_ring);
+
+       return 0;
+}
+
+int hw_job_ring_disable_coalescing(struct sec_job_ring_t *job_ring)
+{
+       uint32_t reg_val = 0;
+
+       ASSERT(job_ring != NULL);
+
+       if (job_ring->register_base_addr == NULL) {
+               CAAM_JR_ERR("Jr[%p] has reg base addr as NULL.driver not init",
+                       job_ring);
+               return -1;
+       }
+
+       /* Get the current value of the register */
+       reg_val = GET_JR_REG_LO(JRCFG, job_ring);
+
+       /* Disable coalescing */
+       reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN;
+
+       /* Write in hw */
+       SET_JR_REG_LO(JRCFG, job_ring, reg_val);
+
+       CAAM_JR_DEBUG("Disabled coalescing on jr %p ", job_ring);
+
+       return 0;
+
+}
diff --git a/drivers/crypto/caam_jr/caam_jr_hw_specific.h 
b/drivers/crypto/caam_jr/caam_jr_hw_specific.h
new file mode 100644
index 000000000..7c8909d2b
--- /dev/null
+++ b/drivers/crypto/caam_jr/caam_jr_hw_specific.h
@@ -0,0 +1,503 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017 NXP
+ */
+
+#ifndef CAAM_JR_HW_SPECIFIC_H
+#define CAAM_JR_HW_SPECIFIC_H
+
+#include <caam_jr_config.h>
+
+/*
+ * Offset to the registers of a job ring.
+ * Is different for each job ring.
+ */
+#define CHAN_BASE(jr)   ((size_t)(jr)->register_base_addr)
+
+#ifndef unlikely
+#define unlikely(x)     __builtin_expect(!!(x), 0)
+#endif
+
+#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))
+
+/*
+ * Assert that cond is true. If !cond is true, display str and the vararg list
+ * in a printf-like syntax. also, if !cond is true, return altRet.
+ *
+ * \param cond          A boolean expression to be asserted true
+ * \param altRet        The value to be returned if cond doesn't hold true
+ * \param str           A quoted char string
+ *
+ * E.g.:
+ *      SEC_ASSERT(ret > 0, 0, "ERROR initializing app: code = %d\n", ret);
+ */
+#define SEC_ASSERT(cond, altRet, ...) {\
+       if (unlikely(!(cond))) {\
+               CAAM_JR_ERR(__VA_ARGS__); \
+                       return altRet; \
+       } \
+}
+
+#define SEC_DP_ASSERT(cond, altRet, ...) {\
+       if (unlikely(!(cond))) {\
+               CAAM_JR_DP_ERR(__VA_ARGS__); \
+                       return altRet; \
+       } \
+}
+
+#define ASSERT(x)
+
+/*
+ * Constants representing various job ring registers
+ */
+#if CAAM_BYTE_ORDER == __BIG_ENDIAN
+#define JR_REG_IRBA_OFFSET             0x0000
+#define JR_REG_IRBA_OFFSET_LO          0x0004
+#else
+#define JR_REG_IRBA_OFFSET             0x0004
+#define JR_REG_IRBA_OFFSET_LO          0x0000
+#endif
+
+#define JR_REG_IRSR_OFFSET             0x000C
+#define JR_REG_IRSA_OFFSET             0x0014
+#define JR_REG_IRJA_OFFSET             0x001C
+
+#if CAAM_BYTE_ORDER == __BIG_ENDIAN
+#define JR_REG_ORBA_OFFSET             0x0020
+#define JR_REG_ORBA_OFFSET_LO          0x0024
+#else
+#define JR_REG_ORBA_OFFSET             0x0024
+#define JR_REG_ORBA_OFFSET_LO          0x0020
+#endif
+
+#define JR_REG_ORSR_OFFSET             0x002C
+#define JR_REG_ORJR_OFFSET             0x0034
+#define JR_REG_ORSFR_OFFSET            0x003C
+#define JR_REG_JROSR_OFFSET            0x0044
+#define JR_REG_JRINT_OFFSET            0x004C
+
+#define JR_REG_JRCFG_OFFSET            0x0050
+#define JR_REG_JRCFG_OFFSET_LO         0x0054
+
+#define JR_REG_IRRI_OFFSET             0x005C
+#define JR_REG_ORWI_OFFSET             0x0064
+#define JR_REG_JRCR_OFFSET             0x006C
+
+/*
+ * 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
+
+/*
+ * 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
+
+/*
+ * Constants for descriptors
+ */
+/* 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)
+
+/*
+ * 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 managing the job ring
+ */
+/* Read pointer to job ring input ring start address */
+#if defined(RTE_ARCH_ARM64)
+#define hw_get_inp_queue_base(jr) ((((dma_addr_t)GET_JR_REG(IRBA, (jr))) << 
32) | \
+                                       (GET_JR_REG_LO(IRBA, (jr))))
+
+/* Read pointer to job ring output ring start address */
+#define hw_get_out_queue_base(jr)   (((dma_addr_t)(GET_JR_REG(ORBA, (jr))) << 
32) | \
+                                       (GET_JR_REG_LO(ORBA, (jr))))
+#else
+#define hw_get_inp_queue_base(jr)   ((dma_addr_t)(GET_JR_REG_LO(IRBA, (jr))))
+
+#define hw_get_out_queue_base(jr)   ((dma_addr_t)(GET_JR_REG_LO(ORBA, (jr))))
+#endif
+
+/*
+ * IRJA - Input Ring Jobs Added Register shows
+ * how many new jobs were added to the Input Ring.
+ */
+#define hw_enqueue_desc_on_job_ring(job_ring) SET_JR_REG(IRJA, (job_ring), 1)
+
+#define hw_set_input_ring_size(job_ring, size) SET_JR_REG(IRSR, job_ring, 
(size))
+
+#define hw_set_output_ring_size(job_ring, size) SET_JR_REG(ORSR, job_ring, 
(size))
+
+#if defined(RTE_ARCH_ARM64)
+#define hw_set_input_ring_start_addr(job_ring, start_addr)     \
+{                                                              \
+       SET_JR_REG(IRBA, job_ring, PHYS_ADDR_HI(start_addr));   \
+       SET_JR_REG_LO(IRBA, job_ring, PHYS_ADDR_LO(start_addr));\
+}
+
+#define hw_set_output_ring_start_addr(job_ring, start_addr) \
+{                                                              \
+       SET_JR_REG(ORBA, job_ring, PHYS_ADDR_HI(start_addr));   \
+       SET_JR_REG_LO(ORBA, job_ring, PHYS_ADDR_LO(start_addr));\
+}
+
+#else
+#define hw_set_input_ring_start_addr(job_ring, start_addr)     \
+{                                                              \
+       SET_JR_REG(IRBA, job_ring, 0);  \
+       SET_JR_REG_LO(IRBA, job_ring, PHYS_ADDR_LO(start_addr));\
+}
+
+#define hw_set_output_ring_start_addr(job_ring, start_addr) \
+{                                                              \
+       SET_JR_REG(ORBA, job_ring, 0);  \
+       SET_JR_REG_LO(ORBA, job_ring, PHYS_ADDR_LO(start_addr));\
+}
+#endif
+
+/* 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.
+ */
+#define hw_remove_entries(jr, no_entries) SET_JR_REG(ORJR, (jr), (no_entries))
+
+/* 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.
+ */
+#define hw_get_available_slots(jr)             GET_JR_REG(IRSA, jr)
+
+/* 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.
+ */
+#define hw_get_no_finished_jobs(jr)            GET_JR_REG(ORSFR, jr)
+
+/*
+ * Macros for manipulating JR registers
+ */
+#if CORE_BYTE_ORDER == CAAM_BYTE_ORDER
+#define sec_read_32(addr)      (*(volatile unsigned int *)(addr))
+#define sec_write_32(addr, val)        (*(volatile unsigned int *)(addr) = 
(val))
+
+#else
+#define sec_read_32(addr)      rte_bswap32((*(volatile unsigned int *)(addr)))
+#define sec_write_32(addr, val) \
+                       (*(volatile unsigned int *)(addr) = rte_bswap32(val))
+#endif
+
+#if CAAM_BYTE_ORDER == __LITTLE_ENDIAN
+#define sec_read_64(addr)      (((u64)sec_read_32((u32 *)(addr) + 1) << 32) | \
+                               (sec_read_32((u32 *)(addr))))
+
+#define sec_write_64(addr, val) {                              \
+       sec_write_32((u32 *)(addr) + 1, (u32)((val) >> 32));    \
+       sec_write_32((u32 *)(addr), (u32)(val));                \
+}
+#else /* CAAM_BYTE_ORDER == __BIG_ENDIAN */
+#define sec_read_64(addr)      (((u64)sec_read_32((u32 *)(addr)) << 32) | \
+                               (sec_read_32((u32 *)(addr) + 1)))
+
+#define sec_write_64(addr, val) {                              \
+       sec_write_32((u32 *)(addr), (u32)((val) >> 32));        \
+       sec_write_32((u32 *)(addr) + 1, (u32)(val));            \
+}
+#endif
+
+#if defined(RTE_ARCH_ARM64)
+#define sec_read_addr(a)       sec_read_64((a))
+#define sec_write_addr(a, v)   sec_write_64((a), (v))
+#else
+#define sec_read_addr(a)       sec_read_32((a))
+#define sec_write_addr(a, v)   sec_write_32((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_read_32(JR_REG(name, (jr))))
+#define GET_JR_REG_LO(name, jr)        (sec_read_32(JR_REG_LO(name, (jr))))
+
+#define SET_JR_REG(name, jr, value) \
+                               (sec_write_32(JR_REG(name, (jr)), value))
+#define SET_JR_REG_LO(name, jr, value) \
+                               (sec_write_32(JR_REG_LO(name, (jr)), value))
+
+/* 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 progress */
+} sec_job_ring_state_t;
+
+/* code or cmd block to caam */
+struct sec_cdb {
+       struct {
+               union {
+                       uint32_t word;
+                       struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+                               uint16_t rsvd63_48;
+                               unsigned int rsvd47_39:9;
+                               unsigned int idlen:7;
+#else
+                               unsigned int idlen:7;
+                               unsigned int rsvd47_39:9;
+                               uint16_t rsvd63_48;
+#endif
+                       } field;
+               } __rte_packed hi;
+
+               union {
+                       uint32_t word;
+                       struct {
+#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
+                               unsigned int rsvd31_30:2;
+                               unsigned int fsgt:1;
+                               unsigned int lng:1;
+                               unsigned int offset:2;
+                               unsigned int abs:1;
+                               unsigned int add_buf:1;
+                               uint8_t pool_id;
+                               uint16_t pool_buffer_size;
+#else
+                               uint16_t pool_buffer_size;
+                               uint8_t pool_id;
+                               unsigned int add_buf:1;
+                               unsigned int abs:1;
+                               unsigned int offset:2;
+                               unsigned int lng:1;
+                               unsigned int fsgt:1;
+                               unsigned int rsvd31_30:2;
+#endif
+                       } field;
+               } __rte_packed lo;
+       } __rte_packed sh_hdr;
+
+       uint32_t sh_desc[SEC_JOB_DESCRIPTOR_SIZE];
+};
+
+struct caam_jr_qp {
+       struct sec_job_ring_t *ring;
+       uint64_t rx_pkts;
+       uint64_t rx_errs;
+       uint64_t rx_poll_err;
+       uint64_t tx_pkts;
+       uint64_t tx_errs;
+       uint64_t tx_ring_full;
+};
+
+struct sec_job_ring_t {
+       /* TODO: Add wrapper macro to make it obvious this is the consumer index
+        * on the output ring
+        */
+       uint32_t cidx;          /* 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!
+                                */
+       /* TODO: Add wrapper macro to make it obvious this is the producer index
+        * on the input ring
+        */
+       uint32_t pidx;          /* Producer index for job ring (jobs array) */
+
+       phys_addr_t *input_ring;/* Ring of output descriptors received from SEC.
+                                * Size of array is power of 2 to allow fast
+                                * update of producer/consumer indexes with
+                                * bitwise operations.
+                                */
+
+       struct sec_outring_entry *output_ring;
+                               /* Ring of output descriptors received from SEC.
+                                * Size of array is power of 2 to allow fast
+                                * update of producer/consumer indexes with
+                                * bitwise operations.
+                                */
+
+       uint32_t irq_fd;        /* The file descriptor used for polling from
+                                * user space for interrupts notifications
+                                */
+       uint32_t jr_mode;       /* Model used by SEC Driver to receive
+                                * notifications from SEC.  Can be either
+                                * of the three: #SEC_NOTIFICATION_TYPE_NAPI
+                                * #SEC_NOTIFICATION_TYPE_IRQ or
+                                * #SEC_NOTIFICATION_TYPE_POLL
+                                */
+       uint32_t napi_mode;     /* Job ring mode if NAPI mode is chosen
+                                * Used only when jr_mode is set to
+                                * #SEC_NOTIFICATION_TYPE_NAPI
+                                */
+       void *register_base_addr;       /* Base address for SEC's
+                                        * register memory for this job ring.
+                                        */
+       uint8_t coalescing_en;          /* notifies if coelescing is
+                                        * enabled for the job ring
+                                        */
+       sec_job_ring_state_t jr_state;  /* The state of this job ring */
+
+       struct rte_mempool *ctx_pool;   /* per dev mempool for caam_jr_op_ctx */
+       unsigned int max_nb_queue_pairs;
+       unsigned int max_nb_sessions;
+       struct caam_jr_qp qps[RTE_CAAM_MAX_NB_SEC_QPS]; /* i/o queue for sec */
+};
+
+/* 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;
+               } __rte_packed value;
+               struct {
+                       uint32_t ssrc:4;
+                       uint32_t res:28;
+               } __rte_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;
+               } __rte_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;
+               } __rte_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;
+               } __rte_packed deco_src;
+               struct {
+                       uint32_t ssrc:4;
+                       uint32_t res:17;
+                       uint32_t naddr:3;
+                       uint32_t desc_err:8;
+               } __rte_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;
+               } __rte_packed jmp_halt_cond_src;
+       } __rte_packed error_desc;
+} __rte_packed;
+
+/* @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(struct 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(struct 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  The job ring's error code
+ */
+void hw_handle_job_ring_error(struct 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
+ *
+ */
+void hw_job_ring_error_print(struct sec_job_ring_t *job_ring, int code);
+
+/* @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 descriptor count
+ *                                     threshold.
+ */
+int hw_job_ring_set_coalescing_param(struct 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(struct 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(struct sec_job_ring_t *job_ring);
+
+#endif /* CAAM_JR_HW_SPECIFIC_H */
diff --git a/drivers/crypto/caam_jr/caam_jr_pvt.h 
b/drivers/crypto/caam_jr/caam_jr_pvt.h
new file mode 100644
index 000000000..cc0aa65f1
--- /dev/null
+++ b/drivers/crypto/caam_jr/caam_jr_pvt.h
@@ -0,0 +1,285 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017-2018 NXP
+ */
+
+#ifndef CAAM_JR_PVT_H
+#define CAAM_JR_PVT_H
+
+/* NXP CAAM JR PMD device name */
+
+#define CAAM_JR_ALG_UNSUPPORT  (-1)
+
+/* Minimum job descriptor consists of a oneword job descriptor HEADER and
+ * a pointer to the shared descriptor.
+ */
+#define MIN_JOB_DESC_SIZE      (CAAM_CMD_SZ + CAAM_PTR_SZ)
+#define CAAM_JOB_DESC_SIZE     13
+
+/* CTX_POOL_NUM_BUFS is set as per the ipsec-secgw application */
+#define CTX_POOL_NUM_BUFS      32000
+#define CTX_POOL_CACHE_SIZE    512
+
+#define DIR_ENC                 1
+#define DIR_DEC                 0
+
+#define JR_MAX_NB_MAX_DIGEST   32
+
+#define RTE_CAAM_JR_PMD_MAX_NB_SESSIONS 2048
+
+
+/* Return codes for SEC user space driver APIs */
+enum sec_return_code_e {
+       SEC_SUCCESS = 0,               /* Operation executed successfully.*/
+       SEC_INVALID_INPUT_PARAM,       /* API received an invalid input
+                                       * parameter
+                                       */
+       SEC_OUT_OF_MEMORY,             /* Memory allocation failed. */
+       SEC_DESCRIPTOR_IN_FLIGHT,      /* API function indicates there are
+                                       * descriptors in flight
+                                       * for SEC to process.
+                                       */
+       SEC_LAST_DESCRIPTOR_IN_FLIGHT, /* API function indicates there is one
+                                       * last descriptor in flight
+                                       * for SEC to process that.
+                                       */
+       SEC_PROCESSING_ERROR,          /* Indicates a SEC processing error
+                                       * occurred on a Job Ring which requires
+                                       * a SEC user space driver shutdown. Can
+                                       * be returned from sec_poll_job_ring().
+                                       * Then the only other API that can be
+                                       * called after this error is
+                                       * sec_release().
+                                       */
+       SEC_DESC_PROCESSING_ERROR,     /* Indicates a SEC descriptor processing
+                                       * error occurred on a Job Ring. Can be
+                                       * returned from sec_poll_job_ring().
+                                       * The driver was able to reset job ring
+                                       * and job ring can be used like in a
+                                       * normal case.
+                                       */
+       SEC_JR_IS_FULL,                 /* Job Ring is full. There is no more
+                                        * room in the JR for new descriptors.
+                                        * This can happen if the descriptor RX
+                                        * rate is higher than SEC's capacity.
+                                        */
+       SEC_DRIVER_RELEASE_IN_PROGRESS, /* SEC driver shutdown is in progress,
+                                        * descriptors processing or polling is
+                                        * allowed.
+                                        */
+       SEC_DRIVER_ALREADY_INITIALIZED, /* SEC driver is already initialized.*/
+       SEC_DRIVER_NOT_INITIALIZED,     /* SEC driver is NOT initialized. */
+       SEC_JOB_RING_RESET_IN_PROGRESS, /* Job ring is resetting due to a
+                                        * per-descriptor SEC processing error
+                                        * ::SEC_desc_PROCESSING_ERROR. Reset is
+                                        * finished when sec_poll_job_ring()
+                                        * return. Then the job ring can be used
+                                        * again.
+                                        */
+       SEC_RESET_ENGINE_FAILED,        /* Resetting of SEC Engine by SEC Kernel
+                                        * Driver Failed
+                                        */
+       SEC_ENABLE_IRQS_FAILED,         /* Enabling of IRQs in SEC Kernel Driver
+                                        * Failed
+                                        */
+       SEC_DISABLE_IRQS_FAILED,        /* Disabling of IRQs in SEC Kernel
+                                        * Driver Failed
+                                        */
+       /* END OF VALID VALUES */
+
+       SEC_RETURN_CODE_MAX_VALUE,      /* Invalid value for return code. It is
+                                        * used to mark the end of the return
+                                        * code values. @note ALL new return
+                                        * code values MUST be added before
+                                        * ::SEC_RETURN_CODE_MAX_VALUE!
+                                        */
+};
+
+enum caam_jr_op_type {
+       CAAM_JR_NONE,  /* No Cipher operations*/
+       CAAM_JR_CIPHER,/* CIPHER operations */
+       CAAM_JR_AUTH,  /* Authentication Operations */
+       CAAM_JR_AEAD,  /* Authenticated Encryption with associated data */
+       CAAM_JR_IPSEC, /* IPSEC protocol operations*/
+       CAAM_JR_PDCP,  /* PDCP protocol operations*/
+       CAAM_JR_PKC,   /* Public Key Cryptographic Operations */
+       CAAM_JR_MAX
+};
+
+struct caam_jr_session {
+       uint8_t dir;         /* Operation Direction */
+       enum rte_crypto_cipher_algorithm cipher_alg; /* Cipher Algorithm*/
+       enum rte_crypto_auth_algorithm auth_alg; /* Authentication Algorithm*/
+       enum rte_crypto_aead_algorithm aead_alg; /* AEAD Algorithm*/
+       union {
+               struct {
+                       uint8_t *data;  /* pointer to key data */
+                       size_t length;  /* key length in bytes */
+               } aead_key;
+               struct {
+                       struct {
+                               uint8_t *data;  /* pointer to key data */
+                               size_t length;  /* key length in bytes */
+                       } cipher_key;
+                       struct {
+                               uint8_t *data;  /* pointer to key data */
+                               size_t length;  /* key length in bytes */
+                       } auth_key;
+               };
+       };
+       struct {
+               uint16_t length;
+               uint16_t offset;
+       } iv;   /* Initialisation vector parameters */
+       uint16_t auth_only_len; /* Length of data for Auth only */
+       uint32_t digest_length;
+       struct ip ip4_hdr;
+       struct caam_jr_qp *qp;
+       struct sec_cdb *cdb;    /* cmd block associated with qp */
+       struct rte_mempool *ctx_pool; /* session mempool for caam_jr_op_ctx */
+};
+
+/*
+ * 16-byte hardware scatter/gather table
+ */
+
+#define SEC4_SG_LEN_EXT                0x80000000      /* Entry points to 
table */
+#define SEC4_SG_LEN_FIN                0x40000000      /* Last ent in table */
+#define SEC4_SG_BPID_MASK      0x000000ff
+#define SEC4_SG_BPID_SHIFT     16
+#define SEC4_SG_LEN_MASK       0x3fffffff      /* Excludes EXT and FINAL */
+#define SEC4_SG_OFFSET_MASK    0x00001fff
+
+struct sec4_sg_entry {
+       uint64_t ptr;
+       uint32_t len;
+       uint32_t bpid_offset;
+};
+
+#define MAX_SG_ENTRIES         16
+#define SG_CACHELINE_0         0
+#define SG_CACHELINE_1         4
+#define SG_CACHELINE_2         8
+#define SG_CACHELINE_3         12
+
+/* 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[CAAM_JOB_DESC_SIZE];
+};
+
+struct caam_jr_op_ctx {
+       struct job_descriptor jobdes;
+       /* sg[0] output, sg[1] input, others are possible sub frames */
+       struct sec4_sg_entry sg[MAX_SG_ENTRIES];
+       struct rte_crypto_op *op;
+       struct rte_mempool *ctx_pool; /* mempool pointer for caam_jr_op_ctx */
+       int64_t vtop_offset;
+       uint8_t digest[JR_MAX_NB_MAX_DIGEST];
+};
+
+/**
+ * Checksum
+ *
+ * @param buffer calculate chksum for buffer
+ * @param len    buffer length
+ *
+ * @return checksum value in host cpu order
+ */
+static inline uint16_t
+calc_chksum(void *buffer, int len)
+{
+       uint16_t *buf = (uint16_t *)buffer;
+       uint32_t sum = 0;
+       uint16_t result;
+
+       for (sum = 0; len > 1; len -= 2)
+               sum += *buf++;
+
+       if (len == 1)
+               sum += *(unsigned char *)buf;
+
+       sum = (sum >> 16) + (sum & 0xFFFF);
+       sum += (sum >> 16);
+       result = ~sum;
+
+       return  result;
+}
+struct uio_job_ring {
+       uint32_t jr_id;
+       uint32_t uio_fd;
+       void *register_base_addr;
+       int map_size;
+       int uio_minor_number;
+};
+
+int sec_cleanup(void);
+int sec_configure(void);
+struct uio_job_ring *config_job_ring(void);
+void free_job_ring(uint32_t uio_fd);
+
+/* For Dma memory allocation of specified length and alignment */
+static inline void *caam_jr_dma_mem_alloc(size_t align, size_t len)
+{
+       return rte_malloc("mem_alloc", len, align);
+}
+
+/* For freeing dma memory */
+static inline void caam_jr_dma_free(void *ptr)
+{
+       rte_free(ptr);
+}
+
+static inline rte_iova_t
+caam_jr_mem_vtop(void *vaddr)
+{
+       const struct rte_memseg *ms;
+
+       ms = rte_mem_virt2memseg(vaddr, NULL);
+       if (ms)
+               return ms->iova + RTE_PTR_DIFF(vaddr, ms->addr);
+       return (size_t)NULL;
+}
+
+static inline void *
+caam_jr_dma_ptov(rte_iova_t paddr)
+{
+       return rte_mem_iova2virt(paddr);
+}
+
+/* Virtual to physical address conversion */
+static inline rte_iova_t caam_jr_dma_vtop(void *ptr)
+{
+       //return rte_malloc_virt2iova(ptr);
+       return caam_jr_mem_vtop(ptr);
+}
+
+/** @brief Request to SEC kernel driver to enable interrupts for
+ *         descriptor finished processing
+ *  Use UIO to communicate with SEC kernel driver: write command
+ *  value that indicates an IRQ enable action into UIO file descriptor
+ *  of this job ring.
+ *
+ * @param [in]  uio_fd     Job Ring UIO File descriptor
+ * @retval 0 for success
+ * @retval -1 value for error
+ */
+uint32_t caam_jr_enable_irqs(uint32_t uio_fd);
+
+/** @brief Request to SEC kernel driver to disable interrupts for descriptor
+ *  finished processing
+ *  Use UIO to communicate with SEC kernel driver: write command
+ *  value that indicates an IRQ disable action into UIO file descriptor
+ *  of this job ring.
+ *
+ * @param [in]  uio_fd    UIO File descripto
+ * @retval 0 for success
+ * @retval -1 value for error
+ *
+ */
+uint32_t caam_jr_disable_irqs(uint32_t uio_fd);
+
+#endif
diff --git a/drivers/crypto/caam_jr/caam_jr_uio.c 
b/drivers/crypto/caam_jr/caam_jr_uio.c
new file mode 100644
index 000000000..bc9ace07e
--- /dev/null
+++ b/drivers/crypto/caam_jr/caam_jr_uio.c
@@ -0,0 +1,491 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2017-2018 NXP
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <rte_common.h>
+#include <rte_malloc.h>
+#include <rte_crypto.h>
+#include <rte_security.h>
+#include <caam_jr_config.h>
+
+/* RTA header files */
+#include <hw/desc/common.h>
+#include <hw/desc/algo.h>
+#include <hw/desc/ipsec.h>
+
+#include <caam_jr_hw_specific.h>
+#include <caam_jr_pvt.h>
+#include <caam_jr_log.h>
+
+/* Prefix path to sysfs directory where UIO device attributes are exported.
+ * Path for UIO device X is /sys/class/uio/uioX
+ */
+#define SEC_UIO_DEVICE_SYS_ATTR_PATH    "/sys/class/uio"
+
+/* Subfolder in sysfs where mapping attributes are exported
+ * for each UIO device. Path for mapping Y for device X is:
+ *      /sys/class/uio/uioX/maps/mapY
+ */
+#define SEC_UIO_DEVICE_SYS_MAP_ATTR     "maps/map"
+
+/* Name of UIO device file prefix. Each UIO device will have a device file
+ * /dev/uioX, where X is the minor device number.
+ */
+#define SEC_UIO_DEVICE_FILE_NAME    "/dev/uio"
+
+/*
+ * Name of UIO device. Each user space SEC job ring will have a corresponding
+ * UIO device with the name sec-channelX, where X is the job ring id.
+ * Maximum length is #SEC_UIO_MAX_DEVICE_NAME_LENGTH.
+ *
+ * @note  Must be kept in synch with SEC kernel driver
+ * define #SEC_UIO_DEVICE_NAME !
+ */
+#define SEC_UIO_DEVICE_NAME     "fsl-jr"
+
+/* Maximum length for the name of an UIO device file.
+ * Device file name format is: /dev/uioX.
+ */
+#define SEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH 30
+
+/* Maximum length for the name of an attribute file for an UIO device.
+ * Attribute files are exported in sysfs and have the name formatted as:
+ *      /sys/class/uio/uioX/<attribute_file_name>
+ */
+#define SEC_UIO_MAX_ATTR_FILE_NAME  100
+
+/* Command that is used by SEC user space driver and SEC kernel driver
+ *  to signal a request from the former to the later to disable job DONE
+ *  and error IRQs on a certain job ring.
+ *  The configuration is done at SEC Controller's level.
+ *  @note   Need to be kept in synch with #SEC_UIO_DISABLE_IRQ_CMD from
+ *          linux/drivers/crypto/talitos.c !
+ */
+#define SEC_UIO_DISABLE_IRQ_CMD     0
+
+/* Command that is used by SEC user space driver and SEC kernel driver
+ *  to signal a request from the former to the later to enable job DONE
+ *  and error IRQs on a certain job ring.
+ *  The configuration is done at SEC Controller's level.
+ *  @note   Need to be kept in synch with #SEC_UIO_ENABLE_IRQ_CMD from
+ *          linux/drivers/crypto/talitos.c !
+ */
+#define SEC_UIO_ENABLE_IRQ_CMD      1
+
+/** Command that is used by SEC user space driver and SEC kernel driver
+ *  to signal a request from the former to the later to do a SEC engine reset.
+ *  @note   Need to be kept in synch with #SEC_UIO_RESET_SEC_ENGINE_CMD from
+ *          linux/drivers/crypto/talitos.c !
+ */
+#define SEC_UIO_RESET_SEC_ENGINE_CMD    3
+
+/* The id for the mapping used to export SEC's registers to
+ * user space through UIO devices.
+ */
+#define SEC_UIO_MAP_ID              0
+
+static struct uio_job_ring g_uio_job_ring[MAX_SEC_JOB_RINGS];
+static int g_uio_jr_num;
+
+/** @brief Checks if a file name contains a certain substring.
+ * If so, it extracts the number following the substring.
+ * This function assumes a filename format of: [text][number].
+ * @param [in]  filename    File name
+ * @param [in]  match       String to match in file name
+ * @param [out] number      The number extracted from filename
+ *
+ * @retval true if file name matches the criteria
+ * @retval false if file name does not match the criteria
+ */
+static bool
+file_name_match_extract(const char filename[], const char match[], int *number)
+{
+       char *substr = NULL;
+
+       substr = strstr(filename, match);
+       if (substr == NULL)
+               return false;
+
+       /* substring <match> was found in <filename>
+        * read number following <match> substring in <filename>
+        */
+       sscanf(filename + strlen(match), "%d", number);
+       return true;
+}
+
+/** @brief Reads first line from a file.
+ * Composes file name as: root/subdir/filename
+ *
+ * @param [in]  root     Root path
+ * @param [in]  subdir   Subdirectory name
+ * @param [in]  filename File name
+ * @param [out] line     The first line read from file.
+ *
+ * @retval 0 for succes
+ * @retval other value for error
+ */
+static int
+file_read_first_line(const char root[], const char subdir[],
+                   const char filename[], char *line)
+{
+       char absolute_file_name[SEC_UIO_MAX_ATTR_FILE_NAME];
+       int fd = 0, ret = 0;
+
+       /*compose the file name: root/subdir/filename */
+       memset(absolute_file_name, 0, sizeof(absolute_file_name));
+       snprintf(absolute_file_name, SEC_UIO_MAX_ATTR_FILE_NAME,
+                "%s/%s/%s", root, subdir, filename);
+
+       fd = open(absolute_file_name, O_RDONLY);
+       SEC_ASSERT(fd > 0, fd, "Error opening file %s",
+                       absolute_file_name);
+
+       /* read UIO device name from first line in file */
+       ret = read(fd, line, SEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH);
+       close(fd);
+
+       /* NULL-ify string */
+       line[SEC_UIO_MAX_DEVICE_FILE_NAME_LENGTH - 1] = '\0';
+
+       if (ret <= 0) {
+               CAAM_JR_ERR("Error reading from file %s", absolute_file_name);
+               return ret;
+       }
+
+       return 0;
+}
+
+/** @brief Uses UIO control to send commands to SEC kernel driver.
+ * The mechanism is to write a command word into the file descriptor
+ * that the user-space driver obtained for each user-space SEC job ring.
+ * Both user-space driver and kernel driver must have the same understanding
+ * about the command codes.
+ *
+ * @param [in]  UIO FD             The UIO file descriptor
+ * @param [in]  uio_command         Command word
+ *
+ * @retval Result of write operation on the job ring's UIO file descriptor.
+ *         Should be sizeof(int) for success operations.
+ *         Other values can be returned and used, if desired to add special
+ *         meaning to return values, but this has to be programmed in SEC
+ *         kernel driver as well. No special return values are used.
+ */
+static int sec_uio_send_command(uint32_t uio_fd, int32_t uio_command)
+{
+       int ret;
+
+       /* Use UIO file descriptor we have for this job ring.
+        * Writing a command code to this file descriptor will make the
+        * SEC kernel driver execute the desired command.
+        */
+       ret = write(uio_fd, &uio_command, sizeof(int));
+       return ret;
+}
+
+/** @brief Request to SEC kernel driver to enable interrupts for
+ *         descriptor finished processing
+ *  Use UIO to communicate with SEC kernel driver: write command
+ *  value that indicates an IRQ enable action into UIO file descriptor
+ *  of this job ring.
+ *
+ * @param [in]  uio_fd     Job Ring UIO File descriptor
+ * @retval 0 for success
+ * @retval -1 value for error
+ */
+uint32_t caam_jr_enable_irqs(uint32_t uio_fd)
+{
+       int ret;
+
+       /* Use UIO file descriptor we have for this job ring.
+        * Writing a command code to this file descriptor will make the
+        * SEC kernel driver enable DONE and Error IRQs for this job ring,
+        * at Controller level.
+        */
+       ret = sec_uio_send_command(uio_fd, SEC_UIO_ENABLE_IRQ_CMD);
+       SEC_ASSERT(ret == sizeof(int), -1,
+               "Failed to request SEC engine to enable job done and "
+               "error IRQs through UIO control. UIO FD %d. Reset SEC driver!",
+               uio_fd);
+       CAAM_JR_DEBUG("Enabled IRQs on jr with uio_fd %d", uio_fd);
+       return 0;
+}
+
+
+/** @brief Request to SEC kernel driver to disable interrupts for descriptor
+ *  finished processing
+ *  Use UIO to communicate with SEC kernel driver: write command
+ *  value that indicates an IRQ disable action into UIO file descriptor
+ *  of this job ring.
+ *
+ * @param [in]  uio_fd    UIO File descripto
+ * @retval 0 for success
+ * @retval -1 value for error
+ *
+ */
+uint32_t caam_jr_disable_irqs(uint32_t uio_fd)
+{
+       int ret;
+
+       /* Use UIO file descriptor we have for this job ring.
+        * Writing a command code to this file descriptor will make the
+        * SEC kernel driver disable IRQs for this job ring,
+        * at Controller level.
+        */
+
+       ret = sec_uio_send_command(uio_fd, SEC_UIO_DISABLE_IRQ_CMD);
+       SEC_ASSERT(ret == sizeof(int), -1,
+               "Failed to request SEC engine to disable job done and "
+               "IRQs through UIO control. UIO_FD %d Reset SEC driver!",
+               uio_fd);
+       CAAM_JR_DEBUG("Disabled IRQs on jr with uio_fd %d", uio_fd);
+       return 0;
+}
+
+/** @brief Maps register range assigned for a job ring.
+ *
+ * @param [in] uio_device_fd    UIO device file descriptor
+ * @param [in] uio_device_id    UIO device id
+ * @param [in] uio_map_id       UIO allows maximum 5 different mapping for
+                               each device. Maps start with id 0.
+ * @param [out] map_size        Map size.
+ * @retval  NULL if failed to map registers
+ * @retval  Virtual address for mapped register address range
+ */
+static void *
+uio_map_registers(int uio_device_fd, int uio_device_id,
+               int uio_map_id, int *map_size)
+{
+       void *mapped_address = NULL;
+       unsigned int uio_map_size = 0;
+       char uio_sys_root[SEC_UIO_MAX_ATTR_FILE_NAME];
+       char uio_sys_map_subdir[SEC_UIO_MAX_ATTR_FILE_NAME];
+       char uio_map_size_str[32];
+       int ret = 0;
+
+       /* compose the file name: root/subdir/filename */
+       memset(uio_sys_root, 0, sizeof(uio_sys_root));
+       memset(uio_sys_map_subdir, 0, sizeof(uio_sys_map_subdir));
+       memset(uio_map_size_str, 0, sizeof(uio_map_size_str));
+
+       /* Compose string: /sys/class/uio/uioX */
+       sprintf(uio_sys_root, "%s/%s%d", SEC_UIO_DEVICE_SYS_ATTR_PATH,
+               "uio", uio_device_id);
+       /* Compose string: maps/mapY */
+       sprintf(uio_sys_map_subdir, "%s%d", SEC_UIO_DEVICE_SYS_MAP_ATTR,
+               uio_map_id);
+
+       /* Read first (and only) line from file
+        * /sys/class/uio/uioX/maps/mapY/size
+        */
+       ret = file_read_first_line(uio_sys_root, uio_sys_map_subdir,
+                                "size", uio_map_size_str);
+       SEC_ASSERT(ret == 0, NULL, "file_read_first_line() failed");
+
+       /* Read mapping size, expressed in hexa(base 16) */
+       uio_map_size = strtol(uio_map_size_str, NULL, 16);
+
+       /* Map the region in user space */
+       mapped_address = mmap(0, /*dynamically choose virtual address */
+               uio_map_size, PROT_READ | PROT_WRITE,
+               MAP_SHARED, uio_device_fd, 0);
+       /* offset = 0 because UIO device has only one mapping
+        * for the entire SEC register memory
+        */
+       if (mapped_address == MAP_FAILED) {
+               CAAM_JR_ERR(
+                       "Failed to map registers! errno = %d job ring fd  = %d,"
+                       "uio device id = %d, uio map id = %d", errno,
+                       uio_device_fd, uio_device_id, uio_map_id);
+               return NULL;
+       }
+
+       /*
+        * Save the map size to use it later on for munmap-ing.
+        */
+       *map_size = uio_map_size;
+
+       CAAM_JR_INFO("UIO dev[%d] mapped region [id =%d] size 0x%x at %p",
+               uio_device_id, uio_map_id, uio_map_size, mapped_address);
+
+       return mapped_address;
+}
+
+void free_job_ring(uint32_t uio_fd)
+{
+       struct uio_job_ring *job_ring = NULL;
+       int i;
+
+       if (!job_ring->uio_fd)
+               return;
+
+       for (i = 0; i < MAX_SEC_JOB_RINGS; i++) {
+               if (g_uio_job_ring[i].uio_fd == uio_fd) {
+                       job_ring = &g_uio_job_ring[i];
+                       break;
+               }
+       }
+       if (job_ring == NULL) {
+               CAAM_JR_ERR("JR not available for fd = %x\n", uio_fd);
+               return;
+       }
+
+       /* Open device file */
+       CAAM_JR_INFO("Closed device file for job ring %d , fd = %d",
+                       job_ring->jr_id, job_ring->uio_fd);
+       close(job_ring->uio_fd);
+       g_uio_jr_num--;
+       job_ring->uio_fd = 0;
+
+       if (job_ring->register_base_addr == NULL)
+               return;
+
+       /* Unmap the PCI memory resource of device */
+       if (munmap(job_ring->register_base_addr, job_ring->map_size)) {
+               CAAM_JR_INFO("cannot munmap(%p, 0x%lx): %s",
+                       job_ring->register_base_addr,
+                       (unsigned long)job_ring->map_size, strerror(errno));
+       } else
+               CAAM_JR_DEBUG("  JR UIO memory unmapped at %p",
+                               job_ring->register_base_addr);
+       job_ring->register_base_addr = NULL;
+}
+
+struct uio_job_ring *config_job_ring(void)
+{
+       char uio_device_file_name[32];
+       struct uio_job_ring *job_ring = NULL;
+       int i;
+
+       for (i = 0; i < MAX_SEC_JOB_RINGS; i++) {
+               if (g_uio_job_ring[i].uio_fd == 0) {
+                       job_ring = &g_uio_job_ring[i];
+                       g_uio_jr_num++;
+                       break;
+               }
+       }
+
+       if (job_ring == NULL) {
+               CAAM_JR_ERR("No free job ring\n");
+               return NULL;
+       }
+
+       /* Find UIO device created by SEC kernel driver for this job ring. */
+       memset(uio_device_file_name, 0, sizeof(uio_device_file_name));
+
+       sprintf(uio_device_file_name, "%s%d", SEC_UIO_DEVICE_FILE_NAME,
+               job_ring->uio_minor_number);
+
+       /* Open device file */
+       job_ring->uio_fd = open(uio_device_file_name, O_RDWR);
+       SEC_ASSERT(job_ring->uio_fd > 0, NULL,
+               "Failed to open UIO device file for job ring %d",
+               job_ring->jr_id);
+
+       CAAM_JR_INFO("Open device(%s) file for job ring=%d , uio_fd = %d",
+               uio_device_file_name, job_ring->jr_id, job_ring->uio_fd);
+
+       ASSERT(job_ring->register_base_addr == NULL);
+       job_ring->register_base_addr = uio_map_registers(
+                       job_ring->uio_fd, job_ring->uio_minor_number,
+                       SEC_UIO_MAP_ID, &job_ring->map_size);
+
+       SEC_ASSERT(job_ring->register_base_addr != NULL, NULL,
+               "Failed to map SEC registers");
+       return job_ring;
+}
+
+int sec_configure(void)
+{
+       char uio_name[32];
+       int config_jr_no = 0, jr_id = -1;
+       int uio_minor_number = -1;
+       int ret;
+       DIR *d = NULL;
+       struct dirent *dir;
+
+       d = opendir(SEC_UIO_DEVICE_SYS_ATTR_PATH);
+       if (d == NULL) {
+               printf("\nError opening directory '%s': %s\n",
+                       SEC_UIO_DEVICE_SYS_ATTR_PATH, strerror(errno));
+               return -1;
+       }
+
+       /* Iterate through all subdirs */
+       while ((dir = readdir(d)) != NULL) {
+               if (!strncmp(dir->d_name, ".", 1) ||
+                               !strncmp(dir->d_name, "..", 2))
+                       continue;
+
+               if (file_name_match_extract
+                       (dir->d_name, "uio", &uio_minor_number)) {
+               /*
+                * Open file uioX/name and read first line which contains
+                * the name for the device. Based on the name check if this
+                * UIO device is UIO device for job ring with id jr_id.
+                */
+                       memset(uio_name, 0, sizeof(uio_name));
+                       ret = file_read_first_line(SEC_UIO_DEVICE_SYS_ATTR_PATH,
+                                       dir->d_name, "name", uio_name);
+                       CAAM_JR_INFO("sec device uio name: %s", uio_name);
+                       SEC_ASSERT(ret == 0, -1, "file_read_first_line failed");
+
+                       if (file_name_match_extract(uio_name,
+                                               SEC_UIO_DEVICE_NAME,
+                                               &jr_id)) {
+                               g_uio_job_ring[config_jr_no].jr_id = jr_id;
+                               g_uio_job_ring[config_jr_no].uio_minor_number =
+                                                       uio_minor_number;
+                               CAAM_JR_INFO("Detected logical JRID:%d", jr_id);
+                               config_jr_no++;
+
+                               /* todo  find the actual ring id
+                                * OF_FULLNAME=/soc/crypto@1700000/jr@20000
+                                */
+                       }
+               }
+       }
+       closedir(d);
+
+       if (config_jr_no == 0) {
+               CAAM_JR_ERR("! No SEC Job Rings assigned for userspace usage!");
+               return 0;
+       }
+       CAAM_JR_INFO("Total JR detected =%d", config_jr_no);
+       return config_jr_no;
+}
+
+int sec_cleanup(void)
+{
+       int i;
+       struct uio_job_ring *job_ring;
+
+       for (i = 0; i < g_uio_jr_num; i++) {
+               job_ring = &g_uio_job_ring[i];
+               /* munmap SEC's register memory */
+               if (job_ring->register_base_addr) {
+                       munmap(job_ring->register_base_addr,
+                               job_ring->map_size);
+                       job_ring->register_base_addr = NULL;
+               }
+               /* I need to close the fd after shutdown UIO commands need to be
+                * sent using the fd
+                */
+               if (job_ring->uio_fd != 0) {
+                       CAAM_JR_INFO(
+                       "Closed device file for job ring %d , fd = %d",
+                       job_ring->jr_id, job_ring->uio_fd);
+                       close(job_ring->uio_fd);
+               }
+       }
+       return 0;
+}
diff --git a/drivers/crypto/caam_jr/meson.build 
b/drivers/crypto/caam_jr/meson.build
index 3edd0a212..7b024e886 100644
--- a/drivers/crypto/caam_jr/meson.build
+++ b/drivers/crypto/caam_jr/meson.build
@@ -6,6 +6,9 @@ if host_machine.system() != 'linux'
 endif
 
 deps += ['bus_vdev', 'bus_dpaa', 'security']
-sources = files('caam_jr.c')
+sources = files('caam_jr_hw.c', 'caam_jr_uio.c', 'caam_jr.c')
 
 allow_experimental_apis = true
+
+includes += include_directories('../dpaa2_sec/')
+includes += include_directories('../../bus/dpaa/include/')
-- 
2.17.1

Reply via email to