Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F137979111
D45589.id139838.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
134 KB
Referenced Files
None
Subscribers
None
D45589.id139838.diff
View Options
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, ¬ified_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
Details
Attached
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)
Attached To
Mode
D45589: caam: Introduce new driver for NXP CAAM controller
Attached
Detach File
Event Timeline
Log In to Comment