Platform: nuvoton m2354: update for tf-m v1.6

Change-Id: I937f4a8148fe2c161be584c9a462c1886ff50b9f
diff --git a/platform/ext/platform_introduction.rst b/platform/ext/platform_introduction.rst
index b9e043e..656e1aa 100644
--- a/platform/ext/platform_introduction.rst
+++ b/platform/ext/platform_introduction.rst
@@ -49,6 +49,8 @@
           <https://developer.arm.com/products/system-design/development-boards/cortex-m-prototyping-systems/mps2>`_
         - `M2351.
           <https://www.nuvoton.com/products/iot-solution/iot-platform/numaker-pfm-m2351/>`_
+        - `M2354.
+          <https://www.nuvoton.com/board/numaker-m2354/>`_
 
     - Dual Core Cortex-M system:
 
diff --git a/platform/ext/target/nuvoton/common/bsp/StdDriver/inc/tamper.h b/platform/ext/target/nuvoton/common/bsp/StdDriver/inc/tamper.h
deleted file mode 100644
index 466f69a..0000000
--- a/platform/ext/target/nuvoton/common/bsp/StdDriver/inc/tamper.h
+++ /dev/null
@@ -1,463 +0,0 @@
-/**************************************************************************//**
- * @file     tamper.h
- * @version  V3.00
- * @brief    TAMPER driver header file
- *
- * @copyright SPDX-License-Identifier: Apache-2.0
- * @copyright Copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
- *****************************************************************************/
-#ifndef __TAMPER_H__
-#define __TAMPER_H__
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-
-/** @addtogroup Standard_Driver Standard Driver
-  @{
-*/
-
-/** @addtogroup TAMPER_Driver Tamper Driver
-  @{
-*/
-
-/** @addtogroup TAMPER_EXPORTED_CONSTANTS Tamper Exported Constants
-  @{
-*/
-
-#define TAMPER_TAMPER0_SELECT      (0x1UL << 0)    /*!< Select Tamper 0 */
-#define TAMPER_TAMPER1_SELECT      (0x1UL << 1)    /*!< Select Tamper 1 */
-#define TAMPER_TAMPER2_SELECT      (0x1UL << 2)    /*!< Select Tamper 2 */
-#define TAMPER_TAMPER3_SELECT      (0x1UL << 3)    /*!< Select Tamper 3 */
-#define TAMPER_TAMPER4_SELECT      (0x1UL << 4)    /*!< Select Tamper 4 */
-#define TAMPER_TAMPER5_SELECT      (0x1UL << 5)    /*!< Select Tamper 5 */
-#define TAMPER_MAX_TAMPER_PIN_NUM  6UL             /*!< Tamper Pin number */
-
-#define TAMPER_TAMPER_HIGH_LEVEL_DETECT    1UL     /*!< Tamper pin detect voltage level is high */
-#define TAMPER_TAMPER_LOW_LEVEL_DETECT     0UL     /*!< Tamper pin detect voltage level is low */
-
-#define TAMPER_TAMPER_DEBOUNCE_ENABLE      1UL     /*!< Enable tamper pin de-bounce function */
-#define TAMPER_TAMPER_DEBOUNCE_DISABLE     0UL     /*!< Disable tamper pin de-bounce function */
-
-#define TAMPER_PAIR0_SELECT        (0x1UL << 0)    /*!< Select Pair 0 */
-#define TAMPER_PAIR1_SELECT        (0x1UL << 1)    /*!< Select Pair 1 */
-#define TAMPER_PAIR2_SELECT        (0x1UL << 2)    /*!< Select Pair 2 */
-#define TAMPER_MAX_PAIR_NUM        3UL             /*!< Pair number */
-
-#define TAMPER_2POW6_CLK           (0x0UL << TAMPER_TIOCTL_DYNRATE_Pos) /*!< 64 RTC clock cycles */
-#define TAMPER_2POW7_CLK           (0x1UL << TAMPER_TIOCTL_DYNRATE_Pos) /*!< 64 x 2 RTC clock cycles */
-#define TAMPER_2POW8_CLK           (0x2UL << TAMPER_TIOCTL_DYNRATE_Pos) /*!< 64 x 4 RTC clock cycles */
-#define TAMPER_2POW9_CLK           (0x3UL << TAMPER_TIOCTL_DYNRATE_Pos) /*!< 64 x 6 RTC clock cycles */
-#define TAMPER_2POW10_CLK          (0x4UL << TAMPER_TIOCTL_DYNRATE_Pos) /*!< 64 x 8 RTC clock cycles */
-#define TAMPER_2POW11_CLK          (0x5UL << TAMPER_TIOCTL_DYNRATE_Pos) /*!< 64 x 10 RTC clock cycles */
-#define TAMPER_2POW12_CLK          (0x6UL << TAMPER_TIOCTL_DYNRATE_Pos) /*!< 64 x 12 RTC clock cycles */
-#define TAMPER_2POW13_CLK          (0x7UL << TAMPER_TIOCTL_DYNRATE_Pos) /*!< 64 x 14 RTC clock cycles */
-
-#define TAMPER_ACTS_2POW10_CLK     (0x0UL << 5)    /*!< 1024 LIRC32K clock cycles */
-#define TAMPER_ACTS_2POW11_CLK     (0x1UL << 5)    /*!< 1024 x 2 LIRC32K clock cycles */
-#define TAMPER_ACTS_2POW12_CLK     (0x2UL << 5)    /*!< 1024 x 4 LIRC32K clock cycles */
-#define TAMPER_ACTS_2POW13_CLK     (0x3UL << 5)    /*!< 1024 x 6 LIRC32K clock cycles */
-#define TAMPER_ACTS_2POW14_CLK     (0x4UL << 5)    /*!< 1024 x 8 LIRC32K clock cycles */
-#define TAMPER_ACTS_2POW15_CLK     (0x5UL << 5)    /*!< 1024 x 16 LIRC32K clock cycles */
-#define TAMPER_ACTS_2POW16_CLK     (0x6UL << 5)    /*!< 1024 x 32 LIRC32K clock cycles */
-#define TAMPER_ACTS_2POW17_CLK     (0x7UL << 5)    /*!< 1024 x 64 LIRC32K clock cycles */
-
-#define TAMPER_REF_RANDOM_PATTERN        0x0UL     /*!< The new reference pattern is generated by random number generator when the reference pattern run out */
-#define TAMPER_REF_SEED                  0x1UL     /*!< The new reference pattern is repeated from SEED (TAMPER_SEED[31:0]) when the reference pattern run out */
-
-#define TAMPER_VG_192M_SAMPLE            0x0UL     /*!< Select voltage glitch 192M sampleing rate */
-
-/**@}*/ /* end of group TAMPER_EXPORTED_CONSTANTS */
-
-
-/** @addtogroup TAMPER_EXPORTED_FUNCTIONS Tamper Exported Functions
-  @{
-*/
-
-/**
-  * @brief      Reset Tamper Coreblock
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    To set TAMPER INIT control register to reset the tamper coreblock.
-  *
-  */
-#define TAMPER_CORE_RESET()                 ((uint32_t)(TAMPER->INIT = 0x55AA))
-
-/**
-  * @brief      Release Tamper Coreblock
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    To set TAMPER INIT control register to release the tamper coreblock.
-  *
-  */
-#define TAMPER_CORE_RELEASE()               ((uint32_t)(TAMPER->INIT = 0x5500))
-
-/**
-  * @brief      Get the Voltage Regulator Power Ready Status
-  *
-  * @param      None
-  *
-  * @retval     0   The power status of voltage regulator is not ready.
-  * @retval     1   The power status of voltage regulator is ready.
-  *
-  * @details    This macro will return the power status of voltage regulator.
-  *
-  */
-#define TAMPER_TLDO_IS_READY()              (TAMPER->INIT & TAMPER_INIT_TLDORDY_Msk ? 1:0)
-
-/**
-  * @brief      Enable LXT Clock Detection
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    To set TAMPER FUNEN control register to enable LXT clock detection.
-  *
-  */
-#define TAMPER_ENABLE_LXTDET()              ((uint32_t)(TAMPER->FUNEN = (TAMPER->FUNEN & ~0xFFUL) | 0x44))
-
-/**
-  * @brief      Disable LXT Clock Detection
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    To set TAMPER FUNEN control register to disable LXT clock detection.
-  *
-  */
-#define TAMPER_DISABLE_LXTDET()             ((uint32_t)(TAMPER->FUNEN = (TAMPER->FUNEN & ~0xFFUL) | 0x40))
-
-/**
-  * @brief      Tamper I/O TAMPER Block Detection Selection
-  *
-  * @param[in]  u32TamperSelect   Tamper pin select. Possible options are
-  *                               - \ref TAMPER_TAMPER0_SELECT
-  *                               - \ref TAMPER_TAMPER1_SELECT
-  *                               - \ref TAMPER_TAMPER2_SELECT
-  *                               - \ref TAMPER_TAMPER3_SELECT
-  *                               - \ref TAMPER_TAMPER4_SELECT
-  *                               - \ref TAMPER_TAMPER5_SELECT
-  *
-  * @return     None
-  *
-  * @details    To set TAMPER FUNEN control register to select tamper I/O 0~5 and its function is detected through TAMPER block.
-  *
-  */
-__STATIC_INLINE void TAMPER_IOSEL_TAMPER(uint32_t u32TamperSelect)
-{
-    uint32_t i;
-
-    for(i = 0UL; i < (uint32_t)TAMPER_MAX_TAMPER_PIN_NUM; i++)
-    {
-        if(u32TamperSelect & (0x1UL << i))
-        {
-            TAMPER->FUNEN = (TAMPER->FUNEN & ~0xFFUL) | (0x94 + i * 0x10UL);
-        }
-    }
-}
-
-/**
-  * @brief      Tamper I/O RTC Block Detection Selection
-  *
-  * @param[in]  u32TamperSelect   Tamper pin select. Possible options are
-  *                               - \ref TAMPER_TAMPER0_SELECT
-  *                               - \ref TAMPER_TAMPER1_SELECT
-  *                               - \ref TAMPER_TAMPER2_SELECT
-  *                               - \ref TAMPER_TAMPER3_SELECT
-  *                               - \ref TAMPER_TAMPER4_SELECT
-  *                               - \ref TAMPER_TAMPER5_SELECT
-  *
-  * @return     None
-  *
-  * @details    To set TAMPER FUNEN control register to select tamper I/O 0~5 and its function is detected through RTC block.
-  *
-  */
-__STATIC_INLINE void TAMPER_IOSEL_RTC(uint32_t u32TamperSelect)
-{
-    uint32_t i;
-
-    for(i = 0UL; i < (uint32_t)TAMPER_MAX_TAMPER_PIN_NUM; i++)
-    {
-        if(u32TamperSelect & (0x1UL << i))
-        {
-            TAMPER->FUNEN = (TAMPER->FUNEN & ~0xFFUL) | (0x90 + i * 0x10UL);
-        }
-    }
-}
-
-/**
-  * @brief      Enable HIRC48M
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    To set TAMPER FUNEN control register to enable HIRC48M.
-  *
-  */
-#define TAMPER_ENABLE_HIRC48M()             ((uint32_t)(TAMPER->FUNEN &= (~TAMPER_FUNEN_HIRC48MEN_Msk)))
-
-/**
-  * @brief      Disable HIRC48M
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    To set TAMPER FUNEN control register to disable HIRC48M.
-  *
-  */
-#define TAMPER_DISABLE_HIRC48M()            ((uint32_t)(TAMPER->FUNEN = (TAMPER->FUNEN & (~TAMPER_FUNEN_HIRC48MEN_Msk)) | (0x5A << TAMPER_FUNEN_HIRC48MEN_Pos)))
-
-/**
-  * @brief      Voltage Glitch Sampling Rate Selection
-  *
-  * @param[in]  u32VGSampleRate Voltage Glitch sampling rate select. Possible option is
-  *                             - \ref TAMPER_VG_192M_SAMPLE
-  *
-  * @return     None
-  *
-  * @details    To set TAMPER FUNEN control register to enable voltage glitch channel 0~3 to select voltage glitch sampling rate.
-  *
-  */
-__STATIC_INLINE void TAMPER_VG_SAMPLE_SEL(uint32_t u32VGSampleRate)
-{
-    TAMPER->FUNEN &= ~0xF000000UL;
-
-    if(u32VGSampleRate == TAMPER_VG_192M_SAMPLE)
-    {
-        TAMPER->FUNEN |= TAMPER_FUNEN_VGCHEN0_Msk | TAMPER_FUNEN_VGCHEN1_Msk | TAMPER_FUNEN_VGCHEN2_Msk | TAMPER_FUNEN_VGCHEN3_Msk;
-    }
-}
-
-/**
-  * @brief      Enable to Trigger Key Store
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Set KSTRIGEN bit of TAMPER TRIEN control register to trigger Key Store when Tamper event is detected.
-  *
-  */
-#define TAMPER_ENABLE_KS_TRIG()             ((uint32_t)(TAMPER->TRIEN |= TAMPER_TRIEN_KSTRIGEN_Msk))
-
-/**
-  * @brief      Disable to Trigger Key Store
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Clear KSTRIGEN bit of TAMPER TRIEN control register to not trigger Key Store when Tamper event is detected.
-  *
-  */
-#define TAMPER_DISABLE_KS_TRIG()            ((uint32_t)(TAMPER->TRIEN &= (~TAMPER_TRIEN_KSTRIGEN_Msk)))
-
-/**
-  * @brief      Enable Wake-up Function
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Set WAKEUPEN bit of TAMPER TRIEN control register to wake-up the system when Tamper event is detected.
-  *
-  */
-#define TAMPER_ENABLE_WAKEUP()              ((uint32_t)(TAMPER->TRIEN |= TAMPER_TRIEN_WAKEUPEN_Msk))
-
-/**
-  * @brief      Disable Wake-up Function
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Clear WAKEUPEN bit of TAMPER TRIEN control register to not wake-up the system when Tamper event is detected.
-  *
-  */
-#define TAMPER_DISABLE_WAKEUP()             ((uint32_t)(TAMPER->TRIEN &= (~TAMPER_TRIEN_WAKEUPEN_Msk)))
-
-/**
-  * @brief      Enable to Clear Crypto Function
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Set CRYPTOEN bit of TAMPER TRIEN control register to reset Crypto when Tamper event is detected.
-  *
-  */
-#define TAMPER_ENABLE_CRYPTO()              ((uint32_t)(TAMPER->TRIEN |= TAMPER_TRIEN_CRYPTOEN_Msk))
-
-/**
-  * @brief      Disable to Clear Crypto Function
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Clear CRYPTOEN bit of TAMPER TRIEN control register to not reset Crypto when Tamper event is detected.
-  *
-  */
-#define TAMPER_DISABLE_CRYPTO()             ((uint32_t)(TAMPER->TRIEN &= (~TAMPER_TRIEN_CRYPTOEN_Msk)))
-
-/**
-  * @brief      Enable to Trigger Chip Reset
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Set CHIPRSTEN bit of TAMPER TRIEN control register to reset the system when Tamper event is detected.
-  *
-  */
-#define TAMPER_ENABLE_CHIPRST()              ((uint32_t)(TAMPER->TRIEN |= TAMPER_TRIEN_CHIPRSTEN_Msk))
-
-/**
-  * @brief      Disable to Trigger Chip Reset
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Clear CHIPRSTEN bit of TAMPER TRIEN control register to not reset the system when Tamper event is detected.
-  *
-  */
-#define TAMPER_DISABLE_CHIPRST()             ((uint32_t)(TAMPER->TRIEN &= (~TAMPER_TRIEN_CHIPRSTEN_Msk)))
-
-/**
-  * @brief      Enable to Clear RTC Spare Register
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Set RTCSPCLREN bit of TAMPER TRIEN control register to reset RTC spare register when Tamper event is detected.
-  *
-  */
-#define TAMPER_ENABLE_RTCSPCLR()              ((uint32_t)(TAMPER->TRIEN |= TAMPER_TRIEN_RTCSPCLREN_Msk))
-
-/**
-  * @brief      Disable to Clear RTC Spare Register
-  *
-  * @param      None
-  *
-  * @return     None
-  *
-  * @details    Clear RTCSPCLREN bit of TAMPER TRIEN control register to not reset RTC spare register when Tamper event is detected.
-  *
-  */
-#define TAMPER_DISABLE_RTCSPCLR()             ((uint32_t)(TAMPER->TRIEN &= (~TAMPER_TRIEN_RTCSPCLREN_Msk)))
-
-/**
-  * @brief      Get Tamper Interrupt Flag
-  *
-  * @param      None
-  *
-  * @retval     0   Tamper event Interrupt did not occur
-  * @retval     1   Tamper event Interrupt occurred
-  *
-  * @details    This macro indicates Tamper event intertupt occurred or not.
-  *
-  */
-#define TAMPER_GET_INT_FLAG()      ((TAMPER->INTSTS & (0xAA7FAFFF))? 1:0)
-
-/**
-  * @brief      Clear Tamper Interrupt Status
-  *
-  * @param[in]  u32TamperFlag   Tamper event interrupt flag. It consists of:
-  *                             - \ref TAMPER_INTSTS_TAMP0IF_Msk
-  *                             - \ref TAMPER_INTSTS_TAMP1IF_Msk
-  *                             - \ref TAMPER_INTSTS_TAMP2IF_Msk
-  *                             - \ref TAMPER_INTSTS_TAMP3IF_Msk
-  *                             - \ref TAMPER_INTSTS_TAMP4IF_Msk
-  *                             - \ref TAMPER_INTSTS_TAMP5IF_Msk
-  *                             - \ref TAMPER_INTSTS_CLKFAILIF_Msk
-  *                             - \ref TAMPER_INTSTS_CLKSTOPIF_Msk
-  *                             - \ref TAMPER_INTSTS_OVPOUTIF_Msk
-  *                             - \ref TAMPER_INTSTS_VGPEVIF_Msk
-  *                             - \ref TAMPER_INTSTS_VGNEVIF_Msk
-  *                             - \ref TAMPER_INTSTS_ACTSEIF_Msk
-  *                             - \ref TAMPER_INTSTS_ACTST5IF_Msk
-  *                             - \ref TAMPER_INTSTS_ACTST25IF_Msk
-  *                             - \ref TAMPER_INTSTS_BODIF_Msk
-  *                             - \ref TAMPER_INTSTS_ACTST1IF_Msk
-  *                             - \ref TAMPER_INTSTS_ACTST3IF_Msk
-  *                             - \ref TAMPER_INTSTS_ACTST21IF_Msk
-  *                             - \ref TAMPER_INTSTS_ACTST23IF_Msk
-  *
-  * @return     None
-  *
-  * @details    This macro is used to clear Tamper event flag.
-  *
-  */
-#define TAMPER_CLR_INT_STATUS(u32TamperFlag)   (TAMPER->INTSTS = (u32TamperFlag))
-
-/**
-  * @brief      Get Tamper Interrupt Status
-  *
-  * @param      None
-  *
-  * @retval     TAMPER_INTSTS_TAMP0IF_Msk
-  * @retval     TAMPER_INTSTS_TAMP1IF_Msk
-  * @retval     TAMPER_INTSTS_TAMP2IF_Msk
-  * @retval     TAMPER_INTSTS_TAMP3IF_Msk
-  * @retval     TAMPER_INTSTS_TAMP4IF_Msk
-  * @retval     TAMPER_INTSTS_TAMP5IF_Msk
-  * @retval     TAMPER_INTSTS_CLKFAILIF_Msk
-  * @retval     TAMPER_INTSTS_CLKSTOPIF_Msk
-  * @retval     TAMPER_INTSTS_OVPOUTIF_Msk
-  * @retval     TAMPER_INTSTS_VGPEVIF_Msk
-  * @retval     TAMPER_INTSTS_VGNEVIF_Msk
-  * @retval     TAMPER_INTSTS_ACTSEFIF_Msk
-  * @retval     TAMPER_INTSTS_ACTST5IF_Msk
-  * @retval     TAMPER_INTSTS_ACTST25IF_Msk
-  * @retval     TAMPER_INTSTS_RTCLVRIF_Msk
-  * @retval     TAMPER_INTSTS_RIOTRIGIF_Msk
-  * @retval     TAMPER_INTSTS_RCLKTRIGIF_Msk
-  * @retval     TAMPER_INTSTS_BODIF_Msk
-  * @retval     TAMPER_INTSTS_ACTST1IF_Msk
-  * @retval     TAMPER_INTSTS_ACTST3IF_Msk
-  * @retval     TAMPER_INTSTS_ACTST21IF_Msk
-  * @retval     TAMPER_INTSTS_ACTST23IF_Msk
-  *
-  * @details    This macro indicates Tamper event status.
-  *
-  */
-#define TAMPER_GET_INT_STATUS()    ((TAMPER->INTSTS & (0xAA7FAFFF)))
-
-void TAMPER_EnableInt(uint32_t u32IntFlagMask);
-void TAMPER_DisableInt(uint32_t u32IntFlagMask);
-void TAMPER_StaticTamperEnable(uint32_t u32TamperSelect, uint32_t u32DetecLevel, uint32_t u32DebounceEn);
-void TAMPER_StaticTamperDisable(uint32_t u32TamperSelect);
-void TAMPER_DynamicTamperEnable(uint32_t u32PairSel, uint32_t u32DebounceEn, uint32_t u32Pair1Source, uint32_t u32Pair2Source);
-void TAMPER_DynamicTamperDisable(uint32_t u32PairSel);
-void TAMPER_DynamicTamperConfig(uint32_t u32ChangeRate, uint32_t u32SeedReload, uint32_t u32RefPattern, uint32_t u32Seed);
-void TAMPER_ActiveShieldDynamicTamperEnable(uint32_t u32PairSel1, uint32_t u32Pair1Source1, uint32_t u32PairSel2, uint32_t u32Pair1Source2);
-void TAMPER_ActiveShieldDynamicTamperDisable(uint32_t u32PairSel1, uint32_t u32PairSe2);
-void TAMPER_ActiveShieldDynamicTamperConfig(uint32_t u32ChangeRate1, uint32_t u32SeedReload1, uint32_t u32RefPattern1, uint32_t u32Seed,
-        uint32_t u32ChangeRate2, uint32_t u32SeedReload2, uint32_t u32RefPattern2, uint32_t u32Seed2);
-
-
-/**@}*/ /* end of group TAMPER_EXPORTED_FUNCTIONS */
-
-/**@}*/ /* end of group TAMPER_Driver */
-
-/**@}*/ /* end of group Standard_Driver */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __TAMPER_H__ */
diff --git a/platform/ext/target/nuvoton/common/cmsis_drivers/Driver_Flash.c b/platform/ext/target/nuvoton/common/cmsis_drivers/Driver_Flash.c
index 3170879..8b6b033 100644
--- a/platform/ext/target/nuvoton/common/cmsis_drivers/Driver_Flash.c
+++ b/platform/ext/target/nuvoton/common/cmsis_drivers/Driver_Flash.c
@@ -79,13 +79,12 @@
 static int32_t is_range_valid(struct arm_flash_dev_t *flash_dev,
                               uint32_t offset)
 {
-    uint32_t flash_limit = 0;
+    uint32_t flash_size = 0;
     int32_t rc = 0;
 
-    flash_limit = (flash_dev->data->sector_count * flash_dev->data->sector_size)
-                  - 1;
+    flash_size = (flash_dev->data->sector_count * flash_dev->data->sector_size);
 
-    if(offset > flash_limit)
+    if(offset >= flash_size)
     {
         rc = -1;
     }
@@ -204,7 +203,7 @@
     cnt *= data_width_byte[DriverCapabilities.data_width];
 
     /* Check flash memory boundaries */
-    rc = is_range_valid(FLASH0_DEV, addr + cnt - 1);
+    rc = is_range_valid(FLASH0_DEV, addr + cnt);
     if (rc != 0) {
         return ARM_DRIVER_ERROR_PARAMETER;
     }
@@ -214,7 +213,7 @@
     for(i = 0; i < cnt; i++)
     {
         taddr = start_addr + i;
-        if(taddr >= (FLASH_AREA_0_OFFSET+FLASH_S_PARTITION_SIZE))
+        if(taddr >= SCU->FNSADDR)
             taddr += NS_OFFSET;
         pu8[i] = *(uint8_t*)taddr;
     }
@@ -234,7 +233,7 @@
     cnt *= data_width_byte[DriverCapabilities.data_width];
 
     /* Check flash memory boundaries and alignment with minimal write size */
-    rc  = is_range_valid(FLASH0_DEV, addr + cnt - 1);
+    rc  = is_range_valid(FLASH0_DEV, addr + cnt);
     rc |= is_write_aligned(FLASH0_DEV, addr);
     rc |= is_write_aligned(FLASH0_DEV, cnt);
     if(rc != 0)
@@ -258,8 +257,15 @@
             if(j>=4)
             {
                 FMC_Write(start_addr+(i+1-4), u32Data);
+                // verify
+                if(M32(start_addr + i - 3) != u32Data)
+                {
+                    printf("flash write verify fail @ %08x W:%08x R:%08x\r\n", start_addr + i - 3, u32Data, M32(start_addr + i - 3));
+                }
+
                 j = 0;
                 u32Data = 0;
+
             }
         }
 
