[][openwrt][mt7988][crypto][EIP197 DDK Porting]

[Description]
Add eip197 DDK(Driver Development Kit) and firmware
to eip197 package(crypto-eip)

eip197 DDK v5.6.1
eip197b-iew firmware v3.5

[Release-log]
N/A

Change-Id: I662327ecfbdac69742bf0b50362d7c28fc06372b
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7895272
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip201.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip201.c
new file mode 100644
index 0000000..753a1cb
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip201.c
@@ -0,0 +1,567 @@
+/* eip201_sl.c
+ *
+ * Driver Library for the Security-IP-201 Advanced Interrupt Controller.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2007-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+// Top-level Interrupt controller configuration
+#include "c_eip201.h"           // configuration
+
+// Driver Framework Basic Defs API
+#include "basic_defs.h"         // uint32_t, inline, etc.
+
+// Interrupt controller API
+#include "eip201.h"             // the API we will implement
+
+// Driver Framework Device API
+#include "device_rw.h"          // Device_Read32/Write32
+
+// create a constant where all unused interrupts are '1'
+#if (EIP201_STRICT_ARGS_MAX_NUM_OF_INTERRUPTS < 32)
+#define EIP201_NOTUSEDIRQ_MASK (uint32_t) \
+                    (~((1 << EIP201_STRICT_ARGS_MAX_NUM_OF_INTERRUPTS)-1))
+#else
+#define EIP201_NOTUSEDIRQ_MASK 0
+#endif
+
+#ifdef EIP201_STRICT_ARGS
+#define EIP201_CHECK_IF_IRQ_SUPPORTED(_irqs) \
+        if (_irqs & EIP201_NOTUSEDIRQ_MASK) \
+            return EIP201_STATUS_UNSUPPORTED_IRQ;
+#else
+#define EIP201_CHECK_IF_IRQ_SUPPORTED(_irqs)
+#endif /* EIP201_STRICT_ARGS */
+
+
+/*----------------------------------------------------------------------------
+ *  EIP201 registers
+ */
+enum
+{
+    EIP201_REGISTER_OFFSET_POL_CTRL     = EIP201_LO_REG_BASE+0,
+    EIP201_REGISTER_OFFSET_TYPE_CTRL    = EIP201_LO_REG_BASE+4,
+    EIP201_REGISTER_OFFSET_ENABLE_CTRL  = EIP201_LO_REG_BASE+8,
+    EIP201_REGISTER_OFFSET_RAW_STAT     = EIP201_HI_REG_BASE+12,
+    EIP201_REGISTER_OFFSET_ENABLE_SET   = EIP201_LO_REG_BASE+12,
+    EIP201_REGISTER_OFFSET_ENABLED_STAT = EIP201_HI_REG_BASE+16,
+    EIP201_REGISTER_OFFSET_ACK          = EIP201_LO_REG_BASE+16,
+    EIP201_REGISTER_OFFSET_ENABLE_CLR   = EIP201_LO_REG_BASE+20,
+    EIP201_REGISTER_OFFSET_OPTIONS      = EIP201_HI_REG_BASE+24,
+    EIP201_REGISTER_OFFSET_VERSION      = EIP201_HI_REG_BASE+28
+};
+
+// this implementation supports only the EIP-201 HW1.1 and HW1.2
+// 0xC9  = 201
+// 0x39  = binary inverse of 0xC9
+#define EIP201_SIGNATURE      0x36C9
+#define EIP201_SIGNATURE_MASK 0xffff
+
+/*----------------------------------------------------------------------------
+ * EIP201_Read32
+ *
+ * This routine reads from a Register location in the EIP201, applying
+ * endianness swapping when required (depending on configuration).
+ */
+static inline int
+EIP201_Read32(
+        Device_Handle_t Device,
+        const unsigned int Offset,
+        uint32_t * const Value_p)
+{
+    return Device_Read32Check(Device, Offset, Value_p);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Write32
+ *
+ * This routine writes to a Register location in the EIP201, applying
+ * endianness swapping when required (depending on configuration).
+ */
+static inline int
+EIP201_Write32(
+        Device_Handle_t Device,
+        const unsigned int Offset,
+        const uint32_t Value)
+{
+    return Device_Write32(Device, Offset, Value);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Config_Change
+ */
+#ifndef EIP201_REMOVE_CONFIG_CHANGE
+EIP201_Status_t
+EIP201_Config_Change(
+        Device_Handle_t Device,
+        const EIP201_SourceBitmap_t Sources,
+        const EIP201_Config_t Config)
+{
+    uint32_t Value;
+    uint32_t NewPol = 0;
+    uint32_t NewType = 0;
+    int rc;
+    EIP201_CHECK_IF_IRQ_SUPPORTED(Sources);
+
+    /*
+        EIP201_CONFIG_ACTIVE_LOW,       // Type=0, Pol=0
+        EIP201_CONFIG_ACTIVE_HIGH,      // Type=0, Pol=1
+        EIP201_CONFIG_FALLING_EDGE,     // Type=1, Pol=0
+        EIP201_CONFIG_RISING_EDGE       // Type=1, Pol=1
+    */
+
+    // do we want Type=1?
+    if (Config == EIP201_CONFIG_FALLING_EDGE ||
+        Config == EIP201_CONFIG_RISING_EDGE)
+    {
+        NewType = Sources;
+    }
+
+    // do we want Pol=1?
+    if (Config == EIP201_CONFIG_ACTIVE_HIGH ||
+        Config == EIP201_CONFIG_RISING_EDGE)
+    {
+        NewPol = Sources;
+    }
+
+    if (Sources)
+    {
+        // modify polarity register
+        rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_POL_CTRL, &Value);
+        if (rc) return rc;
+        Value &= ~Sources;
+        Value |= NewPol;
+        rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_POL_CTRL, Value);
+        if (rc) return rc;
+
+        // modify type register
+        rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_TYPE_CTRL, &Value);
+        if (rc) return rc;
+        Value &= ~Sources;
+        Value |= NewType;
+        rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_TYPE_CTRL, Value);
+        if (rc) return rc;
+    }
+
+    return EIP201_STATUS_SUCCESS;
+}
+#endif /* EIP201_REMOVE_CONFIG_CHANGE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Config_Read
+ */
+#ifndef EIP201_REMOVE_CONFIG_READ
+
+static const EIP201_Config_t EIP201_Setting2Config[4] =
+{
+    EIP201_CONFIG_ACTIVE_LOW,       // Type=0, Pol=0
+    EIP201_CONFIG_ACTIVE_HIGH,      // Type=0, Pol=1
+    EIP201_CONFIG_FALLING_EDGE,     // Type=1, Pol=0
+    EIP201_CONFIG_RISING_EDGE       // Type=1, Pol=1
+};
+
+EIP201_Config_t
+EIP201_Config_Read(
+        Device_Handle_t Device,
+        const EIP201_Source_t Source)
+{
+    uint32_t Value;
+    unsigned char Setting = 0;
+    int rc = 0;
+
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_TYPE_CTRL, &Value);
+    if (rc) return rc;
+    if (Value & Source)
+    {
+        // Type=1, thus edge
+        Setting += 2;
+    }
+
+    EIP201_Read32(Device, EIP201_REGISTER_OFFSET_POL_CTRL, &Value);
+    if (Value & Source)
+    {
+        // Pol=1, this rising edge or active high
+        Setting++;
+    }
+
+    return EIP201_Setting2Config[Setting];
+}
+#endif /* EIP201_REMOVE_CONFIG_READ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceMask_EnableSource
+ *
+ * See header file for function specifications.
+ */
+#ifndef EIP201_REMOVE_SOURCEMASK_ENABLESOURCE
+EIP201_Status_t
+EIP201_SourceMask_EnableSource(
+        Device_Handle_t Device,
+        const EIP201_SourceBitmap_t Sources)
+{
+    int rc;
+    EIP201_CHECK_IF_IRQ_SUPPORTED(Sources);
+
+    rc = EIP201_Write32(
+            Device,
+            EIP201_REGISTER_OFFSET_ENABLE_SET,
+            Sources);
+
+    return rc;
+}
+#endif /* EIP201_REMOVE_SOURCEMASK_ENABLESOURCE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceMask_DisableSource
+ */
+#ifndef EIP201_REMOVE_SOURCEMASK_DISABLESOURCE
+EIP201_Status_t
+EIP201_SourceMask_DisableSource(
+        Device_Handle_t Device,
+        const EIP201_SourceBitmap_t Sources)
+{
+    int rc;
+    rc = EIP201_Write32(
+            Device,
+            EIP201_REGISTER_OFFSET_ENABLE_CLR,
+            Sources);
+
+    return rc;
+}
+#endif /* EIP201_REMOVE_SOURCEMASK_DISABLESOURCE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceMask_SourceIsEnabled
+ */
+#ifndef EIP201_REMOVE_SOURCEMASK_SOURCEISENABLED
+bool
+EIP201_SourceMask_SourceIsEnabled(
+        Device_Handle_t Device,
+        const EIP201_Source_t Source)
+{
+    int rc;
+    uint32_t SourceMasks;
+
+    rc =  EIP201_Read32(
+                        Device,
+        EIP201_REGISTER_OFFSET_ENABLE_CTRL, &SourceMasks);
+
+    if (rc) return false;
+    if (SourceMasks & Source)
+        return true;
+
+    return false;
+}
+#endif /* EIP201_REMOVE_SOURCEMASK_SOURCEISENABLED */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceMask_ReadAll
+ */
+#ifndef EIP201_REMOVE_SOURCEMASK_READALL
+EIP201_SourceBitmap_t
+EIP201_SourceMask_ReadAll(
+        Device_Handle_t Device)
+{
+    uint32_t Value;
+    EIP201_Read32(Device, EIP201_REGISTER_OFFSET_ENABLE_CTRL, &Value);
+    return Value;
+}
+#endif /* EIP201_REMOVE_SOURCEMASK_READALL */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_IsEnabledSourcePending
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_ISENABLEDSOURCEPENDING
+bool
+EIP201_SourceStatus_IsEnabledSourcePending(
+        Device_Handle_t Device,
+        const EIP201_Source_t Source)
+{
+    uint32_t Statuses;
+    int rc;
+
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_ENABLED_STAT, &Statuses);
+    if (rc) return false;
+
+    if (Statuses & Source)
+        return true;
+
+    return false;
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_ISENABLEDSOURCEPENDING */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_IsRawSourcePending
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_ISRAWSOURCEPENDING
+bool
+EIP201_SourceStatus_IsRawSourcePending(
+        Device_Handle_t Device,
+        const EIP201_Source_t Source)
+{
+    uint32_t Statuses;
+    int rc;
+
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_RAW_STAT, &Statuses);
+    if (rc) return false;
+
+    if (Statuses & Source)
+        return true;
+
+    return false;
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_ISRAWSOURCEPENDING */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_ReadAllEnabled
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_READALLENABLED
+EIP201_SourceBitmap_t
+EIP201_SourceStatus_ReadAllEnabled(
+        Device_Handle_t Device)
+{
+    uint32_t Value;
+    EIP201_Read32(Device, EIP201_REGISTER_OFFSET_ENABLED_STAT, &Value);
+    return Value;
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_READALLENABLED */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_ReadAllRaw
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_READALLRAW
+EIP201_SourceBitmap_t
+EIP201_SourceStatus_ReadAllRaw(
+        Device_Handle_t Device)
+{
+    uint32_t Value;
+    EIP201_Read32(Device, EIP201_REGISTER_OFFSET_RAW_STAT, &Value);
+    return Value;
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_READALLRAW */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_ReadAllEnabledCheck
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_READALLENABLED
+EIP201_Status_t
+EIP201_SourceStatus_ReadAllEnabledCheck(
+        Device_Handle_t Device,
+        EIP201_SourceBitmap_t * const Statuses_p)
+{
+    return EIP201_Read32(Device, EIP201_REGISTER_OFFSET_ENABLED_STAT, Statuses_p);
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_READALLENABLED */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_SourceStatus_ReadAllRawCheck
+ */
+#ifndef EIP201_REMOVE_SOURCESTATUS_READALLRAW
+EIP201_Status_t
+EIP201_SourceStatus_ReadAllRawCheck(
+        Device_Handle_t Device,
+        EIP201_SourceBitmap_t * const Statuses_p)
+{
+    return EIP201_Read32(Device, EIP201_REGISTER_OFFSET_RAW_STAT, Statuses_p);
+}
+#endif /* EIP201_REMOVE_SOURCESTATUS_READALLRAW */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201Lib_Detect
+ *
+ *  Detect the presence of EIP201 hardware.
+ */
+#ifndef EIP201_REMOVE_INITIALIZE
+static EIP201_Status_t
+EIP201Lib_Detect(
+        Device_Handle_t Device)
+{
+    uint32_t Value;
+    int rc;
+
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_VERSION, &Value);
+    if (rc) return rc;
+    Value &= EIP201_SIGNATURE_MASK;
+    if ( Value != EIP201_SIGNATURE)
+        return EIP201_STATUS_UNSUPPORTED_HARDWARE_VERSION;
+
+    // Prevent interrupts going of by disabling them
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_ENABLE_CTRL, 0);
+    if (rc) return rc;
+
+    // Get the number of interrupt sources
+    rc = EIP201_Read32(Device, EIP201_REGISTER_OFFSET_OPTIONS, &Value);
+    if (rc) return rc;
+    // lowest 6 bits contain the number of inputs, which should be between 1-32
+    Value &= MASK_6_BITS;
+    if (Value == 0 || Value > 32)
+        return EIP201_STATUS_UNSUPPORTED_HARDWARE_VERSION;
+
+    return EIP201_STATUS_SUCCESS;
+}
+#endif /* EIP201_REMOVE_INITIALIZE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Initialize API
+ *
+ *  See header file for function specification.
+ */
+#ifndef EIP201_REMOVE_INITIALIZE
+EIP201_Status_t
+EIP201_Initialize(
+        Device_Handle_t Device,
+        const EIP201_SourceSettings_t * SettingsArray_p,
+        const unsigned int SettingsCount)
+{
+    EIP201_SourceBitmap_t ActiveLowSources = 0;
+    EIP201_SourceBitmap_t ActiveHighSources = 0;
+    EIP201_SourceBitmap_t FallingEdgeSources = 0;
+    EIP201_SourceBitmap_t RisingEdgeSources = 0;
+    EIP201_SourceBitmap_t EnabledSources = 0;
+    int rc;
+
+    // check presence of EIP201 hardware
+    rc = EIP201Lib_Detect(Device);
+    if (rc) return rc;
+
+    // disable all interrupts and set initial configuration
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_ENABLE_CTRL, 0);
+    if (rc) return rc;
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_POL_CTRL, 0);
+    if (rc) return rc;
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_TYPE_CTRL, 0);
+    if (rc) return rc;
+
+    // process the setting, if provided
+    if (SettingsArray_p != NULL)
+    {
+        unsigned int i;
+
+        for (i = 0; i < SettingsCount; i++)
+        {
+            // check
+            const EIP201_Source_t Source = SettingsArray_p[i].Source;
+            EIP201_CHECK_IF_IRQ_SUPPORTED(Source);
+
+            // determine polarity
+            switch(SettingsArray_p[i].Config)
+            {
+                case EIP201_CONFIG_ACTIVE_LOW:
+                    ActiveLowSources |= Source;
+                    break;
+
+                case EIP201_CONFIG_ACTIVE_HIGH:
+                    ActiveHighSources |= Source;
+                    break;
+
+                case EIP201_CONFIG_FALLING_EDGE:
+                    FallingEdgeSources |= Source;
+                    break;
+
+                case EIP201_CONFIG_RISING_EDGE:
+                    RisingEdgeSources |= Source;
+                    break;
+
+                default:
+                    // invalid parameter
+                    break;
+            } // switch
+
+            // determine enabled mask
+            if (SettingsArray_p[i].fEnable)
+                EnabledSources |= Source;
+        } // for
+    }
+
+    // program source configuration
+    rc = EIP201_Config_Change(
+            Device,
+            ActiveLowSources,
+            EIP201_CONFIG_ACTIVE_LOW);
+    if (rc) return rc;
+
+    rc = EIP201_Config_Change(
+            Device,
+            ActiveHighSources,
+            EIP201_CONFIG_ACTIVE_HIGH);
+    if (rc) return rc;
+
+    rc = EIP201_Config_Change(
+            Device,
+            FallingEdgeSources,
+            EIP201_CONFIG_FALLING_EDGE);
+    if (rc) return rc;
+
+    rc = EIP201_Config_Change(
+            Device,
+            RisingEdgeSources,
+            EIP201_CONFIG_RISING_EDGE);
+    if (rc) return rc;
+
+    // the configuration change could have triggered the edge-detection logic
+    // so acknowledge all edge-based interrupts immediately
+    {
+        const uint32_t Value = FallingEdgeSources | RisingEdgeSources;
+        rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_ACK, Value);
+        if (rc) return rc;
+    }
+
+    // set mask (enable required interrupts)
+    rc = EIP201_SourceMask_EnableSource(Device, EnabledSources);
+
+    return rc;
+}
+#endif /* EIP201_REMOVE_INITIALIZE */
+
+
+/*----------------------------------------------------------------------------
+ * EIP201_Acknowledge
+ *
+ * See header file for function specification.
+ */
+#ifndef EIP201_REMOVE_ACKNOWLEDGE
+EIP201_Status_t
+EIP201_Acknowledge(
+        Device_Handle_t Device,
+        const EIP201_SourceBitmap_t Sources)
+{
+    int rc;
+    EIP201_CHECK_IF_IRQ_SUPPORTED(Sources);
+
+    rc = EIP201_Write32(Device, EIP201_REGISTER_OFFSET_ACK, Sources);
+
+    return rc;
+}
+#endif /* EIP201_REMOVE_ACKNOWLEDGE */
+
+/* end of file eip201_sl.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cd_format.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cd_format.c
new file mode 100644
index 0000000..1190450
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cd_format.c
@@ -0,0 +1,185 @@
+/* eip202_cd_format.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * Command Descriptor Internal interface
+ *
+ * This module contains the EIP-202 Command Descriptor specific functionality
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_cd_format.h"
+
+// Descriptor I/O Driver Library API implementation
+#include "eip202_cdr.h"                 // EIP202_ARM_CommandDescriptor_t
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // bool, uint32_t, uint8_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"              // DMAResource_Handle_t
+#include "dmares_rw.h"                 // DMAResource_Write/Read
+
+// Standard IOToken API
+#include "iotoken.h"
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CD_Make_ControlWord
+ */
+uint32_t
+EIP202_CD_Make_ControlWord(
+        const uint8_t TokenWordCount,
+        const uint32_t SegmentByteCount,
+        const bool fFirstSegment,
+        const bool fLastSegment,
+        const bool fForceEngine,
+        const uint8_t EngineId)
+{
+    uint32_t Value = 0;
+
+    if(fFirstSegment)
+        Value |= BIT_23;
+
+    if(fLastSegment)
+        Value |= BIT_22;
+
+    Value |= ((((uint32_t)TokenWordCount) & MASK_8_BITS) << 24);
+    Value |= ((((uint32_t)SegmentByteCount) & MASK_16_BITS));
+    if (fForceEngine)
+        Value |= BIT_21 | (((uint32_t)EngineId & MASK_5_BITS) << 16);
+
+    return Value;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CD_Write
+ */
+void
+EIP202_CD_Write(
+        DMAResource_Handle_t Handle,
+        const unsigned int WordOffset,
+        const EIP202_ARM_CommandDescriptor_t * const Descr_p,
+        const bool fATP)
+
+{
+    unsigned int InTokenWordOffset;
+
+#ifdef EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+    IOToken_Mark_Set(Descr_p->Token_p);
+#endif
+
+#ifdef EIP202_64BIT_DEVICE
+    // Write Control Word
+    DMAResource_Write32(Handle, WordOffset, Descr_p->ControlWord);
+
+    // Lengths greater than 20 bits not supported yet.
+#ifndef EIP202_CDR_OPT1
+    DMAResource_Write32(Handle, WordOffset + 1, 0);
+#endif
+
+    // Write Source Packet Data address
+    DMAResource_Write32(Handle, WordOffset + 2, Descr_p->SrcPacketAddr.Addr);
+    DMAResource_Write32(Handle, WordOffset + 3, Descr_p->SrcPacketAddr.UpperAddr);
+
+    if (fATP)
+    {
+#ifndef EIP202_CDR_OPT2
+        // Write Token Data address
+        DMAResource_Write32(Handle,
+                            WordOffset + 4,
+                            Descr_p->TokenDataAddr.Addr);
+        DMAResource_Write32(Handle,
+                            WordOffset + 5,
+                            Descr_p->TokenDataAddr.UpperAddr);
+#endif
+        InTokenWordOffset = WordOffset + 6;
+    }
+    else
+        InTokenWordOffset = WordOffset + 4;
+#else // EIP202_64BIT_DEVICE
+    // Write Control Word
+    DMAResource_Write32(Handle, WordOffset, Descr_p->ControlWord);
+
+    // Write Source Packet Data address
+    DMAResource_Write32(Handle, WordOffset + 1, Descr_p->SrcPacketAddr.Addr);
+
+    if (fATP)
+    {
+#ifndef EIP202_CDR_OPT2
+        // Write Token Data address
+        DMAResource_Write32(Handle, WordOffset + 2, Descr_p->TokenDataAddr.Addr);
+#endif
+        InTokenWordOffset = WordOffset + 3;
+    }
+    else
+        InTokenWordOffset = WordOffset + 2;
+#endif // !EIP202_64BIT_DEVICE
+
+    // Write Input Token (only for the first segment and if token is available)
+    if (Descr_p->ControlWord & BIT_23 && Descr_p->Token_p)
+    {
+        unsigned int i, offset = InTokenWordOffset;
+
+        // Write Application ID
+#ifdef EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+        IOToken_Mark_Set(Descr_p->Token_p);
+#endif
+
+        for (i = 0; i < IOToken_InWordCount_Get(); i++)
+            DMAResource_Write32(Handle, offset + i, Descr_p->Token_p[i]);
+    }
+
+    return;
+}
+
+
+/* end of file eip202_cd_format.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_dscr.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_dscr.c
new file mode 100644
index 0000000..f7d1527
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_dscr.c
@@ -0,0 +1,363 @@
+/* eip202_cdr_dscr.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * 1) Descriptor I/O Driver Library API implementation
+ * 2) Internal Command Descriptor interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// Descriptor I/O Driver Library API implementation
+#include "eip202_cdr.h"
+
+// Internal Command Descriptor interface
+#include "eip202_cdr_dscr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_cdr_level0.h"         // EIP-202 Level 0 macros
+#include "eip202_cdr_fsm.h"             // CDR State machine
+#include "eip202_cd_format.h"           // CD Format API
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"         // types of the DMA resource API
+#include "dmares_rw.h"            // read/write of the DMA resource API.
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_CDR_FillLevel_Finalize
+ *
+ */
+static EIP202_Ring_Error_t
+EIP202Lib_CDR_FillLevel_Finalize(
+        const unsigned int CDWordCount,
+        volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p,
+        unsigned int * const FillLevelDscrCount_p)
+{
+#ifdef EIP202_RING_DEBUG_FSM
+    EIP202_Ring_Error_t rv;
+
+    if(CDWordCount == 0)
+        // CD Ring is empty
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                EIP202_CDR_STATE_INITIALIZED);
+    else if(CDWordCount > 0 &&
+            CDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        // CD Ring is free
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_CDR_STATE_FREE);
+    else if(CDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        // CD Ring is full
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_CDR_STATE_FULL);
+    else
+        rv = EIP202_RING_ILLEGAL_IN_STATE;
+
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+#endif
+
+    // Store actual fill level
+    *FillLevelDscrCount_p = CDWordCount /
+                            (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    // Return actual fill level plus one descriptor to distinguish
+    // ring full from ring empty
+    if(CDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        (*FillLevelDscrCount_p)++;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+  Internal Command Descriptor interface
+  ---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_WriteCB
+ */
+int
+EIP202_CDR_WriteCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        const unsigned int WriteIndex,
+        const unsigned int WriteCount,
+        const unsigned int TotalWriteLimit,
+        const void * Descriptors_p,
+        const int DescriptorCount,
+        const unsigned int DescriptorSkipCount)
+{
+    Device_Handle_t Device;
+    unsigned int i, DescOffsetWordCount;
+    unsigned int nWritten = 0;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p =
+                                            CDRIOAREA(CallbackParam1_p);
+    if(CallbackParam1_p == NULL || Descriptors_p == NULL)
+        return -1;
+
+    IDENTIFIER_NOT_USED(CallbackParam2);
+    IDENTIFIER_NOT_USED(DescriptorCount);
+    IDENTIFIER_NOT_USED(TotalWriteLimit);
+
+    Device = TrueIOArea_p->Device;
+
+    DescOffsetWordCount = (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    // Write descriptors to CDR
+    for(i = WriteIndex; i < WriteIndex + WriteCount; i++)
+    {
+        EIP202_CD_Write(
+            TrueIOArea_p->RingHandle,
+            i * DescOffsetWordCount,
+            ((const EIP202_ARM_CommandDescriptor_t *)Descriptors_p) +
+                                            DescriptorSkipCount + nWritten,
+            TrueIOArea_p->fATP);
+
+        nWritten++;
+    }
+
+    if (nWritten > 0)
+    {
+        // Call PreDMA to prepared descriptors in Ring DMA buffer for handover
+        // to the Device (the EIP-202 DMA Master)
+        DMAResource_PreDMA(TrueIOArea_p->RingHandle,
+                           WriteIndex * DescOffsetWordCount *
+                             (unsigned int)sizeof(uint32_t),
+                           nWritten * DescOffsetWordCount *
+                             (unsigned int)sizeof(uint32_t));
+
+        // CDS point: hand over written Command Descriptors to the Device
+        EIP202_CDR_COUNT_WR(Device,
+                            (uint16_t)(nWritten * DescOffsetWordCount),
+                            false);
+    }
+
+    return (int) nWritten;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_ReadCB
+ */
+int
+EIP202_CDR_ReadCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        const unsigned int ReadIndex,
+        const unsigned int ReadLimit,
+        void * Descriptors_p,
+        const unsigned int DescriptorSkipCount)
+{
+    IDENTIFIER_NOT_USED(CallbackParam1_p);
+    IDENTIFIER_NOT_USED(CallbackParam2);
+    IDENTIFIER_NOT_USED(ReadIndex);
+    IDENTIFIER_NOT_USED(ReadLimit);
+    IDENTIFIER_NOT_USED(Descriptors_p);
+    IDENTIFIER_NOT_USED(DescriptorSkipCount);
+
+    // Not used for CDR
+
+    return -1;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_StatusCB
+ */
+int
+EIP202_CDR_StatusCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        int * const DeviceReadPos_p)
+{
+    IDENTIFIER_NOT_USED(CallbackParam1_p);
+    IDENTIFIER_NOT_USED(CallbackParam2);
+
+    *DeviceReadPos_p = -1;  // not used
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+  Descriptor I/O Driver Library API implementation
+  ---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_FillLevel_Get
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_FillLevel_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    Device_Handle_t Device;
+    unsigned int CDWordCount;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    Device = TrueIOArea_p->Device;
+
+    {
+        uint32_t Value32;
+
+        EIP202_CDR_COUNT_RD(Device, &Value32);
+
+        TrueIOArea_p->CountRD       = Value32;
+        TrueIOArea_p->fValidCountRD = true;
+
+        CDWordCount = (unsigned int)Value32;
+    }
+
+    return EIP202Lib_CDR_FillLevel_Finalize(CDWordCount,
+                                            TrueIOArea_p,
+                                            FillLevelDscrCount_p);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Write_ControlWord
+ */
+uint32_t
+EIP202_CDR_Write_ControlWord(
+        const EIP202_CDR_Control_t * const  CommandCtrl_p)
+{
+    return EIP202_CD_Make_ControlWord(CommandCtrl_p->TokenWordCount,
+                                     CommandCtrl_p->SegmentByteCount,
+                                     CommandCtrl_p->fFirstSegment,
+                                     CommandCtrl_p->fLastSegment,
+                                     CommandCtrl_p->fForceEngine,
+                                     CommandCtrl_p->EngineId);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Descriptor_Put
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Descriptor_Put(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const EIP202_ARM_CommandDescriptor_t * CommandDscr_p,
+        const unsigned int DscrRequestedCount,
+        unsigned int * const DscrDoneCount_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    Device_Handle_t Device;
+    int res;
+    unsigned int CDWordCount, CDFreeCount, CDNewRequestedCount;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(CommandDscr_p);
+    EIP202_RING_CHECK_POINTER(DscrDoneCount_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Check how many descriptors can be put
+    {
+        uint32_t Value32;
+
+        if (TrueIOArea_p->fValidCountRD)
+        {
+            Value32 = TrueIOArea_p->CountRD;
+            TrueIOArea_p->fValidCountRD = false;
+        }
+        else
+        {
+            EIP202_CDR_COUNT_RD(Device, &Value32);
+            TrueIOArea_p->CountRD = Value32;
+        }
+
+        CDWordCount = (unsigned int)Value32;
+    }
+
+    // Check if CDR is full
+    if(CDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
+    {
+        // CD Ring is full
+        *FillLevelDscrCount_p = CDWordCount /
+                            (unsigned int)TrueIOArea_p->DescOffsWordCount;
+        *DscrDoneCount_p = 0;
+
+        return EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_CDR_STATE_FULL);
+    }
+
+    CDFreeCount =
+            ((unsigned int)TrueIOArea_p->RingSizeWordCount - CDWordCount) /
+                    (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    CDNewRequestedCount = MIN(CDFreeCount, DscrRequestedCount);
+
+    // Put command descriptors to CDR
+    res = RingHelper_Put((volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+                         CommandDscr_p,
+                         (int)CDNewRequestedCount);
+    if(res >= 0)
+        *DscrDoneCount_p = (unsigned int)res;
+    else
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Increase the fill level by the number of successfully put descriptors
+    CDWordCount += ((unsigned int)res *
+                         (unsigned int)TrueIOArea_p->DescOffsWordCount);
+
+    return EIP202Lib_CDR_FillLevel_Finalize(CDWordCount,
+                                           TrueIOArea_p,
+                                           FillLevelDscrCount_p);
+}
+
+
+/* end of file eip202_cdr_dscr.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_event.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_event.c
new file mode 100644
index 0000000..07e8481
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_event.c
@@ -0,0 +1,172 @@
+/* eip202_cdr_event.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * CDR Event Management API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_cdr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_cdr_level0.h"         // EIP-202 Level 0 macros
+#include "eip202_cdr_fsm.h"             // CDR State machine
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Status_Get
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Status_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_CDR_Status_t * const Status_p)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(Status_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_CDR_STAT_RD(Device,
+                       &Status_p->fDMAError,
+                       &Status_p->fTresholdInt,
+                       &Status_p->fError,
+                       &Status_p->fOUFlowError,
+                       &Status_p->fTimeoutInt,
+                       &Status_p->CDFIFOWordCount);
+
+    EIP202_CDR_COUNT_RD(Device, &Status_p->CDPrepWordCount);
+    EIP202_CDR_PROC_COUNT_RD(Device,
+                             &Status_p->CDProcWordCount,
+                             &Status_p->CDProcPktWordCount);
+
+    // Transit to a new state
+    if(Status_p->fDMAError)
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_CDR_STATE_FATAL_ERROR);
+    else
+        // Remain in the current state
+        rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                                 (EIP202_CDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_FillLevel_Low_INT_Enable
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_FillLevel_Low_INT_Enable(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const unsigned int ThresholdDscrCount,
+        const unsigned int Timeout)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_CDR_THRESH_WR(Device,
+                         (uint32_t)ThresholdDscrCount *
+                               TrueIOArea_p->DescOffsWordCount,
+                         (uint8_t)Timeout);
+
+    // Remain in the current state
+    rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_CDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_FillLevel_Low_INT_ClearAndDisable
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_FillLevel_Low_INT_ClearAndDisable(
+        EIP202_Ring_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Disable timeout interrupt and stop timeout counter for
+    // reducing power consumption
+    EIP202_CDR_THRESH_DEFAULT_WR(Device);
+
+    // Clear all CDR interrupts
+    EIP202_CDR_STAT_CLEAR_ALL_IRQ_WR(Device);
+
+    // Remain in the current state
+    rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_CDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/* end of file eip202_cdr_event.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_fsm.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_fsm.c
new file mode 100644
index 0000000..dda97e8
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_fsm.c
@@ -0,0 +1,174 @@
+/* eip202_cdr_fsm.c
+ *
+ * EIP-202 Ring Control Driver Library API
+ * State Machine Internal Interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_cdr_fsm.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"              // IDENTIFIER_NOT_USED
+
+// EIP-202 Ring Control Driver Library Types API
+#include "eip202_ring_types.h"        // EIP202_Ring_* types
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_State_Set
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_State_Set(
+        volatile EIP202_CDR_State_t * const CurrentState,
+        const EIP202_CDR_State_t NewState)
+{
+#ifdef EIP202_RING_DEBUG_FSM
+    switch(*CurrentState)
+    {
+        case EIP202_CDR_STATE_UNKNOWN:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+         case EIP202_CDR_STATE_UNINITIALIZED:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_INITIALIZED:
+                   *CurrentState = NewState;
+                   break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_CDR_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_CDR_STATE_FREE:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_CDR_STATE_FULL:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_CDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_CDR_STATE_FATAL_ERROR:
+            switch(NewState)
+            {
+                case EIP202_CDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP202_RING_ILLEGAL_IN_STATE;
+    }
+#else
+    IDENTIFIER_NOT_USED(CurrentState);
+    IDENTIFIER_NOT_USED(NewState);
+#endif // EIP202_RING_DEBUG_FSM
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/* end of file eip202_cdr_fsm.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_init.c
new file mode 100644
index 0000000..4b010f9
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_cdr_init.c
@@ -0,0 +1,403 @@
+/* eip202_cdr_init.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * CDR Init/Reset API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_cdr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Types API
+#include "eip202_ring_types.h"          // EIP202_Ring_* types
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_cdr_level0.h"          // EIP-202 Level 0 macros
+#include "eip202_cdr_fsm.h"             // CDR State machine
+#include "eip202_cdr_dscr.h"            // RingHelper callbacks
+#include "eip202_cd_format.h"           // EIP-202 Command Descriptor
+
+// RingHelper API
+#include "ringhelper.h"                // RingHelper_Init
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+// Driver Framework Device API
+#include "device_types.h"              // Device_Handle_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"         // types of the DMA resource API
+#include "dmares_rw.h"            // read/write of the DMA resource API.
+
+// Driver Framework C Run-Time Library API
+#include "clib.h"
+
+// Standard IOToken API
+#include "iotoken.h"                   // IOToken_InWordCount_Get()
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_Detect
+ *
+ * Checks the presence of EIP-202 HIA hardware. Returns true when found.
+ */
+static bool
+EIP202Lib_CDR_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    // read-write test one of the registers
+
+    // Set MASK_31_BITS bits of the EIP202_CDR_RING_BASE_ADDR_LO register
+    EIP202_CDR_Write32(Device,
+                       EIP202_CDR_RING_BASE_ADDR_LO,
+                       MASK_31_BITS );
+
+    Value = EIP202_CDR_Read32(Device, EIP202_CDR_RING_BASE_ADDR_LO);
+    if ((Value & MASK_31_BITS) != MASK_31_BITS)
+        return false;
+
+    // Clear MASK_31_BITS bits of the EIP202_CDR_RING_BASE_ADDR_LO register
+    EIP202_CDR_Write32(Device, EIP202_CDR_RING_BASE_ADDR_LO, 0);
+    Value = EIP202_CDR_Read32(Device, EIP202_CDR_RING_BASE_ADDR_LO);
+    if ((Value & MASK_31_BITS) != 0)
+       return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_CDR_ClearAllDescriptors
+ *
+ * Clear all descriptors
+ */
+static inline void
+EIP202Lib_CDR_ClearAllDescriptors(
+        DMAResource_Handle_t Handle,
+        const uint32_t DescriptorSpacingWordCount,
+        const uint32_t DescriptorSizeWordCount,
+        const uint32_t NumberOfDescriptors)
+{
+    unsigned int i, j;
+
+    for(i = 0; i < NumberOfDescriptors; i++)
+        for(j = 0; j < DescriptorSizeWordCount; j++)
+            DMAResource_Write32(Handle, i * DescriptorSpacingWordCount + j, 0);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Init
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Init(
+        EIP202_Ring_IOArea_t * IOArea_p,
+        const Device_Handle_t Device,
+        const EIP202_CDR_Settings_t * const CDRSettings_p)
+{
+    uint16_t CDFIFOWordCount;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    // Initialize the IO Area
+    TrueIOArea_p->fValidCountRD = false;
+    TrueIOArea_p->Device = Device;
+    TrueIOArea_p->State = (unsigned int)EIP202_CDR_STATE_UNINITIALIZED;
+
+    // Check if the CPU integer size is enough to store 32-bit value
+    if(sizeof(unsigned int) < sizeof(uint32_t))
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    // Detect presence of EIP-202 CDR hardware
+    if(!EIP202Lib_CDR_Detect(Device))
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    if(CDRSettings_p->fATPtoToken)
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    // Extension of 32-bit pointers to 64-bit addresses not supported.
+    if(CDRSettings_p->Params.DMA_AddressMode == EIP202_RING_64BIT_DMA_EXT_ADDR)
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    if(CDRSettings_p->Params.DscrOffsWordCount == 0 ||
+       CDRSettings_p->Params.DscrOffsWordCount <
+       CDRSettings_p->Params.DscrSizeWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Ring size cannot be smaller than one descriptor size or
+    // larger than 4194303 (16MB / 4 - 1), in 32-bit words
+    if(CDRSettings_p->Params.RingSizeWordCount <
+       CDRSettings_p->Params.DscrOffsWordCount ||
+       CDRSettings_p->Params.RingSizeWordCount > 4194303)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Read Command Descriptor FIFO size (in 32-bit words)
+    EIP202_CDR_STAT_FIFO_SIZE_RD(Device, &CDFIFOWordCount);
+
+    if(CDRSettings_p->Params.DscrSizeWordCount >
+             EIP202_CD_CTRL_DATA_MAX_WORD_COUNT + IOToken_InWordCount_Get() ||
+       CDRSettings_p->Params.DscrSizeWordCount > CDFIFOWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if(CDRSettings_p->Params.DscrFetchSizeWordCount > CDFIFOWordCount ||
+       CDRSettings_p->Params.DscrThresholdWordCount > CDFIFOWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if(CDRSettings_p->Params.DscrFetchSizeWordCount %
+                            CDRSettings_p->Params.DscrOffsWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if( CDRSettings_p->Params.IntThresholdDscrCount >
+        CDRSettings_p->Params.RingSizeWordCount )
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Configure the Ring Helper
+    TrueIOArea_p->RingHelperCallbacks.WriteFunc_p = &EIP202_CDR_WriteCB;
+    TrueIOArea_p->RingHelperCallbacks.ReadFunc_p = &EIP202_CDR_ReadCB;
+    TrueIOArea_p->RingHelperCallbacks.StatusFunc_p = &EIP202_CDR_StatusCB;
+    TrueIOArea_p->RingHelperCallbacks.CallbackParam1_p = IOArea_p;
+    TrueIOArea_p->RingHelperCallbacks.CallbackParam2 = 0;
+    TrueIOArea_p->RingHandle = CDRSettings_p->Params.RingDMA_Handle;
+    TrueIOArea_p->DescOffsWordCount = CDRSettings_p->Params.DscrOffsWordCount;
+    TrueIOArea_p->RingSizeWordCount = CDRSettings_p->Params.RingSizeWordCount;
+    TrueIOArea_p->fATP = CDRSettings_p->fATP;
+
+    // Initialize one RingHelper instance for one CDR instance
+    if( RingHelper_Init(
+         (volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+         (volatile RingHelper_CallbackInterface_t*)&TrueIOArea_p->RingHelperCallbacks,
+         true, // Separate CDR ring
+         (unsigned int)(CDRSettings_p->Params.RingSizeWordCount /
+             CDRSettings_p->Params.DscrOffsWordCount),
+         (unsigned int)(CDRSettings_p->Params.RingSizeWordCount /
+                        CDRSettings_p->Params.DscrOffsWordCount)) < 0)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Transit to a new state
+    rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                             EIP202_CDR_STATE_INITIALIZED);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    // Prepare the CDR DMA buffer
+    // Initialize all descriptors with zero for CDR
+    EIP202Lib_CDR_ClearAllDescriptors(
+            TrueIOArea_p->RingHandle,
+            CDRSettings_p->Params.DscrOffsWordCount,
+            CDRSettings_p->Params.DscrSizeWordCount,
+            CDRSettings_p->Params.RingSizeWordCount /
+                 CDRSettings_p->Params.DscrOffsWordCount);
+
+    // Call PreDMA to make sure engine sees it
+    DMAResource_PreDMA(TrueIOArea_p->RingHandle,
+                       0,
+                       (unsigned int)(TrueIOArea_p->RingSizeWordCount*4));
+
+    EIP202_CDR_RING_BASE_ADDR_LO_WR(
+                       Device,
+                       CDRSettings_p->Params.RingDMA_Address.Addr);
+
+    EIP202_CDR_RING_BASE_ADDR_HI_WR(
+                       Device,
+                       CDRSettings_p->Params.RingDMA_Address.UpperAddr);
+
+    EIP202_CDR_RING_SIZE_WR(
+                       Device,
+                       CDRSettings_p->Params.RingSizeWordCount);
+
+    EIP202_CDR_DESC_SIZE_WR(
+                       Device,
+                       CDRSettings_p->Params.DscrSizeWordCount,
+                       CDRSettings_p->Params.DscrOffsWordCount,
+                       CDRSettings_p->fATPtoToken,
+                       CDRSettings_p->fATP,
+                       CDRSettings_p->Params.DMA_AddressMode == EIP202_RING_64BIT_DMA_DSCR_PTR);
+
+    EIP202_CDR_CFG_WR(
+                       Device,
+                       CDRSettings_p->Params.DscrFetchSizeWordCount,
+                       CDRSettings_p->Params.DscrThresholdWordCount);
+
+    EIP202_CDR_DMA_CFG_WR(
+                       Device,
+                       (uint8_t)CDRSettings_p->Params.ByteSwap_Descriptor_Mask,
+                       (uint8_t)CDRSettings_p->Params.ByteSwap_Packet_Mask,
+                       (uint8_t)CDRSettings_p->Params.ByteSwap_Token_Mask,
+                       // Bufferability control
+                       true,  // Buffer Ownership Word DMA writes
+                       EIP202_RING_CD_WR_CACHE_CTRL, // Write cache type control
+                       EIP202_RING_CD_RD_CACHE_CTRL, // Read cache type control
+                       EIP202_RING_CD_PROT_VALUE,
+                       EIP202_RING_DATA_PROT_VALUE,
+                       EIP202_RING_ACD_PROT_VALUE);
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Reset
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Reset(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_CDR_True_IOArea_t * const TrueIOArea_p = CDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    // Initialize the IO Area
+    memset((void*)IOArea_p, 0, sizeof(*TrueIOArea_p));
+    TrueIOArea_p->Device = Device;
+    TrueIOArea_p->State = (unsigned int)EIP202_CDR_STATE_UNKNOWN;
+
+    // Transit to a new state
+    rv = EIP202_CDR_State_Set((volatile EIP202_CDR_State_t*)&TrueIOArea_p->State,
+                             EIP202_CDR_STATE_UNINITIALIZED);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    // Clear CDR count
+    EIP202_CDR_COUNT_WR(Device, 0, true);
+
+    // Re-init CDR
+    EIP202_CDR_POINTER_DEFAULT_WR(Device);
+
+    // Restore default register values
+    EIP202_CDR_RING_BASE_ADDR_LO_DEFAULT_WR(Device);
+    EIP202_CDR_RING_BASE_ADDR_HI_DEFAULT_WR(Device);
+    EIP202_CDR_RING_SIZE_DEFAULT_WR(Device);
+    EIP202_CDR_DESC_SIZE_DEFAULT_WR(Device);
+    EIP202_CDR_CFG_DEFAULT_WR(Device);
+    EIP202_CDR_DMA_CFG_DEFAULT_WR(Device);
+
+    // Clear and disable all CDR interrupts
+    EIP202_CDR_STAT_CLEAR_ALL_IRQ_WR(Device);
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Options_Get
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_CDR_Options_Get(
+        const Device_Handle_t Device,
+        EIP202_Ring_Options_t * const Options_p)
+{
+    uint32_t Rev;
+
+    EIP202_RING_CHECK_POINTER(Options_p);
+
+    // Note: thie register does not exist in all versions of the device.
+    //       If it exists, the options register is also available.
+    Rev = EIP202_CDR_Read32(Device, EIP202_CDR_VERSION);
+    if ( !EIP202_CDR_REV_SIGNATURE_MATCH((uint16_t)Rev))
+    {
+        // No local CDR version and options registers available,
+        // function not supported
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+    }
+
+    EIP202_CDR_OPTIONS_RD(Device,
+                          &Options_p->NofRings,
+                          &Options_p->NofPes,
+                          &Options_p->fExpPlf,
+                          &Options_p->CF_Size,
+                          &Options_p->RF_Size,
+                          &Options_p->HostIfc,
+                          &Options_p->DMA_Len,
+                          &Options_p->HDW,
+                          &Options_p->TgtAlign,
+                          &Options_p->fAddr64);
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_CDR_Dump
+ *
+ */
+void
+EIP202_CDR_Dump(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_RingAdmin_t * const RingAdmin_p)
+{
+    EIP202_RDR_True_IOArea_t * const TrueIOArea_p =
+                            (EIP202_RDR_True_IOArea_t * const)IOArea_p;
+
+    if(!TrueIOArea_p)
+        return;
+
+    if(!RingAdmin_p)
+        return;
+
+    RingAdmin_p->IN_Size           = TrueIOArea_p->RingHelper.IN_Size;
+    RingAdmin_p->IN_Tail           = TrueIOArea_p->RingHelper.IN_Tail;
+    RingAdmin_p->OUT_Size          = TrueIOArea_p->RingHelper.OUT_Size;
+    RingAdmin_p->OUT_Head          = TrueIOArea_p->RingHelper.OUT_Head;
+
+    RingAdmin_p->fSeparate         = TrueIOArea_p->RingHelper.fSeparate;
+
+    RingAdmin_p->DescOffsWordCount = TrueIOArea_p->DescOffsWordCount;
+    RingAdmin_p->RingSizeWordCount = TrueIOArea_p->RingSizeWordCount;
+}
+
+
+/* end of file eip202_cdr_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_global_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_global_init.c
new file mode 100644
index 0000000..7a0006d
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_global_init.c
@@ -0,0 +1,457 @@
+/* eip202_global_init.c
+ *
+ * EIP-202 Global Control Driver Library
+ * Initialization Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_global_init.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip97_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"             // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                   // ZEROINIT
+
+// Driver Framework Device API
+#include "device_types.h"           // Device_Handle_t
+
+#include "eip202_global_level0.h"   // EIP-202 Level 0 macros
+
+// EIP97_Interfaces_Get
+#include "eip97_global_internal.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Detect
+ */
+bool
+EIP202_Global_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    Value = EIP202_Read32(Device, EIP202_G_REG_VERSION);
+    if (!EIP202_REV_SIGNATURE_MATCH( Value ))
+        return false;
+
+    return true;
+}
+
+
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_HWRevision_Get
+ */
+void
+EIP202_Global_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP202_Capabilities_t * const Capabilities_p)
+{
+    EIP202_EIP_REV_RD(Device,
+                      &Capabilities_p->EipNumber,
+                      &Capabilities_p->ComplmtEipNumber,
+                      &Capabilities_p->HWPatchLevel,
+                      &Capabilities_p->MinHWRevision,
+                      &Capabilities_p->MajHWRevision);
+
+    EIP202_OPTIONS_RD(Device,
+                      &Capabilities_p->NofRings,
+                      &Capabilities_p->NofPes,
+                      &Capabilities_p->fExpPlf,
+                      &Capabilities_p->CF_Size,
+                      &Capabilities_p->RF_Size,
+                      &Capabilities_p->HostIfc,
+                      &Capabilities_p->DMA_Len,
+                      &Capabilities_p->HDW,
+                      &Capabilities_p->TgtAlign,
+                      &Capabilities_p->fAddr64);
+
+    EIP202_OPTIONS2_RD(Device,
+                       &Capabilities_p->NofLA_Ifs,
+                       &Capabilities_p->NofIN_Ifs,
+                       &Capabilities_p->NofAXI_WrChs,
+                       &Capabilities_p->NofAXI_RdClusters,
+                       &Capabilities_p->NofAXI_RdCPC);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Endianness_Slave_Configure
+ *
+ * Configure Endianness Conversion method
+ * for the EIP-202 slave (MMIO) interface
+ *
+ */
+bool
+EIP202_Global_Endianness_Slave_Configure(
+        const Device_Handle_t Device)
+{
+#ifdef EIP97_GLOBAL_ENABLE_SWAP_REG_DATA
+    uint32_t Value;
+
+    // Read and check the revision register
+    Value = EIP202_Read32(Device, EIP202_G_REG_VERSION);
+    if (!EIP202_REV_SIGNATURE_MATCH( Value ))
+    {
+        // No match, try to enable the Slave interface byte swap
+        // Must be done via EIP-202 HIA GLobal
+        EIP202_MST_CTRL_BYTE_SWAP_UPDATE(Device, true);
+
+        // Read and check the revision register again
+        Value = EIP202_Read32(Device, EIP202_G_REG_VERSION);
+        if (!EIP202_REV_SIGNATURE_MATCH( Value ))
+            // Bail out if still not OK
+            return false;
+    }
+
+    return true;
+#else
+    IDENTIFIER_NOT_USED(Device);
+    return true;
+#endif // EIP97_GLOBAL_ENABLE_SWAP_REG_DATA
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Init
+ */
+void
+EIP202_Global_Init(
+        const Device_Handle_t Device,
+        unsigned int NofPE,
+        unsigned int NofLA,
+        uint8_t ipbuf_min,
+        uint8_t ipbuf_max,
+        uint8_t itbuf_min,
+        uint8_t itbuf_max,
+        uint8_t opbuf_min,
+        uint8_t opbuf_max)
+{
+    unsigned int i;
+    uint8_t BufferCtrl;
+    unsigned int NofPEs,NofRings,NofLAs,NofIN,DFEDSEOffset;
+    EIP97_Interfaces_Get(&NofPEs,&NofRings,&NofLAs,&NofIN);
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    // Configure EIP-202 HIA Global
+    EIP202_MST_CTRL_BUS_BURST_SIZE_UPDATE(Device,
+                                          EIP97_GLOBAL_BUS_BURST_SIZE,
+                                          EIP97_GLOBAL_RX_BUS_BURST_SIZE);
+    EIP202_MST_CTRL_BUS_TIMEOUT_UPDATE(Device,
+                                       EIP97_GLOBAL_TIMEOUT_VALUE);
+    if (NofLA)
+        // User-configured value
+        BufferCtrl = EIP97_GLOBAL_DSE_BUFFER_CTRL;
+    else
+        // Default register reset value
+        BufferCtrl = (uint8_t)EIP202_DSE_BUFFER_CTRL;
+
+    for (i = 0; i < NofPE; i++)
+    {
+        // Configure EIP-202 HIA DFE Global
+        EIP202_DFE_CFG_WR(Device,
+                          DFEDSEOffset,
+                          i,
+                          ipbuf_min,
+                          EIP97_GLOBAL_DFE_DATA_CACHE_CTRL,
+                          ipbuf_max,
+                          itbuf_min,
+                          EIP97_GLOBAL_DFE_CTRL_CACHE_CTRL,
+                          itbuf_max,
+                          (EIP97_GLOBAL_DFE_ADV_THRESH_MODE_FLAG == 1),
+                          (EIP97_GLOBAL_DFE_AGGRESSIVE_DMA_FLAG == 1));
+
+        // Configure EIP-202 HIA DSE Global
+        EIP202_DSE_CFG_WR(Device,
+                          DFEDSEOffset,
+                          i,
+                          opbuf_min,
+                          EIP97_GLOBAL_DSE_DATA_CACHE_CTRL,
+                          opbuf_max,
+                          BufferCtrl,
+                          (EIP97_GLOBAL_DSE_ENABLE_SINGLE_WR_FLAG == 1),
+                          (EIP97_GLOBAL_DSE_AGGRESSIVE_DMA_FLAG == 1));
+
+    }
+
+    // Configure HIA Look-aside FIFO
+    EIP202_LASIDE_BASE_ADDR_LO_WR(Device,
+                                  EIP202_LASIDE_DSCR_BYTE_SWAP_METHOD);
+
+    for (i = EIP97_GLOBAL_LAFIFO_RING_ID;
+         i < NofLAs +
+             EIP97_GLOBAL_LAFIFO_RING_ID;
+         i++)
+    {
+        EIP202_LASIDE_SLAVE_CTRL_WR(Device,
+                                    i,
+                                    EIP202_LASIDE_IN_PKT_BYTE_SWAP_METHOD,
+                                    EIP202_LASIDE_IN_PKT_PROTO,
+                                    EIP202_LASIDE_TOKEN_BYTE_SWAP_METHOD,
+                                    EIP202_LASIDE_TOKEN_PROTO,
+                                    true); // Clear cmd descriptor error
+
+        EIP202_LASIDE_MASTER_CTRL_WR(Device,
+                                     i,
+                                     EIP202_LASIDE_OUT_PKT_BYTE_SWAP_METHOD,
+                                     EIP202_LASIDE_OUT_PKT_PROTO,
+                                     true); // Clear res descriptor error
+    }
+    // Configure HIA Inline FIFO
+    for (i = 0; i < NofIN; i++)
+        EIP202_INLINE_CTRL_WR(Device,
+                              i,
+                              EIP202_INLINE_IN_PKT_BYTE_SWAP_METHOD,
+                              false, // Clear protocol error
+                              EIP202_INLINE_OUT_PKT_BYTE_SWAP_METHOD,
+                              opbuf_min,
+                              opbuf_max,
+                              EIP202_INLINE_BURST_SIZE,
+                              EIP202_INLINE_FORCE_INORDER);
+
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Reset
+ */
+bool
+EIP202_Global_Reset(
+        const Device_Handle_t Device,
+        const unsigned int NofPE)
+{
+    unsigned int i;
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    // Restore the EIP-202 default configuration
+    // Resets DFE thread and clears ring assignment
+    for (i = 0; i < NofPE; i++)
+        EIP202_DFE_TRD_CTRL_WR(Device, DFEDSEOffset, i, 0, false, true);
+
+    // HIA DFE defaults
+    for (i = 0; i < NofPE; i++)
+        EIP202_DFE_CFG_DEFAULT_WR(Device, DFEDSEOffset, i);
+
+#ifndef EIP202_RA_DISABLE
+    EIP202_RA_PRIO_0_DEFAULT_WR(Device);
+    EIP202_RA_PRIO_1_DEFAULT_WR(Device);
+    EIP202_RA_PRIO_2_DEFAULT_WR(Device);
+    EIP202_RA_PRIO_3_DEFAULT_WR(Device);
+
+    // Resets ring assignment
+    for (i = 0; i < NofPE; i++)
+        EIP202_RA_PE_CTRL_WR(Device, i, 0, false, true);
+#endif // #ifndef EIP202_RA_DISABLE
+
+    // Resets DSE thread and clears ring assignment
+    for (i = 0; i < NofPE; i++)
+        EIP202_DSE_TRD_CTRL_WR(Device, DFEDSEOffset, i, 0, false, true);
+
+    // HIA DSE defaults
+    for (i = 0; i < NofPE; i++)
+        EIP202_DSE_CFG_DEFAULT_WR(Device, DFEDSEOffset, i);
+
+
+    // HIA LASIDE defaults
+    EIP202_LASIDE_BASE_ADDR_LO_DEFAULT_WR(Device);
+    EIP202_LASIDE_BASE_ADDR_HI_DEFAULT_WR(Device);
+    for (i = EIP97_GLOBAL_LAFIFO_RING_ID;
+         i < EIP97_GLOBAL_MAX_NOF_LAFIFO_TO_USE + EIP97_GLOBAL_LAFIFO_RING_ID;
+         i++)
+    {
+        EIP202_LASIDE_MASTER_CTRL_DEFAULT_WR(Device, i);
+        EIP202_LASIDE_SLAVE_CTRL_DEFAULT_WR(Device, i);
+    }
+
+    // HIA INLINE defaults
+    for (i = 0; i < NofPE; i++)
+        EIP202_INLINE_CTRL_DEFAULT_WR(Device, i);
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Reset_IsDone
+ */
+bool
+EIP202_Global_Reset_IsDone(
+        const Device_Handle_t Device,
+        const unsigned int PEnr)
+{
+    uint8_t RingId;
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    // Check for completion of all DMA transfers
+    EIP202_DFE_TRD_STAT_RINGID_RD(Device, DFEDSEOffset, PEnr, &RingId);
+    if(RingId == EIP202_DFE_TRD_REG_STAT_IDLE)
+    {
+        EIP202_DSE_TRD_STAT_RINGID_RD(Device, DFEDSEOffset, PEnr, &RingId);
+        if(RingId == EIP202_DFE_TRD_REG_STAT_IDLE)
+        {
+            // Take DFE thread out of reset
+            EIP202_DFE_TRD_CTRL_DEFAULT_WR(Device, DFEDSEOffset, PEnr);
+
+            // Take DSE thread out of reset
+            EIP202_DSE_TRD_CTRL_DEFAULT_WR(Device, DFEDSEOffset, PEnr);
+
+            // Do not restore the EIP-202 Master Control default configuration
+            // so this will not change the endianness conversion configuration
+            // for the Slave interface
+        }
+        return true;
+    }
+    else
+    {
+        return false;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Global_Configure
+ */
+void
+EIP202_Global_Configure(
+        const Device_Handle_t Device,
+        const unsigned int PE_Number,
+        const EIP202_Global_Ring_PE_Map_t * const RingPEMap_p)
+{
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+    // Disable EIP-202 HIA DFE thread(s)
+    EIP202_DFE_TRD_CTRL_WR(Device,
+                           DFEDSEOffset,
+                           PE_Number,   // Thread Nr
+                           0,
+                           false,       // Disable thread
+                           false);      // Do not reset thread
+
+    // Disable EIP-202 HIA DSE thread(s)
+    EIP202_DSE_TRD_CTRL_WR(Device,
+                           DFEDSEOffset,
+                           PE_Number,   // Thread Nr
+                           0,
+                           false,       // Disable thread
+                           false);      // Do not reset thread
+
+#ifndef EIP202_RA_DISABLE
+    // Configure the HIA Ring Arbiter
+    EIP202_RA_PRIO_0_WR(
+            Device,
+            (RingPEMap_p->RingPrio_Mask & BIT_0) == 0 ? false : true,
+            (uint8_t)(RingPEMap_p->RingSlots0 & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_1) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 4) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_2) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 8) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_3) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 12) & MASK_4_BITS));
+
+    EIP202_RA_PRIO_1_WR(
+            Device,
+            (RingPEMap_p->RingPrio_Mask & BIT_4) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 16) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_5) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 20) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_6) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 24) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_7) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots0 >> 28) & MASK_4_BITS));
+
+    EIP202_RA_PRIO_2_WR(
+            Device,
+            (RingPEMap_p->RingPrio_Mask & BIT_8) == 0 ? false : true,
+            (uint8_t)(RingPEMap_p->RingSlots1 & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_9) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 4) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_10) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 8) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_11) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 12) & MASK_4_BITS));
+
+    EIP202_RA_PRIO_3_WR(
+            Device,
+            (RingPEMap_p->RingPrio_Mask & BIT_12) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 16) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_13) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 20) & MASK_4_BITS),
+            (RingPEMap_p->RingPrio_Mask & BIT_14) == 0 ? false : true,
+            (uint8_t)((RingPEMap_p->RingSlots1 >> 24) & MASK_4_BITS));
+
+    // Ring assignment in the Ring Arbiter
+    EIP202_RA_PE_CTRL_WR(Device,
+                         PE_Number,
+                         RingPEMap_p->RingPE_Mask,
+                         true,
+                         false);
+#endif // #ifndef EIP202_RA_DISABLE
+
+    {
+        // Assign Rings to this DFE thread
+        // Enable EIP-202 HIA DFE thread(s)
+        EIP202_DFE_TRD_CTRL_WR(Device,
+                               DFEDSEOffset,
+                               PE_Number,   // Thread Nr
+                               RingPEMap_p->RingPE_Mask,  // Rings to assign
+                               true,        // Enable thread
+                               false);      // Do not reset thread
+
+        // Assign Rings to this DSE thread
+        // Enable EIP-202 HIA DSE thread(s)
+        EIP202_DSE_TRD_CTRL_WR(Device,
+                               DFEDSEOffset,
+                               PE_Number,   // Thread Nr
+                               RingPEMap_p->RingPE_Mask,   // Rings to assign
+                               true,        // Enable thread
+                               false);      // Do not reset thread
+    }
+}
+
+/* end of file eip202_global_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rd_format.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rd_format.c
new file mode 100644
index 0000000..d3ce3c6
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rd_format.c
@@ -0,0 +1,313 @@
+/* eip202_rd_format.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * Result Descriptor Internal interface
+ *
+ * This module contains the EIP-202 Result Descriptor specific functionality
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_rd_format.h"
+
+// Descriptor I/O Driver Library API implementation
+#include "eip202_rdr.h"                 // EIP202_ARM_CommandDescriptor_t
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // bool, uint32_t, uint8_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"              // DMAResource_Handle_t
+#include "dmares_rw.h"                 // DMAResource_Write/Read
+
+// Standard IOToken API
+#include "iotoken.h"
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RD_Make_ControlWord
+ */
+uint32_t
+EIP202_RD_Make_ControlWord(
+        const uint8_t ExpectedResultWordCount,
+        const uint32_t PrepSegmentByteCount,
+        const bool fFirstSegment,
+        const bool fLastSegment)
+{
+    uint32_t Value = 0;
+
+    if(fFirstSegment)
+        Value |= BIT_23;
+
+    if(fLastSegment)
+        Value |= BIT_22;
+
+    Value |= ((((uint32_t)ExpectedResultWordCount) & MASK_8_BITS) << 24);
+    Value |= ((((uint32_t)PrepSegmentByteCount)    & MASK_20_BITS));
+
+    return Value;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_Prepared_Write
+ */
+void
+EIP202_Prepared_Write(
+        DMAResource_Handle_t Handle,
+        const unsigned int WordOffset,
+        const EIP202_ARM_PreparedDescriptor_t * const Descr_p)
+{
+#ifdef EIP202_64BIT_DEVICE
+    // Write Control Word
+    DMAResource_Write32(Handle, WordOffset, Descr_p->PrepControlWord);
+
+    // Do not support lengths greater than 20 bit.
+    DMAResource_Write32(Handle, WordOffset + 1, 0);
+
+    // Write Destination Packet Data address
+    DMAResource_Write32(Handle, WordOffset + 2, Descr_p->DstPacketAddr.Addr);
+    DMAResource_Write32(Handle, WordOffset + 3, Descr_p->DstPacketAddr.UpperAddr);
+
+#else
+    // Write Control Word
+    DMAResource_Write32(Handle, WordOffset, Descr_p->PrepControlWord);
+
+    // Write Destination Packet Data address
+    DMAResource_Write32(Handle, WordOffset + 1, Descr_p->DstPacketAddr.Addr);
+#endif
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_ReadDescriptor
+ */
+void
+EIP202_ReadDescriptor(
+        EIP202_ARM_ResultDescriptor_t * const Descr_p,
+        const DMAResource_Handle_t Handle,
+        const unsigned int WordOffset,
+        const unsigned int DscrOffsWordCount,
+        const unsigned int TokenOffsWordCount,
+        bool * const fLastSegment,
+        bool * const fFirstSegment)
+{
+    unsigned int OutTokenWordOffset;
+
+#ifdef EIP202_64BIT_DEVICE
+    // Word 0 - Control Word
+    Descr_p->ProcControlWord = DMAResource_Read32(Handle, WordOffset);
+
+    // Word 1 - extended length, not read.
+
+    // Word 2 & 3 - Destination Packet Data Buffer Address
+    Descr_p->DstPacketAddr.Addr = DMAResource_Read32(Handle, WordOffset + 2);
+    Descr_p->DstPacketAddr.UpperAddr = DMAResource_Read32(Handle, WordOffset + 3);
+
+    OutTokenWordOffset = WordOffset + TokenOffsWordCount;
+#else // EIP202_64BIT_DEVICE
+    // Word 0 - Control Word
+    Descr_p->ProcControlWord = DMAResource_Read32(Handle, WordOffset);
+
+    // Word 1 - Destination Packet Data Buffer Address
+    Descr_p->DstPacketAddr.Addr = DMAResource_Read32(Handle, WordOffset + 1);
+
+    OutTokenWordOffset = WordOffset + 2;
+#endif // !EIP202_64BIT_DEVICE
+
+    if (Descr_p->Token_p == NULL)
+    {
+        *fLastSegment   = false;
+        *fFirstSegment  = false;
+        return; // Fatal error
+    }
+
+    // Read token data
+    {
+        unsigned int i;
+
+#ifdef EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+        for (i = 0; i < IOToken_OutWordCount_Get(); i++)
+            if (i != (unsigned int)IOToken_OutMarkOffset_Get())
+                Descr_p->Token_p[i] = DMAResource_Read32(
+                                          Handle,
+                                          OutTokenWordOffset + i);
+#else
+        for (i = 0; i < IOToken_OutWordCount_Get(); i++)
+            Descr_p->Token_p[i] = DMAResource_Read32(
+                                    Handle,
+                                    OutTokenWordOffset + i);
+#endif
+    }
+
+    // Check if this descriptor is for the last segment
+    if((Descr_p->ProcControlWord & BIT_22) != 0)
+        *fLastSegment = true; // Processed packet
+    else
+        *fLastSegment = false;
+
+    // Check if this descriptor is for the first segment
+    if((Descr_p->ProcControlWord & BIT_23) != 0)
+        *fFirstSegment = true; // New packet descriptor chain detected
+    else
+        *fFirstSegment = false;
+
+    IDENTIFIER_NOT_USED(DscrOffsWordCount);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_ClearDescriptor
+ */
+void
+EIP202_ClearDescriptor(
+        EIP202_ARM_ResultDescriptor_t * const Descr_p,
+        const DMAResource_Handle_t Handle,
+        const unsigned int WordOffset,
+        const unsigned int TokenOffsWordCount,
+        const unsigned int DscrWordCount)
+{
+    IDENTIFIER_NOT_USED(Descr_p);
+
+#if defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+
+    DMAResource_Write32(Handle, WordOffset + DscrWordCount - 1, 0);
+    IDENTIFIER_NOT_USED(TokenOffsWordCount);
+
+#elif defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS)
+
+    IDENTIFIER_NOT_USED(DscrWordCount);
+
+    DMAResource_Write32(Handle,
+                        WordOffset + TokenOffsWordCount +
+                                  IOToken_OutMarkOffset_Get(),
+                        0);
+#else
+    IDENTIFIER_NOT_USED(Handle);
+    IDENTIFIER_NOT_USED(WordOffset);
+    IDENTIFIER_NOT_USED(DscrWordCount);
+    IDENTIFIER_NOT_USED(TokenOffsWordCount);
+#endif // !EIP202_RDR_OWNERSHIP_WORD_ENABLE
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RD_Read_ControlWord
+ */
+void
+EIP202_RD_Read_ControlWord(
+        const uint32_t ControlWord,
+        uint32_t * TokenData_p,
+        EIP202_RDR_Result_Control_t * const RDControl_p,
+        EIP202_RDR_Result_Token_t * const ResToken_p)
+{
+    RDControl_p->ProcSegmentByteCount =  (ControlWord        & MASK_20_BITS);
+    RDControl_p->ProcResultWordCount  = ((ControlWord >> 24) & MASK_8_BITS);
+
+    // Fill in EIP202_RDR_Result_Control_t
+    if((ControlWord & BIT_20) != 0)
+        RDControl_p->fDscrOverflow = true;
+    else
+        RDControl_p->fDscrOverflow = false;
+
+    if((ControlWord & BIT_21) != 0)
+        RDControl_p->fBufferOverflow = true;
+    else
+        RDControl_p->fBufferOverflow = false;
+
+    if((ControlWord & BIT_22) != 0)
+        RDControl_p->fLastSegment = true;
+    else
+        RDControl_p->fLastSegment = false;
+
+    if((ControlWord & BIT_23) != 0)
+        RDControl_p->fFirstSegment = true;
+    else
+        RDControl_p->fFirstSegment = false;
+
+    IDENTIFIER_NOT_USED(TokenData_p);
+    IDENTIFIER_NOT_USED(ResToken_p);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RD_Read_BypassData
+ */
+void
+EIP202_RD_Read_BypassData(
+        const uint32_t * BypassData_p,
+        const uint8_t BypassWordCount,
+        EIP202_RDR_BypassData_t * const BD_p)
+{
+    if (BypassWordCount == 1)
+    {
+        BD_p->Fail.ErrorFlags = BypassData_p[0] & MASK_2_BITS;
+    }
+    else if (BypassWordCount == 2)
+    {
+        BD_p->Pass.TOS_TC           = BypassData_p[0] & MASK_8_BITS;
+        BD_p->Pass.fDF              = ((BypassData_p[0] & BIT_8) != 0);
+        BD_p->Pass.NextHeaderOffset = (BypassData_p[0] >> 8) & MASK_16_BITS;
+        BD_p->Pass.HdrProcCtxRef    = BypassData_p[1];
+    }
+    else
+    {
+        IDENTIFIER_NOT_USED(BypassData_p);
+        IDENTIFIER_NOT_USED(BypassWordCount);
+        IDENTIFIER_NOT_USED(BD_p);
+    }
+}
+
+
+/* end of file eip202_rd_format.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_dscr.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_dscr.c
new file mode 100644
index 0000000..831a486
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_dscr.c
@@ -0,0 +1,735 @@
+/* eip202_rdr_dscr.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * 1) Descriptor I/O Driver Library API implementation
+ * 2) Internal Result Descriptor interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// Descriptor I/O Driver Library API implementation
+#include "eip202_rdr.h"
+
+// Internal Result Descriptor interface
+#include "eip202_rdr_dscr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_rdr_level0.h"         // EIP-202 Level 0 macros
+#include "eip202_rdr_fsm.h"             // RDR State machine
+#include "eip202_rd_format.h"           // RD Format API
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"         // types of the DMA resource API
+#include "dmares_rw.h"            // read/write of the DMA resource API.
+
+// Standard IOToken API
+#include "iotoken.h"
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// EIP-202 HW limit for the number of packets to acknowledge at once
+#define EIP202_RING_MAX_RD_PACKET_COUNT      127
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_RDR_Prepared_FillLevel_Get
+ */
+static EIP202_Ring_Error_t
+EIP202Lib_RDR_Prepared_FillLevel_Get(
+        const Device_Handle_t Device,
+        volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p,
+        unsigned int * const FillLevelDscrCount_p)
+{
+    unsigned int RDWordCount;
+    EIP202_Ring_Error_t rv;
+
+    EIP202_RDR_PREP_COUNT_RD(Device, (uint32_t*)&RDWordCount);
+
+    // Remain in the current state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_RDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    *FillLevelDscrCount_p = RDWordCount /
+                            (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    if(RDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        (*FillLevelDscrCount_p)++;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_RDR_Processed_FillLevel_Finalize
+ */
+static EIP202_Ring_Error_t
+EIP202Lib_RDR_Processed_FillLevel_Finalize(
+        const unsigned int RDWordCount,
+        const unsigned int PktCount,
+        volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p,
+        unsigned int * const FillLevelDscrCount_p,
+        unsigned int * const FillLevelPktCount_p)
+{
+#ifdef EIP202_RING_DEBUG_FSM
+    EIP202_Ring_Error_t rv;
+
+    if(RDWordCount == 0)
+        // CD Ring is empty
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                EIP202_RDR_STATE_INITIALIZED);
+    else if(RDWordCount > 0 &&
+            RDWordCount < (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        // CD Ring is free
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_RDR_STATE_FREE);
+    else if(RDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
+        // CD Ring is full
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_RDR_STATE_FULL);
+    else
+        rv = EIP202_RING_ILLEGAL_IN_STATE;
+
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+#endif
+
+    *FillLevelDscrCount_p = RDWordCount /
+                            (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    *FillLevelPktCount_p = PktCount;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+  Internal Result Descriptor interface
+  ---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_WriteCB
+ */
+int
+EIP202_RDR_WriteCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        const unsigned int WriteIndex,
+        const unsigned int WriteCount,
+        const unsigned int TotalWriteLimit,
+        const void * Descriptors_p,
+        const int DescriptorCount,
+        const unsigned int DescriptorSkipCount)
+{
+    Device_Handle_t Device;
+    unsigned int i, DescOffsetWordCount;
+    unsigned int nWritten = 0;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p =
+                                            RDRIOAREA(CallbackParam1_p);
+    if(CallbackParam1_p == NULL || Descriptors_p == NULL)
+        return -1;
+
+    IDENTIFIER_NOT_USED(CallbackParam2);
+    IDENTIFIER_NOT_USED(DescriptorCount);
+    IDENTIFIER_NOT_USED(TotalWriteLimit);
+
+    Device = TrueIOArea_p->Device;
+
+    DescOffsetWordCount = (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    // Write descriptors to RDR
+    for(i = WriteIndex; i < WriteIndex + WriteCount; i++)
+    {
+        EIP202_Prepared_Write(
+            TrueIOArea_p->RingHandle,
+            i * DescOffsetWordCount,
+            ((const EIP202_ARM_PreparedDescriptor_t *)Descriptors_p) +
+                    DescriptorSkipCount + nWritten);
+
+        nWritten++;
+    }
+
+    if (nWritten > 0)
+    {
+        // Call PreDMA to prepared descriptors in Ring DMA buffer for handover
+        // to the Device (the EIP-202 DMA Master)
+        DMAResource_PreDMA(TrueIOArea_p->RingHandle,
+                           WriteIndex *
+                              DescOffsetWordCount *
+                               (unsigned int)sizeof(uint32_t),
+                           nWritten *
+                             DescOffsetWordCount *
+                               (unsigned int)sizeof(uint32_t));
+
+        // CDS point: hand over written Prepared Descriptors to the Device
+        EIP202_RDR_PREP_COUNT_WR(Device,
+                                 (uint16_t)(nWritten * DescOffsetWordCount),
+                                 false);
+    }
+
+    return (int)nWritten;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_ReadCB
+ */
+int
+EIP202_RDR_ReadCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        const unsigned int ReadIndex,
+        const unsigned int ReadLimit,
+        void * Descriptors_p,
+        const unsigned int DescriptorSkipCount)
+{
+    Device_Handle_t Device;
+    unsigned int i, DescOffsetWordCount;
+    bool fGotDescriptor, fLastSegment = false, fFirstSegment = false;
+    unsigned int GotDscrCount = 0, GotPktCount = 0;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p =
+                                       RDRIOAREA(CallbackParam1_p);
+
+    if(CallbackParam1_p == NULL || Descriptors_p == NULL)
+        return -1;
+
+    IDENTIFIER_NOT_USED(CallbackParam2);
+
+    Device = TrueIOArea_p->Device;
+
+    DescOffsetWordCount = (unsigned int )TrueIOArea_p->DescOffsWordCount;
+
+    // Read descriptors from RDR
+    for(i = ReadIndex; i < ReadIndex + ReadLimit; i++)
+    {
+        EIP202_ARM_ResultDescriptor_t * CurrentResultDesc_p =
+            ((EIP202_ARM_ResultDescriptor_t *)Descriptors_p) +
+                    DescriptorSkipCount + GotDscrCount;
+
+#define EIP202_RING_RDR_ALL_DESCRIPTORS_TO_GET_DONE             \
+         (TrueIOArea_p->AcknowledgedRDCount + GotDscrCount >=  \
+              TrueIOArea_p->RDToGetCount)
+
+// This can be true only if the PktRequestedCount parameter in
+// the EIP202_RDR_Descriptor_Get() function is set to a non-zero value
+#define EIP202_RING_RDR_ALL_PACKETS_TO_GET_DONE                 \
+         (TrueIOArea_p->PktToGetCount > 0 &&                   \
+          TrueIOArea_p->AcknowledgedPktCount + GotPktCount >=  \
+              TrueIOArea_p->PktToGetCount)
+
+        // Stop reading the descriptors if all the requested
+        // descriptors and packet chains have been read
+        if(EIP202_RING_RDR_ALL_PACKETS_TO_GET_DONE)
+        {
+            if(EIP202_RING_RDR_ALL_DESCRIPTORS_TO_GET_DONE)
+                break; // for
+        }
+
+        // Call PostDMA before reading descriptors from
+        // the EIP-202 DMA Master
+        DMAResource_PostDMA(TrueIOArea_p->RingHandle,
+                            i * DescOffsetWordCount *
+                              (unsigned int)sizeof(uint32_t),
+                            DescOffsetWordCount *
+                              (unsigned int)sizeof(uint32_t));
+
+        // Check if a processed result descriptor is received
+#if defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+        {
+            uint32_t OwnershipWord =
+                        DMAResource_Read32(TrueIOArea_p->RingHandle,
+                                           i * DescOffsetWordCount +
+                                                 DescOffsetWordCount - 1);
+            fGotDescriptor =
+                    (OwnershipWord == EIP202_RDR_OWNERSHIP_WORD_PATTERN);
+#ifdef EIP202_RING_BUS_KEEPALIVE_WORKAROUND
+            // Read from the device to solve a keep-alive problem in some
+            // bus environments.
+            Device_Read32(Device,0);
+#endif
+        }
+#elif defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS)
+        CurrentResultDesc_p->Token_p[IOToken_OutMarkOffset_Get()] =
+                DMAResource_Read32(TrueIOArea_p->RingHandle,
+                                   i * DescOffsetWordCount +
+                                   TrueIOArea_p->TokenOffsetWordCount +
+                                   IOToken_OutMarkOffset_Get());
+        fGotDescriptor = (IOToken_Mark_Check(CurrentResultDesc_p->Token_p) == 0);
+#else
+        fGotDescriptor = true; // according to EIP202_RDR_PROC_COUNT_RD()
+#endif
+
+        if (fGotDescriptor)
+        {
+            // Read Result Descriptor
+            EIP202_ReadDescriptor(CurrentResultDesc_p,
+                                  TrueIOArea_p->RingHandle,
+                                  i * DescOffsetWordCount,
+                                  DescOffsetWordCount,
+                                  TrueIOArea_p->TokenOffsetWordCount,
+                                  &fLastSegment,
+                                  &fFirstSegment);
+
+            // Stop reading the descriptors if all the requested
+            // packet chains have been read and a new processed packet descriptor
+            // chain is detected
+            if(fFirstSegment && EIP202_RING_RDR_ALL_PACKETS_TO_GET_DONE)
+                break; // for
+
+            if (fFirstSegment)
+                TrueIOArea_p->PacketFound = true;
+
+            GotDscrCount++;
+
+            if(TrueIOArea_p->PacketFound && fLastSegment)
+            {
+                GotPktCount++;
+                TrueIOArea_p->PacketFound = false;
+            }
+
+#if defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS) || \
+    defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+            // Clear this descriptor
+            EIP202_ClearDescriptor(CurrentResultDesc_p,
+                                   TrueIOArea_p->RingHandle,
+                                   i * DescOffsetWordCount,
+                                   TrueIOArea_p->TokenOffsetWordCount,
+                                   DescOffsetWordCount);
+
+            // Ensure next PostDMA does not undo the clear operation above
+            DMAResource_PreDMA(
+                TrueIOArea_p->RingHandle,
+                i * DescOffsetWordCount * (unsigned int)sizeof(uint32_t),
+                DescOffsetWordCount * (unsigned int)sizeof(uint32_t));
+#endif
+        }
+        else
+        {
+            // The fGotDescriptor is set in EIP202_ReadDescriptor() and
+            // depends on the Application ID field in the result descriptor
+            // when EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS is defined.
+            // In case of a packet descriptor chain the Engine writes the
+            // Application ID field for the last segment descriptor only
+            // but we need to acknowledge all the descriptors of the chain
+            break; // for
+        }
+    } // for
+
+    // Check if there are processed result descriptors and packets
+    // that must be acknowledged
+    if (GotDscrCount > 0)
+    {
+        unsigned int NewGotPktCount;
+
+#if EIP202_RING_RD_INTERRUPTS_PER_PACKET_FLAG != 1
+        GotPktCount = 0;
+#endif
+
+        // EIP-202 HW limits the number of packets to acknowledge at once to
+        // EIP202_RING_MAX_RD_PACKET_COUNT packets
+        NewGotPktCount = MIN(GotPktCount, EIP202_RING_MAX_RD_PACKET_COUNT);
+
+        // CDS point: hand over read Result Descriptors to the Device
+        EIP202_RDR_PROC_COUNT_WR(
+                Device,
+                (uint16_t)(GotDscrCount * DescOffsetWordCount),
+                (uint8_t)NewGotPktCount,
+                false);
+    }
+
+    // Update acknowledged packets counter
+    TrueIOArea_p->AcknowledgedPktCount += GotPktCount;
+
+    // Update acknowledged descriptors counter
+    TrueIOArea_p->AcknowledgedRDCount += GotDscrCount;
+
+    return (int)GotDscrCount;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_StatusCB
+ */
+int
+EIP202_RDR_StatusCB(
+        void * const CallbackParam1_p,
+        const int CallbackParam2,
+        int * const DeviceReadPos_p)
+{
+    IDENTIFIER_NOT_USED(CallbackParam1_p);
+    IDENTIFIER_NOT_USED(CallbackParam2);
+
+    *DeviceReadPos_p = -1;  // not used
+
+    return 0;
+}
+
+
+/*----------------------------------------------------------------------------
+  Descriptor I/O Driver Library API implementation
+  ---------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_FillLevel_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_FillLevel_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    int FillLevel;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    FillLevel = RingHelper_FillLevel_Get(
+            (volatile RingHelper_t*)&TrueIOArea_p->RingHelper);
+
+    if(FillLevel < 0)
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+    else
+    {
+        *FillLevelDscrCount_p = (unsigned int)FillLevel;
+        return EIP202_RING_NO_ERROR;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Prepared_FillLevel_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Prepared_FillLevel_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    Device_Handle_t Device;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    Device = TrueIOArea_p->Device;
+
+    return EIP202Lib_RDR_Prepared_FillLevel_Get(Device,
+                                               TrueIOArea_p,
+                                               FillLevelDscrCount_p);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Write_Prepared_ControlWord
+ *
+ * This helper function returns the control word that can be written to
+ * the logical prepared descriptor.
+ *
+ * This function is re-entrant.
+ *
+ */
+uint32_t
+EIP202_RDR_Write_Prepared_ControlWord(
+        const EIP202_RDR_Prepared_Control_t * const  PreparedCtrl_p)
+{
+    return EIP202_RD_Make_ControlWord(PreparedCtrl_p->ExpectedResultWordCount,
+                                     PreparedCtrl_p->PrepSegmentByteCount,
+                                     PreparedCtrl_p->fFirstSegment,
+                                     PreparedCtrl_p->fLastSegment);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Descriptor_Prepare
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Descriptor_Prepare(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const EIP202_ARM_PreparedDescriptor_t * PreparedDscr_p,
+        const unsigned int DscrRequestedCount,
+        unsigned int * const DscrPreparedCount_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    int res, FillLevel;
+    unsigned int RDWordCount, RDFreeCount, DscrNewRequestedCount;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(PreparedDscr_p);
+    EIP202_RING_CHECK_POINTER(DscrPreparedCount_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    // Check how many more descriptors can be added (prepared) to RDR
+    FillLevel = RingHelper_FillLevel_Get(
+            (volatile RingHelper_t*)&TrueIOArea_p->RingHelper);
+    if(FillLevel < 0)
+        return EIP202_RING_ARGUMENT_ERROR; // Error, RDR admin corrupted
+
+    // Check if RDR is full
+    RDWordCount = ((unsigned int)FillLevel *
+            (unsigned int)TrueIOArea_p->DescOffsWordCount);
+    if(RDWordCount == (unsigned int)TrueIOArea_p->RingSizeWordCount)
+    {
+        // RD Ring is full
+        *FillLevelDscrCount_p = (unsigned int)FillLevel;
+        *DscrPreparedCount_p = 0;
+
+        // Remain in the current state
+        return EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                   (EIP202_RDR_State_t)TrueIOArea_p->State);
+    }
+
+    // Calculate the maximum number of descriptors that can be added to RDR
+    RDFreeCount =
+            ((unsigned int)TrueIOArea_p->RingSizeWordCount - RDWordCount) /
+                    (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    DscrNewRequestedCount = MIN(RDFreeCount, DscrRequestedCount);
+
+    res = RingHelper_Put((volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+                         PreparedDscr_p,
+                         (int)DscrNewRequestedCount);
+    if(res >= 0)
+        *DscrPreparedCount_p = (unsigned int)res;
+    else
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Get the current RDR fill level
+    FillLevel = RingHelper_FillLevel_Get(
+            (volatile RingHelper_t*)&TrueIOArea_p->RingHelper);
+    if(FillLevel < 0)
+        return EIP202_RING_ARGUMENT_ERROR; // Error, RDR admin corrupted
+    else
+    {
+        *FillLevelDscrCount_p = (unsigned int)FillLevel;
+        return EIP202_RING_NO_ERROR;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Processed_FillLevel_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Processed_FillLevel_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        unsigned int * FillLevelDscrCount_p,
+        unsigned int * FillLevelPktCount_p)
+{
+// If configured then the driver cannot rely on the register counter
+#if defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS) || \
+    defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+    IDENTIFIER_NOT_USED(FillLevelDscrCount_p);
+    IDENTIFIER_NOT_USED(FillLevelPktCount_p);
+    IDENTIFIER_NOT_USED(IOArea_p);
+
+    return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+#else
+    Device_Handle_t Device;
+    unsigned int RDWordCount, PktCount;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+    EIP202_RING_CHECK_POINTER(FillLevelPktCount_p);
+
+    Device = TrueIOArea_p->Device;
+
+    {
+        uint8_t Value8;
+        uint32_t Value32;
+
+        EIP202_RDR_PROC_COUNT_RD(Device, &Value32, &Value8);
+
+        RDWordCount = (unsigned int)Value32;
+        PktCount = (unsigned int)Value8;
+    }
+
+    return EIP202Lib_RDR_Processed_FillLevel_Finalize(RDWordCount,
+                                                     PktCount,
+                                                     TrueIOArea_p,
+                                                     FillLevelDscrCount_p,
+                                                     FillLevelPktCount_p);
+#endif // EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Read_Processed_ControlWord
+ */
+void
+EIP202_RDR_Read_Processed_ControlWord(
+        EIP202_ARM_ResultDescriptor_t * const  ResDscr_p,
+        EIP202_RDR_Result_Control_t * const RDControl_p,
+        EIP202_RDR_Result_Token_t * const ResToken_p)
+{
+    IDENTIFIER_NOT_USED(ResToken_p);
+
+    EIP202_RD_Read_ControlWord(ResDscr_p->ProcControlWord,
+                               NULL,
+                               RDControl_p,
+                               NULL);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Read_Processed_BypassData
+ */
+void
+EIP202_RDR_Read_Processed_BypassData(
+        const EIP202_RDR_Result_Token_t * const  ResToken_p,
+        EIP202_RDR_BypassData_t * const BD_p)
+{
+    EIP202_RD_Read_BypassData(ResToken_p->BypassData_p,
+                              ResToken_p->BypassWordCount,
+                              BD_p);
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Descriptor_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Descriptor_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_ARM_ResultDescriptor_t * ResultDscr_p,
+        const unsigned int PktRequestedCount,
+        const unsigned int DscrRequestedCount,
+        unsigned int * const DscrDoneCount_p,
+        unsigned int * FillLevelDscrCount_p)
+{
+    Device_Handle_t Device;
+    int res;
+    unsigned int RDWordCount, ProcDsrcCount, ProcPktCount;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(ResultDscr_p);
+    EIP202_RING_CHECK_POINTER(DscrDoneCount_p);
+    EIP202_RING_CHECK_POINTER(FillLevelDscrCount_p);
+
+    if(DscrRequestedCount == 0)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    // Check how many descriptors can be obtained
+    {
+        uint8_t Value8;
+        uint32_t Value32;
+
+#ifdef EIP202_RDR_OWNERSHIP_WORD_ENABLE
+        Value32 = MIN(PktRequestedCount, DscrRequestedCount);
+        Value8  = MIN(EIP202_RING_MAX_RD_PACKET_COUNT, Value32);
+        Value32 = Value8 * TrueIOArea_p->DescOffsWordCount;
+        IDENTIFIER_NOT_USED(Device);
+#else
+        EIP202_RDR_PROC_COUNT_RD(Device, &Value32, &Value8);
+#endif
+        RDWordCount = (unsigned int)Value32;
+        ProcPktCount = (unsigned int)Value8;
+    }
+
+    // Check if RDR is empty or
+    // if RDR has no fully processed packet descriptor chain
+    if(RDWordCount == 0 ||
+       (PktRequestedCount != 0 && ProcPktCount == 0))
+    {
+        // Nothing to do
+        *FillLevelDscrCount_p = 0;
+        *DscrDoneCount_p = 0;
+
+        return EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                   EIP202_RDR_STATE_INITIALIZED);
+    }
+
+    ProcDsrcCount = RDWordCount /
+                    (unsigned int)TrueIOArea_p->DescOffsWordCount;
+
+    TrueIOArea_p->AcknowledgedRDCount = 0;
+    TrueIOArea_p->AcknowledgedPktCount = 0;
+    TrueIOArea_p->RDToGetCount = MIN(ProcDsrcCount, DscrRequestedCount);
+    TrueIOArea_p->PktToGetCount = MIN(ProcPktCount, PktRequestedCount);
+
+    // Get processed (result) descriptors
+    res = RingHelper_Get((volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+// If configured then the driver cannot rely on the register counter
+#if defined(EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS) || \
+    defined(EIP202_RDR_OWNERSHIP_WORD_ENABLE)
+                         -1, // Certainly available RD count unknown
+#else
+                         (int)TrueIOArea_p->RDToGetCount,
+#endif // EIP202_RING_ANTI_DMA_RACE_CONDITION_CDS
+                         ResultDscr_p,
+                         (int)DscrRequestedCount);
+    if(res >= 0)
+        *DscrDoneCount_p = (unsigned int)res;
+    else
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Increase the fill level by the number of successfully got descriptors
+    RDWordCount -= ((unsigned int)res *
+                         (unsigned int)TrueIOArea_p->DescOffsWordCount);
+
+    // Increase the fill level by the number of acknowledged packets
+    ProcPktCount -= TrueIOArea_p->AcknowledgedPktCount;
+
+    return EIP202Lib_RDR_Processed_FillLevel_Finalize(RDWordCount,
+                                                     ProcPktCount,
+                                                     TrueIOArea_p,
+                                                     FillLevelDscrCount_p,
+                                                     &ProcPktCount);
+}
+
+
+/* end of file eip202_rdr_dscr.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_event.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_event.c
new file mode 100644
index 0000000..6f6efc8
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_event.c
@@ -0,0 +1,230 @@
+/* eip202_rdr_event.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * CDR Event Management API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_rdr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_rdr_level0.h"         // EIP-202 Level 0 macros
+#include "eip202_rdr_fsm.h"             // RDR State machine
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Status_Get
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Status_Get(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_RDR_Status_t * const Status_p)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+    EIP202_RING_CHECK_POINTER(Status_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_RDR_PREP_COUNT_RD(Device, &Status_p->RDPrepWordCount);
+    EIP202_RDR_PROC_COUNT_RD(Device,
+                             &Status_p->RDProcWordCount,
+                             &Status_p->RDProcPktWordCount);
+
+    EIP202_RDR_STAT_RD(Device,
+                       &Status_p->fDMAError,
+                       &Status_p->fTresholdInt,
+                       &Status_p->fError,
+                       &Status_p->fOUFlowError,
+                       &Status_p->fTimeoutInt,
+                       &Status_p->fRDBufOverflowInt,
+                       &Status_p->fRDOverflowInt,
+                       &Status_p->RDFIFOWordCount);
+
+    // Transit to a new state
+    if(Status_p->fDMAError)
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                 EIP202_RDR_STATE_FATAL_ERROR);
+    else
+        // Remain in the current state
+        rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                                 (EIP202_RDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Processed_FillLevel_High_INT_Enable
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Processed_FillLevel_High_INT_Enable(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const unsigned int ThresholdDscrCount,
+        const unsigned int Timeout,
+        const bool fIntPerPacket)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    if(EIP202_RING_RD_INTERRUPTS_PER_PACKET_FLAG == 0 && fIntPerPacket)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    if (fIntPerPacket)
+    {
+        EIP202_RDR_THRESH_WR(Device,
+                             (uint32_t)ThresholdDscrCount,
+                             // Set packet processing mode,
+                             // e.g. interrupts per packet i.s.o. descriptor
+                             true,
+                             (uint8_t)Timeout);
+    }
+    else
+    {
+        EIP202_RDR_THRESH_WR(Device,
+                             (uint32_t)ThresholdDscrCount *
+                             TrueIOArea_p->DescOffsWordCount,
+                             // Set packet processing mode,
+                             // e.g. interrupts per packet i.s.o. descriptor
+                             false,
+                             (uint8_t)Timeout);
+    }
+
+#ifdef EIP202_CLUSTERED_WRITES_DISABLE
+    // Prevent clustered write operations, break them with a read operation
+    // Note: Reading the EIP202_RDR_RING_BASE_ADDR_LO register
+    //       has no side effects!
+    EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+#endif
+
+    // Remain in the current state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_RDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Processed_FillLevel_High_INT_ClearAndDisable
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Processed_FillLevel_High_INT_ClearAndDisable(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const bool fOvflIntOnly)
+{
+    Device_Handle_t Device;
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    if(fOvflIntOnly)
+    {
+        // Clear Descriptor and Buffer overflow interrupts
+        EIP202_RDR_STAT_CLEAR_DSCR_BUF_OFLO_IRQ_WR(Device);
+    }
+    else
+    {
+        // Disable Processed Descriptor threshold interrupt,
+        // Disable Timeout interrupt and stop timeout counter for
+        // reducing power consumption
+        EIP202_RDR_THRESH_WR(
+                           Device,
+                           TrueIOArea_p->RingSizeWordCount,
+                           0,  // Set descriptor processing mode
+                           0); // Disable timeout
+
+#ifdef EIP202_CLUSTERED_WRITES_DISABLE
+        // Prevent clustered write operations, break them with a read operation
+        // Note: Reading the EIP202_RDR_RING_BASE_ADDR_LO register
+        //       has no side effects!
+        EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+#endif
+
+        // Clear all RDR interrupts
+        EIP202_RDR_STAT_CLEAR_ALL_IRQ_WR(Device);
+
+#ifdef EIP202_CLUSTERED_WRITES_DISABLE
+        // Prevent clustered write operations, break them with a read operation
+        // Note: Reading the EIP202_RDR_RING_BASE_ADDR_LO register
+        //       has no side effects!
+        EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+#endif
+    }
+
+    // Remain in the current state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             (EIP202_RDR_State_t)TrueIOArea_p->State);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/* end of file eip202_rdr_event.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_fsm.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_fsm.c
new file mode 100644
index 0000000..a3fa0e5
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_fsm.c
@@ -0,0 +1,174 @@
+/* eip202_rdr_fsm.c
+ *
+ * EIP-202 Ring Control Driver Library API
+ * State Machine Internal Interface implementation for RDR
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_rdr_fsm.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"              // IDENTIFIER_NOT_USED
+
+// EIP-202 Ring Control Driver Library Types API
+#include "eip202_ring_types.h"        // EIP202_Ring_* types
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_State_Set
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_State_Set(
+        volatile EIP202_RDR_State_t * const CurrentState,
+        const EIP202_RDR_State_t NewState)
+{
+#ifdef EIP202_RING_DEBUG_FSM
+    switch(*CurrentState)
+    {
+        case EIP202_RDR_STATE_UNKNOWN:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+         case EIP202_RDR_STATE_UNINITIALIZED:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_INITIALIZED:
+                   *CurrentState = NewState;
+                   break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_RDR_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_RDR_STATE_FREE:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_RDR_STATE_FULL:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FREE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                case EIP202_RDR_STATE_FULL:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP202_RDR_STATE_FATAL_ERROR:
+            switch(NewState)
+            {
+                case EIP202_RDR_STATE_UNINITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP202_RING_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP202_RING_ILLEGAL_IN_STATE;
+    }
+#else
+    IDENTIFIER_NOT_USED(CurrentState);
+    IDENTIFIER_NOT_USED(NewState);
+#endif // EIP202_RING_DEBUG_FSM
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/* end of file eip202_rdr_fsm.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_init.c
new file mode 100644
index 0000000..6fd658c
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip202_rdr_init.c
@@ -0,0 +1,372 @@
+/* eip202_rdr_init.c
+ *
+ * EIP-202 Ring Control Driver Library
+ * RDR Init/Reset API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip202_rdr.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip202_ring.h"
+
+// EIP-202 Ring Control Driver Library Types API
+#include "eip202_ring_types.h"          // EIP202_Ring_* types
+
+// EIP-202 Ring Control Driver Library Internal interfaces
+#include "eip202_ring_internal.h"
+#include "eip202_rdr_level0.h"          // EIP-202 Level 0 macros
+#include "eip202_rdr_fsm.h"             // RDR State machine
+#include "eip202_rdr_dscr.h"            // RingHelper callbacks
+#include "eip202_rd_format.h"           // EIP-202 Result Descriptor
+
+// RingHelper API
+#include "ringhelper.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED, bool, uint32_t
+
+// Driver Framework Device API
+#include "device_types.h"              // Device_Handle_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"         // types of the DMA resource API
+#include "dmares_rw.h"            // read/write of the DMA resource API.
+
+// Driver Framework C Run-Time Library API
+#include "clib.h"
+
+// Standard IOToken API
+#include "iotoken.h"                   // IOToken_InWordCount_Get()
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_Detect
+ *
+ * Checks the presence of EIP-202 HIA hardware. Returns true when found.
+ */
+static bool
+EIP202Lib_RDR_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    // read-write test one of the registers
+
+    // Set MASK_31_BITS bits of the EIP202_RDR_RING_BASE_ADDR_LO register
+    EIP202_RDR_Write32(Device,
+                       EIP202_RDR_RING_BASE_ADDR_LO,
+                       MASK_31_BITS );
+
+    Value = EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+    if ((Value & MASK_31_BITS) != MASK_31_BITS)
+        return false;
+
+    // Clear MASK_31_BITS bits of the EIP202_RDR_RING_BASE_ADDR_LO register
+    EIP202_RDR_Write32(Device, EIP202_RDR_RING_BASE_ADDR_LO, 0);
+    Value = EIP202_RDR_Read32(Device, EIP202_RDR_RING_BASE_ADDR_LO);
+    if ((Value & MASK_31_BITS) != 0)
+       return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_RDR_ClearAllDescriptors
+ *
+ * Clear all descriptors
+ */
+static inline void
+EIP202Lib_RDR_ClearAllDescriptors(
+        DMAResource_Handle_t Handle,
+        const uint32_t DescriptorSpacingWordCount,
+        const uint32_t DescriptorSizeWordCount,
+        const uint32_t NumberOfDescriptors)
+{
+    unsigned int i, j;
+
+    for(i = 0; i < NumberOfDescriptors; i++)
+        for(j = 0; j < DescriptorSizeWordCount; j++)
+            DMAResource_Write32(Handle, i * DescriptorSpacingWordCount + j, 0);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Init
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Init(
+        EIP202_Ring_IOArea_t * IOArea_p,
+        const Device_Handle_t Device,
+        const EIP202_RDR_Settings_t * const RDRSettings_p)
+{
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+    TrueIOArea_p->State = (unsigned int)EIP202_RDR_STATE_UNINITIALIZED;
+
+    // Check if the CPU integer size is enough to store 32-bit value
+    if(sizeof(unsigned int) < sizeof(uint32_t))
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    // Detect presence of EIP-202 CDR hardware
+    if(!EIP202Lib_RDR_Detect(Device))
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    // Extension of 32-bit pointers to 64-bit addresses not supported.
+    if(RDRSettings_p->Params.DMA_AddressMode == EIP202_RING_64BIT_DMA_EXT_ADDR)
+        return EIP202_RING_UNSUPPORTED_FEATURE_ERROR;
+
+    if(RDRSettings_p->Params.DscrOffsWordCount == 0 ||
+       RDRSettings_p->Params.DscrOffsWordCount <
+       RDRSettings_p->Params.DscrSizeWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Ring size cannot be smaller than one descriptor size or
+    // larger than 4194303 (16MB / 4 - 1), in 32-bit words
+    if(RDRSettings_p->Params.RingSizeWordCount <
+       RDRSettings_p->Params.DscrOffsWordCount ||
+       RDRSettings_p->Params.RingSizeWordCount > 4194303)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if(RDRSettings_p->Params.DscrSizeWordCount >
+             RDRSettings_p->Params.TokenOffsetWordCount + IOToken_OutWordCount_Get())
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if(RDRSettings_p->Params.DscrFetchSizeWordCount %
+                            RDRSettings_p->Params.DscrOffsWordCount)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    if( RDRSettings_p->Params.IntThresholdDscrCount *
+            RDRSettings_p->Params.DscrOffsWordCount >
+                      RDRSettings_p->Params.RingSizeWordCount )
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Configure the Ring Helper
+    TrueIOArea_p->RingHelperCallbacks.WriteFunc_p = &EIP202_RDR_WriteCB;
+    TrueIOArea_p->RingHelperCallbacks.ReadFunc_p = &EIP202_RDR_ReadCB;
+    TrueIOArea_p->RingHelperCallbacks.StatusFunc_p = &EIP202_RDR_StatusCB;
+    TrueIOArea_p->RingHelperCallbacks.CallbackParam1_p = IOArea_p;
+    TrueIOArea_p->RingHelperCallbacks.CallbackParam2 = 0;
+    TrueIOArea_p->RingHandle = RDRSettings_p->Params.RingDMA_Handle;
+    TrueIOArea_p->DescOffsWordCount = RDRSettings_p->Params.DscrOffsWordCount;
+    TrueIOArea_p->RingSizeWordCount = RDRSettings_p->Params.RingSizeWordCount;
+    TrueIOArea_p->TokenOffsetWordCount = RDRSettings_p->Params.TokenOffsetWordCount;
+    TrueIOArea_p->PacketFound = false;
+
+    // Initialize one RingHelper instance for one RDR instance
+    if( RingHelper_Init(
+         (volatile RingHelper_t*)&TrueIOArea_p->RingHelper,
+         (volatile RingHelper_CallbackInterface_t*)&TrueIOArea_p->RingHelperCallbacks,
+         false, // One RDR as combined rings
+         (unsigned int)(RDRSettings_p->Params.RingSizeWordCount /
+             RDRSettings_p->Params.DscrOffsWordCount),
+         (unsigned int)(RDRSettings_p->Params.RingSizeWordCount /
+             RDRSettings_p->Params.DscrOffsWordCount)) < 0)
+        return EIP202_RING_ARGUMENT_ERROR;
+
+    // Transit to a new state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             EIP202_RDR_STATE_INITIALIZED);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    // Prepare the RDR DMA buffer
+    // Initialize all descriptors with zero for RDR
+    EIP202Lib_RDR_ClearAllDescriptors(
+            TrueIOArea_p->RingHandle,
+            RDRSettings_p->Params.DscrOffsWordCount,
+            RDRSettings_p->Params.DscrSizeWordCount,
+            RDRSettings_p->Params.RingSizeWordCount /
+                 RDRSettings_p->Params.DscrOffsWordCount);
+
+    // Call PreDMA to make sure engine sees it
+    DMAResource_PreDMA(TrueIOArea_p->RingHandle,
+                       0,
+                       (unsigned int)(TrueIOArea_p->RingSizeWordCount*4));
+
+    EIP202_RDR_RING_BASE_ADDR_LO_WR(
+                       Device,
+                       RDRSettings_p->Params.RingDMA_Address.Addr);
+
+    EIP202_RDR_RING_BASE_ADDR_HI_WR(
+                       Device,
+                       RDRSettings_p->Params.RingDMA_Address.UpperAddr);
+
+    EIP202_RDR_RING_SIZE_WR(
+                       Device,
+                       RDRSettings_p->Params.RingSizeWordCount);
+
+    EIP202_RDR_DESC_SIZE_WR(
+                       Device,
+                       RDRSettings_p->Params.DscrSizeWordCount,
+                       RDRSettings_p->Params.DscrOffsWordCount,
+                       RDRSettings_p->Params.DMA_AddressMode == EIP202_RING_64BIT_DMA_DSCR_PTR);
+
+    EIP202_RDR_CFG_WR(Device,
+                      RDRSettings_p->Params.DscrFetchSizeWordCount,
+                      RDRSettings_p->Params.DscrThresholdWordCount,
+#ifdef EIP202_RDR_OWNERSHIP_WORD_ENABLE
+                      true);  // Ownership write mode
+#else
+                      RDRSettings_p->fContinuousScatter); // Normal mode, no ownership words are used.
+/* Always enable ownership words for continuous scatter */
+#endif
+
+    // Disable Processed Descriptor threshold interrupt,
+    // Disable Timeout interrupt and stop timeout counter for
+    // reducing power consumption
+    EIP202_RDR_THRESH_WR(
+                       Device,
+                       TrueIOArea_p->RingSizeWordCount,
+                       0,  // Set descriptor processing mode
+                       0); // Disable timeout
+
+    EIP202_RDR_DMA_CFG_WR(
+                       Device,
+                       (uint8_t)RDRSettings_p->Params.ByteSwap_Descriptor_Mask,
+                       (uint8_t)RDRSettings_p->Params.ByteSwap_Packet_Mask,
+
+                       // Bufferability control for DMA writes of
+                       EIP202_RING_RD_RES_BUF,  // result token
+                       EIP202_RING_RD_CTRL_BUF, // descriptor control words
+                       EIP202_RING_RD_OWN_BUF,  // ownership words
+
+                       EIP202_RING_RD_WR_CACHE_CTRL, // Write cache type control
+                       EIP202_RING_RD_RD_CACHE_CTRL, // Read cache type control
+                       EIP202_RING_RD_PROT_VALUE,
+                       EIP202_RING_DATA_PROT_VALUE,
+                       RDRSettings_p->fContinuousScatter|EIP202_RDR_PAD_TO_OFFSET); // Result descriptor padding
+/* Note: for continuous scatter: always set RDR_PAD_TO_OFFSET. */
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Reset
+ *
+ */
+EIP202_Ring_Error_t
+EIP202_RDR_Reset(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    EIP202_Ring_Error_t rv;
+    volatile EIP202_RDR_True_IOArea_t * const TrueIOArea_p = RDRIOAREA(IOArea_p);
+
+    EIP202_RING_CHECK_POINTER(IOArea_p);
+
+    // Initialize the IO Area
+    memset((void*)IOArea_p, 0, sizeof(*TrueIOArea_p));
+    TrueIOArea_p->Device = Device;
+    TrueIOArea_p->State = (unsigned int)EIP202_RDR_STATE_UNKNOWN;
+
+    // Transit to a new state
+    rv = EIP202_RDR_State_Set((volatile EIP202_RDR_State_t*)&TrueIOArea_p->State,
+                             EIP202_RDR_STATE_UNINITIALIZED);
+    if(rv != EIP202_RING_NO_ERROR)
+        return EIP202_RING_ILLEGAL_IN_STATE;
+
+    // Clear RDR count
+    EIP202_RDR_PREP_COUNT_WR(Device, 0, true);
+    EIP202_RDR_PROC_COUNT_WR(Device, 0, 0, true);
+
+    // Re-init RDR
+    EIP202_RDR_PREP_PNTR_DEFAULT_WR(Device);
+    EIP202_RDR_PROC_PNTR_DEFAULT_WR(Device);
+
+    // Restore default register values
+    EIP202_RDR_RING_BASE_ADDR_LO_DEFAULT_WR(Device);
+    EIP202_RDR_RING_BASE_ADDR_HI_DEFAULT_WR(Device);
+    EIP202_RDR_RING_SIZE_DEFAULT_WR(Device);
+    EIP202_RDR_DESC_SIZE_DEFAULT_WR(Device);
+    EIP202_RDR_CFG_DEFAULT_WR(Device);
+    EIP202_RDR_DMA_CFG_DEFAULT_WR(Device);
+    EIP202_RDR_THRESH_DEFAULT_WR(Device);
+
+    // Clear and disable all RDR interrupts
+    EIP202_RDR_STAT_CLEAR_ALL_IRQ_WR(Device);
+
+    return EIP202_RING_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202_RDR_Dump
+ *
+ */
+void
+EIP202_RDR_Dump(
+        EIP202_Ring_IOArea_t * const IOArea_p,
+        EIP202_RingAdmin_t * const RingAdmin_p)
+{
+    EIP202_RDR_True_IOArea_t * const TrueIOArea_p =
+                            (EIP202_RDR_True_IOArea_t * const)IOArea_p;
+
+    if(!TrueIOArea_p)
+        return;
+
+    if(!RingAdmin_p)
+        return;
+
+    RingAdmin_p->IN_Size           = TrueIOArea_p->RingHelper.IN_Size;
+    RingAdmin_p->IN_Tail           = TrueIOArea_p->RingHelper.IN_Tail;
+    RingAdmin_p->OUT_Size          = TrueIOArea_p->RingHelper.OUT_Size;
+    RingAdmin_p->OUT_Head          = TrueIOArea_p->RingHelper.OUT_Head;
+
+    RingAdmin_p->fSeparate         = TrueIOArea_p->RingHelper.fSeparate;
+
+    RingAdmin_p->DescOffsWordCount = TrueIOArea_p->DescOffsWordCount;
+    RingAdmin_p->RingSizeWordCount = TrueIOArea_p->RingSizeWordCount;
+}
+
+
+/* end of file eip202_rdr_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_dtl.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_dtl.c
new file mode 100644
index 0000000..6cbdba3
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_dtl.c
@@ -0,0 +1,1837 @@
+/* eip207_flow_dtl.c
+ *
+ * Partial EIP-207 Flow Control Generic API implementation and
+ * full EIP-207 Flow Control DTL API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Driver Library Flow Control Generic API
+#include "eip207_flow_dtl.h"
+
+// EIP-207 Driver Library Flow Control Generic API
+#include "eip207_flow_generic.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_flow.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                       // ZEROINIT, memset, memcpy
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"
+#include "dmares_rw.h"
+
+// EIP-207 Flow Control Driver Library Internal interfaces
+#include "eip207_flow_level0.h"         // EIP-207 Level 0 macros
+#include "eip207_flow_hte_dscr_dtl.h"   // HTE descriptor DTL
+#include "eip207_flow_internal.h"
+
+#ifndef EIP207_FLUE_RC_HP
+// EIP-207 (Global Control) Record Cache (RC) interface
+#include "eip207_rc.h"
+
+// EIP-207s (Global Control) Flow Look-Up Engine Cache (FLUEC) interface
+#include "eip207_fluec.h"
+#endif // !EIP207_FLUE_RC_HP
+
+// EIP-207 Firmware API
+#include "firmware_eip207_api_flow_cs.h" // Classification API: Flow Control
+#include "firmware_eip207_api_cs.h"      // Classification API: General
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+#define EIP207_FLOW_MAX_RECORDS_PER_BUCKET              3
+
+
+// Flow record input data required for the flow record creation
+typedef struct
+{
+    // Bitwise of zero or more EIP207_FLOW_FLAG_* flags, see above
+    uint32_t Flags;
+
+    // Physical (DMA/bus) address of the transform record
+    EIP207_Flow_Address_t Xform_DMA_Addr;
+
+    // Software flow record reference
+    uint32_t SW_FR_Reference;
+
+    // Transform record type, true - large, false - small
+    bool fLarge;
+} EIP207_Flow_FR_Data_t;
+
+// Transform record input data required for the transform record creation
+typedef struct
+{
+    // Transform record type, true - large, false - small
+    bool fLarge;
+
+} EIP207_Flow_TR_Data_t;
+
+// Transform record input data required for the Transform record creation
+typedef struct
+{
+    // Record hash ID
+    const EIP207_Flow_ID_t * HashID_p;
+
+    // Flow record input data, fill with NULL if not used
+    const EIP207_Flow_FR_Data_t * FR_Data_p;
+
+    // Transform record input data, fill with NULL if not used
+    const EIP207_Flow_TR_Data_t * TR_Data_p;
+
+    // Note: FR_Data_p and TR_Data_p cannot be both NULL!
+
+} EIP207_Flow_Record_InputData_t;
+
+// Full record descriptor
+typedef struct
+{
+    EIP207_Flow_Dscr_t                  RecDscr;
+
+    EIP207_Flow_HTE_Dscr_RecData_t      RecData;
+
+    void *                              Reserved_p;
+} EIP207_Flow_Rec_Dscr_t;
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_Entry_Lookup
+ */
+static void
+EIP207Lib_Flow_Entry_Lookup(
+        const uint32_t HashID_Word0,
+        const uint32_t TableSize,
+        unsigned int * const HT_Entry_ByteOffset,
+        unsigned int * const DT_Entry_Index)
+{
+    uint32_t HashID_W0, Mask;
+
+    // From the EIP-197 Programmer Manual:
+    // The hash engine completes the hash ID calculation and
+    // adds bits [(table_size+10):6] (with table_size coming from
+    // the FLUE_SIZE(_VM)_f register) of the hash ID, multiplied by 64,
+    // to the table base address given in the FLUE_HASHBASE(_VM)_f_* registers.
+
+    // Calculate the entry byte offset in the HT for this record
+    HashID_W0 = (HashID_Word0 & (~MASK_6_BITS));
+
+    Mask = (1 << (TableSize + 10 + 1)) - 1;
+
+    // Calculate the HT entry byte offset
+    *HT_Entry_ByteOffset = (unsigned int)(HashID_W0 & Mask);
+
+    // Translate the HT entry byte offset to the index in the HT
+    // HT entry size is one hash bucket (16 words = 64 bytes)
+    *DT_Entry_Index = (*HT_Entry_ByteOffset) >> 6; // divide by 64
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_TableSize_To_EntryCount
+ *
+ * Convert EIP207_Flow_HashTable_Entry_Count_t to a number
+ */
+static inline unsigned int
+EIP207Lib_Flow_TableSize_To_EntryCount(
+        const unsigned int TableSize)
+{
+    return (1 << (TableSize + 5));
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HTE_Dscr_ByteCount_Get
+ */
+static inline unsigned int
+EIP207Lib_Flow_HTE_Dscr_ByteCount_Get(void)
+{
+    return sizeof(EIP207_Flow_HTE_Dscr_t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_Record_Add
+ *
+ * Updates Hash ID and record offset in the hash bucket,
+ * first Hash ID then record byte offset
+ */
+static inline void
+EIP207Lib_Flow_HB_Record_Add(
+        const DMAResource_Handle_t HT_DMA_Handle,
+        const unsigned int HB_ByteOffset,
+        const unsigned int slot,
+        const uint32_t Rec_ByteOffset,
+        const uint32_t RecType,
+        const EIP207_Flow_ID_t * const HashID_p)
+{
+    unsigned int i;
+    unsigned int HB_WordOffset = HB_ByteOffset >> 2;
+
+    // Write record Hash ID words
+    for (i = 0; i < EIP207_FLOW_HASH_ID_WORD_COUNT; i++)
+        DMAResource_Write32(HT_DMA_Handle,
+                            HB_WordOffset +
+                             EIP207_FLOW_HB_HASH_ID_1_WORD_OFFSET + i +
+                             EIP207_FLOW_HASH_ID_WORD_COUNT * (slot - 1),
+                            HashID_p->Word32[i]);
+
+    // Write record offset
+    DMAResource_Write32(HT_DMA_Handle,
+                        HB_WordOffset +
+                        EIP207_FLOW_HB_REC_1_WORD_OFFSET + (slot - 1),
+                        Rec_ByteOffset | RecType);
+
+    // Perform pre-DMA for this hash bucket
+    DMAResource_PreDMA(HT_DMA_Handle,
+                       HB_ByteOffset,
+                       EIP207_FLOW_HT_ENTRY_WORD_COUNT *
+                         sizeof(uint32_t));
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_Record_Remove
+ *
+ * Updates Hash ID and record offset in the hash bucket,
+ * first record byte offset then Hash ID
+ */
+static inline void
+EIP207Lib_Flow_HB_Record_Remove(
+        const DMAResource_Handle_t HT_DMA_Handle,
+        const unsigned int HB_ByteOffset,
+        const unsigned int slot,
+        EIP207_Flow_ID_t * HashID_p)
+{
+    unsigned int i;
+    unsigned int HB_WordOffset = HB_ByteOffset >> 2;
+    EIP207_Flow_ID_t HashID;
+
+    // Write record offset
+    DMAResource_Write32(HT_DMA_Handle,
+                        HB_WordOffset +
+                        EIP207_FLOW_HB_REC_1_WORD_OFFSET + (slot - 1),
+                        EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+    // Read old record Hash ID words
+    for (i = 0; i < EIP207_FLOW_HASH_ID_WORD_COUNT; i++)
+        HashID.Word32[i] = DMAResource_Read32(
+                             HT_DMA_Handle,
+                             HB_WordOffset +
+                             EIP207_FLOW_HB_HASH_ID_1_WORD_OFFSET + i +
+                             EIP207_FLOW_HASH_ID_WORD_COUNT * (slot - 1));
+
+    // Write new record Hash ID words
+    for (i = 0; i < EIP207_FLOW_HASH_ID_WORD_COUNT; i++)
+    {
+        DMAResource_Write32(HT_DMA_Handle,
+                            HB_WordOffset +
+                             EIP207_FLOW_HB_HASH_ID_1_WORD_OFFSET + i +
+                             EIP207_FLOW_HASH_ID_WORD_COUNT * (slot - 1),
+                            HashID_p->Word32[i]);
+
+        // Store old record Hash ID words
+        HashID_p->Word32[i] = HashID.Word32[i];
+    }
+
+    // Perform pre-DMA for this hash bucket
+    DMAResource_PreDMA(HT_DMA_Handle,
+                       HB_ByteOffset,
+                       EIP207_FLOW_HT_ENTRY_WORD_COUNT *
+                         sizeof(uint32_t));
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_BuckOffs_Update
+ *
+ * Update bucket offset in the hash bucket (identified by HB_ByteOffset)
+ * by writing the Update_Value in there
+ */
+static inline void
+EIP207Lib_Flow_HB_BuckOffs_Update(
+        const DMAResource_Handle_t HT_DMA_Handle,
+        const unsigned int HB_ByteOffset,
+        const uint32_t Update_Value)
+{
+    unsigned int HB_WordOffset = HB_ByteOffset >> 2;
+
+    // Write record offset
+    DMAResource_Write32(HT_DMA_Handle,
+                        HB_WordOffset +
+                        EIP207_FLOW_HB_OVFL_BUCKET_WORD_OFFSET,
+                        Update_Value);
+
+    // Perform pre-DMA for this hash bucket
+    DMAResource_PreDMA(HT_DMA_Handle,
+                       HB_ByteOffset,
+                       EIP207_FLOW_HT_ENTRY_WORD_COUNT *
+                         sizeof(uint32_t));
+}
+
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_HashID_Match
+ *
+ * Checks if the hash bucket already contains this Hash ID
+ */
+static bool
+EIP207Lib_Flow_HB_HashID_Match(
+        const DMAResource_Handle_t HT_DMA_Handle,
+        const unsigned int HB_ByteOffset,
+        const uint32_t RecType,
+        const EIP207_Flow_ID_t * const HashID_p)
+{
+    uint32_t Word32;
+    bool fMatch;
+    unsigned int i, j;
+    unsigned int HB_WordOffset = HB_ByteOffset >> 2;
+
+    // Read Hash ID's from the bucket
+    // (this DMA resource is read-only for the FLUE device)
+    for (i = 0; i < EIP207_FLOW_HTE_BKT_NOF_REC_MAX; i++)
+    {
+        for (j = 0; j < EIP207_FLOW_HASH_ID_WORD_COUNT; j++)
+        {
+            fMatch = true;
+
+            Word32 = DMAResource_Read32(
+                                 HT_DMA_Handle,
+                                 HB_WordOffset +
+                                  EIP207_FLOW_HB_HASH_ID_1_WORD_OFFSET +
+                                    i * EIP207_FLOW_HASH_ID_WORD_COUNT + j);
+
+            if (Word32 != HashID_p->Word32[j])
+            {
+                fMatch = false;
+                break; // No match, skip this hash ID
+            }
+        } // for
+
+        if (fMatch)
+            break; // Matching Hash ID found, stop searching
+    } // for
+
+    if (fMatch)
+    {
+        uint32_t Match_RecType;
+
+        // Check the record type in the record offset for Hash ID with index i
+        // to confirm the match
+        Word32 = DMAResource_Read32(
+                             HT_DMA_Handle,
+                             HB_WordOffset +
+                              EIP207_FLOW_HB_REC_1_WORD_OFFSET + i);
+
+        // Note: small transform record and large transform record
+        //       fall under the same record type for this check!
+        Match_RecType = Word32 & RecType;
+
+        if ((Match_RecType == EIP207_FLOW_RECORD_FR_ADDRESS  &&
+             (RecType == EIP207_FLOW_RECORD_TR_ADDRESS         ||
+              RecType == EIP207_FLOW_RECORD_TR_LARGE_ADDRESS))    ||
+
+            (RecType == EIP207_FLOW_RECORD_FR_ADDRESS        &&
+             (Match_RecType == EIP207_FLOW_RECORD_TR_ADDRESS   ||
+              Match_RecType == EIP207_FLOW_RECORD_TR_LARGE_ADDRESS)))
+        {
+            // Match not confirmed, a different record type is used
+            fMatch = false;
+        }
+    }
+
+    return fMatch;
+}
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_Slot_Get
+ *
+ * Determine the free offset slot number (1,2 or 3) and claim it
+ */
+static inline EIP207_Flow_Error_t
+EIP207Lib_Flow_HB_Slot_Get(
+        uint32_t * const RecOffsMask_p,
+        unsigned int * FreeSlot_p)
+{
+    if ((*RecOffsMask_p & EIP207_FLOW_HTE_REC_OFFSET_1) == 0)
+    {
+        *FreeSlot_p = 1;
+        *RecOffsMask_p |= EIP207_FLOW_HTE_REC_OFFSET_1;
+    }
+    else if((*RecOffsMask_p & EIP207_FLOW_HTE_REC_OFFSET_2) == 0)
+    {
+        *FreeSlot_p = 2;
+        *RecOffsMask_p |= EIP207_FLOW_HTE_REC_OFFSET_2;
+    }
+    else if((*RecOffsMask_p & EIP207_FLOW_HTE_REC_OFFSET_3) == 0)
+    {
+        *FreeSlot_p = 3;
+        *RecOffsMask_p |= EIP207_FLOW_HTE_REC_OFFSET_3;
+    }
+    else
+        // Consistency checks for the found HTE descriptor
+        return EIP207_FLOW_INTERNAL_ERROR;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_HB_Slot_Put
+ *
+ * Determine the used offset slot number (1,2 or 3) and release it
+ */
+static inline EIP207_Flow_Error_t
+EIP207Lib_Flow_HB_Slot_Put(
+        uint32_t * const RecOffsMask_p,
+        const unsigned int Slot)
+{
+    switch (Slot)
+    {
+        case 1:
+            *RecOffsMask_p &= ~EIP207_FLOW_HTE_REC_OFFSET_1;
+            break;
+
+        case 2:
+            *RecOffsMask_p &= ~EIP207_FLOW_HTE_REC_OFFSET_2;
+            break;
+
+        case 3:
+            *RecOffsMask_p &= ~EIP207_FLOW_HTE_REC_OFFSET_3;
+            break;
+
+        default:
+            // Consistency checks for the slot to release
+            return EIP207_FLOW_INTERNAL_ERROR;
+    }
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_Dscr_InternalData_Set
+ */
+static inline void
+EIP207Lib_Flow_Dscr_InternalData_Set(
+        EIP207_Flow_Dscr_t * const Dscr_p)
+{
+    EIP207_Flow_Rec_Dscr_t * p = (EIP207_Flow_Rec_Dscr_t*)Dscr_p;
+
+    Dscr_p->InternalData_p = &p->RecData;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_FR_Write
+ */
+static void
+EIP207Lib_Flow_FR_Write(
+        const DMAResource_Handle_t DMA_Handle,
+        const EIP207_Flow_FR_Data_t * const FR_Data_p,
+        const uint32_t Xform_ByteOffset,
+        const uint32_t Xform_Addr,
+        const uint32_t Xform_UpperAddr)
+{
+    unsigned int i;
+    uint32_t Record_Type;
+
+    // Write flow record with 0's
+    for (i = 0; i < FIRMWARE_EIP207_CS_FRC_RECORD_WORD_COUNT; i++)
+        DMAResource_Write32(DMA_Handle, i, 0);
+
+#ifdef EIP207_FLOW_NO_TYPE_BITS_IN_FLOW_RECORD
+    Record_Type = 0;
+#else
+    Record_Type = FR_Data_p->fLarge ?
+        EIP207_FLOW_RECORD_TR_LARGE_ADDRESS :
+        EIP207_FLOW_RECORD_TR_ADDRESS;
+#endif
+
+    // Write Transform Record 32-bit offset
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_XFORM_OFFS_WORD_OFFSET,
+                        Xform_ByteOffset + Record_Type);
+
+    // Write Transform Record low half of 64-bit address
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_XFORM_ADDR_WORD_OFFSET,
+                        Xform_Addr + Record_Type);
+
+    // Write Transform Record high half of 64-bit address
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_XFORM_ADDR_HI_WORD_OFFSET,
+                        Xform_UpperAddr);
+
+    // Not supported yet
+    // Write ARC4 State Record physical address
+    //DMAResource_Write32(FR_Dscr_p->Data.DMA_Handle,
+    //                    FIRMWARE_EIP207_CS_FLOW_FR_ARC4_ADDR_WORD_OFFSET,
+    //                    EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+    // Write Software Flow Record Reference
+    // NOTE: this is a 32-bit value!
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_SW_ADDR_WORD_OFFSET,
+                        FR_Data_p->SW_FR_Reference);
+
+    // Write the Flags field
+    DMAResource_Write32(DMA_Handle,
+                        FIRMWARE_EIP207_CS_FLOW_FR_FLAGS_WORD_OFFSET,
+                        FR_Data_p->Flags);
+
+    // Perform pre-DMA for the entire flow record
+    DMAResource_PreDMA(DMA_Handle, 0, 0);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_DTL_Record_Add
+ */
+static EIP207_Flow_Error_t
+EIP207Lib_Flow_DTL_Record_Add(
+        volatile EIP207_Flow_HT_Params_t * const HT_Params_p,
+        EIP207_Flow_Dscr_t * const Rec_Dscr_p,
+        const EIP207_Flow_Record_InputData_t * const RecData_p)
+{
+    uint32_t Rec_ByteOffset;
+    unsigned int slot = 0;
+    EIP207_Flow_HTE_Dscr_t * HTE_Dscr_Updated_p = NULL;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+    // Consistency check for the provided record descriptor
+    if (Rec_Dscr_p->DMA_Addr.Addr == EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+    // Add the record to the Hash Table
+    {
+        EIP207_Flow_HTE_Dscr_t * HTE_Dscr_p;
+        unsigned int Entry_Index, HTE_ByteOffset, HT_TableSize;
+        uint32_t Record_Type = EIP207_FLOW_RECORD_DUMMY_ADDRESS;
+        DMAResource_Handle_t HT_DMA_Handle = HT_Params_p->HT_DMA_Handle;
+
+        // Transform record
+        if (RecData_p->TR_Data_p != NULL)
+            Record_Type = RecData_p->TR_Data_p->fLarge ?
+                            EIP207_FLOW_RECORD_TR_LARGE_ADDRESS :
+                                       EIP207_FLOW_RECORD_TR_ADDRESS;
+        // Flow record
+        else if (RecData_p->FR_Data_p != NULL)
+            Record_Type = EIP207_FLOW_RECORD_FR_ADDRESS;
+        else
+            return EIP207_FLOW_INTERNAL_ERROR; // Unknown record, error
+
+        HT_TableSize = HT_Params_p->HT_TableSize;
+
+        HTE_ByteOffset  = 0;
+        Entry_Index     = 0;
+
+        EIP207Lib_Flow_Entry_Lookup(
+                RecData_p->HashID_p->Word32[0], // Word 0 is used for lookup
+                HT_TableSize,
+                &HTE_ByteOffset,
+                &Entry_Index);
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+        {
+            unsigned int HT_EntryCount =
+                    EIP207Lib_Flow_TableSize_To_EntryCount(HT_TableSize);
+
+            if (Entry_Index >= HT_EntryCount)
+                return EIP207_FLOW_INTERNAL_ERROR;
+        }
+#endif
+
+        // Calculate the record byte offset,
+        // HT_Params_p->BaseAddr.Addr is the base
+        // address of the DMA bank where the record
+        // must have been allocated
+        Rec_ByteOffset = Rec_Dscr_p->DMA_Addr.Addr - HT_Params_p->BaseAddr.Addr;
+
+        // Convert the DT entry index to the HTE descriptor pointer
+        {
+            void * p;
+            unsigned char * DT_p = (unsigned char*)HT_Params_p->DT_p;
+
+            // Read the entry value at the calculated offset from the DT
+            p = DT_p + Entry_Index * EIP207Lib_Flow_HTE_Dscr_ByteCount_Get();
+
+            HTE_Dscr_p = (EIP207_Flow_HTE_Dscr_t*)p;
+        }
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+        // Consistency checks for the found HTE descriptor
+        if (HTE_Dscr_p->Bucket_ByteOffset != (uint32_t)HTE_ByteOffset)
+            return EIP207_FLOW_INTERNAL_ERROR;
+
+        // Check that this HTE is not an overflow one
+        if (HTE_Dscr_p->fOverflowBucket)
+            return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+        do // Walk the bucket chain, look for bucket where record can be added
+        {
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+            if (HTE_Dscr_p->RecordCount > EIP207_FLOW_MAX_RECORDS_PER_BUCKET)
+                return EIP207_FLOW_INTERNAL_ERROR;
+
+            // Check if the hash bucket does not contain this Hash ID already
+            if (HTE_Dscr_Updated_p == NULL && EIP207Lib_Flow_HB_HashID_Match(
+                     HT_DMA_Handle,
+                     HTE_Dscr_p->Bucket_ByteOffset,
+                     Record_Type,
+                     RecData_p->HashID_p))
+                return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+            // Check if the found hash bucket can be used to add
+            // the record or a next bucket in the chain must be used
+            if (HTE_Dscr_p->RecordCount < EIP207_FLOW_MAX_RECORDS_PER_BUCKET)
+            {
+                uint32_t TempMask = HTE_Dscr_p->UsedRecOffsMask;
+                uint32_t TempSlot = slot;
+
+                // Use the found bucket to add the record
+
+                // Determine the offset slot (1,2 or 3) where the record offset
+                // and Hash ID can be stored
+                {
+                    EIP207_Flow_Error_t Flow_Rc =
+                            EIP207Lib_Flow_HB_Slot_Get(
+                                    &TempMask,
+                                    &TempSlot);
+
+                    if(Flow_Rc != EIP207_FLOW_NO_ERROR)
+                        return Flow_Rc;
+                }
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                // Check if the record offset in the HTE slot is a dummy pointer
+                {
+                    // Read record offset
+                    // (this DMA resource is read-only for the FLUE device)
+                    uint32_t Record_ByteOffset =
+                                DMAResource_Read32(
+                                         HT_DMA_Handle,
+                                         (HTE_Dscr_p->Bucket_ByteOffset >> 2) +
+                                           EIP207_FLOW_HB_REC_1_WORD_OFFSET +
+                                            (TempSlot - 1));
+
+                    if ((Record_ByteOffset &
+                         EIP207_FLOW_RECORD_ADDRESS_TYPE_BITS) !=
+                            EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+                        return EIP207_FLOW_INTERNAL_ERROR;
+                }
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+                // Add the record only if it has not been done already
+                if (HTE_Dscr_Updated_p == NULL)
+                {
+                    HTE_Dscr_p->UsedRecOffsMask = TempMask;
+                    slot = TempSlot;
+
+                    // If flow record is added then write it
+                    if (RecData_p->FR_Data_p != NULL)
+                        EIP207Lib_Flow_FR_Write(
+                                 Rec_Dscr_p->DMA_Handle,
+                                 RecData_p->FR_Data_p,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.Addr -
+                                 HT_Params_p->BaseAddr.Addr,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.Addr,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.UpperAddr);
+
+                    // Update the found hash bucket with the
+                    // record Hash ID and offset
+
+                    // CDS point: after this operation is done the FLUE
+                    //            hardware can find the transform record!
+                    EIP207Lib_Flow_HB_Record_Add(HT_DMA_Handle,
+                                             HTE_Dscr_p->Bucket_ByteOffset,
+                                             slot,
+                                             Rec_ByteOffset,
+                                             Record_Type,
+                                             RecData_p->HashID_p);
+
+                    // Increase the HTE descriptor record count
+                    // for the added record
+                    HTE_Dscr_p->RecordCount++;
+                }
+
+                // The found HTE is updated, record is added
+                if (HTE_Dscr_Updated_p == NULL)
+                    HTE_Dscr_Updated_p = HTE_Dscr_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                // Get the next HTE descriptor in the chain
+                HTE_Dscr_p = EIP207_Flow_HTE_Dscr_List_Next_Get(HTE_Dscr_p);
+                continue; // Validate the entire chain
+#else
+                break;
+#endif
+            }
+            else // Found bucket record count is max possible
+            {
+                EIP207_Flow_HTE_Dscr_t * HTE_Dscr_Next_p;
+
+                // Use a next overflow bucket to add the record, find a bucket
+                // in the chain with a free slot for the new record
+
+                // Get the next HTE descriptor in the chain
+                HTE_Dscr_Next_p =
+                           EIP207_Flow_HTE_Dscr_List_Next_Get(HTE_Dscr_p);
+
+                // Check if we have one and
+                // that the record has not been added already
+                if (HTE_Dscr_Next_p == NULL && HTE_Dscr_Updated_p == NULL)
+                {
+                    // No chain is present for HTE_Dscr_p.
+                    // Link a new HTE descriptor from the free list to
+                    // the found HTE descriptor
+
+                    EIP207_Flow_HTE_Dscr_t * FreeList_Head_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                    // Check if the overflow bucket offset is a dummy pointer
+                    {
+                        // Read the overflow bucket offset
+                        // (this DMA resource is read-only for the FLUE device)
+                        uint32_t Bucket_ByteOffset =
+                                DMAResource_Read32(
+                                    HT_DMA_Handle,
+                                    (HTE_Dscr_p->Bucket_ByteOffset >> 2) +
+                                      EIP207_FLOW_HB_OVFL_BUCKET_WORD_OFFSET);
+
+                        if (Bucket_ByteOffset !=
+                                EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+                            return EIP207_FLOW_INTERNAL_ERROR;
+                    }
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+                    FreeList_Head_p =
+                        (EIP207_Flow_HTE_Dscr_t*)HT_Params_p->FreeList_Head_p;
+
+                    // Check if the record can be added
+                    if (FreeList_Head_p == NULL)
+                        // Out of descriptors for overflow buckets
+                        return EIP207_FLOW_OUT_OF_MEMORY_ERROR;
+
+                    slot = 1; // start with slot 1 in the new bucket
+
+                    // Get a free HTE descriptor from the free list head
+                    HTE_Dscr_Next_p =
+                          EIP207_Flow_HTE_Dscr_List_Next_Get(FreeList_Head_p);
+
+                    // Check if the last descriptor is present in the free list
+                    if (HTE_Dscr_Next_p == NULL)
+                    {
+                        HTE_Dscr_Next_p = FreeList_Head_p;
+                        HT_Params_p->FreeList_Head_p = NULL; // List is empty
+                    }
+                    else
+                    {
+                        // Remove the got HTE descriptor from the free list
+                        EIP207_Flow_HTE_Dscr_List_Remove(HTE_Dscr_Next_p);
+                    }
+
+                    // Add the got HTE descriptor to the overflow chain,
+                    // we know that HTE_Dscr_p is the last descriptor
+                    // in the chain
+                    EIP207_Flow_HTE_Dscr_List_Next_Set(HTE_Dscr_p,
+                                                       HTE_Dscr_Next_p);
+                    EIP207_Flow_HTE_Dscr_List_Prev_Set(HTE_Dscr_Next_p,
+                                                       HTE_Dscr_p);
+
+                    // We add first record to the bucket which HTE descriptor
+                    // just fresh-taken from the free list
+                    HTE_Dscr_Next_p->UsedRecOffsMask =
+                                       EIP207_FLOW_HTE_REC_OFFSET_1;
+
+                    // If flow record is added then write it
+                    if (RecData_p->FR_Data_p != NULL)
+                        EIP207Lib_Flow_FR_Write(
+                                 Rec_Dscr_p->DMA_Handle,
+                                 RecData_p->FR_Data_p,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.Addr -
+                                 HT_Params_p->BaseAddr.Addr,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.Addr,
+                                 RecData_p->FR_Data_p->Xform_DMA_Addr.UpperAddr);
+
+                    // Update the overflow bucket with hash ID and record offset
+                    EIP207Lib_Flow_HB_Record_Add(HT_DMA_Handle,
+                                             HTE_Dscr_Next_p->Bucket_ByteOffset,
+                                             slot,
+                                             Rec_ByteOffset,
+                                             Record_Type,
+                                             RecData_p->HashID_p);
+
+                    // CDS point: after the next write32() operation is done
+                    //            the FLUE HW can find the overflow bucket!
+
+                    // Update bucket offset to the found bucket
+                    // Note: bucket offset can use any address (pointer) type
+                    //       but not NULL!
+                    EIP207Lib_Flow_HB_BuckOffs_Update(
+                                           HT_DMA_Handle,
+                                           HTE_Dscr_p->Bucket_ByteOffset,
+                                           HTE_Dscr_Next_p->Bucket_ByteOffset |
+                                             EIP207_FLOW_RECORD_TR_ADDRESS);
+
+                    // Increment record count for the added record
+                    HTE_Dscr_Next_p->RecordCount++;
+
+                    // Bucket is updated, record is added
+                    if (HTE_Dscr_Updated_p == NULL)
+                        HTE_Dscr_Updated_p = HTE_Dscr_Next_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                    HTE_Dscr_p = HTE_Dscr_Next_p;
+                    continue; // Validate the entire chain
+#else
+                    break;
+#endif
+                }
+                else // Overflow chain is present for the found HTE_Dscr_p
+                {
+                    // HTE_Dscr_p - last found HTE descriptor in the chain
+                    // HTE_Dscr_Next_p - next HTE descriptor for HTE_Dscr_p
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+                    if (HTE_Dscr_Next_p != NULL)
+                    {
+                        // Consistency checks: next HTE descriptor must be on
+                        //                     the overflow chain
+                        if (!HTE_Dscr_Next_p->fOverflowBucket)
+                            return EIP207_FLOW_INTERNAL_ERROR;
+
+                        // Check if the overflow bucket offset is
+                        // a dummy pointer
+                        {
+                            // Read the overflow bucket offset
+                            // from the previous bucket
+                            uint32_t Bucket_ByteOffset =
+                                DMAResource_Read32(
+                                       HT_DMA_Handle,
+                                       (HTE_Dscr_p->Bucket_ByteOffset >> 2) +
+                                       EIP207_FLOW_HB_OVFL_BUCKET_WORD_OFFSET);
+
+                            if (Bucket_ByteOffset !=
+                                (HTE_Dscr_Next_p->Bucket_ByteOffset|
+                                EIP207_FLOW_RECORD_TR_ADDRESS))
+                                return EIP207_FLOW_INTERNAL_ERROR;
+                        }
+                    }
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+                    HTE_Dscr_p = HTE_Dscr_Next_p;
+                    continue;
+
+                } // overflow bucket is found
+
+            } // "bucket full" handling is done
+
+        } while(HTE_Dscr_p != NULL);
+
+    } // Record is added to the Hash Table
+
+    // Fill in record descriptor internal data
+    {
+        EIP207_Flow_HTE_Dscr_RecData_t * Rec_DscrData_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+        // Check if the free slot number was found and
+        // the HTE descriptor to update was found
+        if (slot == 0 || HTE_Dscr_Updated_p == NULL)
+            return EIP207_FLOW_INTERNAL_ERROR;
+#endif
+
+        EIP207Lib_Flow_Dscr_InternalData_Set(Rec_Dscr_p);
+        Rec_DscrData_p =
+              (EIP207_Flow_HTE_Dscr_RecData_t*)Rec_Dscr_p->InternalData_p;
+
+        Rec_DscrData_p->Slot         = slot;
+        Rec_DscrData_p->HTE_Dscr_p   = HTE_Dscr_Updated_p;
+
+        if (RecData_p->TR_Data_p != NULL)
+        {
+            if (RecData_p->TR_Data_p->fLarge)
+                Rec_DscrData_p->Type = EIP207_FLOW_REC_TRANSFORM_LARGE;
+            else
+                Rec_DscrData_p->Type = EIP207_FLOW_REC_TRANSFORM_SMALL;
+        }
+        else if (RecData_p->FR_Data_p != NULL)
+            Rec_DscrData_p->Type = EIP207_FLOW_REC_FLOW;
+        else
+            return EIP207_FLOW_INTERNAL_ERROR;
+    }
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_DTL_Record_Remove
+ */
+static EIP207_Flow_Error_t
+EIP207Lib_Flow_DTL_Record_Remove(
+        const Device_Handle_t Device,
+        const unsigned int HashTableId,
+        volatile EIP207_Flow_HT_Params_t * const HT_Params_p,
+        EIP207_Flow_Dscr_t * const Rec_Dscr_p)
+{
+    EIP207_Flow_ID_t HashID;
+    DMAResource_Handle_t HT_DMA_Handle;
+    EIP207_Flow_HTE_Dscr_t * HTE_Dscr_p;
+    EIP207_Flow_HTE_Dscr_RecData_t * Rec_DscrData_p =
+               (EIP207_Flow_HTE_Dscr_RecData_t*)Rec_Dscr_p->InternalData_p;
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+    // Consistency check for the provided TR descriptor
+    if (Rec_Dscr_p->DMA_Addr.Addr == EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+        return EIP207_FLOW_INTERNAL_ERROR;
+
+    if (Rec_DscrData_p == NULL)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+    // get the HTE descriptor for the record to remove
+    HTE_Dscr_p = Rec_DscrData_p->HTE_Dscr_p;
+
+    HT_DMA_Handle = HT_Params_p->HT_DMA_Handle;
+
+    ZEROINIT(HashID);
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+    // Check record count is sane
+    if (HTE_Dscr_p->RecordCount > EIP207_FLOW_MAX_RECORDS_PER_BUCKET ||
+        HTE_Dscr_p->RecordCount == 0)
+        return EIP207_FLOW_INTERNAL_ERROR;
+
+    // Check the record descriptor slot number
+    if (Rec_DscrData_p->Slot < 1 || Rec_DscrData_p->Slot > 3)
+        return EIP207_FLOW_INTERNAL_ERROR; // Incorrect record slot number
+
+    // Check the record offset calculated from the record descriptor
+    // matches the one on the bucket
+    {
+        uint32_t Rec_ByteOffset2;
+        uint32_t Rec_ByteOffset1 =
+                DMAResource_Read32(HT_DMA_Handle,
+                                   (HTE_Dscr_p->Bucket_ByteOffset >> 2) +
+                                     EIP207_FLOW_HB_REC_1_WORD_OFFSET +
+                                       (Rec_DscrData_p->Slot - 1));
+
+        // Clear the bits that specify the record type
+        Rec_ByteOffset1 &= (~EIP207_FLOW_RECORD_ADDRESS_TYPE_BITS);
+
+        // Calculate the record byte offset,
+        // HT_Params_p->BaseAddr.Addr is the base
+        // address of the DMA bank where the record
+        // must have been allocated
+        Rec_ByteOffset2 = Rec_Dscr_p->DMA_Addr.Addr -
+                                            HT_Params_p->BaseAddr.Addr;
+
+        if (Rec_ByteOffset1 != Rec_ByteOffset2)
+            return EIP207_FLOW_INTERNAL_ERROR; // Incorrect record offset
+    }
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+    if (HTE_Dscr_p->RecordCount > 1)
+    {
+        // Remove the non-last record from the bucket
+
+        EIP207_Flow_Error_t Flow_Rc;
+
+        // CDS point: record is removed when the next function returns!
+
+        // Update the record offset in the bucket.
+        // Update the Hash ID (optional)
+        EIP207Lib_Flow_HB_Record_Remove(HT_DMA_Handle,
+                                        HTE_Dscr_p->Bucket_ByteOffset,
+                                        Rec_DscrData_p->Slot,
+                                        &HashID);
+
+        // Mark this record slot as free in the HTE descriptor
+        Flow_Rc = EIP207Lib_Flow_HB_Slot_Put(&HTE_Dscr_p->UsedRecOffsMask,
+                                             Rec_DscrData_p->Slot);
+        if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+            return Flow_Rc;
+
+        // Decrease record count in the HTE descriptor
+        HTE_Dscr_p->RecordCount--;
+    }
+    else // record count = 1, so when removing the record also remove the bucket
+    {
+        // Remove the last record from the removed bucket.
+        // Also remove the bucket from the chain first.
+
+        if (HTE_Dscr_p->fOverflowBucket)
+        {
+            // Remove the last record from the overflow bucket
+
+            EIP207_Flow_HTE_Dscr_t * FreeList_Head_p;
+
+            // Get the neighboring HTE descriptors in the chain
+            EIP207_Flow_HTE_Dscr_t * HTE_Dscr_Prev_p =
+                           EIP207_Flow_HTE_Dscr_List_Prev_Get(HTE_Dscr_p);
+            EIP207_Flow_HTE_Dscr_t * HTE_Dscr_Next_p =
+                           EIP207_Flow_HTE_Dscr_List_Next_Get(HTE_Dscr_p);
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+            // Check if the previous HTE descriptor is not NULL,
+            // it may not be NULL for the overflow bucket
+            if (HTE_Dscr_Prev_p == NULL)
+                return EIP207_FLOW_INTERNAL_ERROR;
+#endif
+
+            // CDS point: bucket (and record) is removed when
+            //            the next function returns and the wait loop is done!
+
+            // Remove HTE_Dscr_p bucket from the chain,
+            // make the HTE_Dscr_Prev_p bucket refer to HTE_Dscr_Next_p bucket
+            // Note: bucket offset can use any address (pointer) type
+            //       but not NULL!
+            EIP207Lib_Flow_HB_BuckOffs_Update(
+                                     HT_DMA_Handle,
+                                     HTE_Dscr_Prev_p->Bucket_ByteOffset,
+                                     HTE_Dscr_Next_p ? // the last in chain?
+                                         (HTE_Dscr_Next_p->Bucket_ByteOffset |
+                                             EIP207_FLOW_RECORD_TR_ADDRESS) :
+                                          EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+            // Wait loop: this is to wait for the EIP-207 packet classification
+            //            engine to complete processing using this bucket
+            //            before it can be re-used for another record lookup
+            {
+                unsigned int LoopCount, Value = 1;
+
+                for (LoopCount = 0;
+                     LoopCount < EIP207_FLOW_RECORD_REMOVE_WAIT_COUNT;
+                     LoopCount++)
+                {
+                    // Do some work in the loop
+                    if (LoopCount & BIT_0)
+                        Value <<= 1;
+                    else
+                        Value >>= 1;
+                }
+            } // HB remove wait loop is done!
+
+            // Remove record from the HTE_Dscr_p bucket
+            // which is not in the chain anymore
+            EIP207Lib_Flow_HB_Record_Remove(HT_DMA_Handle,
+                                            HTE_Dscr_p->Bucket_ByteOffset,
+                                            Rec_DscrData_p->Slot,
+                                            &HashID);
+
+            // Update the bucket offset in the removed from the chain
+            // HTE_Dscr_p bucket
+            EIP207Lib_Flow_HB_BuckOffs_Update(
+                                     HT_DMA_Handle,
+                                     HTE_Dscr_p->Bucket_ByteOffset,
+                                     EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+            // Remove HTE descriptor from the chain
+            EIP207_Flow_HTE_Dscr_List_Remove(HTE_Dscr_p);
+
+            // Add the HTE descriptor to the free list
+            FreeList_Head_p =
+                    (EIP207_Flow_HTE_Dscr_t*)HT_Params_p->FreeList_Head_p;
+
+            // Insert the HTE descriptor at the free list head
+            if (FreeList_Head_p != NULL)
+                EIP207_Flow_HTE_Dscr_List_Insert(FreeList_Head_p, HTE_Dscr_p);
+        }
+        else
+        {
+            // Remove the last record from the HT bucket
+            // Note: the chain may still be present for this HTE_Dscr_p bucket
+
+            // CDS point: record is removed when the next function returns!
+
+            // Update the record offset in the bucket.
+            // Update the Hash ID (optional)
+            EIP207Lib_Flow_HB_Record_Remove(HT_DMA_Handle,
+                                            HTE_Dscr_p->Bucket_ByteOffset,
+                                            Rec_DscrData_p->Slot,
+                                            &HashID);
+
+            // Wait loop: this is to wait for the EIP-207 packet classification
+            //            engine to complete processing using this bucket
+            //            before it can be re-used for another record lookup
+            {
+                unsigned int LoopCount, Value = 1;
+
+                for (LoopCount = 0;
+                     LoopCount < EIP207_FLOW_RECORD_REMOVE_WAIT_COUNT;
+                     LoopCount++)
+                {
+                    // Do some work in the loop
+                    if (LoopCount & BIT_0)
+                        Value <<= 1;
+                    else
+                        Value >>= 1;
+                }
+            } // HB remove wait loop is done!
+
+            // Mark this record slot as free in the HTE descriptor
+            EIP207Lib_Flow_HB_Slot_Put(&HTE_Dscr_p->UsedRecOffsMask,
+                                       Rec_DscrData_p->Slot);
+        }
+
+        // Update the HTE_Dscr_p record offset mask and record count
+        HTE_Dscr_p->UsedRecOffsMask = 0;
+        HTE_Dscr_p->RecordCount = 0;
+    }
+
+#ifndef EIP207_FLUE_RC_HP
+    // Invalidate lookup result in the FLUEC
+    EIP207_FLUEC_Invalidate(Device,
+                            (uint8_t)HashTableId,
+                            HashID.Word32[0],
+                            HashID.Word32[1],
+                            HashID.Word32[2],
+                            HashID.Word32[3]);
+#else
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(HashTableId);
+#endif
+
+    // Invalidate the internal data of the DTL transform record descriptor
+    Rec_DscrData_p->Slot         = 0;
+    Rec_DscrData_p->HTE_Dscr_p   = NULL;
+    Rec_DscrData_p->Type         = EIP207_FLOW_REC_INVALID;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_Is32bitAddressable
+ */
+static bool
+EIP207Lib_Flow_Is32bitAddressable(
+        const uint32_t BaseAddrLo,
+        const uint32_t BaseAddrHi,
+        const uint32_t AddrLo,
+        const uint32_t AddrHi)
+{
+    if(BaseAddrHi == AddrHi)
+    {
+        if(BaseAddrLo > AddrLo)
+            return false;
+    }
+    else if (BaseAddrHi < AddrHi && (BaseAddrHi == AddrHi + 1))
+    {
+        if(BaseAddrLo <= AddrLo)
+            return false;
+    }
+    else
+        return false;
+
+    return true;
+}
+#endif // EIP207_FLOW_STRICT_ARGS
+
+
+/*****************************************************************************
+ * Generic API functions implemented in DTL-specific way
+ */
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_HTE_Dscr_ByteCount_Get
+ */
+unsigned int
+EIP207_Flow_HTE_Dscr_ByteCount_Get(void)
+{
+    return EIP207Lib_Flow_HTE_Dscr_ByteCount_Get();
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_FR_Dscr_ByteCount_Get
+ */
+unsigned int
+EIP207_Flow_FR_Dscr_ByteCount_Get(void)
+{
+    return sizeof(EIP207_Flow_Rec_Dscr_t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_TR_Dscr_ByteCount_Get
+ */
+unsigned int
+EIP207_Flow_TR_Dscr_ByteCount_Get(void)
+{
+    return sizeof(EIP207_Flow_Rec_Dscr_t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_Record_Dummy_Addr_Get
+ */
+unsigned int
+EIP207_Flow_Record_Dummy_Addr_Get(void)
+{
+    return EIP207_FLOW_RECORD_DUMMY_ADDRESS;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_HashTable_Install
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_HashTable_Install(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_HT_t * HT_p,
+        bool fLookupCached,
+        bool fReset)
+{
+    unsigned int i, EntryCount;
+    Device_Handle_t Device;
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(HT_p->HT_DMA_Address_p);
+    EIP207_FLOW_CHECK_POINTER(HT_p->DT_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    EntryCount = (unsigned int)HT_p->HT_TableSize;
+    EIP207_FLOW_CHECK_INT_ATMOST(EntryCount,
+                                 EIP207_FLOW_HASH_TABLE_ENTRIES_MAX);
+
+    // Convert EIP207_Flow_HashTable_Entry_Count_t to a number
+    EntryCount = EIP207Lib_Flow_TableSize_To_EntryCount(EntryCount);
+    EIP207_FLOW_CHECK_INT_ATMOST(EntryCount, HT_p->DT_EntryCount);
+
+    // Check Flow Hash Table address alignment
+    if (HT_p->HT_DMA_Address_p->Addr == EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+        return EIP207_FLOW_ARGUMENT_ERROR;
+
+    // Save the flag that indicates whether the FLUEC must be used
+    // Note: FLUEC is enabled and configured via the Global Control interface
+    TrueIOArea_p->HT_Params[HashTableId].fLookupCached = fLookupCached;
+
+    // Save the host address of the Flow Descriptor Table and its size
+    TrueIOArea_p->HT_Params[HashTableId].DT_p          = HT_p->DT_p;
+    TrueIOArea_p->HT_Params[HashTableId].HT_TableSize  =
+                                            (unsigned int)HT_p->HT_TableSize;
+
+    // Save the DMA resource handle of the Flow Hash Table
+    TrueIOArea_p->HT_Params[HashTableId].HT_DMA_Handle =
+                                                    HT_p->HT_DMA_Handle;
+
+    Device = TrueIOArea_p->Device;
+
+    // Initialize the HT and the DT free list with initial values
+    if (fReset)
+    {
+        EIP207_Flow_HTE_Dscr_t * HTE_Dscr_p =
+                                        (EIP207_Flow_HTE_Dscr_t*)HT_p->DT_p;
+
+        // Initialize the Descriptor Table with initial values
+        memset(HT_p->DT_p,
+               0,
+               HT_p->DT_EntryCount * sizeof(EIP207_Flow_HTE_Dscr_t));
+
+        // Number of HTE descriptors is equal to the number of hash buckets
+        // in the HT plus the number of overflow hash buckets.
+
+        for (i = 0; i < HT_p->DT_EntryCount; i++)
+        {
+            unsigned int j;
+
+            // Initialize with dummy address all the words (j)
+            // in HTE descriptor i
+            for (j = 0; j < EIP207_FLOW_HT_ENTRY_WORD_COUNT; j++)
+                DMAResource_Write32(HT_p->HT_DMA_Handle,
+                                    i * EIP207_FLOW_HT_ENTRY_WORD_COUNT + j,
+                                    EIP207_FLOW_RECORD_DUMMY_ADDRESS);
+
+            // Add only the HTE descriptors for the overflow hash buckets
+            // to the free list.
+            if (i >= EntryCount)
+            {
+                // Descriptor Table free list initialization,
+                // all the HTE descriptors are added to the free list
+
+                // First overflow HTE descriptor in DT?
+                if (i == EntryCount)
+                {
+                    EIP207_Flow_HTE_Dscr_List_Prev_Set(HTE_Dscr_p, NULL);
+                    EIP207_Flow_HTE_Dscr_List_Next_Set(HTE_Dscr_p,
+                                                       HTE_Dscr_p + 1);
+
+                    // Set the free list head
+                    TrueIOArea_p->HT_Params[HashTableId].FreeList_Head_p =
+                                                                    HTE_Dscr_p;
+                }
+
+                // Last overflow HTE descriptor in DT?
+                if (i == HT_p->DT_EntryCount - 1)
+                {
+                    // First and last overflow HTE descriptor in DT?
+                    if (i != EntryCount)
+                        EIP207_Flow_HTE_Dscr_List_Prev_Set(HTE_Dscr_p,
+                                                           HTE_Dscr_p - 1);
+                    EIP207_Flow_HTE_Dscr_List_Next_Set(HTE_Dscr_p, NULL);
+                }
+
+                // Non-first and non-last overflow HTE descriptor in DT?
+                if (i != EntryCount && i != (HT_p->DT_EntryCount - 1))
+                {
+                    EIP207_Flow_HTE_Dscr_List_Prev_Set(HTE_Dscr_p,
+                                                       HTE_Dscr_p - 1);
+                    EIP207_Flow_HTE_Dscr_List_Next_Set(HTE_Dscr_p,
+                                                       HTE_Dscr_p + 1);
+                }
+
+                // Mark overflow hash buckets
+                HTE_Dscr_p->fOverflowBucket = true;
+            }
+            else
+                // Mark non-overflow hash buckets
+                HTE_Dscr_p->fOverflowBucket = false;
+
+            // Set hash bucket byte offset
+            HTE_Dscr_p->Bucket_ByteOffset = i *
+                                        EIP207_FLOW_HT_ENTRY_WORD_COUNT *
+                                            sizeof(uint32_t);
+
+            HTE_Dscr_p++; // Next HTE descriptor in the DT
+        } // for
+
+        // Perform pre-DMA for the entire HT including the overflow buckets,
+        // both are expected to be in one linear contiguous DMA-safe buffer
+        DMAResource_PreDMA(HT_p->HT_DMA_Handle, 0, 0);
+    }
+
+    // Install the FHT
+    EIP207_FLUE_HASHBASE_LO_WR(Device,
+                               HashTableId,
+                               HT_p->HT_DMA_Address_p->Addr);
+    EIP207_FLUE_HASHBASE_HI_WR(Device,
+                               HashTableId,
+                               HT_p->HT_DMA_Address_p->UpperAddr);
+    EIP207_FLUE_SIZE_UPDATE(Device,
+                            HashTableId,
+                            (uint8_t)HT_p->HT_TableSize);
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    if (fReset)
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        // Transit to a new state
+        rv = EIP207_Flow_State_Set(
+                (EIP207_Flow_State_t* const)&State,
+                EIP207_FLOW_STATE_ENABLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_FR_Add
+
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_FR_Add(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_FR_Dscr_t * const FR_Dscr_p,
+        const EIP207_Flow_FR_InputData_t * const FlowInData_p)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP207_Flow_Record_InputData_t Rec_Data;
+    EIP207_Flow_FR_Data_t FR_Data;
+    EIP207_Flow_Error_t Flow_Rc;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+    EIP207_FLOW_CHECK_POINTER(FR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(FlowInData_p);
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+    // Provided flow record physical DMA address must be addressable by
+    // a 32-bit offset to the Base Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(!EIP207Lib_Flow_Is32bitAddressable(
+            TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+            TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+            FR_Dscr_p->DMA_Addr.Addr,
+            FR_Dscr_p->DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+
+    // Provided transform record physical DMA address must be addressable by
+    // a 32-bit offset to the Base Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(FlowInData_p->Xform_DMA_Addr.Addr != EIP207_FLOW_RECORD_DUMMY_ADDRESS &&
+       !EIP207Lib_Flow_Is32bitAddressable(
+                TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+                TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+                FlowInData_p->Xform_DMA_Addr.Addr,
+                FlowInData_p->Xform_DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+#endif // EIP207_FLOW_STRICT_ARGS
+
+    ZEROINIT(Rec_Data);
+    ZEROINIT(FR_Data);
+
+    FR_Data.Flags           = FlowInData_p->Flags;
+    FR_Data.SW_FR_Reference = FlowInData_p->SW_FR_Reference;
+    FR_Data.Xform_DMA_Addr  = FlowInData_p->Xform_DMA_Addr;
+    FR_Data.fLarge          = FlowInData_p->fLarge;
+
+    Rec_Data.HashID_p       = &FlowInData_p->HashID;
+    Rec_Data.FR_Data_p      = &FR_Data;
+
+    Flow_Rc = EIP207Lib_Flow_DTL_Record_Add(
+                            &TrueIOArea_p->HT_Params[HashTableId],
+                            (EIP207_Flow_Dscr_t*)FR_Dscr_p,
+                            &Rec_Data);
+    if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+        return Flow_Rc;
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        TrueIOArea_p->Rec_InstalledCounter++;
+
+        // Transit to a new state
+        rv = EIP207_Flow_State_Set((EIP207_Flow_State_t* const)&State,
+                                   EIP207_FLOW_STATE_INSTALLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_RC_BaseAddr_Set
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_RC_BaseAddr_Set(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_Address_t * const FlowBaseAddr_p,
+        const EIP207_Flow_Address_t * const TransformBaseAddr_p)
+{
+    Device_Handle_t Device;
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    IDENTIFIER_NOT_USED(TransformBaseAddr_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Set the common base address for all the records which can be looked up
+    // Note: Standard (legacy) record cache should have
+    //       EIP207_RC_SET_NR_DEFAULT set (which is 0, just one Hash Table);
+    //       High-performance (HP) record cache should have
+    //       HashTableId set
+#ifndef EIP207_FLUE_RC_HP
+    EIP207_RC_BaseAddr_Set(Device,
+                           EIP207_FRC_REG_BASE,
+                           HashTableId, // EIP207_RC_SET_NR_DEFAULT
+                           FlowBaseAddr_p->Addr,
+                           FlowBaseAddr_p->UpperAddr);
+#else
+    EIP207_FLUE_CACHEBASE_LO_WR(Device, HashTableId, FlowBaseAddr_p->Addr);
+    EIP207_FLUE_CACHEBASE_HI_WR(Device, HashTableId, FlowBaseAddr_p->UpperAddr);
+#endif
+
+    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr = FlowBaseAddr_p->Addr;
+    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr =
+                                                    FlowBaseAddr_p->UpperAddr;
+
+    return  EIP207_FLOW_NO_ERROR;
+}
+
+
+/*****************************************************************************
+ * DTL-specific API functions
+ */
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_FR_Remove
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_DTL_FR_Remove(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_FR_Dscr_t * const FR_Dscr_p)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP207_Flow_HTE_Dscr_RecData_t * FR_Data_p;
+    EIP207_Flow_Error_t Flow_Rc;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+    EIP207_FLOW_CHECK_POINTER(FR_Dscr_p);
+
+    FR_Data_p = (EIP207_Flow_HTE_Dscr_RecData_t*)FR_Dscr_p->InternalData_p;
+
+    EIP207_FLOW_CHECK_POINTER(FR_Data_p);
+    EIP207_FLOW_CHECK_POINTER(FR_Data_p->HTE_Dscr_p);
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+    // Provided flow record physical DMA address must be addressable by
+    // a 32-bit offset to the Based Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(!EIP207Lib_Flow_Is32bitAddressable(
+                TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+                TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+                FR_Dscr_p->DMA_Addr.Addr,
+                FR_Dscr_p->DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+
+    if (FR_Data_p->Type != EIP207_FLOW_REC_FLOW)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_STRICT_ARGS
+
+    Flow_Rc = EIP207Lib_Flow_DTL_Record_Remove(
+                          TrueIOArea_p->Device,
+                          HashTableId,
+                          &TrueIOArea_p->HT_Params[HashTableId],
+                          (EIP207_Flow_Dscr_t*)FR_Dscr_p);
+    if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+        return Flow_Rc;
+
+    IDENTIFIER_NOT_USED(FR_Data_p);
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        TrueIOArea_p->Rec_InstalledCounter--;
+
+        // Transit to a new state
+        if (TrueIOArea_p->Rec_InstalledCounter == 0)
+            // Last record is removed
+            rv = EIP207_Flow_State_Set(
+                    (EIP207_Flow_State_t* const)&State,
+                    EIP207_FLOW_STATE_ENABLED);
+        else
+            // Non-last record is removed
+            rv = EIP207_Flow_State_Set(
+                    (EIP207_Flow_State_t* const)&State,
+                    EIP207_FLOW_STATE_INSTALLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+#ifndef EIP207_FLOW_REMOVE_TR_LARGE_SUPPORT
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_TR_Large_WordCount_Get
+ */
+unsigned int
+EIP207_Flow_DTL_TR_Large_WordCount_Get(void)
+{
+    return FIRMWARE_EIP207_CS_FLOW_TRC_RECORD_WORD_COUNT_LARGE;
+}
+#endif // !EIP207_FLOW_REMOVE_TR_LARGE_SUPPORT
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_TR_Add
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_DTL_TR_Add(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_TR_Dscr_t * const TR_Dscr_p,
+        const EIP207_Flow_TR_InputData_t * const XformInData_p)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP207_Flow_Record_InputData_t Rec_Data;
+    EIP207_Flow_TR_Data_t TR_Data;
+    EIP207_Flow_Error_t Flow_Rc;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+    EIP207_FLOW_CHECK_POINTER(TR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(XformInData_p);
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+    // Provided transform record physical DMA address must be addressable by
+    // a 32-bit offset to the Transform Based Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(!EIP207Lib_Flow_Is32bitAddressable(
+                    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+                    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+                    TR_Dscr_p->DMA_Addr.Addr,
+                    TR_Dscr_p->DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+#endif // EIP207_FLOW_STRICT_ARGS
+
+    ZEROINIT(Rec_Data);
+    ZEROINIT(TR_Data);
+
+    TR_Data.fLarge     = XformInData_p->fLarge;
+
+    Rec_Data.HashID_p  = &XformInData_p->HashID;
+    Rec_Data.TR_Data_p = &TR_Data;
+
+    Flow_Rc = EIP207Lib_Flow_DTL_Record_Add(
+                            &TrueIOArea_p->HT_Params[HashTableId],
+                            (EIP207_Flow_Dscr_t*)TR_Dscr_p,
+                            &Rec_Data);
+    if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+        return Flow_Rc;
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        TrueIOArea_p->Rec_InstalledCounter++;
+
+        // Transit to a new state
+        rv = EIP207_Flow_State_Set((EIP207_Flow_State_t* const)&State,
+                                   EIP207_FLOW_STATE_INSTALLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+#ifndef EIP207_FLOW_REMOVE_TR_LARGE_SUPPORT
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_TR_Large_Read
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_DTL_TR_Large_Read(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_TR_Dscr_t * const TR_Dscr_p,
+        EIP207_Flow_TR_OutputData_t * const XformData_p)
+{
+    EIP207_Flow_Error_t rv;
+    uint32_t Value32, SeqNrWordOffset;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(TR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(XformData_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    IDENTIFIER_NOT_USED(IOArea_p);
+    IDENTIFIER_NOT_USED(HashTableId);
+
+    // Prepare the transform record for reading
+    DMAResource_PostDMA(TR_Dscr_p->DMA_Handle, 0, 0);
+
+    // Read the transform record data
+
+    // Recent record Packets Counter
+    XformData_p->PacketsCounter =
+            DMAResource_Read32(
+                    TR_Dscr_p->DMA_Handle,
+                    FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET_LARGE);
+
+    // Read Token Context Instruction word
+    Value32 =
+        DMAResource_Read32(TR_Dscr_p->DMA_Handle,
+                FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET_LARGE);
+
+    // Extract the Sequence Number word offset from the read value
+    FIRMWARE_EIP207_CS_Flow_SeqNum_Offset_Read(Value32, &SeqNrWordOffset);
+
+    // Read the sequence number
+    XformData_p->SequenceNumber =
+            DMAResource_Read32(TR_Dscr_p->DMA_Handle, SeqNrWordOffset);
+
+    // Recent record time stamp
+    rv = EIP207_Flow_Internal_Read64(
+                   TR_Dscr_p->DMA_Handle,
+                   FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET_LARGE,
+                   FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET_LARGE,
+                   &XformData_p->LastTimeLo,
+                   &XformData_p->LastTimeHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    // Recent record Octets Counter
+    rv = EIP207_Flow_Internal_Read64(
+                   TR_Dscr_p->DMA_Handle,
+                   FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET_LARGE,
+                   FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET_LARGE,
+                   &XformData_p->OctetsCounterLo,
+                   &XformData_p->OctetsCounterHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+#endif // !EIP207_FLOW_REMOVE_TR_LARGE_SUPPORT
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_DTL_TR_Remove
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_DTL_TR_Remove(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_TR_Dscr_t * const TR_Dscr_p)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP207_Flow_HTE_Dscr_RecData_t * TR_Data_p;
+    EIP207_Flow_Error_t Flow_Rc;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+    EIP207_FLOW_CHECK_POINTER(TR_Dscr_p);
+
+    TR_Data_p = (EIP207_Flow_HTE_Dscr_RecData_t*)TR_Dscr_p->InternalData_p;
+
+    EIP207_FLOW_CHECK_POINTER(TR_Data_p);
+    EIP207_FLOW_CHECK_POINTER(TR_Data_p->HTE_Dscr_p);
+
+#ifdef EIP207_FLOW_STRICT_ARGS
+    // Provided transform record physical DMA address must be addressable by
+    // a 32-bit offset to the Transform Based Address installed via
+    // the EIP207_Flow_RC_BaseAddr_Set() function
+    if(!EIP207Lib_Flow_Is32bitAddressable(
+                    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.Addr,
+                    TrueIOArea_p->HT_Params[HashTableId].BaseAddr.UpperAddr,
+                    TR_Dscr_p->DMA_Addr.Addr,
+                    TR_Dscr_p->DMA_Addr.UpperAddr))
+        return EIP207_FLOW_ARGUMENT_ERROR;
+
+    if (TR_Data_p->Type != EIP207_FLOW_REC_TRANSFORM_SMALL &&
+        TR_Data_p->Type != EIP207_FLOW_REC_TRANSFORM_LARGE)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_STRICT_ARGS
+
+    Flow_Rc = EIP207Lib_Flow_DTL_Record_Remove(
+                          TrueIOArea_p->Device,
+                          HashTableId,
+                          &TrueIOArea_p->HT_Params[HashTableId],
+                          (EIP207_Flow_Dscr_t*)TR_Dscr_p);
+    if (Flow_Rc != EIP207_FLOW_NO_ERROR)
+        return Flow_Rc;
+
+    IDENTIFIER_NOT_USED(TR_Data_p);
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        EIP207_Flow_Error_t rv;
+        uint32_t State = TrueIOArea_p->State;
+
+        TrueIOArea_p->Rec_InstalledCounter--;
+
+        // Transit to a new state
+        if (TrueIOArea_p->Rec_InstalledCounter == 0)
+            // Last record is removed
+            rv = EIP207_Flow_State_Set(
+                    (EIP207_Flow_State_t* const)&State,
+                    EIP207_FLOW_STATE_ENABLED);
+        else
+            // Non-last record is removed
+            rv = EIP207_Flow_State_Set(
+                    (EIP207_Flow_State_t* const)&State,
+                    EIP207_FLOW_STATE_INSTALLED);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/* end of file eip207_flow_dtl.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_generic.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_generic.c
new file mode 100644
index 0000000..cd3ecbd
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_generic.c
@@ -0,0 +1,512 @@
+/* eip207_flow_generic.c
+ *
+ * Partial EIP-207 Flow Control Generic API implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Driver Library Flow Control Generic API
+#include "eip207_flow_generic.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_flow.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                       // ZEROINIT, memset, memcpy
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"
+#include "dmares_rw.h"
+
+// EIP-207 Flow Control Driver Library Internal interfaces
+#include "eip207_flow_level0.h"         // EIP-207 Level 0 macros
+#include "eip207_flow_internal.h"
+
+// EIP-207 Firmware API
+#include "firmware_eip207_api_flow_cs.h" // Classification API: Flow Control
+#include "firmware_eip207_api_cs.h"      // Classification API: General
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_Detect
+ *
+ * Checks the presence of EIP-207c hardware. Returns true when found.
+ */
+static bool
+EIP207Lib_Flow_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    Value = EIP207_Flow_Read32(Device, EIP207_FLUE_FHT_REG_VERSION);
+    if (!EIP207_FLUE_SIGNATURE_MATCH( Value ))
+        return false;
+
+    // read-write test one of the registers
+
+    // Set MASK_31_BITS bits of the EIP207_FLUE_REG_HASHBASE_LO register
+    EIP207_Flow_Write32( Device,
+                         EIP207_FLUE_FHT_REG_HASHBASE_LO(0),
+                         ~MASK_2_BITS);
+    Value = EIP207_Flow_Read32(Device, EIP207_FLUE_FHT_REG_HASHBASE_LO(0));
+    if ((Value) != ~MASK_2_BITS)
+        return false;
+
+    // Clear MASK_31_BITS bits of the EIP207_FLUE_REG_HASHBASE_LO register
+    EIP207_Flow_Write32(Device, EIP207_FLUE_FHT_REG_HASHBASE_LO(0), 0);
+    Value = EIP207_Flow_Read32(Device, EIP207_FLUE_FHT_REG_HASHBASE_LO(0));
+    if (Value != 0)
+       return false;
+
+    return true;
+}
+
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Flow_State_Set
+ *
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_State_Set(
+        EIP207_Flow_State_t * const CurrentState,
+        const EIP207_Flow_State_t NewState)
+{
+    switch(*CurrentState)
+    {
+        case EIP207_FLOW_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP207_FLOW_STATE_ENABLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_FLOW_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_FLOW_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP207_FLOW_STATE_ENABLED:
+            switch(NewState)
+            {
+                case EIP207_FLOW_STATE_INSTALLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_FLOW_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_FLOW_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP207_FLOW_STATE_INSTALLED:
+            switch(NewState)
+            {
+                case EIP207_FLOW_STATE_INSTALLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_FLOW_STATE_ENABLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_FLOW_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_FLOW_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+
+    return EIP207_FLOW_NO_ERROR;
+}
+#endif // EIP207_FLOW_DEBUG_FSM
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_IOArea_ByteCount_Get
+ */
+unsigned int
+EIP207_Flow_IOArea_ByteCount_Get(void)
+{
+    return sizeof(EIP207_Flow_True_IOArea_t);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_HT_Entry_WordCount_Get
+ */
+unsigned int
+EIP207_Flow_HT_Entry_WordCount_Get(void)
+{
+    return EIP207_FLOW_HT_ENTRY_WORD_COUNT;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_Init
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_Init(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+
+    // Detect presence of EIP-207c HW hardware
+    if (!EIP207Lib_Flow_Detect(Device))
+        return EIP207_FLOW_UNSUPPORTED_FEATURE_ERROR;
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        TrueIOArea_p->Rec_InstalledCounter = 0;
+
+        TrueIOArea_p->State = (uint32_t)EIP207_FLOW_STATE_INITIALIZED;
+    }
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_ID_Compute
+ *
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_ID_Compute(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_SelectorParams_t * const SelectorParams_p,
+        EIP207_Flow_ID_t * const FlowID)
+{
+    uint32_t h1, h2, h3, h4;
+    uint32_t w;
+    const uint32_t * p;
+    uint32_t count, data [FIRMWARE_EIP207_CS_FLOW_HASH_ID_INPUT_WORD_COUNT];
+    Device_Handle_t Device;
+    FIRMWARE_EIP207_CS_Flow_SelectorParams_t Selectors;
+    volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(SelectorParams_p);
+    EIP207_FLOW_CHECK_POINTER(FlowID);
+
+    Device = TrueIOArea_p->Device;
+
+    // Read the IV from the flow hash engine in the classification engine
+    // The IV must have been already installed in the flow hash engine
+    // via the Global Classification Control API
+    EIP207_FHASH_IV_RD(Device, HashTableId, &h1, &h2, &h3, &h4);
+
+    // Install the selectors for the flow hash ID calculation
+    ZEROINIT(Selectors);
+    Selectors.Flags   = SelectorParams_p->Flags;
+    Selectors.DstIp_p = SelectorParams_p->DstIp_p;
+    Selectors.DstPort = SelectorParams_p->DstPort;
+    Selectors.IpProto = SelectorParams_p->IpProto;
+    Selectors.SPI     = SelectorParams_p->SPI;
+#ifdef FIRMWARE_EIP207_CS_FLOW_DTLS_SUPPORTED
+    Selectors.Epoch     = SelectorParams_p->Epoch;
+#endif
+    Selectors.SrcIp_p = SelectorParams_p->SrcIp_p;
+    Selectors.SrcPort = SelectorParams_p->SrcPort;
+    FIRMWARE_EIP207_CS_Flow_Selectors_Reorder(&Selectors, data, &count);
+
+    p = data;
+
+    while (p < &data[count - 3])
+    {
+        w = *p++;
+        h2 ^= w;
+        h1 += w;
+        h1 += h1 << 10;
+        h1 ^= h1 >> 6;
+
+        w = *p++;
+        h3 ^= w;
+        h1 += w;
+        h1 += h1 << 10;
+        h1 ^= h1 >> 6;
+
+        w = *p++;
+        h4 ^= w;
+        h1 += w;
+        h1 += h1 << 10;
+        h1 ^= h1 >> 6;
+
+        /* Mixing step for the 96 bits in h2-h4.  The code comes from a
+           hash table lookup function by Robert J. Jenkins, and has been
+           presented on numerous web pages and in a Dr. Dobbs Journal
+           sometimes in late 90's.
+
+           h1 is computed according to the one-at-a-time hash function,
+           presented in the same article. */
+        h2 -= h3;  h2 -= h4;  h2 ^= h4 >> 13;
+        h3 -= h4;  h3 -= h2;  h3 ^= h2 << 8;
+        h4 -= h2;  h4 -= h3;  h4 ^= h3 >> 13;
+        h2 -= h3;  h2 -= h4;  h2 ^= h4 >> 12;
+        h3 -= h4;  h3 -= h2;  h3 ^= h2 << 16;
+        h4 -= h2;  h4 -= h3;  h4 ^= h3 >> 5;
+        h2 -= h3;  h2 -= h4;  h2 ^= h4 >> 3;
+        h3 -= h4;  h3 -= h2;  h3 ^= h2 << 10;
+        h4 -= h2;  h4 -= h3;  h4 ^= h3 >> 15;
+    } // while
+
+    w = *p++;
+    h1 += w;
+    h1 += h1 << 10;
+    h1 ^= h1 >> 6;
+    h2 ^= w;
+
+    if (p < data + count)
+    {
+        w = *p++;
+        h1 += w;
+        h1 += h1 << 10;
+        h1 ^= h1 >> 6;
+        h3 ^= w;
+
+        if (p < data + count)
+        {
+            w = *p++;
+            h1 += w;
+            h1 += h1 << 10;
+            h1 ^= h1 >> 6;
+            h4 ^= w;
+        }
+    }
+
+    FlowID->Word32[0] = h1;
+    FlowID->Word32[1] = h2;
+    FlowID->Word32[2] = h3;
+    FlowID->Word32[3] = h4;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_FR_WordCount_Get
+ */
+unsigned int
+EIP207_Flow_FR_WordCount_Get(void)
+{
+    return FIRMWARE_EIP207_CS_FRC_RECORD_WORD_COUNT;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_FR_Read
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_FR_Read(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        EIP207_Flow_FR_Dscr_t * const FR_Dscr_p,
+        EIP207_Flow_FR_OutputData_t * const FlowData_p)
+{
+    EIP207_Flow_Error_t rv;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(FR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(FlowData_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    IDENTIFIER_NOT_USED(HashTableId);
+
+#ifdef EIP207_FLOW_CONSISTENCY_CHECK
+    // Consistency check for the provided flow descriptor
+    if (FR_Dscr_p->DMA_Addr.Addr == EIP207_FLOW_RECORD_DUMMY_ADDRESS)
+        return EIP207_FLOW_INTERNAL_ERROR;
+#endif // EIP207_FLOW_CONSISTENCY_CHECK
+
+    // Prepare the flow record for reading
+    DMAResource_PostDMA(FR_Dscr_p->DMA_Handle, 0, 0);
+
+    // Read the flow record data
+
+    // Recent record Packets Counter
+    FlowData_p->PacketsCounter =
+            DMAResource_Read32(FR_Dscr_p->DMA_Handle,
+                               FIRMWARE_EIP207_CS_FLOW_FR_STAT_PKT_WORD_OFFSET);
+
+    // Recent record time stamp
+    rv = EIP207_Flow_Internal_Read64(
+                       FR_Dscr_p->DMA_Handle,
+                       FIRMWARE_EIP207_CS_FLOW_FR_TIME_STAMP_LO_WORD_OFFSET,
+                       FIRMWARE_EIP207_CS_FLOW_FR_TIME_STAMP_HI_WORD_OFFSET,
+                       &FlowData_p->LastTimeLo,
+                       &FlowData_p->LastTimeHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    // Recent record Octets Counter
+    rv = EIP207_Flow_Internal_Read64(
+                       FR_Dscr_p->DMA_Handle,
+                       FIRMWARE_EIP207_CS_FLOW_FR_STAT_OCT_LO_WORD_OFFSET,
+                       FIRMWARE_EIP207_CS_FLOW_FR_STAT_OCT_HI_WORD_OFFSET,
+                       &FlowData_p->OctetsCounterLo,
+                       &FlowData_p->OctetsCounterHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+#ifdef EIP207_FLOW_DEBUG_FSM
+    {
+        volatile EIP207_Flow_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+        uint32_t State = TrueIOArea_p->State;
+
+        // Remain in the current state
+        rv = EIP207_Flow_State_Set(
+                (EIP207_Flow_State_t* const)&State,
+                (EIP207_Flow_State_t)TrueIOArea_p->State);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_FLOW_NO_ERROR)
+            return EIP207_FLOW_ILLEGAL_IN_STATE;
+    }
+#else
+    IDENTIFIER_NOT_USED(IOArea_p);
+#endif // EIP207_FLOW_DEBUG_FSM
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_TR_WordCount_Get
+ */
+unsigned int
+EIP207_Flow_TR_WordCount_Get(void)
+{
+    return FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_TR_Read
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_TR_Read(
+        EIP207_Flow_IOArea_t * const IOArea_p,
+        const unsigned int HashTableId,
+        const EIP207_Flow_TR_Dscr_t * const TR_Dscr_p,
+        EIP207_Flow_TR_OutputData_t * const XformData_p)
+{
+    EIP207_Flow_Error_t rv;
+    uint32_t Value32, SeqNrWordOffset;
+
+    EIP207_FLOW_CHECK_POINTER(IOArea_p);
+    EIP207_FLOW_CHECK_POINTER(TR_Dscr_p);
+    EIP207_FLOW_CHECK_POINTER(XformData_p);
+    EIP207_FLOW_CHECK_INT_ATMOST(HashTableId + 1,
+                                 EIP207_FLOW_MAX_NOF_FLOW_HASH_TABLES_TO_USE);
+
+    IDENTIFIER_NOT_USED(IOArea_p);
+    IDENTIFIER_NOT_USED(HashTableId);
+
+    // Prepare the transform record for reading
+    DMAResource_PostDMA(TR_Dscr_p->DMA_Handle, 0, 0);
+
+    // Read the transform record data
+
+    // Recent record Packets Counter
+    XformData_p->PacketsCounter =
+            DMAResource_Read32(TR_Dscr_p->DMA_Handle,
+                               FIRMWARE_EIP207_CS_FLOW_TR_STAT_PKT_WORD_OFFSET);
+
+    // Read Token Context Instruction word
+    Value32 =
+        DMAResource_Read32(TR_Dscr_p->DMA_Handle,
+                           FIRMWARE_EIP207_CS_FLOW_TR_TK_CTX_INST_WORD_OFFSET);
+
+    // Extract the Sequence Number word offset from the read value
+    FIRMWARE_EIP207_CS_Flow_SeqNum_Offset_Read(Value32, &SeqNrWordOffset);
+
+    // Read the sequence number
+    XformData_p->SequenceNumber =
+            DMAResource_Read32(TR_Dscr_p->DMA_Handle, SeqNrWordOffset);
+
+    // Recent record time stamp
+    rv = EIP207_Flow_Internal_Read64(
+                   TR_Dscr_p->DMA_Handle,
+                   FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_LO_WORD_OFFSET,
+                   FIRMWARE_EIP207_CS_FLOW_TR_TIME_STAMP_HI_WORD_OFFSET,
+                   &XformData_p->LastTimeLo,
+                   &XformData_p->LastTimeHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    // Recent record Octets Counter
+    rv = EIP207_Flow_Internal_Read64(
+                   TR_Dscr_p->DMA_Handle,
+                   FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_LO_WORD_OFFSET,
+                   FIRMWARE_EIP207_CS_FLOW_TR_STAT_OCT_HI_WORD_OFFSET,
+                   &XformData_p->OctetsCounterLo,
+                   &XformData_p->OctetsCounterHi);
+    if (rv != EIP207_FLOW_NO_ERROR)
+        return rv;
+
+    return EIP207_FLOW_NO_ERROR;
+}
+
+
+/* end of file eip207_flow_generic.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_internal.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_internal.c
new file mode 100644
index 0000000..1b61461
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flow_internal.c
@@ -0,0 +1,95 @@
+/* eip207_flow_internal.c
+ *
+ *  EIP-207 Flow Control Internal interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Flow Control Driver Library Internal interfaces
+#include "eip207_flow_internal.h"
+#include "eip207_flow_generic.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+#include "eip207_flow_level0.h"         // EIP-207 Level 0 macros
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"         // BIT definitions, bool, uint32_t
+
+// Driver Framework DMA Resource API
+#include "dmares_types.h"       // DMAResource_Handle_t
+#include "dmares_rw.h"          // DMAResource_Write32()/_Read32()/_PreDMA()
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Flow_Internal_Read64
+ */
+EIP207_Flow_Error_t
+EIP207_Flow_Internal_Read64(
+        const DMAResource_Handle_t Handle,
+        const unsigned int Value64_WordOffsetLo,
+        const unsigned int Value64_WordOffsetHi,
+        uint32_t * const Value64_Lo,
+        uint32_t * const Value64_Hi)
+{
+    uint32_t Value32;
+    unsigned int i;
+
+    for (i = 0; i < EIP207_FLOW_VALUE_64BIT_MAX_NOF_READ_ATTEMPTS; i++)
+    {
+        Value32     = DMAResource_Read32(Handle, Value64_WordOffsetHi);
+        *Value64_Lo = DMAResource_Read32(Handle, Value64_WordOffsetLo);
+
+        // Prepare the flow record for reading
+        DMAResource_PostDMA(Handle, 0, 0);
+
+        *Value64_Hi = DMAResource_Read32(Handle, Value64_WordOffsetHi);
+
+        if (Value32 == (*Value64_Hi))
+            return EIP207_FLOW_NO_ERROR;
+    }
+
+    return EIP207_FLOW_INTERNAL_ERROR;
+}
+
+
+/* end of file eip207_flow_hte_dscr_dtl.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flue.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flue.c
new file mode 100644
index 0000000..1074b7a
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_flue.c
@@ -0,0 +1,177 @@
+/* eip207_ice.c
+ *
+ * EIP-207s Flow Look-Up Engine (FLUE) interface implementation
+ *
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207s Flow Look-Up Engine (FLUE) interface
+#include "eip207_flue.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// EIP-207 HW interface
+#include "eip207_hw_interface.h"
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// EIP-207 Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+#define EIP207_FLUE_3ENTRY_LOOKUP_MODE          1
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_FLUE_Init
+ */
+void
+EIP207_FLUE_Init(
+        const Device_Handle_t Device,
+        const unsigned int HashTableId,
+        const EIP207_Global_FLUEConfig_t * const FLUEConf_p,
+        const bool fARC4Present,
+        const bool fLookupCachePresent)
+{
+    // Configure hash tables
+    EIP207_FLUE_CONFIG_WR(Device,
+                          HashTableId, // Hash Table ID
+                          HashTableId, // Function,
+                                       // set it equal to hash table id
+                          0,           // Generation
+                          true,        // Table enable
+                          true);       // Access enable
+
+    // Use Hash table 0 parameters, they must be the same for all the tables!
+    // Initialize FLUE with EIP-207 Firmware Classification API parameters
+    EIP207_FLUE_OFFSET_WR(Device,
+                          FLUEConf_p->HashTable[HashTableId].fPrefetchXform,
+                          fLookupCachePresent ?
+                              FLUEConf_p->HashTable[HashTableId].fLookupCached :
+                              false,
+                          FIRMWARE_EIP207_CS_XFORM_RECORD_WORD_OFFSET);
+
+    // Use Hash table 0 parameters, they must be the same for all the tables!
+    // Check if ARC4 Record Cache is available
+    if ( fARC4Present )
+    {
+        EIP207_FLUE_ARC4_OFFSET_WR(
+                          Device,
+                          FLUEConf_p->HashTable[HashTableId].fPrefetchARC4State,
+                          EIP207_GLOBAL_FLUE_LOOKUP_MODE,
+                          FIRMWARE_EIP207_CS_ARC4_RECORD_WORD_OFFSET);
+    }
+#if EIP207_GLOBAL_FLUE_LOOKUP_MODE == EIP207_FLUE_3ENTRY_LOOKUP_MODE
+    else
+    {
+        EIP207_FLUE_ARC4_OFFSET_WR(Device,
+                                   HashTableId,
+                                   EIP207_GLOBAL_FLUE_LOOKUP_MODE,
+                                   0);
+    }
+#endif // EIP207_GLOBAL_FLUE_LOOKUP_MODE == EIP207_FLUE_1ENTRY_LOOKUP_MODE
+
+#ifdef EIP207_FLUE_HAVE_VIRTUALIZATION
+    // Virtualisation support present, initialize the lookup table.
+    // All interfaces refer to Table # 0.
+    {
+        unsigned int i;
+        unsigned int c;
+        unsigned int idx0,idx1,idx2,idx3;
+
+        c = FLUEConf_p->InterfacesCount;
+        if (c > EIP207_FLUE_MAX_NOF_INTERFACES_TO_USE)
+            c = EIP207_FLUE_MAX_NOF_INTERFACES_TO_USE;
+
+        for (i = 0; i < c; i += 4)
+        {
+            idx0 = FLUEConf_p->InterfaceIndex[i];
+
+            if (i + 1 < c)
+                idx1 = FLUEConf_p->InterfaceIndex[i + 1];
+            else
+                idx1 = 0;
+
+            if (i + 2 < c)
+                idx2 = FLUEConf_p->InterfaceIndex[i + 2];
+            else
+                idx2 = 0;
+
+            if (i + 3 < c)
+                idx3 = FLUEConf_p->InterfaceIndex[i + 3];
+            else
+                idx3 = 0;
+
+            EIP207_FLUE_IFC_LUT_WR(Device,
+                                   i / 4,
+                                   idx0, idx1, idx2, idx3);
+        }
+    }
+#endif
+
+    return;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_FLUE_Status_Get
+ */
+void
+EIP207_FLUE_Status_Get(
+        const Device_Handle_t Device,
+        EIP207_Global_FLUE_Status_t * const FLUE_Status_p)
+{
+    IDENTIFIER_NOT_USED(Device);
+
+    FLUE_Status_p->Error1 = 0;
+    FLUE_Status_p->Error2 = 0;
+
+    return;
+}
+
+
+/* end of file eip207_flue.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_fluec.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_fluec.c
new file mode 100644
index 0000000..82f04ac
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_fluec.c
@@ -0,0 +1,77 @@
+/* eip207_fluec.c
+ *
+ * EIP-207 Flow Look-Up Engine Cache (FLUEC) interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207s Flow Look-Up Engine Cache (FLUEC) interface
+#include "eip207_fluec.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint8_t, uint32_t,
+                                        // IDENTIFIER_NOT_USED
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_FLUEC_Invalidate
+ */
+void
+EIP207_FLUEC_Invalidate(
+        const Device_Handle_t Device,
+        const uint8_t InvTable,
+        const uint32_t FlowID_W0,
+        const uint32_t FlowID_W1,
+        const uint32_t FlowID_W2,
+        const uint32_t FlowID_W3)
+{
+    // Not implemented
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(InvTable);
+    IDENTIFIER_NOT_USED(FlowID_W0);
+    IDENTIFIER_NOT_USED(FlowID_W1);
+    IDENTIFIER_NOT_USED(FlowID_W2);
+    IDENTIFIER_NOT_USED(FlowID_W3);
+}
+
+
+/* end of file eip207_fluec.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_global_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_global_init.c
new file mode 100644
index 0000000..41586a8
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_global_init.c
@@ -0,0 +1,690 @@
+/* eip207_global_init.c
+ *
+ * EIP-207 Global Control Driver Library
+ * Initialization and status retrieval Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Global Control API
+#include "eip207_global_init.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                       // ZEROINIT
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// EIP-207s Record Cache (RC) internal interface
+#include "eip207_rc_internal.h"
+
+// EIP-207c Input Classification Engine (ICE) interface
+#include "eip207_ice.h"
+
+// EIP-207c Output Classification Engine (OCE) interface
+#include "eip207_oce.h"
+
+// EIP-207s Flow Look-Up Engine (FLUE) interface
+#include "eip207_flue.h"
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// EIP-207s Flow Look-Up Engine Cache (FLUEC) Level0 interface
+#include "eip207_fluec_level0.h"
+
+// EIP-207c Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+// EIP-207c Firmware Download API
+#include "firmware_eip207_api_dwld.h"   // Classification API: FW download
+
+// EIP97 Global init API
+#include "eip97_global_init.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// Maximum number of EIP-207c Classification Engines that should be used
+// Should not exceed the number of engines physically available
+#ifndef EIP207_GLOBAL_MAX_NOF_CE_TO_USE
+#error "EIP207_GLOBAL_MAX_NOF_CE_TO_USE is not defined"
+#endif
+
+// Maximum number of flow hash tables that should be used
+#ifndef EIP207_MAX_NOF_FLOW_HASH_TABLES_TO_USE
+#error "EIP207_MAX_NOF_FLOW_HASH_TABLES_TO_USE is not defined"
+#endif
+
+// Default Classification Engine number
+#define CE_DEFAULT_NR                                   0
+
+#if (CE_DEFAULT_NR >= EIP207_GLOBAL_MAX_NOF_CE_TO_USE)
+#error "Error: CE_DEFAULT_NR must be less than EIP207_GLOBAL_MAX_NOF_CE_TO_USE"
+#endif
+
+// Size of the ARC4 State Record in 32-bit words
+#define EIP207_CS_ARC4RC_RECORD_WORD_COUNT              64
+
+#ifndef FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT
+#define FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT     64
+#endif
+
+// I/O Area, used internally
+typedef struct
+{
+    Device_Handle_t Device;
+    uint32_t State;
+} EIP207_True_IOArea_t;
+
+#define IOAREA(_p) ((volatile EIP207_True_IOArea_t *)_p)
+
+#ifdef EIP207_GLOBAL_STRICT_ARGS
+#define EIP207_GLOBAL_CHECK_POINTER(_p) \
+    if (NULL == (_p)) \
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+#define EIP207_GLOBAL_CHECK_INT_INRANGE(_i, _min, _max) \
+    if ((_i) < (_min) || (_i) > (_max)) \
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+#define EIP207_GLOBAL_CHECK_INT_ATLEAST(_i, _min) \
+    if ((_i) < (_min)) \
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+#define EIP207_GLOBAL_CHECK_INT_ATMOST(_i, _max) \
+    if ((_i) > (_max)) \
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+#else
+/* EIP207_GLOBAL_STRICT_ARGS undefined */
+#define EIP207_GLOBAL_CHECK_POINTER(_p)
+#define EIP207_GLOBAL_CHECK_INT_INRANGE(_i, _min, _max)
+#define EIP207_GLOBAL_CHECK_INT_ATLEAST(_i, _min)
+#define EIP207_GLOBAL_CHECK_INT_ATMOST(_i, _max)
+#endif /*end of EIP207_GLOBAL_STRICT_ARGS */
+
+#define TEST_SIZEOF(type, size) \
+    extern int size##_must_bigger[1 - 2*((int)(sizeof(type) > size))]
+
+// validate the size of the fake and real IOArea structures
+TEST_SIZEOF(EIP207_True_IOArea_t, EIP207_GLOBAL_IOAREA_REQUIRED_SIZE);
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+// EIP-207 Global Control API States
+typedef enum
+{
+    EIP207_GLOBAL_STATE_INITIALIZED  = 5,
+    EIP207_GLOBAL_STATE_FATAL_ERROR  = 7,
+    EIP207_GLOBAL_STATE_RC_ENABLED   = 8,
+    EIP207_GLOBAL_STATE_FW_LOADED    = 9
+} EIP207_Global_State_t;
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Detect
+ *
+ * Checks the presence of EIP-207 hardware. Returns true when found.
+ */
+static bool
+EIP207Lib_Detect(
+        const Device_Handle_t Device,
+        const unsigned int CEnr)
+{
+    uint32_t Value;
+
+    IDENTIFIER_NOT_USED(CEnr);
+
+    Value = EIP207_Read32(Device, EIP207_CS_REG_VERSION);
+    if (!EIP207_CS_SIGNATURE_MATCH( Value ))
+        return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_HWRevision_Get
+ */
+static void
+EIP207Lib_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP207_Options_t * const Options_p,
+        EIP207_Version_t * const Version_p)
+{
+    EIP207_CS_VERSION_RD(
+                      Device,
+                      &Version_p->EipNumber,
+                      &Version_p->ComplmtEipNumber,
+                      &Version_p->HWPatchLevel,
+                      &Version_p->MinHWRevision,
+                      &Version_p->MajHWRevision);
+
+    EIP207_CS_OPTIONS_RD(Device,
+                         &Options_p->NofLookupTables,
+                         &Options_p->fLookupCached,
+                         &Options_p->NofLookupClients,
+                         &Options_p->fCombinedTRC_ARC4,
+                         &Options_p->fCombinedFRC_ARC4,
+                         &Options_p->fARC4Present,
+                         &Options_p->NofARC4_Clients,
+                         &Options_p->fCombinedFRC_TRC,
+                         &Options_p->NofTRC_Clients,
+                         &Options_p->NofFRC_Clients,
+                         &Options_p->NofCacheSets);
+}
+
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Global_State_Set
+ *
+ */
+static EIP207_Global_Error_t
+EIP207Lib_Global_State_Set(
+        EIP207_Global_State_t * const CurrentState,
+        const EIP207_Global_State_t NewState)
+{
+    switch(*CurrentState)
+    {
+        case EIP207_GLOBAL_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP207_GLOBAL_STATE_RC_ENABLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP207_GLOBAL_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+         case EIP207_GLOBAL_STATE_RC_ENABLED:
+            switch(NewState)
+            {
+                case EIP207_GLOBAL_STATE_FW_LOADED:
+                   *CurrentState = NewState;
+                   break;
+                case EIP207_GLOBAL_STATE_FATAL_ERROR:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+    }
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_Init
+ */
+EIP207_Global_Error_t
+EIP207_Global_Init(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device,
+        EIP207_Global_CacheConfig_t * const CacheConf_p,
+        const EIP207_Global_FLUEConfig_t * const FLUEConf_p)
+{
+    unsigned int FLUE_NofLookupTables;
+    EIP207_Global_Capabilities_t Capabilities;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int i;
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(CacheConf_p);
+    EIP207_GLOBAL_CHECK_POINTER(FLUEConf_p);
+
+    // Detect presence of EIP-207 HW hardware
+    if (!EIP207Lib_Detect(Device, CE_DEFAULT_NR))
+        return EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+    TrueIOArea_p->State = (uint32_t)EIP207_GLOBAL_STATE_INITIALIZED;
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+    ZEROINIT(Capabilities);
+
+    EIP207Lib_HWRevision_Get(Device,
+                             &Capabilities.EIP207_Options,
+                             &Capabilities.EIP207_Version);
+
+    FLUE_NofLookupTables = Capabilities.EIP207_Options.NofLookupTables;
+
+    // 0 hash tables has a special meaning for the EIP-207 FLUE HW
+    if (FLUE_NofLookupTables == 0)
+        FLUE_NofLookupTables = EIP207_GLOBAL_MAX_HW_NOF_FLOW_HASH_TABLES;
+
+    // Check actual configuration HW against capabilities
+    // Number of configured cache sets and hash tables
+    if ((Capabilities.EIP207_Options.NofCacheSets <
+            EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE) ||
+        (FLUE_NofLookupTables <
+            EIP207_MAX_NOF_FLOW_HASH_TABLES_TO_USE)  ||
+        (FLUEConf_p->HashTablesCount >
+            EIP207_MAX_NOF_FLOW_HASH_TABLES_TO_USE))
+        return EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Configure EIP-207 Classification Engine
+
+    // Initialize Record Caches
+    {
+        EIP207_Global_Error_t rv;
+
+        // Initialize Flow Record Cache
+#ifndef EIP207_GLOBAL_FRC_DISABLE
+        if ((EIP97_SupportedFuncs_Get() & BIT_3) != 0)
+        {
+            for (i=0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+            {
+                CacheConf_p->FRC[i].DataWordCount = EIP207_FRC_RAM_WORD_COUNT;
+                CacheConf_p->FRC[i].AdminWordCount =
+                    EIP207_FRC_ADMIN_RAM_WORD_COUNT;
+            }
+
+            rv = EIP207_RC_Internal_Init(
+                Device,
+                EIP207_RC_INTERNAL_NOT_COMBINED,
+                EIP207_FRC_REG_BASE,
+                CacheConf_p->FRC,
+                FIRMWARE_EIP207_CS_FRC_RECORD_WORD_COUNT);
+            if (rv != EIP207_GLOBAL_NO_ERROR)
+                return rv;
+        }
+#endif // EIP207_GLOBAL_FRC_DISABLE
+        for (i=0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+        {
+            CacheConf_p->TRC[i].DataWordCount = EIP207_TRC_RAM_WORD_COUNT;
+            CacheConf_p->TRC[i].AdminWordCount =
+                EIP207_TRC_ADMIN_RAM_WORD_COUNT;
+        }
+
+        // Initialize Transform Record Cache
+        rv = EIP207_RC_Internal_Init(
+                 Device,
+                 Capabilities.EIP207_Options.fCombinedFRC_TRC ?
+                         EIP207_RC_INTERNAL_FRC_TRC_COMBINED :
+                                EIP207_RC_INTERNAL_NOT_COMBINED,
+                 EIP207_TRC_REG_BASE,
+                 CacheConf_p->TRC,
+                 FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT);
+        if (rv != EIP207_GLOBAL_NO_ERROR)
+            return rv;
+
+        // Check if ARC4 Record Cache is available
+        if ( Capabilities.EIP207_Options.fARC4Present )
+        {
+            for (i=0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+            {
+                CacheConf_p->ARC4[i].DataWordCount =
+                    EIP207_ARC4RC_RAM_WORD_COUNT;
+                CacheConf_p->ARC4[i].AdminWordCount =
+                    EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT;
+            }
+            // Initialize ARC4 Record Cache
+            rv = EIP207_RC_Internal_Init(
+                    Device,
+                    Capabilities.EIP207_Options.fCombinedFRC_ARC4 ?
+                        EIP207_RC_INTERNAL_FRC_ARC4_COMBINED :
+                    (Capabilities.EIP207_Options.fCombinedTRC_ARC4 ?
+                          EIP207_RC_INTERNAL_TRC_ARC4_COMBINED :
+                                    EIP207_RC_INTERNAL_NOT_COMBINED),
+                    EIP207_ARC4RC_REG_BASE,
+                    CacheConf_p->ARC4,
+                    FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT);
+            if (rv != EIP207_GLOBAL_NO_ERROR)
+                return rv;
+        }
+    }
+
+    // Initialize Flow Hash Engine, set IV values
+    EIP207_FHASH_IV_WR(Device,
+                       FLUEConf_p->IV.IV_Word32[0],
+                       FLUEConf_p->IV.IV_Word32[1],
+                       FLUEConf_p->IV.IV_Word32[2],
+                       FLUEConf_p->IV.IV_Word32[3]);
+
+    // Initialize FLUE Hash Tables
+    {
+        unsigned int i;
+
+        for (i = 0; i < FLUEConf_p->HashTablesCount; i++)
+            EIP207_FLUE_Init(Device,
+                             i,
+                             FLUEConf_p,
+                             Capabilities.EIP207_Options.fARC4Present,
+                             Capabilities.EIP207_Options.fLookupCached);
+    }
+
+    // Initialize optional FLUE Cache
+    if (Capabilities.EIP207_Options.fLookupCached)
+    {
+        EIP207_FLUEC_CTRL_WR(Device,
+                             false,        // Disable cache RAM access
+                             FLUEConf_p->fDelayMemXS,
+                             EIP207_FLUEC_TABLE_SIZE,
+                             EIP207_FLUEC_GROUP_SIZE,
+                             FLUEConf_p->CacheChain);  // Cache chain
+    }
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+        {
+            EIP207_Global_Error_t rv;
+            uint32_t State = TrueIOArea_p->State;
+
+            // Transit to a new state
+            rv = EIP207Lib_Global_State_Set(
+                    (EIP207_Global_State_t* const)&State,
+                    EIP207_GLOBAL_STATE_RC_ENABLED);
+
+            TrueIOArea_p->State = State;
+
+            if (rv != EIP207_GLOBAL_NO_ERROR)
+                return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_Firmware_Load
+ */
+EIP207_Global_Error_t
+EIP207_Global_Firmware_Load(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const unsigned int TimerPrescaler,
+        EIP207_Firmware_t * const IPUE_Firmware_p,
+        EIP207_Firmware_t * const IFPP_Firmware_p,
+        EIP207_Firmware_t * const OPUE_Firmware_p,
+        EIP207_Firmware_t * const OFPP_Firmware_p)
+{
+    EIP207_Global_Error_t EIP207_Rc;
+    Device_Handle_t Device;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Download EIP-207c Input Classification Engine (ICE) firmware,
+    // use the same images for all the instances of the engine
+    EIP207_Rc = EIP207_ICE_Firmware_Load(Device,
+                                         TimerPrescaler,
+                                         IPUE_Firmware_p,
+                                         IFPP_Firmware_p);
+    if (EIP207_Rc != EIP207_GLOBAL_NO_ERROR)
+        return EIP207_Rc;
+
+    // Download EIP-207c Output Classification Engine (OCE) firmware,
+    // use the same images for all the instances of the engine
+    // Download Input Classification Engine (OCE) firmware
+    EIP207_Rc = EIP207_OCE_Firmware_Load(Device,
+                                             TimerPrescaler,
+                                             OPUE_Firmware_p,
+                                             OFPP_Firmware_p);
+        // OCE is not supported by this EIP-207 HW version
+    if (EIP207_Rc != EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR &&
+        EIP207_Rc != EIP207_GLOBAL_NO_ERROR) // OCE is supported
+        return EIP207_Rc; // OCE FW download error, abort!
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+        {
+            EIP207_Global_Error_t rv;
+            uint32_t State = TrueIOArea_p->State;
+
+            // Transit to a new state
+            rv = EIP207Lib_Global_State_Set(
+                    (EIP207_Global_State_t* const)&State,
+                    EIP207_GLOBAL_STATE_FW_LOADED);
+
+            TrueIOArea_p->State = State;
+
+            if (rv != EIP207_GLOBAL_NO_ERROR)
+                return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_HWRevision_Get
+ */
+EIP207_Global_Error_t
+EIP207_Global_HWRevision_Get(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        EIP207_Global_Capabilities_t * const Capabilities_p)
+{
+    Device_Handle_t Device;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(Capabilities_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP207Lib_HWRevision_Get(Device,
+                             &Capabilities_p->EIP207_Options,
+                             &Capabilities_p->EIP207_Version);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_GlobalStats_Get
+ */
+EIP207_Global_Error_t
+EIP207_Global_GlobalStats_Get(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const unsigned int CE_Number,
+        EIP207_Global_GlobalStats_t * const GlobalStats_p)
+{
+    Device_Handle_t Device;
+    EIP207_Global_Error_t rv;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(GlobalStats_p);
+
+    if(CE_Number >= EIP207_GLOBAL_MAX_NOF_CE_TO_USE)
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    rv = EIP207_ICE_GlobalStats_Get(Device, CE_Number, &GlobalStats_p->ICE);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_OCE_GlobalStats_Get(Device, CE_Number, &GlobalStats_p->OCE);
+    if (rv == EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR)
+        return EIP207_GLOBAL_NO_ERROR; // OCE is not supported
+    else                               // by this EIP-207 HW version
+        return rv;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_ClockCount_Get
+ */
+EIP207_Global_Error_t
+EIP207_Global_ClockCount_Get(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const unsigned int CE_Number,
+        EIP207_Global_Clock_t * const Clock_p)
+{
+    Device_Handle_t Device;
+    EIP207_Global_Error_t rv;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(Clock_p);
+
+    if(CE_Number >= EIP207_GLOBAL_MAX_NOF_CE_TO_USE)
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    rv = EIP207_ICE_ClockCount_Get(Device, CE_Number, &Clock_p->ICE);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_OCE_ClockCount_Get(Device, CE_Number, &Clock_p->OCE);
+    if (rv == EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR)
+        return EIP207_GLOBAL_NO_ERROR; // OCE is not supported
+    else                               // by this EIP-207 HW version
+        return rv;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * EIP207_Global_Status_Get
+ */
+EIP207_Global_Error_t
+EIP207_Global_Status_Get(
+        EIP207_Global_IOArea_t * const IOArea_p,
+        const unsigned int CE_Number,
+        EIP207_Global_Status_t * const Status_p,
+        bool * const fFatalError_p)
+{
+    unsigned int i;
+    Device_Handle_t Device;
+    EIP207_Global_Error_t rv;
+    bool fFatalError = false;
+    volatile EIP207_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP207_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP207_GLOBAL_CHECK_POINTER(Status_p);
+    EIP207_GLOBAL_CHECK_POINTER(fFatalError_p);
+
+    if(CE_Number >= EIP207_GLOBAL_MAX_NOF_CE_TO_USE)
+        return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    rv = EIP207_ICE_Status_Get(Device, CE_Number, &Status_p->ICE);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_OCE_Status_Get(Device, CE_Number, &Status_p->OCE);
+    if (rv != EIP207_GLOBAL_NO_ERROR &&
+        rv != EIP207_GLOBAL_UNSUPPORTED_FEATURE_ERROR)
+        return rv;
+
+    EIP207_FLUE_Status_Get(Device, &Status_p->FLUE);
+
+    if (Status_p->ICE.fPUE_EccDerr   ||
+        Status_p->ICE.fFPP_EccDerr   ||
+        Status_p->OCE.fPUE_EccDerr ||
+        Status_p->OCE.fFPP_EccDerr ||
+        Status_p->ICE.fTimerOverflow ||
+        Status_p->OCE.fTimerOverflow ||
+        Status_p->FLUE.Error1 != 0   ||
+        Status_p->FLUE.Error2 != 0)
+        fFatalError = true;
+
+    for (i = 0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+    {
+        EIP207_RC_Internal_Status_Get(Device,
+                                      i,
+                                      &Status_p->FRC[i],
+                                      &Status_p->TRC[i],
+                                      &Status_p->ARC4RC[i]);
+        if (Status_p->FRC[i].fDMAReadError ||
+            Status_p->FRC[i].fDMAWriteError ||
+            Status_p->FRC[i].fAdminEccErr ||
+            Status_p->FRC[i].fDataEccOflo ||
+            Status_p->TRC[i].fDMAReadError ||
+            Status_p->TRC[i].fDMAWriteError ||
+            Status_p->TRC[i].fAdminEccErr ||
+            Status_p->TRC[i].fDataEccOflo ||
+            Status_p->ARC4RC[i].fDMAReadError ||
+            Status_p->ARC4RC[i].fDMAWriteError ||
+            Status_p->ARC4RC[i].fAdminEccErr ||
+            Status_p->ARC4RC[i].fDataEccOflo)
+            fFatalError = true;
+
+        EIP207_RC_Internal_DebugStatistics_Get(Device,
+                                               i,
+                                               &Status_p->FRCStats[i],
+                                               &Status_p->TRCStats[i]);
+    }
+
+    *fFatalError_p = fFatalError;
+
+#ifdef EIP207_GLOBAL_DEBUG_FSM
+    if (fFatalError)
+    {
+        uint32_t State = TrueIOArea_p->State;
+
+        // Transit to a new state
+        rv = EIP207Lib_Global_State_Set(
+                (EIP207_Global_State_t* const)&State,
+                EIP207_GLOBAL_STATE_FATAL_ERROR);
+
+        TrueIOArea_p->State = State;
+
+        if (rv != EIP207_GLOBAL_NO_ERROR)
+            return EIP207_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP207_GLOBAL_DEBUG_FSM
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip207_global_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_ice.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_ice.c
new file mode 100644
index 0000000..9f2e019
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_ice.c
@@ -0,0 +1,572 @@
+/* eip207_ice.c
+ *
+ * EIP-207c Input Classification Engine (ICE) interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207c Input Classification Engine (ICE) interface
+#include "eip207_ice.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// EIP-207 HW interface
+#include "eip207_hw_interface.h"
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+#include "device_rw.h"                  // Read32, Write32
+
+// EIP-207 Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+// EIP-207 Firmware Download API
+#include "firmware_eip207_api_dwld.h"   // Classification API: FW download
+
+// EIP-207 Support API
+#include "eip207_support.h"
+
+// EIP97_Interfaces_Get()
+#include "eip97_global_internal.h"
+
+#include "clib.h"                       // memcmp
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// Allow legacy firmware to be used, which does not have these constants.
+#ifndef FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#define FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_LAST_BYTE_COUNT
+#endif
+#ifndef FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#define FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#endif
+
+// Number fo words to check when reading firmware back.
+#define EIP207_FW_CHECK_WORD_COUNT 16
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_ICE_Firmware_Load
+ */
+EIP207_Global_Error_t
+EIP207_ICE_Firmware_Load(
+        const Device_Handle_t Device,
+        const unsigned int TimerPrescaler,
+        EIP207_Firmware_t * const PUE_Firmware_p,
+        EIP207_Firmware_t * const FPP_Firmware_p)
+{
+    unsigned int NofCEs;
+    EIP97_Interfaces_Get(&NofCEs,NULL,NULL,NULL);
+    // Check if the Adapter provides the IPUE firmware image with correct size.
+    if (!PUE_Firmware_p->Image_p ||
+        PUE_Firmware_p->ImageWordCount > EIP207_IPUE_PROG_RAM_WORD_COUNT)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+    // Check if the Adapter provides the IFPP firmware image with correct size.
+    if (!FPP_Firmware_p->Image_p ||
+        FPP_Firmware_p->ImageWordCount > EIP207_IPUE_PROG_RAM_WORD_COUNT)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+
+    // Clear EIP-207c ICE Scratchpad RAM where the the firmware
+    // administration data will be located
+    {
+        unsigned int i, CECount, BlockCount, RequiredRAMByteCount;
+
+        RequiredRAMByteCount =
+                MAX(FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT,
+                    FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT);
+
+        // Check if the administration RAM required by the EIP-207 firmware
+        // fits into physically available scratchpad RAM
+        if ((EIP207_ICE_SCRATCH_RAM_128B_BLOCK_COUNT * 128) <
+            RequiredRAMByteCount)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+        // Calculate how many 128-byte blocks are required for the firmware
+        // administration data
+        BlockCount = (RequiredRAMByteCount + 127) / 128;
+
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            // Make ICE Scratchpad RAM accessible and set the timer
+            EIP207_ICE_SCRATCH_CTRL_WR(
+                    Device,
+                    CECount,
+                    true, // Change timer
+                    true, // Enable timer
+                    (uint16_t)TimerPrescaler,
+                    EIP207_ICE_SCRATCH_TIMER_OFLO_BIT, // Timer overflow bit
+                    true, // Change access
+                    (uint8_t)BlockCount);
+
+#ifdef DEBUG
+            // Check if the timer runs
+            {
+                uint32_t Value32;
+                unsigned int i;
+
+                for (i = 0; i < 10; i++)
+                {
+                    Value32 = Device_Read32(Device,
+                                            EIP207_ICE_REG_TIMER_LO(CECount));
+
+                    if (Value32 == 0)
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+            }
+#endif
+
+            // Write the ICE Scratchpad RAM with 0
+            for(i = 0; i < (BlockCount * 32); i++)
+            {
+                Device_Write32(Device,
+                               EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                                                           i * sizeof(uint32_t),
+                               0);
+#ifdef DEBUG
+                // Perform read-back check
+                {
+                    uint32_t Value32 =
+                        Device_Read32(
+                               Device,
+                               EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                                                           i * sizeof(uint32_t));
+
+                    if (Value32 != 0)
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+#endif
+            }
+        }
+
+        // Leave the scratchpad RAM accessible for the Host
+    }
+
+    // Download the firmware
+    {
+        unsigned int CECount;
+#ifdef DEBUG
+        unsigned int i;
+#endif
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            // Reset the Input Flow Post-Processor micro-engine (IFPP) to make its
+            // Program RAM accessible
+            EIP207_ICE_FPP_CTRL_WR(Device,
+                                   CECount,
+                                   0,     // No start address for debug mode
+                                   1,       // Clear ECC correctable error
+                                   1,       // Clear ECC non-correctable error
+                                   false, // Debug mode OFF
+                                   true); // SW Reset ON
+
+            // Enable access to IFPP Program RAM
+            EIP207_ICE_RAM_CTRL_WR(Device, CECount, false, true);
+        }
+
+#ifdef DEBUG
+        // Write the Input Flow post-Processor micro-Engine firmware
+        for(i = 0; i < FPP_Firmware_p->ImageWordCount; i++)
+        {
+            Device_Write32(Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t),
+                           FPP_Firmware_p->Image_p[i]);
+            // Perform read-back check
+            {
+                uint32_t Value32 =
+                    Device_Read32(
+                           Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t));
+
+                if (Value32 != FPP_Firmware_p->Image_p[i])
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+            }
+        }
+#else
+        Device_Write32Array(Device,
+                            EIP207_CS_RAM_XS_SPACE_BASE,
+                            FPP_Firmware_p->Image_p,
+                            FPP_Firmware_p->ImageWordCount);
+        // Perform read-back check of small subset
+        {
+            static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT];
+            Device_Read32Array(Device,
+                               EIP207_CS_RAM_XS_SPACE_BASE,
+                               ReadBuf,
+                               EIP207_FW_CHECK_WORD_COUNT);
+            if (memcmp(ReadBuf,
+                       FPP_Firmware_p->Image_p,
+                       EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0)
+                return EIP207_GLOBAL_INTERNAL_ERROR;
+
+        }
+#endif
+
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            // Disable access to IFPP Program RAM
+            // Enable access to IPUE Program RAM
+            EIP207_ICE_RAM_CTRL_WR(Device, CECount, true, false);
+
+            // Reset the Input Pull-Up micro-Engine (IPUE) to make its
+            // Program RAM accessible
+            EIP207_ICE_PUE_CTRL_WR(Device,
+                                   CECount,
+                                   0,     // No start address for debug mode
+                                   1,       // Clear ECC correctable error
+                                   1,       // Clear ECC non-correctable error
+                                   false, // Debug mode OFF
+                                   true); // SW Reset ON
+        }
+
+#ifdef DEBUG
+        // Write the Input Pull-Up micro-Engine firmware
+        for(i = 0; i < PUE_Firmware_p->ImageWordCount; i++)
+        {
+            Device_Write32(Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t),
+                           PUE_Firmware_p->Image_p[i]);
+            // Perform read-back check
+            {
+                uint32_t Value32 =
+                    Device_Read32(
+                           Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t));
+
+                if (Value32 != PUE_Firmware_p->Image_p[i])
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+            }
+        }
+#else
+        Device_Write32Array(Device,
+                            EIP207_CS_RAM_XS_SPACE_BASE,
+                            PUE_Firmware_p->Image_p,
+                            PUE_Firmware_p->ImageWordCount);
+        // Perform read-back check of small subset
+        {
+            static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT];
+            Device_Read32Array(Device,
+                               EIP207_CS_RAM_XS_SPACE_BASE,
+                               ReadBuf,
+                               EIP207_FW_CHECK_WORD_COUNT);
+            if (memcmp(ReadBuf,
+                       PUE_Firmware_p->Image_p,
+                       EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0)
+                return EIP207_GLOBAL_INTERNAL_ERROR;
+
+        }
+#endif
+
+        // Disable access to IPUE Program RAM
+        for (CECount = 0; CECount < NofCEs; CECount++)
+            EIP207_ICE_RAM_CTRL_WR(Device, CECount, false, false);
+
+#ifdef EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK
+        // Check the firmware version and start all the engines
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            uint32_t Value32;
+            unsigned int Ma, Mi, Pl, i;
+            bool fUpdated;
+
+            // Start the IFPP in Debug mode for the firmware version check
+            EIP207_ICE_FPP_CTRL_WR(
+                        Device,
+                        CECount,
+                        FIRMWARE_EIP207_DWLD_IFPP_VERSION_CHECK_DBG_PROG_CNTR,
+                        1,       // Clear ECC correctable error
+                        1,       // Clear ECC non-correctable error
+                        true,    // Debug mode ON
+                        false);  // SW Reset OFF
+
+            // Wait for the IFPP version update
+            for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++)
+            {
+                Value32 = Device_Read32(
+                        Device,
+                        EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                        FIRMWARE_EIP207_DWLD_ADMIN_RAM_IFPP_CTRL_BYTE_OFFSET);
+
+                FIRMWARE_EIP207_DWLD_IFPP_VersionUpdated_Read(Value32,
+                                                              &fUpdated);
+
+                if (fUpdated)
+                    break;
+            }
+
+            if (!fUpdated)
+                return EIP207_GLOBAL_INTERNAL_ERROR;
+
+            Value32 = Device_Read32(
+                      Device,
+                      EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                      FIRMWARE_EIP207_DWLD_ADMIN_RAM_IFPP_VERSION_BYTE_OFFSET);
+
+            FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl);
+
+            if (FPP_Firmware_p->Major == 0 &&
+                FPP_Firmware_p->Minor == 0 &&
+                FPP_Firmware_p->PatchLevel == 0)
+            {  // Adapter did not provide expected version, return it.
+                FPP_Firmware_p->Major = Ma;
+                FPP_Firmware_p->Minor = Mi;
+                FPP_Firmware_p->PatchLevel = Pl;
+            }
+            else
+            {
+                // Adapter provided expected version, check it.
+                if (FPP_Firmware_p->Major != Ma ||
+                    FPP_Firmware_p->Minor != Mi ||
+                    FPP_Firmware_p->PatchLevel != Pl)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+            }
+
+            // Start the IPUE in Debug mode for the firmware version check
+            EIP207_ICE_PUE_CTRL_WR(
+                        Device,
+                        CECount,
+                        FIRMWARE_EIP207_DWLD_IPUE_VERSION_CHECK_DBG_PROG_CNTR,
+                        1,       // Clear ECC correctable error
+                        1,       // Clear ECC non-correctable error
+                        true,    // Debug mode ON
+                        false);  // SW Reset OFF
+
+            // Wait for the IPUE version update
+            for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++)
+            {
+                Value32 = Device_Read32(
+                        Device,
+                        EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                        FIRMWARE_EIP207_DWLD_ADMIN_RAM_IPUE_CTRL_BYTE_OFFSET);
+
+                FIRMWARE_EIP207_DWLD_IPUE_VersionUpdated_Read(Value32,
+                                                              &fUpdated);
+
+                if (fUpdated)
+                    break;
+            }
+
+            if (!fUpdated)
+                return EIP207_GLOBAL_INTERNAL_ERROR;
+
+            Value32 = Device_Read32(
+                     Device,
+                     EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                     FIRMWARE_EIP207_DWLD_ADMIN_RAM_IPUE_VERSION_BYTE_OFFSET);
+
+            FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl);
+
+            if (PUE_Firmware_p->Major == 0 &&
+                PUE_Firmware_p->Minor == 0 &&
+                PUE_Firmware_p->PatchLevel == 0)
+            {  // Adapter did not provide expected version, return it.
+                PUE_Firmware_p->Major = Ma;
+                PUE_Firmware_p->Minor = Mi;
+                PUE_Firmware_p->PatchLevel = Pl;
+            }
+            else
+            {
+                // Adapter provided expected version, check it.
+                if (PUE_Firmware_p->Major != Ma ||
+                    PUE_Firmware_p->Minor != Mi ||
+                    PUE_Firmware_p->PatchLevel != Pl)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+            }
+        } // for
+#else
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            // Start the IFPP in Debug mode
+            EIP207_ICE_FPP_CTRL_WR(
+                            Device,
+                            CECount,
+                            FIRMWARE_EIP207_DWLD_IFPP_VERSION_CHECK_DBG_PROG_CNTR,
+                            1,       // Clear ECC correctable error
+                            1,       // Clear ECC non-correctable error
+                            true,    // Debug mode ON
+                            false);  // SW Reset OFF
+
+            // Start the IPUE in Debug mode
+            EIP207_ICE_PUE_CTRL_WR(
+                            Device,
+                            CECount,
+                            FIRMWARE_EIP207_DWLD_IPUE_VERSION_CHECK_DBG_PROG_CNTR,
+                            1,       // Clear ECC correctable error
+                            1,       // Clear ECC non-correctable error
+                            true,    // Debug mode ON
+                            false);  // SW Reset OFF
+        } // for
+#endif // EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK
+        for (CECount = 0; CECount < NofCEs; CECount++)
+        {
+            uint32_t InputBufferSize = Device_Read32(
+                Device,
+                EIP207_ICE_REG_SCRATCH_RAM(CECount) +
+                4*33) & MASK_16_BITS;
+            if (InputBufferSize != 0)
+            {
+                if (PUE_Firmware_p->Major > 3 ||
+                    (PUE_Firmware_p->Major ==3 &&
+                     PUE_Firmware_p->Minor >=1))
+                {
+                    InputBufferSize -= 2048;
+                }
+                else
+                {
+                    InputBufferSize = (InputBufferSize * 3) / 4;
+                }
+                EIP207_ICE_ADAPT_CTRL_WR(Device, CECount, InputBufferSize);
+            }
+            EIP207_ICE_PUTF_CTRL_WR(Device, CECount, 3, false);
+            EIP207_ICE_PPTF_CTRL_WR(Device, CECount, 0, false);
+        }
+    }
+
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_ICE_GlobalStats_Get
+ */
+EIP207_Global_Error_t
+EIP207_ICE_GlobalStats_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_ICE_GlobalStats_t * const ICE_GlobalStats_p)
+{
+    EIP207_Global_Error_t rv;
+
+    rv = EIP207_Global_Read64(
+                       Device,
+                       EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                         FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_DROP_LO_BYTE_OFFSET,
+                       EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                         FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_DROP_HI_BYTE_OFFSET,
+                       &ICE_GlobalStats_p->DroppedPacketsCounter);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_Global_Read64(
+                     Device,
+                     EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                       FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_IN_OCT_LO_BYTE_OFFSET,
+                     EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                       FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_IN_OCT_HI_BYTE_OFFSET,
+                     &ICE_GlobalStats_p->InboundOctetsCounter);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    rv = EIP207_Global_Read64(
+                    Device,
+                    EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                      FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_OUT_OCT_LO_BYTE_OFFSET,
+                    EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                      FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_OUT_OCT_HI_BYTE_OFFSET,
+                    &ICE_GlobalStats_p->OutboundOctetsCounter);
+    if (rv != EIP207_GLOBAL_NO_ERROR)
+        return rv;
+
+    ICE_GlobalStats_p->InboundPacketsCounter =
+    Device_Read32(Device,
+                  EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                  FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_IN_PKT_BYTE_OFFSET);
+
+    ICE_GlobalStats_p->OutboundPacketCounter =
+    Device_Read32(Device,
+                  EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                  FIRMWARE_EIP207_CS_ADMIN_RAM_STAT_OUT_PKT_BYTE_OFFSET);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_ICE_ClockCount_Get
+ */
+EIP207_Global_Error_t
+EIP207_ICE_ClockCount_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_Value64_t * const ICE_Clock_p)
+{
+    return EIP207_Global_Read64(
+                            Device,
+                            EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                              FIRMWARE_EIP207_CS_ADMIN_RAM_TIME_LO_BYTE_OFFSET,
+                            EIP207_ICE_REG_SCRATCH_RAM(CE_Number) +
+                              FIRMWARE_EIP207_CS_ADMIN_RAM_TIME_HI_BYTE_OFFSET,
+                            ICE_Clock_p);
+}
+
+
+/*-----------------------------------------------------------------------------
+ * EIP207_ICE_Status_Get
+ */
+EIP207_Global_Error_t
+EIP207_ICE_Status_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_CE_Status_t * const ICE_Status_p)
+{
+    EIP207_ICE_PUE_CTRL_RD_CLEAR(Device,
+                           CE_Number,
+                           &ICE_Status_p->fPUE_EccCorr,
+                           &ICE_Status_p->fPUE_EccDerr);
+
+    EIP207_ICE_FPP_CTRL_RD_CLEAR(Device,
+                           CE_Number,
+                           &ICE_Status_p->fFPP_EccCorr,
+                           &ICE_Status_p->fFPP_EccDerr);
+
+    EIP207_ICE_SCRATCH_CTRL_RD(Device,
+                               CE_Number,
+                               &ICE_Status_p->fTimerOverflow);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip207_ice.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_oce.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_oce.c
new file mode 100644
index 0000000..7d29ed2
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_oce.c
@@ -0,0 +1,514 @@
+/* eip207_oce.c
+ *
+ * EIP-207c Output Classification Engine (OCE) interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207c Output Classification Engine (OCE) interface
+#include "eip207_oce.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// Driver Framework C Run-Time Library Abstraction API
+#include "clib.h"                 // ZEROINIT
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+#include "device_rw.h"                  // Read32, Write32
+
+// EIP-207 Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+// EIP-207 Firmware Download API
+#include "firmware_eip207_api_dwld.h"   // Classification API: FW download
+
+// EIP97_Interfaces_Get()
+#include "eip97_global_internal.h"
+
+// EIP97 Global init API
+#include "eip97_global_init.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// Allow legacy firmware to be used, which does not have these constants.
+#ifndef FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#define FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_LAST_BYTE_COUNT
+#endif
+#ifndef FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#define FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT
+#endif
+
+// Number fo words to check when reading firmware back.
+#define EIP207_FW_CHECK_WORD_COUNT 16
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_OCE_Firmware_Load
+ */
+EIP207_Global_Error_t
+EIP207_OCE_Firmware_Load(
+        const Device_Handle_t Device,
+        const unsigned int TimerPrescaler,
+        EIP207_Firmware_t * const PUE_Firmware_p,
+        EIP207_Firmware_t * const FPP_Firmware_p)
+{
+    unsigned int NofCEs;
+
+    if ((EIP97_SupportedFuncs_Get() & BIT_1) != 0)
+    {
+        EIP97_Interfaces_Get(&NofCEs,NULL,NULL,NULL);
+        // Check if the Adapter provides the OPUE firmware image with correct size.
+        if (!PUE_Firmware_p->Image_p ||
+            PUE_Firmware_p->ImageWordCount > EIP207_OPUE_PROG_RAM_WORD_COUNT)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+        // Check if the Adapter provides the OFPP firmware image with correct size.
+        if (!FPP_Firmware_p->Image_p ||
+            FPP_Firmware_p->ImageWordCount > EIP207_OPUE_PROG_RAM_WORD_COUNT)
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+
+        // Clear EIP-207c OCE Scratchpad RAM where the the firmware
+        // administration data will be located
+        {
+            unsigned int i, CECount, BlockCount, RequiredRAMByteCount;
+
+            RequiredRAMByteCount =
+                MAX(FIRMWARE_EIP207_CS_ADMIN_RAM_INPUT_LAST_BYTE_COUNT,
+                    FIRMWARE_EIP207_DWLD_ADMIN_RAM_INPUT_LAST_BYTE_COUNT);
+
+            // Check if the administration RAM required by the EIP-207 firmware
+            // fits into physically available scratchpad RAM
+            if ((EIP207_OCE_SCRATCH_RAM_128B_BLOCK_COUNT * 128) <
+                RequiredRAMByteCount)
+                return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+            // Calculate how many 128-byte blocks are required for the firmware
+            // administration data
+            BlockCount = (RequiredRAMByteCount + 127) / 128;
+
+            for (CECount = 0; CECount < NofCEs; CECount++)
+            {
+                // Make OCE Scratchpad RAM accessible and set the timer
+                EIP207_OCE_SCRATCH_CTRL_WR(
+                    Device,
+                    CECount,
+                    true, // Change timer
+                    true, // Enable timer
+                    (uint16_t)TimerPrescaler,
+                    EIP207_OCE_SCRATCH_TIMER_OFLO_BIT, // Timer overflow bit
+                    true, // Change access
+                    (uint8_t)BlockCount);
+
+#ifdef DEBUG
+                // Check if the timer runs
+                {
+                    uint32_t Value32;
+                    unsigned int i;
+
+                    for (i = 0; i < 10; i++)
+                    {
+                        Value32 = Device_Read32(Device,
+                                                EIP207_OCE_REG_TIMER_LO(CECount));
+
+                        if (Value32 == 0)
+                            return EIP207_GLOBAL_INTERNAL_ERROR;
+                    }
+                }
+#endif
+
+                // Write the OCE Scratchpad RAM with 0
+                for(i = 0; i < (BlockCount * 32); i++)
+                {
+                    Device_Write32(Device,
+                                   EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                                   i * sizeof(uint32_t),
+                                   0);
+#ifdef DEBUG
+                    // Perform read-back check
+                    {
+                        uint32_t Value32 =
+                            Device_Read32(
+                                Device,
+                                EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                                i * sizeof(uint32_t));
+
+                        if (Value32 != 0)
+                            return EIP207_GLOBAL_INTERNAL_ERROR;
+                    }
+#endif
+                }
+            }
+
+            // Leave the scratchpad RAM accessible for the Host
+        }
+
+        // Download the firmware
+        {
+            unsigned int CECount;
+#ifdef DEBUG
+            unsigned int i;
+#endif
+            for (CECount = 0; CECount < NofCEs; CECount++)
+            {
+                // Reset the Input Flow Post-Processor micro-engine (OFPP) to make its
+                // Program RAM accessible
+                EIP207_OCE_FPP_CTRL_WR(Device,
+                                       CECount,
+                                       0,     // No start address for debug mode
+                                       1,       // Clear ECC correctable error
+                                       1,       // Clear ECC non-correctable error
+                                       false, // Debug mode OFF
+                                       true); // SW Reset ON
+
+                // Enable access to OFPP Program RAM
+                EIP207_OCE_RAM_CTRL_WR(Device, CECount, false, true);
+            }
+
+#ifdef DEBUG
+            // Write the Input Flow post-Processor micro-Engine firmware
+            for(i = 0; i < FPP_Firmware_p->ImageWordCount; i++)
+            {
+                Device_Write32(Device,
+                               EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t),
+                               FPP_Firmware_p->Image_p[i]);
+                // Perform read-back check
+                {
+                    uint32_t Value32 =
+                        Device_Read32(
+                            Device,
+                           EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t));
+
+                    if (Value32 != FPP_Firmware_p->Image_p[i])
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+            }
+#else
+            Device_Write32Array(Device,
+                                EIP207_CS_RAM_XS_SPACE_BASE,
+                                FPP_Firmware_p->Image_p,
+                                FPP_Firmware_p->ImageWordCount);
+            // Perform read-back check of small subset
+            {
+                static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT];
+                Device_Read32Array(Device,
+                                   EIP207_CS_RAM_XS_SPACE_BASE,
+                                   ReadBuf,
+                                   EIP207_FW_CHECK_WORD_COUNT);
+                if (memcmp(ReadBuf,
+                           FPP_Firmware_p->Image_p,
+                           EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+
+            }
+#endif
+
+            for (CECount = 0; CECount < NofCEs; CECount++)
+            {
+                // Disable access to OFPP Program RAM
+                // Enable access to OPUE Program RAM
+                EIP207_OCE_RAM_CTRL_WR(Device, CECount, true, false);
+
+                // Reset the Input Pull-Up micro-Engine (OPUE) to make its
+                // Program RAM accessible
+                EIP207_OCE_PUE_CTRL_WR(Device,
+                                       CECount,
+                                       0,     // No start address for debug mode
+                                       1,       // Clear ECC correctable error
+                                       1,       // Clear ECC non-correctable error
+                                   false, // Debug mode OFF
+                                       true); // SW Reset ON
+            }
+
+#ifdef DEBUG
+            // Write the Input Pull-Up micro-Engine firmware
+            for(i = 0; i < PUE_Firmware_p->ImageWordCount; i++)
+            {
+                Device_Write32(Device,
+                               EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t),
+                               PUE_Firmware_p->Image_p[i]);
+                // Perform read-back check
+                {
+                    uint32_t Value32 =
+                        Device_Read32(
+                            Device,
+                            EIP207_CS_RAM_XS_SPACE_BASE + i * sizeof(uint32_t));
+
+                    if (Value32 != PUE_Firmware_p->Image_p[i])
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+            }
+#else
+            Device_Write32Array(Device,
+                                EIP207_CS_RAM_XS_SPACE_BASE,
+                                PUE_Firmware_p->Image_p,
+                                PUE_Firmware_p->ImageWordCount);
+            // Perform read-back check of small subset
+            {
+                static uint32_t ReadBuf[EIP207_FW_CHECK_WORD_COUNT];
+                Device_Read32Array(Device,
+                                   EIP207_CS_RAM_XS_SPACE_BASE,
+                                   ReadBuf,
+                               EIP207_FW_CHECK_WORD_COUNT);
+                if (memcmp(ReadBuf,
+                           PUE_Firmware_p->Image_p,
+                           EIP207_FW_CHECK_WORD_COUNT * sizeof(uint32_t)) != 0)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+
+            }
+#endif
+
+            // Disable access to OPUE Program RAM
+            for (CECount = 0; CECount < EIP207_GLOBAL_MAX_NOF_CE_TO_USE; CECount++)
+                EIP207_OCE_RAM_CTRL_WR(Device, CECount, false, false);
+
+#ifdef EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK
+            // Check the firmware version and start all the engines
+            for (CECount = 0; CECount < NofCEs; CECount++)
+            {
+                uint32_t Value32;
+                unsigned int Ma, Mi, Pl, i;
+                bool fUpdated;
+
+                // Start the OFPP in Debug mode for the firmware version check
+                EIP207_OCE_FPP_CTRL_WR(
+                    Device,
+                    CECount,
+                    FIRMWARE_EIP207_DWLD_OFPP_VERSION_CHECK_DBG_PROG_CNTR,
+                    1,       // Clear ECC correctable error
+                    1,       // Clear ECC non-correctable error
+                    true,    // Debug mode ON
+                    false);  // SW Reset OFF
+
+                // Wait for the OFPP version update
+                for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++)
+                {
+                    Value32 = Device_Read32(
+                        Device,
+                        EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                        FIRMWARE_EIP207_DWLD_ADMIN_RAM_OFPP_CTRL_BYTE_OFFSET);
+
+                    FIRMWARE_EIP207_DWLD_OFPP_VersionUpdated_Read(Value32,
+                                                                  &fUpdated);
+
+                    if (fUpdated)
+                        break;
+                }
+
+                if (!fUpdated)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+
+                Value32 = Device_Read32(
+                    Device,
+                    EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                    FIRMWARE_EIP207_DWLD_ADMIN_RAM_OFPP_VERSION_BYTE_OFFSET);
+
+                FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl);
+
+                if (FPP_Firmware_p->Major == 0 &&
+                    FPP_Firmware_p->Minor == 0 &&
+                    FPP_Firmware_p->PatchLevel == 0)
+                {  // Adapter did not provide expected version, return it.
+                    FPP_Firmware_p->Major = Ma;
+                    FPP_Firmware_p->Minor = Mi;
+                    FPP_Firmware_p->PatchLevel = Pl;
+                }
+                else
+                {
+                    // Adapter provided expected version, check it.
+                    if (FPP_Firmware_p->Major != Ma ||
+                        FPP_Firmware_p->Minor != Mi ||
+                        FPP_Firmware_p->PatchLevel != Pl)
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+
+                // Start the OPUE in Debug mode for the firmware version check
+                EIP207_OCE_PUE_CTRL_WR(
+                    Device,
+                    CECount,
+                    FIRMWARE_EIP207_DWLD_OPUE_VERSION_CHECK_DBG_PROG_CNTR,
+                    1,       // Clear ECC correctable error
+                    1,       // Clear ECC non-correctable error
+                    true,    // Debug mode ON
+                    false);  // SW Reset OFF
+
+                // Wait for the OPUE version update
+                for (i = 0; i < EIP207_FW_VER_CHECK_MAX_NOF_READ_ATTEMPTS; i++)
+                {
+                    Value32 = Device_Read32(
+                        Device,
+                        EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                        FIRMWARE_EIP207_DWLD_ADMIN_RAM_OPUE_CTRL_BYTE_OFFSET);
+
+                    FIRMWARE_EIP207_DWLD_OPUE_VersionUpdated_Read(Value32,
+                                                                  &fUpdated);
+
+                    if (fUpdated)
+                        break;
+                }
+
+                if (!fUpdated)
+                    return EIP207_GLOBAL_INTERNAL_ERROR;
+
+                Value32 = Device_Read32(
+                    Device,
+                     EIP207_OCE_REG_SCRATCH_RAM(CECount) +
+                    FIRMWARE_EIP207_DWLD_ADMIN_RAM_OPUE_VERSION_BYTE_OFFSET);
+
+                FIRMWARE_EIP207_DWLD_Version_Read(Value32, &Ma, &Mi, &Pl);
+
+                if (PUE_Firmware_p->Major == 0 &&
+                    PUE_Firmware_p->Minor == 0 &&
+                PUE_Firmware_p->PatchLevel == 0)
+                {  // Adapter did not provide expected version, return it.
+                    PUE_Firmware_p->Major = Ma;
+                    PUE_Firmware_p->Minor = Mi;
+                    PUE_Firmware_p->PatchLevel = Pl;
+                }
+                else
+                {
+                    // Adapter provided expected version, check it.
+                    if (PUE_Firmware_p->Major != Ma ||
+                    PUE_Firmware_p->Minor != Mi ||
+                        PUE_Firmware_p->PatchLevel != Pl)
+                        return EIP207_GLOBAL_INTERNAL_ERROR;
+                }
+            } // for
+#else
+            for (CECount = 0; CECount < EIP207_GLOBAL_MAX_NOF_CE_TO_USE; CECount++)
+            {
+            // Start the OFPP in Debug mode
+                EIP207_OCE_FPP_CTRL_WR(
+                    Device,
+                    CECount,
+                    FIRMWARE_EIP207_DWLD_OFPP_VERSION_CHECK_DBG_PROG_CNTR,
+                    1,       // Clear ECC correctable error
+                    1,       // Clear ECC non-correctable error
+                    true,    // Debug mode ON
+                    false);  // SW Reset OFF
+
+                // Start the OPUE in Debug mode
+                EIP207_OCE_PUE_CTRL_WR(
+                    Device,
+                    CECount,
+                    FIRMWARE_EIP207_DWLD_OPUE_VERSION_CHECK_DBG_PROG_CNTR,
+                    1,       // Clear ECC correctable error
+                    1,       // Clear ECC non-correctable error
+                            true,    // Debug mode ON
+                    false);  // SW Reset OFF
+            } // for
+#endif // EIP207_GLOBAL_FIRMWARE_DOWNLOAD_VERSION_CHECK
+        }
+    }
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_OCE_GlobalStats_Get
+ */
+EIP207_Global_Error_t
+EIP207_OCE_GlobalStats_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_OCE_GlobalStats_t * const OCE_GlobalStats_p)
+{
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CE_Number);
+
+    // Not used / implemented yet
+    ZEROINIT(*OCE_GlobalStats_p);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_OCE_ClockCount_Get
+ */
+EIP207_Global_Error_t
+EIP207_OCE_ClockCount_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_Value64_t * const OCE_Clock_p)
+{
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CE_Number);
+
+    // Not used / implemented yet
+    ZEROINIT(*OCE_Clock_p);
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/*-----------------------------------------------------------------------------
+ * EIP207_OCE_Status_Get
+ */
+EIP207_Global_Error_t
+EIP207_OCE_Status_Get(
+        const Device_Handle_t Device,
+        const unsigned int CE_Number,
+        EIP207_Global_CE_Status_t * const OCE_Status_p)
+{
+    if ((EIP97_SupportedFuncs_Get() & BIT_1) != 0)
+    {
+        EIP207_OCE_PUE_CTRL_RD_CLEAR(Device,
+                                     CE_Number,
+                                     &OCE_Status_p->fPUE_EccCorr,
+                                     &OCE_Status_p->fPUE_EccDerr);
+
+        EIP207_OCE_FPP_CTRL_RD_CLEAR(Device,
+                                     CE_Number,
+                                     &OCE_Status_p->fFPP_EccCorr,
+                                     &OCE_Status_p->fFPP_EccDerr);
+
+        EIP207_OCE_SCRATCH_CTRL_RD(Device,
+                                   CE_Number,
+                                   &OCE_Status_p->fTimerOverflow);
+    }
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip207_oce.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc.c
new file mode 100644
index 0000000..42ea46c
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc.c
@@ -0,0 +1,107 @@
+/* eip207_rc.c
+ *
+ * EIP-207 Record Cache (RC) interface High-Performance (HP) implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Record Cache (RC) interface
+#include "eip207_rc.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_BaseAddr_Set
+ */
+void
+EIP207_RC_BaseAddr_Set(
+            const Device_Handle_t Device,
+            const uint32_t CacheBase,
+            const unsigned int CacheNr,
+            const uint32_t Address,
+            const uint32_t UpperAddress)
+{
+    // Not implemented
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CacheBase);
+    IDENTIFIER_NOT_USED(CacheNr);
+    IDENTIFIER_NOT_USED(Address);
+    IDENTIFIER_NOT_USED(UpperAddress);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_Record_Update
+ */
+void
+EIP207_RC_Record_Update(
+        const Device_Handle_t Device,
+        const uint32_t CacheBase,
+        const unsigned int CacheNr,
+        const uint32_t Rec_DMA_Addr,
+        const uint8_t Command,
+        const unsigned int ByteOffset,
+        const uint32_t Value32)
+{
+    // Not implemented
+    IDENTIFIER_NOT_USED(Command);
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CacheBase);
+    IDENTIFIER_NOT_USED(Device);
+    IDENTIFIER_NOT_USED(CacheNr);
+    IDENTIFIER_NOT_USED(Rec_DMA_Addr);
+    IDENTIFIER_NOT_USED(ByteOffset);
+    IDENTIFIER_NOT_USED(Value32);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_Record_Dummy_Addr_Get
+ */
+unsigned int
+EIP207_RC_Record_Dummy_Addr_Get(void)
+{
+    return EIP207_RC_RECORD_DUMMY_ADDRESS;
+}
+
+
+/* end of file eip207_rc.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc_internal.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc_internal.c
new file mode 100644
index 0000000..4ca5d25
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_rc_internal.c
@@ -0,0 +1,808 @@
+/* eip207_rc_internal.c
+ *
+ * EIP-207 Record Cache (RC) interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// EIP-207 Record Cache (RC) internal interface
+#include "eip207_rc_internal.h"
+
+// EIP97_Interfaces_Get()
+#include "eip97_global_internal.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// EIP-207 Global Control Driver Library Internal interfaces
+#include "eip207_level0.h"              // EIP-207 Level 0 macros
+
+// EIP-206 Global Control Driver Library Internal interfaces
+#include "eip206_level0.h"              // EIP-206 Level 0 macros
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+
+// EIP-207 Firmware Classification API
+#include "firmware_eip207_api_cs.h"     // Classification API: General
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+#if FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT <= \
+                FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT
+#define EIP207_RC_ARC4_SIZE                             0
+#elif FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT <= \
+                FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT_LARGE
+#define EIP207_RC_ARC4_SIZE                             1
+#else
+#error "Error: ARC4 State Record size too big"
+#endif
+
+// Minimum number of entries in the Record Cache
+#define EIP207_RC_MIN_ENTRY_COUNT                       32
+
+// Maximum number of entries in the Record Cache
+#define EIP207_RC_MAX_ENTRY_COUNT                       4096
+
+// Maximum number of records in cachs
+#define EIP207_RC_MAX_RECORD_COUNT                      1023
+
+// Number of header words (32-bits) in a cache record
+#define EIP207_RC_HEADER_WORD_COUNT                     4
+
+// Number of 32-bit words in one administration memory word
+#define EIP207_RC_ADMIN_MEMWORD_WORD_COUNT              4
+
+// Number of hash table entries in one administration memory word
+#define EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT             8
+
+// Null value used in Record Caches
+#define EIP207_RC_NULL_VALUE                            0x3FF
+
+// Checks for the required configuration parameters
+#ifndef EIP207_FRC_ADMIN_RAM_WORD_COUNT
+#error "EIP207_FRC_ADMIN_RAM_WORD_COUNT not defined"
+#endif // EIP207_FRC_ADMIN_RAM_WORD_COUNT
+
+#ifndef EIP207_TRC_ADMIN_RAM_WORD_COUNT
+#error "EIP207_TRC_ADMIN_RAM_WORD_COUNT not defined"
+#endif // EIP207_TRC_ADMIN_RAM_WORD_COUNT
+
+#ifndef EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT
+#error "EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT not defined"
+#endif // EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT
+
+// Minimum required Record Cache Admin RAM size
+#define EIP207_RC_MIN_ADMIN_RAM_WORD_COUNT \
+      (((EIP207_RC_MIN_ENTRY_COUNT / EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT) * \
+          EIP207_RC_ADMIN_MEMWORD_WORD_COUNT) + \
+             EIP207_RC_HEADER_WORD_COUNT * EIP207_RC_MIN_ENTRY_COUNT)
+
+// Check if the configured FRC Admin RAM size is large enough to contain
+// the minimum required number of record headers with their hash table
+#if EIP207_FRC_ADMIN_RAM_WORD_COUNT > 0 && \
+    EIP207_FRC_ADMIN_RAM_WORD_COUNT < EIP207_RC_MIN_ADMIN_RAM_WORD_COUNT
+#error "Configured FRC Admin RAM size is too small"
+#endif
+
+// Check if the configured TRC Admin RAM size is large enough to contain
+// the minimum required number of record headers with their hash table
+#if EIP207_TRC_ADMIN_RAM_WORD_COUNT > 0 && \
+    EIP207_TRC_ADMIN_RAM_WORD_COUNT < EIP207_RC_MIN_ADMIN_RAM_WORD_COUNT
+#error "Configured TRC Admin RAM size is too small"
+#endif
+
+// Check if the (optional) configured ARC4RC Admin RAM size is large enough
+// to contain the minimum required number of record headers
+// with their hash table
+#if EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT > 0 && \
+    EIP207_ARC4RC_ADMIN_RAM_WORD_COUNT < EIP207_RC_MIN_ADMIN_RAM_WORD_COUNT
+#error "Configured ARC4RC Admin RAM size is too small"
+#endif
+
+// Hash Table Size calculation for *RC_p_PARAMS registers
+// Hash Table entry count =
+//      2 ^ (Hash Table Size + EIP207_RC_HASH_TABLE_SIZE_POWER_FACTOR)
+#define EIP207_RC_HASH_TABLE_SIZE_POWER_FACTOR      5
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_RC_Internal_LowerPowerOfTwo
+ *
+ * Rounds down a value to the lower or equal power of two value.
+ */
+static unsigned int
+EIP207Lib_RC_Internal_LowerPowerOfTwo(const unsigned int Value,
+                                      unsigned int * const Power)
+{
+    unsigned int v = Value;
+    unsigned int i = 0;
+
+    if (v == 0)
+        return v;
+
+    while (v)
+    {
+        v = v >> 1;
+        i++;
+    }
+
+    v = 1 << (i - 1);
+
+    *Power = i - 1;
+
+    return v;
+}
+
+
+#define EIP207_RC_DATA_WORDCOUNT_MAX 131072
+#define EIP207_RC_DATA_WORDCOUNT_MIN 256
+#define EIP207_RC_ADMIN_WORDCOUNT_MAX 16384
+#define EIP207_RC_ADMIN_WORDCOUNT_MIN 64
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_Bank_Set
+ *
+ * Set the bank for the CS RAM to the given address.
+ *
+ * Device (input)
+ *     Device to use.
+ *
+ * BankNr (input)
+ *     Bank number from 0 to 7.
+ *
+ */
+static void
+EIP207Lib_Bank_Set(
+    const Device_Handle_t Device,
+    uint32_t BankNr)
+{
+    uint32_t OldValue = Device_Read32(Device, EIP207_CS_REG_RAM_CTRL);
+
+    uint32_t NewValue = (OldValue & 0xffff8fff) | ((BankNr&0x7) << 12);
+
+    Device_Write32(Device, EIP207_CS_REG_RAM_CTRL, NewValue);
+}
+
+
+static void
+EIP207Lib_RAM_Write32(
+        const Device_Handle_t Device,
+        uint32_t Address,
+        uint32_t Value)
+{
+    Device_Write32(Device,
+                   EIP207_CS_RAM_XS_SPACE_BASE + Address,
+                   Value);
+}
+
+static uint32_t
+EIP207Lib_RAM_Read32(
+        const Device_Handle_t Device,
+        uint32_t Address)
+{
+    return Device_Read32(Device,
+                         EIP207_CS_RAM_XS_SPACE_BASE + Address);
+}
+
+
+
+/*----------------------------------------------------------------------------
+ * EIP207Lib_RAMSize_Probe
+ *
+ * Probe the size of the accessible RAM, do not access more memory than
+ * indicated by MaxSize.
+ *
+ * Device (input)
+ *     Device to use.
+ *
+ * MaxSize (input)
+ *     Maximum size of RAM
+ */
+static unsigned int
+EIP207Lib_RAMSize_Probe(
+    const Device_Handle_t Device,
+    const unsigned int MaxSize)
+{
+    unsigned int MaxBank, MaxPage, MaxOffs, i, RAMSize;
+
+    if (MaxSize <= 16384)
+    {
+        // All RAM is in a single bank.
+        MaxBank = 0;
+    }
+    else
+    {
+        // Probe the maximum bank number that has (distinct) RAM.
+        for (i=0; i<8; i++)
+        {
+            EIP207Lib_Bank_Set(Device, 7 - i);
+            EIP207Lib_RAM_Write32(Device, 0, 7 - i);
+            EIP207Lib_RAM_Write32(Device, 4, 0);
+            EIP207Lib_RAM_Write32(Device, 8, 0);
+            EIP207Lib_RAM_Write32(Device, 12, 0);
+        }
+        MaxBank=0;
+        for (i=0; i<7; i++)
+        {
+            EIP207Lib_Bank_Set(Device, i);
+            if (EIP207Lib_RAM_Read32(Device, 0) != i)
+            {
+                break;
+            }
+            MaxBank = i;
+        }
+    }
+
+    EIP207Lib_Bank_Set(Device, MaxBank);
+
+    for (i=0; i<0x10000; i+=0x100)
+    {
+        EIP207Lib_RAM_Write32(Device, 0xff00-i, 0xff00-i);
+        EIP207Lib_RAM_Write32(Device, 0xff00-i+4, 0);
+        EIP207Lib_RAM_Write32(Device, 0xff00-i+8, 0);
+        EIP207Lib_RAM_Write32(Device, 0xff00-i+12, 0);
+    }
+
+    MaxPage = 0;
+    for (i=0; i<0x10000; i+=0x100)
+    {
+        if (EIP207Lib_RAM_Read32(Device, i) != i)
+        {
+            break;
+        }
+        MaxPage = i;
+    }
+
+    for (i=0; i<0x100; i+= 4)
+    {
+        EIP207Lib_RAM_Write32(Device, MaxPage + 0xfc - i, MaxPage + 0xfc - i);
+    }
+
+    MaxOffs = 0;
+
+    for (i=0; i<0x100; i+=4)
+    {
+        if (EIP207Lib_RAM_Read32(Device, MaxPage + i) != MaxPage + i)
+        {
+            break;
+        }
+        MaxOffs = i;
+    }
+
+    EIP207Lib_Bank_Set(Device, 0);
+    RAMSize = ((MaxBank<<16) + MaxPage + MaxOffs + 4) >> 2;
+
+    if (RAMSize > MaxSize)
+        RAMSize = MaxSize;
+
+    return RAMSize;
+}
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_Internal_Init
+ */
+EIP207_Global_Error_t
+EIP207_RC_Internal_Init(
+        const Device_Handle_t Device,
+        const EIP207_RC_Internal_Combination_Type_t CombinationType,
+        const uint32_t CacheBase,
+        EIP207_Global_CacheParams_t * RC_Params_p,
+        const unsigned int RecordWordCount)
+{
+    unsigned int i;
+    uint16_t RC_Record2_WordCount = 0;
+    uint8_t ClocksPerTick;
+    bool fFrc = false, fTrc = false, fArc4 = false;
+    EIP207_Global_CacheParams_t * RC_p = RC_Params_p;
+    unsigned int NullVal = EIP207_RC_NULL_VALUE;
+
+    switch (CacheBase)
+    {
+        case EIP207_FRC_REG_BASE:
+            fFrc = true;
+            RC_Record2_WordCount = 0;
+            break;
+
+        case EIP207_TRC_REG_BASE:
+            fTrc = true;
+            RC_Record2_WordCount =
+                    FIRMWARE_EIP207_CS_TRC_RECORD_WORD_COUNT_LARGE;
+            break;
+
+        case EIP207_ARC4RC_REG_BASE:
+            fArc4 = true;
+            RC_Record2_WordCount =
+                    FIRMWARE_EIP207_CS_ARC4RC_RECORD_WORD_COUNT_LARGE;
+            break;
+
+        default:
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+    }
+
+    if (CombinationType != EIP207_RC_INTERNAL_NOT_COMBINED)
+    {
+        if( fFrc ) // FRC cannot be combined
+            return EIP207_GLOBAL_ARGUMENT_ERROR;
+
+        // Initialize all the configured for use Record Cache sets
+        for (i = 0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+            EIP207_RC_PARAMS_WR(Device,
+                                CacheBase,
+                                i,     // Cache Set number
+                                false, // Disable cache RAM access
+                                false, // Block Next Command is reserved
+                                false, // Enable access cache administration RAM
+                                0,
+                                0,     // Block Time Base is reserved
+                                false, // Not used for this HW
+                                RC_Record2_WordCount); // Large record size
+
+        return EIP207_GLOBAL_NO_ERROR;
+    }
+    // Indicate if ARC4 state records are considered 'large' transform records.
+    // Only relevent inin case the TRC is used to store ARC4 state records, but
+    // without a combined cache.
+    if (fTrc)
+    {
+        unsigned int NofCEs;
+        EIP97_Interfaces_Get(&NofCEs,NULL,NULL,NULL);
+        for (i = 0; i < NofCEs; i++)
+            EIP206_ARC4_SIZE_WR(Device, i, EIP207_RC_ARC4_SIZE);
+    }
+
+    // Initialize all the configured for use Record Cache sets
+    for (i = 0; i < EIP207_GLOBAL_MAX_NOF_CACHE_SETS_TO_USE; i++)
+    {
+        unsigned int RC_RAM_WordCount = RC_p->DataWordCount;
+        uint8_t RC_HashTableSize;
+        unsigned int j, Power,
+                     RC_RecordCount,
+                     RC_Record_WordCount,
+                     RC_HashTable_EntryCount,
+                     RC_HashTable_WordCount,
+                     RC_AdminRAM_WordCount,
+                     RC_AdminRAM_EntryCount,
+                     RC_HashTable_ByteOffset;
+
+        if (RC_p->fEnable == false)
+            continue; // Cache is not enabled
+
+        // Enable Record Cache RAM access
+        EIP207_CS_RAM_CTRL_WR(
+            Device,
+            fFrc && i==0,
+            fFrc && i==1,
+            fFrc && i==2,
+            fTrc && i==0,
+            fTrc && i==1,
+            fTrc && i==2,
+            fArc4 && i==0,
+            fArc4 && i==1,
+            fArc4 && i==2,
+            false);               // No FLUEC cache RAM access
+
+        // Take Record Cache into reset
+        // Make cache data RAM accessible
+        EIP207_RC_PARAMS_WR(Device,
+                            CacheBase,
+                            i,     // Cache Set number
+                            true,  // Enable cache RAM access
+                            false,
+                            true, // Enable access cache data RAM
+                            0,
+                            0,
+                            false, // Not used here for this HW
+                            0);
+
+        if (RC_RAM_WordCount == 0 ||
+            RC_RAM_WordCount > EIP207_RC_DATA_WORDCOUNT_MAX)
+            RC_RAM_WordCount = EIP207_RC_DATA_WORDCOUNT_MAX;
+        // Check the size of the data RAM.
+        RC_RAM_WordCount = EIP207Lib_RAMSize_Probe(
+            Device,
+            RC_RAM_WordCount);
+
+        // Data RAM may be inaccessible on some hardware configurations,
+        // so RAM size probing may not work. Assume that provided word count
+        // input actually reflects RAM size.
+        if (RC_RAM_WordCount < EIP207_RC_DATA_WORDCOUNT_MIN)
+            RC_RAM_WordCount = MIN(RC_p->DataWordCount, EIP207_RC_DATA_WORDCOUNT_MAX);
+        if (RC_RAM_WordCount < EIP207_RC_DATA_WORDCOUNT_MIN)
+            return EIP207_GLOBAL_INTERNAL_ERROR;
+
+        RC_p->DataWordCount = RC_RAM_WordCount;
+
+        // Take Record Cache into reset
+        // Make cache administration RAM accessible
+        EIP207_RC_PARAMS_WR(Device,
+                            CacheBase,
+                            i,     // Cache Set number
+                            true,  // Enable cache RAM access
+                            false,
+                            false, // Enable access cache administration RAM
+                            0,
+                            0,
+                            false, // Not used here for this HW
+                            0);
+
+        // Get the configured RC Admin RAM size
+        RC_AdminRAM_WordCount = RC_p->AdminWordCount;
+        if (RC_AdminRAM_WordCount == 0 ||
+            RC_AdminRAM_WordCount > EIP207_RC_ADMIN_WORDCOUNT_MAX)
+            RC_AdminRAM_WordCount = EIP207_RC_ADMIN_WORDCOUNT_MAX;
+
+        RC_AdminRAM_WordCount = EIP207Lib_RAMSize_Probe(
+            Device,
+            RC_AdminRAM_WordCount);
+
+        RC_p->AdminWordCount = RC_AdminRAM_WordCount;
+
+        if (RC_AdminRAM_WordCount < EIP207_RC_ADMIN_WORDCOUNT_MIN)
+            return EIP207_GLOBAL_INTERNAL_ERROR;
+
+       // Check the size of the Admin RAM
+
+        // Determine the RC record size to use
+        if (RC_Record2_WordCount > RecordWordCount)
+            RC_Record_WordCount = RC_Record2_WordCount;
+        else
+            RC_Record_WordCount = RecordWordCount;
+
+        // Calculate the maximum possible record count that
+        // the Record Cache Data RAM can contain
+        RC_RecordCount = RC_RAM_WordCount / RC_Record_WordCount;
+        if (RC_RecordCount > EIP207_RC_MAX_RECORD_COUNT)
+            RC_RecordCount = EIP207_RC_MAX_RECORD_COUNT;
+
+        // RC_RecordCount is calculated using the configured RC Data RAM size.
+
+        // RC_AdminRAM_EntryCount is calculated using
+        // the configured RC Admin RAM size.
+
+        // Calculate the maximum possible record count that
+        // the RC Hash Table (in Record Cache Administration RAM) can contain
+        RC_AdminRAM_EntryCount = EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT *
+                                    RC_AdminRAM_WordCount /
+                                (EIP207_RC_ADMIN_MEMWORD_WORD_COUNT +
+                                        EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT *
+                                           EIP207_RC_HEADER_WORD_COUNT);
+
+        // Try to extend the Hash Table in the RC Admin RAM
+        if (RC_RecordCount < RC_AdminRAM_EntryCount)
+        {
+            unsigned int HTSpace_WordCount;
+
+            // Calculate the size of space available for the Hash Table
+            HTSpace_WordCount = RC_AdminRAM_WordCount -
+                                  RC_RecordCount * EIP207_RC_HEADER_WORD_COUNT;
+
+            // Calculate maximum possible Hash Table entry count
+            RC_HashTable_EntryCount = (HTSpace_WordCount /
+                                        EIP207_RC_ADMIN_MEMWORD_WORD_COUNT) *
+                                           EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT;
+        }
+        else // Extension impossible
+            RC_HashTable_EntryCount = RC_AdminRAM_EntryCount;
+
+        // Check minimum number of entries in the record cache
+        RC_HashTable_EntryCount = MAX(EIP207_RC_MIN_ENTRY_COUNT,
+                                      RC_HashTable_EntryCount);
+
+        // Check maximum number of entries in the record cache
+        RC_HashTable_EntryCount = MIN(EIP207_RC_MAX_ENTRY_COUNT,
+                                      RC_HashTable_EntryCount);
+
+        // Round down to power of two
+        Power = 0;
+        RC_HashTable_EntryCount =
+             EIP207Lib_RC_Internal_LowerPowerOfTwo(RC_HashTable_EntryCount,
+                                                   &Power);
+
+        // Hash Table Mask that determines the hash table size
+        if (Power >= EIP207_RC_HASH_TABLE_SIZE_POWER_FACTOR)
+            RC_HashTableSize =
+                    (uint8_t)(Power - EIP207_RC_HASH_TABLE_SIZE_POWER_FACTOR);
+        else
+            // Insufficient memory for Hash Table in the RC Admin RAM
+            return EIP207_GLOBAL_INTERNAL_ERROR;
+
+        // Calculate the Hash Table size in 32-bit words
+        RC_HashTable_WordCount = RC_HashTable_EntryCount /
+                                  EIP207_RC_ADMIN_MEMWORD_ENTRY_COUNT *
+                                       EIP207_RC_ADMIN_MEMWORD_WORD_COUNT;
+
+        // Recalculate the record count that fits the RC Admin RAM space
+        // without the Hash Table, restricting for the maximum records
+        // which fit the RC Data RAM
+        {
+            // Adjusted record count which fits the RC Admin RAM
+            unsigned int RC_AdminRAM_AdjustedEntryCount =
+                             (RC_AdminRAM_WordCount -
+                                RC_HashTable_WordCount) /
+                                   EIP207_RC_HEADER_WORD_COUNT;
+
+            // Maximum record count which fits the RC Data RAM - RC_RecordCount
+            // use the minimum of the two
+            RC_RecordCount = MIN(RC_RecordCount,
+                                 RC_AdminRAM_AdjustedEntryCount);
+        }
+
+        // Clear all ECC errors
+        EIP207_RC_ECCCTRL_WR(Device, CacheBase, i, false, false, false);
+
+        // Clear all record administration words
+        // in Record Cache administration RAM
+        for (j = 0; j < RC_RecordCount; j++)
+        {
+            // Calculate byte offset for the current record
+            unsigned int ByteOffset = EIP207_CS_RAM_XS_SPACE_BASE +
+                                      j *
+                                        EIP207_RC_HEADER_WORD_COUNT *
+                                          sizeof(uint32_t);
+
+            // Write word 0
+            Device_Write32(Device,
+                           ByteOffset,
+                           (NullVal << 20) | // Hash_Collision_Prev
+                           (NullVal << 10)); // Hash_Collision_Next
+
+            // Write word 1
+            ByteOffset += sizeof(uint32_t);
+
+            if (j == RC_RecordCount - 1)
+            {
+                // Last record
+                Device_Write32(Device,
+                               ByteOffset,
+                               ((j - 1) << 10) |   // Free_List_Prev
+                               NullVal);           // Free_List_Next
+            }
+            else if (j == 0)
+            {
+                // First record
+                Device_Write32(Device,
+                               ByteOffset,
+                               (NullVal << 10) | // Free_List_Prev
+                               (j + 1));         // Free_List_Next
+            }
+            else
+            {
+                // All other records
+                Device_Write32(Device,
+                               ByteOffset,
+                               ((j - 1) << 10) | // Free_List_Prev
+                               (j + 1));         // Free_List_Next
+            }
+
+            // Write word 2
+            ByteOffset += sizeof(uint32_t);
+
+            Device_Write32(Device,
+                           ByteOffset,
+                           0); // Address_Key, low bits
+
+            // Write word 3
+            ByteOffset += sizeof(uint32_t);
+
+            Device_Write32(Device,
+                           ByteOffset,
+                           0); // Address_Key, high bits
+        } // for (records)
+
+        // Calculate byte offset for the Hash Table
+        RC_HashTable_ByteOffset = EIP207_CS_RAM_XS_SPACE_BASE +
+                            RC_RecordCount *
+                                EIP207_RC_HEADER_WORD_COUNT *
+                                    sizeof(uint32_t);
+
+        // Clear all hash table words
+        for (j = 0; j < RC_HashTable_WordCount; j++)
+            Device_Write32(Device,
+                           RC_HashTable_ByteOffset + j * sizeof(uint32_t),
+                           0x3FFFFFFF);
+
+        // Disable Record Cache RAM access
+        EIP207_CS_RAM_CTRL_DEFAULT_WR(Device);
+
+        // Write head and tail pointers to the RC Free Chain
+        EIP207_RC_FREECHAIN_WR(
+                  Device,
+                  CacheBase,
+                  i,                               // Cache Set number
+                  0,                               // head pointer
+                  (uint16_t)(RC_RecordCount - 1)); // tail pointer
+
+        // Set Hash Table start
+        // This is an offset from EIP207_CS_RAM_XS_SPACE_BASE
+        // in record administration memory words
+        EIP207_RC_PARAMS2_WR(Device,
+                             CacheBase,
+                             i,
+                             (uint16_t)RC_RecordCount,
+    /* Small Record size */  fArc4 ? 0 : (uint16_t)RecordWordCount,
+                             FIRMWARE_EIP207_RC_DMA_WR_COMB_DLY);
+
+        // Select the highest clock count as specified by
+        // the Host and the Firmware for the FRC
+#ifdef FIRMWARE_EIP207_CS_BLOCK_NEXT_COMMAND_LOGIC_DISABLE
+        ClocksPerTick = RC_p->BlockClockCount;
+#else
+        {
+            uint8_t tmp;
+
+            tmp = (uint8_t)FIRMWARE_EIP207_CS_FRC_BLOCK_TIMEBASE;
+            ClocksPerTick = RC_p->BlockClockCount >= tmp ?
+                                       CacheConf_p->FRC.BlockClockCount : tmp;
+        }
+#endif
+
+        // Take Record Cache out of reset
+        EIP207_RC_PARAMS_WR(Device,
+                            CacheBase,
+                            i,     // Cache Set number
+                            false, // Disable cache RAM access
+                            RC_p->fNonBlock,
+                            false, // Disable access cache administration RAM
+                            RC_HashTableSize,
+                            ClocksPerTick,
+                            false, // Not used here for this HW
+                            RC_Record2_WordCount); // Large record size
+
+        RC_p++;
+    } // for, i cache sets
+
+    return EIP207_GLOBAL_NO_ERROR;
+}
+
+static void
+EIP207_RC_Internal_DebugStatistics_Single_Get(
+        const Device_Handle_t Device,
+        const unsigned int CacheSetId,
+        uint32_t RegBase,
+        EIP207_Global_CacheDebugStatistics_t * const Stats_p)
+{
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_PREFEXEC(RegBase, CacheSetId),
+                         &Stats_p->PrefetchExec);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_PREFBLCK(RegBase, CacheSetId),
+                         &Stats_p->PrefetchBlock);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_PREFDMA(RegBase, CacheSetId),
+                         &Stats_p->PrefetchDMA);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_SELOPS(RegBase, CacheSetId),
+                         &Stats_p->SelectOps);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_SELDMA(RegBase, CacheSetId),
+                         &Stats_p->SelectDMA);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_IDMAWR(RegBase, CacheSetId),
+                         &Stats_p->IntDMAWrite);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_XDMAWR(RegBase, CacheSetId),
+                         &Stats_p->ExtDMAWrite);
+    EIP207_RC_LONGCTR_RD(Device, EIP207_RC_REG_INVCMD(RegBase, CacheSetId),
+                         &Stats_p->InvalidateOps);
+    EIP207_RC_RDMAERRFLGS_RD(Device, RegBase, CacheSetId,
+                             &Stats_p->ReadDMAErrFlags);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_RDMAERR(RegBase, CacheSetId),
+                          &Stats_p->ReadDMAErrors);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_WDMAERR(RegBase, CacheSetId),
+                          &Stats_p->WriteDMAErrors);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_INVECC(RegBase, CacheSetId),
+                          &Stats_p->InvalidateECC);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_DATECC_CORR(RegBase, CacheSetId),
+                          &Stats_p->DataECCCorr);
+    EIP207_RC_SHORTCTR_RD(Device, EIP207_RC_REG_ADMECC_CORR(RegBase, CacheSetId),
+                          &Stats_p->AdminECCCorr);
+
+}
+
+
+void
+EIP207_RC_Internal_DebugStatistics_Get(
+        const Device_Handle_t Device,
+        const unsigned int CacheSetId,
+        EIP207_Global_CacheDebugStatistics_t * const FRC_Stats_p,
+        EIP207_Global_CacheDebugStatistics_t * const TRC_Stats_p)
+{
+    EIP207_RC_Internal_DebugStatistics_Single_Get(
+        Device,
+        CacheSetId,
+        EIP207_FRC_REG_BASE,
+        FRC_Stats_p);
+    EIP207_RC_Internal_DebugStatistics_Single_Get(
+        Device,
+        CacheSetId,
+        EIP207_TRC_REG_BASE,
+        TRC_Stats_p);
+}
+
+/*----------------------------------------------------------------------------
+ * EIP207_RC_Internal_Status_Get
+ */
+void
+EIP207_RC_Internal_Status_Get(
+        const Device_Handle_t Device,
+        const unsigned int CacheSetId,
+        EIP207_Global_CacheStatus_t * const FRC_Status_p,
+        EIP207_Global_CacheStatus_t * const TRC_Status_p,
+        EIP207_Global_CacheStatus_t * const ARC4RC_Status_p)
+{
+    // Read FRC status
+    EIP207_RC_PARAMS_RD(Device,
+                        EIP207_FRC_REG_BASE,
+                        CacheSetId,
+                        &FRC_Status_p->fDMAReadError,
+                        &FRC_Status_p->fDMAWriteError);
+
+    EIP207_RC_ECCCTRL_RD_CLEAR(Device,
+                               EIP207_FRC_REG_BASE,
+                               CacheSetId,
+                               &FRC_Status_p->fDataEccOflo,
+                               &FRC_Status_p->fDataEccErr,
+                               &FRC_Status_p->fAdminEccErr);
+
+    // Read TRC status
+    EIP207_RC_PARAMS_RD(Device,
+                        EIP207_TRC_REG_BASE,
+                        CacheSetId,
+                        &TRC_Status_p->fDMAReadError,
+                        &TRC_Status_p->fDMAWriteError);
+
+    EIP207_RC_ECCCTRL_RD_CLEAR(Device,
+                               EIP207_TRC_REG_BASE,
+                               CacheSetId,
+                               &TRC_Status_p->fDataEccOflo,
+                               &TRC_Status_p->fDataEccErr,
+                               &TRC_Status_p->fAdminEccErr);
+
+    // Read ARC4RC status
+    EIP207_RC_PARAMS_RD(Device,
+                        EIP207_ARC4RC_REG_BASE,
+                        CacheSetId,
+                        &ARC4RC_Status_p->fDMAReadError,
+                        &ARC4RC_Status_p->fDMAWriteError);
+
+    EIP207_RC_ECCCTRL_RD_CLEAR(Device,
+                               EIP207_ARC4RC_REG_BASE,
+                               CacheSetId,
+                               &ARC4RC_Status_p->fDataEccOflo,
+                               &ARC4RC_Status_p->fDataEccErr,
+                               &ARC4RC_Status_p->fAdminEccErr);
+}
+
+
+/* end of file eip207_rc_internal.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_support.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_support.c
new file mode 100644
index 0000000..b5982c6
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip207_support.c
@@ -0,0 +1,86 @@
+/* eip207_support.c
+ *
+ * EIP-207 Support interface implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP-207 Support interface
+#include "eip207_support.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip207_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                 // uint32_t, bool
+
+// Driver Framework Device API
+#include "device_types.h"               // Device_Handle_t
+#include "device_rw.h"                  // Read32, Write32
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP207_Global_Read64
+ */
+EIP207_Global_Error_t
+EIP207_Global_Read64(
+        const Device_Handle_t Device,
+        const unsigned int Value64_OffsetLo,
+        const unsigned int Value64_OffsetHi,
+        EIP207_Global_Value64_t * const Value64_p)
+{
+    uint32_t Value32;
+    unsigned int i;
+
+    for (i = 0; i < EIP207_VALUE_64BIT_MAX_NOF_READ_ATTEMPTS; i++)
+    {
+        Value32 = Device_Read32(Device, Value64_OffsetHi);
+
+        Value64_p->Value64_Lo = Device_Read32(Device, Value64_OffsetLo);
+        Value64_p->Value64_Hi = Device_Read32(Device, Value64_OffsetHi);
+
+        if (Value32 == Value64_p->Value64_Hi)
+            return EIP207_GLOBAL_NO_ERROR;
+    }
+
+    return EIP207_GLOBAL_INTERNAL_ERROR;
+}
+
+
+/* end of file eip207_support.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip74.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip74.c
new file mode 100644
index 0000000..a9ef9ff
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip74.c
@@ -0,0 +1,388 @@
+/* eip74.c
+ *
+ * Implementation of the EIP-74 Driver Library.
+ */
+
+/*****************************************************************************
+* Copyright (c) 2017-2020 by Rambus, Inc. and/or its subsidiaries.
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 2 of the License, or
+* any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*****************************************************************************/
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+// EIP76 initialization API
+#include "eip74.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip74.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"         // uint32_t
+
+// Driver Framework Device API
+#include "device_types.h"       // Device_Handle_t
+
+// EIP-76 Driver Library Internal interfaces
+#include "eip74_level0.h"       // Level 0 macros
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// I/O Area, used internally
+typedef struct
+{
+    Device_Handle_t Device;
+} EIP74_True_IOArea_t;
+
+#define TEST_SIZEOF(type, size) \
+    extern int size##_must_bigger[1 - 2*((int)(sizeof(type) > size))]
+
+
+#ifdef EIP74_STRICT_ARGS
+#define EIP74_CHECK_POINTER(_p) \
+    if (NULL == (_p)) \
+        return EIP74_ARGUMENT_ERROR;
+#define EIP74_CHECK_INT_INRANGE(_i, _min, _max) \
+    if ((_i) < (_min) || (_i) > (_max)) \
+        return EIP74_ARGUMENT_ERROR;
+#define EIP74_CHECK_INT_ATLEAST(_i, _min) \
+    if ((_i) < (_min)) \
+        return EIP74_ARGUMENT_ERROR;
+#define EIP74_CHECK_INT_ATMOST(_i, _max) \
+    if ((_i) > (_max)) \
+        return EIP74_ARGUMENT_ERROR;
+#else
+/* EIP74_STRICT_ARGS undefined */
+#define EIP74_CHECK_POINTER(_p)
+#define EIP74_CHECK_INT_INRANGE(_i, _min, _max)
+#define EIP74_CHECK_INT_ATLEAST(_i, _min)
+#define EIP74_CHECK_INT_ATMOST(_i, _max)
+#endif /*end of EIP74_STRICT_ARGS */
+
+
+// validate the size of the fake and real IOArea structures
+TEST_SIZEOF(EIP74_True_IOArea_t, EIP74_IOAREA_REQUIRED_SIZE);
+
+
+/*----------------------------------------------------------------------------
+ * EIP74Lib_Detect
+ *
+ * Checks the presence of EIP-74 device. Returns true when found.
+ */
+static bool
+EIP74Lib_Detect(
+        const Device_Handle_t Device)
+{
+    uint32_t Value;
+
+    Value = EIP74_Read32(Device, EIP74_REG_VERSION);
+    if (!EIP74_REV_SIGNATURE_MATCH( Value ))
+        return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74Lib_Reset_IsDone
+ */
+static bool
+EIP74Lib_Reset_IsDone(
+        const Device_Handle_t Device)
+{
+    bool fReady, fPSAIWriteOK, fStuckOut, fEarlyReseed;
+    bool fTestReady,fGenPktError, fInstantiated, fTestStuckOut, fNeedClock;
+    uint8_t BlocksAvailable;
+
+    EIP74_STATUS_RD(Device,
+                    &fReady,
+                    &fPSAIWriteOK,
+                    &fStuckOut,
+                    &fEarlyReseed,
+                    &fTestReady,
+                    &fGenPktError,
+                    &fInstantiated,
+                    &fTestStuckOut,
+                    &BlocksAvailable,
+                    &fNeedClock);
+
+    return fPSAIWriteOK;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Init
+ */
+EIP74_Error_t
+EIP74_Init(
+        EIP74_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+
+    TrueIOArea_p->Device = Device;
+
+    if (!EIP74Lib_Detect(Device))
+    {
+        return EIP74_UNSUPPORTED_FEATURE_ERROR;
+    }
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Reset
+ */
+EIP74_Error_t
+EIP74_Reset(
+        EIP74_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_CONTROL_WR(Device,
+                     false, /* fReadyMask */
+                     false, /* fStuckOut */
+                     false, /* fTestMode */
+                     false, /* fHostMode */
+                     false, /* fEnableDRBG */
+                     false, /* fForceStuckOut */
+                     false, /* fRequestdata */
+                     0); /* DataBlocks */
+
+    if (EIP74Lib_Reset_IsDone(Device))
+    {
+        return EIP74_NO_ERROR;
+    }
+    else
+    {
+        return EIP74_BUSY_RETRY_LATER;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Reset_IsDone
+ */
+EIP74_Error_t
+EIP74_Reset_IsDone(
+        EIP74_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    if (EIP74Lib_Reset_IsDone(Device))
+    {
+        return EIP74_NO_ERROR;
+    }
+    else
+    {
+        return EIP74_BUSY_RETRY_LATER;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_HWRevision_Get
+  */
+EIP74_Error_t
+EIP74_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP74_Capabilities_t * const Capabilities_p)
+{
+    EIP74_CHECK_POINTER(Capabilities_p);
+
+    EIP74_VERSION_RD(Device,
+                     &Capabilities_p->HW_Revision.EipNumber,
+                     &Capabilities_p->HW_Revision.ComplmtEipNumber,
+                     &Capabilities_p->HW_Revision.HWPatchLevel,
+                     &Capabilities_p->HW_Revision.MinHWRevision,
+                     &Capabilities_p->HW_Revision.MajHWRevision);
+    EIP74_OPTIONS_RD(Device,
+                     &Capabilities_p->HW_Options.ClientCount,
+                     &Capabilities_p->HW_Options.AESCoreCount,
+                     &Capabilities_p->HW_Options.AESSpeed,
+                     &Capabilities_p->HW_Options.FIFODepth);
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Configure
+ */
+EIP74_Error_t
+EIP74_Configure(
+        EIP74_IOArea_t * const IOArea_p,
+        const EIP74_Configuration_t * const Configuration_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+    EIP74_CHECK_POINTER(Configuration_p);
+    EIP74_CHECK_INT_INRANGE(Configuration_p->GenerateBlockSize, 1, 4095);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_GEN_BLK_SIZE_WR(Device, Configuration_p->GenerateBlockSize);
+    EIP74_RESEED_THR_WR(Device, Configuration_p->ReseedThr);
+    EIP74_RESEED_THR_EARLY_WR(Device, Configuration_p->ReseedThrEarly);
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Instantiate
+ */
+EIP74_Error_t
+EIP74_Instantiate(
+        EIP74_IOArea_t * const IOArea_p,
+        const uint32_t * const Entropy_p,
+        bool fStuckOut)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+    EIP74_CHECK_POINTER(Entropy_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_PS_AI_WR(Device, Entropy_p, 12);
+
+    EIP74_CONTROL_WR(Device,
+                     false, /* fReadyMask */
+                     fStuckOut,
+                     false, /* fTestMode */
+                     false, /* fHostMode */
+                     true, /* fEnableDRBG */
+                     false, /* fForceStuckOut */
+                     false, /* fRequestdata */
+                     0); /* DataBlocks */
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Reseed
+ */
+EIP74_Error_t
+EIP74_Reseed(
+        EIP74_IOArea_t * const IOArea_p,
+        const uint32_t * const Entropy_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+    EIP74_CHECK_POINTER(Entropy_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_PS_AI_WR(Device, Entropy_p, 12);
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Status_Get
+ */
+EIP74_Error_t
+EIP74_Status_Get(
+        EIP74_IOArea_t * const IOArea_p,
+        EIP74_Status_t * const Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    bool fReady, fPSAIWriteOK, fStuckOut, fEarlyReseed;
+    bool fTestReady,fGenPktError, fInstantiated, fTestStuckOut, fNeedClock;
+    uint8_t BlocksAvailable;
+    uint32_t GenBlockCount, ReseedThr;
+    EIP74_CHECK_POINTER(IOArea_p);
+    EIP74_CHECK_POINTER(Status_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_STATUS_RD(Device,
+                    &fReady,
+                    &fPSAIWriteOK,
+                    &fStuckOut,
+                    &fEarlyReseed,
+                    &fTestReady,
+                    &fGenPktError,
+                    &fInstantiated,
+                    &fTestStuckOut,
+                    &BlocksAvailable,
+                    &fNeedClock);
+
+    EIP74_GENERATE_CNT_RD(Device, &GenBlockCount);
+    EIP74_RESEED_THR_RD(Device, &ReseedThr);
+
+    Status_p->GenerateBlockCount = GenBlockCount;
+    Status_p->fStuckOut = fStuckOut;
+    Status_p->fNotInitialized = fGenPktError;
+    Status_p->fReseedError = GenBlockCount == ReseedThr;
+    Status_p->fReseedWarning = fEarlyReseed;
+    Status_p->fInstantiated = fInstantiated;
+    Status_p->AvailableCount = BlocksAvailable;
+
+    return EIP74_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP74_Clear
+ */
+EIP74_Error_t
+EIP74_Clear(
+        EIP74_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    volatile EIP74_True_IOArea_t * const TrueIOArea_p =
+        (EIP74_True_IOArea_t *)IOArea_p;
+    EIP74_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP74_INTACK_WR(Device, false, true, false);
+
+    return EIP74_NO_ERROR;
+}
+
+
+/* end of file eip74.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_event.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_event.c
new file mode 100644
index 0000000..cf47963
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_event.c
@@ -0,0 +1,409 @@
+/* eip97_global_event.c
+ *
+ * EIP-97 Global Control Driver Library
+ * Event Management Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_event.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Default configuration
+#include "c_eip97_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // uint32_t
+
+// Driver Framework Device API
+#include "device_types.h"              // Device_Handle_t
+
+// EIP-97 Global Control Driver Library Internal interfaces
+#include "eip97_global_internal.h"
+#include "eip202_global_level0.h"      // EIP-202 Level 0 macros
+#include "eip96_level0.h"              // EIP-96 Level 0 macros
+#include "eip97_global_fsm.h"          // State machine
+#include "eip97_global_level0.h"
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+#ifdef EIP97_REG_DBG_BASE
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Debug_Statistics_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_Debug_Statistics_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        EIP97_Global_Debug_Statistics_t * const Debug_Statistics_p)
+{
+    Device_Handle_t Device;
+    unsigned int i;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(Debug_Statistics_p);
+
+    Device = TrueIOArea_p->Device;
+
+    for (i = 0; i < 16; i++)
+    {
+        EIP97_DBG_RING_IN_COUNT_RD(Device,
+                                   i,
+                                   &Debug_Statistics_p->Ifc_Packets_In[i]);
+        EIP97_DBG_RING_OUT_COUNT_RD(Device,
+                                    i,
+                                    &Debug_Statistics_p->Ifc_Packets_Out[i]);
+
+    }
+    for (i = 0; i < EIP97_GLOBAL_MAX_NOF_PE_TO_USE; i++)
+    {
+        EIP97_DBG_PIPE_COUNT_RD(Device,
+                                i,
+                                &Debug_Statistics_p->Pipe_Total_Packets[i],
+                                &Debug_Statistics_p->Pipe_Current_Packets[i],
+                                &Debug_Statistics_p->Pipe_Max_Packets[i]);
+        EIP97_DBG_PIPE_DCOUNT_RD(Device,
+                                 i,
+                                 &Debug_Statistics_p->Pipe_Data_Count[i]);
+    }
+    for (i = EIP97_GLOBAL_MAX_NOF_PE_TO_USE; i < 16; i++)
+    {
+        Debug_Statistics_p->Pipe_Total_Packets[i] = 0;
+        Debug_Statistics_p->Pipe_Current_Packets[i] = 0;
+        Debug_Statistics_p->Pipe_Max_Packets[i] = 0;
+        Debug_Statistics_p->Pipe_Data_Count[i] = 0;
+    }
+    return 0;
+}
+#endif
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_DFE_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_DFE_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP97_Global_DFE_Status_t * const DFE_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(DFE_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_DFE_TRD_STAT_RD(Device,
+                           DFEDSEOffset,
+                           PE_Number,
+                           &DFE_Status_p->CDFifoWord32Count,
+                           &DFE_Status_p->CDR_ID,
+                           &DFE_Status_p->DMASize,
+                           &DFE_Status_p->fAtDMABusy,
+                           &DFE_Status_p->fDataDMABusy,
+                           &DFE_Status_p->fDMAError);
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        if(DFE_Status_p->fDMAError)
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    EIP97_GLOBAL_STATE_FATAL_ERROR);
+        else
+            // Remain in the current state
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_DSE_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_DSE_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP97_Global_DSE_Status_t * const DSE_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int DFEDSEOffset;
+    DFEDSEOffset = EIP97_DFEDSE_Offset_Get();
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(DSE_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202_DSE_TRD_STAT_RD(Device,
+                           DFEDSEOffset,
+                           PE_Number,
+                           &DSE_Status_p->RDFifoWord32Count,
+                           &DSE_Status_p->RDR_ID,
+                           &DSE_Status_p->DMASize,
+                           &DSE_Status_p->fDataFlushBusy,
+                           &DSE_Status_p->fDataDMABusy,
+                           &DSE_Status_p->fDMAError);
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        if(DSE_Status_p->fDMAError)
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    EIP97_GLOBAL_STATE_FATAL_ERROR);
+        else
+            // Remain in the current state
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_EIP96_Token_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_EIP96_Token_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP96_Token_Status_t * const Token_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(Token_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        // Remain in the current state
+        rv = EIP97_Global_State_Set(
+                (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP96_TOKEN_CTRL_STAT_RD(Device,
+                             PE_Number,
+                             &Token_Status_p->ActiveTokenCount,
+                             &Token_Status_p->fTokenLocationAvailable,
+                             &Token_Status_p->fResultTokenAvailable,
+                             &Token_Status_p->fTokenReadActive,
+                             &Token_Status_p->fContextCacheActive,
+                             &Token_Status_p->fContextFetch,
+                             &Token_Status_p->fResultContext,
+                             &Token_Status_p->fProcessingHeld,
+                             &Token_Status_p->fBusy);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_EIP96_Context_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_EIP96_Context_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP96_Context_Status_t * const Context_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(Context_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    EIP96_CONTEXT_STAT_RD(Device,
+                          PE_Number,
+                          &Context_Status_p->Error,
+                          &Context_Status_p->AvailableTokenCount,
+                          &Context_Status_p->fActiveContext,
+                          &Context_Status_p->fNextContext,
+                          &Context_Status_p->fResultContext,
+                          &Context_Status_p->fErrorRecovery);
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        if((Context_Status_p->Error & EIP96_TIMEOUT_FATAL_ERROR_MASK) != 0)
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    EIP97_GLOBAL_STATE_FATAL_ERROR);
+        else
+            // Remain in the current state
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_EIP96_OutXfer_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_EIP96_OutXfer_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP96_Output_Transfer_Status_t * const OutXfer_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(OutXfer_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        // Remain in the current state
+        rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP96_OUT_TRANS_CTRL_STAT_RD(Device,
+                                 PE_Number,
+                                 &OutXfer_Status_p->AvailableWord32Count,
+                                 &OutXfer_Status_p->MinTransferWordCount,
+                                 &OutXfer_Status_p->MaxTransferWordCount,
+                                 &OutXfer_Status_p->TransferSizeMask);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_EIP96_PRNG_Status_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_EIP96_PRNG_Status_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        EIP96_PRNG_Status_t * const PRNG_Status_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(PRNG_Status_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        // Remain in the current state
+        rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP96_PRNG_STAT_RD(Device,
+                       PE_Number,
+                       &PRNG_Status_p->fBusy,
+                       &PRNG_Status_p->fResultReady);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip97_global_event.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm.c
new file mode 100644
index 0000000..e3f5ffb
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm.c
@@ -0,0 +1,164 @@
+/* eip97_global_fsm.c
+ *
+ * EIP-97 Global Control Driver Library API State Machine Internal Interface
+ * implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_fsm.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// EIP-97 Driver Library Types API
+#include "eip97_global_types.h"        // EIP97_Global_* types
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_State_Set
+ *
+ */
+EIP97_Global_Error_t
+EIP97_Global_State_Set(
+        volatile EIP97_Global_State_t * const CurrentState,
+        const EIP97_Global_State_t NewState)
+{
+    switch(*CurrentState)
+    {
+        case EIP97_GLOBAL_STATE_UNKNOWN:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_START:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+         case EIP97_GLOBAL_STATE_HW_RESET_DONE:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_INITIALIZED:
+                   *CurrentState = NewState;
+                   break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_SW_RESET_START:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_START:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                case EIP97_GLOBAL_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_INITIALIZED:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_ENABLED:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_INITIALIZED:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_ENABLED:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_START:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_FATAL_ERROR:
+                    break;
+                case EIP97_GLOBAL_STATE_ENABLED:
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        case EIP97_GLOBAL_STATE_FATAL_ERROR:
+            switch(NewState)
+            {
+                case EIP97_GLOBAL_STATE_SW_RESET_START:
+                    *CurrentState = NewState;
+                    break;
+                case EIP97_GLOBAL_STATE_SW_RESET_DONE:
+                    *CurrentState = NewState;
+                    break;
+                default:
+                    return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+            }
+            break;
+
+        default:
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip97_global_fsm.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm_stub.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm_stub.c
new file mode 100644
index 0000000..4289875
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_fsm_stub.c
@@ -0,0 +1,68 @@
+/* eip97_global_fsm_stub.c
+ *
+ * EIP-97 Global Control Driver Library API State Machine Internal Interface
+ * stub implementation
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_fsm.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"                // IDENTIFIER_NOT_USED
+
+// EIP-97 Driver Library Types API
+#include "eip97_global_types.h"        // EIP97_Global_* types
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_State_Set
+ *
+ */
+EIP97_Global_Error_t
+EIP97_Global_State_Set(
+        EIP97_Global_State_t * const CurrentState,
+        const EIP97_Global_State_t NewState)
+{
+    IDENTIFIER_NOT_USED(CurrentState);
+    IDENTIFIER_NOT_USED((bool)NewState);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip97_global_fsm_stub.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_init.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_init.c
new file mode 100644
index 0000000..5f060cb
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_init.c
@@ -0,0 +1,827 @@
+/* eip97_global_init.c
+ *
+ * EIP-97 Global Control Driver Library
+ * Initialization Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_init.h"
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+
+// Default configuration
+#include "c_eip97_global.h"
+
+// Driver Framework Basic Definitions API
+#include "basic_defs.h"             // uint32_t
+
+// Driver Framework C Run-time Library API
+#include "clib.h"                       // ZEROINIT
+
+// Driver Framework Device API
+#include "device_types.h"           // Device_Handle_t
+
+// EIP-97 Global Control Driver Library Internal interfaces
+#include "eip97_global_internal.h"
+#include "eip97_global_level0.h"       // EIP-97 Level 0 macros
+#include "eip202_global_init.h"        // EIP-202 Initialization code
+#include "eip206_level0.h"             // EIP-206 Level 0 macros
+#include "eip96_level0.h"              // EIP-96 Level 0 macros
+#include "eip97_global_fsm.h"          // State machine
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+// Maximum number of Packet Engines that should be used
+// Driver Library will check the maximum number supported run-time
+#ifndef EIP97_GLOBAL_MAX_NOF_PE_TO_USE
+#error "EIP97_GLOBAL_MAX_NOF_PE_TO_USE is not defined"
+#endif
+
+// Number of Ring interfaces
+// Maximum number of Ring interfaces that should be used
+// Driver Library will check the maximum number supported run-time
+#ifndef EIP97_GLOBAL_MAX_NOF_RING_TO_USE
+#error "EIP97_GLOBAL_MAX_NOF_RING_TO_USE is not defined"
+#endif
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+static unsigned int Global97_NofPEs;
+static unsigned int Global97_NofRings;
+static unsigned int Global97_NofLA;
+static unsigned int Global97_NofIN;
+static unsigned int Global97_DFEDSEOffset;
+static unsigned int Global97_SupportedFuncs;
+
+/*----------------------------------------------------------------------------
+ * EIP206Lib_Detect
+ *
+ * Checks the presence of EIP-206 PE hardware. Returns true when found.
+ */
+static bool
+EIP206Lib_Detect(
+        const Device_Handle_t Device,
+        const unsigned int PEnr)
+{
+    uint32_t Value;
+
+    // No revision register for this HW version
+
+    // read-write test one of the registers
+
+    // Set MASK_8_BITS bits of the EIP206_OUT_REG_DBUF_TRESH register
+    EIP206_Write32(Device,
+                   EIP206_OUT_REG_DBUF_TRESH(PEnr),
+                   MASK_8_BITS);
+    Value = EIP206_Read32(Device,
+                          EIP206_OUT_REG_DBUF_TRESH(PEnr));
+    if ((Value & MASK_8_BITS) != MASK_8_BITS)
+        return false;
+
+    // Clear MASK_8_BITS bits of the EIP206_OUT_REG_DBUF_TRESH(PEnr) register
+    EIP206_Write32(Device, EIP206_OUT_REG_DBUF_TRESH(PEnr), 0);
+    Value = EIP206_Read32(Device, EIP206_OUT_REG_DBUF_TRESH(PEnr));
+    if ((Value & MASK_8_BITS) != 0)
+       return false;
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP96Lib_Detect
+ *
+ * Checks the presence of EIP-96 Engine hardware. Returns true when found.
+ */
+static bool
+EIP96Lib_Detect(
+        const Device_Handle_t Device,
+        const unsigned int PEnr)
+{
+    uint32_t Value, DefaultValue;
+    bool fSuccess = true;
+
+    // No revision register for this HW version
+
+    // Save the default register value
+    DefaultValue = EIP96_Read32(Device,
+                                EIP96_REG_CONTEXT_CTRL(PEnr));
+
+    // read-write test one of the registers
+
+    // Set MASK_6_BITS bits of the EIP96_REG_CONTEXT_CTRL register
+    EIP96_Write32(Device,
+                  EIP96_REG_CONTEXT_CTRL(PEnr),
+                  MASK_6_BITS );
+    Value = EIP96_Read32(Device, EIP96_REG_CONTEXT_CTRL(PEnr));
+    if ((Value & MASK_6_BITS) != MASK_6_BITS)
+        fSuccess = false;
+
+    if( fSuccess )
+    {
+        // Clear MASK_6_BITS bits of the EIP96_REG_CONTEXT_CTRL register
+        EIP96_Write32(Device, EIP96_REG_CONTEXT_CTRL(PEnr), 0);
+        Value = EIP96_Read32(Device, EIP96_REG_CONTEXT_CTRL(PEnr));
+        if ((Value & MASK_6_BITS) != 0)
+            fSuccess = false;
+    }
+
+    // Restore the default register value
+    EIP96_Write32(Device,
+            EIP96_REG_CONTEXT_CTRL(PEnr),
+                  DefaultValue );
+    return fSuccess;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97Lib_Detect
+ *
+ * Checks the presence of EIP-97 Engine hardware. Returns true when found.
+ */
+static bool
+EIP97Lib_Detect(
+        const Device_Handle_t Device)
+{
+#ifdef EIP97_GLOBAL_VERSION_CHECK_ENABLE
+    uint32_t Value;
+
+    // read and check the revision register
+    Value = EIP97_Read32(Device, EIP97_REG_VERSION);
+    if (!EIP97_REV_SIGNATURE_MATCH( Value ))
+        return false;
+#else
+    IDENTIFIER_NOT_USED(Device);
+#endif // EIP97_GLOBAL_VERSION_CHECK_ENABLE
+
+    return true;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP202Lib_HWRevision_Get
+ */
+static void
+EIP202Lib_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP202_Options_t * const Options_p,
+        EIP202_Options2_t * const Options2_p,
+        EIP_Version_t * const Version_p)
+{
+    EIP202_Capabilities_t EIP202_Capabilities;
+    EIP202_Global_HWRevision_Get(Device, &EIP202_Capabilities);
+
+    Version_p->EipNumber = EIP202_Capabilities.EipNumber;
+    Version_p->ComplmtEipNumber = EIP202_Capabilities.ComplmtEipNumber;
+    Version_p->HWPatchLevel = EIP202_Capabilities.HWPatchLevel;
+    Version_p->MinHWRevision = EIP202_Capabilities.MinHWRevision;
+    Version_p->MajHWRevision = EIP202_Capabilities.MajHWRevision;
+
+    Options_p->NofRings = EIP202_Capabilities.NofRings;
+    Options_p->NofPes = EIP202_Capabilities.NofPes;
+    Options_p->fExpPlf = EIP202_Capabilities.fExpPlf;
+    Options_p->CF_Size = EIP202_Capabilities.CF_Size;
+    Options_p->RF_Size = EIP202_Capabilities.RF_Size;
+    Options_p->HostIfc = EIP202_Capabilities.HostIfc;
+    Options_p->DMA_Len = EIP202_Capabilities.DMA_Len;
+    Options_p->HDW = EIP202_Capabilities.HDW;
+    Options_p->TgtAlign = EIP202_Capabilities.TgtAlign;
+    Options_p->fAddr64 = EIP202_Capabilities.fAddr64;
+
+    Options2_p->NofLA_Ifs = EIP202_Capabilities.NofLA_Ifs;
+    Options2_p->NofIN_Ifs = EIP202_Capabilities.NofIN_Ifs;
+    Options2_p->NofAXI_WrChs = EIP202_Capabilities.NofAXI_WrChs;
+    Options2_p->NofAXI_RdClusters = EIP202_Capabilities.NofAXI_RdClusters;
+    Options2_p->NofAXI_RdCPC = EIP202_Capabilities.NofAXI_RdCPC;
+
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP96Lib_HWRevision_Get
+ */
+static void
+EIP96Lib_HWRevision_Get(
+        const Device_Handle_t Device,
+        const unsigned int PEnr,
+        EIP96_Options_t * const Options_p,
+        EIP_Version_t * const Version_p)
+{
+    uint32_t OptionsVal;
+    EIP96_EIP_REV_RD(Device,
+                     PEnr,
+                     &Version_p->EipNumber,
+                     &Version_p->ComplmtEipNumber,
+                     &Version_p->HWPatchLevel,
+                     &Version_p->MinHWRevision,
+                     &Version_p->MajHWRevision);
+
+    EIP96_OPTIONS_RD(Device,
+                     PEnr,
+                     &Options_p->fAES,
+                     &Options_p->fAESfb,
+                     &Options_p->fAESspeed,
+                     &Options_p->fDES,
+                     &Options_p->fDESfb,
+                     &Options_p->fDESspeed,
+                     &Options_p->ARC4,
+                     &Options_p->fAES_XTS,
+                     &Options_p->fWireless,
+                     &Options_p->fMD5,
+                     &Options_p->fSHA1,
+                     &Options_p->fSHA1speed,
+                     &Options_p->fSHA224_256,
+                     &Options_p->fSHA384_512,
+                     &Options_p->fXCBC_MAC,
+                     &Options_p->fCBC_MACspeed,
+                     &Options_p->fCBC_MACkeylens,
+                     &Options_p->fGHASH);
+    Global97_SupportedFuncs = Device_Read32(Device, EIP96_REG_OPTIONS(0)) & 0xfffffff0;
+    OptionsVal = Device_Read32(Device, EIP97_REG_OPTIONS);
+    if ((OptionsVal & BIT_30) != 0)
+    {
+        Global97_SupportedFuncs |= BIT_3;
+    }
+    if ((OptionsVal & BIT_25) != 0)
+    {
+        Global97_SupportedFuncs |= BIT_2;
+    }
+    if ((OptionsVal & BIT_24) != 0)
+    {
+        Global97_SupportedFuncs |= BIT_1;
+    }
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97Lib_HWRevision_Get
+ */
+static void
+EIP97Lib_HWRevision_Get(
+        const Device_Handle_t Device,
+        EIP97_Options_t * const Options_p,
+        EIP_Version_t * const Version_p)
+{
+    EIP97_EIP_REV_RD(Device,
+                     &Version_p->EipNumber,
+                     &Version_p->ComplmtEipNumber,
+                     &Version_p->HWPatchLevel,
+                     &Version_p->MinHWRevision,
+                     &Version_p->MajHWRevision);
+
+    EIP97_OPTIONS_RD(Device,
+                     &Options_p->NofPes,
+                     &Options_p->in_tbuf_size,
+                     &Options_p->in_dbuf_size,
+                     &Options_p->out_tbuf_size,
+                     &Options_p->out_dbuf_size,
+                     &Options_p->central_prng,
+                     &Options_p->tg,
+                     &Options_p->trc);
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97Lib_Reset_IsDone
+ */
+static EIP97_Global_Error_t
+EIP97Lib_Reset_IsDone(
+        const Device_Handle_t Device,
+        volatile uint32_t * State_p,
+        const unsigned int PEnr)
+{
+    bool fResetDone = EIP202_Global_Reset_IsDone(Device, PEnr);
+
+    if(fResetDone)
+    {
+        // Transit to a new state
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+        {
+            EIP97_Global_Error_t rv;
+
+            rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)State_p,
+                                        EIP97_GLOBAL_STATE_SW_RESET_DONE);
+            if(rv != EIP97_GLOBAL_NO_ERROR)
+                return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+    }
+    else
+    {
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+        {
+            EIP97_Global_Error_t rv;
+
+            // SW Reset is ongoing, retry later
+            rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)State_p,
+                                        EIP97_GLOBAL_STATE_SW_RESET_START);
+            if(rv != EIP97_GLOBAL_NO_ERROR)
+                return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+        return EIP97_GLOBAL_BUSY_RETRY_LATER;
+    }
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Init
+ */
+EIP97_Global_Error_t
+EIP97_Global_Init(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    unsigned int i;
+    EIP97_Global_Capabilities_t Capabilities;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    ZEROINIT(Capabilities);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    // Attempt to initialize slave byte swapping.
+    if (!EIP202_Global_Endianness_Slave_Configure(Device))
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Detect presence of the EIP-97 HW hardware
+    if (!EIP202_Global_Detect(Device) ||
+        !EIP206Lib_Detect(Device, PE_DEFAULT_NR) ||
+        !EIP96Lib_Detect(Device, PE_DEFAULT_NR) ||
+        !EIP97Lib_Detect(Device))
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+    // Can also be EIP97_GLOBAL_STATE_HW_RESET_DONE
+    TrueIOArea_p->State = (uint32_t)EIP97_GLOBAL_STATE_SW_RESET_DONE;
+
+    EIP97Lib_HWRevision_Get(Device,
+                            &Capabilities.EIP97_Options,
+                            &Capabilities.EIP97_Version);
+
+    EIP202Lib_HWRevision_Get(Device,
+                             &Capabilities.EIP202_Options,
+                             &Capabilities.EIP202_Options2,
+                             &Capabilities.EIP202_Version);
+
+    EIP96Lib_HWRevision_Get(Device,
+                            PE_DEFAULT_NR,
+                            &Capabilities.EIP96_Options,
+                            &Capabilities.EIP96_Version);
+
+    // Check actual configuration HW against capabilities
+    // Number of configured PE's
+    Global97_NofPEs = MIN(Capabilities.EIP202_Options.NofPes,
+                          EIP97_GLOBAL_MAX_NOF_PE_TO_USE);
+
+    // Number of configure ring interfaces
+    Global97_NofRings = MIN(Capabilities.EIP202_Options.NofRings,
+                            EIP97_GLOBAL_MAX_NOF_RING_TO_USE);
+
+    // Number of configured Look-aside FIFO interfaces
+#if EIP97_GLOBAL_MAX_NOF_LAFIFO_TO_USE==0
+    Global97_NofLA = 0;
+#else
+    Global97_NofLA = MIN(Capabilities.EIP202_Options2.NofLA_Ifs,
+                         EIP97_GLOBAL_MAX_NOF_LAFIFO_TO_USE);
+#endif
+#if EIP97_GLOBAL_MAX_NOF_INFIFO_TO_USE==0
+    Global97_NofIN = 0;
+#else
+    // Number of configured Inline FIFO interfaces
+    Global97_NofIN = MIN(Capabilities.EIP202_Options2.NofIN_Ifs,
+                         EIP97_GLOBAL_MAX_NOF_INFIFO_TO_USE);
+#endif
+
+    // EIP197 devices with more than 12 rings move the
+    // DFE and DSE register addresses up by 2*4kB to make room for 2 extra
+    // sets of ring control registers.
+    if (Capabilities.EIP202_Options.NofRings > 12)
+    {
+        Global97_DFEDSEOffset = 0x2000;
+    }
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+        {
+            EIP97_Global_Error_t rv;
+
+            // Transit to a new state
+            rv = EIP97_Global_State_Set(
+                    (volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                    EIP97_GLOBAL_STATE_INITIALIZED);
+            if(rv != EIP97_GLOBAL_NO_ERROR)
+                return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+        }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    // Configure Endianness Conversion method for master (DMA) interface
+    for (i = 0; i < Global97_NofPEs; i++)
+        EIP97_MST_CTRL_WR(Device,
+                          i,
+                          EIP97_GLOBAL_RD_CACHE_VALUE,
+                          EIP97_GLOBAL_WR_CACHE_VALUE,
+                          EIP97_GLOBAL_BYTE_SWAP_METHOD,
+                          EIP97_GLOBAL_SUPPORT_PROTECT_VALUE,
+                          0,  // Disable cache-aligned context writes.
+                          false);
+    {
+        uint8_t ipbuf_max, ipbuf_min,
+                itbuf_max, itbuf_min,
+                opbuf_max, opbuf_min;
+
+#ifdef EIP97_GLOBAL_THRESH_CONFIG_AUTO
+        // Calculate the EIP-202 and EIP-206 Global Control thresholds
+        uint8_t dmalen;
+
+        // Convert to powers of byte counts from powers of 32-bit word counts
+        ipbuf_max = Capabilities.EIP97_Options.in_dbuf_size + 2;
+        itbuf_max = Capabilities.EIP97_Options.in_tbuf_size + 2;
+        opbuf_max = Capabilities.EIP97_Options.out_dbuf_size + 2;
+
+        // EIP-96 token cannot be larger than 2^7 bytes
+        if( itbuf_max > EIP97_GLOBAL_MAX_TOKEN_SIZE )
+            itbuf_max = EIP97_GLOBAL_MAX_TOKEN_SIZE;
+
+        // DMA_Len is power of byte count
+        if (Capabilities.EIP202_Options.DMA_Len >= 1)
+            dmalen = Capabilities.EIP202_Options.DMA_Len - 1;
+        else
+            dmalen = Capabilities.EIP202_Options.DMA_Len;
+
+        ipbuf_max = MIN(ipbuf_max, dmalen);
+        itbuf_max = MIN(itbuf_max, dmalen);
+        opbuf_max = MIN(opbuf_max, dmalen);
+
+        ipbuf_min = ipbuf_max - 1;
+        itbuf_min = itbuf_max - 1;
+        opbuf_min = opbuf_max - 1;
+#else
+        // Use configured statically
+        // the EIP-202 and EIP-206 Global Control thresholds
+        ipbuf_min = EIP97_GLOBAL_DFE_MIN_DATA_XFER_SIZE;
+        ipbuf_max = EIP97_GLOBAL_DFE_MAX_DATA_XFER_SIZE;
+
+        itbuf_min = EIP97_GLOBAL_DFE_MIN_TOKEN_XFER_SIZE;
+        itbuf_max = EIP97_GLOBAL_DFE_MAX_TOKEN_XFER_SIZE;
+
+        opbuf_min = EIP97_GLOBAL_DSE_MIN_DATA_XFER_SIZE;
+        opbuf_max = EIP97_GLOBAL_DSE_MAX_DATA_XFER_SIZE;
+#endif
+
+        EIP202_Global_Init(Device,
+                           Global97_NofPEs,
+                           Capabilities.EIP202_Options2.NofLA_Ifs,
+                           ipbuf_min,
+                           ipbuf_max,
+                           itbuf_min,
+                           itbuf_max,
+                           opbuf_min,
+                           opbuf_max);
+        for (i = 0; i < Global97_NofPEs; i++)
+        {
+
+            // Configure EIP-206 Processing Engine
+            EIP206_IN_DBUF_THRESH_WR(
+                            Device,
+                            i,
+                            0,
+                            ipbuf_min,
+                            ipbuf_max); // ... or use 0xF for maximum, autoconf
+
+            EIP206_IN_TBUF_THRESH_WR(
+                            Device,
+                            i,
+                            EIP97_GLOBAL_IN_TBUF_PKT_THR,
+                            itbuf_min,
+                            itbuf_max); // ... or use 0xF for maximum, autoconf
+
+            EIP206_OUT_DBUF_THRESH_WR(
+                            Device,
+                            i,
+                            opbuf_min,
+                            opbuf_max); // ... or use 0xF for maximum, autoconf
+
+            // Configure EIP-96 Packet Engine
+            EIP96_TOKEN_CTRL_STAT_WR(
+                    Device,
+                    i,
+                    true, /* optimal context update */
+                    EIP97_GLOBAL_EIP96_NO_TOKEN_WAIT, /* CT No token wait */
+                    false, /* Absulute ARC4 pointer */
+                    false, /* Allow reuse cached context */
+                    false, /* Allow postponed reuse */
+                    false, /* Zero length result */
+                    (EIP97_GLOBAL_EIP96_TIMEOUT_CNTR_FLAG == 0) ? false : true,
+                    (EIP97_GLOBAL_EIP96_EXTENDED_ERRORS_ENABLE == 0) ? false : true
+                    );
+            EIP96_TOKEN_CTRL2_WR(
+                    Device,
+                    i,
+                    true,
+                    true,
+                    false,
+                    EIP97_GLOBAL_EIP96_CTX_DONE_PULSE);
+            EIP96_OUT_BUF_CTRL_WR(
+                    Device,
+                    i,
+                    EIP97_GLOBAL_EIP96_PE_HOLD_OUTPUT_DATA,
+                    (EIP97_GLOBAL_EIP96_BLOCK_UPDATE_APPEND == 0) ? false : true,
+                    (EIP97_GLOBAL_EIP96_LEN_DELTA_ENABLE == 0) ? false : true);
+            EIP96_CONTEXT_CTRL_WR(
+                Device,
+                i,
+                EIP97_EIP96_CTX_SIZE,
+                false,
+                true);
+            EIP96_CTX_NUM32_THR_WR(
+                Device,
+                i,
+                EIP97_GLOBAL_EIP96_NUM32_THR);
+            EIP96_CTX_NUM64_THR_L_WR(
+                Device,
+                i,
+                EIP97_GLOBAL_EIP96_NUM64_THR_L);
+            EIP96_CTX_NUM64_THR_H_WR(
+                Device,
+                i,
+                EIP97_GLOBAL_EIP96_NUM64_THR_H);
+#ifdef EIP97_GLOBAL_HAVE_ECN_FIXUP
+            EIP96_ECN_TABLE_WR(Device, i, 0,
+                               0, 0,
+                               1, 0,
+                               2, 0,
+                               3, 0);
+            EIP96_ECN_TABLE_WR(Device, i, 1,
+                               0, EIP96_ECN_CLE0,
+                               1, 0,
+                               1, 0,
+                               3, EIP96_ECN_CLE1);
+            EIP96_ECN_TABLE_WR(Device, i, 2,
+                               0, EIP96_ECN_CLE2,
+                               1, EIP96_ECN_CLE3,
+                               2, 0,
+                               3, 0);
+            EIP96_ECN_TABLE_WR(Device, i, 3,
+                               0, EIP96_ECN_CLE4,
+                               3, 0,
+                               3, 0,
+                               3, 0);
+#endif
+        } // for
+
+    } // EIP-202 HIA Global is configured
+
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Reset
+ */
+EIP97_Global_Error_t
+EIP97_Global_Reset(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const Device_Handle_t Device)
+{
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int i;
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    // Attempt to initialize slave byte swapping.
+    if (!EIP202_Global_Endianness_Slave_Configure(Device))
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    // Initialize the IO Area
+    TrueIOArea_p->Device = Device;
+    // Assume this function is called in the Unknown state but
+    // this may not always be true
+    TrueIOArea_p->State = (uint32_t)EIP97_GLOBAL_STATE_UNKNOWN;
+
+    if (!EIP202_Global_Reset(Device, Global97_NofPEs))
+        return EIP97_GLOBAL_UNSUPPORTED_FEATURE_ERROR;
+
+    for (i = 0; i < Global97_NofPEs; i++)
+    {
+        // Restore the EIP-206 default configuration
+        EIP206_IN_DBUF_THRESH_DEFAULT_WR(Device, i);
+        EIP206_IN_TBUF_THRESH_DEFAULT_WR(Device, i);
+        EIP206_OUT_DBUF_THRESH_DEFAULT_WR(Device, i);
+        EIP206_OUT_TBUF_THRESH_DEFAULT_WR(Device, i);
+
+        // Restore the EIP-96 default configuration
+        EIP96_TOKEN_CTRL_STAT_DEFAULT_WR(Device, i);
+    }
+
+    // Check if Global SW Reset is done
+    for (i = 0; i < Global97_NofPEs; i++)
+    {
+        EIP97_Global_Error_t EIP97_Rc;
+
+        EIP97_Rc =
+            EIP97Lib_Reset_IsDone(Device, &TrueIOArea_p->State, i);
+
+        if (EIP97_Rc != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_Rc;
+    }
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Reset_IsDone
+ */
+EIP97_Global_Error_t
+EIP97_Global_Reset_IsDone(
+        EIP97_Global_IOArea_t * const IOArea_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    unsigned int i;
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    Device = TrueIOArea_p->Device;
+
+    // Check if Global SW Reset is done
+    for (i = 0; i < Global97_NofPEs; i++)
+    {
+        EIP97_Global_Error_t EIP97_Rc;
+
+        EIP97_Rc =
+            EIP97Lib_Reset_IsDone(Device, &TrueIOArea_p->State, i);
+
+        if (EIP97_Rc != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_Rc;
+    }
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_HWRevision_Get
+ */
+EIP97_Global_Error_t
+EIP97_Global_HWRevision_Get(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        EIP97_Global_Capabilities_t * const Capabilities_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(Capabilities_p);
+
+    Device = TrueIOArea_p->Device;
+
+    EIP202Lib_HWRevision_Get(Device,
+                             &Capabilities_p->EIP202_Options,
+                             &Capabilities_p->EIP202_Options2,
+                             &Capabilities_p->EIP202_Version);
+
+    EIP96Lib_HWRevision_Get(Device,
+                            PE_DEFAULT_NR,
+                            &Capabilities_p->EIP96_Options,
+                            &Capabilities_p->EIP96_Version);
+
+    EIP97Lib_HWRevision_Get(Device,
+                            &Capabilities_p->EIP97_Options,
+                            &Capabilities_p->EIP97_Version);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_Configure
+ */
+EIP97_Global_Error_t
+EIP97_Global_Configure(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        const EIP97_Global_Ring_PE_Map_t * const RingPEMap_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+    EIP202_Global_Ring_PE_Map_t EIP202RingPEMap;
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+    EIP97_GLOBAL_CHECK_POINTER(RingPEMap_p);
+
+    if(PE_Number >= Global97_NofPEs)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+    // Figure out which rings must be assigned to
+    // DFE and DSE threads for PE_Number
+    EIP202RingPEMap.RingPE_Mask = (uint16_t)(RingPEMap_p->RingPE_Mask &
+                                             ((1 << (Global97_NofRings + Global97_NofLA + Global97_NofIN))-1));
+    EIP202RingPEMap.RingPrio_Mask = RingPEMap_p->RingPrio_Mask;
+    EIP202RingPEMap.RingSlots0 = RingPEMap_p->RingSlots0;
+    EIP202RingPEMap.RingSlots1 = RingPEMap_p->RingSlots1;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+        EIP97_Global_State_t NewState;
+
+        // Transit to a new state
+        if(EIP202RingPEMap.RingPE_Mask != 0)
+            NewState = EIP97_GLOBAL_STATE_ENABLED;
+        else
+            // Engines without rings not allowed!
+            NewState = EIP97_GLOBAL_STATE_INITIALIZED;
+
+        rv = EIP97_Global_State_Set(
+                (volatile EIP97_Global_State_t*)&TrueIOArea_p->State, NewState);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP202_Global_Configure(Device, PE_Number, &EIP202RingPEMap);
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Interfaces_Get
+ */
+void
+EIP97_Interfaces_Get(
+    unsigned int * const NofPEs_p,
+    unsigned int * const NofRings_p,
+    unsigned int * const NofLA_p,
+    unsigned int * const NofIN_p)
+{
+    if (NofPEs_p)
+        *NofPEs_p = Global97_NofPEs;
+    if (NofRings_p)
+        *NofRings_p = Global97_NofRings;
+    if (NofLA_p)
+        *NofLA_p = Global97_NofLA;
+    if (NofIN_p)
+        *NofIN_p = Global97_NofIN;
+}
+
+/*----------------------------------------------------------------------------
+ * EIP97_DFEDSE_Offset_Get
+ */
+unsigned int
+EIP97_DFEDSE_Offset_Get(void)
+{
+    return Global97_DFEDSEOffset;
+}
+
+
+unsigned int
+EIP97_SupportedFuncs_Get(void)
+{
+    return Global97_SupportedFuncs;
+}
+
+
+/* end of file eip97_global_init.c */
diff --git a/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_prng.c b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_prng.c
new file mode 100644
index 0000000..eb41088
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk/kit/eip197/eip97_global_prng.c
@@ -0,0 +1,120 @@
+/* eip97_global_prng.c
+ *
+ * EIP-97 GLobal Control Driver Library
+ * PRNG Module
+ */
+
+/* -------------------------------------------------------------------------- */
+/*                                                                            */
+/*   Module        : ddk197                                                   */
+/*   Version       : 5.6.1                                                    */
+/*   Configuration : DDK-197-GPL                                              */
+/*                                                                            */
+/*   Date          : 2022-Dec-16                                              */
+/*                                                                            */
+/* Copyright (c) 2008-2022 by Rambus, Inc. and/or its subsidiaries.           */
+/*                                                                            */
+/* This program is free software: you can redistribute it and/or modify       */
+/* it under the terms of the GNU General Public License as published by       */
+/* the Free Software Foundation, either version 2 of the License, or          */
+/* any later version.                                                         */
+/*                                                                            */
+/* This program is distributed in the hope that it will be useful,            */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of             */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               */
+/* GNU General Public License for more details.                               */
+/*                                                                            */
+/* You should have received a copy of the GNU General Public License          */
+/* along with this program. If not, see <http://www.gnu.org/licenses/>.       */
+/* -------------------------------------------------------------------------- */
+
+/*----------------------------------------------------------------------------
+ * This module implements (provides) the following interface(s):
+ */
+
+#include "eip97_global_prng.h"
+
+
+/*----------------------------------------------------------------------------
+ * This module uses (requires) the following interface(s):
+ */
+
+// Driver Framework Device API
+#include "device_types.h"              // Device_Handle_t
+
+// EIP-97 Global Control Driver Library Internal interfaces
+#include "eip97_global_internal.h"
+#include "eip96_level0.h"              // EIP-96 Level 0 macros
+#include "eip97_global_fsm.h"          // State machine
+
+
+/*----------------------------------------------------------------------------
+ * Definitions and macros
+ */
+
+
+/*----------------------------------------------------------------------------
+ * Local variables
+ */
+
+
+/*----------------------------------------------------------------------------
+ * EIP97_Global_PRNG_Reseed
+ */
+EIP97_Global_Error_t
+EIP97_Global_PRNG_Reseed(
+        EIP97_Global_IOArea_t * const IOArea_p,
+        const unsigned int PE_Number,
+        const EIP96_PRNG_Reseed_t * const ReseedData_p)
+{
+    Device_Handle_t Device;
+    volatile EIP97_True_IOArea_t * const TrueIOArea_p = IOAREA(IOArea_p);
+
+    EIP97_GLOBAL_CHECK_POINTER(IOArea_p);
+
+    if(PE_Number >= EIP97_GLOBAL_MAX_NOF_PE_TO_USE)
+        return EIP97_GLOBAL_ARGUMENT_ERROR;
+
+    Device = TrueIOArea_p->Device;
+
+#ifdef EIP97_GLOBAL_DEBUG_FSM
+    {
+        EIP97_Global_Error_t rv;
+
+        // Remain in the current state
+        rv = EIP97_Global_State_Set((volatile EIP97_Global_State_t*)&TrueIOArea_p->State,
+                                    (EIP97_Global_State_t)TrueIOArea_p->State);
+        if(rv != EIP97_GLOBAL_NO_ERROR)
+            return EIP97_GLOBAL_ILLEGAL_IN_STATE;
+    }
+#endif // EIP97_GLOBAL_DEBUG_FSM
+
+    EIP96_PRNG_CTRL_WR(Device,
+                       PE_Number, // EIP-96 PE number
+                       false,     // Disable PRNG
+                       false);    // Set PRNG Manual mode
+
+    // Write new seed data
+    EIP96_PRNG_SEED_L_WR(Device, PE_Number, ReseedData_p->SeedLo);
+    EIP96_PRNG_SEED_H_WR(Device, PE_Number, ReseedData_p->SeedHi);
+
+    // Write new key data
+    EIP96_PRNG_KEY_0_L_WR(Device, PE_Number, ReseedData_p->Key0Lo);
+    EIP96_PRNG_KEY_0_H_WR(Device, PE_Number, ReseedData_p->Key0Hi);
+    EIP96_PRNG_KEY_1_L_WR(Device, PE_Number, ReseedData_p->Key1Lo);
+    EIP96_PRNG_KEY_1_H_WR(Device, PE_Number, ReseedData_p->Key1Hi);
+
+    // Write new LFSR data
+    EIP96_PRNG_LFSR_L_WR(Device, PE_Number, ReseedData_p->LFSRLo);
+    EIP96_PRNG_LFSR_H_WR(Device, PE_Number, ReseedData_p->LFSRHi);
+
+    EIP96_PRNG_CTRL_WR(Device,
+                       PE_Number, // EIP-96 PE number
+                       true,      // Enable PRNG
+                       true);     // Set PRNG Auto mode
+
+    return EIP97_GLOBAL_NO_ERROR;
+}
+
+
+/* end of file eip97_global_prng.c */