Page MenuHomeFreeBSD

D45589.id139838.diff
No OneTemporary

D45589.id139838.diff

diff --git a/sys/arm64/conf/std.nxp b/sys/arm64/conf/std.nxp
--- a/sys/arm64/conf/std.nxp
+++ b/sys/arm64/conf/std.nxp
@@ -25,6 +25,9 @@
device dpaa2 # Data Path Acceleration Architecture (2nd Gen)
device enetc # QorIQ LS1028A NIC
+# SEC4/CAAM cypto coprocessor
+device caam
+
# SFF/SFP
device sff # Small Form Factor Transceivers
diff --git a/sys/arm64/qoriq/caam/caam.h b/sys/arm64/qoriq/caam/caam.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/caam.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2017-2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_H
+#define CAAM_H
+
+#include <sys/types.h>
+#include <sys/bus.h>
+
+#include "jr/caam_jr.h"
+
+/*
+ * If CAAM_JR_MODE_ASYNC is defined:
+ * - Jobrings will initialize in SEC_NOTIFICATION_TYPE_IRQ mode
+ * - Use caam_run_descriptor_jr_async() to enqueue jobs
+ * - jobdesc should have a callback set
+ * - callback should set job_arg status and JR_JOB_ARG_SIG_DONE
+ * - callers may wait for completion using JR_JOB_ARG_WAIT_DONE
+ *
+ * else:
+ * - Jobrings will initialize in SEC_NOTIFICATION_TYPE_POLL mode
+ * - Use caam_run_descriptor_jr_blocking() to enqueue jobs and wait for
+ * completion
+ *
+ * Both caam_run_descriptor_jr_async and caam_run_descriptor_jr_blocking are
+ * available at runtime but it's callers responsibility to reinitialize jobring
+ * in an appropriate mode and ensure the jobring is not used in a previous mode
+ * anymore.
+ */
+#define CAAM_JR_MODE_ASYNC 1
+
+/* The hardware use 64bit adressing */
+#define CONFIG_PHYS_64BIT
+/* The hardware is BigEndian - will require endianness swaps */
+#define NXP_SEC_BE
+/* The hardware max Scatter-Gather entries */
+#define MAX_SGT_ENTRIES 32
+
+/* These functions manage external data that need to be passed to/from DMA */
+
+/*
+ * @brief Read common caam register.
+ *
+ * @param [in] dev caam device handle
+ * @param [in] reg register offset
+ *
+ * @retval :: uint32_t register value
+ */
+uint32_t caam_reg_read(device_t dev, uint32_t reg);
+
+/*
+ * @brief Write common caam register.
+ *
+ * @param [in] dev caam device handle
+ * @param [in] reg register offset
+ * @param [in] val value to write
+ */
+void caam_reg_write(device_t dev, uint32_t reg, uint32_t val);
+
+#if defined(CAAM_JR_MODE_ASYNC)
+/*
+ * @brief Submit a job for execution, non-blocking.
+ *
+ * To control completion and status use completion callback with
+ * caam_jr::struct jr_job_arg
+ *
+ * Selected jobring must be started in SEC_NOTIFICATION_TYPE_IRQ mode
+ *
+ * @param [in] dev caam device handle
+ * @param [in] jobdesc job descriptor
+ * @param [in] jr_dev optional handle for a jobring device to use, get with
+ * jr_pool_acquire
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on failure
+ */
+int caam_run_descriptor_jr_async(device_t dev, struct job_descriptor *jobdesc,
+ device_t jr_dev);
+#endif
+
+/*
+ * @brief Submit a job for execution, will poll for job completion.
+ *
+ * Selected jobring must be started in SEC_NOTIFICATION_TYPE_POLL mode
+ *
+ * @param [in] dev caam device handle
+ * @param [in] jobdesc job descriptor
+ * @param [in] jr_dev optional handle for a jobring device to use, get with
+ * jr_pool_acquire
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on failure
+ */
+int caam_run_descriptor_jr_blocking(device_t dev,
+ struct job_descriptor *jobdesc, device_t jr_dev);
+
+#endif /* CAAM_H */
diff --git a/sys/arm64/qoriq/caam/caam.c b/sys/arm64/qoriq/caam/caam.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/caam.c
@@ -0,0 +1,658 @@
+/*
+ * Copyright 2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * This driver is based on arm-trusted-firmware/drivers/nxp/crypto/caam code.
+ */
+
+#include <sys/cdefs.h>
+
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/queue.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+
+#include <dev/fdt/simplebus.h>
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include "caam.h"
+#include "caam_debug.h"
+#include "caam_internal.h"
+#include "jr/caam_jobdesc.h"
+#include "jr/caam_jr.h"
+#include "jr/caam_jr_hw.h"
+#include "jr/caam_jr_pool.h"
+
+/*-------------------------- SFR access functions --------------------------*/
+uint32_t
+caam_reg_read(device_t dev, uint32_t reg)
+{
+ struct caam_softc *sc = device_get_softc(dev);
+ uint32_t result;
+
+ CAAM_LOG_DEBUG("caam_reg_read(%08X) --> ", reg);
+ result = bus_read_4(sc->mem_res, reg);
+
+#if defined(NXP_SEC_BE)
+ result = be32toh(result);
+#elif defined(NXP_SEC_LE)
+ result = le32toh(result);
+#else
+#error Please define CAAM register endianness
+#endif
+
+ CAAM_LOG_DEBUG("%08X\n", result);
+
+ return result;
+}
+
+void
+caam_reg_write(device_t dev, uint32_t reg, uint32_t val)
+{
+ struct caam_softc *sc = device_get_softc(dev);
+ CAAM_LOG_DEBUG("caam_reg_write(%08X, %08X)\n", reg, val);
+
+#if defined(NXP_SEC_BE)
+ val = htobe32(val);
+#elif defined(NXP_SEC_LE)
+ val = htole32(val);
+#else
+#error Please define CAAM register endianness
+#endif
+
+ bus_write_4(sc->mem_res, reg, val);
+ bus_barrier(sc->mem_res, reg, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+}
+
+/*----------------------- CAAM configuration functions ----------------------*/
+
+/* This function checks if Virtualization is enabled for JR and
+ * accordingly sets the bot for starting JR<num> in JRSTARTR register
+ */
+static void
+start_jr(device_t dev, int jr_num)
+{
+ uint32_t ctpr = caam_reg_read(dev, SEC_REG_CTPR_MS_OFFSET);
+ uint32_t jrstartr = caam_reg_read(dev, SEC_REG_JRSTARTR_OFFSET);
+ uint32_t scfgr = caam_reg_read(dev, SEC_REG_SCFGR_OFFSET);
+ bool start = false;
+
+ /* HW limitation of JRSTARTR reg size */
+ MPASS(jr_num < sizeof(jrstartr) * 8);
+
+ 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) {
+ jrstartr |= 1 << jr_num;
+ caam_reg_write(dev, SEC_REG_JRSTARTR_OFFSET, jrstartr);
+ }
+}
+
+/* This functions configures the Job Ring
+ */
+static int
+configure_jr(device_t caam_dev, device_t jr_dev, int jr_num)
+{
+ int ret;
+
+ start_jr(caam_dev, jr_num);
+
+ /* Do HW configuration of the JR */
+#if defined(CAAM_JR_MODE_ASYNC)
+ ret = caam_jr_init(jr_dev, SEC_NOTIFICATION_TYPE_IRQ,
+ SEC_INTERRUPT_COALESCING_TIMER_THRESH,
+ SEC_INTERRUPT_COALESCING_DESCRIPTOR_COUNT_THRESH);
+#else
+ ret = caam_jr_init(jr_dev, SEC_NOTIFICATION_TYPE_POLL, 0, 0);
+#endif
+
+ if (ret != 0) {
+ CAAM_LOG_ERROR("Error in caam_jr_init ret=(%d)\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+/* This function configure SEC block:
+ * - It does basic parameter setting
+ * - Configures all the discovered Job rings assigned to TZ /secure world
+ */
+static void
+configure_caam(device_t dev)
+{
+ uint32_t mcfgr;
+
+ mcfgr = caam_reg_read(dev, 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
+ caam_reg_write(dev, SEC_REG_MCFGR_OFFSET, mcfgr);
+}
+
+/*
+ * @brief Submit a job for execution.
+ *
+ * This is a shared implementation of caam_run_descriptor_jr_async/blocking,
+ * use those wrappers instead.
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on failure
+ */
+static int
+caam_run_descriptor_jr(device_t dev, struct job_descriptor *jobdesc,
+ bool polling, device_t jr_dev)
+{
+ int i = 0, ret = 0;
+ uint32_t *desc_addr = jobdesc->desc;
+ uint32_t desc_len = caam_jobdesc_length(jobdesc->desc);
+ uint32_t desc_word;
+
+ struct caam_softc *sc = device_get_softc(dev);
+ struct jr_pool *p = &sc->jr_pool;
+ device_t jr;
+
+ CAAM_LOG_DEBUG("Descriptor org: \n");
+ for (i = 0; i < desc_len; i++) {
+ desc_word = desc_addr[i];
+ CAAM_LOG_DEBUG("%08X\n", desc_word);
+ sec_mem_out32((uint32_t *)&desc_addr[i], desc_word);
+ }
+
+ CAAM_LOG_DEBUG("Descriptor final: \n");
+ for (i = 0; i < desc_len; i++) {
+ CAAM_LOG_DEBUG("%08X\n", desc_addr[i]);
+ }
+
+ if (jr_dev == NULL) {
+ jr = jr_pool_acquire(p);
+ if (!jr) {
+ return EBUSY;
+ }
+ } else {
+ jr = jr_dev;
+ }
+
+ ret = caam_jr_enqueue(jr, jobdesc);
+ if (ret == 0) {
+ CAAM_LOG_DEBUG("JR enqueue done...\n");
+ } else {
+ CAAM_LOG_WARN("Error in Enqueue\n");
+ return ret;
+ }
+
+ if (polling) {
+ CAAM_LOG_DEBUG("Dequeue in progress\n");
+ ret = caam_jr_dequeue(jr, -1);
+ if (ret == 0) {
+ CAAM_LOG_DEBUG("Dequeue of %x desc success\n", ret);
+ } else {
+ CAAM_LOG_WARN("deq_ret %x\n", ret);
+ ret = EIO;
+ }
+ }
+
+ if (jr_dev == NULL)
+ jr_pool_release(p, jr);
+
+ return ret;
+}
+
+/*--------------------- CAAM Public interface functions ---------------------*/
+#if defined(CAAM_JR_MODE_ASYNC)
+int
+caam_run_descriptor_jr_async(device_t dev, struct job_descriptor *jobdesc,
+ device_t jr_dev)
+{
+ return caam_run_descriptor_jr(dev, jobdesc, false, jr_dev);
+}
+
+static void
+caam_run_op_done(uint32_t *desc, uint32_t status, void *arg, device_t dev)
+{
+ if (arg) {
+ struct jr_job_arg *job_arg = arg;
+
+ job_arg->desc = desc;
+ job_arg->status = status;
+ job_arg->dev = dev;
+
+ JR_JOB_ARG_SIG_DONE(*job_arg);
+ }
+}
+#endif /* defined(CAAM_JR_MODE_ASYNC) */
+
+int
+caam_run_descriptor_jr_blocking(device_t dev, struct job_descriptor *jobdesc,
+ device_t jr_dev)
+{
+#if defined(CAAM_JR_MODE_ASYNC)
+ /* Implement the blocking interface using conditional variable */
+ int rv = 0;
+ void *backup_arg;
+ user_callback backup_callback;
+
+ struct jr_job_arg job_arg;
+ JR_JOB_ARG_INIT(job_arg, caam_run_descriptor);
+
+ backup_arg = jobdesc->arg;
+ backup_callback = jobdesc->callback;
+
+ jobdesc->arg = &job_arg;
+ jobdesc->callback = caam_run_op_done;
+
+ rv = caam_run_descriptor_jr(dev, jobdesc, false, jr_dev);
+ if (rv != 0) {
+ CAAM_LOG_DEV_WARN(dev,
+ "Failed to enqueue async descriptor rv=(%d)\n", rv);
+ return (rv);
+ }
+
+ JR_JOB_ARG_WAIT_DONE(job_arg);
+ if (job_arg.status != 0) {
+ CAAM_LOG_ERROR("Job failed with status %x\n", job_arg.status);
+ rv = EIO;
+ }
+
+ if (backup_callback)
+ backup_callback(job_arg.desc, job_arg.status, backup_arg,
+ job_arg.dev);
+
+ return (rv);
+#else
+ return caam_run_descriptor_jr(dev, jobdesc, true, jr_dev);
+#endif /* defined(CAAM_JR_MODE_ASYNC) */
+}
+
+/*----------------------- Device management functions -----------------------*/
+static int
+caam_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,sec-v4.0"))
+ return (ENXIO);
+
+ device_set_desc(dev, "CAAM backend driver");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+/* Find all jobring child devices, configure and add to jr_pool */
+static int
+caam_jobrings_attach(device_t parent)
+{
+ int rv = 0;
+ struct caam_softc *sc;
+ device_t cdev;
+ phandle_t node;
+ struct jr_pool *p;
+
+ node = ofw_bus_get_node(parent);
+ if (node == -1)
+ return (ENXIO);
+
+ sc = device_get_softc(parent);
+ p = &sc->jr_pool;
+ jr_pool_init(p);
+
+ /*
+ * Now walk the OFW tree and attach all job rings devices.
+ * Failing will reduce available jobring count,
+ * but with at least one CAAM remains functional.
+ */
+ for (node = OF_child(node); node > 0; node = OF_peer(node)) {
+ if (!ofw_bus_node_is_compatible(node, "fsl,sec-v4.0-job-ring"))
+ continue;
+
+ cdev = simplebus_add_device(parent, node, 0, NULL, -1, NULL);
+ if (!cdev) {
+ CAAM_LOG_ERROR("Failed to add child device\n");
+ continue;
+ }
+ rv = device_probe_and_attach(cdev);
+ if (rv != 0)
+ continue;
+
+ rv = configure_jr(parent, cdev, jr_pool_dev_cnt(p));
+ if (rv != 0) {
+ CAAM_LOG_ERROR("Job ring %zu configuration failure\n",
+ jr_pool_dev_cnt(p));
+ continue;
+ }
+
+ jr_pool_add(p, cdev);
+ }
+
+ CAAM_LOG_INFO("Initialized %lu CAAM job rings\n", jr_pool_dev_cnt(p));
+
+ if (jr_pool_dev_cnt(p) < 1) {
+ CAAM_LOG_ERROR("No jobrings available\n");
+ rv = ENODEV;
+ }
+
+ return (rv);
+}
+
+static void caam_jobrings_detach(device_t dev);
+
+static int
+caam_attach(device_t dev)
+{
+ struct caam_softc *sc;
+ phandle_t node;
+ int rv;
+ int rid;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+
+ node = ofw_bus_get_node(dev);
+ if (node == -1)
+ return (ENXIO);
+
+ simplebus_init(dev, node);
+ if (simplebus_fill_ranges(node, &sc->sc) < 0) {
+ CAAM_LOG_ERROR("Failed to fill ranges\n");
+ return (ENXIO);
+ }
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+
+ if (sc->mem_res == NULL) {
+ CAAM_LOG_ERROR("Failed to allocate resource\n");
+ rv = ENXIO;
+ goto cleanup_simplebus;
+ }
+
+ sc->mem_rman.rm_type = RMAN_ARRAY;
+ sc->mem_rman.rm_descr = "CAAM Device Memory";
+ sc->mem_rman.rm_start = rman_get_start(sc->mem_res);
+ sc->mem_rman.rm_end = rman_get_end(sc->mem_res);
+ rv = rman_init(&sc->mem_rman);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("Failed to initialize rman\n");
+ goto cleanup_resource;
+ }
+ rv = rman_manage_region(&sc->mem_rman, rman_get_start(sc->mem_res),
+ rman_get_end(sc->mem_res));
+ if (rv != 0) {
+ CAAM_LOG_ERROR("Failed to initialize RMAN region\n");
+ goto cleanup_rman;
+ }
+
+ /*
+ * Allow devices to identify.
+ */
+ rv = bus_generic_probe(dev);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("bus_generic_probe failed rv=(%d)\n", rv);
+ goto cleanup_rman;
+ }
+
+ /* Initialize the simple CAAM driver stack */
+ configure_caam(dev);
+
+ /* Attach, probe and config jobrings */
+ rv = caam_jobrings_attach(dev);
+ if (rv != 0) {
+ CAAM_LOG_ERROR("caam_jobrings_attach failed rv=(%d)\n", rv);
+ goto cleanup_rman;
+ }
+
+ return (0);
+
+cleanup_rman:
+ rman_fini(&sc->mem_rman);
+cleanup_resource:
+ bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
+cleanup_simplebus:
+ free(sc->sc.ranges, M_DEVBUF);
+
+ return (rv);
+}
+
+/*
+ * Acquire all jobrings, wait until all work is completed and deinitialize.
+ * Deinit jr_pool.
+ */
+static void
+caam_jobrings_detach(device_t dev)
+{
+ struct caam_softc *sc = device_get_softc(dev);
+ struct jr_pool *p = &sc->jr_pool;
+ device_t jr, *jr_drained;
+ int rv, i, maxwait;
+
+ jr_drained = malloc(sizeof(jr) * jr_pool_dev_cnt(p), M_DEVBUF,
+ M_WAITOK);
+ if (!jr_drained) {
+ CAAM_LOG_ERROR("Failed to allocate jr_drained\n");
+ return;
+ }
+
+ jr_pool_shutdown(p);
+
+ for (i = 0; i < jr_pool_dev_cnt(p); ++i) {
+ jr = jr_pool_shutdown_acquire(p);
+
+ maxwait = 1000;
+ while (caam_jr_busy(jr) && maxwait--) {
+ pause("caam_jr detach", hz / 1000);
+ }
+
+ caam_jr_shutdown(jr);
+ rv = device_detach(jr);
+ if (rv)
+ CAAM_LOG_ERROR(
+ "Failed to detach job ring device %p rv=(%d)\n", jr,
+ rv);
+
+ jr_drained[i] = jr;
+ }
+
+ /* must free all before vmem_destroy */
+ for (i -= 1; i >= 0; --i) {
+ jr_pool_release(p, jr_drained[i]);
+ }
+
+ jr_pool_deinit(p);
+
+ free(jr_drained, M_DEVBUF);
+}
+
+static int
+caam_detach(device_t dev)
+{
+ struct caam_softc *sc = device_get_softc(dev);
+
+ caam_jobrings_detach(dev);
+
+ rman_fini(&sc->mem_rman);
+ bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
+ free(sc->sc.ranges, M_DEVBUF);
+
+ return (0);
+}
+
+static int
+caam_activate_resource(device_t bus, device_t child, struct resource *res)
+{
+ struct caam_softc *sc;
+ bus_space_tag_t bt;
+ bus_space_handle_t bh;
+ int i, rv;
+
+ sc = device_get_softc(bus);
+ if (rman_get_type(res) != SYS_RES_IRQ) {
+ for (i = 0; i < sc->sc.nranges; i++) {
+ if (rman_is_region_manager(res, &sc->mem_rman) != 0) {
+ bt = rman_get_bustag(sc->mem_res);
+ rv = bus_space_subregion(bt,
+ rman_get_bushandle(sc->mem_res),
+ rman_get_start(res) -
+ rman_get_start(sc->mem_res),
+ rman_get_size(res), &bh);
+ if (rv != 0)
+ return (rv);
+ rman_set_bustag(res, bt);
+ rman_set_bushandle(res, bh);
+ return (rman_activate_resource(res));
+ }
+ }
+ return (EINVAL);
+ }
+ return (bus_generic_activate_resource(bus, child, res));
+}
+
+static int
+caam_release_resource(device_t bus, device_t child, struct resource *res)
+{
+ struct resource_list *rl;
+ struct resource_list_entry *rle;
+ int passthrough, rv;
+
+ passthrough = (device_get_parent(child) != bus);
+ rl = BUS_GET_RESOURCE_LIST(bus, child);
+ if (rman_get_type(res) != SYS_RES_IRQ) {
+ if ((rman_get_flags(res) & RF_ACTIVE) != 0 ){
+ rv = bus_deactivate_resource(child, res);
+ if (rv != 0)
+ return (rv);
+ }
+ rv = rman_release_resource(res);
+ if (rv != 0)
+ return (rv);
+ if (!passthrough) {
+ rle = resource_list_find(rl, rman_get_type(res),
+ rman_get_rid(res));
+ KASSERT(rle != NULL,
+ ("%s: resource entry not found!", __func__));
+ KASSERT(rle->res != NULL,
+ ("%s: resource entry is not busy", __func__));
+ rle->res = NULL;
+ }
+ return (0);
+ }
+ return (resource_list_release(rl, bus, child, res));
+}
+
+static struct resource *
+caam_alloc_resource(device_t bus, device_t child, int type, int *rid,
+ rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
+{
+ struct caam_softc *sc;
+ struct resource_list *rl;
+ struct resource_list_entry *rle = NULL;
+ struct resource *res;
+ int i, isdefault, passthrough;
+
+ isdefault = RMAN_IS_DEFAULT_RANGE(start, end);
+ passthrough = (device_get_parent(child) != bus);
+ sc = device_get_softc(bus);
+ rl = BUS_GET_RESOURCE_LIST(bus, child);
+ switch (type) {
+ case SYS_RES_MEMORY:
+ KASSERT(!(isdefault && passthrough),
+ ("%s: passthrough of default allocation", __func__));
+ if (!passthrough) {
+ rle = resource_list_find(rl, type, *rid);
+ if (rle == NULL)
+ return (NULL);
+ KASSERT(rle->res == NULL,
+ ("%s: resource entry is busy", __func__));
+ if (isdefault) {
+ start = rle->start;
+ count = ulmax(count, rle->count);
+ end = ulmax(rle->end, start + count - 1);
+ }
+ }
+
+ res = NULL;
+ /* Map caam ranges to nexus ranges. */
+ for (i = 0; i < sc->sc.nranges; i++) {
+ if (start >= sc->sc.ranges[i].bus && end <
+ sc->sc.ranges[i].bus + sc->sc.ranges[i].size) {
+ start += rman_get_start(sc->mem_res);
+ end += rman_get_start(sc->mem_res);
+ res = rman_reserve_resource(&sc->mem_rman, start,
+ end, count, flags & ~RF_ACTIVE, child);
+ if (res == NULL)
+ return (NULL);
+ rman_set_rid(res, *rid);
+ rman_set_type(res, type);
+ if ((flags & RF_ACTIVE) != 0 && bus_activate_resource(
+ child, type, *rid, res) != 0) {
+ rman_release_resource(res);
+ return (NULL);
+ }
+ break;
+ }
+ }
+ if (!passthrough)
+ rle->res = res;
+ return (res);
+ case SYS_RES_IRQ:
+ return (resource_list_alloc(rl, bus, child, type, rid, start,
+ end, count, flags));
+ }
+ return (NULL);
+}
+
+static device_method_t caam_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, caam_probe),
+ DEVMETHOD(device_attach, caam_attach),
+ DEVMETHOD(device_detach, caam_detach),
+
+ DEVMETHOD(bus_alloc_resource, caam_alloc_resource),
+ DEVMETHOD(bus_activate_resource, caam_activate_resource),
+ DEVMETHOD(bus_release_resource, caam_release_resource),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(caam, caam_driver, caam_methods, sizeof(struct caam_softc),
+ simplebus_driver);
+
+DRIVER_MODULE(caam, simplebus, caam_driver, 0, 0);
+MODULE_VERSION(caam, 1);
diff --git a/sys/arm64/qoriq/caam/caam_debug.h b/sys/arm64/qoriq/caam/caam_debug.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/caam_debug.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013-2023, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2023 Alstom Group
+ * Copyright (c) 2023 Sii Poland
+
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef CAAM_DEBUG_H
+#define CAAM_DEBUG_H
+
+/*
+ * The log output macros print output to the console. These macros produce
+ * compiled log output only if the LOG_LEVEL defined in the makefile (or the
+ * make command line) is greater or equal than the level required for that
+ * type of log output.
+ *
+ * The format expected is the same as for printf(). For example:
+ * CAAM_LOG_INFO("Info %s.\n", "message") -> INFO: Info message.
+ * CAAM_LOG_WARN("Warning %s.\n", "message") -> WARNING: Warning message.
+ */
+
+#define LOG_LEVEL_NONE (0u)
+#define LOG_LEVEL_ERROR (10u)
+#define LOG_LEVEL_NOTICE (20u)
+#define LOG_LEVEL_WARNING (30u)
+#define LOG_LEVEL_INFO (40u)
+#define LOG_LEVEL_DEBUG (50u)
+
+#ifndef __ASSEMBLER__
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/syslog.h>
+
+#ifdef DEBUG
+#define LOG_LEVEL LOG_LEVEL_INFO
+#else
+#define LOG_LEVEL LOG_LEVEL_ERROR
+#endif
+
+/*
+ * If the log output is too low then this macro is used in place of tf_log()
+ * below. The intent is to get the compiler to evaluate the function call for
+ * type checking and format specifier correctness but let it optimize it out.
+ */
+#define no_tf_log(fmt, ...) \
+ do { \
+ if (false) { \
+ log(LOG_INFO, fmt, ##__VA_ARGS__); \
+ } \
+ } while (false)
+
+#if LOG_LEVEL >= LOG_LEVEL_ERROR
+#define CAAM_LOG_ERROR(...) log(LOG_ERR, __VA_ARGS__)
+#define CAAM_LOG_ERROR_NL() log(LOG_ERR, "\n")
+#else
+#define CAAM_LOG_ERROR(...) no_tf_log(__VA_ARGS__)
+#define CAAM_LOG_ERROR_NL()
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_NOTICE
+#define CAAM_LOG_NOTICE(...) log(LOG_NOTICE, __VA_ARGS__)
+#else
+#define CAAM_LOG_NOTICE(...) no_tf_log(__VA_ARGS__)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_WARNING
+#define CAAM_LOG_WARN(...) log(LOG_WARNING, __VA_ARGS__)
+#define CAAM_LOG_DEV_WARN(dev, ...) device_log(dev, LOG_WARNING, __VA_ARGS__)
+#else
+#define CAAM_LOG_WARN(...) no_tf_log(__VA_ARGS__)
+#define CAAM_LOG_DEV_WARN(dev, ...) no_tf_log(__VA_ARGS__)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_INFO
+#define CAAM_LOG_INFO(...) log(LOG_INFO, __VA_ARGS__)
+#else
+#define CAAM_LOG_INFO(...) no_tf_log(__VA_ARGS__)
+#endif
+
+#if LOG_LEVEL >= LOG_LEVEL_DEBUG
+#define CAAM_LOG_DEBUG(...) log(LOG_DEBUG, __VA_ARGS__)
+#else
+#define CAAM_LOG_DEBUG(...) no_tf_log(__VA_ARGS__)
+#endif
+
+#endif /* __ASSEMBLER__ */
+#endif /* CAAM_DEBUG_H */
diff --git a/sys/arm64/qoriq/caam/caam_internal.h b/sys/arm64/qoriq/caam/caam_internal.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/caam_internal.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2024 Alstom Group
+ * Copyright 2024 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_INTERNAL_H
+#define CAAM_INTERNAL_H
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <sys/rwlock.h>
+
+#include <dev/fdt/simplebus.h>
+
+#include "jr/caam_jr_pool.h"
+
+/* software context */
+struct caam_softc {
+ struct simplebus_softc sc;
+ device_t dev;
+ struct resource *mem_res;
+ struct rman mem_rman;
+
+ struct jr_pool jr_pool;
+};
+
+#endif /* CAAM_INTERNAL_H */
diff --git a/sys/arm64/qoriq/caam/jr/caam_desc_defines.h b/sys/arm64/qoriq/caam/jr/caam_desc_defines.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_desc_defines.h
@@ -0,0 +1,748 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * Brief CAAM Descriptor defines.
+ */
+
+/*
+ * File imported from OP-TEE.
+ */
+#ifndef __CAAM_DESC_DEFINES_H__
+#define __CAAM_DESC_DEFINES_H__
+
+#define BIT32(i) (1 << (i))
+#define SHIFT_U32(value, shift) ((uint32_t)(value) << (shift))
+/*
+ * Common Command constants
+ */
+#define CMD_TYPE(cmd) SHIFT_U32((cmd) & 0x1F, 27)
+#define GET_CMD_TYPE(op) ((op) & (SHIFT_U32(0x1F, 27)))
+#define CMD_CLASS(val) SHIFT_U32((val) & 0x3, 25)
+#define CLASS_NO 0x0
+#define CLASS_1 0x1
+#define CLASS_2 0x2
+#define CLASS_DECO 0x3
+#define VLF SHIFT_U32(1, 24)
+
+#define CMD_SGT BIT32(24)
+#define CMD_IMM BIT32(23)
+
+/*
+ * HEADER Job Descriptor Header format
+ */
+#define CMD_HDR_JD_TYPE CMD_TYPE(0x16)
+/*
+ * HEADER Shared Descriptor Header format
+ */
+#define CMD_HDR_SHR_TYPE CMD_TYPE(0x17)
+
+/* Must be ONE */
+#define HDR_JD_ONE BIT32(23)
+
+/* Start Index if SHR = 0 */
+#define HDR_JD_START_IDX(line) SHIFT_U32((line) & 0x3F, 16)
+
+#define HDR_SHARE_MASK 0x00000700
+#define HDR_SHARE_NEVER 0x00000000
+#define HDR_SHARE_WAIT 0x00000100
+#define HDR_SHARE_SERIAL 0x00000200
+#define HDR_SHARE_ALWAYS 0x00000300
+#define HDR_SHARE_DEFER 0x00000400
+#define HDR_SHR SHIFT_U32(1, 12)
+#define HDR_SC SHIFT_U32(1, 12)
+#define HDR_REVERSE 0x00000800
+
+/* Descriptor Length */
+#define HDR_JD_DESCLEN(len) SHIFT_U32((len) & 0x7F, 0)
+#define GET_JD_DESCLEN(entry) ((entry) & 0x7F)
+
+/*
+ * KEY Command fields
+ */
+#define CMD_KEY_TYPE CMD_TYPE(0x00)
+
+/* Key Destination */
+#define KEY_DEST(val) SHIFT_U32((KEY_DEST_##val) & 0x3, 16)
+#define KEY_DEST_REG 0x0
+#define KEY_DEST_PKHA_E 0x1
+#define KEY_DEST_AFHA_SBOX 0x2
+#define KEY_DEST_MDHA_SPLIT 0x3
+
+/* Plaintext Store */
+#define KEY_PTS BIT32(14)
+
+/* Key Length */
+#define KEY_LENGTH(len) SHIFT_U32((len) & 0x3FF, 0)
+
+/*
+ * LOAD Command fields
+ */
+#define CMD_LOAD_TYPE CMD_TYPE(0x02)
+#define CMD_LOAD_SEQ_TYPE CMD_TYPE(0x03)
+
+/* Load Destination */
+#define LOAD_DST(reg) SHIFT_U32((reg) & 0x7F, 16)
+
+/* Offset in destination register */
+#define LOAD_OFFSET(off) SHIFT_U32((off) & 0xFF, 8)
+
+/* Length */
+#define LOAD_LENGTH(len) SHIFT_U32((len) & 0xFF, 0)
+
+/*
+ * STORE Command fields
+ */
+#define CMD_STORE_TYPE CMD_TYPE(0x0A)
+#define CMD_STORE_SEQ_TYPE CMD_TYPE(0x0B)
+
+/* Store Source */
+#define STORE_SRC(reg) SHIFT_U32((reg) & 0x7F, 16)
+
+/* Offset in source register */
+#define STORE_OFFSET(off) SHIFT_U32((off) & 0xFF, 8)
+
+/* Length */
+#define STORE_LENGTH(len) SHIFT_U32((len) & 0xFF, 0)
+
+/*
+ * Define the Load/Store Registers Source and Destination
+ */
+#define REG_MODE 0x00
+#define REG_KEY_SIZE 0x01
+#define REG_DATA_SIZE 0x02
+#define REG_ICV_SIZE 0x03
+#define REG_DECO_MID_STATUS 0x04
+#define REG_DECO_CTRL2 0x05
+#define REG_CHA_CTRL 0x06
+#define REG_DECO_CTRL 0x06
+#define REG_IRQ_CTRL 0x07
+#define REG_DECO_PROT_OVERWRITE 0x07
+#define REG_CLEAR_WRITTEN 0x08
+#define REG_MATH0 0x08
+#define REG_MATH1 0x09
+#define REG_MATH2 0x0A
+#define REG_CHA_INST_SELECT 0x0A
+#define REG_AAD_SIZE 0x0B
+#define REG_MATH3 0x0B
+#define REG_ALT_DATA_SIZE_C1 0x0F
+#define REG_PKHA_A_SIZE 0x10
+#define REG_PKHA_B_SIZE 0x11
+#define REG_PKHA_N_SIZE 0x12
+#define REG_PKHA_E_SIZE 0x13
+#define REG_CTX 0x20
+#define REG_MATH0_DW 0x30
+#define REG_MATH1_DW 0x31
+#define REG_MATH2_DW 0x32
+#define REG_MATH3_DW 0x33
+#define REG_MATH0_B 0x38
+#define REG_MATH1_B 0x39
+#define REG_MATH2_B 0x3A
+#define REG_MATH3_B 0x3B
+#define REG_KEY 0x40
+#define REG_DECO_DESC 0x40
+#define REG_NFIFO_n_SIZE 0x70
+#define REG_NFIFO_MATH 0x73
+#define REG_SIZE 0x74
+#define REG_SIZE_MATH 0x75
+#define REG_IFIFO_SHIFT 0x76
+#define REG_OFIFO_SHIFT 0x77
+#define REG_AUX_FIFO 0x78
+#define REG_NFIFO 0x7A
+#define REG_IFIFO 0x7C
+#define REG_OFIFO 0x7E
+
+/*
+ * FIFO LOAD Command fields
+ */
+#define CMD_FIFO_LOAD_TYPE CMD_TYPE(0x04)
+#define CMD_SEQ_FIFO_LOAD_TYPE CMD_TYPE(0x05)
+
+/* Extended Length */
+#define FIFO_LOAD_EXT BIT32(22)
+
+/* Input data */
+#define FIFO_LOAD_INPUT(reg) SHIFT_U32((FIFO_LOAD_##reg) & 0x3F, 16)
+#define FIFO_LOAD_ACTION(act) SHIFT_U32((FIFO_LOAD_##act) & 0x3F, 16)
+
+/* Length */
+#define FIFO_LOAD_MAX 0xFFFF
+#define FIFO_LOAD_LENGTH(len) SHIFT_U32((len) & FIFO_LOAD_MAX, 0)
+
+/*
+ * Define the FIFO Load Type Input
+ */
+#define FIFO_LOAD_PKHA_A0 0x00
+#define FIFO_LOAD_PKHA_A1 0x01
+#define FIFO_LOAD_PKHA_A2 0x02
+#define FIFO_LOAD_PKHA_A3 0x03
+#define FIFO_LOAD_PKHA_B0 0x04
+#define FIFO_LOAD_PKHA_B1 0x05
+#define FIFO_LOAD_PKHA_B2 0x06
+#define FIFO_LOAD_PKHA_B3 0x07
+#define FIFO_LOAD_PKHA_N 0x08
+#define FIFO_LOAD_PKHA_A 0x0C
+#define FIFO_LOAD_PKHA_B 0x0D
+#define FIFO_LOAD_NO_INFO_NFIFO 0x0F
+#define FIFO_LOAD_MSG 0x10
+#define FIFO_LOAD_MSG_C1_OUT_C2 0x18
+#define FIFO_LOAD_IV 0x20
+#define FIFO_LOAD_BITDATA 0x2C
+#define FIFO_LOAD_AAD 0x30
+#define FIFO_LOAD_ICV 0x38
+
+/* Define Action of some FIFO Data */
+#define FIFO_LOAD_NOACTION 0x0
+#define FIFO_LOAD_FLUSH 0x1
+#define FIFO_LOAD_LAST_C1 0x2
+#define FIFO_LOAD_LAST_C2 0x4
+
+/*
+ * FIFO STORE Command fields
+ */
+#define CMD_FIFO_STORE_TYPE CMD_TYPE(0x0C)
+#define CMD_SEQ_FIFO_STORE_TYPE CMD_TYPE(0x0D)
+
+/* Extended Length */
+#define FIFO_STORE_EXT BIT32(22)
+
+/* Output data */
+#define FIFO_STORE_OUTPUT(reg) SHIFT_U32((FIFO_STORE_##reg) & 0x3F, 16)
+
+/* Length */
+#define FIFO_STORE_MAX 0xFFFF
+#define FIFO_STORE_LENGTH(len) SHIFT_U32((len) & FIFO_STORE_MAX, 0)
+
+/*
+ * Define the FIFO Store Type Output
+ */
+#define FIFO_STORE_PKHA_A0 0x00
+#define FIFO_STORE_PKHA_A1 0x01
+#define FIFO_STORE_PKHA_A2 0x02
+#define FIFO_STORE_PKHA_A3 0x03
+#define FIFO_STORE_PKHA_B0 0x04
+#define FIFO_STORE_PKHA_B1 0x05
+#define FIFO_STORE_PKHA_B2 0x06
+#define FIFO_STORE_PKHA_B3 0x07
+#define FIFO_STORE_PKHA_N 0x08
+#define FIFO_STORE_PKHA_A 0x0C
+#define FIFO_STORE_PKHA_B 0x0D
+#define FIFO_STORE_AFHA_SBOX_AES_CCM_JKEK 0x10
+#define FIFO_STORE_AFHA_SBOX_AES_CCM_TKEK 0x11
+#define FIFO_STORE_PKHA_E_AES_CCM_JKEK 0x12
+#define FIFO_STORE_PKHA_E_AES_CCM_TKEK 0x13
+#define FIFO_STORE_KEY_AES_CCM_JKEK 0x14
+#define FIFO_STORE_KEY_AES_CCM_TKEK 0x15
+#define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_CCM_JKEK 0x16
+#define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_CCM_TKEK 0x17
+#define FIFO_STORE_AFHA_SBOX_AES_ECB_JKEK 0x20
+#define FIFO_STORE_AFHA_SBOX_AES_ECB_TKEK 0x21
+#define FIFO_STORE_PKHA_E_AES_ECB_JKEK 0x22
+#define FIFO_STORE_PKHA_E_AES_ECB_TKEK 0x23
+#define FIFO_STORE_KEY_AES_ECB_JKEK 0x24
+#define FIFO_STORE_KEY_AES_ECB_TKEK 0x25
+#define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_ECB_JKEK 0x26
+#define FIFO_STORE_C2_MDHA_SPLIT_KEY_AES_ECB_TKEK 0x27
+#define FIFO_STORE_MSG_DATA 0x30
+#define FIFO_STORE_RNG_TO_MEM 0x34
+#define FIFO_STORE_RNG_STAY_FIFO 0x35
+#define FIFO_STORE_SKIP 0x3F
+
+/*
+ * MOVE Command fields
+ */
+#define CMD_MOVE_TYPE CMD_TYPE(0x0F)
+
+/* Auxiliary */
+#define MOVE_AUX(val) SHIFT_U32((val) & 0x3, 25)
+
+/* Wait for completion */
+#define MOVE_WC BIT32(24)
+
+/* Source */
+#define MOVE_SRC(src) MOVE_SRC_##src
+#define MOVE_REG_SRC(reg) SHIFT_U32((reg) & 0xF, 20)
+#define MOVE_SRC_C1_CTX_REG MOVE_REG_SRC(0x0)
+#define MOVE_SRC_C2_CTX_REG MOVE_REG_SRC(0x1)
+#define MOVE_SRC_OFIFO MOVE_REG_SRC(0x2)
+#define MOVE_SRC_DESC_BUF MOVE_REG_SRC(0x3)
+#define MOVE_SRC_MATH_REG0 MOVE_REG_SRC(0x4)
+#define MOVE_SRC_MATH_REG1 MOVE_REG_SRC(0x5)
+#define MOVE_SRC_MATH_REG2 MOVE_REG_SRC(0x6)
+#define MOVE_SRC_MATH_REG3 MOVE_REG_SRC(0x7)
+#define MOVE_SRC_NFIFO_DECO_ALIGN MOVE_REG_SRC(0x8)
+#define MOVE_SRC_NFIFO_C1_ALIGN (MOVE_REG_SRC(0x9) | MOVE_AUX(0x1))
+#define MOVE_SRC_NFIFO_C2_ALIGN (MOVE_REG_SRC(0x9) | MOVE_AUX(0x0))
+#define MOVE_SRC_DECO_ALIGN (MOVE_REG_SRC(0xA) | MOVE_AUX(0x0))
+#define MOVE_SRC_C1_ALIGN (MOVE_REG_SRC(0xA) | MOVE_AUX(0x1))
+#define MOVE_SRC_C2_ALIGN (MOVE_REG_SRC(0xA) | MOVE_AUX(0x2))
+#define MOVE_SRC_C1_KEY MOVE_REG_SRC(0xD)
+#define MOVE_SRC_C2_KEY MOVE_REG_SRC(0xE)
+
+/* Destination */
+#define MOVE_DST(dst) SHIFT_U32((MOVE_DST_##dst), 16)
+#define MOVE_DST_C1_CTX_REG 0x0
+#define MOVE_DST_C2_CTX_REG 0x1
+#define MOVE_DST_OFIFO 0x2
+#define MOVE_DST_DESC_BUF 0x3
+#define MOVE_DST_MATH_REG0 0x4
+#define MOVE_DST_MATH_REG1 0x5
+#define MOVE_DST_MATH_REG2 0x6
+#define MOVE_DST_MATH_REG3 0x7
+#define MOVE_DST_IFIFO_C1 0x8
+#define MOVE_DST_IFIFO_C2 0x9
+#define MOVE_DST_IFIFO_C2_LC2 ((0x9 << 16 | MOVE_AUX(0x1)) >> 16)
+#define MOVE_DST_IFIFO 0xA
+#define MOVE_DST_PKHA_A 0xC
+#define MOVE_DST_C1_KEY 0xD
+#define MOVE_DST_C2_KEY 0xE
+#define MOVE_DST_AUX_FIFO 0xF
+
+/* Offset */
+#define MOVE_OFFSET(off) SHIFT_U32((off) & 0xFF, 8)
+
+/* Length */
+#define MOVE_LENGTH(len) SHIFT_U32((len) & 0xFF, 0)
+
+/*
+ * Operation Command fields
+ * Algorithm/Protocol/PKHA
+ */
+#define CMD_OP_TYPE CMD_TYPE(0x10)
+
+/* Operation Type */
+#define OP_TYPE(type) SHIFT_U32((OP_TYPE_##type) & 0x7, 24)
+#define OP_TYPE_UNI 0x0
+#define OP_TYPE_PKHA 0x1
+#define OP_TYPE_CLASS1 0x2
+#define OP_TYPE_CLASS2 0x4
+#define OP_TYPE_DECAPS 0x6
+#define OP_TYPE_ENCAPS 0x7
+
+/* Protocol Identifier */
+#define PROTID(id) SHIFT_U32((PROTID_##id) & 0xFF, 16)
+#define PROTID_BLOB 0x0D
+#define PROTID_MPKEY 0x14
+#define PROTID_PKKEY 0x14
+#define PROTID_MPSIGN 0x15
+#define PROTID_DSASIGN 0x15
+#define PROTID_DSAVERIFY 0x16
+#define PROTID_SHARED_SECRET 0x17
+#define PROTID_RSA_ENC 0x18
+#define PROTID_RSA_DEC 0x19
+#define PROTID_RSA_FINISH_KEY 0x1A
+
+/*
+ * RSA Protocol Information
+ */
+#define PROT_RSA_FMT(format) SHIFT_U32((PROT_RSA_FMT_##format) & 0x1, 12)
+#define PROT_RSA_FMT_NO 0
+#define PROT_RSA_FMT_PKCS_V1_5 1
+
+#define PROT_RSA_DEC_KEYFORM(format) SHIFT_U32(((format) - 1) & 0x3, 0)
+
+/* RSA Key Protocol Information */
+#define PROT_RSA_KEY(format) SHIFT_U32((PROT_RSA_KEY_##format) & 0x3, 0)
+#define PROT_RSA_KEY_ALL 0
+#define PROT_RSA_KEY_N_D 2
+
+/*
+ * ECC Protocol Information
+ */
+#define PROT_PK_MSG(type) SHIFT_U32(PROT_PK_MSG_##type, 10)
+#define PROT_PK_MSG_HASHED 2
+#define PROT_PK_TYPE(type) SHIFT_U32(PROT_PK_##type, 1)
+#define PROT_PK_DL 0
+#define PROT_PK_ECC 1
+
+/*
+ * BLOB Protocol Information
+ */
+#define PROT_BLOB_FMT_MSTR BIT32(1)
+#define PROT_BLOB_TYPE(type) SHIFT_U32(1, PROT_BLOB_TYPE_##type)
+#define PROT_BLOB_TYPE_BLACK_KEY BIT32(2)
+#define PROT_BLOB_TYPE_RED 0
+#define PROT_BLOB_SEC_MEM BIT32(3)
+#define PROT_BLOB_EKT 8
+#define PROT_BLOB_INFO(aes) SHIFT_U32(PROT_BLOB_AES_##aes, \
+ PROT_BLOB_EKT)
+#define PROT_BLOB_AES_CCM 1
+#define PROT_BLOB_AES_ECB 0
+#define PROT_BLOB_FORMAT(format) SHIFT_U32(0, PROT_BLOB_FORMAT_##format)
+#define PROT_BLOB_FORMAT_NORMAL 0
+
+/*
+ * MP Protocol Information
+ */
+#define PROT_MP_PUBK_SGT BIT32(31)
+#define PROT_MP_CURVE(curve) SHIFT_U32((curve) & 0xF, 17)
+
+/*
+ * Algorithm Identifier
+ */
+#define OP_ALGO(algo) SHIFT_U32((ALGO_##algo) & 0xFF, 16)
+#define ALGO_AES 0x10
+#define ALGO_DES 0x20
+#define ALGO_3DES 0x21
+#define ALGO_ARC4 0x30
+#define ALGO_RNG 0x50
+#define ALGO_MD5 0x40
+#define ALGO_SHA1 0x41
+#define ALGO_SHA224 0x42
+#define ALGO_SHA256 0x43
+#define ALGO_SHA384 0x44
+#define ALGO_SHA512 0x45
+#define ALGO_SHA512_224 0x46
+#define ALGO_SHA512_256 0x47
+
+/* Algorithm Additional Information */
+#define ALGO_AAI(info) SHIFT_U32((AAI_##info) & 0x1FF, 4)
+
+/* AES AAI */
+#define AAI_AES_CTR_MOD128 0x00
+#define AAI_AES_CBC 0x10
+#define AAI_AES_ECB 0x20
+#define AAI_AES_CFB 0x30
+#define AAI_AES_OFB 0x40
+#define AAI_AES_XTS 0x50
+#define AAI_AES_CMAC 0x60
+#define AAI_AES_XCBC_MAC 0x70
+#define AAI_AES_CCM 0x80
+#define AAI_AES_GCM 0x90
+
+/* DES AAI */
+#define AAI_DES_CBC 0x10
+#define AAI_DES_ECB 0x20
+#define AAI_DES_CFB 0x30
+#define AAI_DES_OFB 0x40
+
+/* Digest MD5/SHA AAI */
+#define AAI_DIGEST_HASH 0x00
+#define AAI_DIGEST_HMAC 0x01
+#define AAI_DIGEST_SMAC 0x02
+#define AAI_DIGEST_HMAC_PRECOMP 0x04
+
+/* Algorithm State */
+#define ALGO_AS(state) SHIFT_U32((AS_##state) & 0x3, 2)
+#define AS_UPDATE 0x0
+#define AS_INIT 0x1
+#define AS_FINAL 0x2
+#define AS_INIT_FINAL 0x3
+
+/* Algorithm Encrypt/Decrypt */
+#define ALGO_DECRYPT SHIFT_U32(0x0, 0)
+#define ALGO_ENCRYPT SHIFT_U32(0x1, 0)
+
+/*
+ * Specific RNG Algorithm bits 12-0
+ */
+/* Secure Key */
+#define ALGO_RNG_SK BIT32(12)
+
+/* State Handle */
+#define ALGO_RNG_SH(sh) SHIFT_U32((sh) & 0x3, 4)
+
+/* Prediction Resistance */
+#define ALGO_RNG_PR BIT32(1)
+
+/* State */
+#define AS_RNG_GENERATE 0x0
+#define AS_RNG_INSTANTIATE 0x1
+#define AS_RNG_RESEED 0x2
+#define AS_RNG_UNINSTANTIATE 0x3
+
+/*
+ * JUMP Command fields
+ */
+#define CMD_JUMP_TYPE CMD_TYPE(0x14)
+
+/* Jump Select Type */
+#define JMP_JSL BIT32(24)
+
+/* Jump Type */
+#define JUMP_TYPE(type) SHIFT_U32((JMP_##type) & 0xF, 20)
+#define JMP_LOCAL 0x0
+#define JMP_LOCAL_INC 0x1
+#define JMP_SUBROUTINE_CALL 0x2
+#define JMP_LOCAL_DEC 0x3
+#define JMP_NON_LOCAL 0x4
+#define JMP_SUBROUTINE_RET 0x6
+#define JMP_HALT 0x8
+#define JMP_HALT_USER_STATUS 0xC
+
+/* Test Type */
+#define JUMP_TST_TYPE(type) SHIFT_U32((JMP_TST_##type) & 0x3, 16)
+#define JMP_TST_ALL_COND_TRUE 0x0
+#define JMP_TST_ALL_COND_FALSE 0x1
+#define JMP_TST_ANY_COND_TRUE 0x2
+#define JMP_TST_ANY_COND_FALSE 0x3
+
+/* Jump Source to increment/decrement */
+#define JMP_SRC(src) SHIFT_U32((JMP_SRC_##src) & 0xF, 12)
+#define JMP_SRC_MATH_0 0x0
+
+/* Test Condition */
+#define JMP_COND(cond) SHIFT_U32((JMP_COND_##cond) & 0xFF, 8)
+#define JMP_COND_MATH(cond) SHIFT_U32((JMP_COND_MATH_##cond) & 0xF, 8)
+#define JMP_COND_NONE 0x00
+#define JMP_COND_PKHA_IS_ZERO 0x80
+#define JMP_COND_PKHA_GCD_1 0x40
+#define JMP_COND_PKHA_IS_PRIME 0x20
+#define JMP_COND_MATH_N 0x08
+#define JMP_COND_MATH_Z 0x04
+#define JMP_COND_NIFP 0x04
+#define JMP_COND_MATH_C 0x02
+#define JMP_COND_MATH_NV 0x01
+
+/* Local Offset */
+#define JMP_LOCAL_OFFSET(off) SHIFT_U32((off) & 0xFF, 0)
+
+/*
+ * MATH Command fields
+ */
+#define CMD_MATH_TYPE CMD_TYPE(0x15)
+#define CMD_MATHI_TYPE CMD_TYPE(0x1D)
+
+/* Immediate Four Bytes */
+#define MATH_IFB BIT32(26)
+
+/* Function Mathematical */
+#define MATH_FUNC(func) SHIFT_U32((MATH_FUNC_##func) & 0xF, 20)
+#define MATH_FUNC_ADD 0x0
+#define MATH_FUNC_ADD_W_CARRY 0x1
+#define MATH_FUNC_SUB 0x2
+#define MATH_FUNC_SUB_W_BORROW 0x3
+#define MATH_FUNC_OR 0x4
+#define MATH_FUNC_AND 0x5
+#define MATH_FUNC_XOR 0x6
+#define MATH_FUNC_SHIFT_L 0x7
+#define MATH_FUNC_SHIFT_R 0x8
+#define MATH_FUNC_SHLD 0x9
+#define MATH_FUNC_ZBYTE 0xA
+#define MATH_FUNC_SWAP_BYTES 0xB
+
+/* Source 0 */
+#define MATH_SRC0(reg) SHIFT_U32((MATH_SRC0_##reg) & 0xF, 16)
+#define MATH_SRC0_REG0 0x0
+#define MATH_SRC0_REG1 0x1
+#define MATH_SRC0_REG2 0x2
+#define MATH_SRC0_IMM_DATA 0x4
+#define MATH_SRC0_DPOVRD 0x7
+#define MATH_SRC0_SIL 0x8
+#define MATH_SRC0_SOL 0x9
+#define MATH_SRC0_VSIL 0xA
+#define MATH_SRC0_VSOL 0xB
+#define MATH_SRC0_ZERO 0xC
+#define MATH_SRC0_ONE 0xF
+
+/* Source 1 */
+#define MATH_SRC1(reg) SHIFT_U32((MATH_SRC1_##reg) & 0xF, 12)
+#define MATH_SRC1_REG0 0x0
+#define MATH_SRC1_REG1 0x1
+#define MATH_SRC1_REG2 0x2
+#define MATH_SRC1_IMM_DATA 0x4
+#define MATH_SRC1_DPOVRD 0x7
+#define MATH_SRC1_VSIL 0x8
+#define MATH_SRC1_VSOL 0x9
+#define MATH_SRC1_IFIFO 0xA
+#define MATH_SRC1_OFIFO 0xB
+#define MATH_SRC1_ONE 0xC
+#define MATH_SRC1_ZERO 0xF
+
+/* Destination */
+#define MATH_DST(reg) SHIFT_U32((MATH_DST_##reg) & 0xF, 8)
+#define MATH_DST_REG0 0x0
+#define MATH_DST_REG1 0x1
+#define MATH_DST_REG2 0x2
+#define MATH_DST_DPOVRD 0x7
+#define MATH_DST_SIL 0x8
+#define MATH_DST_SOL 0x9
+#define MATH_DST_VSIL 0xA
+#define MATH_DST_VSOL 0xB
+#define MATH_DST_NODEST 0xF
+
+/* Length */
+#define MATH_LENGTH(len) SHIFT_U32((len) & 0xF, 0)
+
+/* Immediate Value - MATHI operation */
+#define MATHI_SRC(reg) SHIFT_U32((MATH_SRC0_##reg) & 0xF, 16)
+#define MATHI_DST(reg) SHIFT_U32((MATH_DST_##reg) & 0xF, 12)
+#define MATHI_IMM_VALUE(val) SHIFT_U32((val) & 0xFF, 4)
+
+/*
+ * Sequence Input/Output
+ */
+#define CMD_SEQ_IN_TYPE CMD_TYPE(0x1E)
+#define CMD_SEQ_OUT_TYPE CMD_TYPE(0x1F)
+
+/* Extended Length */
+#define SEQ_EXT BIT32(22)
+
+/* Length */
+#define SEQ_LENGTH(len) SHIFT_U32((len) & 0xFFFF, 0)
+
+/*
+ * PKHA Operation
+ */
+#define PKHA_ALG SHIFT_U32(0x8, 20)
+
+#define PKHA_F2M BIT32(17)
+
+#define PKHA_OUTSEL(dst) SHIFT_U32((PKHA_OUTSEL_##dst) & 0x3, 8)
+#define PKHA_OUTSEL_B 0x0
+#define PKHA_OUTSEL_A 0x1
+
+#define PKHA_FUNC(func) SHIFT_U32((PKHA_FUNC_##func) & 0x3F, 0)
+#define PKHA_FUNC_CPY_NSIZE 0x10
+#define PKHA_FUNC_CPY_SSIZE 0x11
+#define PKHA_FUNC_MOD_ADD_A_B 0x02
+#define PKHA_FUNC_MOD_SUB_A_B 0x03
+#define PKHA_FUNC_MOD_SUB_B_A 0x04
+#define PKHA_FUNC_MOD_MUL_A_B 0x05
+#define PKHA_FUNC_MOD_EXP_A_E 0x06
+#define PKHA_FUNC_MOD_AMODN 0x07
+#define PKHA_FUNC_MOD_INV_A 0x08
+#define PKHA_FUNC_ECC_POINT_ADD_P1_P2 0x09
+#define PKHA_FUNC_ECC_POINT_DBL_P1 0x0A
+#define PKHA_FUNC_ECC_POINT_MUL_E_P1 0x0B
+#define PKHA_FUNC_MONT_RADIX_R2_MODE_N 0x0C
+#define PKHA_FUNC_GCD_A_N 0x0E
+#define PKHA_FUNC_MR_PRIMER_TEST 0x0F
+#define PKHA_FUNC_MOD_CHECK_POINT 0x1C
+
+/* PKHA Copy Memory Source and Destination */
+#define PKHA_REG_SRC(reg) SHIFT_U32((PKHA_REG_##reg) & 0x7, 17)
+#define PKHA_REG_DST(reg) SHIFT_U32((PKHA_REG_##reg) & 0x3, 10)
+#define PKHA_REG_A 0x0
+#define PKHA_REG_B 0x1
+#define PKHA_REG_E 0x2
+#define PKHA_REG_N 0x3
+
+#define PKHA_SEG_SRC(seg) SHIFT_U32((seg) & 0x3, 8)
+#define PKHA_SEG_DST(seg) SHIFT_U32((seg) & 0x3, 6)
+
+#define PKHA_CPY_SRC(src) PKHA_CPY_SRC_##src
+#define PKHA_CPY_SRC_A0 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(0))
+#define PKHA_CPY_SRC_A1 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(1))
+#define PKHA_CPY_SRC_A2 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(2))
+#define PKHA_CPY_SRC_A3 (PKHA_REG_SRC(A) | PKHA_SEG_SRC(3))
+#define PKHA_CPY_SRC_B0 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(0))
+#define PKHA_CPY_SRC_B1 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(1))
+#define PKHA_CPY_SRC_B2 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(2))
+#define PKHA_CPY_SRC_B3 (PKHA_REG_SRC(B) | PKHA_SEG_SRC(3))
+#define PKHA_CPY_SRC_N0 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(0))
+#define PKHA_CPY_SRC_N1 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(1))
+#define PKHA_CPY_SRC_N2 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(2))
+#define PKHA_CPY_SRC_N3 (PKHA_REG_SRC(N) | PKHA_SEG_SRC(3))
+
+#define PKHA_CPY_DST(dst) PKHA_CPY_DST_##dst
+#define PKHA_CPY_DST_A0 (PKHA_REG_DST(A) | PKHA_SEG_DST(0))
+#define PKHA_CPY_DST_A1 (PKHA_REG_DST(A) | PKHA_SEG_DST(1))
+#define PKHA_CPY_DST_A2 (PKHA_REG_DST(A) | PKHA_SEG_DST(2))
+#define PKHA_CPY_DST_A3 (PKHA_REG_DST(A) | PKHA_SEG_DST(3))
+#define PKHA_CPY_DST_B0 (PKHA_REG_DST(B) | PKHA_SEG_DST(0))
+#define PKHA_CPY_DST_B1 (PKHA_REG_DST(B) | PKHA_SEG_DST(1))
+#define PKHA_CPY_DST_B2 (PKHA_REG_DST(B) | PKHA_SEG_DST(2))
+#define PKHA_CPY_DST_B3 (PKHA_REG_DST(B) | PKHA_SEG_DST(3))
+#define PKHA_CPY_DST_N0 (PKHA_REG_DST(N) | PKHA_SEG_DST(0))
+#define PKHA_CPY_DST_N1 (PKHA_REG_DST(N) | PKHA_SEG_DST(1))
+#define PKHA_CPY_DST_N2 (PKHA_REG_DST(N) | PKHA_SEG_DST(2))
+#define PKHA_CPY_DST_N3 (PKHA_REG_DST(N) | PKHA_SEG_DST(3))
+#define PKHA_CPY_DST_E (PKHA_REG_DST(E))
+
+/*
+ * Descriptor Protocol Data Block
+ */
+/* RSA Encryption */
+#define PDB_RSA_ENC_SGT_F SHIFT_U32(1, 31)
+#define PDB_RSA_ENC_SGT_G SHIFT_U32(1, 30)
+#define PDB_RSA_ENC_E_SIZE(len) SHIFT_U32((len) & 0xFFF, 12)
+#define PDB_RSA_ENC_N_SIZE(len) SHIFT_U32((len) & 0xFFF, 0)
+#define PDB_RSA_ENC_F_SIZE(len) SHIFT_U32((len) & 0xFFF, 0)
+
+/* RSA Decryption */
+#define PDB_RSA_DEC_SGT_G SHIFT_U32(1, 31)
+#define PDB_RSA_DEC_SGT_F SHIFT_U32(1, 30)
+#define PDB_RSA_DEC_D_SIZE(len) SHIFT_U32((len) & 0xFFF, 12)
+#define PDB_RSA_DEC_N_SIZE(len) SHIFT_U32((len) & 0xFFF, 0)
+#define PDB_RSA_DEC_Q_SIZE(len) SHIFT_U32((len) & 0xFFF, 12)
+#define PDB_RSA_DEC_P_SIZE(len) SHIFT_U32((len) & 0xFFF, 0)
+
+/* RSA Finalize Key */
+#define PDB_RSA_KEY_P_SIZE(len) SHIFT_U32((len) & 0x1FF, 0)
+#define PDB_RSA_KEY_E_SIZE(len) SHIFT_U32((len) & 0x3FF, 0)
+#define PDB_RSA_KEY_N_SIZE(len) SHIFT_U32((len) & 0x3FF, 16)
+
+/* Manufacturing Curve Select */
+#define PDB_SGT_MP_SIGN_MSG SHIFT_U32(1, 31)
+#define PDB_SGT_MP_SIGN_C SHIFT_U32(1, 29)
+#define PDB_SGT_MP_SIGN_D SHIFT_U32(1, 28)
+#define PDB_MP_CSEL_P256 0x03
+#define PDB_MP_CSEL_P384 0x04
+#define PDB_MP_CSEL_P521 0x05
+
+/* Public Key Generation */
+#define PDB_PKGEN_PD1 SHIFT_U32(1, 25)
+/* Public Key Signature */
+#define PDB_PKSIGN_PD1 SHIFT_U32(1, 22)
+/* Public Key Verify */
+#define PDB_PKVERIFY_PD1 SHIFT_U32(1, 22)
+/* Shared Secret */
+#define PDB_SHARED_SECRET_PD1 SHIFT_U32(1, 25)
+
+/* DSA Signatures */
+#define PDB_DSA_SIGN_N(len) SHIFT_U32((len) & (0x7F), 0)
+#define PDB_DSA_SIGN_L(len) SHIFT_U32((len) & (0x3FF), 7)
+
+/* SGT Flags Signature */
+#define PDB_SGT_PKSIGN_MSG SHIFT_U32(1, 27)
+#define PDB_SGT_PKSIGN_SIGN_C SHIFT_U32(1, 26)
+#define PDB_SGT_PKSIGN_SIGN_D SHIFT_U32(1, 25)
+
+/* DSA Verify */
+#define PDB_DSA_VERIF_N(len) SHIFT_U32((len) & (0x7F), 0)
+#define PDB_DSA_VERIF_L(len) SHIFT_U32((len) & (0x3FF), 7)
+
+/* SGT Flags Verify */
+#define PDB_SGT_PKVERIF_MSG SHIFT_U32(1, 27)
+#define PDB_SGT_PKVERIF_SIGN_C SHIFT_U32(1, 26)
+#define PDB_SGT_PKVERIF_SIGN_D SHIFT_U32(1, 25)
+
+/* SGT Flags Shared Secret */
+#define PDB_SGT_PKDH_SECRET SHIFT_U32(1, 27)
+
+/* DL Keypair Generation */
+#define PDB_DL_KEY_L_SIZE(len) SHIFT_U32((len) & (0x3FF), 7)
+#define PDB_DL_KEY_N_MASK 0x7F
+#define PDB_DL_KEY_N_SIZE(len) SHIFT_U32((len) & (PDB_DL_KEY_N_MASK), 0)
+
+/* ECC Domain Selection */
+#define PDB_ECC_ECDSEL(curve) SHIFT_U32((curve) & 0x3F, 7)
+
+/* Black key padding */
+#define BLACK_KEY_NONCE_SIZE 6
+#define BLACK_KEY_ICV_SIZE 6
+
+/*
+ * ECC Predefined Domain
+ */
+enum caam_ecc_curve {
+ CAAM_ECC_P192 = (0x00),
+ CAAM_ECC_P224,
+ CAAM_ECC_P256,
+ CAAM_ECC_P384,
+ CAAM_ECC_P521,
+ CAAM_ECC_MAX,
+ CAAM_ECC_UNKNOWN = (0xFF),
+};
+
+/*
+ * Blob encapsulation
+ */
+#define BLOB_KEY_MODIFIER_SIZE 16
+#define BLOB_KEY_BLOB_SIZE 32
+#define BLOB_MAC_SIZE 16
+#define BLOB_MAX_BUFFER_LEN ((1ull << 32) - 1)
+#define CAAM_CRYPTO_BLOB_OVERHEAD ((BLOB_KEY_BLOB_SIZE) + (BLOB_MAC_SIZE))
+
+#endif /* __CAAM_DESC_DEFINES_H__ */
diff --git a/sys/arm64/qoriq/caam/jr/caam_desc_helper.h b/sys/arm64/qoriq/caam/jr/caam_desc_helper.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_desc_helper.h
@@ -0,0 +1,568 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright 2018-2021 NXP
+ *
+ * Brief CAAM Descriptor interface.
+ */
+
+/*
+ * File imported from OP-TEE.
+ */
+
+#ifndef __CAAM_DESC_HELPER_H__
+#define __CAAM_DESC_HELPER_H__
+
+#include <sys/types.h>
+
+#include "caam_desc_defines.h"
+
+/*
+ * Returns the descriptor size in bytes of nbEntries
+ */
+#define DESC_SZBYTES(nbentries) ((nbentries) * sizeof(uint32_t))
+
+/*
+ * Descriptor Header starting at idx w/o descriptor length
+ */
+#define DESC_HDR(idx) (CMD_HDR_JD_TYPE | HDR_JD_ONE | HDR_JD_START_IDX(idx))
+
+/*
+ * Shared Descriptor Header starting at idx
+ */
+#define DESC_SHR_HDR(idx) (CMD_HDR_SHR_TYPE | HDR_JD_ONE | HDR_JD_START_IDX(idx))
+
+/*
+ * Descriptor Header starting at index 0 with descriptor length len
+ */
+#define DESC_HEADER(len) (DESC_HDR(0) | HDR_JD_DESCLEN(len))
+
+/*
+ * Shared descriptor header starting at index 0 with length len
+ */
+#define DESC_SHR_HEADER(len) (DESC_SHR_HDR(0) | HDR_JD_DESCLEN(len))
+
+/*
+ * Descriptor Header starting at idx with descriptor length len
+ */
+#define DESC_HEADER_IDX(len, idx) (DESC_HDR(idx) | HDR_JD_DESCLEN(len))
+
+/*
+ * Jump Local of class cla to descriptor offset if test meet the
+ * condition cond
+ */
+#define JUMP_LOCAL(cla, test, cond, offset) \
+ (CMD_JUMP_TYPE | CMD_CLASS(cla) | JUMP_TYPE(LOCAL) | \
+ JUMP_TST_TYPE(test) | (cond) | JMP_LOCAL_OFFSET(offset))
+
+/*
+ * Jump Local of no class to descriptor offset if test meet the
+ * condition cond
+ */
+#define JUMP_CNO_LOCAL(test, cond, offset) \
+ JUMP_LOCAL(CLASS_NO, test, cond, offset)
+
+/*
+ * Jump Local of class 1 to descriptor offset if test meet the
+ * condition cond
+ */
+#define JUMP_C1_LOCAL(test, cond, offset) \
+ JUMP_LOCAL(CLASS_1, test, cond, offset)
+
+/*
+ * First decrement specified source then
+ * Jump Local of no class to descriptor offset if test meet the
+ * condition cond
+ */
+#define JUMP_CNO_LOCAL_DEC(test, src, cond, offset) \
+ (CMD_JUMP_TYPE | CMD_CLASS(CLASS_NO) | JUMP_TYPE(LOCAL_DEC) | \
+ JUMP_TST_TYPE(test) | JMP_SRC(src) | (cond) | \
+ JMP_LOCAL_OFFSET(offset))
+
+/*
+ * Wait until test condition meet and jump next
+ */
+#define WAIT_COND(test, cond) \
+ (JUMP_LOCAL(CLASS_NO, test, JMP_COND(cond), 1) | JMP_JSL)
+
+/*
+ * Jump No Local of class cla to descriptor offset if test meet the
+ * condition cond
+ */
+#define JUMP_NOTLOCAL(cla, test, cond) \
+ (CMD_JUMP_TYPE | CMD_CLASS(cla) | JUMP_TYPE(NON_LOCAL) | \
+ JUMP_TST_TYPE(test) | (cond))
+
+/*
+ * User Halt with error if test meet the condition cond
+ */
+#define HALT_USER(test, cond, error) \
+ (CMD_JUMP_TYPE | JUMP_TYPE(HALT_USER_STATUS) | JUMP_TST_TYPE(test) | \
+ JMP_COND(cond) | JMP_LOCAL_OFFSET(error))
+
+/*
+ * Load Immediate value of length len to register dst of class cla
+ */
+#define LD_IMM(cla, dst, len) \
+ (CMD_LOAD_TYPE | CMD_CLASS(cla) | CMD_IMM | LOAD_DST(dst) | \
+ LOAD_LENGTH(len))
+
+/**
+ * @brief Load Immediate value of length \a len to register \a dst of
+ * class \a cla starting of register offset \a off
+ */
+#define LD_IMM_OFF(cla, dst, len, off) \
+ (CMD_LOAD_TYPE | CMD_CLASS(cla) | CMD_IMM | LOAD_DST(dst) | \
+ LOAD_OFFSET(off) | LOAD_LENGTH(len))
+
+/*
+ * Load Immediate value of length len to register dst w/o class
+ */
+#define LD_NOCLASS_IMM(dst, len) LD_IMM(CLASS_NO, dst, len)
+
+/*
+ * Load value of length len to register dst of class cla
+ */
+#define LD_NOIMM(cla, dst, len) \
+ (CMD_LOAD_TYPE | CMD_CLASS(cla) | LOAD_DST(dst) | LOAD_LENGTH(len))
+
+/*
+ * Load value of length len to register dst of class cla starting
+ * at register offset off
+ */
+#define LD_NOIMM_OFF(cla, dst, len, off) \
+ (CMD_LOAD_TYPE | CMD_CLASS(cla) | LOAD_DST(dst) | LOAD_OFFSET(off) | \
+ LOAD_LENGTH(len))
+
+/*
+ * FIFO Load to register dst class cla with action act
+ */
+#define FIFO_LD(cla, dst, act, len) \
+ (CMD_FIFO_LOAD_TYPE | CMD_CLASS(cla) | FIFO_LOAD_INPUT(dst) | \
+ FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len))
+
+/*
+ * FIFO Load to register dst class cla with action act.
+ * Pointer is a Scatter/Gather Table
+ */
+#define FIFO_LD_SGT(cla, dst, act, len) \
+ (CMD_FIFO_LOAD_TYPE | CMD_CLASS(cla) | CMD_SGT | \
+ FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len))
+
+/*
+ * FIFO Load to register dst class cla with action act.
+ * Pointer is a Scatter/Gather Table
+ * The length is externally defined
+ */
+#define FIFO_LD_SGT_EXT(cla, dst, act) \
+ (CMD_FIFO_LOAD_TYPE | CMD_CLASS(cla) | CMD_SGT | FIFO_LOAD_EXT | \
+ FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act))
+
+/*
+ * FIFO Load to register dst class cla with action act.
+ * The length is externally defined
+ */
+#define FIFO_LD_EXT(cla, dst, act) \
+ (CMD_FIFO_LOAD_TYPE | FIFO_LOAD_EXT | CMD_CLASS(cla) | \
+ FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act))
+
+/*
+ * FIFO Load Immediate data length len to register dst class cla
+ * with action act.
+ */
+#define FIFO_LD_IMM(cla, dst, act, len) \
+ (CMD_FIFO_LOAD_TYPE | CMD_IMM | CMD_CLASS(cla) | \
+ FIFO_LOAD_INPUT(dst) | FIFO_LOAD_ACTION(act) | FIFO_LOAD_LENGTH(len))
+
+/*
+ * Store value of length len from register src of class cla
+ */
+#define ST_NOIMM(cla, src, len) \
+ (CMD_STORE_TYPE | CMD_CLASS(cla) | STORE_SRC(src) | STORE_LENGTH(len))
+
+/*
+ * Store value of length len from register src of class cla
+ * Pointer is a Scatter/Gather Table
+ */
+#define ST_SGT_NOIMM(cla, src, len) \
+ (CMD_STORE_TYPE | CMD_CLASS(cla) | CMD_SGT | STORE_SRC(src) | \
+ STORE_LENGTH(len))
+
+/*
+ * Store value of length len from register src of class cla starting
+ * at register offset off
+ */
+#define ST_NOIMM_OFF(cla, src, len, off) \
+ (CMD_STORE_TYPE | CMD_CLASS(cla) | STORE_SRC(src) | \
+ STORE_OFFSET(off) | STORE_LENGTH(len))
+
+/*
+ * Store value of length len from register src of class cla
+ */
+#define ST_NOIMM_SEQ(cla, src, len) \
+ (CMD_STORE_SEQ_TYPE | CMD_CLASS(cla) | STORE_SRC(src) | \
+ STORE_LENGTH(len))
+
+/*
+ * FIFO Store from register src of length len
+ */
+#define FIFO_ST(src, len) \
+ (CMD_FIFO_STORE_TYPE | FIFO_STORE_OUTPUT(src) | FIFO_STORE_LENGTH(len))
+
+/*
+ * FIFO Store from register src.
+ * The length is externally defined
+ */
+#define FIFO_ST_EXT(src) \
+ (CMD_FIFO_STORE_TYPE | FIFO_STORE_EXT | FIFO_STORE_OUTPUT(src))
+
+/*
+ * FIFO Store from register src of length len.
+ * Pointer is a Scatter/Gather Table
+ */
+#define FIFO_ST_SGT(src, len) \
+ (CMD_FIFO_STORE_TYPE | CMD_SGT | FIFO_STORE_OUTPUT(src) | \
+ FIFO_STORE_LENGTH(len))
+
+/*
+ * FIFO Store from register src.
+ * Pointer is a Scatter/Gather Table
+ * The length is externally defined
+ */
+#define FIFO_ST_SGT_EXT(src) \
+ (CMD_FIFO_STORE_TYPE | CMD_SGT | FIFO_STORE_EXT | \
+ FIFO_STORE_OUTPUT(src))
+
+/*
+ * SEQ FIFO Store from register src of length len
+ */
+#define FIFO_ST_SEQ(src, len) \
+ (CMD_SEQ_FIFO_STORE_TYPE | FIFO_STORE_OUTPUT(src) | \
+ FIFO_STORE_LENGTH(len))
+
+/*
+ * RNG State Handle instantation operation for sh ID
+ */
+#define RNG_SH_INST(sh) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS1) | OP_ALGO(RNG) | ALGO_RNG_SH(sh) | \
+ ALGO_AS(RNG_INSTANTIATE) | ALGO_RNG_PR)
+
+/*
+ * RNG Generates Secure Keys
+ */
+#define RNG_GEN_SECKEYS \
+ (CMD_OP_TYPE | OP_TYPE(CLASS1) | OP_ALGO(RNG) | ALGO_RNG_SK | \
+ ALGO_AS(RNG_GENERATE))
+
+/*
+ * RNG Generates Data
+ */
+#define RNG_GEN_DATA \
+ (CMD_OP_TYPE | OP_TYPE(CLASS1) | OP_ALGO(RNG) | ALGO_AS(RNG_GENERATE))
+
+/*
+ * Hash Init Operation of algorithm algo
+ */
+#define HASH_INIT(algo) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT) | ALGO_ENCRYPT)
+
+/*
+ * Hash Update Operation of algorithm algo
+ */
+#define HASH_UPDATE(algo) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(UPDATE) | \
+ ALGO_ENCRYPT)
+
+/*
+ * Hash Final Operation of algorithm algo
+ */
+#define HASH_FINAL(algo) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(FINAL) | ALGO_ENCRYPT)
+
+/*
+ * Hash Init and Final Operation of algorithm algo
+ */
+#define HASH_INITFINAL(algo) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT_FINAL) | \
+ ALGO_ENCRYPT)
+
+/*
+ * HMAC Init Decryption Operation of algorithm algo
+ */
+#define HMAC_INIT_DECRYPT(algo) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT) | \
+ ALGO_AAI(DIGEST_HMAC) | ALGO_DECRYPT)
+
+/*
+ * HMAC Init and Final Operation of algorithm algo with Precomp key
+ */
+#define HMAC_INITFINAL_PRECOMP(algo) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT_FINAL) | \
+ ALGO_AAI(DIGEST_HMAC_PRECOMP) | ALGO_ENCRYPT)
+
+/*
+ * HMAC Init Operation of algorithm algo with Precomp key
+ */
+#define HMAC_INIT_PRECOMP(algo) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(INIT) | \
+ ALGO_AAI(DIGEST_HMAC_PRECOMP) | ALGO_ENCRYPT)
+
+/*
+ * HMAC Final Operation of algorithm algo with Precomp key
+ */
+#define HMAC_FINAL_PRECOMP(algo) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS2) | (algo) | ALGO_AS(FINAL) | \
+ ALGO_AAI(DIGEST_HMAC_PRECOMP) | ALGO_ENCRYPT)
+
+/*
+ * Cipher Init and Final Operation of algorithm algo
+ */
+#define CIPHER_INITFINAL(algo, encrypt) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(INIT_FINAL) | \
+ ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT))
+
+/*
+ * Cipher Init Operation of algorithm algo
+ */
+#define CIPHER_INIT(algo, encrypt) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(INIT) | \
+ ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT))
+
+/*
+ * Cipher Update Operation of algorithm algo
+ */
+#define CIPHER_UPDATE(algo, encrypt) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(UPDATE) | \
+ ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT))
+
+/*
+ * Cipher Final Operation of algorithm algo
+ */
+#define CIPHER_FINAL(algo, encrypt) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(FINAL) | \
+ ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT))
+
+/*
+ * Cipher Init Final Operation of algorithm algo
+ */
+#define CIPHER_INIT_FINAL(algo, encrypt) \
+ (CMD_OP_TYPE | OP_TYPE(CLASS1) | (algo) | ALGO_AS(INIT_FINAL) | \
+ ((encrypt) ? ALGO_ENCRYPT : ALGO_DECRYPT))
+
+/*
+ * Load a class cla key of length len to register dst.
+ * Immediate version of instruction.
+ */
+#define LD_KEY_IMM(cla, dst, len) \
+ (CMD_KEY_TYPE | CMD_CLASS(cla) | KEY_DEST(dst) | \
+ KEY_LENGTH(len) | CMD_IMM)
+
+/*
+ * Load a class cla key of length len to register dst.
+ * Key can be stored in plain text.
+ */
+#define LD_KEY_PLAIN(cla, dst, len) \
+ (CMD_KEY_TYPE | CMD_CLASS(cla) | KEY_PTS | KEY_DEST(dst) | \
+ KEY_LENGTH(len))
+
+/*
+ * Load a class cla key of length len to register dst.
+ * Key can be stored in plain text.
+ * Pointer is a Scatter/Gatter Table
+ */
+#define LD_KEY_SGT_PLAIN(cla, dst, len) \
+ (CMD_KEY_TYPE | CMD_CLASS(cla) | CMD_SGT | KEY_PTS | KEY_DEST(dst) | \
+ KEY_LENGTH(len))
+
+/*
+ * Load a split key of length len.
+ */
+#define LD_KEY_SPLIT(len) \
+ (CMD_KEY_TYPE | CMD_CLASS(CLASS_2) | KEY_DEST(MDHA_SPLIT) | \
+ KEY_LENGTH(len))
+
+/*
+ * MPPRIVK generation function.
+ */
+#define MPPRIVK (CMD_OP_TYPE | OP_TYPE(ENCAPS) | PROTID(MPKEY))
+
+/*
+ * MPPUBK generation function.
+ */
+#define MPPUBK (CMD_OP_TYPE | OP_TYPE(DECAPS) | PROTID(MPKEY))
+
+/*
+ * MPSIGN function.
+ */
+#define MPSIGN_OP (CMD_OP_TYPE | OP_TYPE(DECAPS) | PROTID(MPSIGN))
+
+/*
+ * Operation Mathematical of length len
+ * dest = src0 (operation func) src1
+ */
+#define MATH(func, src0, src1, dst, len) \
+ (CMD_MATH_TYPE | MATH_FUNC(func) | MATH_SRC0(src0) | MATH_SRC1(src1) | \
+ MATH_DST(dst) | MATH_LENGTH(len))
+
+/*
+ * Operation Mathematical of length len using an immediate value as operand 1
+ * dest = src (operation func) val
+ */
+#define MATHI_OP1(func, src, val, dst, len) \
+ (CMD_MATHI_TYPE | MATH_FUNC(func) | MATHI_SRC(src) | \
+ MATHI_IMM_VALUE(val) | MATHI_DST(dst) | MATH_LENGTH(len))
+
+/*
+ * PKHA Copy function from src to dst. Copy number of words specified
+ * in Source size register
+ */
+#define PKHA_CPY_SSIZE(src, dst) \
+ (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_FUNC(CPY_SSIZE) | \
+ PKHA_CPY_SRC(src) | PKHA_CPY_DST(dst))
+
+/*
+ * PKHA Copy N-Size function from src to dst. Copy number of words specified
+ * in PKHA N size register
+ */
+#define PKHA_CPY_NSIZE(src, dst) \
+ (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_FUNC(CPY_NSIZE) | \
+ PKHA_CPY_SRC(src) | PKHA_CPY_DST(dst))
+
+/*
+ * PKHA Operation op result into dst
+ */
+#define PKHA_OP(op, dst) \
+ (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_FUNC(op) | \
+ PKHA_OUTSEL(dst))
+
+/*
+ * PKHA Binomial operation op result into dst
+ */
+#define PKHA_F2M_OP(op, dst) \
+ (CMD_OP_TYPE | OP_TYPE(PKHA) | PKHA_ALG | PKHA_F2M | PKHA_FUNC(op) | \
+ PKHA_OUTSEL(dst))
+
+/*
+ * Move src to dst
+ */
+#define MOVE(src, dst, off, len) \
+ (CMD_MOVE_TYPE | MOVE_SRC(src) | MOVE_DST(dst) | MOVE_OFFSET(off) | \
+ MOVE_LENGTH(len))
+
+/*
+ * Move src to dst and wait until completion
+ */
+#define MOVE_WAIT(src, dst, off, len) \
+ (CMD_MOVE_TYPE | MOVE_WC | MOVE_SRC(src) | MOVE_DST(dst) | \
+ MOVE_OFFSET(off) | MOVE_LENGTH(len))
+
+/*
+ * RSA Encryption using format
+ */
+#define RSA_ENCRYPT(format) \
+ (CMD_OP_TYPE | PROTID(RSA_ENC) | PROT_RSA_FMT(format))
+
+/*
+ * RSA Decryption using format
+ */
+#define RSA_DECRYPT(format) \
+ (CMD_OP_TYPE | PROTID(RSA_DEC) | PROT_RSA_FMT(format))
+
+/*
+ * RSA Finalize Key in format
+ */
+#define RSA_FINAL_KEY(format) \
+ (CMD_OP_TYPE | PROTID(RSA_FINISH_KEY) | PROT_RSA_KEY(format))
+
+/*
+ * Public Keypair generation
+ */
+#define PK_KEYPAIR_GEN(type) \
+ (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(PKKEY) | PROT_PK_TYPE(type))
+
+/*
+ * DSA/ECDSA signature of message hashed
+ */
+#define DSA_SIGN(type) \
+ (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSASIGN) | PROT_PK_MSG(HASHED) | \
+ PROT_PK_TYPE(type))
+
+/*
+ * DSA/ECDSA signature verify message hashed
+ */
+#define DSA_VERIFY(type) \
+ (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(DSAVERIFY) | \
+ PROT_PK_MSG(HASHED) | PROT_PK_TYPE(type))
+
+/*
+ * DH/ECC Shared Secret
+ */
+#define SHARED_SECRET(type) \
+ (CMD_OP_TYPE | OP_TYPE(UNI) | PROTID(SHARED_SECRET) | \
+ PROT_PK_TYPE(type))
+
+/*
+ * Blob Master Key Verification
+ */
+#define BLOB_MSTR_KEY \
+ (CMD_OP_TYPE | OP_TYPE(ENCAPS) | PROTID(BLOB) | PROT_BLOB_FMT_MSTR)
+
+/*
+ * Blob encapsulation
+ */
+#define BLOB_ENCAPS \
+ (CMD_OP_TYPE | OP_TYPE(ENCAPS) | PROTID(BLOB) | \
+ PROT_BLOB_FORMAT(NORMAL))
+
+/*
+ * Blob decapsulation
+ */
+#define BLOB_DECAPS \
+ (CMD_OP_TYPE | OP_TYPE(DECAPS) | PROTID(BLOB) | \
+ PROT_BLOB_FORMAT(NORMAL))
+
+/*
+ * Black key CCM size
+ */
+#define BLACK_KEY_CCM_SIZE(size) \
+ (ROUNDUP(size, 8) + BLACK_KEY_NONCE_SIZE + BLACK_KEY_ICV_SIZE)
+
+/*
+ * Black key ECB size
+ */
+#define BLACK_KEY_ECB_SIZE(size) ROUNDUP(size, 16)
+
+/*
+ * Sequence Input Pointer of length len
+ */
+#define SEQ_IN_PTR(len) (CMD_SEQ_IN_TYPE | SEQ_LENGTH(len))
+
+/*
+ * Sequence Input Pointer with length in EXT_LENGTH optional word
+ */
+#define SEQ_IN_PTR_EXT ((SEQ_IN_PTR(0)) | SEQ_EXT)
+
+/*
+ * Sequence Output Pointer of length len
+ */
+#define SEQ_OUT_PTR(len) (CMD_SEQ_OUT_TYPE | SEQ_LENGTH(len))
+
+/*
+ * Sequence Output Pointer with length in EXT_LENGTH optional word
+ */
+#define SEQ_OUT_PTR_EXT ((SEQ_OUT_PTR(0)) | SEQ_EXT)
+
+/*
+ * Sequence Output SGT of length len
+ */
+#define SEQ_OUT_SGT_PTR(len) (CMD_SEQ_OUT_TYPE | CMD_SGT | SEQ_LENGTH(len))
+
+struct caam_sgt_entry {
+ uint32_t ptr_hi;
+ uint32_t ptr_lo;
+ uint32_t len_f_e;
+ uint32_t offset;
+};
+
+#define CAAM_SGT_FINAL 0x40000000
+
+#endif /* __CAAM_DESC_HELPER_H__ */
diff --git a/sys/arm64/qoriq/caam/jr/caam_jobdesc.h b/sys/arm64/qoriq/caam/jr/caam_jobdesc.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_jobdesc.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2017-2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_JOBDESC_H
+#define CAAM_JOBDESC_H
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#define DESC_LEN_MASK 0x7f
+
+#define DESC_START_SHIFT 16
+
+#define CLASS_SHIFT 25
+
+#define CMD_SHIFT 27
+#define OP_TYPE_SHIFT 24
+#define OP_PCLID_SHIFT 16
+
+/*
+ * @brief Initialize the descriptor.
+ *
+ * @param [in] desc descriptor pointer
+ */
+void caam_jobdesc_init(uint32_t *desc);
+
+/*
+ * @brief Update start index in first word of descriptor.
+ *
+ * @param [in] desc descriptor pointer
+ * @param [in] index new start index
+ */
+void caam_jobdesc_update_start_index(uint32_t *desc, uint32_t index);
+
+/*
+ * @brief Return Length of descriptor from first word.
+ *
+ * @param [in] desc descriptor pointer
+ *
+ * @retval :: uint32_t descriptor length
+ */
+uint32_t caam_jobdesc_length(uint32_t *desc);
+
+/*
+ * @brief Add word in the descriptor and increment the length.
+ *
+ * @param [in] desc descriptor pointer
+ * @param [in] word word to append
+ */
+void caam_jobdesc_add_word(uint32_t *desc, uint32_t word);
+
+/*
+ * @brief Add Pointer to the descriptor and increment the length.
+ *
+ * @param [in] desc descriptor pointer
+ * @param [in] ptr pointer to append
+ */
+void caam_jobdesc_add_ptr(uint32_t *desc, bus_addr_t ptr);
+
+#endif /* CAAM_JOBDESC_H */
diff --git a/sys/arm64/qoriq/caam/jr/caam_jobdesc.c b/sys/arm64/qoriq/caam/jr/caam_jobdesc.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_jobdesc.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017-2020 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include "caam_jobdesc.h"
+#include "caam_jr_hw.h"
+
+void
+caam_jobdesc_init(uint32_t *desc)
+{
+ *desc = 0;
+}
+
+void
+caam_jobdesc_update_start_index(uint32_t *desc, uint32_t index)
+{
+ desc[0] |= (index << DESC_START_SHIFT);
+}
+
+uint32_t
+caam_jobdesc_length(uint32_t *desc)
+{
+ return desc[0] & DESC_LEN_MASK;
+}
+
+void
+caam_jobdesc_add_word(uint32_t *desc, uint32_t word)
+{
+ uint32_t len = caam_jobdesc_length(desc);
+
+ /* We can add only if there is place */
+ MPASS(len < MAX_DESC_SIZE_WORDS);
+
+ /* Add Word at Last */
+ uint32_t *last = desc + len;
+ *last = word;
+
+ /* Increase the length */
+ desc[0] += 1;
+}
+
+void
+caam_jobdesc_add_ptr(uint32_t *desc, bus_addr_t ptr)
+{
+ uint32_t len = caam_jobdesc_length(desc);
+
+ /* Add Word at Last */
+ ptr_addr_t *ptr_addr = (ptr_addr_t *)(desc + len);
+
+ ptr_addr->m_halves.high = PHYS_ADDR_HI(ptr);
+ ptr_addr->m_halves.low = PHYS_ADDR_LO(ptr);
+
+ /* Increase the length */
+ desc[0] += (uint32_t)(sizeof(bus_addr_t) / sizeof(uint32_t));
+}
diff --git a/sys/arm64/qoriq/caam/jr/caam_jr.h b/sys/arm64/qoriq/caam/jr/caam_jr.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_jr.h
@@ -0,0 +1,315 @@
+/*
+ * Copyright 2017-2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_JR_H
+#define CAAM_JR_H
+
+#include <sys/types.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/mutex.h>
+
+#include "caam_jr_cfg.h"
+
+/* The maximum size of a CAAM descriptor, in WORDs (32 bits). */
+#define MAX_DESC_SIZE_WORDS 64
+
+/* Return codes for JR driver APIs */
+typedef enum caam_jr_return_code_e {
+ CAAM_SUCCESS = 0,
+ CAAM_INVALID_INPUT_PARAM,
+ CAAM_OUT_OF_MEMORY,
+ CAAM_DESCRIPTOR_IN_FLIGHT,
+ CAAM_LAST_DESCRIPTOR_IN_FLIGHT,
+ CAAM_PROCESSING_ERROR,
+ CAAM_DESC_PROCESSING_ERROR,
+ CAAM_JR_IS_FULL,
+ CAAM_DRIVER_RELEASE_IN_PROGRESS,
+ CAAM_DRIVER_ALREADY_INITIALIZED,
+ CAAM_DRIVER_NOT_INITIALIZED,
+ CAAM_JOB_RING_RESET_IN_PROGRESS,
+ CAAM_RESET_ENGINE_FAILED,
+ CAAM_ENABLE_IRQS_FAILED,
+ CAAM_DISABLE_IRQS_FAILED,
+ CAAM_RETURN_CODE_MAX_VALUE,
+} caam_jr_return_code_t;
+
+typedef struct caam_jr_dma_map {
+ bus_dmamap_t mmap;
+ void *buf;
+ size_t buflen;
+ bus_addr_t bus_addr;
+} caam_jr_dma_map_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
+ * CAAM
+ * @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, device_t dev);
+
+/*
+ * Structure encompassing a job descriptor which is to be processed
+ * by CAAM. User should also initialise this structure with the callback
+ * function pointer which will be called by driver after recieving proccessed
+ * descriptor from CAAM. 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 Jobring callback control structure and utilities
+ */
+struct jr_job_arg {
+ struct cv cv;
+ struct mtx mtx;
+ uint32_t *desc;
+ uint32_t status;
+ device_t dev;
+ bool done;
+};
+
+/*
+ * @brief Initializes jr_job_arg intance
+ *
+ * @param [in] job_arg Instance to initialize
+ * @param [in] name cv and mutex name prefix
+ */
+#define JR_JOB_ARG_INIT(job_arg, name) \
+ memset(&(job_arg), 0, sizeof((job_arg))); \
+ mtx_init(&(job_arg).mtx, #name " cv", NULL, MTX_DEF); \
+ cv_init(&(job_arg).cv, #name " job")
+
+/*
+ * @brief deinitializes jr_job_arg intance
+ *
+ * @param [in] job_arg Instance to deinitialize
+ */
+#define JR_JOB_ARG_DEINIT(job_arg) \
+ cv_destroy(&(job_arg).cv); \
+ mtx_destroy(&(job_arg).mtx)
+
+/*
+ * @brief Blocks until JR_JOB_ARG_SIG_DONE() is performed
+ *
+ * job_arg.status (if used) should be up-to-date after the unblock
+ *
+ * @param [in] job_arg jr_job_arg instance to watch
+ */
+#define JR_JOB_ARG_WAIT_DONE(job_arg) \
+ mtx_lock(&(job_arg).mtx); \
+ if (!(job_arg).done) { \
+ cv_wait(&(job_arg).cv, &(job_arg).mtx); \
+ } \
+ mtx_unlock(&(job_arg).mtx)
+
+/*
+ * @brief Unblocks all JR_JOB_ARG_WAIT_DONE()
+ *
+ * If used at all, job_arg.status should be set before this call
+ *
+ * @param [in] job_arg jr_job_arg intance to signal
+ */
+#define JR_JOB_ARG_SIG_DONE(job_arg) \
+ mtx_lock(&(job_arg).mtx); \
+ (job_arg).done = true; \
+ cv_broadcast(&(job_arg).cv); \
+ mtx_unlock(&(job_arg).mtx)
+
+/*
+ * @brief Initializes the CAAM Job Ring
+ * This functions sets up the job ring for receiving descriptors
+ *
+ * @param [in] dev The handle for the CAAM_JR device to
+ * execute the job on.
+ * @param [in] jr_mode The mode to use (irq or pool)
+ * @param [in] irq_coalescing_timer Timer parameter for IRQ mode
+ * @param [in] irq_coalescing_count Count parameter for IRQ mode
+ *
+ * @note Only pool mode is allowed at this time
+ * @retval :: 0 is returned in case shutdown was successful
+ * @retval :: -1 is returned in case of some error
+ */
+int caam_jr_init(device_t dev, uint8_t jr_mode, uint16_t irq_coalescing_timer,
+ uint8_t irq_coalescing_count);
+
+/*
+ * @brief Submit a descriptor for CAAM processing.
+ * This function creates a "job" which is meant to instruct CAAM 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 CAAM to
+ * start or/and finish the "job" processing.
+ * After the processing is finished the CAAM HW writes the processing result
+ * to the provided output buffer.
+ * The Caller must poll JR driver using caam_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] dev The handle for the CAAM_JR device to execute
+ * the job on.
+ * @param [in] jobdescr 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 caam_jr_enqueue(device_t dev, struct job_descriptor *jobdescr);
+
+/*
+ * @brief Polls for available descriptors processed by CAAM on a specific
+ * Job Ring
+ * This function polls the CAAM 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 caam_jr_dequeue() API cannot be called from within a user_callback
+ * function
+ * @param [in] dev The handle for the CAAM_JR device to execute
+ * the job on.
+ * @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 caam_jr_dequeue(device_t dev, int32_t limit);
+
+/*
+ * @brief Shut down the CAAM Job Ring
+ * This functions clears the current jobs and resets the JobRing hardware.
+ *
+ * @param [in] dev The handle for the CAAM_JR device to execute
+ * the job on.
+ *
+ * @retval :: 0 is returned in case shutdown was successful
+ * @retval :: -1 is returned in case of some error
+ */
+int caam_jr_shutdown(device_t dev);
+
+
+/*
+ * @brief Check if jobring has currently any jobs enqueued, processing or
+ * waiting to be dequeued.
+ *
+ * @param [in] dev The handle for the CAAM_JR device to check
+ *
+ * @retval :: true is returned in case there is any unfinished job on the jr
+ * @retval :: false is returned in case the jr is idle
+ */
+bool caam_jr_busy(device_t dev);
+
+/*
+ * @brief Getter for dma_tag.
+ *
+ * @param [in] dev The handle for the CAAM_JR device.
+ *
+ * @retval :: bus_dma_tag_t
+ */
+bus_dma_tag_t caam_jr_get_tag(device_t dev);
+
+/*
+ * @brief Getter for DMA data_tag.
+ *
+ * @param [in] dev The handle for the CAAM_JR device.
+ *
+ * @retval :: bus_dma_tag_t
+ */
+bus_dma_tag_t caam_jr_get_data_tag(device_t dev);
+
+/* caam_jr_dma_map and caam_jr_dma_unmap sync options */
+#define JR_MAP_SYNC (true)
+#define JR_MAP_NOSYNC (false)
+
+/*
+ * @brief DMA map memory with jobrings DMA tag.
+ *
+ * Sync if requested.
+ *
+ * @param [in] dev The handle for the CAAM_JR device
+ * @param [out] bmap DMA mapping details
+ * @param [in] buf buffer to map
+ * @param [in] buflen len to map
+ * @param [in] create_flags dma_map_create flags
+ * @param [in] load_flags dma_map_load flags
+ * @param [in] sync make a prewrite sync to DMA memory
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on failure
+ */
+int caam_jr_dma_map(device_t dev, caam_jr_dma_map_t *bmap, void *buf, size_t buflen,
+ int create_flags, int load_flags, bool sync);
+
+/*
+ * @brief Unmap caam_jr_dma_map() mapped memory.
+ *
+ * Sync if requested
+ *
+ * @param [in] dev The handle for the CAAM_JR device
+ * @param [in] bmap DMA mapping details
+ * @param [in] sync make a postread sync from DMA memory
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on failure
+ */
+int caam_jr_dma_unmap(device_t dev, caam_jr_dma_map_t *bmap, bool sync);
+
+/*
+ * @brief Sync mapped memory after write.
+ *
+ * @param [in] dev The handle for the CAAM_JR device
+ * @param [in] in DMA mapping details
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on failure
+ */
+void caam_jr_dma_sync_to_dma(device_t dev, caam_jr_dma_map_t *bmap);
+
+/*
+ * @brief Sync mapped memory before read.
+ *
+ * @param [in] dev The handle for the CAAM_JR device
+ * @param [out] in DMA mapping details
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on failure
+ */
+void caam_jr_dma_sync_from_dma(device_t dev, caam_jr_dma_map_t *bmap);
+
+#endif /* CAAM_JR_H */
diff --git a/sys/arm64/qoriq/caam/jr/caam_jr.c b/sys/arm64/qoriq/caam/jr/caam_jr.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_jr.c
@@ -0,0 +1,1257 @@
+/*
+ * Copyright 2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+#include <machine/atomic.h>
+
+#include <dev/ofw/ofw_bus.h>
+#include <dev/ofw/ofw_bus_subr.h>
+#include <dev/ofw/openfirm.h>
+
+#include "../caam.h"
+#include "../caam_debug.h"
+#include "caam_jr.h"
+#include "caam_jr_cfg.h"
+#include "caam_jr_hw.h"
+
+#define CAAM_JR_POOL_MAX_COUNT 1000 /* Pool retry count */
+
+/*
+ * Jobring taskqueue responsible for dequeueing completed jobs
+ * from the output ring.
+ * Triggered from jr_intr according to coalescing settings.
+ */
+struct jobring_tq {
+ struct taskqueue *tq;
+ struct task task;
+ device_t dev;
+};
+
+/* software context */
+struct caam_jr_softc {
+ device_t dev;
+ device_t dev_caam;
+ struct resource *mem_res;
+ struct resource *irq_res;
+ void *irq_cookie;
+ bus_dma_tag_t dma_tag;
+ bus_dma_tag_t data_tag;
+
+ struct sec_job_ring_t job_ring;
+
+ caam_jr_dma_map_t ip_ring_map;
+ uint8_t ip_ring_buf[SEC_DMA_MEM_INPUT_RING_SIZE];
+
+ caam_jr_dma_map_t op_ring_map;
+ uint8_t op_ring_buf[SEC_DMA_MEM_OUTPUT_RING_SIZE];
+
+ caam_jr_dma_map_t desc_ring[SEC_JOB_RING_SIZE];
+
+ struct jobring_tq *tq;
+
+ int pending;
+};
+
+/* Schedule jobring_worker to run */
+static void caam_jr_sched_dequeue(device_t dev)
+{
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ taskqueue_enqueue(sc->tq->tq, &sc->tq->task);
+}
+
+/* Dequeue finished jobs and unmask interrupts for related jobring */
+static void jobring_worker(void *context, int pending)
+{
+ int ret;
+ struct jobring_tq *tq = context;
+
+ CAAM_LOG_DEBUG("Dequeue in progress\n");
+
+ ret = caam_jr_dequeue(tq->dev, -1);
+ if (ret == 0) {
+ CAAM_LOG_DEBUG("Dequeue of %x desc success\n", ret);
+ } else {
+ CAAM_LOG_WARN("deq_ret %x\n", ret);
+ }
+}
+
+/*
+ * Initialize and return dequeue handling taskqueue.
+ * Free with caam_free_jobring_task().
+*/
+static struct jobring_tq * caam_create_jobring_task(device_t dev)
+{
+ struct jobring_tq *jobring_tq;
+
+ jobring_tq = malloc(sizeof(*jobring_tq), M_DEVBUF, M_WAITOK | M_ZERO);
+ jobring_tq->dev = dev;
+
+ TASK_INIT(&jobring_tq->task, 0, jobring_worker, jobring_tq);
+ jobring_tq->tq = taskqueue_create_fast(
+ "caam_jobring_tq",
+ M_NOWAIT | M_ZERO,
+ taskqueue_thread_enqueue,
+ &jobring_tq->tq);
+ taskqueue_start_threads(&jobring_tq->tq, 1, PI_SOFT, "caam_jobring_th");
+
+ return jobring_tq;
+}
+
+/*
+ * Stop and free taskqueue created by caam_create_jobring_task().
+ */
+static void
+caam_free_jobring_task(struct jobring_tq *tq)
+{
+ taskqueue_free(tq->tq);
+ free(tq, M_DEVBUF);
+}
+
+/*----------------------- JobRing SFR access functions ----------------------*/
+/* a Macro that can be used to get the offset of Job Ring register */
+#define jr_reg(reg_name) offsetof(struct jobring_regs, reg_name), #reg_name
+
+static uint32_t
+reg_read(struct caam_jr_softc *sc, uint32_t reg, const char *reg_name)
+{
+ uint32_t result;
+
+ CAAM_LOG_DEBUG("reg_read(%s[%08X]) --> ", reg_name, reg);
+ result = bus_read_4(sc->mem_res, reg);
+
+#if defined(NXP_SEC_BE)
+ result = be32toh(result);
+#elif defined(NXP_SEC_LE)
+ result = le32toh(result);
+#else
+#error Please define CAAM register endianness
+#endif
+
+ CAAM_LOG_DEBUG("%08X\n", result);
+
+ return result;
+}
+
+static void
+reg_write(struct caam_jr_softc *sc, uint32_t reg, const char *reg_name,
+ uint32_t val)
+{
+ CAAM_LOG_DEBUG("reg_write(%s[%08X], %08X)\n", reg_name, reg, val);
+
+#if defined(NXP_SEC_BE)
+ val = htobe32(val);
+#elif defined(NXP_SEC_LE)
+ val = htole32(val);
+#else
+#error Please define CAAM register endianness
+#endif
+
+ bus_write_4(sc->mem_res, reg, val);
+ bus_barrier(sc->mem_res, reg, 4,
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+}
+
+/* Do a Read-Modify-Write of a jr register, change only masked bits */
+static void
+reg_write_mask(struct caam_jr_softc *sc, uint32_t reg, const char *reg_name,
+ uint32_t val, uint32_t mask)
+{
+ uint32_t cur;
+
+ cur = reg_read(sc, reg, reg_name);
+ cur &= mask;
+ cur |= mask & val;
+ reg_write(sc, reg, reg_name, cur);
+}
+
+/*-------------------- JobRing hardware access functions --------------------*/
+static inline void
+set_jr_input_ring_start_addr(struct caam_jr_softc *sc, bus_addr_t start_addr)
+{
+ reg_read(sc, jr_reg(irba_h));
+
+#if defined(CONFIG_PHYS_64BIT)
+ reg_write(sc, jr_reg(irba_h), PHYS_ADDR_HI(start_addr));
+#else
+ reg_write(sc, jr_reg(irba_h), 0);
+#endif
+ reg_write(sc, jr_reg(irba_l), PHYS_ADDR_LO(start_addr));
+}
+
+static inline void
+set_jr_output_ring_start_addr(struct caam_jr_softc *sc, bus_addr_t start_addr)
+{
+#if defined(CONFIG_PHYS_64BIT)
+ reg_write(sc, jr_reg(orba_h), PHYS_ADDR_HI(start_addr));
+#else
+ reg_write(sc, jr_reg(orba_h), 0);
+#endif
+ reg_write(sc, jr_reg(orba_l), PHYS_ADDR_LO(start_addr));
+}
+
+/*
+ * IRJA - Input Ring Jobs Added Register shows
+ * how many new jobs were added to the Input Ring.
+ */
+static inline void
+add_jr_entries(struct caam_jr_softc *sc, int num)
+{
+ atomic_add_int(&sc->pending, num);
+
+ /* This action triggers the job execution.
+ In extreme case the whole job processing will already finish
+ before we return from this function. */
+ reg_write(sc, jr_reg(irja), num);
+}
+
+/* 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
+remove_jr_entries(struct caam_jr_softc *sc, int num)
+{
+ reg_write(sc, jr_reg(orjr), num);
+ atomic_subtract_int(&sc->pending, num);
+}
+
+#ifdef notyet
+/* 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
+get_jr_available_slots(struct caam_jr_softc *sc)
+{
+ return reg_read(sc, jr_reg(irsa));
+}
+#endif
+
+/* 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 jr_remove_one_entry in order
+ * to notify the SEC that the entry was processed
+ */
+static inline int
+get_jr_finished_jobs(struct caam_jr_softc *sc)
+{
+ return reg_read(sc, jr_reg(orsf));
+}
+
+/* Unmask interrupts for a jobring */
+static int
+enable_jr_irqs(struct caam_jr_softc *sc)
+{
+ uint32_t reg_val = 0U;
+
+ /* Get the current value of the register */
+ reg_val = reg_read(sc, jr_reg(jrcfg1));
+
+ /* Enable interrupts by disabling interrupt masking*/
+ reg_val &= ~JR_REG_JRCFG_LO_IMSK_EN;
+
+ /* Update parameters in HW */
+ reg_write(sc, jr_reg(jrcfg1), reg_val);
+
+ CAAM_LOG_DEBUG("Enable interrupts on JR\n");
+
+ return 0;
+}
+
+/* Mask interrupts for a jobring. This will NOT clear interrupt status */
+static int
+disable_jr_irqs(struct caam_jr_softc *sc)
+{
+ uint32_t reg_val = 0U;
+
+ /* Get the current value of the register */
+ reg_val = reg_read(sc, jr_reg(jrcfg1));
+
+ /* Disable interrupts by enabling interrupt masking*/
+ reg_val |= JR_REG_JRCFG_LO_IMSK_EN;
+
+ /* Update parameters in HW */
+ reg_write(sc, jr_reg(jrcfg1), reg_val);
+
+ CAAM_LOG_DEBUG("Disable interrupts on JR\n");
+
+ return 0;
+}
+
+/*
+ * Group finished jobs before issuing an interrupt.
+ * SEC should interrupt if irq_coalescing_count jobs finished since last
+ * interrupt or if irq_coalescing_timer SEC cycles passed since last job completed.
+ */
+static int
+set_jr_coalescing_param(struct caam_jr_softc *sc, uint16_t irq_coalescing_timer,
+ uint8_t irq_coalescing_count)
+{
+ uint32_t reg_val = 0U;
+
+ /* 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 */
+ reg_write(sc, jr_reg(jrcfg1), reg_val);
+
+ CAAM_LOG_DEBUG("Set coalescing params on jr\n");
+
+ return 0;
+}
+
+/* Enable set_jr_coalescing_param settings */
+static int
+enable_jr_coalescing(struct caam_jr_softc *sc)
+{
+ uint32_t reg_val = 0U;
+
+ /* Get the current value of the register */
+ reg_val = reg_read(sc, jr_reg(jrcfg1));
+
+ /* Enable coalescing */
+ reg_val |= JR_REG_JRCFG_LO_ICEN_EN;
+
+ /* Write in hw */
+ reg_write(sc, jr_reg(jrcfg1), reg_val);
+
+ CAAM_LOG_DEBUG("Enabled coalescing on jr\n");
+
+ return 0;
+}
+
+/* Disable set_jr_coalescing_param settings */
+static int
+disable_jr_coalescing(struct caam_jr_softc *sc)
+{
+ uint32_t reg_val = 0U;
+
+ /* Get the current value of the register */
+ reg_val = reg_read(sc, jr_reg(jrcfg1));
+
+ /* Disable coalescing */
+ reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN;
+
+ /* Write in hw */
+ reg_write(sc, jr_reg(jrcfg1), reg_val);
+
+ CAAM_LOG_DEBUG("Disabled coalescing on jr");
+
+ return 0;
+}
+
+/*--------------------- JobRing Error handling functions --------------------*/
+/* @brief Process Jump Halt Condition related errors
+ * @param [in] error_code The error code in the descriptor status word
+ */
+static inline void
+handle_desc_jmp_halt_cond_err(union jr_error_code error_code)
+{
+ CAAM_LOG_WARN("JMP %x\n", error_code.error_desc.jmp_halt_cond_src.jmp);
+ CAAM_LOG_WARN("Descriptor Index: %d\n",
+ error_code.error_desc.jmp_halt_cond_src.desc_idx);
+ CAAM_LOG_WARN(" 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
+handle_desc_deco_err(union jr_error_code error_code)
+{
+ CAAM_LOG_WARN("JMP %x\n", error_code.error_desc.deco_src.jmp);
+ CAAM_LOG_WARN("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:
+ CAAM_LOG_WARN(" Descriptor completed but exceeds the Threshold");
+ break;
+ default:
+ CAAM_LOG_WARN("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
+handle_desc_jmp_halt_user_err(union jr_error_code error_code)
+{
+ CAAM_LOG_WARN("Not implemented\n");
+}
+
+/* @brief Process CCB related errors
+ * @param [in] error_code The error code in the descriptor status word
+ */
+static inline void
+handle_desc_ccb_err(union jr_error_code jr_error_code)
+{
+ CAAM_LOG_WARN("Not implemented\n");
+}
+
+/* @brief Process Job Ring related errors
+ * @param [in] error_code The error code in the descriptor status word
+ */
+static inline void
+handle_desc_jr_err(union jr_error_code jr_error_code)
+{
+ CAAM_LOG_WARN("Not implemented\n");
+}
+
+/* Handle job descriptor processing errors */
+static void
+handle_desc_error(struct caam_jr_softc *sc, uint32_t error_code)
+{
+ union jr_error_code jr_err_code;
+
+ jr_err_code.error = error_code;
+
+ switch (jr_err_code.error_desc.value.ssrc) {
+ case SEC_HW_ERR_SSRC_NO_SRC:
+ CAAM_LOG_WARN("No Status Source ");
+ break;
+ case SEC_HW_ERR_SSRC_CCB_ERR:
+ CAAM_LOG_WARN("CCB Status Source");
+ handle_desc_ccb_err(jr_err_code);
+ break;
+ case SEC_HW_ERR_SSRC_JMP_HALT_U:
+ CAAM_LOG_WARN("Jump Halt User Status Source");
+ handle_desc_jmp_halt_user_err(jr_err_code);
+ break;
+ case SEC_HW_ERR_SSRC_DECO:
+ CAAM_LOG_WARN("DECO Status Source");
+ handle_desc_deco_err(jr_err_code);
+ break;
+ case SEC_HW_ERR_SSRC_JR:
+ CAAM_LOG_WARN("Job Ring Status Source");
+ handle_desc_jr_err(jr_err_code);
+ break;
+ case SEC_HW_ERR_SSRC_JMP_HALT_COND:
+ CAAM_LOG_WARN("Jump Halt Condition Codes");
+ handle_desc_jmp_halt_cond_err(jr_err_code);
+ break;
+ default:
+ CAAM_LOG_WARN("Unknown SSRC");
+ break;
+ }
+}
+
+/* Print a log message according to current JRINT register JRE field */
+static int
+read_jr_hw_error(struct caam_jr_softc *sc)
+{
+ uint32_t jrint_error_code;
+
+ if (JR_REG_JRINT_JRE_EXTRACT(reg_read(sc, jr_reg(jrint))) == 0) {
+ return 0;
+ }
+
+ jrint_error_code = JR_REG_JRINT_ERR_TYPE_EXTRACT(
+ reg_read(sc, jr_reg(jrint)));
+ switch (jrint_error_code) {
+ case JRINT_ERR_WRITE_STATUS:
+ CAAM_LOG_WARN("Error writing status to Output Ring ");
+ break;
+ case JRINT_ERR_BAD_INPUT_BASE:
+ CAAM_LOG_WARN("Bad Input Ring Base (not on a 4-byte boundary)\n");
+ break;
+ case JRINT_ERR_BAD_OUTPUT_BASE:
+ CAAM_LOG_WARN("Bad Output Ring Base (not on a 4-byte boundary)\n");
+ break;
+ case JRINT_ERR_WRITE_2_IRBA:
+ CAAM_LOG_WARN("Invalid write to Input Ring Base Address Register\n");
+ break;
+ case JRINT_ERR_WRITE_2_ORBA:
+ CAAM_LOG_WARN("Invalid write to Output Ring Base Address Register\n");
+ break;
+ case JRINT_ERR_RES_B4_HALT:
+ CAAM_LOG_WARN("Job Ring released before Job Ring is halted\n");
+ break;
+ case JRINT_ERR_REM_TOO_MANY:
+ CAAM_LOG_WARN("Removed too many jobs from job ring\n");
+ break;
+ case JRINT_ERR_ADD_TOO_MANY:
+ CAAM_LOG_WARN("Added too many jobs on job ring\n");
+ break;
+ default:
+ CAAM_LOG_WARN("Unknown SEC JR Error :%d\n", jrint_error_code);
+ break;
+ }
+ return jrint_error_code;
+}
+
+/*------------------ Low level JobRing management functions -----------------*/
+static int
+shutdown_job_ring(struct caam_jr_softc *sc)
+{
+ unsigned int timeout = SEC_TIMEOUT;
+ uint32_t tmp = 0U;
+
+ CAAM_LOG_DEBUG("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
+ */
+
+ disable_jr_irqs(sc);
+
+ /* initiate flush (required prior to reset) */
+ reg_write(sc, jr_reg(jrcr), JR_REG_JRCR_VAL_RESET);
+
+ /* dummy read */
+ tmp = reg_read(sc, jr_reg(jrcr));
+ (void)tmp;
+
+ do {
+ tmp = reg_read(sc, jr_reg(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) {
+ CAAM_LOG_ERROR("Failed to flush hw job ring %x\n %u", tmp, timeout);
+ /* unmask interrupts */
+ if (sc->job_ring.jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+ enable_jr_irqs(sc);
+ }
+ return EIO;
+ }
+ /* Initiate reset */
+ timeout = SEC_TIMEOUT;
+ reg_write(sc, jr_reg(jrcr), JR_REG_JRCR_VAL_RESET);
+
+ do {
+ tmp = reg_read(sc, jr_reg(jrcr));
+ } while (((tmp & JR_REG_JRCR_VAL_RESET) != 0U) && ((--timeout) != 0U));
+
+ if (timeout == 0U) {
+ CAAM_LOG_ERROR("Failed to reset hw job ring\n");
+ /* unmask interrupts */
+ if (sc->job_ring.jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+ enable_jr_irqs(sc);
+ }
+ return EIO;
+ }
+ /* unmask interrupts */
+ if (sc->job_ring.jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+ enable_jr_irqs(sc);
+ }
+ return 0;
+}
+
+static int
+reset_job_ring(struct caam_jr_softc *sc)
+{
+ int ret = 0;
+
+ /* First reset the job ring in hw */
+ ret = shutdown_job_ring(sc);
+ if (ret != 0) {
+ CAAM_LOG_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
+ */
+ reg_write(sc, jr_reg(irs), SEC_JOB_RING_SIZE);
+
+ /* Write the JR output queue size to the HW register */
+ reg_write(sc, jr_reg(ors), SEC_JOB_RING_SIZE);
+
+ /* Write the JR input queue start address */
+ set_jr_input_ring_start_addr(sc, sc->ip_ring_map.bus_addr);
+
+ /* Write the JR output queue start address */
+ set_jr_output_ring_start_addr(sc, sc->op_ring_map.bus_addr);
+
+ return 0;
+}
+
+/* Remove all currently finished jobs from output ring without executing callbacks */
+static void
+flush_job_ring(struct caam_jr_softc *sc, 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;
+
+ CAAM_LOG_DEBUG("JR pi[%d]i ci[%d]\n", sc->job_ring.pidx, sc->job_ring.cidx);
+ CAAM_LOG_DEBUG("error code %x\n", error_code);
+ CAAM_LOG_DEBUG("Notify_desc = %d\n", do_notify);
+
+ number_of_jobs_available = get_jr_finished_jobs(sc);
+
+ /* Discard all jobs */
+ jobs_no_to_discard = number_of_jobs_available;
+
+ CAAM_LOG_DEBUG("JR pi[%d]i ci[%d]\n", sc->job_ring.pidx, sc->job_ring.cidx);
+ CAAM_LOG_DEBUG("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
+ */
+
+ sc->job_ring.cidx = SEC_CIRCULAR_COUNTER(sc->job_ring.cidx,
+ SEC_JOB_RING_SIZE);
+
+ remove_jr_entries(sc, 1);
+ }
+
+ if (do_notify == true) {
+ if (notified_descs == NULL) {
+ return;
+ }
+ *notified_descs = discarded_descs_no;
+ }
+}
+
+/* return 0 in case of success
+ * !0 in case of error from SEC block
+ *
+ * notified is 0 in case job not yet processed by SEC
+ */
+static int
+poll_job_ring(struct caam_jr_softc *sc, int32_t limit, int32_t *notified)
+{
+ int32_t jobs_no_to_notify = 0;
+ int32_t number_of_jobs_available = 0;
+ int32_t notified_descs_no = 0;
+ uint32_t sec_error_code = 0U;
+ uintptr_t *fnptr, *arg_addr;
+ user_callback usercall = NULL;
+ uint8_t *current_desc;
+ void *arg;
+ uintptr_t current_desc_addr;
+ bus_addr_t current_desc_loc;
+ int i;
+
+ /* check here if any JR error that cannot be written
+ * in the output status word has occurred
+ */
+ sec_error_code = read_jr_hw_error(sc);
+ if (unlikely(sec_error_code) != 0) {
+ CAAM_LOG_WARN("Error here itself %x\n", sec_error_code);
+ return EIO;
+ }
+ /* 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 = get_jr_finished_jobs(sc);
+ jobs_no_to_notify = (limit < 0 || limit > number_of_jobs_available) ?
+ number_of_jobs_available :
+ limit;
+ CAAM_LOG_DEBUG("JR - pi %d, ci %d,\n", sc->job_ring.pidx, sc->job_ring.cidx);
+ CAAM_LOG_DEBUG("Jobs submitted %d \n", number_of_jobs_available);
+ CAAM_LOG_DEBUG("Jobs to notify %d \n", jobs_no_to_notify);
+
+ while (jobs_no_to_notify > notified_descs_no) {
+ /* Make sure that the Output Ring contain data written by the
+ * Job Ring hardware */
+ caam_jr_dma_sync_from_dma(sc->dev, &sc->op_ring_map);
+ CAAM_LOG_DEBUG("output_ring[%i] = %016lX, %08X\n", 0,
+ sc->job_ring.output_ring[sc->job_ring.cidx].desc,
+ sc->job_ring.output_ring[sc->job_ring.cidx].status);
+
+ /* Get job status here */
+ sec_error_code = sec_mem_in32(
+ &(sc->job_ring.output_ring[sc->job_ring.cidx].status));
+
+ /* Get completed descriptor */
+ current_desc_loc = (uintptr_t)&sc->job_ring
+ .output_ring[sc->job_ring.cidx]
+ .desc;
+ current_desc_addr = sec_read_addr(current_desc_loc);
+
+ CAAM_LOG_DEBUG("output_ring[%d] [%016lX]=%016lX\n ", sc->job_ring.cidx,
+ (uintptr_t)current_desc_loc, current_desc_addr);
+
+ /* search the descriptor with this bus address */
+ current_desc = NULL;
+ i = sc->job_ring.cidx;
+ do {
+ if(sc->desc_ring[i].bus_addr == current_desc_addr) {
+ current_desc = sc->desc_ring[i].buf;
+
+ CAAM_LOG_DEBUG(
+ "Found descriptor at: phy:%016lX -> vir:%016lX\n ",
+ (uintptr_t)current_desc_addr,
+ (uintptr_t)current_desc);
+
+ /* The DMA is no longer needed, sync and unmap it */
+ caam_jr_dma_unmap(sc->dev, &sc->desc_ring[i], JR_MAP_SYNC);
+ sc->desc_ring[i].buf = NULL;
+ sc->desc_ring[i].bus_addr = 0;
+
+ break;
+
+ }
+ i = SEC_CIRCULAR_COUNTER(i, SEC_JOB_RING_SIZE);
+ } while (i != sc->job_ring.pidx);
+
+ /* now increment the consumer index for the current job ring,
+ * AFTER saving job in temporary location!
+ */
+ sc->job_ring.cidx = SEC_CIRCULAR_COUNTER(sc->job_ring.cidx,
+ SEC_JOB_RING_SIZE);
+
+ /* Signal that the job has been processed & the slot is free */
+ remove_jr_entries(sc, 1);
+
+ /* In case we could not find the descriptor we will not be able to execute the callback */
+ if ((current_desc_addr == 0) || (current_desc == NULL)) {
+ CAAM_LOG_ERROR("No descriptor returned from SEC\n");
+ return EIO;
+ }
+
+ /* Execute the user provided callback */
+ arg_addr = (uintptr_t *)(current_desc +
+ (MAX_DESC_SIZE_WORDS * sizeof(uint32_t)));
+
+ fnptr = (uintptr_t *)(current_desc +
+ (MAX_DESC_SIZE_WORDS * sizeof(uint32_t) + sizeof(void *)));
+
+ arg = (void *)*(arg_addr);
+ if (*fnptr != 0) {
+ CAAM_LOG_DEBUG("Callback Function called\n");
+ usercall = (user_callback) * (fnptr);
+ (*usercall)((uint32_t *)current_desc, sec_error_code,
+ arg, sc->dev);
+ }
+
+ /* In case error was detected, print it and return */
+ if (sec_error_code != 0) {
+ CAAM_LOG_WARN("desc at cidx %d, error: %x\n ", sc->job_ring.cidx, sec_error_code);
+ handle_desc_error(sc, sec_error_code);
+ return EIO;
+ }
+
+ notified_descs_no++;
+ }
+
+ *notified = notified_descs_no;
+ return 0;
+}
+
+/*-------------------- JobRing Public interface functions -------------------*/
+int
+caam_jr_init(device_t dev, uint8_t jr_mode, uint16_t irq_coalescing_timer,
+ uint8_t irq_coalescing_count)
+{
+ int ret = 0;
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ sc->job_ring.jr_mode = jr_mode;
+ sc->job_ring.irq_fd = 0;
+
+ sc->job_ring.input_ring = (bus_addr_t *)sc->ip_ring_buf;
+ memset(sc->job_ring.input_ring, 0, SEC_DMA_MEM_INPUT_RING_SIZE);
+
+ sc->job_ring.output_ring = (struct sec_outring_entry *)sc->op_ring_buf;
+ memset(sc->job_ring.output_ring, 0, SEC_DMA_MEM_OUTPUT_RING_SIZE);
+
+ caam_jr_dma_sync_to_dma(sc->dev, &sc->ip_ring_map);
+ caam_jr_dma_sync_to_dma(sc->dev, &sc->op_ring_map);
+
+ /* Reset job ring in SEC hw and configure job ring registers */
+ ret = reset_job_ring(sc);
+ if (ret != 0) {
+ CAAM_LOG_ERROR("Failed to reset hardware job ring\n");
+ return ret;
+ }
+
+ if (jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
+ /* Enable IRQ if driver work sin interrupt mode */
+ CAAM_LOG_ERROR("Enabling DONE IRQ generation on job ring\n");
+ ret = enable_jr_irqs(sc);
+ if (ret != 0) {
+ CAAM_LOG_ERROR("Failed to enable irqs for job ring\n");
+ return ret;
+ }
+ }
+ if ((irq_coalescing_timer != 0) || (irq_coalescing_count != 0)) {
+ set_jr_coalescing_param(sc, irq_coalescing_timer,
+ irq_coalescing_count);
+
+ enable_jr_coalescing(sc);
+ sc->job_ring.coalescing_en = 1;
+ }
+
+ sc->job_ring.jr_state = SEC_JOB_RING_STATE_STARTED;
+
+ return ret;
+}
+
+int
+caam_jr_enqueue(device_t dev, struct job_descriptor *jobdescr)
+{
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ /* Check job ring state */
+ if (sc->job_ring.jr_state != SEC_JOB_RING_STATE_STARTED) {
+ CAAM_LOG_WARN("Job ring is currently resetting\n");
+ return ENXIO;
+ }
+
+ if (SEC_JOB_RING_IS_FULL(sc->job_ring.pidx, sc->job_ring.cidx,
+ SEC_JOB_RING_SIZE, SEC_JOB_RING_SIZE)) {
+ CAAM_LOG_WARN("Job ring is full, pending: %d\n",
+ atomic_load_int(&sc->pending));
+ return ENOMEM;
+ }
+
+ /* Create DMA mapping and load the descriptor to bus memmory for this
+ * job */
+ caam_jr_dma_map(dev, &sc->desc_ring[sc->job_ring.pidx], jobdescr,
+ sizeof(struct job_descriptor), 0, BUS_DMA_NOWAIT, JR_MAP_SYNC);
+
+ /* Set ptr in input ring to current descriptor */
+ sec_write_addr(&sc->job_ring.input_ring[sc->job_ring.pidx],
+ sc->desc_ring[sc->job_ring.pidx].bus_addr);
+
+ caam_jr_dma_sync_to_dma(dev, &sc->ip_ring_map);
+ CAAM_LOG_DEBUG("input_ring[%i] = %016lX\n", sc->job_ring.pidx,
+ sc->job_ring.input_ring[sc->job_ring.pidx]);
+
+ /* increment the producer index for the current job ring */
+ sc->job_ring.pidx = SEC_CIRCULAR_COUNTER(sc->job_ring.pidx,
+ SEC_JOB_RING_SIZE);
+
+ /* Notify HW that a new job is enqueued */
+ add_jr_entries(sc, 1);
+
+ return 0;
+}
+
+int
+caam_jr_dequeue(device_t dev, int32_t limit)
+{
+ int ret = 0, irq_ret = 0;
+ int notified_descs_no = 0;
+ struct caam_jr_softc *sc = device_get_softc(dev);
+ uint64_t pool_count;
+
+ /* Validate input arguments */
+ if (((limit == 0) || (limit > SEC_JOB_RING_SIZE))) {
+ CAAM_LOG_WARN("Invalid limit parameter configuration\n");
+ return EINVAL;
+ }
+
+ CAAM_LOG_DEBUG("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.
+ */
+ pool_count = 0;
+
+ while (notified_descs_no == 0) {
+ /* Run hw poll job ring */
+ ret = poll_job_ring(sc, limit, &notified_descs_no);
+ if (ret != 0) {
+ CAAM_LOG_WARN("Error polling SEC engine job ring\n");
+ break;
+ }
+
+ CAAM_LOG_DEBUG("Jobs notified[%d]. ", notified_descs_no);
+
+ pool_count++;
+ if (pool_count >= CAAM_JR_POOL_MAX_COUNT) {
+ CAAM_LOG_NOTICE("Timeout during job dequeue\n");
+ break;
+ }
+ }
+
+ if (sc->job_ring.jr_mode == SEC_NOTIFICATION_TYPE_IRQ) {
+ /* Always enable IRQ generation when in pure IRQ mode */
+ irq_ret = enable_jr_irqs(sc);
+ if (irq_ret != 0) {
+ CAAM_LOG_WARN("Failed to enable irqs for job ring");
+ ret = irq_ret;
+ }
+ }
+
+ return ret;
+}
+
+int
+caam_jr_shutdown(device_t dev)
+{
+ int ret = 0;
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ ret = shutdown_job_ring(sc);
+ if (ret != 0) {
+ CAAM_LOG_ERROR("Failed to shutdown hardware job ring\n");
+ return ret;
+ }
+
+ if (sc->job_ring.coalescing_en != 0) {
+ disable_jr_coalescing(sc);
+ }
+
+ if (sc->job_ring.jr_mode != SEC_NOTIFICATION_TYPE_POLL) {
+ ret = disable_jr_irqs(sc);
+ if (ret != 0) {
+ CAAM_LOG_ERROR("Failed to disable irqs for job ring");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+bool
+caam_jr_busy(device_t dev)
+{
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ return (atomic_load_int(&sc->pending) != 0);
+}
+
+bus_dma_tag_t
+caam_jr_get_tag(device_t dev)
+{
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ return (sc->dma_tag);
+}
+
+bus_dma_tag_t
+caam_jr_get_data_tag(device_t dev)
+{
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ return (sc->data_tag);
+}
+
+static void
+dma_callback(void *arg, bus_dma_segment_t *segs, int nseg, int error)
+{
+ if (error)
+ return;
+ *(bus_addr_t *)arg = segs[0].ds_addr;
+}
+
+int
+caam_jr_dma_map(device_t dev, caam_jr_dma_map_t *bmap, void *buf, size_t buflen,
+ int create_flags, int load_flags, bool sync)
+{
+ int error;
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ /* Remember the CPU visible memory */
+ bmap->buf = buf;
+ bmap->buflen = buflen;
+
+ /* Map and load the buffer */
+ error = bus_dmamap_create(sc->dma_tag, create_flags, &bmap->mmap);
+ if (error != 0) {
+ CAAM_LOG_ERROR("Cannot create DMA map, %i\n", error);
+ return (error);
+ }
+
+ bmap->bus_addr = ULONG_MAX;
+ error = bus_dmamap_load(sc->dma_tag, /* DMA tag */
+ bmap->mmap, /* DMA map */
+ bmap->buf, /* buffer */
+ bmap->buflen, /* buffersize */
+ dma_callback, /* callback */
+ &bmap->bus_addr, /* callbackarg */
+ load_flags); /* flags */
+ if (error || bmap->bus_addr == ULONG_MAX) {
+ CAAM_LOG_ERROR("Cannot map memory!\n");
+ bus_dmamap_destroy(sc->dma_tag, bmap->mmap);
+ bmap->mmap = NULL;
+ return (ENOMEM);
+ }
+
+ if (sync) {
+ /* Make sure that the data is synchronized to DMA memory */
+ caam_jr_dma_sync_to_dma(dev, bmap);
+ }
+
+ return error;
+}
+
+int
+caam_jr_dma_unmap(device_t dev, caam_jr_dma_map_t *bmap, bool sync)
+{
+ int error = 0;
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ if (bmap->mmap != NULL) {
+ if (sync) {
+ /* Make sure that the data is synchronized to CPU memory */
+ caam_jr_dma_sync_from_dma(dev, bmap);
+ }
+
+ /* Now it is safe to remove the mapping */
+ bus_dmamap_unload(sc->dma_tag, bmap->mmap);
+ error = bus_dmamap_destroy(sc->dma_tag, bmap->mmap);
+ bmap->mmap = NULL;
+ if (error)
+ CAAM_LOG_ERROR("%s: bus_dmamap_destroy failed: %d\n", __func__,
+ error);
+ }
+
+ return error;
+}
+
+void
+caam_jr_dma_sync_to_dma(device_t dev, caam_jr_dma_map_t *bmap)
+{
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ bus_dmamap_sync(sc->dma_tag, bmap->mmap, BUS_DMASYNC_PREWRITE);
+}
+
+void
+caam_jr_dma_sync_from_dma(device_t dev, caam_jr_dma_map_t *bmap)
+{
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ bus_dmamap_sync(sc->dma_tag, bmap->mmap, BUS_DMASYNC_POSTREAD);
+}
+
+/*----------------------- Device management functions -----------------------*/
+static int
+init_caam_jr_dma(struct caam_jr_softc *sc)
+{
+ int error;
+
+ /* Map and load the Input Ring buffer */
+ error = caam_jr_dma_map(sc->dev, &sc->ip_ring_map, sc->ip_ring_buf,
+ SEC_DMA_MEM_INPUT_RING_SIZE, 0, BUS_DMA_NOWAIT, JR_MAP_SYNC);
+ if (error != 0) {
+ CAAM_LOG_ERROR("cannot create Input Ring map, %i\n", error);
+ return (error);
+ }
+
+ /* Map and load the Output Ring buffer */
+ error = caam_jr_dma_map(sc->dev, &sc->op_ring_map, sc->op_ring_buf,
+ SEC_DMA_MEM_OUTPUT_RING_SIZE, 0, BUS_DMA_NOWAIT, JR_MAP_SYNC);
+ if (error != 0) {
+ CAAM_LOG_ERROR("cannot create Output Ring map\n");
+ return (error);
+ }
+
+ return (0);
+}
+
+static void
+free_caam_jr_dma(struct caam_jr_softc *sc)
+{
+ caam_jr_dma_unmap(sc->dev, &sc->ip_ring_map, JR_MAP_SYNC);
+ caam_jr_dma_unmap(sc->dev, &sc->op_ring_map, JR_MAP_SYNC);
+}
+
+static int
+caam_jr_probe(device_t dev)
+{
+ if (!ofw_bus_status_okay(dev))
+ return (ENXIO);
+
+ if (!ofw_bus_is_compatible(dev, "fsl,sec-v4.0-job-ring"))
+ return (ENXIO);
+
+ device_set_desc(dev, "CAAM Job Ring backend driver");
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+/*
+ * Jobring descriptor completion interrupt handler.
+ * Interrupt should occur after each completion or according to coalescing settings.
+ */
+static void
+jr_intr(void *arg)
+{
+ struct caam_jr_softc *sc = (struct caam_jr_softc *)arg;
+
+ /* We might have switched to polled mode midway */
+ if (sc->job_ring.jr_mode != SEC_NOTIFICATION_TYPE_IRQ)
+ return;
+
+ disable_jr_irqs(sc);
+
+ /* Clear current interrupt */
+ reg_write_mask(sc, jr_reg(jrint), JRINT_JRI_CLEAR, JRINT_JRI_MASK);
+
+ /* dequeue will re-enable interrupts after processing user callbacks */
+ caam_jr_sched_dequeue(sc->dev);
+}
+
+static int
+caam_jr_attach(device_t dev)
+{
+ CAAM_LOG_DEBUG("caam_jr_attach\n");
+
+ int rid = 0;
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ sc->dev = dev;
+ sc->dev_caam = device_get_parent(dev);
+ sc->pending = 0;
+
+ rid = 0;
+ sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (sc->mem_res == NULL) {
+ goto error;
+ }
+
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), 4, 0,
+ BUS_SPACE_MAXADDR_40BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, 1, BUS_SPACE_MAXSIZE_32BIT,
+ BUS_DMA_COHERENT, NULL, NULL, &sc->dma_tag)) {
+ CAAM_LOG_ERROR("Cannot create JR DMA tag\n");
+ goto free_res_mem;
+ }
+
+ if (bus_dma_tag_create(bus_get_dma_tag(dev), 4, 0,
+ BUS_SPACE_MAXADDR_40BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ BUS_SPACE_MAXSIZE_32BIT, MAX_SGT_ENTRIES, BUS_SPACE_MAXSIZE_32BIT,
+ BUS_DMA_COHERENT, NULL, NULL, &sc->data_tag)) {
+ CAAM_LOG_ERROR("Cannot create JR DMA tag\n");
+ goto free_dma_tag;
+ }
+
+ if (init_caam_jr_dma(sc) != 0) {
+ CAAM_LOG_ERROR("Failed to setup jr dma\n");
+ goto free_data_tag;
+ }
+
+ sc->tq = caam_create_jobring_task(dev);
+ if (!sc->tq) {
+ CAAM_LOG_ERROR("Failed to setup jr interrupt handling\n");
+ goto free_jr_dma;
+ }
+
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_ACTIVE | RF_SHAREABLE);
+ if (!sc->irq_res) {
+ CAAM_LOG_ERROR("Failed to alloc jr IRQ\n");
+ goto free_jobring;
+ }
+
+ if (bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC | INTR_MPSAFE,
+ NULL, jr_intr, sc, &sc->irq_cookie)) {
+ CAAM_LOG_ERROR("Failed to setup jr interrupts\n");
+ goto free_res_irq;
+ }
+
+ return (0);
+
+free_res_irq:
+ bus_free_resource(dev, SYS_RES_IRQ, sc->irq_res);
+
+free_jobring:
+ caam_free_jobring_task(sc->tq);
+
+free_jr_dma:
+ free_caam_jr_dma(sc);
+
+free_data_tag:
+ bus_dma_tag_destroy(sc->data_tag);
+
+free_dma_tag:
+ bus_dma_tag_destroy(sc->dma_tag);
+
+free_res_mem:
+ bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
+
+error:
+ return (ENXIO);
+}
+
+static int
+caam_jr_detach(device_t dev)
+{
+ CAAM_LOG_DEBUG("caam_jr_detach\n");
+
+ struct caam_jr_softc *sc = device_get_softc(dev);
+
+ /* If any descriptors in flight , poll and wait
+ * until all descriptors are received and silently discarded.
+ */
+ flush_job_ring(sc, false, 0, NULL);
+
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_cookie);
+
+ bus_free_resource(dev, SYS_RES_IRQ, sc->irq_res);
+
+ caam_free_jobring_task(sc->tq);
+
+ free_caam_jr_dma(sc);
+
+ bus_dma_tag_destroy(sc->data_tag);
+
+ bus_dma_tag_destroy(sc->dma_tag);
+
+ bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
+
+ return (0);
+}
+
+static device_method_t caam_jr_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, caam_jr_probe),
+ DEVMETHOD(device_attach, caam_jr_attach),
+ DEVMETHOD(device_detach, caam_jr_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t caam_jr_driver = {
+ "caam_jr",
+ caam_jr_methods,
+ sizeof(struct caam_jr_softc),
+};
+
+DRIVER_MODULE(caam_jr, simplebus, caam_jr_driver, 0, 0);
+MODULE_VERSION(caam_jr, 1);
diff --git a/sys/arm64/qoriq/caam/jr/caam_jr_cfg.h b/sys/arm64/qoriq/caam/jr/caam_jr_cfg.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_jr_cfg.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2017-2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_JR_CFG_H
+#define CAAM_JR_CFG_H
+
+#include <sys/types.h>
+#include <sys/bus.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
+
+/*
+ * 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(bus_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))
+
+/*
+ * 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.
+ */
+#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.
+ *
+ * Currently set to 0 to minimize delay.
+ */
+#define SEC_INTERRUPT_COALESCING_DESCRIPTOR_COUNT_THRESH 0
+
+/*
+ * 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.
+ *
+ * Currently set to 0 to minimize delay.
+ */
+#define SEC_INTERRUPT_COALESCING_TIMER_THRESH 0
+
+#endif /* CAAM_JR_CFG_H */
diff --git a/sys/arm64/qoriq/caam/jr/caam_jr_hw.h b/sys/arm64/qoriq/caam/jr/caam_jr_hw.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_jr_hw.h
@@ -0,0 +1,372 @@
+/*
+ * Copyright 2017-2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2023 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_JR_HW_H
+#define CAAM_JR_HW_H
+
+#include <sys/types.h>
+#include <sys/bus.h>
+
+#include "../caam.h"
+#include "caam_jr.h"
+#include "caam_jr_cfg.h"
+
+/* DEFINES AND MACROS */
+
+/* Used to retry resetting a job ring in SEC hardware. */
+#define SEC_TIMEOUT 100000
+
+#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
+
+#define SEC_REG_SSTA_OFFSET 0x0FD4
+#define SSTA_MOO_SHIFT 8
+#define SSTA_MOO_MASK (0x3 << SSTA_MOO_SHIFT)
+#define SSTA_MOO_NON_SECURE 0x0
+#define SSTA_MOO_SECURE 0x1
+#define SSTA_MOO_TRUSTED 0x2
+#define SSTA_MOO_FAIL 0x3
+
+/* 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 RNG_STATE1_HANDLE_INSTANTIATED 0x00000002
+#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 ((0xffffu) << RTSDCTL_ENT_DLY_SHIFT)
+#define RTFRQMAX_DISABLE (1 << 20)
+
+/* Job ring interrupt handling */
+#define JR_REG_JRINIT_JRI_SHIFT 0
+#define JRINT_JRI_MASK (1 << JR_REG_JRINIT_JRI_SHIFT)
+#define JRINT_JRI_CLEAR (1 << JR_REG_JRINIT_JRI_SHIFT)
+
+/* 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;
+
+/* 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_mem_in32(a) (be32toh(*(uint32_t *)(uintptr_t)(a)))
+#define sec_mem_out32(a, v) \
+ ({ *(uint32_t *)(uintptr_t)(a) = (uint32_t)htobe32(v); })
+#define sec_mem_in64(addr) \
+ (((uint64_t)sec_mem_in32((uintptr_t)(addr)) << 32) | \
+ (sec_mem_in32(((uintptr_t)(addr)) + 4)))
+#define sec_mem_out64(addr, val) \
+ ({ \
+ sec_mem_out32(((uintptr_t)(addr)), (uint32_t)((val) >> 32)); \
+ sec_mem_out32(((uintptr_t)(addr)) + 4, (uint32_t)(val)); \
+ })
+
+#elif defined(NXP_SEC_LE)
+
+#define sec_mem_in32(a) (*(uint32_t *)(uintptr_t)(a))
+#define sec_mem_out32(a, v) ({ *(uint32_t *)(uintptr_t)(a) = (uint32_t)(v); })
+#define sec_mem_in64(addr) \
+ (((uint64_t)sec_in32((uintptr_t)(addr) + 4) << 32) | \
+ (sec_in32((uintptr_t)(addr))))
+#define sec_mem_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 SEC register endianness
+#endif
+
+#if defined(CONFIG_PHYS_64BIT)
+#define sec_read_addr(a) sec_mem_in64((a))
+#define sec_write_addr(a, v) sec_mem_out64((a), (v))
+
+#else
+#define sec_read_addr(a) sec_mem_in32((a))
+#define sec_write_addr(a, v) sec_mem_out32((a), (v))
+#endif
+
+/* 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.
+ */
+ bus_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;
+ /* 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 {
+ bus_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 jr_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;
+
+#endif /* CAAM_JR_HW_H */
diff --git a/sys/arm64/qoriq/caam/jr/caam_jr_pool.h b/sys/arm64/qoriq/caam/jr/caam_jr_pool.h
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_jr_pool.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2024 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef CAAM_JR_POOL_H
+#define CAAM_JR_POOL_H
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/vmem.h>
+
+/*
+ * @brief Jobring allocator control structure
+ */
+struct jr_pool
+{
+ size_t jr_dev_cnt;
+ vmem_t *vm;
+
+ /* Allow releases but not acquires */
+ bool shutting_down;
+};
+
+/*
+ * @brief Take ownership of a jobring and get its device pointer.
+ *
+ * Release acquired jobring with jr_pool_release() on the same pool.
+ * Will block until a jobring can be acquired unless there is an internal
+ * failure or jr_pool is in a shutdown state.
+ *
+ * @param [in] p jr_pool to acquire from
+ *
+ * @retval :: device_t is returned if there is a jobring available
+ * @retval :: NULL is returned if shutting down or on internal error
+ */
+device_t
+jr_pool_acquire(struct jr_pool *p);
+
+/*
+ * @brief Release a jobring and return it to jr_pool.
+ *
+ * @param [in] p jr_pool to release to
+ */
+void
+jr_pool_release(struct jr_pool *p, device_t jr);
+
+/*
+ * @brief Add a new jobring to jr_pool.
+ *
+ * @param [in] p jr_pool to add to
+ * @param [in] device jobring device pointer
+ *
+ * @retval :: 0 is returned on success
+ * @retval :: errno is returned on internal error
+ */
+int
+jr_pool_add(struct jr_pool *p, device_t device);
+
+/*
+ * @brief Return current jr_pool size.
+ *
+ * @param [in] p jr_pool
+ *
+ * @retval :: size_t total jobrings added to this pool.
+ */
+size_t
+jr_pool_dev_cnt(struct jr_pool *p);
+
+/*
+ * @brief Initialize jr_pool instance.
+ *
+ * @param [in] p jr_pool to initialize.
+ */
+void
+jr_pool_init(struct jr_pool *p);
+
+/*
+ * @brief Enter shutdown state on a pool.
+ *
+ * When pool is in shutdown state any jr_pool_acquire() requests will be
+ * rejected and return NULL, releases are still allowed.
+ *
+ * @param [in] p jr_pool to shut down
+ */
+void
+jr_pool_shutdown(struct jr_pool *p);
+
+/*
+ * @brief Take ownership of a jobring and get its device pointer.
+ *
+ * Allowed while in shutdown state.
+ * Release acquired jobring with jr_pool_release() on the same pool.
+ * Will block until a jobring can be acquired unless there is an internal
+ * failure.
+ *
+ * @param [in] p jr_pool to acquire from
+ *
+ * @retval :: device_t is returned if there is a jobring available
+ * @retval :: NULL is returned if shutting down or on internal error
+ */
+device_t
+jr_pool_shutdown_acquire(struct jr_pool *p);
+
+/*
+ * @brief Deinitialize jr_pool instance.
+ *
+ * Each pool member needs to be released before deinit can be called.
+ *
+ * A recommended approach is to mark jr_pool_shutdown() and
+ * wait until all members are released by acquirers.
+ * jr_pool_shutdown_acquire() can be then used to perform additional operations
+ * on pool members during shutdown.
+ * After all members return to the pool deinit can be safely called.
+ *
+ * @param [in] p jr_pool to deinit.
+ */
+void
+jr_pool_deinit(struct jr_pool *p);
+
+#endif /* CAAM_JR_POOL_H */
diff --git a/sys/arm64/qoriq/caam/jr/caam_jr_pool.c b/sys/arm64/qoriq/caam/jr/caam_jr_pool.c
new file mode 100644
--- /dev/null
+++ b/sys/arm64/qoriq/caam/jr/caam_jr_pool.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2021 NXP
+ * Copyright 2023 Alstom Group
+ * Copyright 2024 Sii Poland
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/malloc.h>
+#include <sys/types.h>
+#include <sys/vmem.h>
+
+#include "../caam_debug.h"
+#include "caam_jr_pool.h"
+
+device_t
+jr_pool_acquire(struct jr_pool *p)
+{
+ int ret;
+ device_t jr = NULL;
+
+ if (p->shutting_down)
+ return (NULL);
+
+ ret = vmem_alloc(p->vm, 1, M_WAITOK | M_FIRSTFIT, (vmem_addr_t *)&jr);
+ if (!jr || ret) {
+ CAAM_LOG_ERROR("vmem_alloc failed ret=%d\n", ret);
+ return (NULL);
+ }
+
+ return (jr);
+}
+
+void
+jr_pool_release(struct jr_pool *p, device_t jr)
+{
+ vmem_free(p->vm, (vmem_addr_t)jr, 1);
+}
+
+int
+jr_pool_add(struct jr_pool *p, device_t device)
+{
+ p->jr_dev_cnt++;
+
+ return vmem_add(p->vm, (vmem_addr_t)device, 1, M_WAITOK);
+}
+
+size_t
+jr_pool_dev_cnt(struct jr_pool *p)
+{
+ return p->jr_dev_cnt;
+}
+
+void
+jr_pool_init(struct jr_pool *p)
+{
+ p->jr_dev_cnt = 0;
+ p->shutting_down = false;
+ p->vm = vmem_create("jr_pool", 0, 0, 1, 0, M_ZERO | M_WAITOK);
+ if (!p->vm) {
+ CAAM_LOG_ERROR("Failed to create vm arena\n");
+ return;
+ }
+}
+
+void
+jr_pool_shutdown(struct jr_pool *p)
+{
+ p->shutting_down = true;
+}
+
+device_t
+jr_pool_shutdown_acquire(struct jr_pool *p)
+{
+ int ret;
+ device_t jr = NULL;
+
+ ret = vmem_alloc(p->vm, 1, M_WAITOK | M_FIRSTFIT, (vmem_addr_t *)&jr);
+ if (!jr || ret) {
+ CAAM_LOG_ERROR("vmem_alloc failed ret=%d\n", ret);
+ return (NULL);
+ }
+
+ return (jr);
+}
+
+void
+jr_pool_deinit(struct jr_pool *p)
+{
+ vmem_destroy(p->vm);
+}
diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64
--- a/sys/conf/files.arm64
+++ b/sys/conf/files.arm64
@@ -686,6 +686,10 @@
arm64/qoriq/clk/lx2160a_clkgen.c optional clk soc_nxp_ls fdt
arm64/qoriq/clk/qoriq_clk_pll.c optional clk soc_nxp_ls
arm64/qoriq/clk/qoriq_clkgen.c optional clk soc_nxp_ls fdt
+arm64/qoriq/caam/caam.c optional caam soc_nxp_ls
+arm64/qoriq/caam/jr/caam_jr.c optional caam soc_nxp_ls
+arm64/qoriq/caam/jr/caam_jr_pool.c optional caam soc_nxp_ls
+arm64/qoriq/caam/jr/caam_jobdesc.c optional caam soc_nxp_ls
dev/ahci/ahci_fsl_fdt.c optional soc_nxp_ls ahci fdt
dev/flash/flexspi/flex_spi.c optional clk flex_spi soc_nxp_ls fdt

File Metadata

Mime Type
text/plain
Expires
Fri, Nov 28, 8:49 PM (10 h, 45 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
26300591
Default Alt Text
D45589.id139838.diff (134 KB)

Event Timeline