diff --git a/platform/ext/target/nuvoton/common/mmio_defs.h b/platform/ext/target/nuvoton/common/mmio_defs.h
new file mode 100644
index 0000000..34e4e31
--- /dev/null
+++ b/platform/ext/target/nuvoton/common/mmio_defs.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __MMIO_DEFS_H__
+#define __MMIO_DEFS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include "tfm_peripherals_def.h"
+
+/* Boundary handle binding macros. */
+#define HANDLE_PER_ATTR_BITS            (0x4)
+#define HANDLE_ATTR_PRIV_MASK           ((1 << HANDLE_PER_ATTR_BITS) - 1)
+#if TFM_LVL == 3
+#define HANDLE_ATTR_RW_POS              (1 << (HANDLE_PER_ATTR_BITS - 1))
+#define HANDLE_ATTR_INDEX_MASK          (HANDLE_ATTR_RW_POS - 1)
+#define HANDLE_INDEX_BITS               (0x8)
+#define HANDLE_INDEX_MASK               (((1 << HANDLE_INDEX_BITS) -1) << 24)
+#define HANDLE_ENCODE_INDEX(attr, idx)                              \
+    do {                                                            \
+        (attr) |= (((idx) << 24) & HANDLE_INDEX_MASK);              \
+        (idx)++;                                                    \
+    } while (0)
+#endif
+
+/* Allowed named MMIO of this platform */
+const uintptr_t partition_named_mmio_list[] = {
+    (uintptr_t)TFM_PERIPHERAL_TIMER0,
+    (uintptr_t)TFM_PERIPHERAL_STD_UART,
+#ifdef PSA_API_TEST_IPC
+    (uintptr_t)FF_TEST_UART_REGION,
+    (uintptr_t)FF_TEST_WATCHDOG_REGION,
+    (uintptr_t)FF_TEST_NVMEM_REGION,
+    (uintptr_t)FF_TEST_SERVER_PARTITION_MMIO,
+    (uintptr_t)FF_TEST_DRIVER_PARTITION_MMIO,
+#endif
+};
+
+/*
+ * Platform AN521 only has named MMIO.
+ * If the platform has numbered MMIO, define them in another list.
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MMIO_DEFS_H__ */
diff --git a/platform/ext/target/nuvoton/common/native_drivers/arm_uart_drv.c b/platform/ext/target/nuvoton/common/native_drivers/arm_uart_drv.c
new file mode 100644
index 0000000..d61ae48
--- /dev/null
+++ b/platform/ext/target/nuvoton/common/native_drivers/arm_uart_drv.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright (c) 2016-2017 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "arm_uart_drv.h"
+
+#include <stddef.h>
+
+/* UART register map structure */
+struct _arm_uart_reg_map_t {
+    volatile uint32_t data;   /* Offset: 0x000 (R/W) data register    */
+    volatile uint32_t state;  /* Offset: 0x004 (R/W) status register  */
+    volatile uint32_t ctrl;   /* Offset: 0x008 (R/W) control register */
+    union {
+        volatile uint32_t intrstatus;  /* Offset: 0x00c (R/ ) interrupt status
+                                        *                     register */
+        volatile uint32_t intrclear;   /* Offset: 0x00c ( /W) interrupt clear
+                                        *                     register  */
+    }intr_reg;
+    volatile uint32_t bauddiv;        /* Offset: 0x010 (R/W) Baudrate divider
+                                       *                     register */
+};
+
+/* CTRL Register */
+#define ARM_UART_TX_EN       (1ul << 0)
+#define ARM_UART_RX_EN       (1ul << 1)
+#define ARM_UART_TX_INTR_EN  (1ul << 2)
+#define ARM_UART_RX_INTR_EN  (1ul << 3)
+
+/* STATE Register */
+#define ARM_UART_TX_BF  (1ul << 0)
+#define ARM_UART_RX_BF  (1ul << 1)
+
+/* INTSTATUS Register */
+#define ARM_UART_TX_INTR  (1ul << 0)
+#define ARM_UART_RX_INTR  (1ul << 1)
+
+/* UART state definitions */
+#define ARM_UART_INITIALIZED  (1ul << 0)
+
+enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
+                                    uint32_t system_clk)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+    if(system_clk == 0) {
+        return ARM_UART_ERR_INVALID_ARG;
+    }
+
+    /* Sets baudrate and system clock */
+    dev->data->system_clk = system_clk;
+    dev->data->baudrate = dev->cfg->default_baudrate;
+
+    /* Sets baudrate */
+    p_uart->bauddiv = (dev->data->system_clk / dev->cfg->default_baudrate);
+
+    /* Enables receiver and transmitter */
+    p_uart->ctrl = ARM_UART_RX_EN | ARM_UART_TX_EN;
+
+    dev->data->state = ARM_UART_INITIALIZED;
+
+    return ARM_UART_ERR_NONE;
+}
+
+enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
+                                            uint32_t baudrate)
+{
+    uint32_t bauddiv;
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(baudrate == 0) {
+        return ARM_UART_ERR_INVALID_BAUD;
+    }
+
+    if(!(dev->data->state & ARM_UART_INITIALIZED)) {
+        return ARM_UART_ERR_NOT_INIT;
+    }
+
+    /* Sets baudrate */
+    bauddiv = (dev->data->system_clk / baudrate);
+    dev->data->baudrate = baudrate;
+
+    /* Minimum bauddiv value */
+    if(bauddiv < 16) {
+        return ARM_UART_ERR_INVALID_BAUD;
+    }
+
+    p_uart->bauddiv = bauddiv;
+
+    return ARM_UART_ERR_NONE;
+}
+
+uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev)
+{
+    return dev->data->baudrate;
+}
+
+enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
+                                         uint32_t system_clk)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(system_clk == 0) {
+        return ARM_UART_ERR_INVALID_ARG;
+    }
+
+    if(!(dev->data->state & ARM_UART_INITIALIZED)) {
+        return ARM_UART_ERR_NOT_INIT;
+    }
+
+    /* Sets system clock */
+    dev->data->system_clk = system_clk;
+
+    /* Updates baudrate divider */
+    p_uart->bauddiv = (dev->data->system_clk / dev->data->baudrate);
+
+    /* Enables receiver and transmitter */
+    return ARM_UART_ERR_NONE;
+}
+
+enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(!(p_uart->state & ARM_UART_RX_BF)) {
+        return ARM_UART_ERR_NOT_READY;
+    }
+
+    /* Reads data */
+    *byte = (uint8_t)p_uart->data;
+
+    return ARM_UART_ERR_NONE;
+}
+
+enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(p_uart->state & ARM_UART_TX_BF) {
+        return ARM_UART_ERR_NOT_READY;
+    }
+
+    /* Sends data */
+    p_uart->data = byte;
+
+    return ARM_UART_ERR_NONE;
+}
+
+enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(!(dev->data->state & ARM_UART_INITIALIZED)) {
+        return ARM_UART_ERR_NOT_INIT;
+    }
+
+    p_uart->ctrl |= ARM_UART_TX_INTR_EN;
+
+    return ARM_UART_ERR_NONE;
+}
+
+void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(dev->data->state & ARM_UART_INITIALIZED ) {
+        p_uart->ctrl &= ~ARM_UART_TX_INTR_EN;
+    }
+}
+
+uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(!(dev->data->state & ARM_UART_INITIALIZED)) {
+        return 0;
+    }
+
+    return !(p_uart->state & ARM_UART_TX_BF);
+}
+
+enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(!(dev->data->state & ARM_UART_INITIALIZED)) {
+        return ARM_UART_ERR_NOT_INIT;
+    }
+
+    p_uart->ctrl |= ARM_UART_RX_INTR_EN;
+
+    return ARM_UART_ERR_NONE;
+}
+
+void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(dev->data->state & ARM_UART_INITIALIZED) {
+        p_uart->ctrl &= ~ARM_UART_RX_INTR_EN;
+    }
+}
+
+uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(!(dev->data->state & ARM_UART_INITIALIZED)) {
+        return 0;
+    }
+
+    return (p_uart->state & ARM_UART_RX_BF);
+}
+
+void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
+                              enum arm_uart_irq_t irq)
+{
+    struct _arm_uart_reg_map_t* p_uart =
+                                    (struct _arm_uart_reg_map_t*)dev->cfg->base;
+
+    if(dev->data->state & ARM_UART_INITIALIZED) {
+        /* Clears pending interrupts */
+        switch(irq) {
+        case ARM_UART_IRQ_RX:
+            p_uart->intr_reg.intrclear = ARM_UART_RX_INTR;
+            break;
+        case ARM_UART_IRQ_TX:
+            p_uart->intr_reg.intrclear = ARM_UART_TX_INTR;
+            break;
+        case ARM_UART_IRQ_COMBINED:
+            p_uart->intr_reg.intrclear = (ARM_UART_RX_INTR | ARM_UART_TX_INTR);
+            break;
+        /* default: not defined to force all cases to be handled */
+        }
+    }
+}
diff --git a/platform/ext/target/nuvoton/common/native_drivers/arm_uart_drv.h b/platform/ext/target/nuvoton/common/native_drivers/arm_uart_drv.h
new file mode 100644
index 0000000..64d8200
--- /dev/null
+++ b/platform/ext/target/nuvoton/common/native_drivers/arm_uart_drv.h
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2016-2017 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * \file arm_uart_drv.h
+ * \brief Generic driver for ARM UART.
+ */
+
+#ifndef __ARM_UART_DRV_H__
+#define __ARM_UART_DRV_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ARM UART device configuration structure */
+struct arm_uart_dev_cfg_t {
+    const uint32_t base;              /*!< UART base address */
+    const uint32_t default_baudrate;  /*!< Default baudrate */
+};
+
+/* ARM UART device data structure */
+struct arm_uart_dev_data_t {
+    uint32_t state;       /*!< Indicates if the uart driver
+                               is initialized and enabled */
+    uint32_t system_clk;  /*!< System clock */
+    uint32_t baudrate;    /*!< Baudrate */
+};
+
+/* ARM UART device structure */
+struct arm_uart_dev_t {
+    const struct arm_uart_dev_cfg_t* const cfg;  /*!< UART configuration */
+    struct arm_uart_dev_data_t* const data;      /*!< UART data */
+};
+
+/* ARM UART enumeration types */
+enum arm_uart_error_t {
+    ARM_UART_ERR_NONE = 0,      /*!< No error */
+    ARM_UART_ERR_INVALID_ARG,   /*!< Error invalid input argument */
+    ARM_UART_ERR_INVALID_BAUD,  /*!< Invalid baudrate */
+    ARM_UART_ERR_NOT_INIT,      /*!< Error UART not initialized */
+    ARM_UART_ERR_NOT_READY,     /*!< Error UART not ready */
+};
+
+enum arm_uart_irq_t {
+    ARM_UART_IRQ_RX,       /*!< RX interrupt source */
+    ARM_UART_IRQ_TX,       /*!< TX interrupt source */
+    ARM_UART_IRQ_COMBINED  /*!< RX-TX combined interrupt source */
+};
+
+/**
+ * \brief Initializes UART. It uses the default baudrate to configure
+ * the peripheral at this point.
+ *
+ * \param[in] dev         UART device struct \ref arm_uart_dev_t
+ * \param[in] system_clk  System clock used by the device.
+ *
+ * \return Returns error code as specified in \ref arm_uart_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum arm_uart_error_t arm_uart_init(struct arm_uart_dev_t* dev,
+                                    uint32_t system_clk);
+
+/**
+ * \brief Sets the UART baudrate.
+ *
+ * \param[in] dev       UART device struct \ref arm_uart_dev_t
+ * \param[in] baudrate  New baudrate.
+ *
+ * \return Returns error code as specified in \ref arm_uart_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum arm_uart_error_t arm_uart_set_baudrate(struct arm_uart_dev_t* dev,
+                                            uint32_t baudrate);
+
+/**
+ * \brief Gets the UART baudrate.
+ *
+ * \param[in] dev  UART device struct \ref arm_uart_dev_t
+ *
+ * \return Returns the UART baudrate.
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+uint32_t arm_uart_get_baudrate(struct arm_uart_dev_t* dev);
+
+/**
+ * \brief Sets system clock.
+ *
+ * \param[in] dev         UART device struct \ref arm_uart_dev_t
+ * \param[in] system_clk  System clock used by the device.
+ *
+ * \return Returns error code as specified in \ref arm_uart_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum arm_uart_error_t arm_uart_set_clock(struct arm_uart_dev_t* dev,
+                                         uint32_t system_clk);
+/**
+ * \brief Reads one byte from UART dev.
+ *
+ * \param[in] dev   UART device struct \ref arm_uart_dev_t
+ * \param[in] byte  Pointer to byte.
+ *
+ * \return Returns error code as specified in \ref arm_uart_error_t
+ *
+ * \note For better performance, this function doesn't check if dev and byte
+ * pointer are NULL, and if the driver is initialized.
+ */
+enum arm_uart_error_t arm_uart_read(struct arm_uart_dev_t* dev, uint8_t* byte);
+
+/**
+ * \brief Writes a byte to UART dev.
+ *
+ * \param[in] dev   UART device struct \ref arm_uart_dev_t
+ * \param[in] byte  Byte to write.
+ *
+ * \return Returns error code as specified in \ref arm_uart_error_t
+ *
+ * \note For better performance, this function doesn't check if dev is NULL and
+ * if the driver is initialized to have better performance.
+ */
+enum arm_uart_error_t arm_uart_write(struct arm_uart_dev_t* dev, uint8_t byte);
+
+/**
+ * \brief Enables TX interrupt.
+ *
+ * \param[in] dev  UART device struct \ref arm_uart_dev_t
+ *
+ * \return Returns error code as specified in \ref arm_uart_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum arm_uart_error_t arm_uart_irq_tx_enable(struct arm_uart_dev_t* dev);
+
+/**
+ * \brief Disables TX interrupt.
+ *
+ * \param[in] dev  UART device struct \ref arm_uart_dev_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+void arm_uart_irq_tx_disable(struct arm_uart_dev_t* dev);
+
+/**
+ * \brief  Verifies if Tx is ready to send more data.
+ *
+ * \param[in] dev  UART device struct \ref arm_uart_dev_t
+ *
+ * \return  1 if TX is ready, 0 otherwise.
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+uint32_t arm_uart_tx_ready(struct arm_uart_dev_t* dev);
+
+/**
+ * \brief Enables RX interrupt.
+ *
+ * \param[in] dev  UART device struct \ref arm_uart_dev_t
+ *
+ * \return Returns error code as specified in \ref arm_uart_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum arm_uart_error_t arm_uart_irq_rx_enable(struct arm_uart_dev_t* dev);
+
+/**
+ * \brief Disables RX interrupt
+ *
+ * \param[in] dev  UART device struct \ref arm_uart_dev_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+void arm_uart_irq_rx_disable(struct arm_uart_dev_t* dev);
+
+/**
+ * \brief Verifies if Rx has data.
+ *
+ * \param[in] dev  UART device struct \ref arm_uart_dev_t
+ *
+ * \return 1 if RX has data, 0 otherwise.
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+uint32_t arm_uart_rx_ready(struct arm_uart_dev_t* dev);
+
+/**
+ * \brief Clears UART interrupt.
+ *
+ * \param[in] dev  UART device struct \ref arm_uart_dev_t
+ * \param[in] irq  IRQ source to clean \ref arm_uart_irq_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+void arm_uart_clear_interrupt(struct arm_uart_dev_t* dev,
+                              enum arm_uart_irq_t irq);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __ARM_UART_DRV_H__ */
diff --git a/platform/ext/target/nuvoton/common/spm_hal.c b/platform/ext/target/nuvoton/common/spm_hal.c
index a7aa327..acaced1 100644
--- a/platform/ext/target/nuvoton/common/spm_hal.c
+++ b/platform/ext/target/nuvoton/common/spm_hal.c
@@ -81,6 +81,8 @@
 
 uint32_t tfm_spm_hal_get_ns_entry_point(void)
 {
+    printf("ns entry point = 0x%08x\r\n", memory_regions.non_secure_code_start + 4);
+
     return *((uint32_t *)(memory_regions.non_secure_code_start+ 4));
 }
 
