[][openwrt][mt7988][crypto][EIP197 Alpha Release]

[Description]
Add alpha version of EIP197 package(crypto-eip)

[Release-log]
N/A

Change-Id: Ib90915f531aa238b90bd0fecc81e2ec3bf6016cc
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7908928
diff --git a/package-21.02/kernel/crypto-eip/Config.in b/package-21.02/kernel/crypto-eip/Config.in
new file mode 100644
index 0000000..c68eb36
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/Config.in
@@ -0,0 +1,30 @@
+menu "Crypto Offload Configuration"
+	depends on PACKAGE_kmod-crypto-eip
+
+choice
+	prompt "Crypto Offload Mode"
+	default CRYPTO_OFFLOAD_INLINE
+	help
+	  Select crypto offload mode. Support lookaside mode or inline mode.
+
+config CRYPTO_OFFLOAD_INLINE
+	bool "Inline Mode"
+	depends on TARGET_mediatek_mt7988 && !PACKAGE_kmod-eip197_driver
+	select PACKAGE_kmod-crypto-eip-inline
+	select PACKAGE_kmod-crypto-eip-ddk
+	select PACKAGE_crypto-eip-inline-fw
+endchoice
+
+choice
+	prompt "Crypto XFRM Offload Method"
+	depends on CRYPTO_OFFLOAD_INLINE
+	default CRYPTO_XFRM_OFFLOAD_MTK_PCE
+	help
+	  Select crypto XFRM offload method. Either RAMBUS PCL support or
+	  MTK PCE support.
+
+config CRYPTO_XFRM_OFFLOAD_MTK_PCE
+	bool "Enable MTK PCE XFRM Offload"
+endchoice
+
+endmenu
diff --git a/package-21.02/kernel/crypto-eip/Makefile b/package-21.02/kernel/crypto-eip/Makefile
new file mode 100644
index 0000000..494eadb
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/Makefile
@@ -0,0 +1,46 @@
+# SPDX-Liscense-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2023 MediaTek Inc.
+#
+# Author: Chris.Chou <chris.chou@mediatek.com>
+#         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+
+include $(TOPDIR)/rules.mk
+include $(INCLUDE_DIR)/kernel.mk
+
+PKG_NAME:=crypto-eip
+PKG_RELEASE:=1
+
+include $(INCLUDE_DIR)/package.mk
+include $(INCLUDE_DIR)/package-defaults.mk
+
+# For package initialization such as menuconfig or description etc.
+EIP_KERNEL_PKGS:=
+EIP_PKGS:=
+
+include crypto-eip.mk
+include $(filter-out crypto-eip.mk,$(wildcard *.mk))
+
+EXTRA_CFLAGS+= \
+	$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
+	$(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG))))
+
+EXTRA_CFLAGS+= -Wall -Werror
+
+define Build/Prepare
+	mkdir -p $(PKG_BUILD_DIR)/firmware
+	$(CP) -r `find ./firmware -maxdepth 1 | grep -v ".git"` $(PKG_BUILD_DIR)/firmware/
+	$(CP) -r `find ./src -maxdepth 1 | grep -v ".git"` $(PKG_BUILD_DIR)/
+endef
+
+define Build/Compile
+	$(MAKE) -C "$(LINUX_DIR)" \
+		$(KERNEL_MAKE_FLAGS) \
+		M="$(PKG_BUILD_DIR)" \
+		EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
+		$(EXTRA_KCONFIG) \
+		modules
+endef
+
+$(foreach KERNEL_PKG,$(EIP_KERNEL_PKGS),$(eval $(call KernelPackage,$(KERNEL_PKG))))
+$(foreach PKG,$(EIP_PKGS),$(eval $(call BuildPackage,$(PKG))))
diff --git a/package-21.02/kernel/crypto-eip/crypto-eip-ddk.mk b/package-21.02/kernel/crypto-eip/crypto-eip-ddk.mk
new file mode 100644
index 0000000..bd6f30a
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/crypto-eip-ddk.mk
@@ -0,0 +1,55 @@
+# SPDX-Liscense-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2023 MediaTek Inc.
+#
+# Author: Chris.Chou <chris.chou@mediatek.com>
+#         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+
+# Configure for crypto-eip DDK makefile
+EIP_KERNEL_PKGS+= \
+	crypto-eip-ddk
+
+ifeq ($(CONFIG_PACKAGE_kmod-crypto-eip-ddk),y)
+EXTRA_KCONFIG+= \
+	CONFIG_RAMBUS_DDK=m
+
+EXTRA_CFLAGS+= \
+	-I$(PKG_BUILD_DIR)/ddk/inc \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/configs \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/device \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/device/lkm \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/device/lkm/of \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/dmares \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/firmware_api \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/kit/builder/sa \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/kit/builder/token \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/kit/eip197 \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/kit/iotoken \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/kit/list \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/kit/ring \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/libc \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/log \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/shdevxs \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/slad \
+	-I$(PKG_BUILD_DIR)/ddk/inc/crypto-eip/ddk/slad/lkm \
+	-DEIP197_BUS_VERSION_AXI3 \
+	-DDRIVER_64BIT_HOST \
+	-DDRIVER_64BIT_DEVICE \
+	-DADAPTER_AUTO_TOKENBUILDER
+endif
+
+# crypto-eip-ddk kernel package configuration
+define KernelPackage/crypto-eip-ddk
+  CATEGORY:=MTK Properties
+  SUBMENU:=Drivers
+  TITLE:= MTK EIP DDK
+  FILES+=$(PKG_BUILD_DIR)/ddk/crypto-eip-ddk.ko
+  DEPENDS:= \
+	@CRYPTO_OFFLOAD_INLINE \
+	kmod-crypto-eip
+endef
+
+define KernelPackage/crypto-eip-ddk/description
+  Porting DDK source code to package.
+endef
diff --git a/package-21.02/kernel/crypto-eip/crypto-eip-fw.mk b/package-21.02/kernel/crypto-eip/crypto-eip-fw.mk
new file mode 100644
index 0000000..eabefae
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/crypto-eip-fw.mk
@@ -0,0 +1,31 @@
+# SPDX-Liscense-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2023 MediaTek Inc.
+#
+# Author: Chris.Chou <chris.chou@mediatek.com>
+#         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+
+# Configure for crypto firmware makefile
+EIP_PKGS+= \
+	crypto-eip-inline-fw
+
+define Package/crypto-eip-inline-fw
+  TITLE:=Mediatek EIP Firmware
+  SECTION:=firmware
+  CATEGORY:=Firmware
+  DEPENDS:=@CRYPTO_OFFLOAD_INLINE
+endef
+
+define Package/crypto-eip-inline-fw/description
+  Load firmware for EIP197 inline mode.
+endef
+
+define Package/crypto-eip-inline-fw/install
+	$(INSTALL_DIR) $(1)/lib/firmware/
+	$(CP) \
+		$(PKG_BUILD_DIR)/firmware/bin/firmware_eip207_ifpp.bin \
+		$(PKG_BUILD_DIR)/firmware/bin/firmware_eip207_ipue.bin \
+		$(PKG_BUILD_DIR)/firmware/bin/firmware_eip207_ofpp.bin \
+		$(PKG_BUILD_DIR)/firmware/bin/firmware_eip207_opue.bin \
+		$(1)/lib/firmware/
+endef
diff --git a/package-21.02/kernel/crypto-eip/crypto-eip.mk b/package-21.02/kernel/crypto-eip/crypto-eip.mk
new file mode 100644
index 0000000..31df9bd
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/crypto-eip.mk
@@ -0,0 +1,82 @@
+# SPDX-Liscense-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2023 MediaTek Inc.
+#
+# Author: Chris.Chou <chris.chou@mediatek.com>
+#         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+
+# Configure for crypto-eip top makefile
+EIP_KERNEL_PKGS+= \
+	crypto-eip \
+	crypto-eip-inline
+
+ifeq ($(CONFIG_PACKAGE_kmod-crypto-eip),y)
+EXTRA_KCONFIG+= \
+	CONFIG_CRYPTO_OFFLOAD_INLINE=$(CONFIG_CRYPTO_OFFLOAD_INLINE)
+endif
+
+ifeq ($(CONFIG_CRYPTO_OFFLOAD_INLINE),y)
+EXTRA_KCONFIG+= \
+	CONFIG_MTK_CRYPTO_EIP_INLINE=m \
+	CONFIG_CRYPTO_XFRM_OFFLOAD_MTK_PCE=$(CONFIG_CRYPTO_XFRM_OFFLOAD_MTK_PCE)
+
+EXTRA_CFLAGS+= \
+	-I$(LINUX_DIR)/drivers/net/ethernet/mediatek/ \
+	-I$(KERNEL_BUILD_DIR)/pce/inc/
+endif
+
+# crypto-eip kernel package configuration
+define KernelPackage/crypto-eip
+  CATEGORY:=MTK Properties
+  SUBMENU:=Drivers
+  TITLE:= EIP-197 Crypto Engine Driver
+  DEFAULT:=y
+  KCONFIG:= \
+	CONFIG_CRYPTO_HW=y \
+	CONFIG_CRYPTO_AUTHENC=y \
+	CONFIG_CRYPTO_AES=y \
+	CONFIG_CRYPTO_AEAD=y \
+	CONFIG_CRYPTO_DES=y \
+	CONFIG_CRYPTO_MD5=y \
+	CONFIG_CRYPTO_SHA1=y \
+	CONFIG_CRYPTO_SHA256=y \
+	CONFIG_CRYPTO_SHA512=y \
+	CONFIG_CRYPTO_SHA3=y \
+	CONFIG_CRYPTO_HMAC=y \
+	CONFIG_INET_ESP=y
+  DEPENDS:= \
+	@TARGET_mediatek \
+	+strongswan \
+	+strongswan-default
+  $(call AddDepends/crypto)
+endef
+
+define KernelPackage/crypto-eip/description
+  Enable crypto engine to accelerate encrypt/decrypt. Support look aside
+  mode (semi-HW) and inline mode (pure-HW). Look aside mode is bind with
+  Linux Crypto API and support AES, DES, SHA1, and SHA2 algorithms. In-
+  line mode only support ESP Tunnel mode (single tunnel) now.
+endef
+
+define KernelPackage/crypto-eip/config
+	source "$(SOURCE)/Config.in"
+endef
+
+define KernelPackage/crypto-eip-inline
+  CATEGORY:=MTK Properties
+  SUBMENU:=Drivers
+  TITLE:= EIP-197 Crypto Engine Inline Driver
+  KCONFIG:= \
+	CONFIG_INET_ESP_OFFLOAD=y
+  DEPENDS:= \
+	@CRYPTO_OFFLOAD_INLINE \
+	kmod-crypto-eip \
+	kmod-crypto-eip-ddk \
+	+kmod-pce
+  FILES:=$(PKG_BUILD_DIR)/crypto-eip-inline.ko
+  $(call AddDepends/crypto)
+endef
+
+define KernelPackage/crypto-eip-inline/description
+  EIP197 inline mode. HW offload for IPsec ESP Tunnel mode.
+endef
diff --git a/package-21.02/kernel/crypto-eip/src/Kconfig b/package-21.02/kernel/crypto-eip/src/Kconfig
new file mode 100644
index 0000000..5dbbc5f
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/Kconfig
@@ -0,0 +1,8 @@
+config MTK_CRYPTO_EIP_INLINE
+	tristate "Mediatek Crypto EIP Inline"
+	help
+	  Support for Mediatek driver to control inline crypto HW offload
+	  engine EIP197. The HW offload engine support IPsec ESP inline
+	  offload. Currently, it only support ESP Tunnel and transport mode.
+	  The driver cooperate XFRM offload framework with Mediatek HNAT
+	  driver to offload ESP protocol.
diff --git a/package-21.02/kernel/crypto-eip/src/Makefile b/package-21.02/kernel/crypto-eip/src/Makefile
new file mode 100644
index 0000000..6beba79
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/Makefile
@@ -0,0 +1,17 @@
+# SPDX-Liscense-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2023 MediaTek Inc.
+#
+# Author: Chris.Chou <chris.chou@mediatek.com>
+#         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+
+obj-$(CONFIG_MTK_CRYPTO_EIP_INLINE) += crypto-eip-inline.o
+
+ccflags-y += -I$(src)/inc
+
+crypto-eip-inline-y += init.o
+crypto-eip-inline-y += ddk-wrapper.o
+
+crypto-eip-inline-$(CONFIG_CRYPTO_XFRM_OFFLOAD_MTK_PCE) += xfrm-offload.o
+
+include $(wildcard $(src)/*.mk)
diff --git a/package-21.02/kernel/crypto-eip/src/ddk-wrapper.c b/package-21.02/kernel/crypto-eip/src/ddk-wrapper.c
new file mode 100644
index 0000000..d923693
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk-wrapper.c
@@ -0,0 +1,573 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ * Author: Chris.Chou <chris.chou@mediatek.com>
+ *         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+ */
+
+#include <crypto/aes.h>
+#include <crypto/hash.h>
+#include <crypto/hmac.h>
+#include <crypto/md5.h>
+#include <linux/delay.h>
+
+#include <crypto-eip/ddk/slad/api_pcl.h>
+#include <crypto-eip/ddk/slad/api_pcl_dtl.h>
+#include <crypto-eip/ddk/slad/api_pec.h>
+#include <crypto-eip/ddk/slad/api_driver197_init.h>
+
+#include "crypto-eip/crypto-eip.h"
+#include "crypto-eip/ddk-wrapper.h"
+#include "crypto-eip/internal.h"
+#include "crypto-eip/crypto-eip197-inline-ddk.h"
+
+static bool crypto_iotoken_create(IOToken_Input_Dscr_t * const dscr_p,
+				  void * const ext_p, u32 *data_p,
+				  PEC_CommandDescriptor_t * const pec_cmd_dscr)
+{
+	int IOTokenRc;
+
+	dscr_p->InPacket_ByteCount = pec_cmd_dscr->SrcPkt_ByteCount;
+	dscr_p->Ext_p = ext_p;
+
+	IOTokenRc = IOToken_Create(dscr_p, data_p);
+	if (IOTokenRc < 0) {
+		CRYPTO_ERR("IOToken_Create error %d\n", IOTokenRc);
+		return false;
+	}
+
+	pec_cmd_dscr->InputToken_p = data_p;
+
+	return true;
+}
+
+unsigned int crypto_pe_get_one(IOToken_Output_Dscr_t *const OutTokenDscr_p,
+			       u32 *OutTokenData_p,
+			       PEC_ResultDescriptor_t *RD_p)
+{
+	int LoopCounter = MTK_EIP197_INLINE_NOF_TRIES;
+	int IOToken_Rc;
+	PEC_Status_t pecres;
+
+	ZEROINIT(*OutTokenDscr_p);
+	ZEROINIT(*RD_p);
+
+	/* Link data structures */
+	RD_p->OutputToken_p = OutTokenData_p;
+
+	while (LoopCounter > 0) {
+		/* Try to get the processed packet from the driver */
+		unsigned int Counter = 0;
+
+		pecres = PEC_Packet_Get(PEC_INTERFACE_ID, RD_p, 1, &Counter);
+		if (pecres != PEC_STATUS_OK) {
+			/* IO error */
+			CRYPTO_ERR("PEC_Packet_Get error %d\n", pecres);
+			return 0;
+		}
+
+		if (Counter) {
+			IOToken_Rc = IOToken_Parse(OutTokenData_p, OutTokenDscr_p);
+			if (IOToken_Rc < 0) {
+				/* IO error */
+				CRYPTO_ERR("IOToken_Parse error %d\n", IOToken_Rc);
+				return 0;
+			}
+
+			if (OutTokenDscr_p->ErrorCode != 0) {
+				/* Packet process error */
+				CRYPTO_ERR("Result descriptor error 0x%x\n",
+					OutTokenDscr_p->ErrorCode);
+				return 0;
+			}
+
+			/* packet received */
+			return Counter;
+		}
+
+		/* Wait for MTK_EIP197_PKT_GET_TIMEOUT_MS milliseconds */
+		udelay(MTK_EIP197_PKT_GET_TIMEOUT_MS * 1000);
+		LoopCounter--;
+	}
+
+	CRYPTO_ERR("Timeout when reading packet\n");
+
+	/* IO error (timeout, not result packet received) */
+	return 0;
+}
+
+
+bool crypto_basic_hash(SABuilder_Auth_t HashAlgo, uint8_t *Input_p,
+				unsigned int InputByteCount, uint8_t *Output_p,
+				unsigned int OutputByteCount, bool fFinalize)
+{
+	SABuilder_Params_Basic_t ProtocolParams;
+	SABuilder_Params_t params;
+	unsigned int SAWords = 0;
+	static uint8_t DummyAuthKey[64];
+	int rc;
+
+	DMABuf_Properties_t DMAProperties = {0, 0, 0, 0};
+	DMABuf_HostAddress_t TokenHostAddress;
+	DMABuf_HostAddress_t PktHostAddress;
+	DMABuf_HostAddress_t SAHostAddress;
+	DMABuf_Status_t DMAStatus;
+
+	DMABuf_Handle_t TokenHandle = {0};
+	DMABuf_Handle_t PktHandle = {0};
+	DMABuf_Handle_t SAHandle = {0};
+
+	unsigned int TokenMaxWords = 0;
+	unsigned int TokenHeaderWord;
+	unsigned int TokenWords = 0;
+	unsigned int TCRWords = 0;
+	void *TCRData = 0;
+
+	TokenBuilder_Params_t TokenParams;
+	PEC_CommandDescriptor_t Cmd;
+	PEC_ResultDescriptor_t Res;
+	unsigned int count;
+
+	u32 OutputToken[IOTOKEN_IN_WORD_COUNT];
+	u32 InputToken[IOTOKEN_IN_WORD_COUNT];
+	IOToken_Output_Dscr_t OutTokenDscr;
+	IOToken_Input_Dscr_t InTokenDscr;
+	void *InTokenDscrExt_p = NULL;
+
+#ifdef CRYPTO_IOTOKEN_EXT
+	IOToken_Input_Dscr_Ext_t InTokenDscrExt;
+
+	ZEROINIT(InTokenDscrExt);
+	InTokenDscrExt_p = &InTokenDscrExt;
+#endif
+	ZEROINIT(InTokenDscr);
+	ZEROINIT(OutTokenDscr);
+
+	rc = SABuilder_Init_Basic(&params, &ProtocolParams, SAB_DIRECTION_OUTBOUND);
+	if (rc) {
+		CRYPTO_ERR("SABuilder_Init_Basic failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	params.AuthAlgo = HashAlgo;
+	params.AuthKey1_p = DummyAuthKey;
+
+	if (!fFinalize)
+		params.flags |= SAB_FLAG_HASH_SAVE | SAB_FLAG_HASH_INTERMEDIATE;
+	params.flags |= SAB_FLAG_SUPPRESS_PAYLOAD;
+	ProtocolParams.ICVByteCount = OutputByteCount;
+
+	rc = SABuilder_GetSizes(&params, &SAWords, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of size errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
+	DMAProperties.Size = MAX(4*SAWords, 256);
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &SAHostAddress, &SAHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of SA failed: %d\n", DMAStatus);
+		goto error_exit;
+	}
+
+	rc = SABuilder_BuildSA(&params, (u32 *)SAHostAddress.p, NULL, NULL);
+	if (rc) {
+		CRYPTO_ERR("SA not created because of errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	rc = TokenBuilder_GetContextSize(&params, &TCRWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetContextSize returned errors: %d\n", rc);
+		goto error_exit;
+	}
+
+	TCRData = kmalloc(4 * TCRWords, GFP_KERNEL);
+	if (!TCRData) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of TCR failed\n");
+		goto error_exit;
+	}
+
+	rc = TokenBuilder_BuildContext(&params, TCRData);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_BuildContext failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	rc = TokenBuilder_GetSize(TCRData, &TokenMaxWords);
+	if (rc) {
+		CRYPTO_ERR("TokenBuilder_GetSize failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_TOKEN;
+	DMAProperties.Size = 4*TokenMaxWords;
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &TokenHostAddress, &TokenHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of token builder failed: %d\n", DMAStatus);
+		goto error_exit;
+	}
+
+	DMAProperties.fCached = true;
+	DMAProperties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	DMAProperties.Bank = MTK_EIP197_INLINE_BANK_PACKET;
+	DMAProperties.Size = MAX(InputByteCount, OutputByteCount);
+
+	DMAStatus = DMABuf_Alloc(DMAProperties, &PktHostAddress, &PktHandle);
+	if (DMAStatus != DMABUF_STATUS_OK) {
+		rc = 1;
+		CRYPTO_ERR("Allocation of source packet buffer failed: %d\n",
+			   DMAStatus);
+		goto error_exit;
+	}
+
+	rc = PEC_SA_Register(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+	if (rc != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC_SA_Register failed: %d\n", rc);
+		goto error_exit;
+	}
+
+	memcpy(PktHostAddress.p, Input_p, InputByteCount);
+
+	ZEROINIT(TokenParams);
+	TokenParams.PacketFlags |= (TKB_PACKET_FLAG_HASHFIRST
+				    | TKB_PACKET_FLAG_HASHAPPEND);
+	if (fFinalize)
+		TokenParams.PacketFlags |= TKB_PACKET_FLAG_HASHFINAL;
+
+	rc = TokenBuilder_BuildToken(TCRData, (u8 *) PktHostAddress.p,
+				     InputByteCount, &TokenParams,
+				     (u32 *) TokenHostAddress.p,
+				     &TokenWords, &TokenHeaderWord);
+	if (rc != TKB_STATUS_OK) {
+		CRYPTO_ERR("Token builder failed: %d\n", rc);
+		goto error_exit_unregister;
+	}
+
+	ZEROINIT(Cmd);
+	Cmd.Token_Handle = TokenHandle;
+	Cmd.Token_WordCount = TokenWords;
+	Cmd.SrcPkt_Handle = PktHandle;
+	Cmd.SrcPkt_ByteCount = InputByteCount;
+	Cmd.DstPkt_Handle = PktHandle;
+	Cmd.SA_Handle1 = SAHandle;
+	Cmd.SA_Handle2 = DMABuf_NULLHandle;
+
+
+#if defined(CRYPTO_IOTOKEN_EXT)
+	InTokenDscrExt.HW_Services  = IOTOKEN_CMD_PKT_LAC;
+#endif
+	InTokenDscr.TknHdrWordInit = TokenHeaderWord;
+
+	if (!crypto_iotoken_create(&InTokenDscr,
+				   InTokenDscrExt_p,
+				   InputToken,
+				   &Cmd)) {
+		rc = 1;
+		goto error_exit_unregister;
+	}
+
+	rc = PEC_Packet_Put(PEC_INTERFACE_ID, &Cmd, 1, &count);
+	if (rc != PEC_STATUS_OK && count != 1) {
+		rc = 1;
+		CRYPTO_ERR("PEC_Packet_Put error: %d\n", rc);
+		goto error_exit_unregister;
+	}
+
+	if (crypto_pe_get_one(&OutTokenDscr, OutputToken, &Res) < 1) {
+		rc = 1;
+		CRYPTO_ERR("error from crypto_pe_get_one\n");
+		goto error_exit_unregister;
+	}
+	memcpy(Output_p, PktHostAddress.p, OutputByteCount);
+
+error_exit_unregister:
+	PEC_SA_UnRegister(PEC_INTERFACE_ID, SAHandle, DMABuf_NULLHandle,
+				DMABuf_NULLHandle);
+
+error_exit:
+	DMABuf_Release(SAHandle);
+	DMABuf_Release(TokenHandle);
+	DMABuf_Release(PktHandle);
+
+	if (TCRData != NULL)
+		kfree(TCRData);
+
+	return rc == 0;
+}
+
+bool crypto_hmac_precompute(SABuilder_Auth_t AuthAlgo,
+			    uint8_t *AuthKey_p,
+			    unsigned int AuthKeyByteCount,
+			    uint8_t *Inner_p,
+			    uint8_t *Outer_p)
+{
+	SABuilder_Auth_t HashAlgo;
+	unsigned int blocksize, hashsize, digestsize;
+	static uint8_t pad_block[128], hashed_key[128];
+	unsigned int i;
+
+	switch (AuthAlgo) {
+	case SAB_AUTH_HMAC_MD5:
+		HashAlgo = SAB_AUTH_HASH_MD5;
+		blocksize = 64;
+		hashsize = 16;
+		digestsize = 16;
+		break;
+	case SAB_AUTH_HMAC_SHA1:
+		HashAlgo = SAB_AUTH_HASH_SHA1;
+		blocksize = 64;
+		hashsize = 20;
+		digestsize = 20;
+		break;
+	case SAB_AUTH_HMAC_SHA2_224:
+		HashAlgo = SAB_AUTH_HASH_SHA2_224;
+		blocksize = 64;
+		hashsize = 28;
+		digestsize = 32;
+		break;
+	case SAB_AUTH_HMAC_SHA2_256:
+		HashAlgo = SAB_AUTH_HASH_SHA2_256;
+		blocksize = 64;
+		hashsize = 32;
+		digestsize = 32;
+		break;
+	case SAB_AUTH_HMAC_SHA2_384:
+		HashAlgo = SAB_AUTH_HASH_SHA2_384;
+		blocksize = 128;
+		hashsize = 48;
+		digestsize = 64;
+		break;
+	case SAB_AUTH_HMAC_SHA2_512:
+		HashAlgo = SAB_AUTH_HASH_SHA2_512;
+		blocksize = 128;
+		hashsize = 64;
+		digestsize = 64;
+		break;
+	default:
+		CRYPTO_ERR("Unknown HMAC algorithm\n");
+		return false;
+	}
+
+	memset(hashed_key, 0, blocksize);
+	if (AuthKeyByteCount <= blocksize) {
+		memcpy(hashed_key, AuthKey_p, AuthKeyByteCount);
+	} else {
+		if (!crypto_basic_hash(HashAlgo, AuthKey_p, AuthKeyByteCount,
+				       hashed_key, hashsize, true))
+			return false;
+	}
+
+	for (i = 0; i < blocksize; i++)
+		pad_block[i] = hashed_key[i] ^ 0x36;
+
+	if (!crypto_basic_hash(HashAlgo, pad_block, blocksize,
+			       Inner_p, digestsize, false))
+		return false;
+
+	for (i = 0; i < blocksize; i++)
+		pad_block[i] = hashed_key[i] ^ 0x5c;
+
+	if (!crypto_basic_hash(HashAlgo, pad_block, blocksize,
+			       Outer_p, digestsize, false))
+		return false;
+
+	return true;
+}
+
+static SABuilder_Crypto_t set_crypto_algo(struct xfrm_algo *ealg)
+{
+	if (strcmp(ealg->alg_name, "cbc(des)") == 0)
+		return SAB_CRYPTO_DES;
+	else if (strcmp(ealg->alg_name, "cbc(aes)") == 0)
+		return SAB_CRYPTO_AES;
+	else if (strcmp(ealg->alg_name, "cbc(des3_ede)") == 0)
+		return SAB_CRYPTO_3DES;
+
+	return SAB_CRYPTO_NULL;
+}
+
+static bool set_auth_algo(struct xfrm_algo_auth *aalg, SABuilder_Params_t *params,
+			  uint8_t *inner, uint8_t *outer)
+{
+	if (strcmp(aalg->alg_name, "hmac(sha1)") == 0) {
+		params->AuthAlgo = SAB_AUTH_HMAC_SHA1;
+		inner = kcalloc(SHA1_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		outer = kcalloc(SHA1_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		crypto_hmac_precompute(SAB_AUTH_HMAC_SHA1, &aalg->alg_key[0],
+					aalg->alg_key_len / 8, inner, outer);
+
+		params->AuthKey1_p = inner;
+		params->AuthKey2_p = outer;
+	} else if (strcmp(aalg->alg_name, "hmac(sha256)") == 0) {
+		params->AuthAlgo = SAB_AUTH_HMAC_SHA2_256;
+		inner = kcalloc(SHA256_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		outer = kcalloc(SHA256_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		crypto_hmac_precompute(SAB_AUTH_HMAC_SHA2_256, &aalg->alg_key[0],
+					aalg->alg_key_len / 8, inner, outer);
+		params->AuthKey1_p = inner;
+		params->AuthKey2_p = outer;
+	} else if (strcmp(aalg->alg_name, "hmac(sha384)") == 0) {
+		params->AuthAlgo = SAB_AUTH_HMAC_SHA2_384;
+		inner = kcalloc(SHA384_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		outer = kcalloc(SHA384_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		crypto_hmac_precompute(SAB_AUTH_HMAC_SHA2_384, &aalg->alg_key[0],
+					aalg->alg_key_len / 8, inner, outer);
+		params->AuthKey1_p = inner;
+		params->AuthKey2_p = outer;
+	} else if (strcmp(aalg->alg_name, "hmac(sha512)") == 0) {
+		params->AuthAlgo = SAB_AUTH_HMAC_SHA2_512;
+		inner = kcalloc(SHA512_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		outer = kcalloc(SHA512_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		crypto_hmac_precompute(SAB_AUTH_HMAC_SHA2_512, &aalg->alg_key[0],
+					aalg->alg_key_len / 8, inner, outer);
+		params->AuthKey1_p = inner;
+		params->AuthKey2_p = outer;
+	} else if (strcmp(aalg->alg_name, "hmac(md5)") == 0) {
+		params->AuthAlgo = SAB_AUTH_HMAC_MD5;
+		inner = kcalloc(MD5_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		outer = kcalloc(MD5_DIGEST_SIZE, sizeof(uint8_t), GFP_KERNEL);
+		crypto_hmac_precompute(SAB_AUTH_HMAC_MD5, &aalg->alg_key[0],
+					aalg->alg_key_len / 8, inner, outer);
+		params->AuthKey1_p = inner;
+		params->AuthKey2_p = outer;
+	} else {
+		return false;
+	}
+
+	return true;
+}
+
+u32 *mtk_ddk_tr_ipsec_build(struct mtk_xfrm_params *xfrm_params, u32 ipsec_mode)
+{
+	struct xfrm_state *xs = xfrm_params->xs;
+	SABuilder_Params_IPsec_t ipsec_params;
+	SABuilder_Status_t sa_status;
+	SABuilder_Params_t params;
+	bool set_auth_success = false;
+	unsigned int SAWords = 0;
+	uint8_t *inner, *outer;
+
+	DMABuf_Status_t dma_status;
+	DMABuf_Properties_t dma_properties = {0, 0, 0, 0};
+	DMABuf_HostAddress_t sa_host_addr;
+
+	DMABuf_Handle_t sa_handle = {0};
+
+	sa_status = SABuilder_Init_ESP(&params,
+				       &ipsec_params,
+				       be32_to_cpu(xs->id.spi),
+				       ipsec_mode,
+				       SAB_IPSEC_IPV4,
+				       xfrm_params->dir);
+
+	if (sa_status != SAB_STATUS_OK) {
+		pr_err("SABuilder_Init_ESP failed\n");
+		sa_handle.p = NULL;
+		return (u32 *) sa_handle.p;
+	}
+
+	/* Add crypto key and parameters */
+	params.CryptoAlgo = set_crypto_algo(xs->ealg);
+	params.CryptoMode = SAB_CRYPTO_MODE_CBC;
+	params.KeyByteCount = xs->ealg->alg_key_len / 8;
+	params.Key_p = xs->ealg->alg_key;
+
+	/* Add authentication key and parameters */
+	set_auth_success = set_auth_algo(xs->aalg, &params, inner, outer);
+	if (set_auth_success != true) {
+		CRYPTO_ERR("Set Auth Algo failed\n");
+		sa_handle.p = NULL;
+		return (u32 *) sa_handle.p;
+	}
+
+	ipsec_params.IPsecFlags |= (SAB_IPSEC_PROCESS_IP_HEADERS
+				    | SAB_IPSEC_EXT_PROCESSING);
+	if (ipsec_mode == SAB_IPSEC_TUNNEL) {
+		ipsec_params.SrcIPAddr_p = (uint8_t *) &xs->props.saddr.a4;
+		ipsec_params.DestIPAddr_p = (uint8_t *) &xs->id.daddr.a4;
+	}
+
+	sa_status = SABuilder_GetSizes(&params, &SAWords, NULL, NULL);
+	if (sa_status != SAB_STATUS_OK) {
+		CRYPTO_ERR("SA not created because of size errors\n");
+		sa_handle.p = NULL;
+		return (u32 *) sa_handle.p;
+	}
+
+	dma_properties.fCached = true;
+	dma_properties.Alignment = MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT;
+	dma_properties.Bank = MTK_EIP197_INLINE_BANK_TRANSFORM;
+	dma_properties.Size = SAWords * sizeof(u32);
+
+	dma_status = DMABuf_Alloc(dma_properties, &sa_host_addr, &sa_handle);
+	if (dma_status != DMABUF_STATUS_OK) {
+		CRYPTO_ERR("Allocation of SA failed\n");
+		/* goto error_exit; */
+		sa_handle.p = NULL;
+		return (u32 *) sa_handle.p;
+	}
+
+	sa_status = SABuilder_BuildSA(&params, (u32 *) sa_host_addr.p, NULL, NULL);
+	if (sa_status != SAB_STATUS_OK) {
+		CRYPTO_ERR("SA not created because of errors\n");
+		sa_handle.p = NULL;
+		return (u32 *) sa_handle.p;
+	}
+
+	kfree(inner);
+	kfree(outer);
+	return (u32 *) sa_host_addr.p;
+}
+
+int mtk_ddk_pec_init(void)
+{
+	PEC_InitBlock_t pec_init_blk = {0, 0, false};
+	PEC_Capabilities_t pec_cap;
+	PEC_Status_t pec_sta;
+	u32 i = MTK_EIP197_INLINE_NOF_TRIES;
+
+	while (i) {
+		pec_sta = PEC_Init(PEC_INTERFACE_ID, &pec_init_blk);
+		if (pec_sta == PEC_STATUS_OK) {
+			CRYPTO_INFO("PEC_INIT ok!\n");
+			break;
+		} else if (pec_sta != PEC_STATUS_OK && pec_sta != PEC_STATUS_BUSY) {
+			return pec_sta;
+		}
+
+		mdelay(MTK_EIP197_INLINE_RETRY_DELAY_MS);
+		i--;
+	}
+
+	if (!i) {
+		CRYPTO_ERR("PEC could not be initialized: %d\n", pec_sta);
+		return pec_sta;
+	}
+
+	pec_sta = PEC_Capabilities_Get(&pec_cap);
+	if (pec_sta != PEC_STATUS_OK) {
+		CRYPTO_ERR("PEC capability could not be obtained: %d\n", pec_sta);
+		return pec_sta;
+	}
+
+	CRYPTO_INFO("PEC Capabilities: %s\n", pec_cap.szTextDescription);
+
+	return 0;
+}
+
+void mtk_ddk_pec_deinit(void)
+{
+}
diff --git a/package-21.02/kernel/crypto-eip/src/ddk.mk b/package-21.02/kernel/crypto-eip/src/ddk.mk
new file mode 100644
index 0000000..7c2a3c6
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/ddk.mk
@@ -0,0 +1,8 @@
+# SPDX-Liscense-Identifier: GPL-2.0-or-later
+#
+# Copyright (C) 2023 MediaTek Inc.
+#
+# Author: Chris.Chou <chris.chou@mediatek.com>
+#         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+
+obj-$(CONFIG_RAMBUS_DDK) += ddk/
diff --git a/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/crypto-eip.h b/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/crypto-eip.h
new file mode 100644
index 0000000..24f6f91
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/crypto-eip.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ * Author: Chris.Chou <chris.chou@mediatek.com>
+ *         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+ */
+
+#ifndef _CRYPTO_EIP_H_
+#define _CRYPTO_EIP_H_
+
+#include <crypto/sha.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <net/xfrm.h>
+
+#include "crypto-eip/crypto-eip197-inline-ddk.h"
+
+struct mtk_crypto;
+
+extern struct mtk_crypto mcrypto;
+
+#define TRANSFORM_RECORD_LEN		64
+
+#define MAX_TUNNEL_NUM			10
+#define PACKET_INBOUND			1
+#define PACKET_OUTBOUND			2
+
+#define HASH_CACHE_SIZE			SHA512_BLOCK_SIZE
+
+#define EIP197_FORCE_CLK_ON2		(0xfffd8)
+#define EIP197_FORCE_CLK_ON		(0xfffe8)
+#define EIP197_AUTO_LOOKUP_1		(0xfffffffc)
+#define EIP197_AUTO_LOOKUP_2		(0xffffffff)
+
+struct mtk_crypto {
+	struct mtk_eth *eth;
+	void __iomem *crypto_base;
+	void __iomem *eth_base;
+};
+
+struct mtk_xfrm_params {
+	struct xfrm_state *xs;
+	struct list_head node;
+	struct cdrt_entry *cdrt;
+
+	u32 *p_tr;			/* pointer to transform record */
+	u32 dir;			/* SABuilder_Direction_t */
+};
+
+void crypto_eth_write(u32 reg, u32 val);
+
+/* xfrm callback functions */
+int mtk_xfrm_offload_state_add(struct xfrm_state *xs);
+void mtk_xfrm_offload_state_delete(struct xfrm_state *xs);
+void mtk_xfrm_offload_state_free(struct xfrm_state *xs);
+void mtk_xfrm_offload_state_tear_down(void);
+int mtk_xfrm_offload_policy_add(struct xfrm_policy *xp);
+bool mtk_xfrm_offload_ok(struct sk_buff *skb, struct xfrm_state *xs);
+#endif /* _CRYPTO_EIP_H_ */
diff --git a/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/crypto-eip197-inline-ddk.h b/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/crypto-eip197-inline-ddk.h
new file mode 100644
index 0000000..00fb1a8
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/crypto-eip197-inline-ddk.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ * Author: Chris.Chou <chris.chou@mediatek.com>
+ *         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+ */
+
+#ifndef _CRYPTO_EIP197_INLINE_DDK_H_
+#define _CRYPTO_EIP197_INLINE_DDK_H_
+
+#include <crypto-eip/ddk/basic_defs.h>
+#include <crypto-eip/ddk/configs/cs_ddk197.h>
+#include <crypto-eip/ddk/configs/cs_driver_ext.h>
+#include <crypto-eip/ddk/configs/cs_adapter.h>
+#include <crypto-eip/ddk/libc/clib.h>
+#include <crypto-eip/ddk/kit/builder/sa/sa_builder.h>
+#include <crypto-eip/ddk/kit/builder/sa/sa_builder_ipsec.h>
+#include <crypto-eip/ddk/kit/builder/sa/sa_builder_basic.h>
+#include <crypto-eip/ddk/kit/builder/sa/sa_builder_params_basic.h>
+#include <crypto-eip/ddk/kit/builder/token/token_builder.h>
+#include <crypto-eip/ddk/kit/iotoken/iotoken.h>
+#include <crypto-eip/ddk/kit/iotoken/iotoken_ext.h>
+#include <crypto-eip/ddk/slad/api_dmabuf.h>
+#include <crypto-eip/ddk/slad/api_pcl.h>
+#include <crypto-eip/ddk/slad/api_pcl_dtl.h>
+#include <crypto-eip/ddk/slad/api_pec.h>
+#include <crypto-eip/ddk/log/log.h>
+
+#ifdef DDK_EIP197_FW33_FEATURES
+#define MTK_EIP197_INLINE_STRIP_PADDING
+#endif
+
+#define CRYPTO_IOTOKEN_EXT
+
+#define MTK_EIP197_INLINE_BANK_PACKET			0
+
+#define MTK_EIP197_INLINE_BANK_TRANSFORM		1
+#define MTK_EIP197_INLINE_BANK_TOKEN			0
+
+/* Delay in milliseconds between tries to receive the packet */
+#define MTK_EIP197_INLINE_RETRY_DELAY_MS		2
+#define MTK_EIP197_PKT_GET_TIMEOUT_MS			2
+
+/* Maximum number of tries to receive the packet. */
+#define MTK_EIP197_INLINE_NOF_TRIES			10
+
+#define MTK_EIP197_INLINE_DMA_ALIGNMENT_BYTE_COUNT	16
+
+/* PEC Configuration */
+#ifdef DDK_PEC_IF_ID
+#define PEC_INTERFACE_ID				DDK_PEC_IF_ID
+#else
+#define PEC_INTERFACE_ID				0
+#endif
+#define PEC_REDIRECT_INTERFACE				7
+#define PEC_INLINE_INTERFACE				15
+
+#define PCL_INTERFACE_ID				0
+#endif /* _CRYPTO_EIP197_INLINE_DDK_H_ */
diff --git a/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/ddk-wrapper.h b/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/ddk-wrapper.h
new file mode 100644
index 0000000..db2b84f
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/ddk-wrapper.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ * Author: Chris.Chou <chris.chou@mediatek.com>
+ *         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+ */
+
+#ifndef _CRYPTO_EIP_DDK_WRAPPER_H_
+#define _CRYPTO_EIP_DDK_WRAPPER_H_
+
+#include "crypto-eip.h"
+
+u32 *mtk_ddk_tr_ipsec_build(struct mtk_xfrm_params *xfrm_params, u32 ipsec_mod);
+
+int mtk_ddk_pec_init(void);
+void mtk_ddk_pec_deinit(void);
+#endif /* _CRYPTO_EIP_DDK_WRAPPER_H_ */
diff --git a/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/internal.h b/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/internal.h
new file mode 100644
index 0000000..e843841
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/inc/crypto-eip/internal.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ * Author: Chris.Chou <chris.chou@mediatek.com>
+ *         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+ */
+
+#ifndef _CRYPTO_EIP_INTERNAL_H_
+#define _CRYPTO_EIP_INTERNAL_H_
+
+#include <linux/device.h>
+
+extern struct device *crypto_dev;
+
+#define CRYPTO_DBG(fmt, ...)		dev_dbg(crypto_dev, fmt, ##__VA_ARGS__)
+#define CRYPTO_INFO(fmt, ...)		dev_info(crypto_dev, fmt, ##__VA_ARGS__)
+#define CRYPTO_NOTICE(fmt, ...)		dev_notice(crypto_dev, fmt, ##__VA_ARGS__)
+#define CRYPTO_WARN(fmt, ...)		dev_warn(crypto_dev, fmt, ##__VA_ARGS__)
+#define CRYPTO_ERR(fmt, ...)		dev_err(crypto_dev, fmt, ##__VA_ARGS__)
+
+#define setbits(addr, set)		writel(readl(addr) | (set), (addr))
+#define clrbits(addr, clr)		writel(readl(addr) & ~(clr), (addr))
+#define clrsetbits(addr, clr, set)	writel((readl(addr) & ~(clr)) | (set), (addr))
+#endif /* _CRYPTO_EIP_INTERNAL_H_ */
diff --git a/package-21.02/kernel/crypto-eip/src/init.c b/package-21.02/kernel/crypto-eip/src/init.c
new file mode 100644
index 0000000..cc53a39
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/init.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ * Author: Chris.Chou <chris.chou@mediatek.com>
+ *         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+
+#include <mtk_eth_soc.h>
+#include <mtk_hnat/hnat.h>
+
+#include <crypto-eip/ddk/configs/cs_hwpal_ext.h>
+
+#include "crypto-eip/crypto-eip.h"
+#include "crypto-eip/ddk-wrapper.h"
+#include "crypto-eip/internal.h"
+
+#define DRIVER_AUTHOR	"Ren-Ting Wang <ren-ting.wang@mediatek.com, " \
+			"Chris.Chou <chris.chou@mediatek.com"
+
+struct mtk_crypto mcrypto;
+struct device *crypto_dev;
+
+inline void crypto_eth_write(u32 reg, u32 val)
+{
+	writel(val, mcrypto.eth_base + reg);
+}
+
+static inline void crypto_eip_write(u32 reg, u32 val)
+{
+	writel(val, mcrypto.crypto_base + reg);
+}
+
+static inline void crypto_eip_set(u32 reg, u32 mask)
+{
+	setbits(mcrypto.crypto_base + reg, mask);
+}
+
+static inline void crypto_eip_clr(u32 reg, u32 mask)
+{
+	clrbits(mcrypto.crypto_base + reg, mask);
+}
+
+static inline void crypto_eip_rmw(u32 reg, u32 mask, u32 val)
+{
+	clrsetbits(mcrypto.crypto_base + reg, mask, val);
+}
+
+static inline u32 crypto_eip_read(u32 reg)
+{
+	return readl(mcrypto.crypto_base + reg);
+}
+
+static bool mtk_crypto_eip_offloadable(struct sk_buff *skb)
+{
+	/* TODO: check is esp */
+	return true;
+}
+
+static const struct xfrmdev_ops mtk_xfrmdev_ops = {
+	.xdo_dev_state_add = mtk_xfrm_offload_state_add,
+	.xdo_dev_state_delete = mtk_xfrm_offload_state_delete,
+	.xdo_dev_state_free = mtk_xfrm_offload_state_free,
+	.xdo_dev_offload_ok = mtk_xfrm_offload_ok,
+
+	/* Not support at v5.4*/
+	.xdo_dev_policy_add = mtk_xfrm_offload_policy_add,
+};
+
+static void mtk_crypto_xfrm_offload_deinit(struct mtk_eth *eth)
+{
+	int i;
+
+	mtk_crypto_offloadable = NULL;
+
+	for (i = 0; i < MTK_MAC_COUNT; i++) {
+		eth->netdev[i]->xfrmdev_ops = NULL;
+		eth->netdev[i]->features &= (~NETIF_F_HW_ESP);
+		eth->netdev[i]->hw_enc_features &= (~NETIF_F_HW_ESP);
+		rtnl_lock();
+		netdev_change_features(eth->netdev[i]);
+		rtnl_unlock();
+	}
+}
+
+static void mtk_crypto_xfrm_offload_init(struct mtk_eth *eth)
+{
+	int i;
+
+	for (i = 0; i < MTK_MAC_COUNT; i++) {
+		eth->netdev[i]->xfrmdev_ops = &mtk_xfrmdev_ops;
+		eth->netdev[i]->features |= NETIF_F_HW_ESP;
+		eth->netdev[i]->hw_enc_features |= NETIF_F_HW_ESP;
+		rtnl_lock();
+		netdev_change_features(eth->netdev[i]);
+		rtnl_unlock();
+	}
+
+	mtk_crypto_offloadable = mtk_crypto_eip_offloadable;
+}
+
+static int __init mtk_crypto_eth_dts_init(struct platform_device *pdev)
+{
+	struct platform_device *eth_pdev;
+	struct device_node *crypto_node;
+	struct device_node *eth_node;
+	struct resource res;
+	int ret = 0;
+
+	crypto_node = pdev->dev.of_node;
+
+	eth_node = of_parse_phandle(crypto_node, "eth", 0);
+	if (!eth_node)
+		return -ENODEV;
+
+	eth_pdev = of_find_device_by_node(eth_node);
+	if (!eth_pdev) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (!eth_pdev->dev.driver) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (of_address_to_resource(eth_node, 0, &res)) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	mcrypto.eth_base = devm_ioremap(&pdev->dev,
+					res.start, resource_size(&res));
+	if (!mcrypto.eth_base) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mcrypto.eth = platform_get_drvdata(eth_pdev);
+
+out:
+	of_node_put(eth_node);
+
+	return ret;
+}
+
+static int __init mtk_crypto_eip_dts_init(void)
+{
+	struct platform_device *crypto_pdev;
+	struct device_node *crypto_node;
+	struct resource res;
+	int ret;
+
+	crypto_node = of_find_compatible_node(NULL, NULL, HWPAL_PLATFORM_DEVICE_NAME);
+	if (!crypto_node)
+		return -ENODEV;
+
+	crypto_pdev = of_find_device_by_node(crypto_node);
+	if (!crypto_pdev) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* check crypto platform device is ready */
+	if (!crypto_pdev->dev.driver) {
+		ret = -EFAULT;
+		goto out;
+	}
+
+	if (of_address_to_resource(crypto_node, 0, &res)) {
+		ret = -ENXIO;
+		goto out;
+	}
+
+	mcrypto.crypto_base = devm_ioremap(&crypto_pdev->dev,
+					   res.start, resource_size(&res));
+	if (!mcrypto.crypto_base) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ret = mtk_crypto_eth_dts_init(crypto_pdev);
+	if (ret)
+		goto out;
+
+	crypto_dev = &crypto_pdev->dev;
+
+out:
+	of_node_put(crypto_node);
+
+	return ret;
+}
+
+static int __init mtk_crypto_eip_hw_init(void)
+{
+	crypto_eip_write(EIP197_FORCE_CLK_ON, 0xffffffff);
+
+	crypto_eip_write(EIP197_FORCE_CLK_ON2, 0xffffffff);
+
+	/* TODO: adjust AXI burst? */
+
+	mtk_ddk_pec_init();
+
+	return 0;
+}
+
+static void __exit mtk_crypto_eip_hw_deinit(void)
+{
+	mtk_ddk_pec_deinit();
+
+	crypto_eip_write(EIP197_FORCE_CLK_ON, 0);
+
+	crypto_eip_write(EIP197_FORCE_CLK_ON2, 0);
+}
+
+static int __init mtk_crypto_eip_init(void)
+{
+	int ret;
+
+	ret = mtk_crypto_eip_dts_init();
+	if (ret) {
+		CRYPTO_ERR("crypto-eip dts init failed: %d\n", ret);
+		return ret;
+	}
+
+	ret = mtk_crypto_eip_hw_init();
+	if (ret) {
+		CRYPTO_ERR("crypto-eip hw init failed: %d\n", ret);
+		return ret;
+	}
+
+	mtk_crypto_xfrm_offload_init(mcrypto.eth);
+
+	CRYPTO_INFO("crypto-eip init done\n");
+
+	return ret;
+}
+
+static void __exit mtk_crypto_eip_exit(void)
+{
+	/* TODO: deactivate all tunnel */
+
+	mtk_crypto_xfrm_offload_deinit(mcrypto.eth);
+
+	mtk_crypto_eip_hw_deinit();
+}
+
+module_init(mtk_crypto_eip_init);
+module_exit(mtk_crypto_eip_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MediaTek Crypto EIP Control Driver");
+MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/package-21.02/kernel/crypto-eip/src/xfrm-offload.c b/package-21.02/kernel/crypto-eip/src/xfrm-offload.c
new file mode 100644
index 0000000..bd79147
--- /dev/null
+++ b/package-21.02/kernel/crypto-eip/src/xfrm-offload.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (C) 2023 MediaTek Inc.
+ *
+ * Author: Chris.Chou <chris.chou@mediatek.com>
+ *         Ren-Ting Wang <ren-ting.wang@mediatek.com>
+ */
+
+#include <linux/bitops.h>
+
+#include <mtk_eth_soc.h>
+#include <mtk_hnat/hnat.h>
+#include <mtk_hnat/nf_hnat_mtk.h>
+
+#include <pce/cdrt.h>
+#include <pce/cls.h>
+#include <pce/netsys.h>
+
+#include <crypto-eip/ddk/configs/cs_hwpal_ext.h>
+#include <crypto-eip/ddk/kit/iotoken/iotoken.h>
+#include <crypto-eip/ddk/kit/iotoken/iotoken_ext.h>
+
+#include "crypto-eip/crypto-eip.h"
+#include "crypto-eip/ddk-wrapper.h"
+#include "crypto-eip/internal.h"
+
+static LIST_HEAD(xfrm_params_head);
+
+static void mtk_xfrm_offload_cdrt_tear_down(struct mtk_xfrm_params *xfrm_params)
+{
+	memset(&xfrm_params->cdrt->desc, 0, sizeof(struct cdrt_desc));
+
+	mtk_pce_cdrt_entry_write(xfrm_params->cdrt);
+}
+
+static int mtk_xfrm_offload_cdrt_setup(struct mtk_xfrm_params *xfrm_params)
+{
+	struct cdrt_desc *cdesc = &xfrm_params->cdrt->desc;
+
+	cdesc->desc1.common.type = 3;
+	cdesc->desc1.token_len = 48;
+	cdesc->desc1.p_tr[0] = __pa(xfrm_params->p_tr) | 2;
+
+	cdesc->desc2.hw_srv = 2;
+	cdesc->desc2.allow_pad = 1;
+	cdesc->desc2.strip_pad = 1;
+
+	return mtk_pce_cdrt_entry_write(xfrm_params->cdrt);
+}
+
+static int mtk_xfrm_offload_cls_entry_setup(struct mtk_xfrm_params *xfrm_params)
+{
+	struct cls_entry esp_cls_entry = {
+		.entry = xfrm_params->cdrt->idx + 10, /* TODO: need update */
+		.cdesc = {
+			.fport = 0x3,
+			.tport_idx = 0x2,
+			.cdrt_idx = xfrm_params->cdrt->idx,
+
+			.l4_udp_hdr_nez_m = 0x1,
+			.l4_udp_hdr_nez = 0x1,
+			.l4_hdr_usr_data_m = 0xffffffff,
+			.l4_hdr_usr_data = be32_to_cpu(xfrm_params->xs->id.spi),
+			.l4_valid_m = 0x3,
+			.l4_valid = 0x3,
+			.l4_dport_m = 0x0,
+			.l4_dport = 0x0,
+			.tag_m = 0x3,
+			.tag = 0x1,
+			.dip_match_m = 0x0,
+			.dip_match = 0x0,
+			.l4_type_m = 0xff,
+			.l4_type = 0x32,
+		},
+	};
+
+	return mtk_pce_cls_entry_register(&esp_cls_entry);
+}
+
+static void mtk_xfrm_offload_context_tear_down(struct mtk_xfrm_params *xfrm_params)
+{
+	mtk_xfrm_offload_cdrt_tear_down(xfrm_params);
+
+	/* TODO: free context */
+	devm_kfree(crypto_dev, xfrm_params->p_tr);
+
+	/* TODO: transform record tear down */
+}
+
+static int mtk_xfrm_offload_context_setup(struct mtk_xfrm_params *xfrm_params)
+{
+	u32 *tr;
+	int ret;
+
+	xfrm_params->p_tr = devm_kcalloc(crypto_dev, sizeof(u32),
+					 TRANSFORM_RECORD_LEN, GFP_KERNEL);
+	if (unlikely(!xfrm_params->p_tr))
+		return -ENOMEM;
+
+	switch (xfrm_params->xs->outer_mode.encap) {
+	case XFRM_MODE_TUNNEL:
+		tr = mtk_ddk_tr_ipsec_build(xfrm_params, SAB_IPSEC_TUNNEL);
+		break;
+	case XFRM_MODE_TRANSPORT:
+		tr = mtk_ddk_tr_ipsec_build(xfrm_params, SAB_IPSEC_TRANSPORT);
+		break;
+	default:
+		ret = -ENOMEM;
+		goto err_out;
+	}
+
+	if (!tr) {
+		ret = -EINVAL;
+		goto err_out;
+	}
+
+	memcpy(xfrm_params->p_tr, tr, sizeof(u32) * TRANSFORM_RECORD_LEN);
+
+	/* TODO: free tr */
+
+	return mtk_xfrm_offload_cdrt_setup(xfrm_params);
+
+err_out:
+	devm_kfree(crypto_dev, xfrm_params->p_tr);
+
+	return ret;
+}
+
+static int mtk_xfrm_offload_state_add_outbound(struct xfrm_state *xs,
+					       struct mtk_xfrm_params *xfrm_params)
+{
+	int ret;
+
+	xfrm_params->cdrt = mtk_pce_cdrt_entry_alloc(CDRT_ENCRYPT);
+	if (IS_ERR(xfrm_params->cdrt))
+		return PTR_ERR(xfrm_params->cdrt);
+
+	xfrm_params->dir = SAB_DIRECTION_OUTBOUND;
+
+	ret = mtk_xfrm_offload_context_setup(xfrm_params);
+	if (ret)
+		goto free_cdrt;
+
+	return ret;
+
+free_cdrt:
+	mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
+
+	return ret;
+}
+
+static int mtk_xfrm_offload_state_add_inbound(struct xfrm_state *xs,
+					      struct mtk_xfrm_params *xfrm_params)
+{
+	int ret;
+
+	xfrm_params->cdrt = mtk_pce_cdrt_entry_alloc(CDRT_DECRYPT);
+	if (IS_ERR(xfrm_params->cdrt))
+		return PTR_ERR(xfrm_params->cdrt);
+
+	xfrm_params->dir = SAB_DIRECTION_INBOUND;
+
+	ret = mtk_xfrm_offload_context_setup(xfrm_params);
+	if (ret)
+		goto free_cdrt;
+
+	ret = mtk_xfrm_offload_cls_entry_setup(xfrm_params);
+	if (ret)
+		goto tear_down_context;
+
+	return ret;
+
+tear_down_context:
+	mtk_xfrm_offload_context_tear_down(xfrm_params);
+
+free_cdrt:
+	mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
+
+	return ret;
+}
+
+int mtk_xfrm_offload_state_add(struct xfrm_state *xs)
+{
+	struct mtk_xfrm_params *xfrm_params;
+	int ret = 0;
+
+	/* TODO: maybe support IPv6 in the future? */
+	if (xs->props.family != AF_INET) {
+		CRYPTO_NOTICE("Only IPv4 xfrm states may be offloaded\n");
+		return -EINVAL;
+	}
+
+	/* only support ESP right now */
+	if (xs->id.proto != IPPROTO_ESP) {
+		CRYPTO_NOTICE("Unsupported protocol 0x%04x\n", xs->id.proto);
+		return -EINVAL;
+	}
+
+	/* only support tunnel mode or transport mode */
+	if (!(xs->outer_mode.encap == XFRM_MODE_TUNNEL
+	    || xs->outer_mode.encap == XFRM_MODE_TRANSPORT))
+		return -EINVAL;
+
+	xfrm_params = devm_kzalloc(crypto_dev,
+				   sizeof(struct mtk_xfrm_params),
+				   GFP_KERNEL);
+	if (!xfrm_params)
+		return -ENOMEM;
+
+	xfrm_params->xs = xs;
+	INIT_LIST_HEAD(&xfrm_params->node);
+
+	if (xs->xso.flags & XFRM_OFFLOAD_INBOUND)
+		/* rx path */
+		ret = mtk_xfrm_offload_state_add_inbound(xs, xfrm_params);
+	else
+		/* tx path */
+		ret = mtk_xfrm_offload_state_add_outbound(xs, xfrm_params);
+
+	if (ret) {
+		devm_kfree(crypto_dev, xfrm_params);
+		goto out;
+	}
+
+	xs->xso.offload_handle = (unsigned long)xfrm_params;
+	list_add_tail(&xfrm_params->node, &xfrm_params_head);
+out:
+	return ret;
+}
+
+void mtk_xfrm_offload_state_delete(struct xfrm_state *xs)
+{
+}
+
+void mtk_xfrm_offload_state_free(struct xfrm_state *xs)
+{
+	struct mtk_xfrm_params *xfrm_params;
+
+	if (!xs->xso.offload_handle)
+		return;
+
+	xfrm_params = (struct mtk_xfrm_params *)xs->xso.offload_handle;
+
+	list_del(&xfrm_params->node);
+
+	if (xs->xso.flags & XFRM_OFFLOAD_INBOUND)
+		mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
+
+	mtk_xfrm_offload_context_tear_down(xfrm_params);
+
+	mtk_pce_cdrt_entry_free(xfrm_params->cdrt);
+
+	devm_kfree(crypto_dev, xfrm_params);
+}
+
+void mtk_xfrm_offload_state_tear_down(void)
+{
+	struct mtk_xfrm_params *xfrm_params, *tmp;
+
+	list_for_each_entry_safe(xfrm_params, tmp, &xfrm_params_head, node)
+		mtk_xfrm_offload_state_free(xfrm_params->xs);
+}
+
+int mtk_xfrm_offload_policy_add(struct xfrm_policy *xp)
+{
+	return 0;
+}
+
+bool mtk_xfrm_offload_ok(struct sk_buff *skb,
+			 struct xfrm_state *xs)
+{
+	struct mtk_xfrm_params *xfrm_params;
+
+	xfrm_params = (struct mtk_xfrm_params *)xs->xso.offload_handle;
+	skb_hnat_cdrt(skb) = xfrm_params->cdrt->idx;
+
+	return false;
+}