meta-nuvoton-npcm8xx: import at 62f317ab

Copy the contents of meta-nuvoton from Nuvoton's fork of OpenBMC[0] into
meta-gbmc-staging as a folder named meta-nuvoton-npcm8xx. This will
allow us to import their code without affecting other users of the
meta-nuvoton layer.

Imported from branch `npcm-master` at revision 62f317ab.

To build with support for npcm8xx (Arbel) in your machine bblayers.conf,
add meta-gbmc-staging/meta-nuvoton-npcm8xx and remove meta-nuvoton.

[0] https://github.com/Nuvoton-Israel/openbmc

Tested:
With internal CL 106631, built and booted on NPCM845 EVB

Google-Bug-Id: 223452756
Signed-off-by: Benjamin Fair <benjaminfair@google.com>
Change-Id: If9622e4ea79f3aaf8f4f09e7c53b78b8d80ef09a
diff --git a/meta-nuvoton-npcm8xx/COPYING.MIT b/meta-nuvoton-npcm8xx/COPYING.MIT
new file mode 100644
index 0000000..89de354
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/COPYING.MIT
@@ -0,0 +1,17 @@
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/meta-nuvoton-npcm8xx/COPYING.apache-2.0 b/meta-nuvoton-npcm8xx/COPYING.apache-2.0
new file mode 100644
index 0000000..67db858
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/COPYING.apache-2.0
@@ -0,0 +1,175 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
diff --git a/meta-nuvoton-npcm8xx/LICENSE b/meta-nuvoton-npcm8xx/LICENSE
new file mode 100644
index 0000000..22a3b52
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/LICENSE
@@ -0,0 +1,12 @@
+Different components of meta-nuvoton are under different licenses (a mix
+of MIT and Apache-2.0). Please see:
+
+COPYING.Apache-2.0
+COPYING.MIT (MIT)
+
+All metadata is MIT licensed unless otherwise stated. Source code
+included in tree for individual recipes is under the LICENSE stated in
+the associated recipe (.bb file) unless otherwise stated.
+
+License information for any other files is either explicitly stated
+or defaults to Apache-2.0.
diff --git a/meta-nuvoton-npcm8xx/OWNERS b/meta-nuvoton-npcm8xx/OWNERS
new file mode 100644
index 0000000..929031c
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/OWNERS
@@ -0,0 +1,2 @@
+owners:
+- benjaminfair@google.com
diff --git a/meta-nuvoton-npcm8xx/README.md b/meta-nuvoton-npcm8xx/README.md
new file mode 100644
index 0000000..a93a03c
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/README.md
@@ -0,0 +1,8 @@
+Nuvoton NPCM7XX
+================
+
+This is the Nuvoton NPCM7XX Board Support Package (BSP) layer.
+The NPCM7XX is an ARM based SoC with external DDR RAM and 
+supports a large set of peripherals made by Nuvoton. 
+More information about the NPCM7XX can be found
+[here](http://www.nuvoton.com/hq/products/cloud-computing/ibmc/?__locale=en).
diff --git a/meta-nuvoton-npcm8xx/classes/fitimage_nuvoton_npcm8xx.bbclass b/meta-nuvoton-npcm8xx/classes/fitimage_nuvoton_npcm8xx.bbclass
new file mode 100644
index 0000000..1b7c77e
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/classes/fitimage_nuvoton_npcm8xx.bbclass
@@ -0,0 +1,206 @@
+#
+# Assemble fitImage
+#
+# $1 ... .its filename
+# $2 ... fitImage name
+# $3 ... include ramdisk
+fitimage_assemble_npcm8xx() {
+	kernelcount=1
+	dtbcount=""
+	DTBS=""
+	ramdiskcount=${3}
+	setupcount=""
+	bootscr_id=""
+	rm -f ${1} arch/${ARCH}/boot/${2}
+	final_offset=600
+
+	fitimage_emit_fit_header ${1}
+
+	#
+	# Step 1: Prepare a image section.
+	#
+	fitimage_emit_section_maint ${1} imagestart
+
+	#
+	# Step 2: Prepare a DTB image section
+	#
+
+	if [ -n "${KERNEL_DEVICETREE}" ]; then
+		dtbcount=1
+		for DTB in ${KERNEL_DEVICETREE}; do
+			if echo ${DTB} | grep -q '/dts/'; then
+				bbwarn "${DTB} contains the full path to the the dts file, but only the dtb name should be used."
+				DTB=`basename ${DTB} | sed 's,\.dts$,.dtb,g'`
+			fi
+
+			# Skip ${DTB} if it's also provided in ${EXTERNAL_KERNEL_DEVICETREE}
+			if [ -n "${EXTERNAL_KERNEL_DEVICETREE}" ] && [ -s ${EXTERNAL_KERNEL_DEVICETREE}/${DTB} ]; then
+				continue
+			fi
+
+			DTB_PATH="arch/${ARCH}/boot/dts/${DTB}"
+			if [ ! -e "${DTB_PATH}" ]; then
+				DTB_PATH="arch/${ARCH}/boot/${DTB}"
+			fi
+
+			DTB=$(echo "${DTB}" | tr '/' '_')
+			DTBS="${DTBS} ${DTB}"
+			fitimage_emit_section_dtb ${1} ${DTB} ${DTB_PATH}
+		done
+	fi
+
+	if [ -n "${EXTERNAL_KERNEL_DEVICETREE}" ]; then
+		dtbcount=1
+		for DTB in $(find "${EXTERNAL_KERNEL_DEVICETREE}" \( -name '*.dtb' -o -name '*.dtbo' \) -printf '%P\n' | sort); do
+			DTB=$(echo "${DTB}" | tr '/' '_')
+			DTBS="${DTBS} ${DTB}"
+			fitimage_emit_section_dtb ${1} ${DTB} "${EXTERNAL_KERNEL_DEVICETREE}/${DTB}"
+		done
+	fi
+
+	#
+	# Step 3: Prepare a kernel image section.
+	#
+
+	uboot_prep_kimage
+
+	if [ "${INITRAMFS_IMAGE_BUNDLE}" = "1" ]; then
+		initramfs_bundle_path="arch/"${UBOOT_ARCH}"/boot/"${KERNEL_IMAGETYPE_REPLACEMENT}".initramfs"
+		if [ -e "${initramfs_bundle_path}" ]; then
+
+			#
+			# Include the kernel/rootfs bundle.
+			#
+
+			fitimage_emit_section_kernel ${1} "${kernelcount}" "${initramfs_bundle_path}" "${linux_comp}"
+		else
+			bbwarn "${initramfs_bundle_path} not found."
+		fi
+	else
+		fitimage_emit_section_kernel ${1} "${kernelcount}" linux.bin "${linux_comp}"
+	fi
+
+	#
+	# Step 4: Prepare a u-boot script section
+	#
+
+	if [ -n "${UBOOT_ENV}" ] && [ -d "${STAGING_DIR_HOST}/boot" ]; then
+		if [ -e "${STAGING_DIR_HOST}/boot/${UBOOT_ENV_BINARY}" ]; then
+			cp ${STAGING_DIR_HOST}/boot/${UBOOT_ENV_BINARY} ${B}
+			bootscr_id="${UBOOT_ENV_BINARY}"
+			fitimage_emit_section_boot_script ${1} "${bootscr_id}" ${UBOOT_ENV_BINARY}
+		else
+			bbwarn "${STAGING_DIR_HOST}/boot/${UBOOT_ENV_BINARY} not found."
+		fi
+	fi
+	#
+	# Step 5: Prepare a setup section. (For x86)
+	#
+	if [ -e arch/${ARCH}/boot/setup.bin ]; then
+		setupcount=1
+		fitimage_emit_section_setup ${1} "${setupcount}" arch/${ARCH}/boot/setup.bin
+	fi
+
+	#
+	# Step 6: Prepare a ramdisk section.
+	#
+	if [ "x${ramdiskcount}" = "x1" ] && [ "${INITRAMFS_IMAGE_BUNDLE}" != "1" ]; then
+		# Find and use the first initramfs image archive type we find
+		for img in cpio.lz4 cpio.lzo cpio.lzma cpio.xz cpio.gz ext2.gz cpio; do
+			initramfs_path="${DEPLOY_DIR_IMAGE}/${INITRAMFS_IMAGE_NAME}.${img}"
+			echo "Using $initramfs_path"
+			if [ -e "${initramfs_path}" ]; then
+				fitimage_emit_section_ramdisk ${1} "${ramdiskcount}" "${initramfs_path}"
+				break
+			fi
+		done
+	fi
+
+	fitimage_emit_section_maint ${1} sectend
+
+	# Force the first Kernel and DTB in the default config
+	kernelcount=1
+	if [ -n "${dtbcount}" ]; then
+		dtbcount=1
+	fi
+
+	#
+	# Step 7: Prepare a configurations section
+	#
+	fitimage_emit_section_maint ${1} confstart
+
+	# kernel-fitimage.bbclass currently only supports a single kernel (no less or
+	# more) to be added to the FIT image along with 0 or more device trees and
+	# 0 or 1 ramdisk.
+        # It is also possible to include an initramfs bundle (kernel and rootfs in one binary)
+        # When the initramfs bundle is used ramdisk is disabled.
+	# If a device tree is to be part of the FIT image, then select
+	# the default configuration to be used is based on the dtbcount. If there is
+	# no dtb present than select the default configuation to be based on
+	# the kernelcount.
+	if [ -n "${DTBS}" ]; then
+		i=1
+		for DTB in ${DTBS}; do
+			dtb_ext=${DTB##*.}
+			if [ "${dtb_ext}" = "dtbo" ]; then
+				fitimage_emit_section_config ${1} "" "${DTB}" "" "${bootscr_id}" "" "`expr ${i} = ${dtbcount}`"
+			else
+				fitimage_emit_section_config ${1} "${kernelcount}" "${DTB}" "${ramdiskcount}" "${bootscr_id}" "${setupcount}" "`expr ${i} = ${dtbcount}`"
+			fi
+			i=`expr ${i} + 1`
+		done
+	else
+		defaultconfigcount=1
+		fitimage_emit_section_config ${1} "${kernelcount}" "" "${ramdiskcount}" "${bootscr_id}"  "${setupcount}" "${defaultconfigcount}"
+	fi
+
+	fitimage_emit_section_maint ${1} sectend
+
+	fitimage_emit_section_maint ${1} fitend
+
+	#
+	# Step 8: Assemble the image
+	#
+	${UBOOT_MKIMAGE} -E -p ${final_offset} \
+		${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \
+		-f ${1} \
+		arch/${ARCH}/boot/${2}
+
+	#
+	# Step 9: Sign the image and add public key to U-Boot dtb
+	#
+	if [ "x${UBOOT_SIGN_ENABLE}" = "x1" ] ; then
+		add_key_to_u_boot=""
+		if [ -n "${UBOOT_DTB_BINARY}" ]; then
+			# The u-boot.dtb is a symlink to UBOOT_DTB_IMAGE, so we need copy
+			# both of them, and don't dereference the symlink.
+			cp -P ${STAGING_DATADIR}/u-boot*.dtb ${B}
+			add_key_to_u_boot="-K ${B}/${UBOOT_DTB_BINARY}"
+		fi
+		${UBOOT_MKIMAGE_SIGN} -E -p ${final_offset} \
+			${@'-D "${UBOOT_MKIMAGE_DTCOPTS}"' if len('${UBOOT_MKIMAGE_DTCOPTS}') else ''} \
+			-F -k "${UBOOT_SIGN_KEYDIR}" \
+			$add_key_to_u_boot \
+			-r arch/${ARCH}/boot/${2} \
+			${UBOOT_MKIMAGE_SIGN_ARGS}
+	fi
+}
+
+do_assemble_fitimage:append() {
+	if echo ${KERNEL_IMAGETYPES} | grep -wq "fitImage"; then
+		cd ${B}
+		fitimage_assemble_npcm8xx fit-image.its fitImage
+	fi
+}
+
+do_assemble_fitimage_initramfs:append() {
+	if echo ${KERNEL_IMAGETYPES} | grep -wq "fitImage" && \
+		test -n "${INITRAMFS_IMAGE}" ; then
+		cd ${B}
+		if [ "${INITRAMFS_IMAGE_BUNDLE}" = "1" ]; then
+			fitimage_assemble_npcm8xx fit-image-${INITRAMFS_IMAGE}.its fitImage ""
+		else
+			fitimage_assemble_npcm8xx fit-image-${INITRAMFS_IMAGE}.its fitImage-${INITRAMFS_IMAGE} 1
+		fi
+	fi
+}
diff --git a/meta-nuvoton-npcm8xx/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass b/meta-nuvoton-npcm8xx/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass
new file mode 100644
index 0000000..89b8e52
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/classes/image_types_phosphor_nuvoton_npcm8xx.bbclass
@@ -0,0 +1,245 @@
+UBOOT_BINARY := "u-boot.${UBOOT_SUFFIX}"
+BOOTBLOCK = "BootBlockAndHeader.bin"
+ATF_BINARY := "bl31AndHeader.bin"
+OPTEE_BINARY := "teeAndHeader.bin"
+KMT_BINARY = "KmtAndHeader.bin"
+TIPFWL0_BINARY = "TipFwAndHeader_L0.bin"
+TIPFWL1_BINARY = "TipFwAndHeader_L1.bin"
+KMT_TIPFWL0_BINARY = "Kmt_TipFwL0.bin"
+KMT_TIPFWL0L1_BINARY = "Kmt_TipFwL0L1.bin"
+KMT_TIPFW_BB_BINARY = "Kmt_TipFw_BootBlock.bin"
+KMT_TIPFW_BB_BL31_BINARY = "Kmt_TipFw_BootBlock_BL31.bin"
+KMT_TIPFW_BB_BL31_TEE_BINARY = "Kmt_TipFw_BootBlock_BL31_Tee.bin"
+KMT_TIPFW_BB_BL31_TEE_UBOOT_BINARY = "Kmt_TipFw_BootBlock_BL31_Tee_uboot.bin"
+KMT_TIPFW_BB_UBOOT_BINARY = "u-boot.bin.merged"
+FULL_SUFFIX = "full"
+MERGED_SUFFIX = "merged"
+UBOOT_SUFFIX:append = ".${MERGED_SUFFIX}"
+
+IGPS_DIR = "${STAGING_DIR_NATIVE}/${datadir}/npcm8xx-igps"
+inherit logging
+
+# Prepare the Bootblock and U-Boot images using npcm8xx-bingo
+do_prepare_bootloaders() {
+    local olddir="$(pwd)"
+    cd ${DEPLOY_DIR_IMAGE}
+
+    if [ "${SECURED_TIPFW}" = "False" ]; then
+        bingo ${IGPS_DIR}/KmtAndHeader_${IGPS_MACHINE}.xml \
+                -o ${DEPLOY_DIR_IMAGE}/${KMT_BINARY}
+
+        bingo ${IGPS_DIR}/TipFwAndHeader_L0_${IGPS_MACHINE}.xml \
+                -o ${DEPLOY_DIR_IMAGE}/${TIPFWL0_BINARY}
+
+        bingo ${IGPS_DIR}/TipFwAndHeader_L1_${IGPS_MACHINE}.xml \
+                -o ${DEPLOY_DIR_IMAGE}/${TIPFWL1_BINARY}
+    fi
+
+    if [ "${SECURED_OS}" = "True" ]; then
+        bingo ${IGPS_DIR}/BL31_AndHeader_${IGPS_MACHINE}.xml \
+                -o ${DEPLOY_DIR_IMAGE}/${ATF_BINARY}
+
+        bingo ${IGPS_DIR}/OpTeeAndHeader_${IGPS_MACHINE}.xml \
+                -o ${DEPLOY_DIR_IMAGE}/${OPTEE_BINARY}
+    fi
+
+    bingo ${IGPS_DIR}/BootBlockAndHeader_${IGPS_MACHINE}.xml \
+            -o ${DEPLOY_DIR_IMAGE}/${BOOTBLOCK}
+
+    bingo ${IGPS_DIR}/UbootHeader_${IGPS_MACHINE}.xml \
+            -o ${UBOOT_BINARY}.${FULL_SUFFIX}
+             
+    cd "$olddir"
+}
+
+python do_merge_bootloaders() {
+
+    def crc32_tab_val( c ):
+        crc = c  % (1<<32)
+        for x in range(0, 8):
+            if ( crc & 0x00000001 ):
+                crc = ( (crc >> 1)  % (1<<32) ) ^ 0xEDB88320
+            else:
+                crc =   crc >> 1
+            crc = crc  % (1<<32)
+        return crc
+
+    def update_crc( crc, c ):
+        long_c = (0x000000ff & c)   % (1<<32)
+        tmp = (crc ^ long_c)    % (1<<32)
+        crc = ((crc >> 8) ^ crc32_tab_val( tmp & 0xff ))   % (1<<32)
+        crc = crc  % (1<<32)
+        return crc;
+
+    def CalcCRC32(bin_filename, begin_offset, embed_ecc, output_filename):
+        try:
+            input_size = os.path.getsize(bin_filename)
+            if (begin_offset >= input_size):
+                print("\nfile too small\n")
+
+            crc = 0
+            with open(bin_filename, "rb") as binary_file:
+                tmp = binary_file.read(begin_offset)
+                while True:
+                    va = binary_file.read(1)
+                    if va:
+                        crc = update_crc(crc, ord(va))
+                    else:
+                        break
+
+            crc = crc  & 0xffffffff
+            with open(bin_filename, "rb") as binary_file:
+                input = binary_file.read()
+            crc_arr = bytearray(4)
+            for ind in range(4):
+                crc_arr[ind] = (crc >> (ind*8) ) & 255
+            output = input[:embed_ecc] + crc_arr + input[(embed_ecc + 4):]
+            output_file = open(output_filename, "w+b")
+            output_file.write(output)
+            output_file.close()
+
+        except:
+            raise
+        finally:
+            return
+
+    def CRC32_binary(binfile, begin_offset, embed_ecc, outputFile):
+        CalcCRC32(binfile, begin_offset, embed_ecc, outputFile)
+
+    def Merge_bin_files_and_pad(inF1, inF2, outF, align, padding_at_end):
+        padding_size = 0
+        padding_size_end = 0
+        F1_size = os.path.getsize(inF1)
+        F2_size = os.path.getsize(inF2)
+
+        if ((F1_size % align) != 0):
+            padding_size = align - (F1_size % align)
+
+        if ((F2_size % align) != 0):
+            padding_size_end = align - (F2_size % align)
+
+        with open(outF, "wb") as file3:
+            with open(inF1, "rb") as file1:
+                data = file1.read()
+                file3.write(data)
+
+            file3.write(b'\xFF' * padding_size)
+
+            with open(inF2, "rb") as file2:
+                data = file2.read()
+                file3.write(data)
+
+            file3.write(b'\xFF' * padding_size_end)
+
+        file1.close()
+        file2.close()
+        file3.close()
+
+    if d.getVar('SECURED_TIPFW', True) == "True":
+        d.setVar('KMT_TIPFW_BINARY', "Kmt_TipFwL0_TipFwL1.bin")
+
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BOOTBLOCK',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BINARY',True)),
+            0x1000, 0x20)
+    else:
+        CRC32_binary(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_BINARY',True)),
+            112, 12,
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_BINARY',True)))
+
+        CRC32_binary(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('TIPFWL0_BINARY',True)),
+            112, 12,
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('TIPFWL0_BINARY',True)))
+
+        CRC32_binary(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('TIPFWL1_BINARY',True)),
+            112, 12,
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('TIPFWL1_BINARY',True)))
+
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('TIPFWL0_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFWL0_BINARY',True)),
+            0x1000, 0x20)
+
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFWL0_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('TIPFWL1_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFWL0L1_BINARY',True)),
+            0x1000, 0x20)
+
+        os.remove(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFWL0_BINARY',True)))
+
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFWL0L1_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('BOOTBLOCK',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BINARY',True)),
+            0x1000, 0x20)
+
+    if d.getVar('SECURED_OS', True) == "True":
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('ATF_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_BINARY',True)),
+            0x1000, 0x20)
+
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('OPTEE_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_TEE_BINARY',True)),
+            0x1000, 0x20)
+
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BL31_TEE_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s.full' % d.getVar('UBOOT_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_UBOOT_BINARY',True)),
+            0x1000, 0x20)
+    else:
+        Merge_bin_files_and_pad(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s.full' % d.getVar('UBOOT_BINARY',True)),
+            os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True), '%s' % d.getVar('KMT_TIPFW_BB_UBOOT_BINARY',True)),
+            0x1000, 0x20)
+}
+
+prepare_secureos = "${@ "arm-trusted-firmware:do_deploy optee-os:do_deploy" if bb.utils.to_boolean(d.getVar('SECURED_OS')) else "" }"
+
+do_prepare_bootloaders[depends] += " \
+    npcm8xx-kmt:do_deploy \
+    npcm8xx-kmt-tipfwl0l1:do_deploy \
+    npcm8xx-tipfw-l0:do_deploy \
+    npcm8xx-tipfw-l1:do_deploy \
+    npcm8xx-bootblock:do_deploy \
+    ${prepare_secureos} \
+    npcm7xx-bingo-native:do_populate_sysroot \
+    npcm8xx-igps-native:do_populate_sysroot \
+    "
+
+# link images for we only need to flash partial image with idea name
+do_generate_ext4_tar:append() {
+    cd ${DEPLOY_DIR_IMAGE}
+    ln -sf ${UBOOT_BINARY} image-u-boot
+    ln -sf ${DEPLOY_DIR_IMAGE}/${FLASH_KERNEL_IMAGE} image-kernel
+    ln -sf ${S}/ext4/${IMAGE_LINK_NAME}.${FLASH_EXT4_BASETYPE}.zst image-rofs
+    ln -sf ${IMGDEPLOYDIR}/${IMAGE_LINK_NAME}.rwfs.${FLASH_EXT4_OVERLAY_BASETYPE} image-rwfs
+    ln -sf ${IMAGE_NAME}.rootfs.wic.gz image-emmc.gz
+}
+
+addtask do_prepare_bootloaders before do_generate_static after do_generate_rwfs_static
+addtask do_merge_bootloaders before do_generate_static after do_prepare_bootloaders
+addtask do_merge_bootloaders before do_generate_ext4_tar after do_prepare_bootloaders
+
+# Include the full bootblock and u-boot in the final static image
+python do_generate_static:append() {
+    _append_image(os.path.join(d.getVar('DEPLOY_DIR_IMAGE', True),
+                               'u-boot.%s' % d.getVar('UBOOT_SUFFIX',True)),
+                  int(d.getVar('FLASH_UBOOT_OFFSET', True)),
+                  int(d.getVar('FLASH_KERNEL_OFFSET', True)))
+}
+
+do_make_ubi:append() {
+    # Concatenate the uboot and ubi partitions
+    dd bs=1k conv=notrunc seek=${FLASH_UBOOT_OFFSET} \
+        if=${DEPLOY_DIR_IMAGE}/u-boot.${UBOOT_SUFFIX} \
+        of=${IMGDEPLOYDIR}/${IMAGE_NAME}.ubi.mtd
+}
+
+do_make_ubi[depends] += "${PN}:do_prepare_bootloaders"
+do_generate_ubi_tar[depends] += "${PN}:do_prepare_bootloaders"
+do_generate_ubi_tar[depends] += "${PN}:do_merge_bootloaders"
+do_generate_static_tar[depends] += "${PN}:do_prepare_bootloaders"
+do_generate_static_tar[depends] += "${PN}:do_merge_bootloaders"
+do_generate_ext4_tar[depends] += "${PN}:do_prepare_bootloaders"
+do_generate_ext4_tar[depends] += "${PN}:do_merge_bootloaders"
diff --git a/meta-nuvoton-npcm8xx/conf/layer.conf b/meta-nuvoton-npcm8xx/conf/layer.conf
new file mode 100644
index 0000000..d8f5062
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/conf/layer.conf
@@ -0,0 +1,10 @@
+# We have a conf and classes directory, add to BBPATH
+BBPATH .= ":${LAYERDIR}"
+
+BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
+            ${LAYERDIR}/recipes-*/*/*.bbappend"
+
+BBFILE_COLLECTIONS += "nuvoton-layer"
+BBFILE_PATTERN_nuvoton-layer = ""
+LAYERVERSION_nuvoton-layer = "1"
+LAYERSERIES_COMPAT_nuvoton-layer = "honister kirkstone"
diff --git a/meta-nuvoton-npcm8xx/conf/machine/evb-npcm750.conf b/meta-nuvoton-npcm8xx/conf/machine/evb-npcm750.conf
new file mode 100644
index 0000000..f0216ea
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/conf/machine/evb-npcm750.conf
@@ -0,0 +1,13 @@
+KMACHINE = "nuvoton"
+KERNEL_DEVICETREE = "${KMACHINE}-npcm750-evb.dtb"
+
+UBOOT_MACHINE = "PolegSVB_config"
+IGPS_MACHINE = "EB"
+
+FLASH_SIZE = "32768"
+
+require conf/machine/include/npcm7xx.inc
+require conf/machine/include/obmc-bsp-common.inc
+require conf/machine/include/obmc-evb-common.inc
+
+IMAGE_FSTYPES = "cpio.${INITRAMFS_CTYPE}.u-boot mtd-static"
diff --git a/meta-nuvoton-npcm8xx/conf/machine/include/npcm7xx.inc b/meta-nuvoton-npcm8xx/conf/machine/include/npcm7xx.inc
new file mode 100644
index 0000000..0a15467
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/conf/machine/include/npcm7xx.inc
@@ -0,0 +1,33 @@
+#@TYPE: Machine
+#@NAME: Nuvoton NPCM7XX
+#@DESCRIPTION: Common machine configuration for Nuvoton NPCM7XX Chip
+
+require conf/machine/include/nuvoton.inc
+
+KERNEL_IMAGETYPE ?= "uImage"
+KERNEL_EXTRA_ARGS ?= "UIMAGE_LOADADDR=0x00008000"
+
+UBOOT_MACHINE ?= "PolegSVB_config"
+UBOOT_ENTRYPOINT ?= "0x00008000"
+UBOOT_LOADADDRESS ?= "0x00008000"
+
+FLASH_UBOOT_OFFSET = "0"
+FLASH_UBOOT_ENV_OFFSET = "1024"
+FLASH_KERNEL_OFFSET = "2048"
+FLASH_UBI_OFFSET = "${FLASH_KERNEL_OFFSET}"
+FLASH_ROFS_OFFSET = "7680"
+FLASH_RWFS_OFFSET = "30720"
+
+# UBI volume sizes in KB unless otherwise noted.
+FLASH_UBI_RWFS_SIZE = "6144"
+FLASH_UBI_RWFS_TXT_SIZE = "6MiB"
+
+DEFAULTTUNE ?= "arm7a-novfp"
+
+SERIAL_CONSOLES = "115200;ttyS3"
+
+SOC_FAMILY = "npcm7xx"
+include conf/machine/include/soc-family.inc
+MACHINEOVERRIDES .= ":npcm7xx"
+
+require conf/machine/include/tune-arm7a-novfp.inc
diff --git a/meta-nuvoton-npcm8xx/conf/machine/include/npcm8xx.inc b/meta-nuvoton-npcm8xx/conf/machine/include/npcm8xx.inc
new file mode 100644
index 0000000..98974d4
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/conf/machine/include/npcm8xx.inc
@@ -0,0 +1,36 @@
+#@TYPE: Machine
+#@NAME: Nuvoton NPCM8XX
+#@DESCRIPTION: Common machine configuration for Nuvoton NPCM8XX Chip
+
+require conf/machine/include/nuvoton.inc
+
+KERNEL_IMAGETYPE ?= "Image"
+KERNEL_EXTRA_ARGS ?= "UIMAGE_LOADADDR=0x00008000"
+
+UBOOT_MACHINE ?= "ArbelEVB_defconfig"
+UBOOT_ENTRYPOINT ?= "0"
+UBOOT_LOADADDRESS ?= "0"
+
+FLASH_SIZE = "32768"
+FLASH_UBOOT_OFFSET = "0"
+FLASH_KERNEL_OFFSET = "2048"
+FLASH_ROFS_OFFSET = "8192"
+FLASH_RWFS_OFFSET = "31744"
+
+# UBI volume sizes in KB unless otherwise noted.
+FLASH_UBI_RWFS_SIZE = "6144"
+FLASH_UBI_RWFS_TXT_SIZE = "6MiB"
+
+SERIAL_CONSOLES = "115200;ttyS0"
+
+SECURED_TIPFW = "True"
+SECURED_OS = "True"
+
+SOC_FAMILY = "npcm8xx"
+include conf/machine/include/soc-family.inc
+MACHINEOVERRIDES .= ":npcm8xx"
+
+require conf/machine/include/arm/armv8a/tune-cortexa35.inc
+
+IMAGE_CLASSES:append:npcm8xx = " image_types_phosphor_nuvoton_npcm8xx"
+KERNEL_CLASSES:append:npcm8xx = " fitimage_nuvoton_npcm8xx"
diff --git a/meta-nuvoton-npcm8xx/conf/machine/include/nuvoton.inc b/meta-nuvoton-npcm8xx/conf/machine/include/nuvoton.inc
new file mode 100644
index 0000000..068fe35
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/conf/machine/include/nuvoton.inc
@@ -0,0 +1,6 @@
+PREFERRED_PROVIDER_virtual/kernel ?= "linux-nuvoton"
+PREFERRED_PROVIDER_virtual/bootloader ?= "u-boot-nuvoton"
+PREFERRED_PROVIDER_u-boot ?= "u-boot-nuvoton"
+PREFERRED_PROVIDER_u-boot-fw-utils ?= "u-boot-fw-utils-nuvoton"
+
+MACHINEOVERRIDES .= ":nuvoton"
diff --git a/meta-nuvoton-npcm8xx/conf/machine/include/tune-arm7a-novfp.inc b/meta-nuvoton-npcm8xx/conf/machine/include/tune-arm7a-novfp.inc
new file mode 100644
index 0000000..b8c6d8c
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/conf/machine/include/tune-arm7a-novfp.inc
@@ -0,0 +1,11 @@
+DEFAULTTUNE ?= "arm7a-novfp"
+
+require conf/machine/include/arm/arch-armv7a.inc
+
+TUNEVALID[arm7a-novfp] = "Enable arm7a-novfp specific processor optimizations"
+
+AVAILTUNES += "arm7a-novfp"
+ARMPKGARCH:tune-arm7a-novfp = "armv7a"
+TUNE_FEATURES:tune-armv7a = "arm armv7a"
+TUNE_FEATURES:tune-arm7a-novfp = "${TUNE_FEATURES:tune-armv7a} arm7a-novfp"
+PACKAGE_EXTRA_ARCHS:tune-arm7a-novfp = "${PACKAGE_EXTRA_ARCHS:tune-armv7a}"
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware.bb b/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware.bb
new file mode 100644
index 0000000..70fa39e
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware.bb
@@ -0,0 +1,11 @@
+ATF_VERSION = "1.3"
+SRCREV = "469101d48a1b0cb6c93ea5fe3bd3b32b46bd047e"
+BRANCH = "nuvoton"
+LIC_FILES_CHKSUM = "file://license.rst;md5=1dd070c98a281d18d9eefd938729b031"
+
+include arm-trusted-firmware.inc
+
+FILESEXTRAPATHS:prepend:npcm8xx = "${THISDIR}/${PN}:"
+SRC_URI:append:npcm8xx= " file://0001-plat-nuvoton-npcm845x-fix-build-warning.patch \
+                   file://0002-plat-nuvoton-npcm845x-fix-reboot-hang.patch \
+                 "
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware.inc b/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware.inc
new file mode 100644
index 0000000..bf56357
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware.inc
@@ -0,0 +1,59 @@
+DESCRIPTION = "ARM Trusted Firmware"
+
+LICENSE = "BSD"
+LIC_FILES_CHKSUM ?= "file://license.rst;md5=1dd070c98a281d18d9eefd938729b031"
+
+PV="1.3.0+git${SRCPV}"
+
+inherit deploy
+
+S = "${WORKDIR}/git"
+
+BRANCH ?= ""
+REPO ?= "git://github.com/Nuvoton-Israel/arm-trusted-firmware.git;protocol=https"
+BRANCHARG = "${@['nobranch=1', 'branch=${BRANCH}'][d.getVar('BRANCH', True) != '']}"
+SRC_URI = "${REPO};${BRANCHARG}"
+
+inherit image-artifact-names
+
+MACHINE_SOC ?= "npcm8xx"
+PLATFORM = "npcm845x"
+
+# requires CROSS_COMPILE set by hand as there is no configure script
+# Some versions of u-boot use .bin and others use .img.  By default use .bin
+# but enable individual recipes to change this value.
+ATF_SUFFIX ?= "bin"
+ATF_IMAGE ?= "bl31-${MACHINE_SOC}-${PV}-${PR}.${ATF_SUFFIX}"
+ATF_SYMLINK ?= "bl31-${MACHINE_SOC}.${ATF_SUFFIX}"
+
+export CROSS_COMPILE="${TARGET_PREFIX}"
+
+# Let the Makefile handle setting up the CFLAGS and LDFLAGS as it is a standalone application
+CFLAGS[unexport] = "1"
+LDFLAGS[unexport] = "1"
+AS[unexport] = "1"
+LD[unexport] = "1"
+
+do_configure() {
+	oe_runmake clean -C ${S} PLAT=${PLATFORM}
+}
+
+do_compile() {
+	oe_runmake -C ${S} PLAT=${PLATFORM} SPD=opteed all
+}
+
+# do_install() nothing
+do_install[noexec] = "1"
+
+do_deploy() {
+    # Create deploy folder
+    install -d ${DEPLOYDIR}
+
+    # Copy IPL to deploy folder
+    install -m 0644 ${S}/build/${PLATFORM}/release/bl31.bin ${DEPLOYDIR}/bl31.bin
+    cd ${DEPLOYDIR}
+    ln -sf bl31.bin ${ATF_SYMLINK}
+    ln -sf bl31.bin ${ATF_IMAGE}
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware/0001-plat-nuvoton-npcm845x-fix-build-warning.patch b/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware/0001-plat-nuvoton-npcm845x-fix-build-warning.patch
new file mode 100644
index 0000000..f68cd6d
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware/0001-plat-nuvoton-npcm845x-fix-build-warning.patch
@@ -0,0 +1,39 @@
+From 50067a3307193c39ed559e49b0cff3f56cbc9cee Mon Sep 17 00:00:00 2001
+From: Joseph Liu <kwliu@nuvoton.com>
+Date: Thu, 14 Apr 2022 15:45:43 +0800
+Subject: [PATCH] plat: nuvoton: npcm845x: fix build warning
+
+Signed-off-by: Joseph Liu <kwliu@nuvoton.com>
+---
+ plat/nuvoton/npcm845x/npcm845x_psci.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/plat/nuvoton/npcm845x/npcm845x_psci.c b/plat/nuvoton/npcm845x/npcm845x_psci.c
+index f4ac3ac22..f6db31132 100644
+--- a/plat/nuvoton/npcm845x/npcm845x_psci.c
++++ b/plat/nuvoton/npcm845x/npcm845x_psci.c
+@@ -219,8 +219,8 @@ void npcm845x_pwr_domain_on_finish(const psci_power_state_t *target_state)
+ 		INFO("%s: target_state->pwr_domain_state[%lu]=%x\n",
+ 			__func__, i, target_state->pwr_domain_state[i]);
+ 			
+-		assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+-					PLAT_LOCAL_STATE_OFF);
++	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
++			PLAT_LOCAL_STATE_OFF);
+ 
+ 
+ 	gicv2_pcpu_distif_init();
+@@ -244,8 +244,8 @@ void npcm845x_pwr_domain_suspend_finish(const psci_power_state_t *target_state)
+ 			__func__, i, target_state->pwr_domain_state[i]);
+ 			
+ 			
+-		assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
+-					PLAT_LOCAL_STATE_OFF);
++	assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] ==
++			PLAT_LOCAL_STATE_OFF);
+ 
+ 
+ 	gicv2_pcpu_distif_init();
+-- 
+2.25.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware/0002-plat-nuvoton-npcm845x-fix-reboot-hang.patch b/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware/0002-plat-nuvoton-npcm845x-fix-reboot-hang.patch
new file mode 100644
index 0000000..bba8d90
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/arm-trusted-firmware/arm-trusted-firmware/0002-plat-nuvoton-npcm845x-fix-reboot-hang.patch
@@ -0,0 +1,27 @@
+From a62ae26bdc74acca92acfcd129e8c84dabc15941 Mon Sep 17 00:00:00 2001
+From: Stanley Chu <yschu@nuvoton.com>
+Date: Mon, 18 Apr 2022 14:27:51 +0800
+Subject: [PATCH] plat: nuvoton: npcm845x: fix reboot hang
+
+Signed-off-by: Stanley Chu <yschu@nuvoton.com>
+---
+ plat/nuvoton/npcm845x/npcm845x_psci.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/plat/nuvoton/npcm845x/npcm845x_psci.c b/plat/nuvoton/npcm845x/npcm845x_psci.c
+index f6db31132..a8b919d85 100644
+--- a/plat/nuvoton/npcm845x/npcm845x_psci.c
++++ b/plat/nuvoton/npcm845x/npcm845x_psci.c
+@@ -266,7 +266,8 @@ void __dead2 npcm845x_system_reset(void)
+ 	 * In future - support all reset types. For now, SW1 reset
+ 	 * Enable software reset 1 to reboot the BMC
+ 	 */ 
+-	mmio_write_32(SWRSTR, SWRSTR_SWRST1);
++	//mmio_write_32(SWRSTR, SWRSTR_SWRST1);
++	mmio_write_32(0xf000801c, 0x83);
+ 	while (1);
+ }
+ 
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-bingo-native_git.bb b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-bingo-native_git.bb
new file mode 100644
index 0000000..5ec9420
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-bingo-native_git.bb
@@ -0,0 +1,20 @@
+SUMMARY = "XML-based binary image generator"
+DESCRIPTION = "XML-based binary image generator"
+HOMEPAGE = "https://github.com/Nuvoton-Israel/bingo"
+PR = "r1"
+PV = "0.1+git${SRCPV}"
+LICENSE = "GPL-2.0-only"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+
+SRC_URI += "git://github.com/Nuvoton-Israel/bingo;branch=master;protocol=https"
+SRCREV = "4f102ff7851da9fd11965857edd1b3046c187b7a"
+
+S = "${WORKDIR}/git"
+
+do_install () {
+
+	install -d "${D}${bindir}"
+	install deliverables/linux/Release/bingo ${D}${bindir}
+}
+
+inherit native
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-bootblock_10.10.17.bb b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-bootblock_10.10.17.bb
new file mode 100644
index 0000000..21ae615
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-bootblock_10.10.17.bb
@@ -0,0 +1,26 @@
+SUMMARY = "Primary bootloader for NPCM7XX (Poleg) devices"
+DESCRIPTION = "Primary bootloader for NPCM7XX (Poleg) devices"
+HOMEPAGE = "https://github.com/Nuvoton-Israel/npcm7xx-bootblock"
+LICENSE = "GPL-2.0-only"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+
+FILENAME = "Poleg_bootblock_${PV}.bin"
+
+S = "${WORKDIR}"
+
+SRCREV = "7bfef99f7a0354395519c4975f96d66cdda1fb67"
+SRC_URI = " \
+    https://raw.githubusercontent.com/Nuvoton-Israel/bootblock/${SRCREV}/LICENSE;name=lic \
+    https://github.com/Nuvoton-Israel/bootblock/releases/download/BootBlock_${PV}/Poleg_bootblock_basic.bin;downloadfilename=${FILENAME};name=bin \
+"
+
+SRC_URI[lic.md5sum] = "b234ee4d69f5fce4486a80fdaf4a4263"
+SRC_URI[bin.sha256sum] = "3e92e3f6c4624139d000f91541792a54f52205637bb88abd14310c854694cb39"
+
+inherit deploy
+
+do_deploy () {
+	install -D -m 644 ${WORKDIR}/${FILENAME} ${DEPLOYDIR}/Poleg_bootblock.bin
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-igps-native_02.01.12.bb b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-igps-native_02.01.12.bb
new file mode 100644
index 0000000..5ef884c
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-igps-native_02.01.12.bb
@@ -0,0 +1,25 @@
+SUMMARY = "Image Generation and Programming Scripts for NPCM7XX (Poleg) devices"
+DESCRIPTION = "Image Generation and Programming Scripts for NPCM7XX (Poleg) devices"
+HOMEPAGE = "https://github.com/Nuvoton-Israel/igps"
+LICENSE = "GPL-2.0-only"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+
+SRC_URI = " \
+    git://github.com/Nuvoton-Israel/igps;branch=master;protocol=https \
+    file://0001-Adjust-paths-for-use-with-Bitbake.patch \
+"
+# tag IGPS_02.01.12
+SRCREV = "2fb1a3b0d61164ed1157e27889a4ec2292cbc760"
+
+S = "${WORKDIR}/git"
+
+DEST = "${D}${datadir}/${BPN}"
+
+do_install() {
+	install -d ${DEST}
+	install ImageGeneration/references/BootBlockAndHeader_${IGPS_MACHINE}.xml ${DEST}
+	install ImageGeneration/references/UbootHeader_${IGPS_MACHINE}.xml ${DEST}
+	install ImageGeneration/inputs/mergedBootBlockAndUboot.xml ${DEST}
+}
+
+inherit native
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-igps/0001-Adjust-paths-for-use-with-Bitbake.patch b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-igps/0001-Adjust-paths-for-use-with-Bitbake.patch
new file mode 100644
index 0000000..118f199
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm7xx-igps/0001-Adjust-paths-for-use-with-Bitbake.patch
@@ -0,0 +1,145 @@
+From 215a2d9660a929beae8bc420239467fc9e135b4f Mon Sep 17 00:00:00 2001
+From: Benjamin Fair <benjaminfair@google.com>
+Date: Wed, 23 Oct 2019 14:23:08 -0700
+Subject: [PATCH] Adjust paths for use with Bitbake
+
+Signed-off-by: Benjamin Fair <benjaminfair@google.com>
+---
+ ImageGeneration/inputs/mergedBootBlockAndUboot.xml     | 10 +++++-----
+ ImageGeneration/references/BootBlockAndHeader_EB.xml   |  6 +++---
+ .../references/BootBlockAndHeader_RunBMC.xml           |  6 +++---
+ ImageGeneration/references/UbootHeader_EB.xml          |  6 +++---
+ ImageGeneration/references/UbootHeader_RunBMC.xml      |  6 +++---
+ 5 files changed, 17 insertions(+), 17 deletions(-)
+
+diff --git a/ImageGeneration/inputs/mergedBootBlockAndUboot.xml b/ImageGeneration/inputs/mergedBootBlockAndUboot.xml
+index d832f96..f4c7756 100644
+--- a/ImageGeneration/inputs/mergedBootBlockAndUboot.xml
++++ b/ImageGeneration/inputs/mergedBootBlockAndUboot.xml
+@@ -18,18 +18,18 @@
+ 		<name>BootBlock</name>         <!-- name of field -->
+ 		<config>
+ 			<offset>0</offset>            <!-- offset in the header -->
+-			<size format='FileSize'>output_binaries/BootBlockAndHeader.bin</size>              <!-- size in the header -->
++			<size format='FileSize'>Poleg_bootblock.bin.full</size>              <!-- size in the header -->
+ 		</config>
+-		<content format='FileContent'>output_binaries/BootBlockAndHeader.bin</content>  <!-- content the user should fill -->
++		<content format='FileContent'>Poleg_bootblock.bin.full</content>  <!-- content the user should fill -->
+ 	</BinField>
+ 		
+ 	<BinField>
+ 		<name>u-boot</name>         <!-- name of field -->
+ 		<config>
+-			<offset format='FileSize' align='0x1000'>output_binaries/BootBlockAndHeader.bin</offset>            <!-- offset in the header -->
+-			<size format='FileSize'>output_binaries/UbootAndHeader.bin</size>              <!-- size in the header -->
++			<offset format='FileSize' align='0x1000'>Poleg_bootblock.bin.full</offset>            <!-- offset in the header -->
++			<size format='FileSize'>u-boot.bin.full</size>              <!-- size in the header -->
+ 		</config>
+-		<content format='FileContent'>output_binaries/UbootAndHeader.bin</content>  <!-- content the user should fill -->
++		<content format='FileContent'>u-boot.bin.full</content>  <!-- content the user should fill -->
+ 	</BinField>
+ 	
+ </Bin_Ecc_Map>
+diff --git a/ImageGeneration/references/BootBlockAndHeader_EB.xml b/ImageGeneration/references/BootBlockAndHeader_EB.xml
+index 775534f..157535d 100644
+--- a/ImageGeneration/references/BootBlockAndHeader_EB.xml
++++ b/ImageGeneration/references/BootBlockAndHeader_EB.xml
+@@ -42,7 +42,7 @@
+ 			<offset>0x144</offset>       
+ 			<size>0x4</size> 
+ 		</config>
+-		<content format='FileSize'>inputs/Poleg_bootblock.bin</content>	<!-- content the user should fill -->
++		<content format='FileSize'>Poleg_bootblock.bin</content>	<!-- content the user should fill -->
+ 	</BinField>
+ 	
+ 	<BinField>
+@@ -50,9 +50,9 @@
+ 		<name>Code</name>             <!-- name of field -->
+ 		<config>
+ 			<offset>0x200</offset>       
+-			<size format='FileSize'>inputs/Poleg_bootblock.bin</size>                 <!-- size in the header calculated by tool-->
++			<size format='FileSize'>Poleg_bootblock.bin</size>                 <!-- size in the header calculated by tool-->
+ 		</config>
+-		<content format='FileContent'>inputs/Poleg_bootblock.bin</content>  <!-- content the user should fill -->
++		<content format='FileContent'>Poleg_bootblock.bin</content>  <!-- content the user should fill -->
+ 	</BinField>	
+ 	
+ 	<!-- BMC optional fields -->
+diff --git a/ImageGeneration/references/BootBlockAndHeader_RunBMC.xml b/ImageGeneration/references/BootBlockAndHeader_RunBMC.xml
+index cc719e9..4d1e972 100644
+--- a/ImageGeneration/references/BootBlockAndHeader_RunBMC.xml
++++ b/ImageGeneration/references/BootBlockAndHeader_RunBMC.xml
+@@ -42,7 +42,7 @@
+ 			<offset>0x144</offset>       
+ 			<size>0x4</size> 
+ 		</config>
+-		<content format='FileSize'>inputs/Poleg_bootblock.bin</content>	<!-- content the user should fill -->
++		<content format='FileSize'>Poleg_bootblock.bin</content>	<!-- content the user should fill -->
+ 	</BinField>
+ 	
+ 	<BinField>
+@@ -50,9 +50,9 @@
+ 		<name>Code</name>             
+ 		<config>
+ 			<offset>0x200</offset>       
+-			<size format='FileSize'>inputs/Poleg_bootblock.bin</size>                 <!-- size in the header calculated by tool-->
++			<size format='FileSize'>Poleg_bootblock.bin</size>                 <!-- size in the header calculated by tool-->
+ 		</config>
+-		<content format='FileContent'>inputs/Poleg_bootblock.bin</content>  <!-- content the user should fill -->
++		<content format='FileContent'>Poleg_bootblock.bin</content>  <!-- content the user should fill -->
+ 	</BinField>	
+ 	
+ 	<!-- BMC optional fields -->
+diff --git a/ImageGeneration/references/UbootHeader_EB.xml b/ImageGeneration/references/UbootHeader_EB.xml
+index 1e72e22..475ec45 100644
+--- a/ImageGeneration/references/UbootHeader_EB.xml
++++ b/ImageGeneration/references/UbootHeader_EB.xml
+@@ -42,7 +42,7 @@
+ 			<offset>0x144</offset>        <!-- offset in the header -->
+ 			<size>0x4</size>              <!-- size in the header -->
+ 		</config>
+-		<content format='FileSize'>inputs/u-boot.bin</content>	<!-- content the user should fill -->
++		<content format='FileSize'>u-boot.bin</content>	<!-- content the user should fill -->
+ 	</BinField>
+ 	
+ 	<BinField>
+@@ -50,9 +50,9 @@
+ 		<name>Code</name>             <!-- name of field -->
+ 		<config>
+ 			<offset>0x200</offset>        <!-- offset in the header -->
+-			<size format='FileSize'>inputs/u-boot.bin</size>                 <!-- size in the header calculated by tool-->
++			<size format='FileSize'>u-boot.bin</size>                 <!-- size in the header calculated by tool-->
+ 		</config>
+-		<content format='FileContent'>inputs/u-boot.bin</content>  <!-- content the user should fill -->
++		<content format='FileContent'>u-boot.bin</content>  <!-- content the user should fill -->
+ 	</BinField>	
+ 	
+ 	<!-- BMC optional fields -->
+diff --git a/ImageGeneration/references/UbootHeader_RunBMC.xml b/ImageGeneration/references/UbootHeader_RunBMC.xml
+index 7eb3076..481ed2f 100644
+--- a/ImageGeneration/references/UbootHeader_RunBMC.xml
++++ b/ImageGeneration/references/UbootHeader_RunBMC.xml
+@@ -42,7 +42,7 @@
+ 			<offset>0x144</offset>        <!-- offset in the header -->
+ 			<size>0x4</size>              <!-- size in the header -->
+ 		</config>
+-		<content format='FileSize'>inputs/u-boot.bin</content>	<!-- content the user should fill -->
++		<content format='FileSize'>u-boot.bin</content>	<!-- content the user should fill -->
+ 	</BinField>
+ 	
+ 	<BinField>
+@@ -50,9 +50,9 @@
+ 		<name>Code</name>             <!-- name of field -->
+ 		<config>
+ 			<offset>0x200</offset>        <!-- offset in the header -->
+-			<size format='FileSize'>inputs/u-boot.bin</size>                 <!-- size in the header calculated by tool-->
++			<size format='FileSize'>u-boot.bin</size>                 <!-- size in the header calculated by tool-->
+ 		</config>
+-		<content format='FileContent'>inputs/u-boot.bin</content>  <!-- content the user should fill -->
++		<content format='FileContent'>u-boot.bin</content>  <!-- content the user should fill -->
+ 	</BinField>	
+ 	
+ 	<!-- BMC optional fields -->
+-- 
+2.24.0.rc0.303.g954a862665-goog
+
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-bootblock/arbel_a35_bootblock.0.1.9.bin b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-bootblock/arbel_a35_bootblock.0.1.9.bin
new file mode 100644
index 0000000..b23fb33
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-bootblock/arbel_a35_bootblock.0.1.9.bin
Binary files differ
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-bootblock_0.1.9.bb b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-bootblock_0.1.9.bb
new file mode 100644
index 0000000..43bb244
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-bootblock_0.1.9.bb
@@ -0,0 +1,15 @@
+LICENSE = "CLOSED"
+
+SRC_URI = " \
+    file://arbel_a35_bootblock.${PV}.bin\
+"
+
+S = "${WORKDIR}"
+
+inherit deploy
+
+do_deploy () {
+	install -D -m 644 ${S}/arbel_a35_bootblock.${PV}.bin ${DEPLOYDIR}/arbel_a35_bootblock.bin
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps-native_git.bb b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps-native_git.bb
new file mode 100644
index 0000000..e3b2a1a
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps-native_git.bb
@@ -0,0 +1,36 @@
+SUMMARY = "Image Generation and Programming Scripts for NPCM8XX (Arbel) devices"
+DESCRIPTION = "Image Generation and Programming Scripts for NPCM8XX (Arbel) devices"
+HOMEPAGE = "https://github.com/Nuvoton-Israel/igps"
+LICENSE = "GPLv2"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+
+SRC_URI = " \
+    git://github.com/Nuvoton-Israel/igps;branch=master;protocol=https \
+    file://KmtAndHeader_${IGPS_MACHINE}.xml \
+    file://TipFwAndHeader_L0_${IGPS_MACHINE}.xml \
+    file://TipFwAndHeader_L1_${IGPS_MACHINE}.xml \
+    file://BootBlockAndHeader_${IGPS_MACHINE}.xml \
+    file://BL31_AndHeader_${IGPS_MACHINE}.xml \
+    file://OpTeeAndHeader_${IGPS_MACHINE}.xml \
+    file://UbootHeader_${IGPS_MACHINE}.xml \
+"
+
+# tag IGPS_02.01.12
+SRCREV = "2fb1a3b0d61164ed1157e27889a4ec2292cbc760"
+
+S = "${WORKDIR}/git"
+
+DEST = "${D}${datadir}/${BPN}"
+
+do_install() {
+	install -d ${DEST}
+	install ${WORKDIR}/KmtAndHeader_${IGPS_MACHINE}.xml ${DEST}
+	install ${WORKDIR}/TipFwAndHeader_L0_${IGPS_MACHINE}.xml ${DEST}
+	install ${WORKDIR}/TipFwAndHeader_L1_${IGPS_MACHINE}.xml ${DEST}
+	install ${WORKDIR}/BootBlockAndHeader_${IGPS_MACHINE}.xml ${DEST}
+	install ${WORKDIR}/BL31_AndHeader_${IGPS_MACHINE}.xml ${DEST}
+	install ${WORKDIR}/OpTeeAndHeader_${IGPS_MACHINE}.xml ${DEST}
+	install ${WORKDIR}/UbootHeader_${IGPS_MACHINE}.xml ${DEST}
+}
+
+inherit native
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/BL31_AndHeader_EB.xml b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/BL31_AndHeader_EB.xml
new file mode 100644
index 0000000..69220bf
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/BL31_AndHeader_EB.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- SPDX-License-Identifier: GPL-2.0
+#
+# Nuvoton IGPS: Image Generation And Programming Scripts For Arbel BMC
+#
+# Copyright (C) 2022 Nuvoton Technologies, All Rights Reserved
+#======================================== -->
+
+<Bin_Ecc_Map>
+	<!-- BMC mandatory fields -->
+	<ImageProperties>
+		<BinSize>0</BinSize>         <!-- If 0 the binary size will be calculated by the tool -->
+		<PadValue>0xFF</PadValue>	<!-- Byte value to pad the empty areas, default is 0 -->
+	</ImageProperties>
+		
+	<BinField>
+		<!-- BootBlock tag (0x50 0x08 0x55 0xAA 0x54 0x4F 0x4F 0x42) or 
+			     uboot tag (0x55 0x42 0x4F 0x4F 0x54 0x42 0x4C 0x4B) -->
+		<name>StartTag</name>         
+		<config>
+			<offset>0</offset>           
+			<size>0x8</size> 
+		</config>
+		<content format='bytes'>0x0A 0x42 0x4C 0x33 0x31 0x4E 0x50 0x43</content>  <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Version (Major.Minor) -->
+		<name>version</name>          
+		<config>
+			<offset>0x100</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- BootBlock or u-boot Code size -->
+		<name>DestAddr</name>         
+		<config>
+			<offset>0x1F8</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0xFFFB0E00</content>	<!-- content the user should fill -->
+	</BinField>
+		
+	<BinField>
+		<!-- BootBlock or u-boot Code size -->
+		<name>CodeSize</name>         
+		<config>
+			<offset>0x1FC</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='FileSize'>bl31.bin</content>	<!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- The BootBlock or u-boot binary file -->
+		<name>Code</name>             
+		<config>
+			<offset>0x200</offset>       
+			<size format='FileSize'>bl31.bin</size>                 <!-- size in the header calculated by tool-->
+		</config>
+		<content format='FileContent'>bl31.bin</content>  <!-- content the user should fill -->
+	</BinField>
+	
+</Bin_Ecc_Map>
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/BootBlockAndHeader_EB.xml b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/BootBlockAndHeader_EB.xml
new file mode 100644
index 0000000..730e694
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/BootBlockAndHeader_EB.xml
@@ -0,0 +1,515 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- SPDX-License-Identifier: GPL-2.0
+#
+# Nuvoton IGPS: Image Generation And Programming Scripts For Arbel BMC
+#
+# Copyright (C) 2022 Nuvoton Technologies, All Rights Reserved
+#======================================== -->
+
+<Bin_Ecc_Map>
+	<!-- BMC mandatory fields -->
+	<ImageProperties>
+		<BinSize>0</BinSize>         <!-- If 0 the binary size will be calculated by the tool -->
+		<PadValue>0xFF</PadValue>	<!-- Byte value to pad the empty areas, default is 0 -->
+	</ImageProperties>
+		
+	<BinField>
+		<!-- BootBlock tag (0x0A 0x50 0x08 0x55 0xAA 0x54 0x4F 0x4F) -->
+		<name>StartTag</name>         
+		<config>
+			<offset>0</offset>           
+			<size>0x8</size> 
+		</config>
+		<content format='bytes'>0x0A 0x50 0x08 0x55 0xAA 0x54 0x4F 0x4F</content>
+	</BinField>
+	
+	<BinField>
+		<!-- Version (Major.Minor) -->
+		<name>version</name>          
+		<config>
+			<offset>0x100</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0</content>               <!-- content the user should fill -->
+	</BinField>
+		
+	<BinField>
+		<!-- Board manufaturer ( Dell = 0, Nuvoton = 100, Google = 1, MS = 2) -->
+		<name>vendor</name>          
+		<config>
+			<offset>0x104</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>100</content>                              <!--Board_manufacturer: Nuvoton-->
+	</BinField>
+	<BinField>
+		<!-- Board type ( DRB = 0, SVB = 1, EB = 2 RunBMC = 10) -->
+		<!-- WARNING: Currently this value is only printed to serial. -->
+		<name>board_type</name>          
+		<config>
+			<offset>0x108</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0x02</content>                                   <!--Board_type: SVB-->
+	</BinField>
+	
+	<BinField>
+		<!-- supported values: 300, 500, 666, 700, 720, 750, 775, 787.5 800, 850, 900, 950, 975, 1000, 1037, 1050, 1062.5 1066, 1100, 1150, 1200.  
+		     Recommended: 1066 or 800. Note: not all values are tested  -->
+		<name>MC_FREQ_IN_MHZ</name>          
+		<config>
+			<offset>0x10C</offset>       
+			<size>0x2</size> 
+		</config>
+		<content format='32bit'>1066</content> 
+	</BinField>
+	<BinField>
+		<!-- supporeted values: 333,500,600,666,700,720,750,800,825,850,900,950,1000. 
+		     Recommended: 1000. Note: not all values are tested -->
+		<name>CPU_FREQ_IN_MHZ</name>          
+		<config>
+			<offset>0x10E</offset>       
+			<size>0x2</size> 
+		</config>
+		<content format='32bit'>1000</content>
+	</BinField>
+
+	<BinField>
+		<!-- DDR: SOC (BMC) drive -->
+		<name>ddr_soc_drive</name>
+		<config>
+			<offset>0x110</offset>
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>48</content>     <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- DDR: SOC (BMC) termination in ohm-->
+		<name>ddr_soc_odt</name>
+		<config>
+			<offset>0x114</offset>
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>48</content>     <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<!-- DDR: DRAM  drive -->
+		<name>ddr_dram_drive</name>
+		<config>
+			<offset>0x118</offset>
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>48</content>     <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- DDR: DRAM termination in ohm -->
+		<name>ddr_dram_odt</name>
+		<config>
+			<offset>0x11C</offset>
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>48</content>     <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<!--  -->
+		<name>NoECC_Region_0_Start</name>
+		<config>
+			<offset>0x120</offset>
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0</content>     <!-- content the user should fill -->
+	</BinField>
+	
+	
+	<BinField>
+		<!--  -->
+		<name>NoECC_Region_0_End</name>
+		<config>
+			<offset>0x124</offset>
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0</content>     <!-- content the user should fill -->
+	</BinField>
+	
+	
+	<BinField>
+		<!--  -->
+		<name>NoECC_Region_1_Start</name>
+		<config>
+			<offset>0x128</offset>
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0</content>     <!-- content the user should fill -->
+	</BinField>
+	
+	
+	<BinField>
+		<!--  -->
+		<name>NoECC_Region_1_End</name>
+		<config>
+			<offset>0x12C</offset>
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0</content>     <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!--  -->
+		<name>dram_max_size</name>
+		<config>
+			<offset>0x130</offset>
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0x40000000</content>     <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<!-- MC_CONFIG. 
+			Bit 0: MC_CAPABILITY_ECC_EN (0x01)
+			Bit 2: Select DRAM type. 
+				0: 1600 DRAM type clk.
+				1: 2133 DRAM type clk.
+			Bit 3: enable 3 seconds delay.
+			Bit 4: enable debug sweeps (in addition to sweep_debug)
+			 -->
+		<name>MC_CONFIG</name>          
+		<config>
+			<offset>0x134</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0x04</content>  
+	</BinField>
+	
+
+	<BinField>
+		<!-- HOST_IF.
+			0xFF: LPC backward compatible
+			0x00: LPC. 
+			0x01: eSPI
+			0x02: GPIOs TRIS.  -->
+		<name>HOST_IF</name>          
+		<config>
+			<offset>0x135</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0x00</content>
+	</BinField>
+	
+	
+	
+	
+	<BinField>
+		<!-- bit 7 : pos\neg
+             bits [6:0] DQS0 in value		-->
+		<name>MC_DQS_IN_LANE0</name>          
+		<config>
+			<offset>0x136</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- bit 7 : pos\neg
+             bits [6:0] DQS1 in value		-->
+		<name>MC_DQS_IN_LANE1</name>          
+		<config>
+			<offset>0x137</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	
+	<BinField>
+		<!-- bit 7 : pos\neg
+             bits [6:0] DQS0 out value		-->
+		<name>MC_DQS_OUT_LANE0</name>          
+		<config>
+			<offset>0x138</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- bit 7 : pos\neg
+             bits [6:0] DQS1 out value		-->
+		<name>MC_DQS_OUT_LANE1</name>          
+		<config>
+			<offset>0x139</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- bit 6 : incr\dec
+             bits [5:0] TRIM value		-->
+		<name>MC_DLLS_TRIM_ADRCTL</name>          
+		<config>
+			<offset>0x13A</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+
+	<BinField>
+		<!-- bit 6 : incr\dec
+             bits [5:0] TRIM value		-->
+		<name>MC_DLLS_TRIM_ADRCTRL_MA</name>          
+		<config>
+			<offset>0x13B</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- bit 6 : incr\dec
+             bits [5:0] TRIM value		-->
+		<name>MC_DLLS_TRIM_CLK</name>          
+		<config>
+			<offset>0x13C</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	
+	
+	<BinField>
+		<!-- mc_dlls_trim_clk_sqew: not implemented -->
+		<name>mc_dlls_trim_clk_sqew</name>          
+		<config>
+			<offset>0x13D</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- PHASE1 lane 0 -->
+		<name>PHASE1_LANE0</name>          
+		<config>
+			<offset>0x13E</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- PHASE1 lane 1 -->
+		<name>PHASE1_LANE1</name>          
+		<config>
+			<offset>0x13F</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- PHASE2 lane 0 -->
+		<name>PHASE2_LANE0</name>          
+		<config>
+			<offset>0x140</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- PHASE2 lane 1 -->
+		<name>PHASE2_LANE1</name>          
+		<config>
+			<offset>0x141</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+
+
+
+	<BinField>
+		<!-- DLLS_TRIM_1 lane 0 -->
+		<name>DLLS_TRIM_1_LANE0</name>          
+		<config>
+			<offset>0x142</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- DLLS_TRIM_1 lane 1 -->
+		<name>DLLS_TRIM_1_LANE1</name>          
+		<config>
+			<offset>0x143</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+
+
+	<BinField>
+		<!-- DLLS_TRIM_2 lane 0 -->
+		<name>DLLS_TRIM_2_LANE0</name>          
+		<config>
+			<offset>0x144</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- DLLS_TRIM_2 lane 1 -->
+		<name>DLLS_TRIM_2_LANE1</name>          
+		<config>
+			<offset>0x145</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	
+	<BinField>
+		<!-- DLLS_TRIM_3 lane 0 -->
+		<name>DLLS_TRIM_3_LANE0</name>          
+		<config>
+			<offset>0x146</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- DLLS_TRIM_3 lane 1 -->
+		<name>DLLS_TRIM_3_LANE1</name>          
+		<config>
+			<offset>0x147</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+
+
+	<BinField>
+		<!-- DLLS_TRIM_2 OFFSET lane 0 
+			msb: 1 incr, 0 decr
+			[1:7] offset value added\decremented to trim2 after SCL.
+		-->
+		<name>DLLS_TRIM_2_OFFSET_LANE0</name>          
+		<config>
+			<offset>0x148</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- DLLS_TRIM_2 OFFSET lane 1 
+			msb: 1 incr, 0 decr
+			[1:7] offset value added\decremented to trim2 after SCL.
+		-->
+		<name>DLLS_TRIM_2_OFFSET_LANE1</name>          
+		<config>
+			<offset>0x149</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	
+	<BinField>
+		<!-- VREF_SOC lane 0 -->
+		<name>VREF_SOC_LANE0</name>          
+		<config>
+			<offset>0x14A</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	<BinField>
+		<!-- VREF_SOC lane 1 -->
+		<name>VREF_SOC_LANE1</name>          
+		<config>
+			<offset>0x14B</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+	
+	
+	<BinField>
+		<!-- VREF_DRAM -->
+		<name>VREF_DRAM</name>          
+		<config>
+			<offset>0x14C</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0xFF</content>
+	</BinField>
+	
+
+	<BinField>
+		<!-- SWEEP_DEBUG: enable running charectarization sweeps. bitwise:
+				ADRCTL_MA_SWEEP       BIT(0)
+				ADRCTL_SWEEP          BIT(1)
+				TRIM_2_LANE0_SWEEP    BIT(2)
+				TRIM_2_LANE1_SWEEP    BIT(3)
+				VREF_SWEEP            BIT(4)
+				DRAM_SWEEP            BIT(5)
+				OP_DQS_SWEEP          BIT(6)
+				IP_DQS_SWEEP          BIT(7)
+		-->
+		<name>SWEEP_DEBUG</name>          
+		<config>
+			<offset>0x14D</offset>       
+			<size>0x1</size> 
+		</config>
+		<content format='32bit'>0x00</content>
+	</BinField>
+	
+	
+	
+	
+	<BinField>
+		<!-- Code destination address, 32-bit aligned: for BootBlock should be 0xFFFD0000 so code will run in 0xFFFB0200 as linked for -->
+		<name>DestAddr</name>         
+		<config>
+			<offset>0x1F8</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0xFFFD0000</content>     <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- BootBlock or u-boot Code size -->
+		<name>CodeSize</name>         
+		<config>
+			<offset>0x1FC</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='FileSize'>arbel_a35_bootblock.bin</content>	<!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- The BootBlock or u-boot binary file -->
+		<name>Code</name>             
+		<config>
+			<offset>0x200</offset>       
+			<size format='FileSize'>arbel_a35_bootblock.bin</size>                 <!-- size in the header calculated by tool-->
+		</config>
+		<content format='FileContent'>arbel_a35_bootblock.bin</content>  <!-- content the user should fill -->
+	</BinField>
+	
+</Bin_Ecc_Map>
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/KmtAndHeader_EB.xml b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/KmtAndHeader_EB.xml
new file mode 100644
index 0000000..aed8e61
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/KmtAndHeader_EB.xml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- SPDX-License-Identifier: GPL-2.0
+#
+# Nuvoton IGPS: Image Generation And Programming Scripts For Arbel BMC
+#
+# Copyright (C) 2022 Nuvoton Technologies, All Rights Reserved
+#======================================== -->
+
+<Bin_Ecc_Map>
+
+	<!-- BMC mandatory fields -->
+	<ImageProperties>
+		<BinSize>0</BinSize> <!-- If 0 the binary size will be calculated by the tool -->
+		<PadValue>0</PadValue>	<!-- Byte value to pad the empty areas, default is 0 -->
+	</ImageProperties>
+
+	<BinField>
+		<name>Anchor</name> <!-- name of field -->
+		<config>
+			<offset>0</offset>
+			<size>4</size>
+		</config>
+		<content format='bytes'>0x5E 0x4D 0x3B 0x2A</content>  <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<!-- CRC Enabled  (0x1E 0xAB 0xF2 0x57) or
+		     CRC Disabled (0xE1 0x54 0xF2 0x57) -->
+		<name>ExendedAnchor_CrcEn</name>         <!-- name of field -->
+		<config>
+			<offset>4</offset>
+			<size>4</size>
+		</config>
+		<content format='bytes'>0xE1 0x54 0xF2 0x57</content>  <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>FWCrc</name>  <!-- name of field -->
+		<config>
+			<offset>12</offset>
+			<size>4</size>
+		</config>
+		<content format='bytes'>0x00 0x00 0x00 0x00</content>     <!-- will be calculated by IGPS -->
+	</BinField>
+
+	<BinField>
+		<name>SPI0_FlashClock</name>  <!-- name of field -->
+		<config>
+			<offset>112</offset>
+			<size>1</size>
+		</config>
+		<content format='bytes'>0x0F</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>SPI1_FlashClock</name>  <!-- name of field -->
+		<config>
+			<offset>113</offset>
+			<size>1</size>
+		</config>
+		<content format='bytes'>0x0F</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>SPI3_FlashClock</name>  <!-- name of field -->
+		<config>
+			<offset>114</offset>
+			<size>1</size>
+		</config>
+		<content format='bytes'>0x0F</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>SpiFlashReadMode</name>  <!-- name of field -->
+		<config>
+			<offset>118</offset>
+			<size>2</size>
+		</config>
+		<content format='bytes'>0x0B 0x10</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<!-- Code destination address, 32-bit aligned -->
+		<name>FwStartAddr</name>         <!-- name of field -->
+		<config>
+			<offset>120</offset>
+			<size>4</size>
+		</config>
+		<content format='32bit'>0x0005F000</content>     <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<!-- Code size -->
+		<name>FwLength</name>         <!-- name of field -->
+		<config>
+			<offset>132</offset>
+			<size>4</size>
+		</config>
+		<content format='FileSize'>kmt_map.bin</content>	<!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>KeyIndex</name>  <!-- name of field -->
+		<config>
+			<offset>140</offset>
+			<size>4</size>
+		</config>
+		<content format='32bit'>0x1</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>KeyInvalid</name>  <!-- name of field -->
+		<config>
+			<offset>144</offset>
+			<size>4</size>
+		</config>
+		<content format='32bit'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>TipFwEncryptionControl</name>  <!-- name of field -->
+		<config>
+			<offset>148</offset>
+			<size>1</size>
+		</config>
+		<content format='bytes'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>OtpFwVersion</name>  <!-- name of field -->
+		<config>
+			<offset>152</offset>
+			<size>2</size>
+		</config>
+		<content format='bytes'>0x00 0x00</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>fwTableOffset</name>  <!-- name of field -->
+		<config>
+			<offset>168</offset>
+			<size>4</size>
+		</config>
+		<content format='32bit'>0x80001000</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>kmt_map</name>             <!-- name of field -->
+		<config>
+			<offset>256</offset>
+			<size format='FileSize'>kmt_map.bin</size>                 <!-- size in the header calculated by tool-->
+		</config>
+		<content format='FileContent'>kmt_map.bin</content>  <!-- content the user should fill -->
+	</BinField>
+
+</Bin_Ecc_Map>
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/OpTeeAndHeader_EB.xml b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/OpTeeAndHeader_EB.xml
new file mode 100644
index 0000000..88b36da
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/OpTeeAndHeader_EB.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- SPDX-License-Identifier: GPL-2.0
+#
+# Nuvoton IGPS: Image Generation And Programming Scripts For Arbel BMC
+#
+# Copyright (C) 2022 Nuvoton Technologies, All Rights Reserved
+#======================================== -->
+
+<Bin_Ecc_Map>
+	<!-- BMC mandatory fields -->
+	<ImageProperties>
+		<BinSize>0</BinSize>         <!-- If 0 the binary size will be calculated by the tool -->
+		<PadValue>0xFF</PadValue>	<!-- Byte value to pad the empty areas, default is 0 -->
+	</ImageProperties>
+		
+	<BinField>
+		<!-- BootBlock tag (0x50 0x08 0x55 0xAA 0x54 0x4F 0x4F 0x42) or 
+			     uboot tag (0x55 0x42 0x4F 0x4F 0x54 0x42 0x4C 0x4B) -->
+		<name>StartTag</name>         
+		<config>
+			<offset>0</offset>           
+			<size>0x8</size> 
+		</config>
+		<content format='bytes'>0x0A 0x54 0x45 0x45 0x5F 0x4E 0x50 0x43</content>  <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Version (Major.Minor) -->
+		<name>version</name>          
+		<config>
+			<offset>0x100</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- BootBlock or u-boot Code size -->
+		<name>DestAddr</name>         
+		<config>
+			<offset>0x1F8</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='32bit'>0x35FFFDE4</content>	<!-- content the user should fill -->
+	</BinField>
+		
+	<BinField>
+		<!-- BootBlock or u-boot Code size -->
+		<name>CodeSize</name>         
+		<config>
+			<offset>0x1FC</offset>       
+			<size>0x4</size> 
+		</config>
+		<content format='FileSize'>tee.bin</content>	<!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- The BootBlock or u-boot binary file -->
+		<name>Code</name>             
+		<config>
+			<offset>0x200</offset>       
+			<size format='FileSize'>tee.bin</size>                 <!-- size in the header calculated by tool-->
+		</config>
+		<content format='FileContent'>tee.bin</content>  <!-- content the user should fill -->
+	</BinField>
+	
+</Bin_Ecc_Map>
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/TipFwAndHeader_L0_EB.xml b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/TipFwAndHeader_L0_EB.xml
new file mode 100644
index 0000000..e0edf3f
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/TipFwAndHeader_L0_EB.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- SPDX-License-Identifier: GPL-2.0
+#
+# Nuvoton IGPS: Image Generation And Programming Scripts For Arbel BMC
+#
+# Copyright (C) 2022 Nuvoton Technologies, All Rights Reserved
+#======================================== -->
+
+<Bin_Ecc_Map>
+
+	<!-- BMC mandatory fields -->
+	<ImageProperties>
+		<BinSize>0</BinSize> <!-- If 0 the binary size will be calculated by the tool -->
+		<PadValue>0xFF</PadValue>	<!-- Byte value to pad the empty areas, default is 0 -->
+	</ImageProperties>
+
+	<BinField>
+		<name>Anchor</name> <!-- name of field -->
+		<config>
+			<offset>0</offset>
+			<size>4</size>
+		</config>
+		<content format='bytes'>0x5E 0x4D 0x7A 0x9B</content>  <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<!-- CRC Enabled  (0x1E 0xAB 0xF2 0x57) or
+		     CRC Disabled (0xE1 0x54 0xF2 0x57) -->
+		<name>ExendedAnchor_CrcEn</name>         <!-- name of field -->
+		<config>
+			<offset>4</offset>
+			<size>4</size>
+		</config>
+		<content format='bytes'>0xE1 0x54 0xF2 0x57</content>  <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>FWCrc</name>  <!-- name of field -->
+		<config>
+			<offset>12</offset>
+			<size>4</size>
+		</config>
+		<content format='bytes'>0x00 0x00 0x00 0x00</content>     <!-- will be calculated by IGPS -->
+	</BinField>
+
+	<BinField>
+		<!-- Code destination address, 32-bit aligned -->
+		<name>FwStartAddr</name>         <!-- name of field -->
+		<config>
+			<offset>120</offset>
+			<size>4</size>
+		</config>
+		<content format='32bit'>0x00020000</content>     <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<!-- Code size -->
+		<name>FwLength</name>         <!-- name of field -->
+		<config>
+			<offset>132</offset>
+			<size>4</size>
+		</config>
+		<content format='FileSize'>arbel_tip_fw_L0.bin</content>	<!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>KeyIndex</name>  <!-- name of field -->
+		<config>
+			<offset>140</offset>
+			<size>4</size>
+		</config>
+		<content format='32bit'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>OtpFwVersion</name>  <!-- name of field -->
+		<config>
+			<offset>152</offset>
+			<size>2</size>
+		</config>
+		<content format='bytes'>0x00 0x00</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>AesCbcIV</name>  <!-- name of field -->
+		<config>
+			<offset>172</offset>
+			<size>16</size>
+		</config>
+		<content format='bytes'>0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>TipFW</name>             <!-- name of field -->
+		<config>
+			<offset>256</offset>
+			<size format='FileSize'>arbel_tip_fw_L0.bin</size>                 <!-- size in the header calculated by tool-->
+		</config>
+		<content format='FileContent'>arbel_tip_fw_L0.bin</content>  <!-- content the user should fill -->
+	</BinField>
+
+</Bin_Ecc_Map>
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/TipFwAndHeader_L1_EB.xml b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/TipFwAndHeader_L1_EB.xml
new file mode 100644
index 0000000..0db4431
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/TipFwAndHeader_L1_EB.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- SPDX-License-Identifier: GPL-2.0
+#
+# Nuvoton IGPS: Image Generation And Programming Scripts For Arbel BMC
+#
+# Copyright (C) 2022 Nuvoton Technologies, All Rights Reserved
+#======================================== -->
+
+<Bin_Ecc_Map>
+
+	<!-- BMC mandatory fields -->
+	<ImageProperties>
+		<BinSize>0</BinSize> <!-- If 0 the binary size will be calculated by the tool -->
+		<PadValue>0xFF</PadValue>	<!-- Byte value to pad the empty areas, default is 0 -->
+	</ImageProperties>
+		
+	<BinField>
+		<!-- tip_fw_L1 tag (0x0A 0x54 0x49 0x50 0x5F 0x4C 0x31 0x0A) -->
+		<name>StartTag</name>         <!-- name of field -->
+		<config>
+			<offset>0</offset>            <!-- offset in the header -->
+			<size>0x8</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0x0A 0x54 0x49 0x50 0x5F 0x4C 0x31 0x0A</content>
+	</BinField>
+	
+
+
+
+
+	<BinField>
+		<name>FWCrc</name>  <!-- name of field -->
+		<config>
+			<offset>12</offset>
+			<size>4</size>
+		</config>
+		<content format='bytes'>0x00 0x00 0x00 0x00</content>     <!-- will be calculated by IGPS -->
+	</BinField>
+
+
+	<BinField>
+		<name>KeyIndex</name>  <!-- name of field -->
+		<config>
+			<offset>140</offset>
+			<size>4</size>
+		</config>
+		<content format='32bit'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>OtpFwVersion</name>  <!-- name of field -->
+		<config>
+			<offset>152</offset>
+			<size>2</size>
+		</config>
+		<content format='bytes'>0x00 0x00</content>               <!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<!-- Code destination address, 32-bit aligned -->
+		<name>DestAddr_L1</name>         <!-- name of field -->
+		<config>
+			<offset>0x1F8</offset>        <!-- offset in the header -->
+			<size>0x4</size>              <!-- size in the header -->
+		</config>
+		<content format='32bit'>0x40000</content>  <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- BootBlock or u-boot Code size -->
+		<name>CodeSize_L1</name>         <!-- name of field -->
+		<config>
+			<offset>0x1FC</offset>        <!-- offset in the header -->
+			<size>0x4</size>              <!-- size in the header -->
+		</config>
+		<content format='FileSize'>arbel_tip_fw_L1.bin</content>	<!-- content the user should fill -->
+	</BinField>
+
+	<BinField>
+		<name>TipFW_L1</name>             <!-- name of field -->
+		<config>
+			<offset>0x200</offset>
+			<size format='FileSize'>arbel_tip_fw_L1.bin</size>                 <!-- size in the header calculated by tool-->
+		</config>
+		<content format='FileContent'>arbel_tip_fw_L1.bin</content>  <!-- content the user should fill -->
+	</BinField>
+
+</Bin_Ecc_Map>
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/UbootHeader_EB.xml b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/UbootHeader_EB.xml
new file mode 100644
index 0000000..9ab23c7
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-igps/UbootHeader_EB.xml
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- SPDX-License-Identifier: GPL-2.0
+#
+# Nuvoton IGPS: Image Generation And Programming Scripts For Arbel BMC
+#
+# Copyright (C) 2022 Nuvoton Technologies, All Rights Reserved
+#======================================== -->
+
+<Bin_Ecc_Map>
+	<!-- BMC mandatory fields -->
+	<ImageProperties>
+		<BinSize>0</BinSize>         <!-- If 0 the binary size will be calculated by the tool -->
+		<PadValue>0xFF</PadValue>	<!-- Byte value to pad the empty areas, default is 0 -->
+	</ImageProperties>
+		
+	<BinField>
+		<!-- uboot tag (0x0A 0x55 0x42 0x4F 0x4F 0x54 0x42 0x4C) -->
+		<name>StartTag</name>         <!-- name of field -->
+		<config>
+			<offset>0</offset>            <!-- offset in the header -->
+			<size>0x8</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0x0A 0x55 0x42 0x4F 0x4F 0x54 0x42 0x4C</content>
+	</BinField>
+	
+	<!-- BMC optional fields -->
+	<BinField>
+		<!-- Word contents copied by ROM code to FIU0 FIU_DRD_CFG register -->
+		<name>FIU0_DRD_CFG_Set</name>  <!-- name of field -->
+		<config>
+			<offset>0x108</offset>        <!-- offset in the header -->
+			<size>0x4</size>              <!-- size in the header -->
+		</config>
+		<content format='32bit'>0x030111BC</content>               <!-- content the user should fill 0x030032EB -->
+	</BinField>
+	
+	<BinField>
+		<!-- Defines the clock divide ratio from AHB to FIU0 clock -->
+		<name>FIU0_Clk_Divider</name>  <!-- name of field -->
+		<config>
+			<offset>0x10C</offset>        <!-- offset in the header -->
+			<size>0x1</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Defines if FIU0 CS1 is enabled -->
+		<name>fiu0_cs1_en</name>  <!-- name of field -->
+		<config>
+			<offset>0x10D</offset>        <!-- offset in the header -->
+			<size>0x1</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Defines if FIU0 CS2 is enabled -->
+		<name>fiu0_cs2_en</name>  <!-- name of field -->
+		<config>
+			<offset>0x10E</offset>        <!-- offset in the header -->
+			<size>0x1</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Defines if FIU0 CS3 is enabled -->
+		<name>fiu0_cs3_en</name>  <!-- name of field -->
+		<config>
+			<offset>0x10F</offset>        <!-- offset in the header -->
+			<size>0x1</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<!-- BMC optional fields -->
+	<BinField>
+		<!-- Word contents copied by ROM code to FIU3 FIU_DRD_CFG register -->
+		<name>FIU3_DRD_CFG_Set</name>  <!-- name of field -->
+		<config>
+			<offset>0x110</offset>        <!-- offset in the header -->
+			<size>0x4</size>              <!-- size in the header -->
+		</config>
+		<content format='32bit'>0x030011BB</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<!-- BMC optional fields -->
+	<BinField>
+		<!-- Word contents copied by ROM code to FIU3 FIU_DRD_CFG register -->
+		<name>FIU3_DWR_CFG_Set</name>  <!-- name of field -->
+		<config>
+			<offset>0x114</offset>        <!-- offset in the header -->
+			<size>0x4</size>              <!-- size in the header -->
+		</config>
+		<content format='32bit'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Defines the clock divide ratio from AHB to FIU3 clock -->
+		<name>FIU3_Clk_Divider</name>  <!-- name of field -->
+		<config>
+			<offset>0x118</offset>        <!-- offset in the header -->
+			<size>0x1</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+
+	<BinField>
+		<!-- Defines if FIU3 CS1 is enabled -->
+		<name>fiu3_cs1_en</name>  <!-- name of field -->
+		<config>
+			<offset>0x119</offset>        <!-- offset in the header -->
+			<size>0x1</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Defines if FIU3 CS2 is enabled -->
+		<name>fiu3_cs2_en</name>  <!-- name of field -->
+		<config>
+			<offset>0x11A</offset>        <!-- offset in the header -->
+			<size>0x1</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Defines if FIU3 CS3 is enabled -->
+		<name>fiu3_cs3_en</name>  <!-- name of field -->
+		<config>
+			<offset>0x11B</offset>        <!-- offset in the header -->
+			<size>0x1</size>              <!-- size in the header -->
+		</config>
+		<content format='bytes'>0x0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Version (Major.Minor) -->
+		<name>Version</name>          <!-- name of field -->
+		<config>
+			<offset>0x148</offset>        <!-- offset in the header -->
+			<size>0x4</size>              <!-- size in the header -->
+		</config>
+		<content format='32bit'>0</content>               <!-- content the user should fill -->
+	</BinField>
+	
+		<!-- BMC optional fields -->
+	<BinField>
+		<!-- Word contents copied by BB code to FIU0 FIU_DWR_CFG register -->
+		<name>FIU0_DWR_CFG_Set</name>  <!-- name of field -->
+		<config>
+			<offset>0x14C</offset>        <!-- offset in the header -->
+			<size>0x4</size>              <!-- size in the header -->
+		</config>
+		<content format='32bit'>0x03001102</content>               <!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- Code destination address, 32-bit aligned -->
+		<name>DestAddr</name>         <!-- name of field -->
+		<config>
+			<offset>0x1F8</offset>        <!-- offset in the header -->
+			<size>0x4</size>              <!-- size in the header -->
+		</config>
+		<content format='32bit'>0x7E00</content>  <!-- including uboot header. uboot image starts at 0x8000 -->
+	</BinField>
+	
+	<BinField>
+		<!-- BootBlock or u-boot Code size -->
+		<name>CodeSize</name>         <!-- name of field -->
+		<config>
+			<offset>0x1FC</offset>        <!-- offset in the header -->
+			<size>0x4</size>              <!-- size in the header -->
+		</config>
+		<content format='FileSize'>u-boot.bin</content>	<!-- content the user should fill -->
+	</BinField>
+	
+	<BinField>
+		<!-- The BootBlock or u-boot binary file -->
+		<name>Code</name>             <!-- name of field -->
+		<config>
+			<offset>0x200</offset>        <!-- offset in the header -->
+			<size format='FileSize'>u-boot.bin</size>                 <!-- size in the header calculated by tool-->
+		</config>
+		<content format='FileContent'>u-boot.bin</content>  <!-- content the user should fill -->
+	</BinField>	
+	
+	
+	
+</Bin_Ecc_Map>
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt-tipfwl0l1/Kmt_TipFwL0_TipFwL1.bin b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt-tipfwl0l1/Kmt_TipFwL0_TipFwL1.bin
new file mode 100644
index 0000000..f64834c
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt-tipfwl0l1/Kmt_TipFwL0_TipFwL1.bin
Binary files differ
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt-tipfwl0l1_git.bb b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt-tipfwl0l1_git.bb
new file mode 100644
index 0000000..0c2099a
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt-tipfwl0l1_git.bb
@@ -0,0 +1,15 @@
+LICENSE = "CLOSED"
+
+SRC_URI = " \
+    file://Kmt_TipFwL0_TipFwL1.bin \
+"
+
+S = "${WORKDIR}"
+
+inherit deploy
+
+do_deploy () {
+	install -D -m 644 ${S}/Kmt_TipFwL0_TipFwL1.bin ${DEPLOYDIR}/Kmt_TipFwL0_TipFwL1.bin
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt/kmt_map.bin b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt/kmt_map.bin
new file mode 100644
index 0000000..d3351de
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt/kmt_map.bin
Binary files differ
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt_git.bb b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt_git.bb
new file mode 100644
index 0000000..dbe86a5
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-kmt_git.bb
@@ -0,0 +1,15 @@
+LICENSE = "CLOSED"
+
+SRC_URI = " \
+    file://kmt_map.bin \
+"
+
+S = "${WORKDIR}"
+
+inherit deploy
+
+do_deploy () {
+	install -D -m 644 ${S}/kmt_map.bin ${DEPLOYDIR}/kmt_map.bin
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l0/arbel_tip_fw_l0.0.2.2.bin b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l0/arbel_tip_fw_l0.0.2.2.bin
new file mode 100644
index 0000000..fe74d3d
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l0/arbel_tip_fw_l0.0.2.2.bin
Binary files differ
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l0_0.2.2.bb b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l0_0.2.2.bb
new file mode 100644
index 0000000..fcd3a33
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l0_0.2.2.bb
@@ -0,0 +1,15 @@
+LICENSE = "CLOSED"
+
+SRC_URI = " \
+    file://arbel_tip_fw_l0.${PV}.bin \
+"
+
+S = "${WORKDIR}"
+
+inherit deploy
+
+do_deploy () {
+	install -D -m 644 ${S}/arbel_tip_fw_l0.${PV}.bin ${DEPLOYDIR}/arbel_tip_fw_L0.bin
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l1/arbel_tip_fw_l1.0.0.7.bin b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l1/arbel_tip_fw_l1.0.0.7.bin
new file mode 100644
index 0000000..8781b6e
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l1/arbel_tip_fw_l1.0.0.7.bin
Binary files differ
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l1_0.0.7.bb b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l1_0.0.7.bb
new file mode 100644
index 0000000..a850701
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/images/npcm8xx-tipfw-l1_0.0.7.bb
@@ -0,0 +1,15 @@
+LICENSE = "CLOSED"
+
+SRC_URI = " \
+    file://arbel_tip_fw_l1.${PV}.bin \
+"
+
+S = "${WORKDIR}"
+
+inherit deploy
+
+do_deploy () {
+	install -D -m 644 ${S}/arbel_tip_fw_l1.${PV}.bin ${DEPLOYDIR}/arbel_tip_fw_L1.bin
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/files/u-boot-emmc.cfg b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/files/u-boot-emmc.cfg
new file mode 100644
index 0000000..4bc6522
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/files/u-boot-emmc.cfg
@@ -0,0 +1,5 @@
+CONFIG_CMD_EXT4=y
+CONFIG_CMD_FS_GENERIC=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_PART=y
+CONFIG_CMD_UNZIP=y
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/files/u-boot-env-emmc.txt b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/files/u-boot-env-emmc.txt
new file mode 100644
index 0000000..8668db5
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/files/u-boot-env-emmc.txt
@@ -0,0 +1,12 @@
+autoload=no
+autostart=no
+bootargs=earlycon=uart8250,mmio32,0xf0001000 console=ttyS0,115200n8 mem=464M
+bootcmd=setenv origbootargs ${bootargs}; run mmc_bootargs; run bootsidecmd
+setmmcargs=setenv bootargs ${bootargs} rootwait root=PARTLABEL=${rootfs}
+mmc_bootargs=setenv bootargs earlycon=${earlycon} console=${console} mem=${mem}
+boota=setenv bootpart 2; setenv rootfs rofs-a; run bootmmc
+bootb=setenv bootpart 3; setenv rootfs rofs-b; run bootmmc
+bootmmc=run setmmcargs; ext4load mmc 1:${bootpart} ${loadaddr} fitImage && bootm; echo Error loading kernel FIT image
+bootsidecmd=if test ${bootside} = b; then run bootb; run boota; else run boota; run bootb; fi
+bootside=a
+loadaddr=0x1200000
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-common-nuvoton.inc b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-common-nuvoton.inc
new file mode 100644
index 0000000..087c87f
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-common-nuvoton.inc
@@ -0,0 +1,14 @@
+HOMEPAGE = "https://github.com/Nuvoton-Israel/u-boot"
+SECTION = "bootloaders"
+DEPENDS += "flex-native bison-native"
+
+LICENSE = "GPL-2.0-or-later"
+LIC_FILES_CHKSUM = "file://Licenses/README;md5=5a7450c57ffe5ae63fd732446b988025"
+
+UBRANCH = "npcm-v2021.04"
+SRC_URI = "git://github.com/Nuvoton-Israel/u-boot.git;branch=${UBRANCH};protocol=https"
+SRCREV = "c07f3f27389626f366f06bea467ad7b6c3c0060d"
+
+S = "${WORKDIR}/git"
+
+PV .= "+${UBRANCH}+"
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-emmc.inc b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-emmc.inc
new file mode 100644
index 0000000..1001ee8
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-emmc.inc
@@ -0,0 +1,16 @@
+# SPI uboot image should support eMMC
+SRC_URI:append = " file://u-boot-emmc.cfg"
+SRC_URI:append:df-phosphor-mmc = " file://u-boot-env-emmc.txt"
+
+UBOOT_ENV_SIZE:df-phosphor-mmc = "0x40000"
+UBOOT_ENV:df-phosphor-mmc = "u-boot-env"
+UBOOT_ENV_SUFFIX:df-phosphor-mmc = "bin"
+UBOOT_ENV_TXT:df-phosphor-mmc = "u-boot-env-emmc.txt"
+
+do_compile:append() {
+    if [ -n "${UBOOT_ENV}" ]
+    then
+        # Generate redundant environment image
+        ${B}/tools/mkenvimage -s ${UBOOT_ENV_SIZE} -p 0 -o ${WORKDIR}/${UBOOT_ENV_BINARY} ${WORKDIR}/${UBOOT_ENV_TXT}
+    fi
+}
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-fw-utils-nuvoton_git.bb b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-fw-utils-nuvoton_git.bb
new file mode 100644
index 0000000..4ccfdd1
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-fw-utils-nuvoton_git.bb
@@ -0,0 +1,40 @@
+require u-boot-common-nuvoton.inc
+
+SUMMARY = "U-Boot bootloader fw_printenv/setenv utilities"
+DEPENDS = "mtd-utils bison-native"
+
+PROVIDES += "u-boot-fw-utils"
+
+INSANE_SKIP:${PN} = "already-stripped"
+
+EXTRA_OEMAKE:class-target = 'CROSS_COMPILE="${TARGET_PREFIX}" HOSTCC="${BUILD_CC} ${BUILD_FLAGS} ${BUILD_LDFLAGS}" CC="${CC} ${CFLAGS} ${LDFLAGS}" STRIP=true V=1'
+EXTRA_OEMAKE:class-cross = 'ARCH=${TARGET_ARCH} CC="${CC} ${CFLAGS} ${LDFLAGS}" V=1'
+
+inherit uboot-config
+
+do_compile () {
+  oe_runmake ${UBOOT_MACHINE}
+  oe_runmake envtools
+}
+
+do_install () {
+  install -d ${D}${base_sbindir}
+  install -d ${D}${sysconfdir}
+  install -m 755 ${S}/tools/env/fw_printenv ${D}${base_sbindir}/fw_printenv
+  install -m 755 ${S}/tools/env/fw_printenv ${D}${base_sbindir}/fw_setenv
+  install -m 0644 ${S}/tools/env/fw_env.config ${D}${sysconfdir}/fw_env.config
+}
+
+do_install:class-cross () {
+  install -d ${D}${bindir_cross}
+  install -m 755 ${S}/tools/env/fw_printenv ${D}${bindir_cross}/fw_printenv
+  install -m 755 ${S}/tools/env/fw_printenv ${D}${bindir_cross}/fw_setenv
+}
+
+SYSROOT_PREPROCESS_FUNCS:class-cross = "uboot_fw_utils_cross"
+uboot_fw_utils_cross() {
+	sysroot_stage_dir ${D}${bindir_cross} ${SYSROOT_DESTDIR}${bindir_cross}
+}
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+BBCLASSEXTEND = "cross"
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-nuvoton.inc b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-nuvoton.inc
new file mode 100644
index 0000000..40fb5ad
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-nuvoton.inc
@@ -0,0 +1,337 @@
+SUMMARY = "Universal Boot Loader for embedded devices"
+PROVIDES = "virtual/bootloader"
+
+B = "${WORKDIR}/build"
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+DEPENDS += "kern-tools-native"
+
+inherit uboot-config uboot-extlinux-config uboot-sign deploy cml1 python3native
+
+DEPENDS += "swig-native"
+
+EXTRA_OEMAKE = 'CROSS_COMPILE=${TARGET_PREFIX} CC="${TARGET_PREFIX}gcc ${TOOLCHAIN_OPTIONS}" V=1'
+EXTRA_OEMAKE += 'HOSTCC="${BUILD_CC} ${BUILD_CFLAGS} ${BUILD_LDFLAGS}"'
+EXTRA_OEMAKE += 'STAGING_INCDIR=${STAGING_INCDIR_NATIVE} STAGING_LIBDIR=${STAGING_LIBDIR_NATIVE}'
+
+PACKAGECONFIG ??= "openssl"
+# u-boot will compile its own tools during the build, with specific
+# configurations (aka when CONFIG_FIT_SIGNATURE is enabled) openssl is needed as
+# a host build dependency.
+PACKAGECONFIG[openssl] = ",,openssl-native"
+
+# Allow setting an additional version string that will be picked up by the
+# u-boot build system and appended to the u-boot version.  If the .scmversion
+# file already exists it will not be overwritten.
+UBOOT_LOCALVERSION ?= ""
+
+# Some versions of u-boot use .bin and others use .img.  By default use .bin
+# but enable individual recipes to change this value.
+UBOOT_SUFFIX ??= "bin"
+UBOOT_IMAGE ?= "u-boot-${MACHINE}-${PV}-${PR}.${UBOOT_SUFFIX}"
+UBOOT_SYMLINK ?= "u-boot-${MACHINE}.${UBOOT_SUFFIX}"
+UBOOT_MAKE_TARGET ?= "all"
+
+# Output the ELF generated. Some platforms can use the ELF file and directly
+# load it (JTAG booting, QEMU) additionally the ELF can be used for debugging
+# purposes.
+UBOOT_ELF ?= ""
+UBOOT_ELF_SUFFIX ?= "elf"
+UBOOT_ELF_IMAGE ?= "u-boot-${MACHINE}-${PV}-${PR}.${UBOOT_ELF_SUFFIX}"
+UBOOT_ELF_BINARY ?= "u-boot.${UBOOT_ELF_SUFFIX}"
+UBOOT_ELF_SYMLINK ?= "u-boot-${MACHINE}.${UBOOT_ELF_SUFFIX}"
+
+# Some versions of u-boot build an SPL (Second Program Loader) image that
+# should be packaged along with the u-boot binary as well as placed in the
+# deploy directory.  For those versions they can set the following variables
+# to allow packaging the SPL.
+SPL_BINARY ?= ""
+SPL_BINARYNAME ?= "${@os.path.basename(d.getVar("SPL_BINARY"))}"
+SPL_IMAGE ?= "${SPL_BINARYNAME}-${MACHINE}-${PV}-${PR}"
+SPL_SYMLINK ?= "${SPL_BINARYNAME}-${MACHINE}"
+
+# Additional environment variables or a script can be installed alongside
+# u-boot to be used automatically on boot.  This file, typically 'uEnv.txt'
+# or 'boot.scr', should be packaged along with u-boot as well as placed in the
+# deploy directory.  Machine configurations needing one of these files should
+# include it in the SRC_URI and set the UBOOT_ENV parameter.
+UBOOT_ENV_SUFFIX ?= "txt"
+UBOOT_ENV ?= ""
+UBOOT_ENV_BINARY ?= "${UBOOT_ENV}.${UBOOT_ENV_SUFFIX}"
+UBOOT_ENV_IMAGE ?= "${UBOOT_ENV}-${MACHINE}-${PV}-${PR}.${UBOOT_ENV_SUFFIX}"
+UBOOT_ENV_SYMLINK ?= "${UBOOT_ENV}-${MACHINE}.${UBOOT_ENV_SUFFIX}"
+
+# U-Boot EXTLINUX variables. U-Boot searches for /boot/extlinux/extlinux.conf
+# to find EXTLINUX conf file.
+UBOOT_EXTLINUX_INSTALL_DIR ?= "/boot/extlinux"
+UBOOT_EXTLINUX_CONF_NAME ?= "extlinux.conf"
+UBOOT_EXTLINUX_SYMLINK ?= "${UBOOT_EXTLINUX_CONF_NAME}-${MACHINE}-${PR}"
+
+# Set Device tree from the machine config automatically
+UBOOT_MAKE_TARGET += '${@"" if d.getVar("UBOOT_DEVICETREE") is None \
+    else " DEVICE_TREE=" + d.getVar("UBOOT_DEVICETREE")}'
+
+# returns all the elements from the src uri that are .cfg files
+def find_cfgs(d):
+    sources=src_patches(d, True)
+    sources_list=[]
+    for s in sources:
+        if s.endswith('.cfg'):
+            sources_list.append(s)
+
+    return sources_list
+
+do_configure () {
+    if [ -z "${UBOOT_CONFIG}" ]; then
+        if [ -n "${UBOOT_MACHINE}" ]; then
+            oe_runmake -C ${S} O=${B} ${UBOOT_MACHINE}
+        else
+            oe_runmake -C ${S} O=${B} oldconfig
+        fi
+        merge_config.sh -m .config ${@" ".join(find_cfgs(d))}
+        cml1_do_configure
+    fi
+}
+
+do_compile () {
+	if [ "${@bb.utils.filter('DISTRO_FEATURES', 'ld-is-gold', d)}" ]; then
+		sed -i 's/$(CROSS_COMPILE)ld$/$(CROSS_COMPILE)ld.bfd/g' ${S}/config.mk
+	fi
+
+	unset LDFLAGS
+	unset CFLAGS
+	unset CPPFLAGS
+
+	if [ ! -e ${B}/.scmversion -a ! -e ${S}/.scmversion ]
+	then
+		echo ${UBOOT_LOCALVERSION} > ${B}/.scmversion
+		echo ${UBOOT_LOCALVERSION} > ${S}/.scmversion
+	fi
+
+    if [ -n "${UBOOT_CONFIG}" ]
+    then
+        unset i j k
+        for config in ${UBOOT_MACHINE}; do
+            i=$(expr $i + 1);
+            for type in ${UBOOT_CONFIG}; do
+                j=$(expr $j + 1);
+                if [ $j -eq $i ]
+                then
+                    oe_runmake -C ${S} O=${B}/${config} ${config}
+                    oe_runmake -C ${S} O=${B}/${config} ${UBOOT_MAKE_TARGET}
+                    for binary in ${UBOOT_BINARIES}; do
+                        k=$(expr $k + 1);
+                        if [ $k -eq $i ]; then
+                            cp ${B}/${config}/${binary} ${B}/${config}/u-boot-${type}.${UBOOT_SUFFIX}
+                        fi
+                    done
+                    unset k
+                fi
+            done
+            unset  j
+        done
+        unset  i
+    else
+        oe_runmake -C ${S} O=${B} ${UBOOT_MAKE_TARGET}
+    fi
+
+}
+
+do_install () {
+    if [ -n "${UBOOT_CONFIG}" ]
+    then
+        for config in ${UBOOT_MACHINE}; do
+            i=$(expr $i + 1);
+            for type in ${UBOOT_CONFIG}; do
+                j=$(expr $j + 1);
+                if [ $j -eq $i ]
+                then
+                    install -d ${D}/boot
+                    install -m 644 ${B}/${config}/u-boot-${type}.${UBOOT_SUFFIX} ${D}/boot/u-boot-${type}-${PV}-${PR}.${UBOOT_SUFFIX}
+                    ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_SUFFIX} ${D}/boot/${UBOOT_BINARY}-${type}
+                    ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_SUFFIX} ${D}/boot/${UBOOT_BINARY}
+                fi
+            done
+            unset  j
+        done
+        unset  i
+    else
+        install -d ${D}/boot
+        install -m 644 ${B}/${UBOOT_BINARY} ${D}/boot/${UBOOT_IMAGE}
+        ln -sf ${UBOOT_IMAGE} ${D}/boot/${UBOOT_BINARY}
+    fi
+
+    if [ -n "${UBOOT_ELF}" ]
+    then
+        if [ -n "${UBOOT_CONFIG}" ]
+        then
+            for config in ${UBOOT_MACHINE}; do
+                i=$(expr $i + 1);
+                for type in ${UBOOT_CONFIG}; do
+                    j=$(expr $j + 1);
+                    if [ $j -eq $i ]
+                    then
+                        install -m 644 ${B}/${config}/${UBOOT_ELF} ${D}/boot/u-boot-${type}-${PV}-${PR}.${UBOOT_ELF_SUFFIX}
+                        ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_ELF_SUFFIX} ${D}/boot/${UBOOT_BINARY}-${type}
+                        ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_ELF_SUFFIX} ${D}/boot/${UBOOT_BINARY}
+                    fi
+                done
+                unset j
+            done
+            unset i
+        else
+            install -m 644 ${B}/${UBOOT_ELF} ${D}/boot/${UBOOT_ELF_IMAGE}
+            ln -sf ${UBOOT_ELF_IMAGE} ${D}/boot/${UBOOT_ELF_BINARY}
+        fi
+    fi
+
+    if [ -e ${WORKDIR}/fw_env.config ] ; then
+        install -d ${D}${sysconfdir}
+        install -m 644 ${WORKDIR}/fw_env.config ${D}${sysconfdir}/fw_env.config
+    fi
+
+    if [ -n "${SPL_BINARY}" ]
+    then
+        if [ -n "${UBOOT_CONFIG}" ]
+        then
+            for config in ${UBOOT_MACHINE}; do
+                i=$(expr $i + 1);
+                for type in ${UBOOT_CONFIG}; do
+                    j=$(expr $j + 1);
+                    if [ $j -eq $i ]
+                    then
+                         install -m 644 ${B}/${config}/${SPL_BINARY} ${D}/boot/${SPL_IMAGE}-${type}-${PV}-${PR}
+                         ln -sf ${SPL_IMAGE}-${type}-${PV}-${PR} ${D}/boot/${SPL_BINARYNAME}-${type}
+                         ln -sf ${SPL_IMAGE}-${type}-${PV}-${PR} ${D}/boot/${SPL_BINARYNAME}
+                    fi
+                done
+                unset  j
+            done
+            unset  i
+        else
+            install -m 644 ${B}/${SPL_BINARY} ${D}/boot/${SPL_IMAGE}
+            ln -sf ${SPL_IMAGE} ${D}/boot/${SPL_BINARYNAME}
+        fi
+    fi
+
+    if [ -n "${UBOOT_ENV}" ]
+    then
+        install -m 644 ${WORKDIR}/${UBOOT_ENV_BINARY} ${D}/boot/${UBOOT_ENV_IMAGE}
+        ln -sf ${UBOOT_ENV_IMAGE} ${D}/boot/${UBOOT_ENV_BINARY}
+    fi
+
+    if [ "${UBOOT_EXTLINUX}" = "1" ]
+    then
+        install -Dm 0644 ${UBOOT_EXTLINUX_CONFIG} ${D}/${UBOOT_EXTLINUX_INSTALL_DIR}/${UBOOT_EXTLINUX_CONF_NAME}
+    fi
+
+}
+
+FILES:${PN} = "/boot ${sysconfdir} ${datadir}"
+
+do_deploy () {
+    if [ -n "${UBOOT_CONFIG}" ]
+    then
+        for config in ${UBOOT_MACHINE}; do
+            i=$(expr $i + 1);
+            for type in ${UBOOT_CONFIG}; do
+                j=$(expr $j + 1);
+                if [ $j -eq $i ]
+                then
+                    install -d ${DEPLOYDIR}
+                    install -m 644 ${B}/${config}/u-boot-${type}.${UBOOT_SUFFIX} ${DEPLOYDIR}/u-boot-${type}-${PV}-${PR}.${UBOOT_SUFFIX}
+                    cd ${DEPLOYDIR}
+                    ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_SUFFIX} ${UBOOT_SYMLINK}-${type}
+                    ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_SUFFIX} ${UBOOT_SYMLINK}
+                    ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_SUFFIX} ${UBOOT_BINARY}-${type}
+                    ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_SUFFIX} ${UBOOT_BINARY}
+                fi
+            done
+            unset  j
+        done
+        unset  i
+    else
+        install -d ${DEPLOYDIR}
+        install -m 644 ${B}/${UBOOT_BINARY} ${DEPLOYDIR}/${UBOOT_IMAGE}
+        cd ${DEPLOYDIR}
+        rm -f ${UBOOT_BINARY} ${UBOOT_SYMLINK}
+        ln -sf ${UBOOT_IMAGE} ${UBOOT_SYMLINK}
+        ln -sf ${UBOOT_IMAGE} ${UBOOT_BINARY}
+    fi
+
+    if [ -n "${UBOOT_ELF}" ]
+    then
+        if [ -n "${UBOOT_CONFIG}" ]
+        then
+            for config in ${UBOOT_MACHINE}; do
+                i=$(expr $i + 1);
+                for type in ${UBOOT_CONFIG}; do
+                    j=$(expr $j + 1);
+                    if [ $j -eq $i ]
+                    then
+                        install -m 644 ${B}/${config}/${UBOOT_ELF} ${DEPLOYDIR}/u-boot-${type}-${PV}-${PR}.${UBOOT_ELF_SUFFIX}
+                        ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_ELF_SUFFIX} ${DEPLOYDIR}/${UBOOT_ELF_BINARY}-${type}
+                        ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_ELF_SUFFIX} ${DEPLOYDIR}/${UBOOT_ELF_BINARY}
+                        ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_ELF_SUFFIX} ${DEPLOYDIR}/${UBOOT_ELF_SYMLINK}-${type}
+                        ln -sf u-boot-${type}-${PV}-${PR}.${UBOOT_ELF_SUFFIX} ${DEPLOYDIR}/${UBOOT_ELF_SYMLINK}
+                    fi
+                done
+                unset j
+            done
+            unset i
+        else
+            install -m 644 ${B}/${UBOOT_ELF} ${DEPLOYDIR}/${UBOOT_ELF_IMAGE}
+            ln -sf ${UBOOT_ELF_IMAGE} ${DEPLOYDIR}/${UBOOT_ELF_BINARY}
+            ln -sf ${UBOOT_ELF_IMAGE} ${DEPLOYDIR}/${UBOOT_ELF_SYMLINK}
+        fi
+    fi
+
+
+     if [ -n "${SPL_BINARY}" ]
+     then
+        if [ -n "${UBOOT_CONFIG}" ]
+        then
+            for config in ${UBOOT_MACHINE}; do
+                i=$(expr $i + 1);
+                for type in ${UBOOT_CONFIG}; do
+                    j=$(expr $j + 1);
+                    if [ $j -eq $i ]
+                    then
+                        install -m 644 ${B}/${config}/${SPL_BINARY} ${DEPLOYDIR}/${SPL_IMAGE}-${type}-${PV}-${PR}
+                        rm -f ${DEPLOYDIR}/${SPL_BINARYNAME} ${DEPLOYDIR}/${SPL_SYMLINK}-${type}
+                        ln -sf ${SPL_IMAGE}-${type}-${PV}-${PR} ${DEPLOYDIR}/${SPL_BINARYNAME}-${type}
+                        ln -sf ${SPL_IMAGE}-${type}-${PV}-${PR} ${DEPLOYDIR}/${SPL_BINARYNAME}
+                        ln -sf ${SPL_IMAGE}-${type}-${PV}-${PR} ${DEPLOYDIR}/${SPL_SYMLINK}-${type}
+                        ln -sf ${SPL_IMAGE}-${type}-${PV}-${PR} ${DEPLOYDIR}/${SPL_SYMLINK}
+                    fi
+                done
+                unset  j
+            done
+            unset  i
+        else
+            install -m 644 ${B}/${SPL_BINARY} ${DEPLOYDIR}/${SPL_IMAGE}
+            rm -f ${DEPLOYDIR}/${SPL_BINARYNAME} ${DEPLOYDIR}/${SPL_SYMLINK}
+            ln -sf ${SPL_IMAGE} ${DEPLOYDIR}/${SPL_BINARYNAME}
+            ln -sf ${SPL_IMAGE} ${DEPLOYDIR}/${SPL_SYMLINK}
+        fi
+    fi
+
+
+    if [ -n "${UBOOT_ENV}" ]
+    then
+        install -m 644 ${WORKDIR}/${UBOOT_ENV_BINARY} ${DEPLOYDIR}/${UBOOT_ENV_IMAGE}
+        rm -f ${DEPLOYDIR}/${UBOOT_ENV_BINARY} ${DEPLOYDIR}/${UBOOT_ENV_SYMLINK}
+        ln -sf ${UBOOT_ENV_IMAGE} ${DEPLOYDIR}/${UBOOT_ENV_BINARY}
+        ln -sf ${UBOOT_ENV_IMAGE} ${DEPLOYDIR}/${UBOOT_ENV_SYMLINK}
+    fi
+
+    if [ "${UBOOT_EXTLINUX}" = "1" ]
+    then
+        install -m 644 ${UBOOT_EXTLINUX_CONFIG} ${DEPLOYDIR}/${UBOOT_EXTLINUX_SYMLINK}
+        ln -sf ${UBOOT_EXTLINUX_SYMLINK} ${DEPLOYDIR}/${UBOOT_EXTLINUX_CONF_NAME}-${MACHINE}
+        ln -sf ${UBOOT_EXTLINUX_SYMLINK} ${DEPLOYDIR}/${UBOOT_EXTLINUX_CONF_NAME}
+    fi
+}
+
+addtask deploy before do_build after do_compile
diff --git a/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-nuvoton_git.bb b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-nuvoton_git.bb
new file mode 100644
index 0000000..3ecb4a4
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-bsp/u-boot/u-boot-nuvoton_git.bb
@@ -0,0 +1,8 @@
+DESCRIPTION = "U-boot for Nuvoton NPCM7xx Baseboard Management Controller"
+
+require u-boot-common-nuvoton.inc
+require u-boot-nuvoton.inc
+
+PROVIDES += "u-boot"
+
+DEPENDS += "dtc-native"
diff --git a/meta-nuvoton-npcm8xx/recipes-connectivity/openssl/openssl_%.bbappend b/meta-nuvoton-npcm8xx/recipes-connectivity/openssl/openssl_%.bbappend
new file mode 100644
index 0000000..2557052
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-connectivity/openssl/openssl_%.bbappend
@@ -0,0 +1 @@
+EXTRA_OECONF:class-native:append = " no-module"
diff --git a/meta-nuvoton-npcm8xx/recipes-core/udev/udev-nuvoton-mtd-partitions.bb b/meta-nuvoton-npcm8xx/recipes-core/udev/udev-nuvoton-mtd-partitions.bb
new file mode 100644
index 0000000..21991b7
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-core/udev/udev-nuvoton-mtd-partitions.bb
@@ -0,0 +1,15 @@
+SUMMARY = "udev rules for MTD partitions"
+DESCRIPTION = "udev rules for MTD partitions"
+PR = "r1"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://${COREBASE}/meta/files/common-licenses/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10"
+
+S = "${WORKDIR}"
+SRC_URI += "file://76-nuvoton-mtd-partitions.rules"
+
+RDEPENDS:${PN} += "udev"
+
+do_install() {
+    install -d ${D}/${base_libdir}/udev/rules.d
+    install -m 0644 ${WORKDIR}/76-nuvoton-mtd-partitions.rules ${D}/${base_libdir}/udev/rules.d
+}
diff --git a/meta-nuvoton-npcm8xx/recipes-core/udev/udev-nuvoton-mtd-partitions/76-nuvoton-mtd-partitions.rules b/meta-nuvoton-npcm8xx/recipes-core/udev/udev-nuvoton-mtd-partitions/76-nuvoton-mtd-partitions.rules
new file mode 100644
index 0000000..28e4586
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-core/udev/udev-nuvoton-mtd-partitions/76-nuvoton-mtd-partitions.rules
@@ -0,0 +1 @@
+ENV{DEVTYPE}=="mtd", SYMLINK+="mtd/%s{name}"
diff --git a/meta-nuvoton-npcm8xx/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend b/meta-nuvoton-npcm8xx/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend
new file mode 100644
index 0000000..bba4429
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-graphics/obmc-ikvm/obmc-ikvm_%.bbappend
@@ -0,0 +1,7 @@
+LIC_FILES_CHKSUM = "file://LICENSE;md5=d32239bcb673463ab874e80d47fae504"
+SRC_URI:nuvoton := "git://github.com/Nuvoton-Israel/obmc-ikvm.git;branch=master;protocol=https"
+SRCREV:nuvoton := "40f879557d7fe612a6dac6dbc0d1dbdca1eacfc5"
+
+#LIC_FILES_CHKSUM = "file://LICENSE;md5=75859989545e37968a99b631ef42722e"
+#SRC_URI:nuvoton := "git://github.com/Nuvoton-Israel/obmc-ikvm.git;branch=upstream;protocol=https"
+#SRCREV:nuvoton := "e7ae01193609dd86ef982a4641fefa2cc8af8f12"
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton.inc b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton.inc
new file mode 100644
index 0000000..0ea2761
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton.inc
@@ -0,0 +1,22 @@
+DESCRIPTION = "Linux kernel for Nuvoton NPCM7xx"
+SECTION = "kernel"
+LICENSE = "GPL-2.0-only"
+
+PROVIDES += "virtual/kernel"
+
+KCONFIG_MODE="--alldefconfig"
+
+KSRC ?= "git://github.com/Nuvoton-Israel/linux;protocol=https;branch=${KBRANCH}"
+SRC_URI = "${KSRC}"
+SRC_URI:append:npcm7xx = " file://defconfig"
+SRC_URI:append:npcm8xx = " file://npcm8xx_defconfig"
+
+LINUX_VERSION_EXTENSION ?= "-${SRCREV}"
+
+PV = "${LINUX_VERSION}+git${SRCPV}"
+
+inherit kernel
+require recipes-kernel/linux/linux-yocto.inc
+
+# From 4.16+ the COPYING file changed
+LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0003-i2c-nuvoton-npcm750-runbmc-integrate-the-slave-mqueu.patch b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0003-i2c-nuvoton-npcm750-runbmc-integrate-the-slave-mqueu.patch
new file mode 100644
index 0000000..352b554
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0003-i2c-nuvoton-npcm750-runbmc-integrate-the-slave-mqueu.patch
@@ -0,0 +1,479 @@
+From 4ccb3076c71c9aa3355cc849f991d4d8e5301654 Mon Sep 17 00:00:00 2001
+From: kfting <kfting@nuvoton.com>
+Date: Mon, 15 Jul 2019 09:22:29 +0800
+Subject: [PATCH] i2c: nuvoton-npcm750-runbmc: integrate the slave mqueue
+
+1. Add support for the runbmc IPMB functionality
+2. The slave mqueue node is required on the i2c bus 5 for runbmc.
+
+Signed-off-by: kfting <kfting@nuvoton.com>
+---
+ .../sysfs-bus-i2c-devices-slave-mqueue        |  10 +
+ .../bindings/i2c/i2c-slave-mqueue.txt         |  34 +++
+ Documentation/i2c/slave-mqueue-backend.rst    | 124 ++++++++++
+ drivers/i2c/Kconfig                           |  25 ++
+ drivers/i2c/Makefile                          |   1 +
+ drivers/i2c/i2c-slave-mqueue.c                | 215 ++++++++++++++++++
+ 6 files changed, 409 insertions(+)
+ create mode 100644 Documentation/ABI/testing/sysfs-bus-i2c-devices-slave-mqueue
+ create mode 100644 Documentation/devicetree/bindings/i2c/i2c-slave-mqueue.txt
+ create mode 100644 Documentation/i2c/slave-mqueue-backend.rst
+ create mode 100644 drivers/i2c/i2c-slave-mqueue.c
+
+diff --git a/Documentation/ABI/testing/sysfs-bus-i2c-devices-slave-mqueue b/Documentation/ABI/testing/sysfs-bus-i2c-devices-slave-mqueue
+new file mode 100644
+index 000000000000..28318108ce85
+--- /dev/null
++++ b/Documentation/ABI/testing/sysfs-bus-i2c-devices-slave-mqueue
+@@ -0,0 +1,10 @@
++What:		/sys/bus/i2c/devices/*/slave-mqueue
++Date:		May 2019
++KernelVersion:	5.2
++Contact:	Eduardo Valentin <eduval@amazon.com>
++Description:
++		Reading to this file will return exactly one message,
++		when available, of the i2c-slave-mqueue device attached
++		to that bus. Userspace can also poll on this file to
++		get notified when new messages are available.
++Users:		i2c-slave-mqueue driver
+diff --git a/Documentation/devicetree/bindings/i2c/i2c-slave-mqueue.txt b/Documentation/devicetree/bindings/i2c/i2c-slave-mqueue.txt
+new file mode 100644
+index 000000000000..eb1881a4fc0e
+--- /dev/null
++++ b/Documentation/devicetree/bindings/i2c/i2c-slave-mqueue.txt
+@@ -0,0 +1,34 @@
++===============================================
++Device Tree for I2C slave message queue backend
++===============================================
++
++Some protocols over I2C/SMBus are designed for bi-directional transferring
++messages by using I2C Master Write protocol. This requires that both sides
++of the communication have slave addresses.
++
++This I2C slave mqueue (message queue) is used to receive and queue
++messages from the remote i2c intelligent device; and it will add the target
++slave address (with R/W# bit is always 0) into the message at the first byte.
++
++Links
++----
++`Intelligent Platform Management Bus
++Communications Protocol Specification
++<https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmp-spec-v1.0.pdf>`_
++
++`Management Component Transport Protocol (MCTP)
++SMBus/I2C Transport Binding Specification
++<https://www.dmtf.org/sites/default/files/standards/documents/DSP0237_1.1.0.pdf>`_
++
++Required Properties:
++- compatible		: should be "i2c-slave-mqueue"
++- reg			: slave address
++
++Example:
++
++i2c {
++	slave_mqueue: i2c-slave-mqueue {
++		compatible = "i2c-slave-mqueue";
++		reg = <0x10>;
++	};
++};
+diff --git a/Documentation/i2c/slave-mqueue-backend.rst b/Documentation/i2c/slave-mqueue-backend.rst
+new file mode 100644
+index 000000000000..376dff998fa3
+--- /dev/null
++++ b/Documentation/i2c/slave-mqueue-backend.rst
+@@ -0,0 +1,124 @@
++.. SPDX-License-Identifier: GPL-2.0
++
++=====================================
++Linux I2C slave message queue backend
++=====================================
++
++:Author: Haiyue Wang <haiyue.wang@linux.intel.com>
++
++Some protocols over I2C/SMBus are designed for bi-directional transferring
++messages by using I2C Master Write protocol. This requires that both sides
++of the communication have slave addresses.
++
++Like MCTP (Management Component Transport Protocol) and IPMB (Intelligent
++Platform Management Bus), they both require that the userspace can receive
++messages from i2c drivers under slave mode.
++
++This I2C slave mqueue (message queue) backend is used to receive and queue
++messages from the remote i2c intelligent device; and it will add the target
++slave address (with R/W# bit is always 0) into the message at the first byte,
++so that userspace can use this byte to dispatch the messages into different
++handling modules. Also, like IPMB, the address byte is in its message format,
++it needs it to do checksum.
++
++For messages are time related, so this backend will flush the oldest message
++to queue the newest one.
++
++Link
++----
++`Intelligent Platform Management Bus
++Communications Protocol Specification
++<https://www.intel.com/content/dam/www/public/us/en/documents/product-briefs/ipmp-spec-v1.0.pdf>`_
++
++`Management Component Transport Protocol (MCTP)
++SMBus/I2C Transport Binding Specification
++<https://www.dmtf.org/sites/default/files/standards/documents/DSP0237_1.1.0.pdf>`_
++
++How to use
++----------
++For example, the I2C5 bus has slave address 0x10, the below command will create
++the related message queue interface:
++
++    echo slave-mqueue 0x1010 > /sys/bus/i2c/devices/i2c-5/new_device
++
++Then you can dump the messages like this:
++
++    hexdump -C /sys/bus/i2c/devices/5-1010/slave-mqueue
++
++Code Example
++------------
++*Note: call 'lseek' before 'read', this is a requirement from kernfs' design.*
++
++::
++
++  #include <sys/types.h>
++  #include <sys/stat.h>
++  #include <unistd.h>
++  #include <poll.h>
++  #include <time.h>
++  #include <fcntl.h>
++  #include <stdio.h>
++
++  int main(int argc, char *argv[])
++  {
++          int i, r;
++          struct pollfd pfd;
++          struct timespec ts;
++          unsigned char data[256];
++
++          pfd.fd = open(argv[1], O_RDONLY | O_NONBLOCK);
++          if (pfd.fd < 0)
++                  return -1;
++
++          pfd.events = POLLPRI;
++
++          while (1) {
++                  r = poll(&pfd, 1, 5000);
++
++                  if (r < 0)
++                          break;
++
++                  if (r == 0 || !(pfd.revents & POLLPRI))
++                          continue;
++
++                  lseek(pfd.fd, 0, SEEK_SET);
++                  r = read(pfd.fd, data, sizeof(data));
++                  if (r <= 0)
++                          continue;
++
++                  clock_gettime(CLOCK_MONOTONIC, &ts);
++                  printf("[%ld.%.9ld] :", ts.tv_sec, ts.tv_nsec);
++                  for (i = 0; i < r; i++)
++                          printf(" %02x", data[i]);
++                  printf("\n");
++          }
++
++          close(pfd.fd);
++
++          return 0;
++  }
++
++Result
++------
++*./a.out "/sys/bus/i2c/devices/5-1010/slave-mqueue"*
++
++::
++
++  [10183.232500449] : 20 18 c8 2c 78 01 5b
++  [10183.479358348] : 20 18 c8 2c 78 01 5b
++  [10183.726556812] : 20 18 c8 2c 78 01 5b
++  [10183.972605863] : 20 18 c8 2c 78 01 5b
++  [10184.220124772] : 20 18 c8 2c 78 01 5b
++  [10184.467764166] : 20 18 c8 2c 78 01 5b
++  [10193.233421784] : 20 18 c8 2c 7c 01 57
++  [10193.480273460] : 20 18 c8 2c 7c 01 57
++  [10193.726788733] : 20 18 c8 2c 7c 01 57
++  [10193.972781945] : 20 18 c8 2c 7c 01 57
++  [10194.220487360] : 20 18 c8 2c 7c 01 57
++  [10194.468089259] : 20 18 c8 2c 7c 01 57
++  [10203.233433099] : 20 18 c8 2c 80 01 53
++  [10203.481058715] : 20 18 c8 2c 80 01 53
++  [10203.727610472] : 20 18 c8 2c 80 01 53
++  [10203.974044856] : 20 18 c8 2c 80 01 53
++  [10204.220734634] : 20 18 c8 2c 80 01 53
++  [10204.468461664] : 20 18 c8 2c 80 01 53
+diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
+index 438905e2a1d0..5ffe13438b6f 100644
+--- a/drivers/i2c/Kconfig
++++ b/drivers/i2c/Kconfig
+@@ -133,6 +133,31 @@ config I2C_SLAVE_TESTUNIT
+ 	  multi-master, SMBus Host Notify, etc. Please read
+ 	  Documentation/i2c/slave-testunit-backend.rst for further details.
+ 
++config I2C_SLAVE_MQUEUE
++	tristate "I2C mqueue (message queue) slave driver"
++	help
++	  Some protocols over I2C are designed for bi-directional transferring
++	  messages by using I2C Master Write protocol. This driver is used to
++	  receive and queue messages from the remote I2C device.
++
++	  Userspace can get the messages by reading sysfs file that this driver
++	  exposes.
++
++	  This support is also available as a module. If so, the module will be
++	  called i2c-slave-mqueue.
++
++config I2C_SLAVE_MQUEUE_MESSAGE_SIZE
++	int "The message size of I2C mqueue slave"
++	depends on I2C_SLAVE_MQUEUE
++	default 120
++
++config I2C_SLAVE_MQUEUE_QUEUE_SIZE
++	int "The queue size of I2C mqueue slave"
++	depends on I2C_SLAVE_MQUEUE
++	default 32
++	help
++	  This number MUST be power of 2.
++
+ endif
+ 
+ config I2C_DEBUG_CORE
+diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
+index c1d493dc9bac..0442e5cf8587 100644
+--- a/drivers/i2c/Makefile
++++ b/drivers/i2c/Makefile
+@@ -17,5 +17,6 @@ obj-y				+= algos/ busses/ muxes/
+ obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o
+ obj-$(CONFIG_I2C_SLAVE_EEPROM)	+= i2c-slave-eeprom.o
+ obj-$(CONFIG_I2C_SLAVE_TESTUNIT)	+= i2c-slave-testunit.o
++obj-$(CONFIG_I2C_SLAVE_MQUEUE)	+= i2c-slave-mqueue.o
+ 
+ ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
+diff --git a/drivers/i2c/i2c-slave-mqueue.c b/drivers/i2c/i2c-slave-mqueue.c
+new file mode 100644
+index 000000000000..c17c4911928f
+--- /dev/null
++++ b/drivers/i2c/i2c-slave-mqueue.c
+@@ -0,0 +1,215 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2017 - 2018, Intel Corporation.
++
++#include <linux/i2c.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/of.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/sysfs.h>
++
++#define MQ_MSGBUF_SIZE		CONFIG_I2C_SLAVE_MQUEUE_MESSAGE_SIZE
++#define MQ_QUEUE_SIZE		CONFIG_I2C_SLAVE_MQUEUE_QUEUE_SIZE
++#define MQ_QUEUE_NEXT(x)	(((x) + 1) & (MQ_QUEUE_SIZE - 1))
++
++struct mq_msg {
++	int	len;
++	u8	*buf;
++};
++
++struct mq_queue {
++	struct bin_attribute	bin;
++	struct kernfs_node	*kn;
++
++	spinlock_t		lock; /* spinlock for queue index handling */
++	int			in;
++	int			out;
++
++	struct mq_msg		*curr;
++	int			truncated; /* drop current if truncated */
++	struct mq_msg		queue[MQ_QUEUE_SIZE];
++};
++
++static int i2c_slave_mqueue_callback(struct i2c_client *client,
++				     enum i2c_slave_event event, u8 *val)
++{
++	struct mq_queue *mq = i2c_get_clientdata(client);
++	struct mq_msg *msg = mq->curr;
++	int ret = 0;
++
++	switch (event) {
++	case I2C_SLAVE_WRITE_REQUESTED:
++		mq->truncated = 0;
++
++		msg->len = 1;
++		msg->buf[0] = client->addr << 1;
++		break;
++
++	case I2C_SLAVE_WRITE_RECEIVED:
++		if (msg->len < MQ_MSGBUF_SIZE) {
++			msg->buf[msg->len++] = *val;
++		} else {
++			dev_err(&client->dev, "message is truncated!\n");
++			mq->truncated = 1;
++			ret = -EINVAL;
++		}
++		break;
++
++	case I2C_SLAVE_STOP:
++		if (unlikely(mq->truncated || msg->len < 2))
++			break;
++
++		spin_lock(&mq->lock);
++		mq->in = MQ_QUEUE_NEXT(mq->in);
++		mq->curr = &mq->queue[mq->in];
++		mq->curr->len = 0;
++
++		/* Flush the oldest message */
++		if (mq->out == mq->in)
++			mq->out = MQ_QUEUE_NEXT(mq->out);
++		spin_unlock(&mq->lock);
++
++		kernfs_notify(mq->kn);
++		break;
++
++	default:
++		*val = 0xFF;
++		break;
++	}
++
++	return ret;
++}
++
++static ssize_t i2c_slave_mqueue_bin_read(struct file *filp,
++					 struct kobject *kobj,
++					 struct bin_attribute *attr,
++					 char *buf, loff_t pos, size_t count)
++{
++	struct mq_queue *mq;
++	struct mq_msg *msg;
++	unsigned long flags;
++	bool more = false;
++	ssize_t ret = 0;
++
++	mq = dev_get_drvdata(kobj_to_dev(kobj));
++
++	spin_lock_irqsave(&mq->lock, flags);
++	if (mq->out != mq->in) {
++		msg = &mq->queue[mq->out];
++
++		if (msg->len <= count) {
++			ret = msg->len;
++			memcpy(buf, msg->buf, ret);
++		} else {
++			ret = -EOVERFLOW; /* Drop this HUGE one. */
++		}
++
++		mq->out = MQ_QUEUE_NEXT(mq->out);
++		if (mq->out != mq->in)
++			more = true;
++	}
++	spin_unlock_irqrestore(&mq->lock, flags);
++
++	if (more)
++		kernfs_notify(mq->kn);
++
++	return ret;
++}
++
++static int i2c_slave_mqueue_probe(struct i2c_client *client,
++				  const struct i2c_device_id *id)
++{
++	struct device *dev = &client->dev;
++	struct mq_queue *mq;
++	int ret, i;
++	void *buf;
++
++	BUILD_BUG_ON(!is_power_of_2(MQ_QUEUE_SIZE));
++
++	mq = devm_kzalloc(dev, sizeof(*mq), GFP_KERNEL);
++	if (!mq)
++		return -ENOMEM;
++
++	buf = devm_kmalloc_array(dev, MQ_QUEUE_SIZE, MQ_MSGBUF_SIZE,
++				 GFP_KERNEL);
++	if (!buf)
++		return -ENOMEM;
++
++	for (i = 0; i < MQ_QUEUE_SIZE; i++)
++		mq->queue[i].buf = buf + i * MQ_MSGBUF_SIZE;
++
++	i2c_set_clientdata(client, mq);
++
++	spin_lock_init(&mq->lock);
++	mq->curr = &mq->queue[0];
++
++	sysfs_bin_attr_init(&mq->bin);
++	mq->bin.attr.name = "slave-mqueue";
++	mq->bin.attr.mode = 0400;
++	mq->bin.read = i2c_slave_mqueue_bin_read;
++	mq->bin.size = MQ_MSGBUF_SIZE * MQ_QUEUE_SIZE;
++
++	ret = sysfs_create_bin_file(&dev->kobj, &mq->bin);
++	if (ret)
++		return ret;
++
++	mq->kn = kernfs_find_and_get(dev->kobj.sd, mq->bin.attr.name);
++	if (!mq->kn) {
++		sysfs_remove_bin_file(&dev->kobj, &mq->bin);
++		return -EFAULT;
++	}
++
++	ret = i2c_slave_register(client, i2c_slave_mqueue_callback);
++	if (ret) {
++		kernfs_put(mq->kn);
++		sysfs_remove_bin_file(&dev->kobj, &mq->bin);
++		return ret;
++	}
++
++	return 0;
++}
++
++static int i2c_slave_mqueue_remove(struct i2c_client *client)
++{
++	struct mq_queue *mq = i2c_get_clientdata(client);
++
++	i2c_slave_unregister(client);
++
++	kernfs_put(mq->kn);
++	sysfs_remove_bin_file(&client->dev.kobj, &mq->bin);
++
++	return 0;
++}
++
++static const struct i2c_device_id i2c_slave_mqueue_id[] = {
++	{ "slave-mqueue", 0 },
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(i2c, i2c_slave_mqueue_id);
++
++#ifdef CONFIG_OF
++static const struct of_device_id i2c_slave_mqueue_of_match[] = {
++	{
++		.compatible = "i2c-slave-mqueue",
++	},
++	{ /* sentinel */ }
++};
++MODULE_DEVICE_TABLE(of, i2c_slave_mqueue_of_match);
++#endif
++
++static struct i2c_driver i2c_slave_mqueue_driver = {
++	.driver = {
++		.name	= "i2c-slave-mqueue",
++		.of_match_table = of_match_ptr(i2c_slave_mqueue_of_match),
++	},
++	.probe		= i2c_slave_mqueue_probe,
++	.remove		= i2c_slave_mqueue_remove,
++	.id_table	= i2c_slave_mqueue_id,
++};
++module_i2c_driver(i2c_slave_mqueue_driver);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Haiyue Wang <haiyue.wang@linux.intel.com>");
++MODULE_DESCRIPTION("I2C slave mode for receiving and queuing messages");
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0004-driver-ncsi-replace-del-timer-sync.patch b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0004-driver-ncsi-replace-del-timer-sync.patch
new file mode 100644
index 0000000..9d5a093
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0004-driver-ncsi-replace-del-timer-sync.patch
@@ -0,0 +1,25 @@
+From 65545ab80b03473b661696dc296fd9f238ba5e16 Mon Sep 17 00:00:00 2001
+From: Joseph Liu <kwliu@nuvoton.com>
+Date: Thu, 9 Jan 2020 11:21:30 +0800
+Subject: [PATCH 24/34] driver: ncsi: replace del_timer_sync() with del_timer()
+
+---
+ net/ncsi/ncsi-manage.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c
+index 70fe02697544..87484beee5fd 100644
+--- a/net/ncsi/ncsi-manage.c
++++ b/net/ncsi/ncsi-manage.c
+@@ -181,7 +181,7 @@ void ncsi_stop_channel_monitor(struct ncsi_channel *nc)
+ 	nc->monitor.enabled = false;
+ 	spin_unlock_irqrestore(&nc->lock, flags);
+ 
+-	del_timer_sync(&nc->monitor.timer);
++	del_timer(&nc->monitor.timer);
+ }
+ 
+ struct ncsi_channel *ncsi_find_channel(struct ncsi_package *np,
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0015-driver-misc-nuvoton-vdm-support-openbmc-libmctp.patch b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0015-driver-misc-nuvoton-vdm-support-openbmc-libmctp.patch
new file mode 100644
index 0000000..e2a34fa
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0015-driver-misc-nuvoton-vdm-support-openbmc-libmctp.patch
@@ -0,0 +1,214 @@
+From fcae4930d0f6a24eca27509e0acbc9da533ed64c Mon Sep 17 00:00:00 2001
+From: Joseph Liu <kwliu@nuvoton.com>
+Date: Mon, 30 Nov 2020 14:33:04 +0800
+Subject: [PATCH] driver: misc: nuvoton: vdm: support openbmc libmctp
+
+---
+ drivers/misc/npcm-vdm/vdm_common.c | 87 +++---------------------------
+ drivers/misc/npcm-vdm/vdm_module.c | 26 +++++++--
+ 2 files changed, 31 insertions(+), 82 deletions(-)
+
+diff --git a/drivers/misc/npcm-vdm/vdm_common.c b/drivers/misc/npcm-vdm/vdm_common.c
+index b622da52dda7..cbf536301fb4 100644
+--- a/drivers/misc/npcm-vdm/vdm_common.c
++++ b/drivers/misc/npcm-vdm/vdm_common.c
+@@ -262,95 +262,24 @@ int vdm_SendMessage(uint8_t route_type, uint16_t aBDF,uint8_t  *apData,uint32_t
+ 	uint8_t     idx;
+ 	uint8_t 	tag,paddingBytesNum;
+ 	uint8_t 	currLength;
+-	uint32_t pci_message_header[4]={0};
+ 
+ 	ready_for_transmit=0;
+ 
+-	pci_message_header[0]=
+-			// ( ( ((1) << 5)+ ( (0x13/*1 0011 (broadcasting) */) << 0)) << 0) + // fmt + type . filled dynamically
+-			( ( ( PCIe_TC0 << 4)+  (PCIe_NO_IDO << 2) +  	// TC + atr[2]
+-					(PCIe_NO_TH << 0) ) << 8   ) + 			// TH
+-			( ( (PCIe_NO_TD << 7) + (PCIe_NO_EP << 6) +     // TD  + EP
+-					(PCIe_NO_RLX_ORDER_NO_SNOOP << 4) +     // atr[1,0]
+-					(PCIe_NO_AT << 2)  ) << 16); 			// AT
+-			//+ ( (0) << 24) ;// length . filled dynamically
+-
+-	pci_message_header[1]=
+-			( (0) << 0) + //  request ID filled automatically by HW
+-			( ( PCIe_TAG ) << 8) + // defult tag
+-			( (PCIe_MSG_VDM_TYPE1) << 24 ) ;//message code (vd type1)
+-
+-
+-	pci_message_header[2]=
+-			// ( (0) << 0) + // bus_num (reserved in broadcasting) . filled dynamically
+-			// ( ( (0 << 3) + (0 << 0) ) << 8) + // dev_num + func_num (reserved in broadcasting) . filled dynamically
+-			( ( (VDM_VENDOR_ID >> 8) & 0xff) << 16) +// vendor id msb
+-			( ( VDM_VENDOR_ID & 0xff ) << 24 ) ;// vendor id lsb
+-
+-//	PRINTF("<1>vdm:vdm_SendMessage \n"  );
+-
+ 	// data will be split by PCIe_MAX_PAYLOAD_SIZE_BYTES
+ 	while(aLength)
+ 	{
+-		if(aLength>PCIe_MAX_PAYLOAD_SIZE_BYTES)
+-		{
+-			currLength=PCIe_MAX_PAYLOAD_SIZE_BYTES;
+-		}
++		if (aLength > PCIe_MAX_PAYLOAD_SIZE_BYTES)
++			currLength = PCIe_MAX_PAYLOAD_SIZE_BYTES;
+ 		else
+-		{
+-			currLength=aLength;
+-		}
++			currLength = aLength;
++
+ 		aLength-=currLength;
+ 
+-		paddingBytesNum =  ( currLength % 4);
+-		if ( 0 != paddingBytesNum )
+-		{
++		paddingBytesNum =  (currLength % 4);
++		if (0 != paddingBytesNum )
+ 			paddingBytesNum = 4 - paddingBytesNum;
+-		}
+-
+-		/*********** fill first U32 of TLP :  ***************/
+-		pci_message_header[0] &= (~PCIe_HEADER_FMT_FIELD_MASK);
+-		pci_message_header[0] &= (~PCIe_HEADER_LENGTH_FIELD_MASK);
+-		if(currLength > 4)
+-		{
+-			pci_message_header[0] |= PCIe_HEADER_FMT_MSG_WITH_PAYLOAD;
+-			pci_message_header[0] |= ((    ((currLength-1)/4) & 0xff) << 24);
+-			pci_message_header[0] |= ( ((  ((currLength-1)/4) >> 8) & 0x3) << 16);
+-		}
+-		else
+-		{
+-			pci_message_header[0] |= PCIe_HEADER_FMT_MSG_NO_PAYLOAD;
+-		}
+-
+-		/* route_type icludes tlp type and route mechanism*/
+-		pci_message_header[0] &= (~PCIe_HEADER_ROUTE_FIELD_MASK);
+-		pci_message_header[0] |= route_type;
+-
+-		pci_message_header[0] &= (~PCIe_HEADER_ATTR_MASK);
+-		pci_message_header[0] |= PCIe_HEADER_ATTR_TEST;
+-
+-
+-		/*********** fill second U32 of TLP :  ***************/
+-		pci_message_header[1] &= (~PCIe_HEADER_TAG_FIELD_MASK);
+-		tag = (paddingBytesNum & 3 ) << 4 ;
+-		pci_message_header[1] |= (tag << 16);
+-
+-
+-		/*********** fill third U32 of TLP :  ***************/
+-		pci_message_header[2] &= (~PCIe_HEADER_DEST_BDF_FIELD_MASK);
+-
+-		if(PCIe_HEADER_ROUTE_BY_ID == route_type)
+-		{
+-			pci_message_header[2] |=
+-					( ( (aBDF >> 8) & 0xff) ) +
+-					( ( aBDF & 0xff ) << 8 ) ;
+-		}
+-
+-		iowrite32(pci_message_header[0], vdm_virt_addr + VDM_TXF_REG);
+-		iowrite32(pci_message_header[1], vdm_virt_addr + VDM_TXF_REG);
+-		iowrite32(pci_message_header[2], vdm_virt_addr + VDM_TXF_REG);
+ 
+-		while(currLength >3 )
++		while (currLength >3 )
+ 		{
+ 			txData=(apData[3]<<24) + (apData[2]<<16) + (apData[1]<<8) + (apData[0]) ;
+ 			iowrite32(txData, vdm_virt_addr + VDM_TXF_REG);
+@@ -401,7 +330,7 @@ int vdm_SendMessage(uint8_t route_type, uint16_t aBDF,uint8_t  *apData,uint32_t
+ 		// test VDM_CNT_REG_VDM_ENABLE_BIT_POS to see that PCIe bus was not reset
+ 		for (i=0 ; i< SEND_TIMEOUT; i++)
+ 		{
+-			if((read_reg_bit(VDM_TX_DONE_BIT_POS, vdm_virt_addr + VDM_STAT_REG) == 1) || vdm_is_in_reset())
++			if((read_reg_bit(VDM_CNT_REG_START_TX_BIT, vdm_virt_addr + VDM_CNT_REG) == 0) || vdm_is_in_reset())
+ 				break;
+ 			else
+ 				nano_delay(100);
+diff --git a/drivers/misc/npcm-vdm/vdm_module.c b/drivers/misc/npcm-vdm/vdm_module.c
+index 1cdcab95e8ae..b9f319fbe8d6 100644
+--- a/drivers/misc/npcm-vdm/vdm_module.c
++++ b/drivers/misc/npcm-vdm/vdm_module.c
+@@ -279,13 +279,14 @@ static ssize_t vdm_read(struct file *filp, char *buf, size_t count, loff_t *f_po
+ 	while(1)
+ 	{
+ 		spin_lock_irqsave(&lock, flags);
++#if 0
+ 		if(0 == pVDM_Instance->BDF_is_set)
+ 		{
+ 			ret = -ENOENT  ;
+ 			VDM_DEBUG_LOG(tBDF,"BDF was not set for given pVDM Instance\n");
+ 			goto unlock_and_exit;
+ 		}
+-
++#endif
+ 		if (vdm_is_in_reset())
+ 		{
+ 			pVDM_Instance->last_errors |= PCIE_VDM_ERR_BUS_RESET_OCCURED;
+@@ -380,13 +381,21 @@ static ssize_t vdm_write( struct file *filp, const char *buf, size_t count, loff
+ 		goto failed;
+ 	}
+ 	//pr_debug("<1> vdm module write start  \n");
+-
++#if 0
+ 	if((count-1) > pVDM_Instance->mptxBufferLength)
+ 	{
+ 		VDM_DEBUG_LOG(tBDF,"vdm module data length is too big\n");
+ 		ret = -EINVAL;
+ 		goto failed;
+ 	}
++#endif
++	if(count > pVDM_Instance->mptxBufferLength)
++	{
++		VDM_DEBUG_LOG(tBDF,"vdm module data length is too big\n");
++		ret = -EINVAL;
++		goto failed;
++	}
++
+ 	if(count < 2)
+ 	{
+ 		VDM_DEBUG_LOG(tBDF,"vdm module : wrong buffer\n");
+@@ -394,6 +403,14 @@ static ssize_t vdm_write( struct file *filp, const char *buf, size_t count, loff
+ 		goto failed;
+ 	}
+ 
++	if(copy_from_user( pVDM_Instance->mptxBuffer , &buf[0] , count))
++	{
++		ret = -EFAULT;
++                VDM_DEBUG_LOG(tBDF,"Failed for copying data from user\n");
++		goto failed;
++	}
++
++#if 0
+ 	if(copy_from_user( pVDM_Instance->mptxBuffer , &buf[1] , count-1))
+ 	{
+ 		ret = -EFAULT;
+@@ -407,6 +424,7 @@ static ssize_t vdm_write( struct file *filp, const char *buf, size_t count, loff
+ 		VDM_DEBUG_LOG(tBDF,"BDF was not set\n");
+ 		goto failed;
+ 	}
++
+ 	if (copy_from_user(&route_type, &buf[0], sizeof(route_type)))
+ 	{
+ 		ret = -EFAULT;
+@@ -420,8 +438,9 @@ static ssize_t vdm_write( struct file *filp, const char *buf, size_t count, loff
+ 	{
+ 		route_type=PCIe_HEADER_ROUTE_FROM_RC;
+ 	}
++#endif
+ 
+-        VDM_DEBUG_LOG(tBDF,"Before writing data route_type %d BDF 0x%X and count %d\n",route_type,pVDM_Instance->mBDF,count );
++	VDM_DEBUG_LOG(tBDF,"Before writing data route_type %d BDF 0x%X and count %d\n",route_type,pVDM_Instance->mBDF,count );
+ 
+ 	if (0 == vdm_SendMessage(route_type , pVDM_Instance->mBDF , pVDM_Instance->mptxBuffer,count-1))
+ 		ret = count;
+@@ -608,6 +627,7 @@ static int vdm_open(struct inode *inode, struct file *filp)
+ 	}
+ 
+ 	memset(pVDM_Instance,0,sizeof(vdm_instance_t));
++	pVDM_Instance_Default = pVDM_Instance;
+ 	pVDM_Instance->BDF_is_set = 0;
+ 	pVDM_Instance->last_errors = 0;
+ 	pVDM_Instance->dbg_counter = 0;
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0017-drivers-i2c-workaround-for-i2c-slave-behavior.patch b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0017-drivers-i2c-workaround-for-i2c-slave-behavior.patch
new file mode 100644
index 0000000..c9cfb86
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/0017-drivers-i2c-workaround-for-i2c-slave-behavior.patch
@@ -0,0 +1,44 @@
+From 12744251cc8ceeb3f4bb16fccb70ff0200b13dbf Mon Sep 17 00:00:00 2001
+From: kfting <kfting@nuvoton.com>
+Date: Thu, 1 Jul 2021 15:29:45 +0800
+Subject: [PATCH] drivers: i2c: workaround for i2c slave behavior
+
+1. Not verified yet.
+
+Signed-off-by: kfting <kfting@nuvoton.com>
+---
+ drivers/i2c/busses/i2c-npcm7xx.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c
+index 78dc9eeb83a2..0753cf4c41aa 100644
+--- a/drivers/i2c/busses/i2c-npcm7xx.c
++++ b/drivers/i2c/busses/i2c-npcm7xx.c
+@@ -1166,13 +1166,13 @@ static irqreturn_t npcm_i2c_int_slave_handler(struct npcm_i2c *bus)
+ 		bus->stop_ind = I2C_SLAVE_RESTART_IND;
+ 		bus->master_or_slave = I2C_SLAVE;
+ 		if (bus->operation == I2C_READ_OPER)
+-			npcm_i2c_read_fifo_slave(bus, npcm_i2c_fifo_usage(bus));
++		  npcm_i2c_slave_rd_wr(bus);
+ 		bus->operation = I2C_WRITE_OPER;
+ 		iowrite8(0, bus->reg + NPCM_I2CRXF_CTL);
+ 		val = NPCM_I2CFIF_CTS_CLR_FIFO | NPCM_I2CFIF_CTS_SLVRSTR |
+ 		      NPCM_I2CFIF_CTS_RXF_TXE;
+ 		iowrite8(val, bus->reg + NPCM_I2CFIF_CTS);
+-		npcm_i2c_slave_rd_wr(bus);
++		//npcm_i2c_slave_rd_wr(bus);
+ 		ret = IRQ_HANDLED;
+ 	}
+ 
+@@ -1511,7 +1511,7 @@ static void npcm_i2c_irq_handle_nack(struct npcm_i2c *bus)
+ 		npcm_i2c_master_stop(bus);
+ 
+ 		/* Clear SDA Status bit (by reading dummy byte) */
+-		npcm_i2c_rd_byte(bus);
++		//npcm_i2c_rd_byte(bus);
+ 
+ 		/*
+ 		 * The bus is released from stall only after the SW clears
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/2222-driver-misc-add-nuvoton-vdmx-vdma-driver.patch b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/2222-driver-misc-add-nuvoton-vdmx-vdma-driver.patch
new file mode 100644
index 0000000..502e6d2
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/2222-driver-misc-add-nuvoton-vdmx-vdma-driver.patch
@@ -0,0 +1,847 @@
+From eee53b269f70fbf2e016b60f911043e5a35a3a17 Mon Sep 17 00:00:00 2001
+From: Joseph Liu <kwliu@nuvoton.com>
+Date: Tue, 8 Jun 2021 12:12:30 +0800
+Subject: [PATCH] driver: misc: add nuvoton vdmx/vdma driver
+
+Signed-off-by: Joseph Liu <kwliu@nuvoton.com>
+---
+ .../dts/nuvoton-npcm750-runbmc-olympus.dts    |   5 +
+ drivers/misc/Kconfig                          |   7 +
+ drivers/misc/Makefile                         |   1 +
+ drivers/misc/npcm-vdm/Kconfig                 |   2 +-
+ drivers/misc/npcm7xx-pci-vdm.c                | 760 ++++++++++++++++++
+ 5 files changed, 774 insertions(+), 1 deletion(-)
+ create mode 100644 drivers/misc/npcm7xx-pci-vdm.c
+
+diff --git a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts b/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts
+index e08f8fb13792..693e6d311995 100644
+--- a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts
++++ b/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts
+@@ -31,6 +31,7 @@
+ 		udc8 = &udc8;
+ 		udc9 = &udc9;
+ 		emmc0 = &sdhci0;
++		vdma = &vdma;
+ 		i2c0 = &i2c0;
+ 		i2c1 = &i2c1;
+ 		i2c2 = &i2c2;
+@@ -976,6 +977,10 @@
+ 	status = "okay";
+ };
+ 
++&vdma {
++	status = "okay";
++};
++
+ &vcd {
+ 	status = "okay";
+ 	memory-region = <&vcd_memory>;
+diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
+index 82f10fd5c0ab..4a6b6fe9c11e 100644
+--- a/drivers/misc/Kconfig
++++ b/drivers/misc/Kconfig
+@@ -506,6 +506,13 @@ config NPCM8XX_JTAG_MASTER
+ 	help
+ 	  NPCM8xx JTAG Master Interfaces.
+ 
++config NPCM7XX_PCI_VDM
++	tristate "NPCM7xx PCI VDM/VDMA Controller"
++	depends on (ARCH_NPCM || COMPILE_TEST) && REGMAP && MFD_SYSCON
++	help
++	  Expose the NPCM8xx/7xx PCI VDM/VDMA registers found on
++	  Nuvoton SOCs to userspace.
++
+ source "drivers/misc/c2port/Kconfig"
+ source "drivers/misc/eeprom/Kconfig"
+ source "drivers/misc/cb710/Kconfig"
+diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
+index 1079cd2f62d4..8ce25e00d01f 100644
+--- a/drivers/misc/Makefile
++++ b/drivers/misc/Makefile
+@@ -64,3 +64,4 @@ obj-$(CONFIG_NPCM7XX_JTAG_MASTER)	+= npcm7xx-jtag-master.o
+ obj-$(CONFIG_NPCM8XX_JTAG_MASTER)	+= npcm8xx-jtag-master.o
+ obj-$(CONFIG_MCTP_LPC)		+= mctp-lpc.o
+ obj-$(CONFIG_NPCM7XX_MCU_FLASH) += npcm7xx-mcu-flash.o
++obj-$(CONFIG_NPCM7XX_PCI_VDM)  += npcm7xx-pci-vdm.o
+diff --git a/drivers/misc/npcm-vdm/Kconfig b/drivers/misc/npcm-vdm/Kconfig
+index 3cb4b173f835..e53c4be3bd58 100644
+--- a/drivers/misc/npcm-vdm/Kconfig
++++ b/drivers/misc/npcm-vdm/Kconfig
+@@ -6,7 +6,7 @@ menu "Nuvoton Miscellaneous optional drivers"
+ config NPCM_VDM
+ 	tristate "support npcmx50 VDM on PCIe"
+ 	depends on ARCH_NPCM
+-	default y
++	default n
+ 	help
+ 	  Say Y here if you want ioctl npcmx50 VDM on PCIe.
+ 
+diff --git a/drivers/misc/npcm7xx-pci-vdm.c b/drivers/misc/npcm7xx-pci-vdm.c
+new file mode 100644
+index 000000000000..c27f2b695a94
+--- /dev/null
++++ b/drivers/misc/npcm7xx-pci-vdm.c
+@@ -0,0 +1,760 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2014-2018 Nuvoton Technology corporation.
++
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/gpio.h>
++#include <linux/of.h>
++#include <linux/of_irq.h>
++#include <linux/of_address.h>
++#include <linux/clk.h>
++#include <linux/uaccess.h>
++#include <linux/regmap.h>
++#include <linux/mfd/syscon.h>
++#include <linux/cdev.h>
++#include <linux/miscdevice.h>
++#include <linux/interrupt.h>
++#include <linux/dma-mapping.h>
++#include <linux/kfifo.h>
++#include <linux/poll.h>
++#include <linux/ptr_ring.h>
++
++#define ENABLE_VDMA 1
++
++#define DEVICE_NAME	"vdm"
++#define TX_TIMEOUT			100
++
++#ifdef CONFIG_ARCH_NPCM7XX
++/* GCR  Register */
++#define MFSEL3 0x64
++#define  MFSEL3_PCIE_PUSE BIT(17)
++#define INTCR3 0x9C
++#define  INTCR3_PCIRREL BIT(30)
++#endif
++
++/* VDM  Register */
++#define VDMX_BA 0xE0800000
++#define VDMX_STATR 0x0000
++
++#ifdef CONFIG_ARCH_NPCM7XX
++#define VDMX_IEN 0x0004
++#define VDMX_RXF 0x0008
++#define VDMX_TXF 0x000C
++#define VDMX_CNT 0x0010
++#define VDMX_RXFILT	0x0014
++#else
++#define VDMX_IEN 0x0100
++#define VDMX_RXF 0x0200
++#define VDMX_TXF 0x0300
++#define VDMX_CNT 0x0400
++#define VDMX_RXFILT	0x0500
++#endif
++
++/* VDMX_STATR */
++#define VDMX_STATR_RXNDW   GENMASK(23, 16)
++#define VDMX_STATR_RXNDW_OFFSET    16
++#define VDMX_STATR_RXDR BIT(2)
++#define VDMX_STATR_RXF BIT(1)
++#define VDMX_STATR_TXS BIT(0)
++
++/* VDMX_IEN */
++#define VDMX_IEN_RXDREN BIT(2)
++#define VDMX_IEN_RXFEN BIT(1)
++#define VDMX_IEN_TXSEN BIT(0)
++
++/* VDMX_CNT */
++#define VDMX_CNT_RXTO_05US BIT(4)
++#define VDMX_CNT_RXTO_1US  BIT(5)
++#define VDMX_CNT_RXTO_2US  (BIT(5) | BIT(4))
++#define VDMX_CNT_RXTO_4US  BIT(6)
++#define VDMX_CNT_RXTO_8US  (BIT(6) | BIT(4))
++#define VDMX_CNT_VDMXEN    BIT(1)
++#define VDMX_CNT_TXP   BIT(0)
++
++/* VDMX_RXFILT */
++#define VDMX_RXFILT_FEN    BIT(31)
++
++#define VDMX_VENDOR_ID     0xb4a1
++#define VDMX_RX_LEN	1024
++#define VDMX_TX_LEN	4
++#define VDMA_BUFFER_SIZE SZ_16K
++
++/* VDMA  Register */
++#define VDMA_CTL	0x0000
++#define  VDMA_CTL_BLOCK_BIT_POS BIT(17)
++#define  VDMA_CTL_BME BIT(9)
++#define  VDMA_CTL_VDMAEN BIT(0)
++
++#define VDMA_SRCB	0x0004
++#define VDMA_DSTB	0x0008
++#define VDMA_CDST	0x0014
++#define VDMA_CTCNT	0x0018
++#define VDMA_ECTL	0x0040
++#define  VDMA_ECTL_DRDYEN   BIT(29)
++#define  VDMA_ECTL_DRDY BIT(28)
++#define  VDMA_ECTL_NRTGIEN  BIT(27)
++#define  VDMA_ECTL_NORTG  BIT(26)
++#define  VDMA_ECTL_HALTINTEN  BIT(25)
++#define  VDMA_ECTL_DMAHALT  BIT(24)
++#define  VDMA_ECTL_BUFFSIZE_POS 16
++#define  VDMA_ECTL_RTRGREQ  BIT(12)
++#define  VDMA_ECTL_RTRGSZ	BIT(11)
++#define  VDMA_ECTL_ENSTSUP1	BIT(10)
++#define  VDMA_ECTL_ENSTSUP0	BIT(9)
++#define  VDMA_ECTL_SZOFS_POS 7
++#define  VDMA_ECTL_SZMOD_BIT23_16 (BIT(5) | BIT(4))
++#define  VDMA_ECTL_STAMPP BIT(2)
++#define  VDMA_ECTL_CYCBUF BIT(1)
++
++#define VDMA_ESRCSZ	0x0044
++#define VDMA_ERDPNT	0x0048
++#define VDMA_EST0AD	0x0050
++#define VDMA_EST0MK	0x0054
++#define VDMA_EST0DT	0x0058
++#define VDMA_EST1AD	0x0060
++#define VDMA_EST1MK	0x0064
++#define VDMA_EST1DT	0x0068
++
++#define VDMA_TX_DONE BIT(0)
++#define VDMA_RX_DONE BIT(1)
++#define VDMA_RX_FULL BIT(2)
++
++typedef void *(*copy_func_t)(void *dest, const void *src, size_t n);
++
++struct mctp_pcie_packet {
++	struct {
++		u32 hdr[4];
++		u32 payload[16];
++	} data;
++	u32 size;
++};
++
++struct npcm7xx_vdm {
++	struct device *dev;
++	struct miscdevice miscdev;
++	spinlock_t lock;
++	int is_open;
++	int irq;
++	struct regmap *vdmx_base;
++	struct regmap *vdma_base;
++	dma_addr_t  dma;
++	void *virt;
++	struct regmap *gcr_base;
++	wait_queue_head_t	wait_queue;
++	struct tasklet_struct tasklet;
++	struct ptr_ring rx_queue;
++	u32 wrap;
++};
++
++static atomic_t npcm7xx_vdm_open_count = ATOMIC_INIT(0);
++
++struct kmem_cache *packet_cache;
++
++static void *packet_alloc(gfp_t flags)
++{
++	return kmem_cache_alloc(packet_cache, flags);
++}
++
++static void packet_free(void *packet)
++{
++	kmem_cache_free(packet_cache, packet);
++}
++
++static void npcm7xx_vdm_rx_tasklet(unsigned long data)
++{
++	struct npcm7xx_vdm *priv = (struct npcm7xx_vdm *)data;
++	struct mctp_pcie_packet *rx_packet;
++	int ret;
++	u32 rdpnt = 0;
++	u32 curdst = 0;
++	u32 size = 0;
++
++	regmap_read(priv->vdma_base, VDMA_CDST, &curdst);
++	regmap_read(priv->vdma_base, VDMA_ERDPNT, &rdpnt);
++
++	dev_dbg(priv->dev, "curdst 0x%x\n", curdst);
++	dev_dbg(priv->dev, "rdpnt 0x%x\n", rdpnt);
++
++	// handle wrapped around
++	while (rdpnt > curdst) {
++		priv->wrap++;
++
++		rx_packet = packet_alloc(GFP_ATOMIC);
++		if (!rx_packet) {
++			dev_err(priv->dev, "Failed to allocate RX packet\n");
++			goto out_skip;
++		}
++
++		size = (priv->dma + VDMA_BUFFER_SIZE) - rdpnt;
++
++		if (size > sizeof(rx_packet->data))
++			size = sizeof(rx_packet->data);
++
++		memcpy(&rx_packet->data,
++		       (void *)(priv->virt + (rdpnt - priv->dma)),
++		size);
++
++		rx_packet->size = size;
++
++		ret = ptr_ring_produce(&priv->rx_queue, rx_packet);
++		if (ret) {
++			dev_warn(priv->dev, "Failed to produce RX packet: %d\n",
++				 ret);
++			packet_free(rx_packet);
++			continue;
++		}
++
++		rdpnt += size;
++
++		if (rdpnt == (priv->dma + VDMA_BUFFER_SIZE)) {
++			int left = curdst - priv->dma;
++			int free = sizeof(rx_packet->data) - size;
++
++			if (left <= free) {
++				memcpy(((void *)&rx_packet->data) + size, (void *)(priv->virt), left);
++				rx_packet->size += left;
++				rdpnt = priv->dma + left;
++			} else {
++				rdpnt = priv->dma;
++			}
++			break;
++		}
++	}
++
++	while (rdpnt < curdst) {
++		rx_packet = packet_alloc(GFP_ATOMIC);
++		if (!rx_packet) {
++			dev_err(priv->dev, "Failed to allocate RX packet\n");
++			goto out_skip;
++		}
++
++		size = curdst - rdpnt;
++		if (size > sizeof(rx_packet->data))
++			size = sizeof(rx_packet->data);
++
++		memcpy(&rx_packet->data,
++		       (void *)(priv->virt + (rdpnt - priv->dma)),
++			size);
++
++		rx_packet->size = size;
++
++		ret = ptr_ring_produce(&priv->rx_queue, rx_packet);
++		if (ret) {
++			dev_warn(priv->dev, "Failed to produce RX packet: %d\n",
++				 ret);
++			packet_free(rx_packet);
++			continue;
++		}
++
++		rdpnt += size;
++	}
++
++out_skip:
++	dev_dbg(priv->dev, "wrap count %d\n", priv->wrap);
++	dev_dbg(priv->dev, "update rdpnt to 0x%x\n", rdpnt);
++	regmap_write(priv->vdma_base, VDMA_ERDPNT, rdpnt);
++
++	wake_up_all(&priv->wait_queue);
++}
++
++static irqreturn_t npcm7xx_vdm_irq(int irq, void *arg)
++{
++	struct npcm7xx_vdm *priv = arg;
++	u32 status = 0;
++
++	regmap_read(priv->vdma_base, VDMA_ECTL, &status);
++	dev_dbg(priv->dev, "status 0x%x\n", status);
++
++	if (status & VDMA_ECTL_DRDY) {
++		dev_dbg(priv->dev, "VDMA_ECTL_DRDY\n");
++		tasklet_hi_schedule(&priv->tasklet);
++	}
++
++	if (status & VDMA_ECTL_DMAHALT) {
++		/*to do: we should reinit dam buffer if dma halt*/
++		dev_dbg(priv->dev, "VDMA_ECTL_DMAHALT\n");
++	}
++
++	if (status & VDMA_ECTL_NORTG) {
++		dev_dbg(priv->dev, "VDMA_ECTL_NORTG\n");
++	}
++
++	regmap_write(priv->vdma_base, VDMA_ECTL, status);
++
++	return IRQ_HANDLED;
++}
++
++static void npcm7xx_vdm_hw_finit(struct npcm7xx_vdm *priv)
++{
++	/* VDM RESET */
++	regmap_write(priv->vdmx_base, VDMX_CNT, 0);
++
++	/* Disable Interrupt */
++	regmap_write(priv->vdmx_base, VDMX_IEN, 0);
++
++	/* Clear VDM STAT */
++	regmap_write(priv->vdmx_base, VDMX_STATR,
++		     VDMX_STATR_RXDR | VDMX_STATR_RXF | VDMX_STATR_TXS);
++
++	/* VDMA Disable */
++	regmap_write(priv->vdma_base, VDMA_CTL, 0);
++
++	/* VDMA Disable Interrupt */
++	regmap_update_bits(priv->vdma_base, VDMA_ECTL, VDMA_ECTL_DRDYEN, ~VDMA_ECTL_DRDYEN);
++	regmap_update_bits(priv->vdma_base, VDMA_ECTL, VDMA_ECTL_HALTINTEN, ~VDMA_ECTL_HALTINTEN);
++	regmap_update_bits(priv->vdma_base, VDMA_ECTL, VDMA_ECTL_NRTGIEN, ~VDMA_ECTL_NRTGIEN);
++
++	/* Clear VDMA State*/
++	regmap_write(priv->vdma_base, VDMA_ECTL,
++		     VDMA_ECTL_DRDY | VDMA_ECTL_NORTG | VDMA_ECTL_DMAHALT);
++}
++
++static int npcm7xx_vdm_hw_init(struct npcm7xx_vdm *priv)
++{
++	int ret = 0;
++	u32 reg_val = 0;
++#ifdef CONFIG_ARCH_NPCM7XX
++	struct regmap *gcr = priv->gcr_base;
++
++	/* Configure PCIE phy selection for bridge */
++	regmap_update_bits(gcr, MFSEL3, MFSEL3_PCIE_PUSE, ~MFSEL3_PCIE_PUSE);
++#endif
++	/* Clear VDM STAT */
++	regmap_write(priv->vdmx_base, VDMX_STATR,
++		     VDMX_STATR_RXDR | VDMX_STATR_RXF | VDMX_STATR_TXS);
++
++	/* VDM RESET */
++	regmap_write(priv->vdmx_base, VDMX_CNT, 0);
++	reg_val = VDMX_CNT_RXTO_8US | VDMX_CNT_VDMXEN;
++	regmap_write(priv->vdmx_base, VDMX_CNT, reg_val);
++
++	/* VDM Filter */
++	reg_val = 0;//VDMX_RXFILT_FEN | VDMX_VENDOR_ID;
++	regmap_write(priv->vdmx_base, VDMX_RXFILT, reg_val);
++
++	/* Enable RX int */
++	regmap_write(priv->vdmx_base, VDMX_IEN, VDMX_IEN_RXFEN);
++
++	/* VDMA Disable */
++	regmap_write(priv->vdma_base, VDMA_CTL, 0);
++
++	regmap_write(priv->vdma_base, VDMA_SRCB, VDMX_BA | VDMX_RXF); // src_addr
++	regmap_write(priv->vdma_base, VDMA_DSTB, priv->dma); // dst_addr
++
++	regmap_write(priv->vdma_base, VDMA_ESRCSZ, VDMX_BA | VDMX_STATR);	// size_addr
++	regmap_write(priv->vdma_base, VDMA_ERDPNT, priv->dma);	// read pointer
++
++	regmap_write(priv->vdma_base, VDMA_EST0AD, VDMX_BA | VDMX_STATR);	// address of clear bit
++	regmap_write(priv->vdma_base, VDMA_EST0MK, 0xffffffff);
++	regmap_write(priv->vdma_base, VDMA_EST0DT, VDMX_IEN_RXFEN);
++
++	reg_val = VDMA_ECTL_DRDYEN | VDMA_ECTL_DRDY | VDMA_ECTL_HALTINTEN | VDMA_ECTL_DMAHALT |
++		VDMA_ECTL_RTRGSZ | VDMA_ECTL_ENSTSUP0 | VDMA_ECTL_CYCBUF | VDMA_ECTL_SZMOD_BIT23_16 |
++		((VDMA_BUFFER_SIZE / SZ_16K) << VDMA_ECTL_BUFFSIZE_POS);
++	regmap_write(priv->vdma_base, VDMA_ECTL, reg_val);
++
++	reg_val = VDMA_CTL_BLOCK_BIT_POS | VDMA_CTL_VDMAEN;
++	regmap_write(priv->vdma_base, VDMA_CTL, reg_val);
++
++	return ret;
++}
++
++static ssize_t npcm7xx_vdm_read(struct file *file, char __user *buf,
++				size_t count, loff_t *ppos)
++{
++	struct miscdevice *misc = file->private_data;
++	struct platform_device *pdev = to_platform_device(misc->parent);
++	struct npcm7xx_vdm *priv = platform_get_drvdata(pdev);
++	struct mctp_pcie_packet *rx_packet;
++
++	if (buf && count > 0) {
++		rx_packet = ptr_ring_consume_bh(&priv->rx_queue);
++		if (!rx_packet)
++			return -EAGAIN;
++
++		if (count > rx_packet->size)
++			count = rx_packet->size;
++
++		if (copy_to_user(buf, &rx_packet->data, count)) {
++			dev_err(priv->dev, "copy to user failed\n");
++			packet_free(rx_packet);
++			return -EFAULT;
++		}
++
++		packet_free(rx_packet);
++	}
++
++	return count;
++}
++
++static int
++npcm7xx_vdm_send(struct npcm7xx_vdm *priv, u8 *txbuf, int size)
++{
++	u32 timeout, stat;
++	int i, ret = -EIO;
++
++	regmap_read(priv->vdmx_base, VDMX_CNT, &stat);
++	if (stat & VDMX_CNT_VDMXEN) {
++		ret = size;
++
++		for (i = 0; i < size; i += VDMX_TX_LEN)
++			regmap_write(priv->vdmx_base, VDMX_TXF, readl(txbuf + i));
++
++		regmap_update_bits(priv->vdmx_base, VDMX_CNT, VDMX_CNT_TXP, VDMX_CNT_TXP);
++
++		timeout = wait_event_interruptible_timeout(priv->wait_queue,
++							   !regmap_read(priv->vdmx_base, VDMX_CNT, &stat) &
++							!(stat & VDMX_CNT_TXP),
++							msecs_to_jiffies(TX_TIMEOUT));
++		if (!timeout) {
++			dev_err(priv->dev, "vdm send timeout 0x%x\n", stat);
++			ret = -EIO;
++		}
++
++		regmap_update_bits(priv->vdmx_base, VDMX_STATR, VDMX_STATR_TXS, VDMX_STATR_TXS);
++	}
++
++	return ret;
++}
++
++static ssize_t npcm7xx_vdm_write(struct file *file, const char __user *buf,
++				 size_t count, loff_t *ppos)
++{
++	struct miscdevice *misc = file->private_data;
++	struct platform_device *pdev = to_platform_device(misc->parent);
++	struct npcm7xx_vdm *priv = platform_get_drvdata(pdev);
++	struct mctp_pcie_packet *tx_packet;
++	int ret;
++
++	if (!access_ok(buf, count)) {
++		ret = -EFAULT;
++		goto out;
++	}
++
++	tx_packet = packet_alloc(GFP_KERNEL);
++	if (!tx_packet) {
++		ret = -ENOMEM;
++		goto out;
++	}
++
++	if (buf && count > 0) {
++		if (count > sizeof(tx_packet->data)) {
++			ret = -ENOSPC;
++			goto out_packet;
++		}
++
++		if (copy_from_user(&tx_packet->data, buf, count)) {
++			dev_err(priv->dev, "copy from user failed\n");
++			ret = -EFAULT;
++			goto out_packet;
++		}
++		tx_packet->size = count;
++
++		ret = npcm7xx_vdm_send(priv, (u8 *)&tx_packet->data, tx_packet->size);
++	}
++
++out_packet:
++	packet_free(tx_packet);
++out:
++	return ret;
++}
++
++static int npcm7xx_vdm_open(struct inode *inode, struct file *file)
++{
++	struct miscdevice *misc = file->private_data;
++	struct platform_device *pdev = to_platform_device(misc->parent);
++	struct npcm7xx_vdm *priv = platform_get_drvdata(pdev);
++
++	if (atomic_inc_return(&npcm7xx_vdm_open_count) == 1) {
++		if (npcm7xx_vdm_hw_init(priv)) {
++			dev_err(priv->dev, "Failed to init VDM\n");
++			return -EBUSY;
++		}
++
++		local_bh_disable();
++		tasklet_hi_schedule(&priv->tasklet);
++		local_bh_enable();
++
++		return 0;
++	}
++
++	atomic_dec(&npcm7xx_vdm_open_count);
++	return -EBUSY;
++}
++
++static int npcm7xx_vdm_release(struct inode *inode, struct file *file)
++{
++	struct miscdevice *misc = file->private_data;
++	struct platform_device *pdev = to_platform_device(misc->parent);
++	struct npcm7xx_vdm *priv = platform_get_drvdata(pdev);
++
++	if (atomic_dec_return(&npcm7xx_vdm_open_count) == 0)
++		npcm7xx_vdm_hw_finit(priv);
++
++	return 0;
++}
++
++static __poll_t npcm7xx_vdm_poll(struct file *file,
++				 struct poll_table_struct *pt)
++{
++	struct miscdevice *misc = file->private_data;
++	struct platform_device *pdev = to_platform_device(misc->parent);
++	struct npcm7xx_vdm *priv = platform_get_drvdata(pdev);
++
++	__poll_t ret = 0;
++
++	poll_wait(file, &priv->wait_queue, pt);
++
++	if (__ptr_ring_peek(&priv->rx_queue))
++		ret |= EPOLLIN;
++
++	return ret;
++}
++
++const struct file_operations npcm7xx_vdm_fops = {
++	.llseek = noop_llseek,
++	.open = npcm7xx_vdm_open,
++	.read = npcm7xx_vdm_read,
++	.write = npcm7xx_vdm_write,
++	.release = npcm7xx_vdm_release,
++	.poll = npcm7xx_vdm_poll,
++};
++
++static int npcm7xx_vdm_config_irq(struct npcm7xx_vdm *priv)
++{
++	struct platform_device *pdev = to_platform_device(priv->dev);
++	int irq, ret;
++
++	irq = platform_get_irq(pdev, 0);
++	if (!irq)
++		return -ENODEV;
++
++	ret = devm_request_irq(priv->dev, irq, npcm7xx_vdm_irq, IRQF_SHARED, DEVICE_NAME, priv);
++	if (ret < 0) {
++		dev_err(priv->dev, "Unable to request IRQ %d\n", irq);
++		return ret;
++	}
++
++	return 0;
++}
++
++static void npcm7xx_vdm_tsk_init(struct npcm7xx_vdm *priv)
++{
++	spin_lock_init(&priv->lock);
++	init_waitqueue_head(&priv->wait_queue);
++
++	ptr_ring_init(&priv->rx_queue, VDMX_RX_LEN, GFP_ATOMIC);
++
++	tasklet_init(&priv->tasklet, npcm7xx_vdm_rx_tasklet,
++		     (unsigned long)priv);
++}
++
++static void npcm7xx_vdm_tsk_fini(struct npcm7xx_vdm *priv)
++{
++	tasklet_disable(&priv->tasklet);
++	tasklet_kill(&priv->tasklet);
++}
++
++static const struct regmap_config npcm7xx_vdmx_regmap_cfg = {
++	.reg_bits       = 32,
++	.reg_stride     = 4,
++	.val_bits       = 32,
++	.max_register   = VDMX_RXFILT,
++};
++
++static const struct regmap_config npcm7xx_vdma_regmap_cfg = {
++	.reg_bits       = 32,
++	.reg_stride     = 4,
++	.val_bits       = 32,
++	.max_register   = VDMA_EST1DT,
++};
++
++static int npcm7xx_vdm_resources_init(struct npcm7xx_vdm *priv)
++{
++	struct platform_device *pdev = to_platform_device(priv->dev);
++
++	void __iomem *regs;
++
++	regs = devm_platform_ioremap_resource(pdev, 0);
++	if (IS_ERR(regs)) {
++		dev_err(priv->dev, "Failed to get regmap!\n");
++		return PTR_ERR(regs);
++	}
++
++	priv->vdmx_base = devm_regmap_init_mmio(priv->dev, regs,
++						&npcm7xx_vdmx_regmap_cfg);
++	if (IS_ERR(priv->vdmx_base))
++		return PTR_ERR(priv->vdmx_base);
++
++	regs = devm_platform_ioremap_resource(pdev, 1);
++	if (IS_ERR(regs)) {
++		dev_err(priv->dev, "Failed to get regmap!\n");
++		return PTR_ERR(regs);
++	}
++
++	priv->vdma_base = devm_regmap_init_mmio(priv->dev, regs,
++						&npcm7xx_vdma_regmap_cfg);
++	if (IS_ERR(priv->vdma_base))
++		return PTR_ERR(priv->vdma_base);
++
++#ifdef CONFIG_ARCH_NPCM7XX
++	priv->gcr_base =
++		syscon_regmap_lookup_by_compatible("nuvoton,npcm750-gcr");
++	if (IS_ERR(priv->gcr_base)) {
++		dev_err(priv->dev, "failed to find nuvoton,npcm750-gcr\n");
++		return PTR_ERR(priv->gcr_base);
++	}
++#endif
++	platform_set_drvdata(pdev, priv);
++
++	return 0;
++}
++
++static int npcm7xx_vdm_dma_init(struct npcm7xx_vdm *priv)
++{
++	priv->virt = dma_alloc_coherent(priv->dev, VDMA_BUFFER_SIZE,
++					&priv->dma, GFP_KERNEL);
++	if (!priv->virt)
++		return -ENOMEM;
++
++	return 0;
++}
++
++static void npcm7xx_vdm_dma_fini(struct npcm7xx_vdm *priv)
++{
++	dma_free_coherent(priv->dev, VDMA_BUFFER_SIZE,
++			  priv->virt, priv->dma);
++}
++
++struct device_type npcm7xx_vdm_type = {
++	.name		= DEVICE_NAME,
++};
++
++static struct miscdevice npcm7xx_vdm_miscdev = {
++	.minor = MISC_DYNAMIC_MINOR,
++	.name = DEVICE_NAME,
++	.fops = &npcm7xx_vdm_fops,
++};
++
++static int npcm_vdm_probe(struct platform_device *pdev)
++{
++	struct npcm7xx_vdm *priv;
++	int ret;
++
++	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
++	if (!priv) {
++		ret = -ENOMEM;
++		goto out;
++	}
++	priv->dev = &pdev->dev;
++	dev_set_drvdata(&pdev->dev, priv);
++
++	ret = npcm7xx_vdm_resources_init(priv);
++	if (ret) {
++		dev_err(priv->dev, "Failed to init resources\n");
++		goto out_drv;
++	}
++
++	ret = npcm7xx_vdm_dma_init(priv);
++	if (ret) {
++		dev_err(priv->dev, "Failed to init DMA\n");
++		goto out_drv;
++	}
++
++	/* register miscdev */
++	npcm7xx_vdm_miscdev.parent = priv->dev;
++	ret = misc_register(&npcm7xx_vdm_miscdev);
++	if (ret) {
++		dev_err(priv->dev, "Failed to register miscdev\n");
++		goto out_dma;
++	}
++	npcm7xx_vdm_miscdev.this_device->type = &npcm7xx_vdm_type;
++
++	npcm7xx_vdm_hw_finit(priv);
++
++	npcm7xx_vdm_tsk_init(priv);
++
++	ret = npcm7xx_vdm_config_irq(priv);
++	if (ret) {
++		dev_err(priv->dev, "Failed to configure IRQ\n");
++		goto out_dma;
++	}
++
++	pr_info("NPCM7XX VDM Driver probed\n");
++
++	return 0;
++
++out_dma:
++	npcm7xx_vdm_dma_fini(priv);
++out_drv:
++	npcm7xx_vdm_tsk_fini(priv);
++out:
++	dev_err(priv->dev, "Failed to probe Nuvoton VDM: %d\n", ret);
++	return ret;
++}
++
++static int npcm_vdm_remove(struct platform_device *pdev)
++{
++	struct npcm7xx_vdm *priv = platform_get_drvdata(pdev);
++
++	if (!priv)
++		return 0;
++
++	misc_deregister(&npcm7xx_vdm_miscdev);
++
++	ptr_ring_cleanup(&priv->rx_queue, &packet_free);
++
++	npcm7xx_vdm_hw_finit(priv);
++
++	npcm7xx_vdm_dma_fini(priv);
++
++	npcm7xx_vdm_tsk_fini(priv);
++
++	kfree(priv);
++
++	return 0;
++}
++
++static const struct of_device_id npcm7xx_vdm_match[] = {
++	{ .compatible = "nuvoton,npcm750-vdm", },
++	{ .compatible = "nuvoton,npcm845-vdm", },
++	{},
++};
++
++static struct platform_driver npcm_vdm_driver = {
++	.probe          = npcm_vdm_probe,
++	.remove			= npcm_vdm_remove,
++	.driver         = {
++		.name   = DEVICE_NAME,
++		.owner	= THIS_MODULE,
++		.of_match_table = npcm7xx_vdm_match,
++	},
++};
++
++static int __init npcm_vdm_init(void)
++{
++	packet_cache =
++		kmem_cache_create_usercopy("mctp-packet",
++					   sizeof(struct mctp_pcie_packet),
++					   0, 0, 0,
++					   sizeof(struct mctp_pcie_packet),
++					   NULL);
++	if (!packet_cache)
++		return -ENOMEM;
++
++	return platform_driver_register(&npcm_vdm_driver);
++}
++
++static void __exit npcm_vdm_exit(void)
++{
++	platform_driver_unregister(&npcm_vdm_driver);
++	kmem_cache_destroy(packet_cache);
++}
++
++module_init(npcm_vdm_init)
++module_exit(npcm_vdm_exit)
++
++MODULE_DEVICE_TABLE(of, npcm7xx_vdm_match);
++MODULE_AUTHOR("Nuvoton Technology Corp.");
++MODULE_DESCRIPTION("VDM Master Driver");
++MODULE_LICENSE("GPL");
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/defconfig b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/defconfig
new file mode 100644
index 0000000..cbc3fd2
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/defconfig
@@ -0,0 +1,130 @@
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_LOG_BUF_SHIFT=21
+CONFIG_CGROUPS=y
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+CONFIG_SLAB=y
+CONFIG_ARCH_NPCM=y
+CONFIG_ARCH_NPCM7XX=y
+CONFIG_SMP=y
+CONFIG_VMSPLIT_3G_OPT=y
+CONFIG_ARM_CRYPTO=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_SHA512=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BINFMT_MISC=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_DEVTMPFS=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_PARTITIONED_MASTER=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_OF_OVERLAY=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_NPCM7XX_LPC_BPC=y
+CONFIG_NPCM7XX_PCI_MBOX=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+CONFIG_NPCM7XX_EMC_ETH=y
+CONFIG_STMMAC_ETH=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_NPCM7XX_KCS_IPMI_BMC=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_NPCM7XX=y
+CONFIG_SPI=y
+CONFIG_SPI_NPCM_FIU=y
+CONFIG_SPI_NPCM_PSPI=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_SENSORS_LM75=y
+CONFIG_SENSORS_NPCM7XX=y
+CONFIG_SENSORS_TMP102=y
+CONFIG_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_EDAC=y
+# CONFIG_EDAC_LEGACY_SYSFS is not set
+CONFIG_EDAC_NPCM7XX=y
+CONFIG_IIO=y
+CONFIG_NPCM_ADC=y
+CONFIG_IIO_MUX=y
+CONFIG_RAS=y
+CONFIG_MUX_MMIO=y
+CONFIG_OVERLAY_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_ROMFS_FS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_CIFS=y
+CONFIG_CIFS_XATTR=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_DYNAMIC_DEBUG=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_INFO_REDUCED=y
+CONFIG_READABLE_ASM=y
+CONFIG_DEBUG_SECTION_MISMATCH=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_FUNCTION_TRACER=y
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/npcm8xx_defconfig b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/npcm8xx_defconfig
new file mode 100644
index 0000000..fb6009d
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/npcm8xx_defconfig
@@ -0,0 +1,188 @@
+CONFIG_SYSVIPC=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_PREEMPT=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_NUMA_BALANCING=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_HUGETLB=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_PERF=y
+CONFIG_USER_NS=y
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_ARM_CPUIDLE=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_ARCH_NPCM=y
+CONFIG_ARCH_NPCM8XX=y
+CONFIG_SMP=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_OF_OVERLAY=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_NBD=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_NPCM7XX_LPC_BPC=y
+CONFIG_NPCM7XX_PCI_MBOX=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_NETDEVICES=y
+CONFIG_STMMAC_ETH=y
+CONFIG_BROADCOM_PHY=y
+CONFIG_PINCTRL_NPCM8XX=y
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_SLAVE=y
+CONFIG_I2C_NPCM7XX=y
+CONFIG_I3C=y
+CONFIG_I3CDEV=y
+CONFIG_SVC_I3C_MASTER=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_NPCM7XX_KCS_IPMI_BMC=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_NPCM=y
+CONFIG_SPI=y
+CONFIG_SPI_NPCM_PSPI=y
+CONFIG_SPI_NPCM_FIU=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_GENERIC_PLATFORM=y
+CONFIG_SENSORS_LM75=y
+CONFIG_SENSORS_NPCM8XX=y
+CONFIG_SENSORS_TMP102=y
+CONFIG_WATCHDOG=y
+CONFIG_NPCM7XX_WATCHDOG=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_CHIPIDEA=y
+CONFIG_USB_CHIPIDEA_UDC=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_NPCM_UDC=y
+CONFIG_USB_GADGET_NPCM_USB2=y
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_NPCM750=y
+CONFIG_ROMFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+CONFIG_CRYPTO_DEV_NPCM=y
+CONFIG_CRYPTO_DEV_NPCM_AES=y
+CONFIG_CRYPTO_DEV_NPCM_SHA=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_NPCM750_OTP=y
+CONFIG_ARM_CRYPTO=y
+CONFIG_PCI=y
+CONFIG_PCIE_NPCM=y
+CONFIG_PECI=y
+CONFIG_PECI_NPCM=y
+CONFIG_MFD_INTEL_PECI_CLIENT=y
+CONFIG_SENSORS_PECI_CPUTEMP=y
+CONFIG_SENSORS_PECI_DIMMTEMP=y
+CONFIG_RESET_NPCM=y
+CONFIG_SENSORS_NPCM7XX=y
+
+CONFIG_IPMI_KCS_BMC=y
+CONFIG_NPCM7XX_KCS_IPMI_BMC=y
+CONFIG_NPCM_VDM=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_THERMAL=y
+CONFIG_NPCM_THERMAL=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MDIO_BITBANG=y
+CONFIG_MDIO_GPIO=y
+CONFIG_TMPFS=y
+CONFIG_EXPERT=y
+
+# Enable KVM Support
+CONFIG_NPCM750_VCD=y
+CONFIG_NPCM750_ECE=y
+
+# Enable JTAG Master Support
+CONFIG_NPCM8XX_JTAG_MASTER=y
+
+# Enable OpenBMC FS support
+CONFIG_OVERLAY_FS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
+CONFIG_DEBUG_FS=y
+
+# Enable EDAC support
+CONFIG_EDAC_SUPPORT=y
+CONFIG_EDAC=y
+CONFIG_EDAC_NPCM8XX=y
+CONFIG_RAS=y
+
+# Enable RemotePorc driver support
+CONFIG_REMOTEPROC=y
+CONFIG_NPCM8XX_REMOTEPROC=y
+
+# Enable SGPIO Driver support
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_NUVOTON_SGPIO=y
+
+# Enable ADC
+CONFIG_NPCM_ADC=y
+CONFIG_IIO=y
+CONFIG_SENSORS_IIO_HWMON=y
+
+# CONFIG_VGA_ARB is not set
+# CONFIG_VGA_ARB_MAX_GPUS is not set
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/v4l2.cfg b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/v4l2.cfg
new file mode 100644
index 0000000..50f53a2
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton/v4l2.cfg
@@ -0,0 +1,13 @@
+CONFIG_CMA=y
+CONFIG_CMA_AREAS=7
+CONFIG_DMA_CMA=y
+CONFIG_CMA_SIZE_MBYTES=32
+CONFIG_CMA_SIZE_SEL_MBYTES=y
+CONFIG_CMA_ALIGNMENT=8
+CONFIG_FORCE_MAX_ZONEORDER=12
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_NUVOTON=y
diff --git a/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton_git.bb b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton_git.bb
new file mode 100644
index 0000000..224898e
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-kernel/linux/linux-nuvoton_git.bb
@@ -0,0 +1,21 @@
+
+#KBRANCH ?= "dev-5.14"
+#LINUX_VERSION ?= "5.14"
+#SRCREV="e2413239f9a751a2a7491569d27dce76773f2777"
+
+KBRANCH ?= "NPCM-5.10-OpenBMC"
+LINUX_VERSION ?= "5.10.67"
+SRCREV = "12abb777ddcade8549704016eb1c233244892355"
+
+require linux-nuvoton.inc
+
+SRC_URI:append:nuvoton = " file://0003-i2c-nuvoton-npcm750-runbmc-integrate-the-slave-mqueu.patch"
+SRC_URI:append:nuvoton = " file://0004-driver-ncsi-replace-del-timer-sync.patch"
+SRC_URI:append:nuvoton = " file://0015-driver-misc-nuvoton-vdm-support-openbmc-libmctp.patch"
+SRC_URI:append:nuvoton = " file://0017-drivers-i2c-workaround-for-i2c-slave-behavior.patch"
+
+# V4L2 VCD driver
+# SRC_URI:append:nuvoton = " file://v4l2.cfg"
+
+# New Arch VDMX/VDMA driver
+# SRC_URI:append:nuvoton = " file://2222-driver-misc-add-nuvoton-vdmx-vdma-driver.patch"
diff --git a/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/files/mcu-update.service b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/files/mcu-update.service
new file mode 100644
index 0000000..95ba4bd
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/files/mcu-update.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=NPCM7xx MCU F/W update service
+
+[Service]
+ExecStart=/usr/bin/loadmcu -d /dev/mcu0 -s /tmp/image-mcu
+Type=oneshot
+ExecStopPost=/bin/systemctl start mcu-version@* --all
diff --git a/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/files/mcu-version.sh b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/files/mcu-version.sh
new file mode 100644
index 0000000..b855aa7
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/files/mcu-version.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+sleep 1
+
+i2c_bus=$(echo $1)
+
+# get mcu firmware version
+version=$(i2ctransfer -f -y $i2c_bus w2@0x70 0x01 0x30 r2)
+
+# parse mcu firmware major revision
+major=`echo $version | awk '{print$2}'`
+
+# parse mcu firmware minor revision
+minor=`echo $version | awk '{print$1}'`
+
+version="V`echo $((major))`.`echo $((minor))`"
+
+if [ $version != "V0.0" ]; then
+   echo "VERSION_ID=$version" > /var/lib/phosphor-bmc-code-mgmt/mcu-release
+else
+   echo "VERSION_ID=N/A" > /var/lib/phosphor-bmc-code-mgmt/mcu-release
+fi
diff --git a/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/files/mcu-version@.service b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/files/mcu-version@.service
new file mode 100644
index 0000000..6e622ef
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/files/mcu-version@.service
@@ -0,0 +1,13 @@
+[Unit]
+Description=NPCM7xx MCU F/W version service
+Requires=xyz.openbmc_project.Software.BMC.Updater.service
+Before=xyz.openbmc_project.Software.BMC.Updater.service
+
+[Service]
+Restart=no
+Type=oneshot
+ExecStart=/usr/bin/mcu-version.sh %i
+SyslogIdentifier=mcu-version.sh
+
+[Install]
+WantedBy={SYSTEMD_DEFAULT_TARGET}
diff --git a/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/loadmcu.bb b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/loadmcu.bb
new file mode 100644
index 0000000..cbd08ee
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadmcu/loadmcu.bb
@@ -0,0 +1,31 @@
+FILESEXTRAPATHS:prepend := "${THISDIR}:"
+DESCRIPTION = "MCU F/W Programmer"
+PR = "r1"
+
+LICENSE = "GPL-2.0-or-later"
+LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+
+inherit systemd
+inherit obmc-phosphor-systemd
+inherit autotools pkgconfig
+
+DEPENDS += "systemd"
+DEPENDS += "autoconf-archive-native"
+RDEPENDS:${PN} += "bash"
+
+SRC_URI = "git://github.com/Nuvoton-Israel/loadmcu.git;branch=master;protocol=https \
+           file://mcu-update.service \
+           file://mcu-version.sh \
+           file://mcu-version@.service \
+          "
+SRCREV = "12fed94b53f6fa0fe1c96bee264c7e363f2ed7d8"
+S = "${WORKDIR}/git"
+
+SYSTEMD_PACKAGES = "${PN}"
+SYSTEMD_SERVICE:${PN} = "mcu-update.service mcu-version@.service"
+SYSTEMD_SERVICE:${PN} += "mcu-version@13.service"
+
+do_install:append() {
+    install -d ${D}${bindir}
+    install -m 0755 ${WORKDIR}/mcu-version.sh ${D}${bindir}/
+}
diff --git a/meta-nuvoton-npcm8xx/recipes-nuvoton/loadsvf/loadsvf_git.bb b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadsvf/loadsvf_git.bb
new file mode 100644
index 0000000..956ffa8
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-nuvoton/loadsvf/loadsvf_git.bb
@@ -0,0 +1,14 @@
+DESCRIPTION = "CPLD/FPGA Programmer"
+PR = "r1"
+
+LICENSE = "GPL-2.0-or-later"
+LIC_FILES_CHKSUM = "file://COPYING;md5=b234ee4d69f5fce4486a80fdaf4a4263"
+
+SRC_URI = "git://github.com/Nuvoton-Israel/loadsvf.git;branch=master;protocol=https"
+SRCREV = "f2296005cbba13b49e5163340cac80efbec9cdf4"
+S = "${WORKDIR}/git"
+
+inherit autotools pkgconfig
+
+DEPENDS += "autoconf-archive-native"
+
diff --git a/meta-nuvoton-npcm8xx/recipes-nuvoton/nuvoton-ipmi/nuvoton-ipmi-oem_git.bb b/meta-nuvoton-npcm8xx/recipes-nuvoton/nuvoton-ipmi/nuvoton-ipmi-oem_git.bb
new file mode 100644
index 0000000..d0c7314
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-nuvoton/nuvoton-ipmi/nuvoton-ipmi-oem_git.bb
@@ -0,0 +1,28 @@
+SUMMARY = "Nuvoton IPMI OEM command library"
+DESCRIPTION = "Nuvoton IPMI OEM command library"
+HOMEPAGE = "https://github.com/nuvoton-ipmi-oem"
+PR = "r1"
+PV = "0.1+git${SRCPV}"
+LICENSE = "Apache-2.0"
+LIC_FILES_CHKSUM = "file://LICENSE;md5=ce3556061e8d4b01638d497053a82dfd"
+
+inherit autotools pkgconfig
+inherit obmc-phosphor-ipmiprovider-symlink
+
+DEPENDS += "autoconf-archive-native"
+DEPENDS += "sdbusplus"
+DEPENDS += "phosphor-logging"
+DEPENDS += "phosphor-ipmi-host"
+DEPENDS += "nlohmann-json"
+
+S = "${WORKDIR}/git"
+SRCBRANCH = "master"
+SRC_URI = "git://github.com/Nuvoton-Israel/nuvoton-ipmi-oem;protocol=https;branch=${SRCBRANCH}"
+SRCREV = "50d80e64a01d933c10484da63b447d6a27b8b702"
+
+FILES:${PN}:append = " ${libdir}/ipmid-providers/lib*${SOLIBS}"
+FILES:${PN}:append = " ${libdir}/host-ipmid/lib*${SOLIBS}"
+FILES:${PN}:append = " ${libdir}/net-ipmid/lib*${SOLIBS}"
+FILES:${PN}-dev:append = " ${libdir}/ipmid-providers/lib*${SOLIBSDEV} ${libdir}/ipmid-providers/*.la"
+
+HOSTIPMI_PROVIDER_LIBRARY += "libnuvoemcmds.so"
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/ipmi/phosphor-ipmi-host/0001-Use-numeric-limit-is-intergral-replace-std-is-intergral.patch b/meta-nuvoton-npcm8xx/recipes-phosphor/ipmi/phosphor-ipmi-host/0001-Use-numeric-limit-is-intergral-replace-std-is-intergral.patch
new file mode 100644
index 0000000..c3a521d
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/ipmi/phosphor-ipmi-host/0001-Use-numeric-limit-is-intergral-replace-std-is-intergral.patch
@@ -0,0 +1,34 @@
+diff --git a/include/ipmid/message/pack.hpp b/include/ipmid/message/pack.hpp
+index 00750007..9c45d514 100644
+--- a/include/ipmid/message/pack.hpp
++++ b/include/ipmid/message/pack.hpp
+@@ -77,7 +77,7 @@ struct PackSingle
+      */
+     static int op(Payload& p, const T& t)
+     {
+-        static_assert(std::is_integral_v<T>,
++        static_assert(std::numeric_limits<T>::is_integer,
+                       "Attempt to pack a type that has no IPMI pack operation");
+         // if not on a byte boundary, must pack values LSbit/LSByte first
+         if (p.bitCount)
+diff --git a/include/ipmid/message/unpack.hpp b/include/ipmid/message/unpack.hpp
+index 4ac49165..3f9c6832 100644
+--- a/include/ipmid/message/unpack.hpp
++++ b/include/ipmid/message/unpack.hpp
+@@ -16,6 +16,7 @@
+ #pragma once
+ 
+ #include <array>
++#include <boost/type_traits/is_fundamental.hpp>
+ #include <ipmid/message/types.hpp>
+ #include <optional>
+ #include <string>
+@@ -74,7 +75,7 @@ struct UnpackSingle
+      */
+     static int op(Payload& p, T& t)
+     {
+-        if constexpr (std::is_fundamental<T>::value)
++        if constexpr (std::numeric_limits<T>::is_integer)
+         {
+             t = 0;
+             if (p.bitCount)
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend b/meta-nuvoton-npcm8xx/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
new file mode 100644
index 0000000..eba096e
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/ipmi/phosphor-ipmi-host_%.bbappend
@@ -0,0 +1,4 @@
+FILESEXTRAPATHS:append:nuvoton := "${THISDIR}/${PN}:"
+
+# Fix static assert build break
+SRC_URI:append:nuvoton = " file://0001-Use-numeric-limit-is-intergral-replace-std-is-intergral.patch"
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui/0001-novnc-add-16-bit-hextile-support-for-nuvoton-ece-eng.patch b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui/0001-novnc-add-16-bit-hextile-support-for-nuvoton-ece-eng.patch
new file mode 100644
index 0000000..00b739b
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui/0001-novnc-add-16-bit-hextile-support-for-nuvoton-ece-eng.patch
@@ -0,0 +1,42 @@
+From 1c23639acdbc68b36b30ed0ef9d3922142985975 Mon Sep 17 00:00:00 2001
+From: Joseph Liu <kwliu@nuvoton.com>
+Date: Tue, 12 May 2020 17:01:29 +0800
+Subject: [PATCH] novnc: add 16-bit hextile support for nuvoton ece engine
+
+Signed-off-by: Joseph Liu <kwliu@nuvoton.com>
+---
+ package-lock.json | 4 ++--
+ package.json      | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/package-lock.json b/package-lock.json
+index 47b22a2e..054ca32f 100644
+--- a/package-lock.json
++++ b/package-lock.json
+@@ -935,8 +935,8 @@
+       }
+     },
+     "@novnc/novnc": {
+-      "version": "git+https://github.com/novnc/noVNC.git#25b3d49d322b0a7c9ee1e071d93042d70f5176b7",
+-      "from": "@novnc/novnc@git+https://github.com/novnc/noVNC.git#25b3d49d322b0a7c9ee1e071d93042d70f5176b7"
++      "version": "Nuvoton-Israel/noVNC.git#openbmc-v1.2.0",
++      "from": "@novnc/novnc@Nuvoton-Israel/noVNC.git#openbmc-v1.2.0"
+     },
+     "@types/anymatch": {
+       "version": "1.3.1",
+diff --git a/package.json b/package.json
+index 7e808df4..517f86e0 100644
+--- a/package.json
++++ b/package.json
+@@ -35,7 +35,7 @@
+     "node"
+   ],
+   "dependencies": {
+-    "@novnc/novnc": "git+https://github.com/novnc/noVNC.git#25b3d49d322b0a7c9ee1e071d93042d70f5176b7",
++    "@novnc/novnc": "Nuvoton-Israel/noVNC.git#openbmc-v1.1.0",
+     "angular": "1.7.9",
+     "angular-animate": "1.7.9",
+     "angular-clipboard": "1.7.0",
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui/0002-support-pldm-sensors-effecters.patch b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui/0002-support-pldm-sensors-effecters.patch
new file mode 100644
index 0000000..e2c49a3
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui/0002-support-pldm-sensors-effecters.patch
@@ -0,0 +1,888 @@
+commit 61623e4129178233eeaf5a0f0e7013271f5a88d2
+Author: Medad CChien <ctcchien@nuvoton.com>
+Date:   Mon Mar 15 09:38:57 2021 +0800
+
+    support pldm sensors and effecters
+    
+    Signed-off-by: Medad CChien <ctcchien@nuvoton.com>
+
+diff --git a/app/common/directives/app-navigation.html b/app/common/directives/app-navigation.html
+index 41441e27..04fa60eb 100644
+--- a/app/common/directives/app-navigation.html
++++ b/app/common/directives/app-navigation.html
+@@ -27,6 +27,11 @@
+             <span>Sensors</span>
+           </a>
+         </li>
++        <li ng-class="{'active': (path == '/server-health/pldm-overview' || path == '/server-health/pldm')}">
++          <a href="#/server-health/pldm-overview" tabindex="{{(showHealthMenu) ? 0 : -1}}">
++            <span>PLDM</span>
++          </a>
++        </li>
+       </ul>
+     </li>
+     <li ng-class="{opened: showControlMenu}">
+@@ -116,4 +121,4 @@
+       </ul>
+     </li>
+   </ul>
+-</nav>
+\ No newline at end of file
++</nav>
+diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
+index f10476d8..2a1fd1f8 100644
+--- a/app/common/services/api-utils.js
++++ b/app/common/services/api-utils.js
+@@ -1051,6 +1051,359 @@ window.angular && (function(angular) {
+                     console.log(error);
+                   });
+         },
++        getAllNumericSensorStatus: function(callback) {
++          $http({
++            method: 'GET',
++            url: DataService.getHost() +
++                '/xyz/openbmc_project/numericsensors/enumerate',
++            withCredentials: true
++          })
++              .then(
++                  function(response) {
++                    var json = JSON.stringify(response.data);
++                    var content = JSON.parse(json);
++                    var dataClone = JSON.parse(JSON.stringify(content.data));
++                    var sensorData = [];
++                    var severity = {};
++                    var title = '';
++                    var tempKeyParts = [];
++                    var order = 0;
++                    var customOrder = 0;
++
++                    function getSensorStatus(reading) {
++                      var severityFlags = {
++                        critical: false,
++                        warning: false,
++                        normal: false
++                      },
++                          severityText = '', order = 0;
++
++                      if (reading.hasOwnProperty('CriticalLow') &&
++                          reading.Value < reading.CriticalLow) {
++                        severityFlags.critical = true;
++                        severityText = 'critical';
++                        order = 2;
++                      } else if (
++                          reading.hasOwnProperty('CriticalHigh') &&
++                          reading.Value > reading.CriticalHigh) {
++                        severityFlags.critical = true;
++                        severityText = 'critical';
++                        order = 2;
++                      } else if (
++                          reading.hasOwnProperty('CriticalLow') &&
++                          reading.hasOwnProperty('WarningLow') &&
++                          reading.Value >= reading.CriticalLow &&
++                          reading.Value <= reading.WarningLow) {
++                        severityFlags.warning = true;
++                        severityText = 'warning';
++                        order = 1;
++                      } else if (
++                          reading.hasOwnProperty('WarningHigh') &&
++                          reading.hasOwnProperty('CriticalHigh') &&
++                          reading.Value >= reading.WarningHigh &&
++                          reading.Value <= reading.CriticalHigh) {
++                        severityFlags.warning = true;
++                        severityText = 'warning';
++                        order = 1;
++                      } else {
++                        severityFlags.normal = true;
++                        severityText = 'normal';
++                      }
++                      return {
++                        flags: severityFlags,
++                        severityText: severityText,
++                        order: order
++                      };
++                    }
++
++                    for (var key in content.data) {
++                      if (content.data.hasOwnProperty(key) &&
++                          content.data[key].hasOwnProperty('Unit')) {
++                        severity = getSensorStatus(content.data[key]);
++
++                        if (!content.data[key].hasOwnProperty('CriticalLow')) {
++                          content.data[key].CriticalLow = '--';
++                          content.data[key].CriticalHigh = '--';
++                        }
++
++                        if (!content.data[key].hasOwnProperty('WarningLow')) {
++                          content.data[key].WarningLow = '--';
++                          content.data[key].WarningHigh = '--';
++                        }
++
++                        tempKeyParts = key.split('/');
++                        title = tempKeyParts.pop();
++                        title = tempKeyParts.pop() + '_' + title;
++                        title = title.split('_')
++                                    .map(function(item) {
++                                      return item.toLowerCase()
++                                                 .charAt(0)
++                                                 .toUpperCase() +
++                                          item.slice(1);
++                                    })
++                                    .reduce(function(prev, el) {
++                                      return prev + ' ' + el;
++                                    });
++
++                        if (Constants.SENSOR_SORT_ORDER.indexOf(
++                                content.data[key].Unit) > -1) {
++                          customOrder = Constants.SENSOR_SORT_ORDER.indexOf(
++                              content.data[key].Unit);
++                        } else {
++                          customOrder = Constants.SENSOR_SORT_ORDER_DEFAULT;
++                        }
++
++                        sensorData.push(Object.assign(
++                            {
++                              path: key,
++                              selected: false,
++                              confirm: false,
++                              copied: false,
++                              title: title,
++                              unit:
++                                  Constants
++                                      .SENSOR_UNIT_MAP[content.data[key].Unit],
++                              severity_flags: severity.flags,
++                              status: severity.severityText,
++                              order: severity.order,
++                              custom_order: customOrder,
++                              search_text:
++                                  (title + ' ' + content.data[key].Value + ' ' +
++                                   Constants.SENSOR_UNIT_MAP[content.data[key]
++                                                                 .Unit] +
++                                   ' ' + severity.severityText + ' ' +
++                                   content.data[key].CriticalLow + ' ' +
++                                   content.data[key].CriticalHigh + ' ' +
++                                   content.data[key].WarningLow + ' ' +
++                                   content.data[key].WarningHigh + ' ')
++                                      .toLowerCase(),
++                              original_data:
++                                  {key: key, value: content.data[key]}
++                            },
++                            content.data[key]));
++                      }
++                    }
++
++                    sensorData.sort(function(a, b) {
++                      return a.title.localeCompare(
++                          b.title, 'en', {numeric: true});
++                    });
++
++                    callback(sensorData, dataClone);
++                  },
++                  function(error) {
++                    console.log(error);
++                  });
++        },
++        toggleEffecterState: function(path, state) {
++          return $http({
++                   method: 'PUT',
++                   url: DataService.getHost() + path + '/attr/setDeviceState',
++                   //url: DataService.getHost() + '/xyz/openbmc_project/effecters/GPIO/PLDM_GPIO91' + '/attr/setDeviceState',
++                   //url: DataService.getHost() + '/xyz/openbmc_project/numericeffecters/FAN_PWM/PLDM_FAN_PWM1' + '/attr/setNumericValue',
++                   withCredentials: true,
++                   data: JSON.stringify({'data': state})
++                 })
++              .then(function(response) {
++                return response.data;
++              });
++        },
++        setEffecterValue: function(path, value) {
++          return $http({
++                   method: 'PUT',
++                   url: DataService.getHost() + path + '/attr/setNumericValue',
++                   //url: DataService.getHost() + '/xyz/openbmc_project/numericeffecters/FAN_PWM/PLDM_FAN_PWM1' + '/attr/setNumericValue',
++                   //url: DataService.getHost() + '/xyz/openbmc_project/numericeffecters/FAN_PWM/PLDM_FAN_PWM1' + '/attr/setDeviceState',
++                   withCredentials: true,
++                   data: JSON.stringify({'data': value})
++                 })
++              .then(function(response) {
++                return response.data;
++              });
++        },
++        getAllEffecterStatus: function(callback) {
++          $http({
++            method: 'GET',
++            url: DataService.getHost() +
++                '/xyz/openbmc_project/stateeffecters/enumerate',
++            withCredentials: true
++          })
++              .then(
++                  function(response) {
++                    var json = JSON.stringify(response.data);
++                    var content = JSON.parse(json);
++                    var dataClone = JSON.parse(JSON.stringify(content.data));
++                    var effecterData = [];
++                    var title = '';
++                    var tempKeyParts = [];
++ 
++                    for (var key in content.data) {
++                      if (content.data.hasOwnProperty(key)) {
++
++                        tempKeyParts = key.split('/');
++                        title = tempKeyParts.pop();
++                        title = tempKeyParts.pop() + '_' + title;
++                        title = title.split('_')
++                                    .map(function(item) {
++                                      return item.toLowerCase()
++                                                 .charAt(0)
++                                                 .toUpperCase() +
++                                          item.slice(1);
++                                    })
++                                    .reduce(function(prev, el) {
++                                      return prev + ' ' + el;
++                                    });
++
++                        effecterData.push(Object.assign(
++                            {
++                              path: key,
++                              selected: false,
++                              confirm: false,
++                              copied: false,
++                              title: title,
++                              search_text:
++                                  (title + ' ' + content.data[key].Value + ' ')
++                                      .toLowerCase(),
++                              original_data:
++                                  {key: key, value: content.data[key]}
++                            },
++                            content.data[key]));
++                      }
++                    }
++
++                    effecterData.sort(function(a, b) {
++                      return a.title.localeCompare(
++                          b.title, 'en', {numeric: true});
++                    });
++
++                    callback(effecterData, dataClone);
++                  },
++                  function(error) {
++                    console.log(error);
++                  });
++        },
++        getAllNumericEffecterStatus: function(callback) {
++          $http({
++            method: 'GET',
++            url: DataService.getHost() +
++                '/xyz/openbmc_project/numericeffecters/enumerate',
++            withCredentials: true
++          })
++              .then(
++                  function(response) {
++                    var json = JSON.stringify(response.data);
++                    var content = JSON.parse(json);
++                    var dataClone = JSON.parse(JSON.stringify(content.data));
++                    var statesensorData = [];
++                    var title = '';
++                    var tempKeyParts = [];
++ 
++                    for (var key in content.data) {
++                      if (content.data.hasOwnProperty(key)) {
++
++                        tempKeyParts = key.split('/');
++                        title = tempKeyParts.pop();
++                        title = tempKeyParts.pop() + '_' + title;
++                        title = title.split('_')
++                                    .map(function(item) {
++                                      return item.toLowerCase()
++                                                 .charAt(0)
++                                                 .toUpperCase() +
++                                          item.slice(1);
++                                    })
++                                    .reduce(function(prev, el) {
++                                      return prev + ' ' + el;
++                                    });
++
++                        statesensorData.push(Object.assign(
++                            {
++                              path: key,
++                              selected: false,
++                              confirm: false,
++                              copied: false,
++                              title: title,
++                              search_text:
++                                  (title + ' ' + content.data[key].Value + ' ')
++                                      .toLowerCase(),
++                              original_data:
++                                  {key: key, value: content.data[key]}
++                            },
++                            content.data[key]));
++                      }
++                    }
++
++                    statesensorData.sort(function(a, b) {
++                      return a.title.localeCompare(
++                          b.title, 'en', {numeric: true});
++                    });
++
++                    callback(statesensorData, dataClone);
++                  },
++                  function(error) {
++                    console.log(error);
++                  });
++        },
++        getAllStateSensorStatus: function(callback) {
++          $http({
++            method: 'GET',
++            url: DataService.getHost() +
++                '/xyz/openbmc_project/statesensors/enumerate',
++            withCredentials: true
++          })
++              .then(
++                  function(response) {
++                    var json = JSON.stringify(response.data);
++                    var content = JSON.parse(json);
++                    var dataClone = JSON.parse(JSON.stringify(content.data));
++                    var statesensorData = [];
++                    var title = '';
++                    var tempKeyParts = [];
++ 
++                    for (var key in content.data) {
++                      if (content.data.hasOwnProperty(key)) {
++
++                        tempKeyParts = key.split('/');
++                        title = tempKeyParts.pop();
++                        title = tempKeyParts.pop() + '_' + title;
++                        title = title.split('_')
++                                    .map(function(item) {
++                                      return item.toLowerCase()
++                                                 .charAt(0)
++                                                 .toUpperCase() +
++                                          item.slice(1);
++                                    })
++                                    .reduce(function(prev, el) {
++                                      return prev + ' ' + el;
++                                    });
++
++                        statesensorData.push(Object.assign(
++                            {
++                              path: key,
++                              selected: false,
++                              confirm: false,
++                              copied: false,
++                              title: title,
++                              search_text:
++                                  (title + ' ' + content.data[key].Value + ' ')
++                                      .toLowerCase(),
++                              original_data:
++                                  {key: key, value: content.data[key]}
++                            },
++                            content.data[key]));
++                      }
++                    }
++
++                    statesensorData.sort(function(a, b) {
++                      return a.title.localeCompare(
++                          b.title, 'en', {numeric: true});
++                    });
++
++                    callback(statesensorData, dataClone);
++                  },
++                  function(error) {
++                    console.log(error);
++                  });
++        },
+         getActivation: function(imageId) {
+           return $http({
+                    method: 'GET',
+diff --git a/app/index.js b/app/index.js
+index 156fab6b..fa0d9e6f 100644
+--- a/app/index.js
++++ b/app/index.js
+@@ -98,6 +98,7 @@ import server_health_index from './server-health/index.js';
+ import inventory_overview_controller from './server-health/controllers/inventory-overview-controller.js';
+ import log_controller from './server-health/controllers/log-controller.js';
+ import sensors_overview_controller from './server-health/controllers/sensors-overview-controller.js';
++import pldm_overview_controller from './server-health/controllers/pldm-overview-controller.js';
+ import syslog_controller from './server-health/controllers/syslog-controller.js';
+ import syslog_filter from './common/directives/syslog-filter.js';
+ import remote_logging_server from './server-health/directives/remote-logging-server.js';
+diff --git a/app/server-health/controllers/pldm-overview-controller.html b/app/server-health/controllers/pldm-overview-controller.html
+new file mode 100644
+index 00000000..1c55677b
+--- /dev/null
++++ b/app/server-health/controllers/pldm-overview-controller.html
+@@ -0,0 +1,274 @@
++<loader loading="loading"></loader>
++<div id="stateeffecters" class="sensors">
++  <h1>State Effecters</h1>
++  <div class="page-header">
++    <h2 class="inline">All state effecters present in the system</h2>
++      <a ng-href="data_state_effecter:text/json;charset=utf-8,{{export_data_state_effecter}}" class="btn btn-tertiary float-right" download="{{export_name_state_effecter}}"><icon file="icon-export.svg"></icon>Export</a>
++  </div>
++  <table id="sensor-categories" class="sensors__table" cellpadding="0" cellspacing="0" ng-show="filteredStateEffecterData.length">
++    <thead class="sensors__thead fixed-table-header">
++      <tr class="sensors__thead-row">
++        <th class="sensors__thead-cell">State Effecters ({{filteredStateEffecterData.length}})<th>
++        <th class="sensors__thead-cell">Previous State<th>
++        <th class="sensors__thead-cell sensor__heading-current">Present State<th>
++        <th class="sensors__thead-cell">Operational State<th>
++        <th class="sensors__thead-cell">Event State<th>
++        <th class="sensors__thead-cell">Toggle State<th>
++      </tr>
++    </thead>
++    <tbody class="sensors__tbody">
++      <tr class="sensors__tbody-row" ng-repeat="state_effecter in data_state_effecter as filteredStateEffecterData">
++        <th class="sensors__tbody-header">
++          <span>{{state_effecter.title}}</span>
++        </th>
++
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Previous State</span>
++          <span class="sensors__tbody-cell__content">
++              <span class="sensors__tbody-info">{{state_effecter.previous_state}}</span>
++          </span>
++        </td>
++
++        <td class="sensors__tbody-cell sensors__tbody-current" ng-class="{'sensors__tbody-current--normal': state_effecter.status == 'normal'}">
++          <span class="sensors__tbody-cell__title">Present State</span>
++          <span class="sensors__tbody-cell__content">
++              <span class="sensors__tbody-info">{{state_effecter.present_state}}</span>
++          </span>
++        </td>
++
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Operational State</span>
++          <span class="sensors__tbody-cell__content">
++            <span class="sensors__tbody-info">{{state_effecter.effecterOperationalState}}</span>
++          </span>
++        </td>
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Event State</span>
++          <span class="sensors__tbody-cell__content">
++            <span class="sensors__tbody-info">{{state_effecter.event_state}}</span>
++          </span>
++        </td>
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Toggle State</span>
++          <span class="sensors__tbody-cell__content">
++            <button class="btn" ng-class="state_effecter.present_state == state_effecter.effecterOperationalState ? 'btn-primary' : 'btn-secondary'"  ng-click="toggleEffecterState(state_effecter)">Toggle
++          </button>
++          </span>
++        </td>
++      </tr>
++    </tbody>
++  </table>
++</div>
++<div id="numericeffecters" class="sensors">
++  <h1>Numeric Effecters</h1>
++  <div class="page-header">
++    <h2 class="inline">All Numeric effecters present in the system</h2>
++      <a ng-href="data_numeric_effecter:text/json;charset=utf-8,{{export_data_numeric_effecter}}" class="btn btn-tertiary float-right" download="{{export_name_numeric_effecter}}"><icon file="icon-export.svg"></icon>Export</a>
++  </div>
++  <table id="sensor-categories" class="sensors__table" cellpadding="0" cellspacing="0" ng-show="filteredNumericStateData.length">
++    <thead class="sensors__thead fixed-table-header">
++      <tr class="sensors__thead-row">
++        <th class="sensors__thead-cell">Numeric Effecters ({{filteredNumericStateData.length}})<th>
++        <th class="sensors__thead-cell sensor__heading-current">Present Value<th>
++        <th class="sensors__thead-cell">Operational State<th>
++        <th class="sensors__thead-cell">Pending value<th>
++        <th class="sensors__thead-cell">Set Value<th>
++      </tr>
++    </thead>
++    <tbody class="sensors__tbody">
++      <tr class="sensors__tbody-row" ng-repeat="numeric_effecter in data_numeric_effecter as filteredNumericStateData">
++        <th class="sensors__tbody-header">
++          <span>{{numeric_effecter.title}}</span>
++        </th>
++
++        <td class="sensors__tbody-cell sensors__tbody-current" ng-class="{'sensors__tbody-current--normal': numeric_effecter.status == 'normal'}">
++          <span class="sensors__tbody-cell__title">Present Value</span>
++          <span class="sensors__tbody-cell__content">
++              <span class="sensors__tbody-info">{{numeric_effecter.presentValue}}</span>
++          </span>
++        </td>
++
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Operational State</span>
++          <span class="sensors__tbody-cell__content">
++            <span class="sensors__tbody-info">{{numeric_effecter.effecterOperationalState}}</span>
++          </span>
++        </td>
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Pending Value</span>
++          <span class="sensors__tbody-cell__content">
++            <span class="sensors__tbody-info">{{numeric_effecter.presentValue}}</span>
++          </span>
++        </td>
++        <td class="sensors__tbody-cell">
++          <input id="net-config__mac" type="text" ng-model="setvalue" />
++          <span class="sensors__tbody-cell__title">Set Value</span>
++          <span class="sensors__tbody-cell__content">
++            <button class="btn btn-primary"  ng-click="setEffecterValue(numeric_effecter,setvalue)">Set
++          </button>
++          </span>
++        </td>
++      </tr>
++    </tbody>
++  </table>
++</div>
++<div id="statesensors" class="sensors">
++  <h1>State Sensors</h1>
++  <div class="page-header">
++    <h2 class="inline">All state sensors present in the system</h2>
++      <a ng-href="data_state_sensor:text/json;charset=utf-8,{{export_data_state_sensor}}" class="btn btn-tertiary float-right" download="{{export_name_state_sensor}}"><icon file="icon-export.svg"></icon>Export</a>
++  </div>
++  <table id="sensor-categories" class="sensors__table" cellpadding="0" cellspacing="0" ng-show="filteredStateSensorData.length">
++    <thead class="sensors__thead fixed-table-header">
++      <tr class="sensors__thead-row">
++        <th class="sensors__thead-cell">Sensors ({{filteredStateSensorData.length}})<th>
++        <th class="sensors__thead-cell">Previous State<th>
++        <th class="sensors__thead-cell sensor__heading-current">Present State<th>
++        <th class="sensors__thead-cell">Operational State<th>
++        <th class="sensors__thead-cell">Event State<th>
++      </tr>
++    </thead>
++    <tbody class="sensors__tbody">
++      <tr class="sensors__tbody-row" ng-repeat="state_sensor in data_state_sensor as filteredStateSensorData">
++        <th class="sensors__tbody-header">
++          <span>{{state_sensor.title}}</span>
++        </th>
++
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Previous State</span>
++          <span class="sensors__tbody-cell__content">
++              <span class="sensors__tbody-info">{{state_sensor.previous_state}}</span>
++          </span>
++        </td>
++
++        <td class="sensors__tbody-cell sensors__tbody-current" ng-class="{'sensors__tbody-current--normal': state_sensor.status == 'normal'}">
++          <span class="sensors__tbody-cell__title">Present State</span>
++          <span class="sensors__tbody-cell__content">
++              <span class="sensors__tbody-info">{{state_sensor.present_state}}</span>
++          </span>
++        </td>
++
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Operational State</span>
++          <span class="sensors__tbody-cell__content">
++            <span class="sensors__tbody-info">{{state_sensor.sensorOperationalState}}</span>
++          </span>
++        </td>
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Event State</span>
++          <span class="sensors__tbody-cell__content">
++            <span class="sensors__tbody-info">{{state_sensor.event_state}}</span>
++          </span>
++        </td>
++      </tr>
++    </tbody>
++  </table>
++</div>
++<div id="numericsensors" class="sensors">
++  <h1>Numeric Sensors</h1>
++  <div class="page-header">
++    <h2 class="inline">All numeric sensors present in the system</h2>
++      <a ng-href="data_numeric_sensor:text/json;charset=utf-8,{{export_data_numeric_sensor}}" class="btn btn-tertiary float-right" download="{{export_name_numeric_sensor}}"><icon file="icon-export.svg"></icon>Export</a>
++  </div>
++
++  <div>
++    <p class="content-label" aria-label="sensors filter">Filter sensors</p>
++    <div class="content__search">
++      <label for="content__search-input">Sensors Search</label>
++      <input id="content__search-input" type="text" ng-model="customSearch" ng-keydown="doSearchOnEnter($event)"/>
++      <div class="search-submit__wrapper">
++        <button class="btn" type="button" aria-label="clear filter" ng-click="clear()">
++            <icon file="icon-close.svg" aria-hidden="true"></icon>
++        </button>
++        <input id="content__search-submit" type="submit" class="btn btn-primary content__search-submit" value="Filter" ng-click="doSearchOnClick()"/>
++      </div>
++    </div>
++
++    <div class="toggle-filter">
++      <p class="content-label">FILTER BY SEVERITY</p>
++      <button class="btn" ng-click="toggleSeverityAll()"
++          ng-class="selectedSeverity.all ? 'btn-primary' : 'btn-secondary'">All
++      </button>
++      <button class="btn" ng-click="toggleSeverity('critical')"
++          ng-class="selectedSeverity.critical ? 'btn-primary' : 'btn-secondary'">Critical
++      </button>
++      <button class="btn" ng-click="toggleSeverity('warning')"
++          ng-class="selectedSeverity.warning ? 'btn-primary' : 'btn-secondary'">Warning
++      </button>
++      <button class="btn" ng-click="toggleSeverity('normal')"
++          ng-class="selectedSeverity.normal ? 'btn-primary' : 'btn-secondary'">Normal
++      </button>
++    </div>
++  </div>
++
++  <div ng-show="filteredSensorData.length == 0">
++    <span ng-if="selectedSeverity.all">{{messages.NO_SENSOR_DATA}}</span>
++    <span ng-if="selectedSeverity.critical">{{messages.CRITICAL_NO_SENSOR_DATA}}</span>
++    <span ng-if="selectedSeverity.warning">{{messages.WARNING_NO_SENSOR_DATA}}</span>
++    <span ng-if="selectedSeverity.normal">{{messages.NORMAL_NO_SENSOR_DATA}}</span>
++  </div>
++
++  <table id="sensor-categories" class="sensors__table" cellpadding="0" cellspacing="0" ng-show="filteredSensorData.length">
++    <thead class="sensors__thead fixed-table-header">
++      <tr class="sensors__thead-row">
++        <th class="sensors__thead-cell">Sensors ({{filteredSensorData.length}})<th>
++        <th class="sensors__thead-cell">Low critical<th>
++        <th class="sensors__thead-cell">Low warning<th>
++        <th class="sensors__thead-cell sensor__heading-current">Current<th>
++        <th class="sensors__thead-cell">High warning<th>
++        <th class="sensors__thead-cell">High critical<th>
++      </tr>
++    </thead>
++    <tbody class="sensors__tbody">
++      <tr class="sensors__tbody-row" ng-repeat="sensor in data_numeric_sensor|filter:filterBySeverity|filter:filterBySearchTerms|orderBy:'+custom_order' as filteredSensorData">
++        <th class="sensors__tbody-header">
++          <status-icon status="{{ sensor.status == 'critical' ? 'error' :
++                                  sensor.status == 'warning' ? 'warn' : null }}"
++                       aria-label="Sensor status: {{sensor.status}}">
++          </status-icon>
++          <span>{{sensor.title}}</span>
++        </th>
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Low critical</span>
++          <span class="sensors__tbody-cell__content">
++              <span class="sensors__tbody-info">{{sensor.CriticalLow}}</span>
++              <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
++            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
++          </span>
++        </td>
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">Low warning</span>
++          <span class="sensors__tbody-cell__content">
++              <span class="sensors__tbody-info">{{sensor.WarningLow}}</span>
++              <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
++            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
++          </span>
++        </td>
++        <td class="sensors__tbody-cell sensors__tbody-current" ng-class="{'sensors__tbody-current--critical': sensor.status == 'critical', 'sensors__tbody-current--warn': sensor.status == 'warning', 'sensors__tbody-current--normal': sensor.status == 'normal'}">
++          <span class="sensors__tbody-cell__title">Current</span>
++          <span class="sensors__tbody-cell__content">
++              <span class="sensors__tbody-info">{{sensor.Value}}</span>
++              <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
++            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
++          </span>
++        </td>
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">High warning</span>
++          <span class="sensors__tbody-cell__content">
++            <span class="sensors__tbody-info">{{sensor.WarningHigh}}</span>
++            <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
++            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
++          </span>
++        </td>
++        <td class="sensors__tbody-cell">
++          <span class="sensors__tbody-cell__title">High critical</span>
++          <span class="sensors__tbody-cell__content">
++            <span class="sensors__tbody-info">{{sensor.CriticalHigh}}</span>
++            <span class="sensors__tbody-degree" ng-if="sensor.unit == 'C'">&deg;</span>
++            <span class="sensors__tbody-unit">{{sensor.unit}}</span>
++          </span>
++        </td>
++      </tr>
++    </tbody>
++  </table>
++</div>
+\ No newline at end of file
+diff --git a/app/server-health/controllers/pldm-overview-controller.js b/app/server-health/controllers/pldm-overview-controller.js
+new file mode 100644
+index 00000000..134a6cac
+--- /dev/null
++++ b/app/server-health/controllers/pldm-overview-controller.js
+@@ -0,0 +1,177 @@
++/**
++ * Controller for sensors-overview
++ *
++ * @module app/serverHealth
++ * @exports sensorsOverviewController
++ * @name sensorsOverviewController
++ */
++
++window.angular && (function(angular) {
++  'use strict';
++  angular.module('app.overview').controller('pldmOverviewController', [
++    '$scope', '$log', '$window', 'APIUtils', 'dataService', 'Constants',
++    function($scope, $log, $window, APIUtils, dataService, Constants) {
++      $scope.dataService = dataService;
++
++      $scope.dropdown_selected = false;
++
++      $scope.$log = $log;
++      $scope.customSearch = '';
++      $scope.searchTerms = [];
++      $scope.messages = Constants.MESSAGES.SENSOR;
++      $scope.selectedSeverity =
++          {all: true, normal: false, warning: false, critical: false};
++      $scope.export_name_state_effecter = 'state_effecters.json';
++      $scope.export_name_numeric_effecter = 'numeric_effecters.json';
++      $scope.export_name_state_sensor = 'state_sensors.json';
++      $scope.export_name_numeric_sensor = 'numeric_sensors.json';
++      $scope.loading = false;
++
++      $scope.jsonData = function(data) {
++        var dt = {};
++        data.data.forEach(function(item) {
++          dt[item.original_data.key] = item.original_data.value;
++        });
++        return JSON.stringify(dt);
++      };
++
++      $scope.clear = function() {
++        $scope.customSearch = '';
++        $scope.searchTerms = [];
++      };
++
++      $scope.doSearchOnEnter = function(event) {
++        var search =
++            $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
++        if (event.keyCode === 13 && search.length >= 2) {
++          $scope.searchTerms = $scope.customSearch.split(' ');
++        } else {
++          if (search.length == 0) {
++            $scope.searchTerms = [];
++          }
++        }
++      };
++
++      $scope.doSearchOnClick = function() {
++        var search =
++            $scope.customSearch.replace(/^\s+/g, '').replace(/\s+$/g, '');
++        if (search.length >= 2) {
++          $scope.searchTerms = $scope.customSearch.split(' ');
++        } else {
++          if (search.length == 0) {
++            $scope.searchTerms = [];
++          }
++        }
++      };
++
++      $scope.toggleSeverityAll = function() {
++        $scope.selectedSeverity.all = !$scope.selectedSeverity.all;
++
++        if ($scope.selectedSeverity.all) {
++          $scope.selectedSeverity.normal = false;
++          $scope.selectedSeverity.warning = false;
++          $scope.selectedSeverity.critical = false;
++        }
++      };
++
++      $scope.toggleSeverity = function(severity) {
++        $scope.selectedSeverity[severity] = !$scope.selectedSeverity[severity];
++
++        if (['normal', 'warning', 'critical'].indexOf(severity) > -1) {
++          if ($scope.selectedSeverity[severity] == false &&
++              (!$scope.selectedSeverity.normal &&
++               !$scope.selectedSeverity.warning &&
++               !$scope.selectedSeverity.critical)) {
++            $scope.selectedSeverity.all = true;
++            return;
++          }
++        }
++
++        if ($scope.selectedSeverity.normal && $scope.selectedSeverity.warning &&
++            $scope.selectedSeverity.critical) {
++          $scope.selectedSeverity.all = true;
++          $scope.selectedSeverity.normal = false;
++          $scope.selectedSeverity.warning = false;
++          $scope.selectedSeverity.critical = false;
++        } else {
++          $scope.selectedSeverity.all = false;
++        }
++      };
++
++      $scope.filterBySeverity = function(sensor) {
++        if ($scope.selectedSeverity.all) return true;
++
++        return (
++            (sensor.severity_flags.normal && $scope.selectedSeverity.normal) ||
++            (sensor.severity_flags.warning &&
++             $scope.selectedSeverity.warning) ||
++            (sensor.severity_flags.critical &&
++             $scope.selectedSeverity.critical));
++      };
++      $scope.filterBySearchTerms = function(sensor) {
++        if (!$scope.searchTerms.length) return true;
++
++        for (var i = 0, length = $scope.searchTerms.length; i < length; i++) {
++          if (sensor.search_text.indexOf($scope.searchTerms[i].toLowerCase()) ==
++              -1)
++            return false;
++        }
++        return true;
++      };
++
++      $scope.toggleEffecterState = function(sensor) {
++        if(sensor.effecterOperationalState != sensor.present_state) {
++          APIUtils.toggleEffecterState(sensor.path, '1');
++          sensor.present_state = '1';
++          sensor.previous_state = '2';
++          //$scope.loadEffecterData();
++          return;
++        }
++        else {
++          APIUtils.toggleEffecterState(sensor.path, '2');
++          sensor.present_state = '2';
++          sensor.previous_state = '1';
++          //$scope.loadEffecterData();
++          return;
++        }
++      };
++
++      $scope.setEffecterValue = function(sensor, setvalue) {
++        APIUtils.setEffecterValue(sensor.path, setvalue);
++        $scope.loadEffecterData();
++      };
++
++      $scope.loadEffecterData = function() {
++        $scope.loading = true;
++        APIUtils.getAllEffecterStatus(function(data, originalData) {
++          $scope.data_state_effecter = data;
++          $scope.originalData_state_effecter = originalData;
++          $scope.export_data_state_effecter = JSON.stringify(originalData);
++          $scope.loading = false;
++        });
++        $scope.loading = true;
++        APIUtils.getAllNumericEffecterStatus(function(data, originalData) {
++          $scope.data_numeric_effecter = data;
++          $scope.originalData_numeric_effecter = originalData;
++          $scope.export_data_numeric_effecter = JSON.stringify(originalData);
++          $scope.loading = false;
++        });
++        $scope.loading = true;
++        APIUtils.getAllStateSensorStatus(function(data, originalData) {
++          $scope.data_state_sensor = data;
++          $scope.originalData_state_sensor = originalData;
++          $scope.export_data_state_sensor = JSON.stringify(originalData);
++          $scope.loading = false;
++        });
++        $scope.loading = true;
++        APIUtils.getAllNumericSensorStatus(function(data, originalData) {
++          $scope.data_numeric_sensor = data;
++          $scope.originalData_numeric_sensor = originalData;
++          $scope.export_data_numeric_sensor = JSON.stringify(originalData);
++          $scope.loading = false;
++        });
++      };
++      $scope.loadEffecterData();
++    }
++  ]);
++})(angular);
+diff --git a/app/server-health/index.js b/app/server-health/index.js
+index 96172d86..173eb9cb 100644
+--- a/app/server-health/index.js
++++ b/app/server-health/index.js
+@@ -42,6 +42,12 @@ window.angular && (function(angular) {
+                 'controller': 'sensorsOverviewController',
+                 authenticated: true
+               })
++              .when('/server-health/pldm-overview', {
++                'template':
++                    require('./controllers/pldm-overview-controller.html'),
++                'controller': 'pldmOverviewController',
++                authenticated: true
++              })
+               .when('/server-health/sys-log', {
+                 'template': require('./controllers/syslog-controller.html'),
+                 'controller': 'sysLogController',
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui/0003-add-mcu-firmware-update-functionality.patch b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui/0003-add-mcu-firmware-update-functionality.patch
new file mode 100644
index 0000000..df11052
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui/0003-add-mcu-firmware-update-functionality.patch
@@ -0,0 +1,138 @@
+From 4a3aedb671ad65c56e0e638453f7a8f713b4a653 Mon Sep 17 00:00:00 2001
+From: Tim Lee <timlee660101@gmail.com>
+Date: Wed, 23 Sep 2020 15:55:33 +0800
+Subject: [PATCH 5/5] add mcu firmware update functionality
+
+Signed-off-by: Tim Lee <timlee660101@gmail.com>
+---
+ app/common/services/api-utils.js              |  9 ++++++++-
+ .../controllers/firmware-controller.html      | 19 ++++++++++++++++++-
+ .../controllers/firmware-controller.js        | 15 ++++++++++++++-
+ 3 files changed, 40 insertions(+), 3 deletions(-)
+
+diff --git a/app/common/services/api-utils.js b/app/common/services/api-utils.js
+index cc1122f3..fd1c5dac 100644
+--- a/app/common/services/api-utils.js
++++ b/app/common/services/api-utils.js
+@@ -1111,6 +1111,7 @@ window.angular && (function(angular) {
+                     var isExtended = false;
+                     var bmcActiveVersion = '';
+                     var hostActiveVersion = '';
++                    var mcuActiveVersion = '';
+                     var imageType = '';
+                     var extendedVersions = [];
+                     var functionalImages = [];
+@@ -1197,13 +1198,19 @@ window.angular && (function(angular) {
+                             imageType == 'Host') {
+                           hostActiveVersion = content.data[key].Version;
+                         }
++
++                         if (activationStatus == 'Functional' &&
++                             imageType == 'MCU') {
++                           mcuActiveVersion = content.data[key].Version;
++                        }
+                       }
+                     }
+ 
+                     deferred.resolve({
+                       data: data,
+                       bmcActiveVersion: bmcActiveVersion,
+-                      hostActiveVersion: hostActiveVersion
++                      hostActiveVersion: hostActiveVersion,
++                      mcuActiveVersion: mcuActiveVersion
+                     });
+                   },
+                   function(error) {
+diff --git a/app/configuration/controllers/firmware-controller.html b/app/configuration/controllers/firmware-controller.html
+index d2ff89dc..3c6c11a0 100644
+--- a/app/configuration/controllers/firmware-controller.html
++++ b/app/configuration/controllers/firmware-controller.html
+@@ -2,7 +2,7 @@
+ <div class="row column">
+   <h1>Firmware</h1>
+   <div class="column small-12 page-header">
+-    <h2 class="inline">Manage BMC and server firmware</h2>
++    <h2 class="inline">Manage BMC, server and MCU firmware</h2>
+   </div>
+ </div>
+ <div class="row column">
+@@ -11,6 +11,7 @@
+ </div>
+ <firmware-list title="BMC images" version="bmcActiveVersion" firmwares="firmwares" filter-by="filters.bmc"></firmware-list>
+ <firmware-list title="Server images" version="hostActiveVersion" firmwares="firmwares" filter-by="filters.host"></firmware-list>
++<firmware-list title="MCU images" version="mcuActiveVersion" firmwares="firmwares" filter-by="filters.mcu"></firmware-list>
+ <div class="row column" id="upload">
+   <div class="column small-12 page-header">
+     <h2 class="inline bold">Specify image file location</h2>
+@@ -134,6 +135,22 @@
+           </div>
+         </fieldset>
+       </form>
++      <form ng-if="activate_image_type == 'MCU'">
++        <fieldset>
++          <div class="row column">
++            <label class="control-radio bold" for="activate-without-reboot">Activate MCU file without rebooting BMC
++              <input type="radio" name="activate-without-reboot" id="activate-without-reboot" ng-model="activate.reboot" ng-value="false"/>
++              <span class="control__indicator control__indicator-on"></span>
++            </label>
++          </div>
++          <div class="row column">
++            <label class="control-radio bold" for="activate-with-reboot">Activate MCU file and automatically reboot BMC
++              <input type="radio" name="activate-with-reboot" id="activate-with-reboot" ng-model="activate.reboot" ng-value="true"/>
++              <span class="control__indicator control__indicator-on"></span>
++            </label>
++          </div>
++        </fieldset>
++      </form>
+     </div>
+     <div class="modal__button-wrapper">
+       <button class="btn  btn-secondary" ng-click="activate_confirm=false;">Cancel</button>
+diff --git a/app/configuration/controllers/firmware-controller.js b/app/configuration/controllers/firmware-controller.js
+index 451c16ce..b208ab74 100644
+--- a/app/configuration/controllers/firmware-controller.js
++++ b/app/configuration/controllers/firmware-controller.js
+@@ -26,6 +26,7 @@ window.angular && (function(angular) {
+       $scope.firmwares = [];
+       $scope.bmcActiveVersion = '';
+       $scope.hostActiveVersion = '';
++      $scope.mcuActiveVersion = '';
+       $scope.activate_confirm = false;
+       $scope.delete_image_id = '';
+       $scope.delete_image_version = '';
+@@ -136,6 +137,17 @@ window.angular && (function(angular) {
+                         warmReboot();
+                       }
+                     }
++                    if ($scope.activate.reboot &&
++                        ($scope.activate_image_type == 'MCU')) {
++                      APIUtils.bmcReboot().then(
++                          function(response) {
++                            toastService.success('BMC is rebooting.')
++                          },
++                          function(error) {
++                            console.log(JSON.stringify(error));
++                            toastService.error('Unable to reboot BMC.');
++                          });
++                    }
+                   });
+             });
+         $scope.activate_confirm = false;
+@@ -308,13 +320,14 @@ window.angular && (function(angular) {
+         $scope.confirm_delete = false;
+       };
+ 
+-      $scope.filters = {bmc: {imageType: 'BMC'}, host: {imageType: 'Host'}};
++      $scope.filters = {bmc: {imageType: 'BMC'}, host: {imageType: 'Host'}, mcu: {imageType: 'MCU'}};
+ 
+       $scope.loadFirmwares = function() {
+         APIUtils.getFirmwares().then(function(result) {
+           $scope.firmwares = result.data;
+           $scope.bmcActiveVersion = result.bmcActiveVersion;
+           $scope.hostActiveVersion = result.hostActiveVersion;
++          $scope.mcuActiveVersion = result.mcuActiveVersion;
+         });
+       };
+ 
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui_%.bbappend b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui_%.bbappend
new file mode 100644
index 0000000..8bff7fb
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/phosphor-webui_%.bbappend
@@ -0,0 +1,5 @@
+FILESEXTRAPATHS:append:nuvoton := ":${THISDIR}/${PN}"
+
+SRC_URI:append:nuvoton = " file://0001-novnc-add-16-bit-hextile-support-for-nuvoton-ece-eng.patch"
+#SRC_URI:append:nuvoton = " file://0002-support-pldm-sensors-effecters.patch"
+SRC_URI:append:nuvoton = " file://0003-add-mcu-firmware-update-functionality.patch"
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue/0001-novnc-add-16-bit-hextile-support-for-nuvoton-ece-eng.patch b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue/0001-novnc-add-16-bit-hextile-support-for-nuvoton-ece-eng.patch
new file mode 100644
index 0000000..2b96345
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue/0001-novnc-add-16-bit-hextile-support-for-nuvoton-ece-eng.patch
@@ -0,0 +1,43 @@
+From c33f0a97a15c99ca3144c9f8e67a67abe8fcee0a Mon Sep 17 00:00:00 2001
+From: Joseph Liu <kwliu@nuvoton.com>
+Date: Thu, 11 Nov 2021 16:10:26 +0800
+Subject: [PATCH] novnc: add 16-bit hextile support for nuvoton ece engine
+
+Signed-off-by: Joseph Liu <kwliu@nuvoton.com>
+---
+ package-lock.json | 5 ++---
+ package.json      | 2 +-
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/package-lock.json b/package-lock.json
+index 413dd624..759fe1ba 100644
+--- a/package-lock.json
++++ b/package-lock.json
+@@ -3281,9 +3281,8 @@
+       "dev": true
+     },
+     "@novnc/novnc": {
+-      "version": "1.2.0",
+-      "resolved": "https://registry.npmjs.org/@novnc/novnc/-/novnc-1.2.0.tgz",
+-      "integrity": "sha512-FaUckOedGhSbwQBXk/KGyxKt9ngskg4wPw6ghbHWXOUEmQscAZr3467lTU5DSfppwHJt5k+lQiHoeYUuY90l2Q=="
++      "version": "Nuvoton-Israel/noVNC.git#openbmc-v1.2.0",
++      "from": "@novnc/novnc@Nuvoton-Israel/noVNC.git#openbmc-v1.2.0"
+     },
+     "@npmcli/move-file": {
+       "version": "1.0.1",
+diff --git a/package.json b/package.json
+index 91d45434..9cb3e226 100644
+--- a/package.json
++++ b/package.json
+@@ -16,7 +16,7 @@
+   },
+   "dependencies": {
+     "@carbon/icons-vue": "10.28.0",
+-    "@novnc/novnc": "1.2.0",
++    "@novnc/novnc": "Nuvoton-Israel/noVNC.git#openbmc-v1.2.0",
+     "axios": "0.21.4",
+     "bootstrap": "4.6.0",
+     "bootstrap-vue": "2.21.2",
+-- 
+2.25.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue/0002-Add-Nuvoton-MCU-firmware-support.patch b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue/0002-Add-Nuvoton-MCU-firmware-support.patch
new file mode 100644
index 0000000..cce40ea
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue/0002-Add-Nuvoton-MCU-firmware-support.patch
@@ -0,0 +1,143 @@
+From 155799c9bd45e80fee3c260dcbba36fa84dabefd Mon Sep 17 00:00:00 2001
+From: Brian Ma <chma0@nuvoton.com>
+Date: Tue, 29 Jun 2021 10:34:23 +0800
+Subject: [PATCH 1/2] Add Nuvoton MCU firmware support
+
+Signed-off-by: Brian Ma <chma0@nuvoton.com>
+---
+ src/locales/en-US.json                        |  1 +
+ .../modules/Configuration/FirmwareStore.js    |  9 +++++
+ src/views/Configuration/Firmware/Firmware.vue |  5 +++
+ .../Firmware/FirmwareCardsMcu.vue             | 37 +++++++++++++++++++
+ 4 files changed, 52 insertions(+)
+ create mode 100644 src/views/Configuration/Firmware/FirmwareCardsMcu.vue
+
+diff --git a/src/locales/en-US.json b/src/locales/en-US.json
+index 437ce03..c087f82 100644
+--- a/src/locales/en-US.json
++++ b/src/locales/en-US.json
+@@ -310,6 +310,7 @@
+     "sectionTitleBmcCards": "BMC",
+     "sectionTitleBmcCardsCombined": "BMC and server",
+     "sectionTitleHostCards": "Host",
++    "sectionTitleMcuCards": "MCU",
+     "sectionTitleUpdateFirmware": "Update firmware",
+     "alert": {
+       "operationInProgress": "Server power operation in progress.",
+diff --git a/src/store/modules/Configuration/FirmwareStore.js b/src/store/modules/Configuration/FirmwareStore.js
+index c6639ff..79f8638 100644
+--- a/src/store/modules/Configuration/FirmwareStore.js
++++ b/src/store/modules/Configuration/FirmwareStore.js
+@@ -6,6 +6,7 @@ const FirmwareStore = {
+   state: {
+     bmcFirmware: [],
+     hostFirmware: [],
++    mcuFirmware: null,
+     bmcActiveFirmwareId: null,
+     hostActiveFirmwareId: null,
+     applyTime: null,
+@@ -24,6 +25,7 @@ const FirmwareStore = {
+         (firmware) => firmware.id === state.hostActiveFirmwareId
+       );
+     },
++    mcuFirmware: (state) => state.mcuFirmware,
+     backupBmcFirmware: (state) => {
+       return state.bmcFirmware.find(
+         (firmware) => firmware.id !== state.bmcActiveFirmwareId
+@@ -40,6 +42,7 @@ const FirmwareStore = {
+     setActiveHostFirmwareId: (state, id) => (state.hostActiveFirmwareId = id),
+     setBmcFirmware: (state, firmware) => (state.bmcFirmware = firmware),
+     setHostFirmware: (state, firmware) => (state.hostFirmware = firmware),
++    setMcuFirmware: (state, firmware) => (state.mcuFirmware = firmware),
+     setApplyTime: (state, applyTime) => (state.applyTime = applyTime),
+     setTftpUploadAvailable: (state, tftpAvailable) =>
+       (state.tftpAvailable = tftpAvailable),
+@@ -81,6 +84,12 @@ const FirmwareStore = {
+           const bmcFirmware = [];
+           const hostFirmware = [];
+           response.forEach(({ data }) => {
++            const Description = data?.Description;
++            if (Description === 'MCU image') {
++              // there is only one MCU firmware, and we just care version
++              const mcuFirmware = data?.Version;
++              commit('setMcuFirmware', mcuFirmware);
++            }
+             const firmwareType = data?.RelatedItem?.[0]?.['@odata.id']
+               .split('/')
+               .pop();
+diff --git a/src/views/Configuration/Firmware/Firmware.vue b/src/views/Configuration/Firmware/Firmware.vue
+index a2acb9b..bfb9b78 100644
+--- a/src/views/Configuration/Firmware/Firmware.vue
++++ b/src/views/Configuration/Firmware/Firmware.vue
+@@ -14,6 +14,9 @@
+ 
+         <!-- Host Firmware -->
+         <host-cards v-if="!isSingleFileUploadEnabled" />
++
++        <!-- MCU Firmware -->
++        <mcu-cards />
+       </b-col>
+     </b-row>
+ 
+@@ -39,6 +42,7 @@ import AlertsServerPower from './FirmwareAlertServerPower';
+ import BmcCards from './FirmwareCardsBmc';
+ import FormUpdate from './FirmwareFormUpdate';
+ import HostCards from './FirmwareCardsHost';
++import McuCards from './FirmwareCardsMcu';
+ import PageSection from '@/components/Global/PageSection';
+ import PageTitle from '@/components/Global/PageTitle';
+ 
+@@ -51,6 +55,7 @@ export default {
+     BmcCards,
+     FormUpdate,
+     HostCards,
++    McuCards,
+     PageSection,
+     PageTitle,
+   },
+diff --git a/src/views/Configuration/Firmware/FirmwareCardsMcu.vue b/src/views/Configuration/Firmware/FirmwareCardsMcu.vue
+new file mode 100644
+index 0000000..3d5641e
+--- /dev/null
++++ b/src/views/Configuration/Firmware/FirmwareCardsMcu.vue
+@@ -0,0 +1,37 @@
++<template>
++  <page-section :section-title="$t('pageFirmware.sectionTitleMcuCards')">
++    <b-card-group deck>
++      <!-- Running image -->
++      <b-card>
++        <template #header>
++          <p class="font-weight-bold m-0">
++            {{ $t('pageFirmware.cardTitleRunning') }}
++          </p>
++        </template>
++        <dl class="mb-0">
++          <dt>{{ $t('pageFirmware.cardBodyVersion') }}</dt>
++          <dd class="mb-0">{{ runningVersion }}</dd>
++        </dl>
++      </b-card>
++    </b-card-group>
++  </page-section>
++</template>
++
++<script>
++import PageSection from '@/components/Global/PageSection';
++
++export default {
++  components: { PageSection },
++  computed: {
++    runningVersion() {
++      return this.$store.getters['firmware/mcuFirmware'] || '--';
++    },
++  },
++};
++</script>
++
++<style lang="scss" scoped>
++.page-section {
++  margin-top: -$spacer * 1.5;
++}
++</style>
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue/0003-DEMO-Add-reboot-cause-support.patch b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue/0003-DEMO-Add-reboot-cause-support.patch
new file mode 100644
index 0000000..95e28ae
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue/0003-DEMO-Add-reboot-cause-support.patch
@@ -0,0 +1,105 @@
+From a9a54e019f0423d583794b71e47ff4248febe7c8 Mon Sep 17 00:00:00 2001
+From: Brian Ma <chma0@nuvoton.com>
+Date: Tue, 29 Jun 2021 10:42:42 +0800
+Subject: [PATCH 2/2] [DEMO]Add reboot cause support
+
+---
+ src/locales/en-US.json                    |  1 +
+ src/store/modules/Control/ControlStore.js | 24 +++++++++++++++++++++++
+ src/views/Control/RebootBmc/RebootBmc.vue |  7 +++++++
+ 3 files changed, 32 insertions(+)
+
+diff --git a/src/locales/en-US.json b/src/locales/en-US.json
+index c087f82..1bc7704 100644
+--- a/src/locales/en-US.json
++++ b/src/locales/en-US.json
+@@ -635,6 +635,7 @@
+   "pageRebootBmc": {
+     "lastReboot": "Last BMC reboot",
+     "rebootBmc": "Reboot BMC",
++    "rebootCause": "Reboot cause:",
+     "rebootInformation": "When you reboot the BMC, your web browser loses contact with the BMC for several minutes. When the BMC is back online, you may need to log in again.",
+     "modal": {
+       "confirmMessage": "Are you sure you want to reboot the BMC?",
+diff --git a/src/store/modules/Control/ControlStore.js b/src/store/modules/Control/ControlStore.js
+index 9b8bf73..09e8b95 100644
+--- a/src/store/modules/Control/ControlStore.js
++++ b/src/store/modules/Control/ControlStore.js
+@@ -34,11 +34,13 @@ const ControlStore = {
+     isOperationInProgress: false,
+     lastPowerOperationTime: null,
+     lastBmcRebootTime: null,
++    lastBmcRebootCause: null,
+   },
+   getters: {
+     isOperationInProgress: (state) => state.isOperationInProgress,
+     lastPowerOperationTime: (state) => state.lastPowerOperationTime,
+     lastBmcRebootTime: (state) => state.lastBmcRebootTime,
++    lastBmcRebootCause: (state) => state.lastBmcRebootCause,
+   },
+   mutations: {
+     setOperationInProgress: (state, inProgress) =>
+@@ -47,6 +49,8 @@ const ControlStore = {
+       (state.lastPowerOperationTime = lastPowerOperationTime),
+     setLastBmcRebootTime: (state, lastBmcRebootTime) =>
+       (state.lastBmcRebootTime = lastBmcRebootTime),
++    setLastBmcRebootCause: (state, lastBmcRebootCause) =>
++      (state.lastBmcRebootCause = lastBmcRebootCause),
+   },
+   actions: {
+     async getLastPowerOperationTime({ commit }) {
+@@ -62,6 +66,26 @@ const ControlStore = {
+         .catch((error) => console.log(error));
+     },
+     getLastBmcRebootTime({ commit }) {
++      // get reboot cause first
++      api
++        .get('/xyz/openbmc_project/state/bmc0/attr/LastRebootCause')
++        .then((response) => {
++          const lastRebootCause = response.data.data;
++          console.log(lastRebootCause);
++          if (
++            lastRebootCause === 'xyz.openbmc_project.State.BMC.RebootCause.POR'
++          ) {
++            commit('setLastBmcRebootCause', 'Power-On-Reset');
++          } else if (
++            lastRebootCause ===
++            'xyz.openbmc_project.State.BMC.RebootCause.Watchdog'
++          ) {
++            commit('setLastBmcRebootCause', 'Watchdog');
++          } else {
++            commit('setLastBmcRebootCause', 'Unknown');
++          }
++        })
++        .catch((error) => console.log(error));
+       return api
+         .get('/redfish/v1/Managers/bmc')
+         .then((response) => {
+diff --git a/src/views/Control/RebootBmc/RebootBmc.vue b/src/views/Control/RebootBmc/RebootBmc.vue
+index 900619c..910188e 100644
+--- a/src/views/Control/RebootBmc/RebootBmc.vue
++++ b/src/views/Control/RebootBmc/RebootBmc.vue
+@@ -15,6 +15,10 @@
+                   {{ lastBmcRebootTime | formatTime }}
+                 </dd>
+                 <dd v-else>--</dd>
++                <dd>
++                  {{ $t('pageRebootBmc.rebootCause') }}
++                  {{ lastBmcRebootCause }}
++                </dd>
+               </dl>
+             </b-col>
+           </b-row>
+@@ -51,6 +55,9 @@ export default {
+     lastBmcRebootTime() {
+       return this.$store.getters['controls/lastBmcRebootTime'];
+     },
++    lastBmcRebootCause() {
++      return this.$store.getters['controls/lastBmcRebootCause'] || '--';
++    },
+   },
+   created() {
+     this.startLoader();
+-- 
+2.17.1
+
diff --git a/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue_%.bbappend b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue_%.bbappend
new file mode 100644
index 0000000..cd08975
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-phosphor/webui/webui-vue_%.bbappend
@@ -0,0 +1,3 @@
+FILESEXTRAPATHS:append:nuvoton := ":${THISDIR}/${PN}"
+
+SRC_URI:append:nuvoton = " file://0001-novnc-add-16-bit-hextile-support-for-nuvoton-ece-eng.patch"
diff --git a/meta-nuvoton-npcm8xx/recipes-security/optee/optee-client.bb b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-client.bb
new file mode 100644
index 0000000..269fdb9
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-client.bb
@@ -0,0 +1,40 @@
+SUMMARY = "OPTEE Client"
+HOMEPAGE = "https://github.com/OP-TEE/optee_client"
+
+LICENSE = "BSD-2-Clause"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=69663ab153298557a59c67a60a743e5b"
+
+PV = "3.16.0+git${SRCPV}"
+
+inherit python3native systemd
+
+SRC_URI = "git://github.com/OP-TEE/optee_client.git;branch=master;protocol=https \
+           file://tee-supplicant.service \
+    "
+SRCREV = "06db73b3f3fdb8d23eceaedbc46c49c0b45fd1e2"
+
+S = "${WORKDIR}/git"
+
+EXTRA_OEMAKE = "CFG_TEE_FS_PARENT_PATH=/var/tee \
+        "
+
+do_install() {
+    oe_runmake install
+
+    install -D -p -m0755 ${S}/out/export/usr/sbin/tee-supplicant ${D}${bindir}/tee-supplicant
+
+    install -D -p -m0644 ${S}/out/export/usr/lib/libteec.so.1.0.0 ${D}${libdir}/libteec.so.1.0.0
+    ln -sf libteec.so.1.0.0 ${D}${libdir}/libteec.so
+    ln -sf libteec.so.1.0.0 ${D}${libdir}/libteec.so.1
+    ln -sf libteec.so.1.0.0 ${D}${libdir}/libteec.so.1.0
+
+    cp -a ${S}/out/export/usr/include ${D}/usr/
+
+	install -d ${D}${systemd_system_unitdir}/
+	install -m 0644 ${WORKDIR}/tee-supplicant.service ${D}${systemd_system_unitdir}/
+	sed -i -e s:/etc:${sysconfdir}:g -e s:/usr/bin:${bindir}:g ${D}${systemd_system_unitdir}/tee-supplicant.service
+}
+
+SYSTEMD_SERVICE:${PN} = "tee-supplicant.service"
+
+FILES:${PN} += "${libdir}/* ${includedir}/* ${systemd_system_unitdir}/*"
diff --git a/meta-nuvoton-npcm8xx/recipes-security/optee/optee-client/tee-supplicant.service b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-client/tee-supplicant.service
new file mode 100644
index 0000000..04e0409
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-client/tee-supplicant.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=TEE Supplicant
+
+[Service]
+User=root
+EnvironmentFile=-/etc/default/tee-supplicant
+ExecStart=/usr/bin/tee-supplicant $OPTARGS /dev/teepriv0
+
+[Install]
+WantedBy=basic.target
diff --git a/meta-nuvoton-npcm8xx/recipes-security/optee/optee-os.bb b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-os.bb
new file mode 100644
index 0000000..6fa6441
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-os.bb
@@ -0,0 +1,71 @@
+SUMMARY = "OP-TEE Trusted OS"
+DESCRIPTION = "OPTEE OS"
+
+LICENSE = "BSD-2-Clause"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE;md5=c1f21c4f72f372ef38a5a4aee55ec173"
+
+PV="1.0.0+git${SRCPV}"
+
+inherit deploy python3native
+DEPENDS = "python3-pycryptodome-native python3-pyelftools-native python3-pycryptodomex-native python3-cryptography-native"
+
+S = "${WORKDIR}/git"
+BRANCH ?= "nuvoton"
+REPO ?= "git://github.com/Nuvoton-Israel/optee_os.git;branch=nuvoton;protocol=https"
+BRANCHARG = "${@['nobranch=1', 'branch=${BRANCH}'][d.getVar('BRANCH', True) != '']}"
+SRC_URI = "${REPO};${BRANCHARG} \           
+	   file://0001-allow-sysroot-for-libgcc-lookup.patch \
+          "
+SRCREV = "6d2cdcf8e9c660751fc656b45ee631ade8d956e4"
+
+OPTEEMACHINE ?= "nuvoton"
+MACHINE_SOC ?= "npcm8xx"
+
+# Some versions of u-boot use .bin and others use .img.  By default use .bin
+# but enable individual recipes to change this value.
+OPTEE_SUFFIX ?= "bin"
+OPTEE_IMAGE ?= "tee-${MACHINE_SOC}-${PV}-${PR}.${OPTEE_SUFFIX}"
+OPTEE_SYMLINK ?= "tee-${MACHINE_SOC}.${OPTEE_SUFFIX}"
+CFG_TEE_TA_LOG_LEVEL ?= "1"
+CFG_TEE_CORE_LOG_LEVEL ?= "1"
+
+EXTRA_OEMAKE = "PLATFORM=${OPTEEMACHINE} CFG_ARM64_core=y \
+                CROSS_COMPILE_core=${HOST_PREFIX} \
+                CROSS_COMPILE_ta_arm64=${HOST_PREFIX} \
+                NOWERROR=1 \
+                ta-targets=ta_arm64 \
+                LDFLAGS= \
+                LIBGCC_LOCATE_CFLAGS=--sysroot=${STAGING_DIR_HOST} \
+        "
+
+OPTEE_ARCH_aarch64 = "arm64"
+
+do_compile() {
+    unset LDFLAGS
+    oe_runmake CFG_TEE_LOGLEVEL=0 CFG_TEE_CORE_LOG_LEVEL=0
+}
+
+do_install () {
+    # Install the TA devkit
+    install -d ${D}/usr/include/optee/export-user_ta/
+
+    for f in ${B}/out/arm-plat-nuvoton/export-ta_arm64/*; do
+        cp -aR $f ${D}/usr/include/optee/export-user_ta/
+    done
+}
+
+do_deploy() {
+    install -d ${DEPLOYDIR}
+    install -m 0644 ${S}/out/arm-plat-${OPTEEMACHINE}/core/tee.bin ${DEPLOYDIR}/tee.bin
+    cd ${DEPLOYDIR}
+    ln -sf tee.bin ${OPTEE_SYMLINK}
+    ln -sf tee.bin ${OPTEE_IMAGE}
+}
+
+addtask deploy before do_build after do_compile
+
+FILES:${PN} = "${nonarch_base_libdir}/firmware/ ${nonarch_base_libdir}/optee_armtz/"
+FILES:${PN}-staticdev = "/usr/include/optee/"
+RDEPENDS:${PN}-dev += "${PN}-staticdev"
+
+PACKAGE_ARCH = "${MACHINE_ARCH}"
\ No newline at end of file
diff --git a/meta-nuvoton-npcm8xx/recipes-security/optee/optee-os/0001-allow-sysroot-for-libgcc-lookup.patch b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-os/0001-allow-sysroot-for-libgcc-lookup.patch
new file mode 100644
index 0000000..e6d8d22
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-os/0001-allow-sysroot-for-libgcc-lookup.patch
@@ -0,0 +1,12 @@
+diff -Nur a/mk/gcc.mk b/mk/gcc.mk
+--- a/mk/gcc.mk	2022-03-06 10:30:27.518860700 +0200
++++ b/mk/gcc.mk	2022-03-07 10:42:04.764306171 +0200
+@@ -13,7 +13,7 @@
+ 			-print-file-name=include 2> /dev/null)
+ 
+ # Get location of libgcc from gcc
+-libgcc$(sm)  	:= $(shell $(CC$(sm)) $(CFLAGS$(arch-bits-$(sm))) \
++libgcc$(sm)  	:= $(shell $(CC$(sm)) $(LIBGCC_LOCATE_CFLAGS) $(CFLAGS$(arch-bits-$(sm))) $(comp-cflags$(sm)) \
+ 			-print-libgcc-file-name 2> /dev/null)
+ libstdc++$(sm)	:= $(shell $(CXX$(sm)) $(CXXFLAGS$(arch-bits-$(sm))) $(comp-cxxflags$(sm)) \
+ 			-print-file-name=libstdc++.a 2> /dev/null)
diff --git a/meta-nuvoton-npcm8xx/recipes-security/optee/optee-os/tee.bin b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-os/tee.bin
new file mode 100644
index 0000000..1061ad2
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-os/tee.bin
Binary files differ
diff --git a/meta-nuvoton-npcm8xx/recipes-security/optee/optee-test.bb b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-test.bb
new file mode 100644
index 0000000..39fe6f8
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes-security/optee/optee-test.bb
@@ -0,0 +1,53 @@
+SUMMARY = "OP-TEE sanity testsuite"
+HOMEPAGE = "https://github.com/OP-TEE/optee_test"
+
+LICENSE = "BSD-2-Clause & GPLv2"
+LIC_FILES_CHKSUM = "file://${S}/LICENSE.md;md5=daa2bcccc666345ab8940aab1315a4fa"
+
+SRC_URI = "git://github.com/OP-TEE/optee_test.git;branch=master;protocol=https"
+SRCREV = "1cf0e6d2bdd1145370033d4e182634458528579d"
+
+PV = "3.16.0+git${SRCPV}"
+
+S = "${WORKDIR}/git"
+
+# Imports machine specific configs from staging to build
+PACKAGE_ARCH = "${MACHINE_ARCH}"
+
+DEPENDS = "optee-client optee-os python3-pycryptodome-native python3-pycryptodomex-native python3-cryptography-native"
+
+inherit python3native
+
+OPTEE_CLIENT_EXPORT = "${STAGING_DIR_HOST}${prefix}"
+TEEC_EXPORT         = "${STAGING_DIR_HOST}${prefix}"
+TA_DEV_KIT_DIR      = "${STAGING_INCDIR}/optee/export-user_ta"
+
+EXTRA_OEMAKE = " TA_DEV_KIT_DIR=${TA_DEV_KIT_DIR} \
+                 OPTEE_CLIENT_EXPORT=${OPTEE_CLIENT_EXPORT} \
+                 TEEC_EXPORT=${TEEC_EXPORT} \
+                 CROSS_COMPILE_HOST=${TARGET_PREFIX} \
+                 CROSS_COMPILE_TA=${TARGET_PREFIX} \
+                 V=1 \
+                 CFG_TEE_CLIENT_LOAD_PATH=${libdir} \
+                 LIBGCC_LOCATE_CFLAGS='--sysroot=${STAGING_DIR_HOST}' \
+               "
+
+do_compile() {
+    # Top level makefile doesn't seem to handle parallel make gracefully
+    oe_runmake xtest
+    oe_runmake ta
+}
+
+do_install () {
+    install -D -p -m0755 ${S}/out/xtest/xtest ${D}${bindir}/xtest
+
+    # install path should match the value set in optee-client/tee-supplicant
+    # default TEEC_LOAD_PATH is /lib
+    mkdir -p ${D}${nonarch_base_libdir}/optee_armtz/
+    install -D -p -m0444 ${S}/out/ta/*/*.ta ${D}${nonarch_base_libdir}/optee_armtz/
+}
+
+FILES:${PN} += "${nonarch_base_libdir} ${libdir}/tee-supplicant/plugins/"
+
+DEBUG_OPTIMIZATION:append = " -Wno-error=maybe-uninitialized -Wno-deprecated-declarations"
+FULL_OPTIMIZATION:append = " -Wno-error=maybe-uninitialized -Wno-deprecated-declarations"
diff --git a/meta-nuvoton-npcm8xx/recipes.txt b/meta-nuvoton-npcm8xx/recipes.txt
new file mode 100644
index 0000000..149509f
--- /dev/null
+++ b/meta-nuvoton-npcm8xx/recipes.txt
@@ -0,0 +1,2 @@
+recipes-bsp          - Anything with links to specific hardware or hardware configuration information
+recipes-kernel       - The kernel and generic applications/libraries with strong kernel dependencies