diff --git a/platform/ext/target/nuvoton/common/target_cfg.h b/platform/ext/target/nuvoton/common/target_cfg.h
index c876880..f427b5f 100644
--- a/platform/ext/target/nuvoton/common/target_cfg.h
+++ b/platform/ext/target/nuvoton/common/target_cfg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2019-2020 Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2020 Arm Limited
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,26 +17,38 @@
 #ifndef __TARGET_CFG_H__
 #define __TARGET_CFG_H__
 
-#include <stdint.h>
+#include "uart_stdout.h"
+#include "tfm_peripherals_def.h"
+#include "tfm_plat_defs.h"
+#include "arm_uart_drv.h"
 
 #define TFM_DRIVER_STDIO    Driver_USART0
 #define NS_DRIVER_STDIO     Driver_USART0
 
-enum ppc_bank_e {
-    PPC_SP_DO_NOT_CONFIGURE = -1,
-    PPC_SP_AHB_PPC_EXP0 = 0,
-    PPC_SP_APB_PPC      = 1,
-    PPC_SP_APB_PPC_EXP0 = 2,
-    PPC_SP_APB_PPC_EXP1 = 3,
-    PPC_SP_APB_PPC_EXP2 = 4,
-    PPC_SP_APB_PPC_EXP3 = 5,
-};
-
 /**
- * \brief MPU configs
+ * \brief Defines the word offsets of Slave Peripheral Protection Controller
+ *        Registers
  */
-#define PRIVILEGED_DEFAULT_ENABLE   1
-#define HARDFAULT_NMI_ENABLE        1
+enum ppc_bank_e
+{
+    PPC_SP_DO_NOT_CONFIGURE = -1,
+    PPC_SP_AHB_PPC0 = 0,
+    PPC_SP_RES0,
+    PPC_SP_RES1,
+    PPC_SP_RES2,
+    PPC_SP_AHB_PPC_EXP0,
+    PPC_SP_AHB_PPC_EXP1,
+    PPC_SP_AHB_PPC_EXP2,
+    PPC_SP_AHB_PPC_EXP3,
+    PPC_SP_APB_PPC0,
+    PPC_SP_APB_PPC1,
+    PPC_SP_RES3,
+    PPC_SP_RES4,
+    PPC_SP_APB_PPC_EXP0,
+    PPC_SP_APB_PPC_EXP1,
+    PPC_SP_APB_PPC_EXP2,
+    PPC_SP_APB_PPC_EXP3,
+};
 
 /**
  * \brief Store the addresses of memory regions
@@ -56,7 +68,8 @@
 /**
  * \brief Holds the data necessary to do isolation for a specific peripheral.
  */
-struct platform_data_t {
+struct platform_data_t
+{
     uint32_t periph_start;
     uint32_t periph_limit;
     enum ppc_bank_e periph_ppc_bank;
@@ -64,13 +77,51 @@
 };
 
 /**
- * \brief Forward declaration
+ * \brief Configures the Memory Protection Controller.
+ *
+ * \return  Returns error code.
  */
-struct mpu_armv8m_region_cfg_t;
+int32_t mpc_init_cfg(void);
 
 /**
- * \brief Enables the fault handlers BusFault, UsageFault,
- *        MemManageFault and SecureFault.
+ * \brief Configures the Peripheral Protection Controller.
+ */
+void ppc_init_cfg(void);
+
+/**
+ * \brief Restict access to peripheral to secure
+ */
+void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t loc);
+
+/**
+ * \brief Allow non-secure access to peripheral
+ */
+void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t loc);
+
+/**
+ * \brief Enable secure unprivileged access to peripheral
+ */
+void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
+
+/**
+ * \brief Clear secure unprivileged access to peripheral
+ */
+void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
+
+/**
+ * \brief Clears PPC interrupt.
+ */
+void ppc_clear_irq(void);
+
+/**
+ * \brief Configures SAU and IDAU.
+ */
+void sau_and_idau_cfg(void);
+
+/**
+ * \brief Enables the fault handlers and sets priorities.
+ *
+ * \return Returns values as specified by the \ref tfm_plat_err_t
  */
 enum tfm_plat_err_t enable_fault_handlers(void);
 
@@ -92,88 +143,18 @@
  * \brief Configures all external interrupts to target the
  *        NS state, apart for the ones associated to secure
  *        peripherals (plus MPC and PPC)
+ *
+ * \return Returns values as specified by the \ref tfm_plat_err_t
  */
 enum tfm_plat_err_t nvic_interrupt_target_state_cfg(void);
 
 /**
  * \brief This function enable the interrupts associated
- *        to the secure peripherals (plus MPC and PPC)
+ *        to the secure peripherals (plus the isolation boundary violation
+ *        interrupts)
+ *
+ * \return Returns values as specified by the \ref tfm_plat_err_t
  */
 enum tfm_plat_err_t nvic_interrupt_enable(void);
 
-/**
- * \brief This function enables the MPU
- */
-enum mpu_armv8m_error_t mpu_enable(uint32_t privdef_en, uint32_t hfnmi_en);
-
-/**
- * \brief This function disables the MPU
- */
-enum mpu_armv8m_error_t mpu_disable(void);
-
-/**
- * \brief This function enables the given MPU region
- */
-enum mpu_armv8m_error_t mpu_region_enable(
-                                    struct mpu_armv8m_region_cfg_t *region_cfg);
-
-/**
- * \brief This function dsables the given MPU region
- */
-enum mpu_armv8m_error_t mpu_region_disable(uint32_t region_nr);
-
-/**
- * \brief This function cleans all the MPU regions configs
- */
-enum mpu_armv8m_error_t mpu_clean(void);
-
-/**
- * \brief Configures the Memory Protection Controller.
- */
-enum tfm_plat_err_t mpc_init_cfg(void);
-
-/**
- * \brief Clear MPC interrupt.
- */
-void mpc_clear_irq(void);
-
-/**
- * \brief Configures the Peripheral Protection Controller.
- */
-enum tfm_plat_err_t ppc_init_cfg(void);
-
-/**
- * \brief Restict peripheral access to secure access only
- *
- * \note The function does not configure privilege
- */
-void ppc_configure_to_secure(enum ppc_bank_e bank, uint32_t pos);
-
-/**
- * \brief Allow non-secure access to peripheral
- *
- * \note The function does not configure privilege
- */
-void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint32_t pos);
-
-/**
- * \brief Enable secure unprivileged access to peripheral
- */
-void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
-
-/**
- * \brief Clear secure unprivileged access to peripheral
- */
-void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
-
-/**
- * \brief Clears PPC interrupt.
- */
-void ppc_clear_irq(void);
-
-/**
- * \brief Configures SAU and IDAU.
- */
-void sau_and_idau_cfg(void);
-
 #endif /* __TARGET_CFG_H__ */
diff --git a/platform/ext/target/nuvoton/common/tfm_hal_isolation.c b/platform/ext/target/nuvoton/common/tfm_hal_isolation.c
index d5e033b..1cfa416 100644
--- a/platform/ext/target/nuvoton/common/tfm_hal_isolation.c
+++ b/platform/ext/target/nuvoton/common/tfm_hal_isolation.c
@@ -5,26 +5,78 @@
  *
  */
 
+#include "array.h"
 #include "cmsis.h"
 #include "Driver_Common.h"
+#include "mmio_defs.h"
 #include "mpu_armv8m_drv.h"
 #include "region.h"
 #include "target_cfg.h"
 #include "tfm_hal_isolation.h"
-#include "tfm_plat_defs.h"
+#include "tfm_peripherals_def.h"
+#include "tfm_core_utils.h"
+#ifdef TFM_PSA_API
+#include "load/partition_defs.h"
+#include "load/asset_defs.h"
+#include "load/spm_load_api.h"
+#endif
+
+/* It can be retrieved from the MPU_TYPE register. */
+#define MPU_REGION_NUM                  8
 
 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
-#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
+static uint32_t n_configured_regions = 0;
+struct mpu_armv8m_dev_t dev_mpu_s = {MPU_BASE};
 
-#define MPU_REGION_VENEERS              0
-#define MPU_REGION_TFM_UNPRIV_CODE      1
-#define MPU_REGION_NS_STACK             2
-#define PARTITION_REGION_RO             3
-#define PARTITION_REGION_RW_STACK       4
 #ifdef CONFIG_TFM_PARTITION_META
-#define MPU_REGION_SP_META_PTR          7
+REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$ZI$$Base);
+REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$ZI$$Limit);
 #endif /* CONFIG_TFM_PARTITION_META */
 
+#if TFM_LVL == 3
+static uint32_t idx_boundary_handle = 0;
+REGION_DECLARE(Image$$, PT_RO_START, $$Base);
+REGION_DECLARE(Image$$, PT_RO_END, $$Base);
+REGION_DECLARE(Image$$, PT_PRIV_RWZI_START, $$Base);
+REGION_DECLARE(Image$$, PT_PRIV_RWZI_END, $$Base);
+
+const static struct mpu_armv8m_region_cfg_t isolation_regions[] = {
+    {
+        0, /* will be updated before using */
+        (uint32_t)&REGION_NAME(Image$$, PT_RO_START, $$Base),
+        (uint32_t)&REGION_NAME(Image$$, PT_RO_END, $$Base),
+        MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
+        MPU_ARMV8M_XN_EXEC_OK,
+        MPU_ARMV8M_AP_RO_PRIV_UNPRIV,
+        MPU_ARMV8M_SH_NONE,
+    },
+    /* For isolation Level 3, set up static isolation for privileged data.
+     * Unprivileged data is dynamically set during Partition scheduling.
+     */
+    {
+        0, /* will be updated before using */
+        (uint32_t)&REGION_NAME(Image$$, PT_PRIV_RWZI_START, $$Base),
+        (uint32_t)&REGION_NAME(Image$$, PT_PRIV_RWZI_END, $$Base),
+        MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
+        MPU_ARMV8M_XN_EXEC_NEVER,
+        MPU_ARMV8M_AP_RW_PRIV_ONLY,
+        MPU_ARMV8M_SH_NONE,
+    },
+#ifdef CONFIG_TFM_PARTITION_META
+    /* TFM partition metadata pointer region */
+    {
+        0, /* will be updated before using */
+        (uint32_t)&REGION_NAME(Image$$, TFM_SP_META_PTR, $$ZI$$Base),
+        (uint32_t)&REGION_NAME(Image$$, TFM_SP_META_PTR, $$ZI$$Limit),
+        MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
+        MPU_ARMV8M_XN_EXEC_NEVER,
+        MPU_ARMV8M_AP_RW_PRIV_UNPRIV,
+        MPU_ARMV8M_SH_NONE
+    }
+#endif
+};
+#else /* TFM_LVL == 3 */
+
 REGION_DECLARE(Image$$, ER_VENEER, $$Base);
 REGION_DECLARE(Image$$, VENEER_ALIGN, $$Limit);
 REGION_DECLARE(Image$$, TFM_UNPRIV_CODE, $$RO$$Base);
@@ -33,15 +85,11 @@
 REGION_DECLARE(Image$$, TFM_APP_CODE_END, $$Base);
 REGION_DECLARE(Image$$, TFM_APP_RW_STACK_START, $$Base);
 REGION_DECLARE(Image$$, TFM_APP_RW_STACK_END, $$Base);
-#ifdef CONFIG_TFM_PARTITION_META
-REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$ZI$$Base);
-REGION_DECLARE(Image$$, TFM_SP_META_PTR, $$ZI$$Limit);
-#endif /* CONFIG_TFM_PARTITION_META */
 
 const struct mpu_armv8m_region_cfg_t region_cfg[] = {
     /* Veneer region */
     {
-        MPU_REGION_VENEERS,
+        0, /* will be updated before using */
         (uint32_t)&REGION_NAME(Image$$, ER_VENEER, $$Base),
         (uint32_t)&REGION_NAME(Image$$, VENEER_ALIGN, $$Limit),
         MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
@@ -51,7 +99,7 @@
     },
     /* TFM Core unprivileged code region */
     {
-        MPU_REGION_TFM_UNPRIV_CODE,
+        0, /* will be updated before using */
         (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Base),
         (uint32_t)&REGION_NAME(Image$$, TFM_UNPRIV_CODE, $$RO$$Limit),
         MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
@@ -61,7 +109,7 @@
     },
     /* RO region */
     {
-        PARTITION_REGION_RO,
+        0, /* will be updated before using */
         (uint32_t)&REGION_NAME(Image$$, TFM_APP_CODE_START, $$Base),
         (uint32_t)&REGION_NAME(Image$$, TFM_APP_CODE_END, $$Base),
         MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
@@ -71,7 +119,7 @@
     },
     /* RW, ZI and stack as one region */
     {
-        PARTITION_REGION_RW_STACK,
+        0, /* will be updated before using */
         (uint32_t)&REGION_NAME(Image$$, TFM_APP_RW_STACK_START, $$Base),
         (uint32_t)&REGION_NAME(Image$$, TFM_APP_RW_STACK_END, $$Base),
         MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
@@ -82,7 +130,7 @@
 #ifdef CONFIG_TFM_PARTITION_META
     /* TFM partition metadata pointer region */
     {
-        MPU_REGION_SP_META_PTR,
+        0, /* will be updated before using */
         (uint32_t)&REGION_NAME(Image$$, TFM_SP_META_PTR, $$ZI$$Base),
         (uint32_t)&REGION_NAME(Image$$, TFM_SP_META_PTR, $$ZI$$Limit),
         MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
@@ -92,39 +140,296 @@
     }
 #endif
 };
+#endif /* TFM_LVL == 3 */
 #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
 
 enum tfm_hal_status_t tfm_hal_set_up_static_boundaries(void)
 {
     /* Set up isolation boundaries between SPE and NSPE */
     sau_and_idau_cfg();
-
-    if (mpc_init_cfg() != TFM_PLAT_ERR_SUCCESS) {
+    if (mpc_init_cfg() != ARM_DRIVER_OK) {
         return TFM_HAL_ERROR_GENERIC;
     }
-
-    if (ppc_init_cfg() != TFM_PLAT_ERR_SUCCESS) {
-        return TFM_HAL_ERROR_GENERIC;
-    }
+    ppc_init_cfg();
 
     /* Set up static isolation boundaries inside SPE */
 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
+    struct mpu_armv8m_region_cfg_t localcfg;
     int32_t i;
-    struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
 
     mpu_armv8m_clean(&dev_mpu_s);
 
+#if TFM_LVL == 3
+    /*
+     * Update MPU region numbers. The numbers start from 0 and are continuous.
+     * Under isolation level3, at lease one MPU region is reserved for private
+     * data asset.
+     */
+    if (ARRAY_SIZE(isolation_regions) >= MPU_REGION_NUM) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
+    for (i = 0; i < ARRAY_SIZE(isolation_regions); i++) {
+        spm_memcpy(&localcfg, &isolation_regions[i], sizeof(localcfg));
+        /* Update region number */
+        localcfg.region_nr = i;
+        /* Enable regions */
+        if (mpu_armv8m_region_enable(&dev_mpu_s, &localcfg) != MPU_ARMV8M_OK) {
+            return TFM_HAL_ERROR_GENERIC;
+        }
+    }
+    n_configured_regions = i;
+#else /* TFM_LVL == 3 */
+    if (ARRAY_SIZE(region_cfg) > MPU_REGION_NUM) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
     for (i = 0; i < ARRAY_SIZE(region_cfg); i++) {
+        spm_memcpy(&localcfg, &region_cfg[i], sizeof(localcfg));
+        localcfg.region_nr = i;
         if (mpu_armv8m_region_enable(&dev_mpu_s,
-            (struct mpu_armv8m_region_cfg_t *)&region_cfg[i])
+            (struct mpu_armv8m_region_cfg_t *)&localcfg)
             != MPU_ARMV8M_OK) {
             return TFM_HAL_ERROR_GENERIC;
         }
     }
+    n_configured_regions = i;
+#endif /* TFM_LVL == 3 */
 
-    mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
-                      HARDFAULT_NMI_ENABLE);
+    /* Enable MPU */
+    if (mpu_armv8m_enable(&dev_mpu_s,
+                          PRIVILEGED_DEFAULT_ENABLE,
+                          HARDFAULT_NMI_ENABLE) != MPU_ARMV8M_OK) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
 #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
 
     return TFM_HAL_SUCCESS;
 }
+
+#ifdef TFM_PSA_API
+/*
+ * Implementation of tfm_hal_bind_boundaries() on AN521:
+ *
+ * The API encodes some attributes into a handle and returns it to SPM.
+ * The attributes include isolation boundaries, privilege, and mmio information.
+ * When scheduler switches running partitions, SPM compares the handle between
+ * partitions to know if boundary update is necessary. If update is required,
+ * SPM passes the handle to platform to do platform settings and update
+ * isolation boundaries.
+ *
+ * The handle should be unique under isolation level 3. The implementation
+ * encodes an index at the highest 8 bits to assure handle uniqueness. While
+ * under isolation level 1/2, handles may not be unique.
+ *
+ * The encoding format assignment:
+ * - For isolation level 3
+ *      BIT | 31        24 | 23         20 | ... | 7           4 | 3        0 |
+ *          | Unique Index | Region Attr 5 | ... | Region Attr 1 | Privileged |
+ *
+ *      In which the "Region Attr i" is:
+ *      BIT |       3      | 2        0 |
+ *          | 1: RW, 0: RO | MMIO Index |
+ *
+ * - For isolation level 1/2
+ *      BIT | 31                           0 |
+ *          | 1: privileged, 0: unprivileged |
+ *
+ * This is a reference implementation on AN521, and may have some limitations.
+ * 1. The maximum number of allowed MMIO regions is 5.
+ * 2. Highest 8 bits are for index. It supports 256 unique handles at most.
+ */
+enum tfm_hal_status_t tfm_hal_bind_boundaries(
+                                    const struct partition_load_info_t *p_ldinf,
+                                    void **pp_boundaries)
+{
+    uint32_t i, j;
+    bool privileged;
+    const struct asset_desc_t *p_asset;
+    struct platform_data_t *plat_data_ptr;
+#if TFM_LVL == 2
+    struct mpu_armv8m_region_cfg_t localcfg;
+#elif TFM_LVL == 3
+    uint32_t partition_attrs = 0;
+#endif
+
+    if (!p_ldinf || !pp_boundaries) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
+
+#if TFM_LVL == 1
+    privileged = true;
+#else
+    privileged = IS_PARTITION_PSA_ROT(p_ldinf);
+#endif
+
+    p_asset = (const struct asset_desc_t *)LOAD_INFO_ASSET(p_ldinf);
+
+    /*
+     * Validate if the named MMIO of partition is allowed by the platform.
+     * Otherwise, skip validation.
+     *
+     * NOTE: Need to add validation of numbered MMIO if platform requires.
+     */
+    for (i = 0; i < p_ldinf->nassets; i++) {
+        if (!(p_asset[i].attr & ASSET_ATTR_NAMED_MMIO)) {
+            continue;
+        }
+        for (j = 0; j < ARRAY_SIZE(partition_named_mmio_list); j++) {
+            if (p_asset[i].dev.dev_ref == partition_named_mmio_list[j]) {
+                break;
+            }
+        }
+
+        if (j == ARRAY_SIZE(partition_named_mmio_list)) {
+            /* The MMIO asset is not in the allowed list of platform. */
+            return TFM_HAL_ERROR_GENERIC;
+        }
+        /* Assume PPC & MPC settings are required even under level 1 */
+        plat_data_ptr = REFERENCE_TO_PTR(p_asset[i].dev.dev_ref,
+                                         struct platform_data_t *);
+
+        if (plat_data_ptr->periph_ppc_bank != PPC_SP_DO_NOT_CONFIGURE) {
+            ppc_configure_to_secure(plat_data_ptr->periph_ppc_bank,
+                                    plat_data_ptr->periph_ppc_loc);
+            if (privileged) {
+                ppc_clr_secure_unpriv(plat_data_ptr->periph_ppc_bank,
+                                      plat_data_ptr->periph_ppc_loc);
+            } else {
+                ppc_en_secure_unpriv(plat_data_ptr->periph_ppc_bank,
+                                      plat_data_ptr->periph_ppc_loc);
+            }
+        }
+#if TFM_LVL == 2
+        /*
+         * Static boundaries are set. Set up MPU region for MMIO.
+         * Setup regions for unprivileged assets only.
+         */
+        if (!privileged) {
+            localcfg.region_base = plat_data_ptr->periph_start;
+            localcfg.region_limit = plat_data_ptr->periph_limit;
+            localcfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX;
+            localcfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
+            localcfg.attr_sh = MPU_ARMV8M_SH_NONE;
+            localcfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
+            localcfg.region_nr = n_configured_regions++;
+
+            if (mpu_armv8m_region_enable(&dev_mpu_s, &localcfg)
+                != MPU_ARMV8M_OK) {
+                return TFM_HAL_ERROR_GENERIC;
+            }
+        }
+#elif TFM_LVL == 3
+        /* Encode MMIO attributes into the "partition_attrs". */
+        partition_attrs <<= HANDLE_PER_ATTR_BITS;
+        partition_attrs |= ((j + 1) & HANDLE_ATTR_INDEX_MASK);
+        if (p_asset[i].attr & ASSET_ATTR_READ_WRITE) {
+            partition_attrs |= HANDLE_ATTR_RW_POS;
+        }
+#endif
+    }
+
+#if TFM_LVL == 3
+    partition_attrs <<= HANDLE_PER_ATTR_BITS;
+    partition_attrs |= ((uint8_t)privileged) & HANDLE_ATTR_PRIV_MASK;
+    /*
+     * Highest 8 bits are reserved for index, if they are non-zero, MMIO numbers
+     * must have exceeded the limit of 5.
+     */
+    if (partition_attrs & HANDLE_INDEX_MASK) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
+    HANDLE_ENCODE_INDEX(partition_attrs, idx_boundary_handle);
+    *pp_boundaries = (void *)partition_attrs;
+#else
+    *pp_boundaries = (void *)(((uint32_t)privileged) & HANDLE_ATTR_PRIV_MASK);
+#endif
+
+    return TFM_HAL_SUCCESS;
+}
+
+enum tfm_hal_status_t tfm_hal_update_boundaries(
+                             const struct partition_load_info_t *p_ldinf,
+                             void *p_boundaries)
+{
+    CONTROL_Type ctrl;
+    uint32_t local_handle = (uint32_t)p_boundaries;
+    bool privileged = !!(local_handle & HANDLE_ATTR_PRIV_MASK);
+#if TFM_LVL == 3
+    struct mpu_armv8m_region_cfg_t localcfg;
+    uint32_t i, mmio_index;
+    struct platform_data_t *plat_data_ptr;
+    struct asset_desc_t *rt_mem;
+#endif
+
+    /* Privileged level is required to be set always */
+    ctrl.w = __get_CONTROL();
+    ctrl.b.nPRIV = privileged ? 0 : 1;
+    __set_CONTROL(ctrl.w);
+
+#if TFM_LVL == 3
+    if (!p_ldinf) {
+        return TFM_HAL_ERROR_GENERIC;
+    }
+
+    /* Update regions, for unprivileged partitions only */
+    if (privileged) {
+        return TFM_HAL_SUCCESS;
+    }
+
+    /* Setup runtime memory first */
+    localcfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
+    localcfg.attr_sh = MPU_ARMV8M_SH_NONE;
+    localcfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DATA_IDX;
+    localcfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
+    rt_mem = (struct asset_desc_t *)LOAD_INFO_ASSET(p_ldinf);
+    /*
+     * AN521 shortcut: The first item is the only runtime memory asset.
+     * Platforms with many memory assets please check this part.
+     */
+    for (i = 0;
+         i < p_ldinf->nassets && !(rt_mem[i].attr & ASSET_ATTR_MMIO);
+         i++) {
+        localcfg.region_nr = n_configured_regions + i;
+        localcfg.region_base = rt_mem[i].mem.start;
+        localcfg.region_limit = rt_mem[i].mem.limit;
+
+        if (mpu_armv8m_region_enable(&dev_mpu_s, &localcfg) != MPU_ARMV8M_OK) {
+            return TFM_HAL_ERROR_GENERIC;
+        }
+    }
+
+    /* Named MMIO part */
+    local_handle = local_handle & (~HANDLE_INDEX_MASK);
+    local_handle >>= HANDLE_PER_ATTR_BITS;
+    mmio_index = local_handle & HANDLE_ATTR_INDEX_MASK;
+
+    localcfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX;
+
+    i = n_configured_regions + i;
+    while (mmio_index && i < MPU_REGION_NUM) {
+        plat_data_ptr =
+          (struct platform_data_t *)partition_named_mmio_list[mmio_index - 1];
+        localcfg.region_nr = i++;
+        localcfg.attr_access = (local_handle & HANDLE_ATTR_RW_POS)?
+                            MPU_ARMV8M_AP_RW_PRIV_UNPRIV :
+                            MPU_ARMV8M_AP_RO_PRIV_UNPRIV;
+        localcfg.region_base = plat_data_ptr->periph_start;
+        localcfg.region_limit = plat_data_ptr->periph_limit;
+
+        if (mpu_armv8m_region_enable(&dev_mpu_s, &localcfg) != MPU_ARMV8M_OK) {
+            return TFM_HAL_ERROR_GENERIC;
+        }
+
+        local_handle >>= HANDLE_PER_ATTR_BITS;
+        mmio_index = local_handle & HANDLE_ATTR_INDEX_MASK;
+    }
+
+    /* Disable unused regions */
+    while (i < MPU_REGION_NUM) {
+        if (mpu_armv8m_region_disable(&dev_mpu_s, i++)!= MPU_ARMV8M_OK) {
+            return TFM_HAL_ERROR_GENERIC;
+        }
+    }
+#endif
+    return TFM_HAL_SUCCESS;
+}
+#endif /* TFM_PSA_API */
diff --git a/platform/ext/target/nuvoton/common/tfm_hal_platform.c b/platform/ext/target/nuvoton/common/tfm_hal_platform.c
index de04d70..c087635 100644
--- a/platform/ext/target/nuvoton/common/tfm_hal_platform.c
+++ b/platform/ext/target/nuvoton/common/tfm_hal_platform.c
@@ -13,39 +13,53 @@
 
 extern const struct memory_region_limits memory_regions;
 
+#ifdef TFM_FIH_PROFILE_ON
+fih_int tfm_hal_platform_init(void)
+#else
 enum tfm_hal_status_t tfm_hal_platform_init(void)
+#endif
 {
     enum tfm_plat_err_t plat_err = TFM_PLAT_ERR_SYSTEM_ERR;
+#ifdef TFM_FIH_PROFILE_ON
+    fih_int fih_rc = FIH_FAILURE;
+#endif
 
     plat_err = enable_fault_handlers();
     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
-        return TFM_HAL_ERROR_GENERIC;
+        FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
     }
 
     plat_err = system_reset_cfg();
     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
-        return TFM_HAL_ERROR_GENERIC;
+        FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
     }
 
+#ifdef TFM_FIH_PROFILE_ON
+    FIH_CALL(init_debug, fih_rc);
+    if (fih_not_eq(fih_rc, fih_int_encode(TFM_PLAT_ERR_SUCCESS))) {
+        FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
+    }
+#else
     plat_err = init_debug();
     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
         return TFM_HAL_ERROR_GENERIC;
     }
+#endif
 
     __enable_irq();
     stdio_init();
 
     plat_err = nvic_interrupt_target_state_cfg();
     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
-        return TFM_HAL_ERROR_GENERIC;
+        FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
     }
 
     plat_err = nvic_interrupt_enable();
     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
-        return TFM_HAL_ERROR_GENERIC;
+        FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
     }
 
-    return TFM_HAL_SUCCESS;
+    FIH_RET(fih_int_encode(TFM_HAL_SUCCESS));
 }
 
 uint32_t tfm_hal_get_ns_VTOR(void)
diff --git a/platform/ext/target/nuvoton/m2354/CMakeLists.txt b/platform/ext/target/nuvoton/m2354/CMakeLists.txt
index 779400f..84057bc 100644
--- a/platform/ext/target/nuvoton/m2354/CMakeLists.txt
+++ b/platform/ext/target/nuvoton/m2354/CMakeLists.txt
@@ -25,7 +25,7 @@
         $<$<C_COMPILER_ID:IAR>:${CMAKE_CURRENT_SOURCE_DIR}/device/source/iar/startup_cmsdk_m2354_s.s>
 )
 target_add_scatter_file(tfm_s
-    $<$<C_COMPILER_ID:ARMClang>:${CMAKE_CURRENT_SOURCE_DIR}/device/source/armclang/m2354_s.sct>
+    $<$<AND:$<VERSION_LESS:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:ARMClang>>:${CMAKE_SOURCE_DIR}/platform/ext/common/armclang/tfm_common_s.sct>
     $<$<AND:$<VERSION_LESS:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:GNU>>:${CMAKE_SOURCE_DIR}/platform/ext/common/gcc/tfm_common_s.ld>
     $<$<AND:$<VERSION_LESS:${TFM_ISOLATION_LEVEL},3>,$<C_COMPILER_ID:IAR>>:${CMAKE_SOURCE_DIR}/platform/ext/common/iar/tfm_common_s.icf>
 )
@@ -88,11 +88,12 @@
         device/source/device_definition.c
         ../common/cmsis_drivers/Driver_Flash.c
         ../common/cmsis_drivers/Driver_USART.c
-        ../common/native_drivers/uart_cmsdk_drv.c
+        ../common/native_drivers/arm_uart_drv.c
         ../common/native_drivers/mpu_armv8m_drv.c
         ../common/native_drivers/timer_cmsdk_drv.c
         bsp/Library/StdDriver/src/timer.c
         bsp/Library/StdDriver/src/fmc.c
+        bsp/Library/StdDriver/src/tamper.c
         ../common/services/src/tfm_platform_system.c
         target_cfg.c
         ../common/spm_hal.c
@@ -114,7 +115,7 @@
 
 target_sources(platform_ns
     PRIVATE
-        ../common/native_drivers/uart_cmsdk_drv.c
+        ../common/native_drivers/arm_uart_drv.c
         ../common/cmsis_drivers/Driver_USART.c
         device/source/device_definition.c
         device/source/system_core_init.c
@@ -144,9 +145,10 @@
             device/source/device_definition.c
             device/source/system_core_init.c
             ../common/cmsis_drivers/Driver_Flash.c
-            ../common/native_drivers/uart_cmsdk_drv.c
+            ../common/native_drivers/arm_uart_drv.c
             ../common/cmsis_drivers/Driver_USART.c
             bsp/Library/StdDriver/src/fmc.c
+            bsp/Library/StdDriver/src/tamper.c
     )
     target_include_directories(platform_bl2
         PUBLIC
diff --git a/platform/ext/target/nuvoton/m2354/README.rst b/platform/ext/target/nuvoton/m2354/README.rst
index 20558e9..b978f74 100644
--- a/platform/ext/target/nuvoton/m2354/README.rst
+++ b/platform/ext/target/nuvoton/m2354/README.rst
@@ -14,6 +14,7 @@
             -G"Unix Makefiles" \
             -DTFM_PLATFORM=nuvoton/m2354 \
             -DTFM_TOOLCHAIN_FILE=../toolchain_GNUARM.cmake \
+            -DMCUBOOT_FIH_PROFILE=MEDIUM \
             -DTEST_S=ON \
             -DTEST_NS=ON \
             -DTFM_ISOLATION_LEVEL=2 \
@@ -45,4 +46,4 @@
 
 --------------
 
-*Copyright (c) 2021, Nuvoton Technology Corp. All rights reserved.*
+*Copyright (c) 2021-2022, Nuvoton Technology Corp. All rights reserved.*
diff --git a/platform/ext/target/nuvoton/common/bsp/Include/tamper_reg.h b/platform/ext/target/nuvoton/m2354/bsp/Device/Nuvoton/M2354/Include/tamper_reg.h
similarity index 100%
rename from platform/ext/target/nuvoton/common/bsp/Include/tamper_reg.h
rename to platform/ext/target/nuvoton/m2354/bsp/Device/Nuvoton/M2354/Include/tamper_reg.h
diff --git a/platform/ext/target/nuvoton/m2354/bsp/Library/StdDriver/inc/tamper.h b/platform/ext/target/nuvoton/m2354/bsp/Library/StdDriver/inc/tamper.h
index 2baa12a..ab4e766 100644
--- a/platform/ext/target/nuvoton/m2354/bsp/Library/StdDriver/inc/tamper.h
+++ b/platform/ext/target/nuvoton/m2354/bsp/Library/StdDriver/inc/tamper.h
@@ -68,6 +68,20 @@
 #define TAMPER_REF_SEED                  0x1UL     /*!< The new reference pattern is repeated from SEED (TAMPER_SEED[31:0]) when the reference pattern run out */
 
 #define TAMPER_VG_192M_SAMPLE            0x0UL     /*!< Select voltage glitch 192M sampleing rate */
+#define TAMPER_VG_96M_SAMPLE             0x1UL     /*!< Select voltage glitch 96M sampleing rate */
+#define TAMPER_VG_48M_SAMPLE             0x2UL     /*!< Select voltage glitch 48M sampleing rate */
+
+#define TAMPER_LBSTRIM_TLVDSEL_1_25V     0x0UL     /*!< Select the trim value of the under-shoot detection level as 1.25V */
+#define TAMPER_LBSTRIM_TLVDSEL_1_20V     0x1UL     /*!< Select the trim value of the under-shoot detection level as 1.2V */
+#define TAMPER_LBSTRIM_TLVDSEL_1_15V     0x2UL     /*!< Select the trim value of the under-shoot detection level as 1.15V */
+#define TAMPER_LBSTRIM_TLVDSEL_1_10V     0x3UL     /*!< Select the trim value of the under-shoot detection level as 1.1V */
+#define TAMPER_LBSTRIM_TLVDSEL_1_05V     0x4UL     /*!< Select the trim value of the under-shoot detection level as 1.05V */
+#define TAMPER_LBSTRIM_TLVDSEL_1_00V     0x5UL     /*!< Select the trim value of the under-shoot detection level as 1.0V */
+#define TAMPER_LBSTRIM_TLVDSEL_0_95V     0x6UL     /*!< Select the trim value of the under-shoot detection level as 0.95V */
+#define TAMPER_LBSTRIM_TLVDSEL_0_90V     0x7UL     /*!< Select the trim value of the under-shoot detection level as 0.9V */
+
+#define TAMPER_LBSTRIM_TOVDSEL_1_35V     0x0UL     /*!< Select the trim value of the over-shoot detection level as 1.35V */
+#define TAMPER_LBSTRIM_TOVDSEL_1_40V     0x1UL     /*!< Select the trim value of the over-shoot detection level as 1.4V */
 
 /**@}*/ /* end of group TAMPER_EXPORTED_CONSTANTS */
 
@@ -79,10 +93,6 @@
 /**
   * @brief      Reset Tamper Coreblock
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    To set TAMPER INIT control register to reset the tamper coreblock.
   *
   */
@@ -91,10 +101,6 @@
 /**
   * @brief      Release Tamper Coreblock
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    To set TAMPER INIT control register to release the tamper coreblock.
   *
   */
@@ -103,8 +109,6 @@
 /**
   * @brief      Get the Voltage Regulator Power Ready Status
   *
-  * @param      None
-  *
   * @retval     0   The power status of voltage regulator is not ready.
   * @retval     1   The power status of voltage regulator is ready.
   *
@@ -116,10 +120,6 @@
 /**
   * @brief      Enable LXT Clock Detection
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    To set TAMPER FUNEN control register to enable LXT clock detection.
   *
   */
@@ -128,10 +128,6 @@
 /**
   * @brief      Disable LXT Clock Detection
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    To set TAMPER FUNEN control register to disable LXT clock detection.
   *
   */
@@ -148,8 +144,6 @@
   *                               - \ref TAMPER_TAMPER4_SELECT
   *                               - \ref TAMPER_TAMPER5_SELECT
   *
-  * @return     None
-  *
   * @details    To set TAMPER FUNEN control register to select tamper I/O 0~5 and its function is detected through TAMPER block.
   *
   */
@@ -177,8 +171,6 @@
   *                               - \ref TAMPER_TAMPER4_SELECT
   *                               - \ref TAMPER_TAMPER5_SELECT
   *
-  * @return     None
-  *
   * @details    To set TAMPER FUNEN control register to select tamper I/O 0~5 and its function is detected through RTC block.
   *
   */
@@ -198,10 +190,6 @@
 /**
   * @brief      Enable HIRC48M
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    To set TAMPER FUNEN control register to enable HIRC48M.
   *
   */
@@ -210,10 +198,6 @@
 /**
   * @brief      Disable HIRC48M
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    To set TAMPER FUNEN control register to disable HIRC48M.
   *
   */
@@ -222,10 +206,10 @@
 /**
   * @brief      Voltage Glitch Sampling Rate Selection
   *
-  * @param[in]  u32VGSampleRate Voltage Glitch sampling rate select. Possible option is
+  * @param[in]  u32VGSampleRate Voltage glitch sampling rate select. Possible options are
   *                             - \ref TAMPER_VG_192M_SAMPLE
-  *
-  * @return     None
+  *                             - \ref TAMPER_VG_96M_SAMPLE
+  *                             - \ref TAMPER_VG_48M_SAMPLE
   *
   * @details    To set TAMPER FUNEN control register to enable voltage glitch channel 0~3 to select voltage glitch sampling rate.
   *
@@ -238,15 +222,76 @@
     {
         TAMPER->FUNEN |= TAMPER_FUNEN_VGCHEN0_Msk | TAMPER_FUNEN_VGCHEN1_Msk | TAMPER_FUNEN_VGCHEN2_Msk | TAMPER_FUNEN_VGCHEN3_Msk;
     }
+    else if(u32VGSampleRate == TAMPER_VG_96M_SAMPLE)
+    {
+        TAMPER->FUNEN |= TAMPER_FUNEN_VGCHEN0_Msk | TAMPER_FUNEN_VGCHEN1_Msk;
+    }
+    else if(u32VGSampleRate == TAMPER_VG_48M_SAMPLE)
+    {
+        TAMPER->FUNEN |= TAMPER_FUNEN_VGCHEN0_Msk;
+    }
 }
 
 /**
+  * @brief      Voltage Glitch Reference Trim Value Initialization
+  *
+  * @details    To set TAMPER VG or VG2 control register to initialize a reference trim value that provides voltage glitch detection
+  *             error tolerance within 15%.
+  *
+  */
+__STATIC_INLINE void TAMPER_VG_TRIM_INIT()
+{
+    if(SYS->PLSTS & SYS_PLSTS_PLSTATUS_PL0)
+    {
+        TAMPER->VG = (TAMPER->VG & ~0xFFFFUL) | 0x8CC8UL;
+    }
+    else if(SYS->PLSTS & SYS_PLSTS_PLSTATUS_PL1)
+    {
+        TAMPER->VG = (TAMPER->VG & ~0xFFFF0000UL) | 0x7CC90000UL;
+    }
+    else if(SYS->PLSTS & SYS_PLSTS_PLSTATUS_PL2)
+    {
+        TAMPER->VG2 = (TAMPER->VG2 & ~0xFFFFUL) | 0x5CCBUL;
+    }
+    else if(SYS->PLSTS & SYS_PLSTS_PLSTATUS_PL3)
+    {
+        TAMPER->VG2 = (TAMPER->VG2 & ~0xFFFF0000UL) | 0x2CCD0000UL;
+    }
+}
+
+/**
+  * @brief      Under-shoot Detection Level Trim Value Initialization
+  *
+  * @param[in]  u32TLVDTrim Under-shoot detect level trim value select. Possible options are
+  *                         - \ref TAMPER_LBSTRIM_TLVDSEL_1_25V
+  *                         - \ref TAMPER_LBSTRIM_TLVDSEL_1_20V
+  *                         - \ref TAMPER_LBSTRIM_TLVDSEL_1_15V
+  *                         - \ref TAMPER_LBSTRIM_TLVDSEL_1_10V
+  *                         - \ref TAMPER_LBSTRIM_TLVDSEL_1_05V
+  *                         - \ref TAMPER_LBSTRIM_TLVDSEL_1_00V
+  *                         - \ref TAMPER_LBSTRIM_TLVDSEL_0_95V
+  *                         - \ref TAMPER_LBSTRIM_TLVDSEL_0_90V
+  *
+  * @details    To set TAMPER LBSTRIM control register to select under-shoot detection level trim value.
+  *
+  */
+#define TAMPER_TLVD_TRIM_INIT(u32TLVDTrim)   ((uint32_t)(TAMPER->LBSTRIM = (TAMPER->LBSTRIM & (~TAMPER_LBSTRIM_TLVDSEL_Msk)) | (u32TLVDTrim << TAMPER_LBSTRIM_TLVDSEL_Pos)))
+
+/**
+  * @brief      Over-shoot Detection Level Trim Value Initialization
+  *
+  * @param[in]  u32TOVDTrim Over-shoot detect level trim value select. Possible options are
+  *                         - \ref TAMPER_LBSTRIM_TOVDSEL_1_35V
+  *                         - \ref TAMPER_LBSTRIM_TOVDSEL_1_40V
+  *
+  * @details    To set TAMPER LBSTRIM control register to select over-shoot detection level trim value.
+  *
+  */
+#define TAMPER_TOVD_TRIM_INIT(u32TOVDTrim)   ((uint32_t)(TAMPER->LBSTRIM = (TAMPER->LBSTRIM & (~TAMPER_LBSTRIM_TOVDSEL_Msk)) | (u32TOVDTrim << TAMPER_LBSTRIM_TOVDSEL_Pos)))
+
+/**
   * @brief      Enable to Trigger Key Store
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Set KSTRIGEN bit of TAMPER TRIEN control register to trigger Key Store when Tamper event is detected.
   *
   */
@@ -255,10 +300,6 @@
 /**
   * @brief      Disable to Trigger Key Store
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Clear KSTRIGEN bit of TAMPER TRIEN control register to not trigger Key Store when Tamper event is detected.
   *
   */
@@ -267,10 +308,6 @@
 /**
   * @brief      Enable Wake-up Function
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Set WAKEUPEN bit of TAMPER TRIEN control register to wake-up the system when Tamper event is detected.
   *
   */
@@ -279,10 +316,6 @@
 /**
   * @brief      Disable Wake-up Function
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Clear WAKEUPEN bit of TAMPER TRIEN control register to not wake-up the system when Tamper event is detected.
   *
   */
@@ -291,10 +324,6 @@
 /**
   * @brief      Enable to Clear Crypto Function
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Set CRYPTOEN bit of TAMPER TRIEN control register to reset Crypto when Tamper event is detected.
   *
   */
@@ -303,10 +332,6 @@
 /**
   * @brief      Disable to Clear Crypto Function
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Clear CRYPTOEN bit of TAMPER TRIEN control register to not reset Crypto when Tamper event is detected.
   *
   */
@@ -315,10 +340,6 @@
 /**
   * @brief      Enable to Trigger Chip Reset
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Set CHIPRSTEN bit of TAMPER TRIEN control register to reset the system when Tamper event is detected.
   *
   */
@@ -327,10 +348,6 @@
 /**
   * @brief      Disable to Trigger Chip Reset
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Clear CHIPRSTEN bit of TAMPER TRIEN control register to not reset the system when Tamper event is detected.
   *
   */
@@ -339,10 +356,6 @@
 /**
   * @brief      Enable to Clear RTC Spare Register
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Set RTCSPCLREN bit of TAMPER TRIEN control register to reset RTC spare register when Tamper event is detected.
   *
   */
@@ -351,10 +364,6 @@
 /**
   * @brief      Disable to Clear RTC Spare Register
   *
-  * @param      None
-  *
-  * @return     None
-  *
   * @details    Clear RTCSPCLREN bit of TAMPER TRIEN control register to not reset RTC spare register when Tamper event is detected.
   *
   */
@@ -363,15 +372,13 @@
 /**
   * @brief      Get Tamper Interrupt Flag
   *
-  * @param      None
-  *
   * @retval     0   Tamper event Interrupt did not occur
   * @retval     1   Tamper event Interrupt occurred
   *
   * @details    This macro indicates Tamper event intertupt occurred or not.
   *
   */
-#define TAMPER_GET_INT_FLAG()      ((TAMPER->INTSTS & (0xAA7FAFFF))? 1:0)
+#define TAMPER_GET_INT_FLAG()      ((TAMPER->INTSTS & (0xAA77AFFF))? 1:0)
 
 /**
   * @brief      Clear Tamper Interrupt Status
@@ -391,14 +398,14 @@
   *                             - \ref TAMPER_INTSTS_ACTSEIF_Msk
   *                             - \ref TAMPER_INTSTS_ACTST5IF_Msk
   *                             - \ref TAMPER_INTSTS_ACTST25IF_Msk
+  *                             - \ref TAMPER_INTSTS_VBATLOSSIF_Msk
+  *                             - \ref TAMPER_INTSTS_SECWDTIF_Msk
   *                             - \ref TAMPER_INTSTS_BODIF_Msk
   *                             - \ref TAMPER_INTSTS_ACTST1IF_Msk
   *                             - \ref TAMPER_INTSTS_ACTST3IF_Msk
   *                             - \ref TAMPER_INTSTS_ACTST21IF_Msk
   *                             - \ref TAMPER_INTSTS_ACTST23IF_Msk
   *
-  * @return     None
-  *
   * @details    This macro is used to clear Tamper event flag.
   *
   */
@@ -407,8 +414,6 @@
 /**
   * @brief      Get Tamper Interrupt Status
   *
-  * @param      None
-  *
   * @retval     TAMPER_INTSTS_TAMP0IF_Msk
   * @retval     TAMPER_INTSTS_TAMP1IF_Msk
   * @retval     TAMPER_INTSTS_TAMP2IF_Msk
@@ -426,6 +431,8 @@
   * @retval     TAMPER_INTSTS_RTCLVRIF_Msk
   * @retval     TAMPER_INTSTS_RIOTRIGIF_Msk
   * @retval     TAMPER_INTSTS_RCLKTRIGIF_Msk
+  * @retval     TAMPER_INTSTS_VBATLOSSIF_Msk
+  * @retval     TAMPER_INTSTS_SECWDTIF_Msk
   * @retval     TAMPER_INTSTS_BODIF_Msk
   * @retval     TAMPER_INTSTS_ACTST1IF_Msk
   * @retval     TAMPER_INTSTS_ACTST3IF_Msk
@@ -435,7 +442,7 @@
   * @details    This macro indicates Tamper event status.
   *
   */
-#define TAMPER_GET_INT_STATUS()    ((TAMPER->INTSTS & (0xAA7FAFFF)))
+#define TAMPER_GET_INT_STATUS()    ((TAMPER->INTSTS & (0xAA77AFFF)))
 
 void TAMPER_EnableInt(uint32_t u32IntFlagMask);
 void TAMPER_DisableInt(uint32_t u32IntFlagMask);
@@ -461,3 +468,4 @@
 #endif
 
 #endif /* __TAMPER_H__ */
+
diff --git a/platform/ext/target/nuvoton/common/bsp/StdDriver/src/tamper.c b/platform/ext/target/nuvoton/m2354/bsp/Library/StdDriver/src/tamper.c
similarity index 100%
rename from platform/ext/target/nuvoton/common/bsp/StdDriver/src/tamper.c
rename to platform/ext/target/nuvoton/m2354/bsp/Library/StdDriver/src/tamper.c
diff --git a/platform/ext/target/nuvoton/m2354/device/source/system_core_init.c b/platform/ext/target/nuvoton/m2354/device/source/system_core_init.c
index 89f1899..460f1f8 100644
--- a/platform/ext/target/nuvoton/m2354/device/source/system_core_init.c
+++ b/platform/ext/target/nuvoton/m2354/device/source/system_core_init.c
@@ -64,63 +64,147 @@
 #endif
 
 //#if __DOMAIN_NS == 0
-#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3L)
 
-  /* Initial the system */
-  SYS_UnlockReg();
+#if (defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3L) && defined(BL2))
 
-  /* Enable HIRC and waiting for stable */
-  CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
-  while((CLK->STATUS & CLK_STATUS_HIRCSTB_Msk) == 0);
+    /* Initial the system */
+    SYS_UnlockReg();
 
-  /* Enable PLL and waiting for stable */
-  CLK->PLLCTL = CLK_PLLCTL_96MHz_HIRC;
-  while((CLK->STATUS & CLK_STATUS_PLLSTB_Msk) == 0);
+#ifdef NV_ENABLE_ETM
+    /* Init ETM Trace */
+    SYS->GPE_MFPH = (SYS->GPE_MFPH & (~(TRACE_CLK_PE12_Msk | TRACE_DATA0_PE11_Msk | TRACE_DATA1_PE10_Msk | TRACE_DATA2_PE9_Msk | TRACE_DATA3_PE8_Msk))) |
+        TRACE_CLK_PE12 | TRACE_DATA0_PE11 | TRACE_DATA1_PE10 | TRACE_DATA2_PE9 | TRACE_DATA3_PE8;
 
-  /* Set flash access delay cycle */
-  FMC->CYCCTL = 3;
-
-  /* Switch HCLK clock source to PLL */
-  CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_PLL;
-  CLK->CLKDIV0 = 0;
-
-  /* Enable IP clock */
-  CLK->APBCLK0 |= CLK_APBCLK0_UART0CKEN_Msk | CLK_APBCLK0_TMR0CKEN_Msk | CLK_APBCLK0_TMR2CKEN_Msk;
-
-  /* Select UART clock source */
-  CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_UART0SEL_Msk)) | CLK_CLKSEL2_UART0SEL_HIRC;
-
-  /* Timer clock source */
-  CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_TMR0SEL_Msk)) | CLK_CLKSEL1_TMR0SEL_HIRC;
-  CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_TMR2SEL_Msk)) | CLK_CLKSEL1_TMR2SEL_HIRC;
-
-  /* Set multi-function pins for UART0 RXD and TXD */
-  SYS->GPA_MFPL = (SYS->GPA_MFPL & (~(UART0_RXD_PA6_Msk | UART0_TXD_PA7_Msk))) | UART0_RXD_PA6 | UART0_TXD_PA7;
-
-  /* Set UART 0 to Non-secure */
-  SCU_SET_PNSSET(UART0_Attr);
-
-  /* Set SAU */
-  SAU->RNR = 3;
-  SAU->RBAR = 0x50000000;
-  SAU->RLAR = (0x5FFFFFFF & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
-
-  /* Init ETM Trace */
-  SYS->GPE_MFPH = (SYS->GPE_MFPH & (~(TRACE_CLK_PE12_Msk | TRACE_DATA0_PE11_Msk | TRACE_DATA1_PE10_Msk | TRACE_DATA2_PE9_Msk | TRACE_DATA3_PE8_Msk))) |
-      TRACE_CLK_PE12 | TRACE_DATA0_PE11 | TRACE_DATA1_PE10 | TRACE_DATA2_PE9 | TRACE_DATA3_PE8;
-
-  /* power gating */
-  M32(0x400001f4) = 0xfffffffful;
-  M32(0x400000dC) = 0ul;
-  /* GPIO clk */
-  CLK->AHBCLK |= (0xffful << 20) | (1ul << 14);
-
-  /* PD2 LED */
-  PD2 = 1;
-  PD->MODE = (PD->MODE & (~(0x3 << 2))) | (1 << 2);
-
+    CLK->AHBCLK |= CLK_AHBCLK_TRACECKEN_Msk;
 #endif
 
+    /* power gating */
+    M32(0x400001f4) = 0xfffffffful;
+    M32(0x400000dC) = 0ul;
+
+    /* Enable SRAM Clock */
+    CLK->AHBCLK |= CLK_AHBCLK_SRAM0CKEN_Msk | CLK_AHBCLK_SRAM1CKEN_Msk | CLK_AHBCLK_SRAM2CKEN_Msk;
+
+    /* Enable GPIO Clock  */
+    CLK->AHBCLK |= CLK_AHBCLK_GPACKEN_Msk | CLK_AHBCLK_GPBCKEN_Msk | CLK_AHBCLK_GPCCKEN_Msk | CLK_AHBCLK_GPDCKEN_Msk |
+                   CLK_AHBCLK_GPECKEN_Msk | CLK_AHBCLK_GPFCKEN_Msk | CLK_AHBCLK_GPGCKEN_Msk | CLK_AHBCLK_GPHCKEN_Msk;
+
+    /* Enable HIRC and waiting for stable */
+    CLK->PWRCTL |= CLK_PWRCTL_HIRCEN_Msk;
+    while((CLK->STATUS & CLK_STATUS_HIRCSTB_Msk) == 0);
+
+    /* Force to use HIRC */
+    CLK->CLKSEL0 = (CLK->CLKSEL0  & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_HIRC;
+
+    /* Enable PLL and waiting for stable */
+    CLK->PLLCTL = CLK_PLLCTL_96MHz_HIRC;
+    while((CLK->STATUS & CLK_STATUS_PLLSTB_Msk) == 0);
+
+    /* Set flash access delay cycle */
+    FMC->CYCCTL = (FMC->CYCCTL & (~FMC_CYCCTL_CYCLE_Msk)) | (4 << FMC_CYCCTL_CYCLE_Pos);
+
+    /* Switch HCLK clock source to PLL */
+    CLK->CLKSEL0 = (CLK->CLKSEL0 & (~CLK_CLKSEL0_HCLKSEL_Msk)) | CLK_CLKSEL0_HCLKSEL_PLL;
+    CLK->CLKDIV0 = (CLK->CLKDIV0 & (~CLK_CLKDIV0_HCLKDIV_Msk)) | (0 << CLK_CLKDIV0_HCLKDIV_Pos);
+
+    /* Enable Crypto Accelerator */
+    CLK->AHBCLK |= CLK_AHBCLK_CRPTCKEN_Msk;
+
+    /* Enable SDH for secondary slot */
+    CLK->AHBCLK |= CLK_AHBCLK_SDH0CKEN_Msk;
+
+    /* Set multi-function pin for SDH */
+    /* CD: PB12(9) */
+    SYS->GPB_MFPH = (SYS->GPB_MFPH & (~SYS_GPB_MFPH_PB12MFP_Msk)) | SD0_nCD_PB12;
+
+    /* CLK: PB1(3), PE6(3) */
+    SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB1MFP_Msk)) | SD0_CLK_PB1;
+    //SYS->GPE_MFPL = (SYS->GPE_MFPL & (~SYS_GPE_MFPL_PE6MFP_Msk)) | SD0_CLK_PE6;
+
+    /* CMD: PB0(3), PE7(3) */
+    SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB0MFP_Msk)) | SD0_CMD_PB0;
+    //SYS->GPE_MFPL = (SYS->GPE_MFPL & (~SYS_GPE_MFPL_PE7MFP_Msk)) | SD0_CMD_PE7;
+
+    /* D0: PB2(3), PE2(3) */
+    SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB2MFP_Msk)) | SD0_DAT0_PB2;
+    //SYS->GPE_MFPL = (SYS->GPE_MFPL & (~SYS_GPE_MFPL_PE2MFP_Msk)) | SD0_DAT0_PE2;
+
+    /* D1: PB3(3), PE3(3) */
+    SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB3MFP_Msk)) | SD0_DAT1_PB3;
+    //SYS->GPE_MFPL = (SYS->GPE_MFPL & (~SYS_GPE_MFPL_PE3MFP_Msk)) | SD0_DAT1_PE3;
+
+    /* D2: PB4(3), PE4(3) */
+    SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB4MFP_Msk)) | SD0_DAT2_PB4;
+    //SYS->GPE_MFPL = (SYS->GPE_MFPL & (~SYS_GPE_MFPL_PE4MFP_Msk)) | SD0_DAT2_PE4;
+
+    /* D3: PB5(3)-, PE5(3) */
+    SYS->GPB_MFPL = (SYS->GPB_MFPL & (~SYS_GPB_MFPL_PB5MFP_Msk)) | SD0_DAT3_PB5;
+    //SYS->GPE_MFPL = (SYS->GPE_MFPL & (~SYS_GPE_MFPL_PE5MFP_Msk)) | SD0_DAT3_PE5;
+
+    NVIC_DisableIRQ(SDH0_IRQn);
+
+
+    /* Enable IP clock */
+    CLK->APBCLK0 |= CLK_APBCLK0_UART0CKEN_Msk | CLK_APBCLK0_TMR0CKEN_Msk | CLK_APBCLK0_TMR2CKEN_Msk;
+
+    /* Select UART clock source */
+    CLK->CLKSEL2 = (CLK->CLKSEL2 & (~CLK_CLKSEL2_UART0SEL_Msk)) | CLK_CLKSEL2_UART0SEL_HIRC;
+
+    /* Timer clock source */
+    CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_TMR0SEL_Msk)) | CLK_CLKSEL1_TMR0SEL_HIRC;
+    CLK->CLKSEL1 = (CLK->CLKSEL1 & (~CLK_CLKSEL1_TMR2SEL_Msk)) | CLK_CLKSEL1_TMR2SEL_HIRC;
+
+    /* Set multi-function pins for UART0 RXD and TXD */
+    SYS->GPA_MFPL = (SYS->GPA_MFPL & (~(UART0_RXD_PA6_Msk | UART0_TXD_PA7_Msk))) | UART0_RXD_PA6 | UART0_TXD_PA7;
+
+    /* Set UART 0 to Non-secure */
+    SCU_SET_PNSSET(UART0_Attr);
+
+    /* Set SAU */
+    SAU->RNR = 3;
+    SAU->RBAR = 0x50000000;
+    SAU->RLAR = (0x5FFFFFFF & SAU_RLAR_LADDR_Msk) | SAU_RLAR_ENABLE_Msk;
+
+#ifndef NU_DISABLE_TAMPER
+    CLK->APBCLK0 |= CLK_APBCLK0_TAMPERCKEN_Msk;
+
+    /* Reset tamper coreblock */
+    TAMPER_CORE_RESET();
+    TAMPER_CORE_RELEASE();
+
+    /* Enable voltage glitch detection clock source and select sampling rate */
+    TAMPER_ENABLE_HIRC48M();
+    TAMPER_VG_SAMPLE_SEL(TAMPER_VG_192M_SAMPLE);
+
+    /* Initialize a reference trim value according to the power level of the system */
+    TAMPER_VG_TRIM_INIT();
+
+    /* Enable voltage glitch positive/negative detection interrupt */
+    TAMPER_EnableInt(TAMPER_INTEN_VGPIEN_Msk | TAMPER_INTEN_VGNIEN_Msk);
+
+    /* Clear voltage glitch positive/negative interrupt flag */
+    TAMPER_CLR_INT_STATUS(TAMPER_INTSTS_VGPEVIF_Msk | TAMPER_INTSTS_VGNEVIF_Msk);
+
+    /* Enable over voltage detector and wait until stable */
+    SYS->OVDCTL = SYS_OVDCTL_OVDEN_Msk;
+    while(!(SYS->OVDCTL & SYS_OVDCTL_OVDSTB_Msk));
+
+    /* Initialize the trim value of under-shoot and over-shoot detection level */
+    TAMPER_TLVD_TRIM_INIT(TAMPER_LBSTRIM_TLVDSEL_0_90V);
+    TAMPER_TOVD_TRIM_INIT(TAMPER_LBSTRIM_TOVDSEL_1_40V);
+
+    /* Clear different voltage interrupt flag */
+    TAMPER_CLR_INT_STATUS(TAMPER_INTSTS_OVPOUTIF_Msk | TAMPER_INTSTS_BODIF_Msk);
+
+    /* Enable different voltage detection interrupt */
+    TAMPER_EnableInt(TAMPER_INTEN_OVPIEN_Msk | TAMPER_INTEN_BODIEN_Msk);
+
+    /* Enable to trigger chip reset */
+    TAMPER_ENABLE_CHIPRST();
+#endif
+#endif
+
+ 
 
 
   SystemCoreClock = SYSTEM_CLOCK;
diff --git a/platform/ext/target/nuvoton/m2354/partition/flash_layout.h b/platform/ext/target/nuvoton/m2354/partition/flash_layout.h
index bc6eb46..399c489 100644
--- a/platform/ext/target/nuvoton/m2354/partition/flash_layout.h
+++ b/platform/ext/target/nuvoton/m2354/partition/flash_layout.h
@@ -94,7 +94,7 @@
 
 /* Protected Storage (PS) Service definitions */
 #define FLASH_PS_AREA_OFFSET            (0x10000)
-#define FLASH_PS_AREA_SIZE              (0x7000)
+#define FLASH_PS_AREA_SIZE              (0x8000)
 
 /* Internal Trusted Storage (ITS) Service definitions */
 #define FLASH_ITS_AREA_OFFSET           (FLASH_PS_AREA_OFFSET + \
diff --git a/platform/ext/target/nuvoton/m2354/target_cfg.c b/platform/ext/target/nuvoton/m2354/target_cfg.c
index e0504a7..9030477 100644
--- a/platform/ext/target/nuvoton/m2354/target_cfg.c
+++ b/platform/ext/target/nuvoton/m2354/target_cfg.c
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2018-2021 Arm Limited
- * Copyright (c) 2020 Nuvoton Technology Corp. All rights reserved.
+ * Copyright (c) 2017-2021 Arm Limited
+ * Copyright (c) 2021 Nuvoton Technology Corp. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,16 +15,17 @@
  * limitations under the License.
  */
 
-#include "partition_M2354.h"
 #include "cmsis.h"
 #include "target_cfg.h"
 #include "Driver_MPC.h"
-#include "platform_description.h"
-#include "device_definition.h"
 #include "region_defs.h"
 #include "tfm_plat_defs.h"
 #include "region.h"
-#include "tfm_secure_api.h"
+#include "NuMicro.h"
+
+#ifdef PSA_API_TEST_IPC
+#define PSA_FF_TEST_SECURE_UART2
+#endif
 
 #define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
 
@@ -48,11 +49,8 @@
         (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
         NS_PARTITION_SIZE - 1,
 
-    .veneer_base =
-        (uint32_t)&REGION_NAME(Image$$, ER_VENEER, $$Base),
-
-    .veneer_limit =
-        (uint32_t)&REGION_NAME(Image$$, VENEER_ALIGN, $$Limit),
+    .veneer_base = (uint32_t)&REGION_NAME(Image$$, ER_VENEER, $$Base),
+    .veneer_limit = (uint32_t)&REGION_NAME(Image$$, VENEER_ALIGN, $$Limit),
 
 #ifdef BL2
     .secondary_partition_base =
@@ -96,8 +94,8 @@
                         NIDEN_SEL_STATUS | DBGEN_SEL_STATUS)
 
 struct platform_data_t tfm_peripheral_std_uart = {
-        UART0_BASE + NS_OFFSET,
-        UART0_BASE + NS_OFFSET + 0xFFF,
+        UART0_BASE+NS_OFFSET,
+        UART0_BASE+NS_OFFSET+0xFFF,
         PPC_SP_DO_NOT_CONFIGURE,
         -1
 };
@@ -116,12 +114,66 @@
         -1
 };
 
+#ifdef PSA_API_TEST_IPC
+
+/* Below data structure are only used for PSA FF tests, and this pattern is
+ * definitely not to be followed for real life use cases, as it can break
+ * security.
+ */
+
+struct platform_data_t
+    tfm_peripheral_FF_TEST_UART_REGION = {
+        UART2_BASE_S,
+        UART2_BASE_S + 0xFFF,
+        PPC_SP_APB_PPC_EXP2,
+        CMSDK_UART2_APB_PPC_POS
+};
+
+struct platform_data_t
+    tfm_peripheral_FF_TEST_WATCHDOG_REGION = {
+        APB_WATCHDOG_BASE_S,
+        APB_WATCHDOG_BASE_S + 0xFFF,
+        PPC_SP_DO_NOT_CONFIGURE,
+        -1
+};
+
+#define FF_TEST_NVMEM_REGION_START            0x102FFC00
+#define FF_TEST_NVMEM_REGION_END              0x102FFFFF
+#define FF_TEST_SERVER_PARTITION_MMIO_START   0x3801FC00
+#define FF_TEST_SERVER_PARTITION_MMIO_END     0x3801FD00
+#define FF_TEST_DRIVER_PARTITION_MMIO_START   0x3801FE00
+#define FF_TEST_DRIVER_PARTITION_MMIO_END     0x3801FF00
+
+struct platform_data_t
+    tfm_peripheral_FF_TEST_NVMEM_REGION = {
+        FF_TEST_NVMEM_REGION_START,
+        FF_TEST_NVMEM_REGION_END,
+        PPC_SP_DO_NOT_CONFIGURE,
+        -1
+};
+
+struct platform_data_t
+    tfm_peripheral_FF_TEST_SERVER_PARTITION_MMIO = {
+        FF_TEST_SERVER_PARTITION_MMIO_START,
+        FF_TEST_SERVER_PARTITION_MMIO_END,
+        PPC_SP_DO_NOT_CONFIGURE,
+        -1
+};
+
+struct platform_data_t
+    tfm_peripheral_FF_TEST_DRIVER_PARTITION_MMIO = {
+        FF_TEST_DRIVER_PARTITION_MMIO_START,
+        FF_TEST_DRIVER_PARTITION_MMIO_END,
+        PPC_SP_DO_NOT_CONFIGURE,
+        -1
+};
+#endif
+
 enum tfm_plat_err_t enable_fault_handlers(void)
 {
-    /* Secure fault is not present in the Baseline implementation. */
-    /* Fault handler enable registers are not present in a Baseline
-     * implementation.
-     */
+    /* Explicitly set secure fault priority to the highest */
+    NVIC_SetPriority(SCU_IRQn, 0);
+
     return TFM_PLAT_ERR_SUCCESS;
 }
 
@@ -132,7 +184,7 @@
     /* Clear SCB_AIRCR_VECTKEY value */
     reg_value &= ~(uint32_t)(SCB_AIRCR_VECTKEY_Msk);
 
-    /* Enable system reset request for the secure world only */
+    /* Enable system reset request only to the secure world */
     reg_value |= (uint32_t)(SCB_AIRCR_WRITE_MASK | SCB_AIRCR_SYSRESETREQS_Msk);
 
     SCB->AIRCR = reg_value;
@@ -142,13 +194,37 @@
 
 enum tfm_plat_err_t init_debug(void)
 {
-    /* Set UART0 to NS for debug message */
-    SCU_SET_PNSSET(UART0_Attr);
+
+#if defined(DAUTH_NONE)
+
+    /* Disable secure and non-secure debug */
+    DPM->NSCTL = 0x5a000000 | DPM_NSCTL_DBGDIS_Msk;
+
+#elif defined(DAUTH_NS_ONLY)
+
+    /* Disable secure debug */
+    DPM->CTL = 0x5a000000 | DPM_CTL_DBGDIS_Msk;
+
+#elif defined(DAUTH_FULL)
+    /* By default, all debug is available */
+    /* If secure or all debug is disable, it may need erase whole chip to alow debug again. */
+#else
+
+#if !defined(DAUTH_CHIP_DEFAULT)
+#error "No debug authentication setting is provided."
+#endif
+
+    /* Set all the debug enable selector bits to 0 */
+
+
+    /* No need to set any enable bits because the value depends on
+     * input signals.
+     */
+#endif
 
     return TFM_PLAT_ERR_SUCCESS;
 }
 
-
 /*----------------- NVIC interrupt target state to NS configuration ----------*/
 enum tfm_plat_err_t nvic_interrupt_target_state_cfg(void)
 {
@@ -157,10 +233,11 @@
         NVIC->ITNS[i] = 0xFFFFFFFF;
     }
 
+    /* Make sure that SCU are targeted to S state */
+    NVIC_ClearTargetState(SCU_IRQn);
+
 #ifdef SECURE_UART1
     /* UART1 is a secure peripheral, so its IRQs have to target S state */
-    NVIC_ClearTargetState(UARTRX1_IRQn);
-    NVIC_ClearTargetState(UARTTX1_IRQn);
     NVIC_ClearTargetState(UART1_IRQn);
 #endif
 
@@ -170,6 +247,11 @@
 /*----------------- NVIC interrupt enabling for S peripherals ----------------*/
 enum tfm_plat_err_t nvic_interrupt_enable(void)
 {
+    NVIC_EnableIRQ(SCU_IRQn);
+
+#ifdef PSA_FF_TEST_SECURE_UART2
+# error "Not support PSA_FF_TEST_SECURE_UART2 in M2354"    
+#endif
 
     return TFM_PLAT_ERR_SUCCESS;
 }
@@ -197,14 +279,11 @@
         (uint32_t)&REGION_NAME(Image$$, ER_VENEER, $$Base),
         (uint32_t)&REGION_NAME(Image$$, VENEER_ALIGN, $$Limit),
         true,
-    },
-    {
-        (PERIPH_BASE + NS_OFFSET),
-        (PERIPH_BASE + NS_OFFSET + 0x10000000 - 1),
-        false,
     }
 };
 
+#define NR_SAU_INIT_STEP                 3
+
 void sau_and_idau_cfg(void)
 {
     uint32_t i;
@@ -212,19 +291,24 @@
     /* Enables SAU */
     TZ_SAU_Enable();
 
-    for(i = 0; i < ARRAY_SIZE(sau_cfg); i++) {
+    for (i = 0; i < ARRAY_SIZE(sau_cfg); i++) {
         SAU->RNR = i;
         SAU->RBAR = sau_cfg[i].RBAR & SAU_RBAR_BADDR_Msk;
         SAU->RLAR = (sau_cfg[i].RLAR & SAU_RLAR_LADDR_Msk) |
-            (sau_cfg[i].nsc ? SAU_RLAR_NSC_Msk : 0U) |
-            SAU_RLAR_ENABLE_Msk;
+                    (sau_cfg[i].nsc ? SAU_RLAR_NSC_Msk : 0U) |
+                    SAU_RLAR_ENABLE_Msk;
     }
 
 }
 
 /*------------------- Memory configuration functions -------------------------*/
+#ifdef BL2
+#define NR_MPC_INIT_STEP                 7
+#else
+#define NR_MPC_INIT_STEP                 6
+#endif
 
-enum tfm_plat_err_t mpc_init_cfg(void)
+int32_t mpc_init_cfg(void)
 {
     int32_t i;
 
@@ -333,22 +417,27 @@
     /* Set TIMER2 for Non-secure */
     SCU_SET_PNSSET(TMR23_Attr);
 
-    return TFM_PLAT_ERR_SUCCESS;
-}
+    /* Add barriers to assure the MPC configuration is done before continue
+     * the execution.
+     */
+    __DSB();
+    __ISB();
 
+    return ARM_DRIVER_OK;
+}
 
 /*---------------------- PPC configuration functions -------------------------*/
+#define NR_PPC_INIT_STEP                 4
 
-enum tfm_plat_err_t ppc_init_cfg(void)
-{
-    return TFM_PLAT_ERR_SUCCESS;
-}
-
-void ppc_configure_to_secure(enum ppc_bank_e bank, uint32_t pos)
+void ppc_init_cfg(void)
 {
 }
 
-void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint32_t pos)
+void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t pos)
+{
+}
+
+void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t pos)
 {
 }