Plaform: AN521: Introduce platform binding HAL

This API (tfm_hal_bind_boundaries) binds partition with platform by
a p_boundaries handle, to let platform records partition info and
apply specific settings. Check the API comment for details.

The patch also:

- Updates the boundary update HAL API.
- Updates the HAL design document.
- Removes the FIH on AN521.

Change-Id: I77bba50d16fc6bb034aff3f4a7a8dfefecf345ec
Signed-off-by: Ken Liu <Ken.Liu@arm.com>
Co-authored-by: Mingyang Sun <mingyang.sun@arm.com>
diff --git a/platform/ext/target/arm/mps2/an521/mmio_defs.h b/platform/ext/target/arm/mps2/an521/mmio_defs.h
new file mode 100644
index 0000000..7d3455e
--- /dev/null
+++ b/platform/ext/target/arm/mps2/an521/mmio_defs.h
@@ -0,0 +1,48 @@
+/*
+ * 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,
+};
+
+/*
+ * 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/arm/mps2/an521/native_drivers/mpu_armv8m_drv.c b/platform/ext/target/arm/mps2/an521/native_drivers/mpu_armv8m_drv.c
index 8231811..04b0f93 100644
--- a/platform/ext/target/arm/mps2/an521/native_drivers/mpu_armv8m_drv.c
+++ b/platform/ext/target/arm/mps2/an521/native_drivers/mpu_armv8m_drv.c
@@ -7,16 +7,15 @@
 
 #include "mpu_armv8m_drv.h"
 #include "cmsis_cpu.h"
-#include "fih.h"
 
 /*
  * FixMe:
  * This is a beta quality driver for MPU in v8M. To be finalized.
  */
 
-fih_int mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
-                          uint32_t privdef_en,
-                          uint32_t hfnmi_en)
+enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
+                                          uint32_t privdef_en,
+                                          uint32_t hfnmi_en)
 {
     /*No error checking*/
 
@@ -46,32 +45,33 @@
     __DSB();
     __ISB();
 
-    FIH_RET(fih_int_encode(MPU_ARMV8M_OK));
+    return MPU_ARMV8M_OK;
 }
 
-fih_int mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev)
+enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev)
 {
     MPU_Type *mpu = (MPU_Type *)dev->base;
 
     /* Reset all fields as enable does full setup */
     mpu->CTRL = 0;
 
-    FIH_RET(fih_int_encode(MPU_ARMV8M_OK));
+    return MPU_ARMV8M_OK;
 }
 
-
-fih_int mpu_armv8m_region_enable(struct mpu_armv8m_dev_t *dev,
-                                 struct mpu_armv8m_region_cfg_t *region_cfg)
+enum mpu_armv8m_error_t mpu_armv8m_region_enable(
+                                struct mpu_armv8m_dev_t *dev,
+                                struct mpu_armv8m_region_cfg_t *region_cfg)
 {
     MPU_Type *mpu = (MPU_Type *)dev->base;
 
+    enum mpu_armv8m_error_t ret_val = MPU_ARMV8M_OK;
     uint32_t ctrl_before;
     uint32_t base_cfg;
     uint32_t limit_cfg;
 
     /*FIXME : Add complete error checking*/
     if ((region_cfg->region_base & ~MPU_RBAR_BASE_Msk) != 0) {
-        FIH_RET(fih_int_encode(MPU_ARMV8M_ERROR));
+        return MPU_ARMV8M_ERROR;
     }
     /* region_limit doesn't need to be aligned but the scatter
      * file needs to be setup to ensure that partitions do not overlap.
@@ -107,12 +107,11 @@
     __DSB();
     __ISB();
 
-    FIH_RET(fih_int_encode(MPU_ARMV8M_OK));
+    return ret_val;
 }
 
-
-fih_int mpu_armv8m_region_disable(struct mpu_armv8m_dev_t *dev,
-                                  uint32_t region_nr)
+enum mpu_armv8m_error_t mpu_armv8m_region_disable(struct mpu_armv8m_dev_t *dev,
+                                                  uint32_t region_nr)
 {
 
     MPU_Type *mpu = (MPU_Type *)dev->base;
@@ -131,25 +130,18 @@
     /*Restore main MPU control*/
     mpu->CTRL = ctrl_before;
 
-    FIH_RET(fih_int_encode(MPU_ARMV8M_OK));
+    return MPU_ARMV8M_OK;
 }
 
-fih_int mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev)
+enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev)
 {
     MPU_Type *mpu = (MPU_Type *)dev->base;
     uint32_t i = (mpu->TYPE & MPU_TYPE_DREGION_Msk) >> MPU_TYPE_DREGION_Pos;
-    fih_int fih_rc = fih_int_encode(MPU_ARMV8M_ERROR);
 
     while (i > 0) {
-        FIH_CALL(mpu_armv8m_region_disable, fih_rc, dev, i - 1);
+        mpu_armv8m_region_disable(dev, i - 1);
         i--;
     }
 
-#ifdef TFM_FIH_PROFILE_ON
-    if (i > 0) {
-        FIH_PANIC;
-    }
-#endif
-
-    FIH_RET(fih_int_encode(MPU_ARMV8M_OK));
+    return MPU_ARMV8M_OK;
 }
diff --git a/platform/ext/target/arm/mps2/an521/native_drivers/mpu_armv8m_drv.h b/platform/ext/target/arm/mps2/an521/native_drivers/mpu_armv8m_drv.h
index 78da639..fe0a206 100644
--- a/platform/ext/target/arm/mps2/an521/native_drivers/mpu_armv8m_drv.h
+++ b/platform/ext/target/arm/mps2/an521/native_drivers/mpu_armv8m_drv.h
@@ -11,7 +11,6 @@
 #include <stdint.h>
 
 #include "cmsis.h"
-#include "fih.h"
 
 #define PRIVILEGED_DEFAULT_ENABLE 1
 #define HARDFAULT_NMI_ENABLE      1
@@ -81,9 +80,9 @@
  * \note This function doesn't check if dev is NULL.
  */
 
-fih_int mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
-                          uint32_t privdef_en,
-                          uint32_t hfnmi_en);
+enum mpu_armv8m_error_t mpu_armv8m_enable(struct mpu_armv8m_dev_t *dev,
+                                          uint32_t privdef_en,
+                                          uint32_t hfnmi_en);
 
 /**
  * \brief Disable MPU
@@ -94,7 +93,7 @@
  *
  * \note This function doesn't check if dev is NULL.
  */
-fih_int mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev);
+enum mpu_armv8m_error_t mpu_armv8m_disable(struct mpu_armv8m_dev_t *dev);
 
 /**
  * \brief Disable MPU and clean all regions
@@ -105,7 +104,7 @@
  *
  * \note This function doesn't check if dev is NULL.
  */
-fih_int mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev);
+enum mpu_armv8m_error_t mpu_armv8m_clean(struct mpu_armv8m_dev_t *dev);
 
 /**
  * \brief Enable MPU Region
@@ -117,8 +116,9 @@
  *
  * \note This function doesn't check if dev is NULL.
  */
-fih_int mpu_armv8m_region_enable(struct mpu_armv8m_dev_t *dev,
-                                 struct mpu_armv8m_region_cfg_t *region_cfg);
+enum mpu_armv8m_error_t mpu_armv8m_region_enable(
+                                struct mpu_armv8m_dev_t *dev,
+                                struct mpu_armv8m_region_cfg_t *region_cfg);
 
 /**
  * \brief Disable MPU Region
@@ -130,7 +130,7 @@
  *
  * \note This function doesn't check if dev is NULL.
  */
-fih_int mpu_armv8m_region_disable(struct mpu_armv8m_dev_t *dev,
-                                  uint32_t region_nr);
+enum mpu_armv8m_error_t mpu_armv8m_region_disable(struct mpu_armv8m_dev_t *dev,
+                                                  uint32_t region_nr);
 
 #endif /* __MPU_ARMV8M_DRV_H__ */
diff --git a/platform/ext/target/arm/mps2/an521/spm_hal.c b/platform/ext/target/arm/mps2/an521/spm_hal.c
index 33e20b5..045129b 100644
--- a/platform/ext/target/arm/mps2/an521/spm_hal.c
+++ b/platform/ext/target/arm/mps2/an521/spm_hal.c
@@ -5,15 +5,11 @@
  *
  */
 
-#include <stdio.h>
 #include "cmsis.h"
-#include "fih.h"
 #include "tfm_spm_hal.h"
 #include "tfm_platform_core_api.h"
 #include "target_cfg.h"
 #include "Driver_MPC.h"
-#include "mpu_armv8m_drv.h"
-#include "region_defs.h"
 #include "utilities.h"
 
 /* Import MPC driver */
@@ -22,105 +18,6 @@
 /* Get address of memory regions to configure MPU */
 extern const struct memory_region_limits memory_regions;
 
-struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
-
-#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
-#define PARTITION_REGION_PERIPH_START   5
-#define PARTITION_REGION_PERIPH_MAX_NUM 2
-
-uint32_t periph_num_count = 0;
-#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
-
-#ifdef TFM_FIH_PROFILE_ON
-fih_int tfm_spm_hal_configure_default_isolation(
-                  bool privileged,
-                  const struct platform_data_t *platform_data)
-#else /* TFM_FIH_PROFILE_ON */
-enum tfm_plat_err_t tfm_spm_hal_configure_default_isolation(
-                  bool privileged,
-                  const struct platform_data_t *platform_data)
-#endif /* TFM_FIH_PROFILE_ON */
-{
-    fih_int fih_rc = FIH_FAILURE;
-#if defined(CONFIG_TFM_ENABLE_MEMORY_PROTECT) && (TFM_LVL != 1)
-    struct mpu_armv8m_region_cfg_t region_cfg;
-#endif
-
-    if (!platform_data) {
-        FIH_RET(fih_int_encode(TFM_PLAT_ERR_INVALID_INPUT));
-    }
-
-#if defined(CONFIG_TFM_ENABLE_MEMORY_PROTECT) && (TFM_LVL != 1)
-    if (!privileged) {
-        region_cfg.region_nr = PARTITION_REGION_PERIPH_START + periph_num_count;
-        periph_num_count++;
-        if (periph_num_count >= PARTITION_REGION_PERIPH_MAX_NUM) {
-            FIH_RET(fih_int_encode(TFM_PLAT_ERR_MAX_VALUE));
-        }
-        region_cfg.region_base = platform_data->periph_start;
-        region_cfg.region_limit = platform_data->periph_limit;
-        region_cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX;
-        region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
-        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
-        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
-
-#ifdef TFM_FIH_PROFILE_ON
-        FIH_CALL(mpu_armv8m_disable, fih_rc, &dev_mpu_s);
-
-        FIH_CALL(mpu_armv8m_region_enable, fih_rc, &dev_mpu_s, &region_cfg);
-        if (fih_not_eq(fih_rc, fih_int_encode(MPU_ARMV8M_OK))) {
-            FIH_RET(fih_int_encode(TFM_PLAT_ERR_SYSTEM_ERR));
-        }
-
-        FIH_CALL(mpu_armv8m_enable, fih_rc, &dev_mpu_s,
-                 PRIVILEGED_DEFAULT_ENABLE, HARDFAULT_NMI_ENABLE);
-        if (fih_not_eq(fih_rc, fih_int_encode(MPU_ARMV8M_OK))) {
-            FIH_RET(fih_int_encode(TFM_PLAT_ERR_SYSTEM_ERR));
-        }
-#else /* TFM_FIH_PROFILE_ON */
-        mpu_armv8m_disable(&dev_mpu_s);
-
-        if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)
-            != MPU_ARMV8M_OK) {
-            return TFM_PLAT_ERR_SYSTEM_ERR;
-        }
-        mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
-                          HARDFAULT_NMI_ENABLE);
-#endif /* TFM_FIH_PROFILE_ON */
-    }
-#endif /* defined(CONFIG_TFM_ENABLE_MEMORY_PROTECT) && (TFM_LVL != 1) */
-
-    if (platform_data->periph_ppc_bank != PPC_SP_DO_NOT_CONFIGURE) {
-#ifdef TFM_FIH_PROFILE_ON
-        FIH_CALL(ppc_configure_to_secure, fih_rc,
-                 platform_data->periph_ppc_bank,
-                 platform_data->periph_ppc_loc);
-        if (privileged) {
-            FIH_CALL(ppc_clr_secure_unpriv, fih_rc,
-                     platform_data->periph_ppc_bank,
-                     platform_data->periph_ppc_loc);
-        } else {
-            FIH_CALL(ppc_en_secure_unpriv, fih_rc,
-                     platform_data->periph_ppc_bank,
-                     platform_data->periph_ppc_loc);
-        }
-#else /* TFM_FIH_PROFILE_ON */
-        ppc_configure_to_secure(platform_data->periph_ppc_bank,
-                                platform_data->periph_ppc_loc);
-        if (privileged) {
-            ppc_clr_secure_unpriv(platform_data->periph_ppc_bank,
-                                  platform_data->periph_ppc_loc);
-        } else {
-            ppc_en_secure_unpriv(platform_data->periph_ppc_bank,
-                                 platform_data->periph_ppc_loc);
-        }
-#endif /* TFM_FIH_PROFILE_ON */
-    }
-
-    fih_rc = fih_int_encode(TFM_PLAT_ERR_SUCCESS);
-    FIH_RET(fih_rc);
-}
-
 void MPC_Handler(void)
 {
     /* Clear MPC interrupt flag and pending MPC IRQ */
@@ -218,21 +115,10 @@
     return system_reset_cfg();
 }
 
-#ifdef TFM_FIH_PROFILE_ON
-fih_int tfm_spm_hal_init_debug(void)
-{
-    fih_int fih_rc = FIH_FAILURE;
-
-    FIH_CALL(init_debug, fih_rc);
-
-    FIH_RET(fih_rc);
-}
-#else /* TFM_FIH_PROFILE_ON */
 enum tfm_plat_err_t tfm_spm_hal_init_debug(void)
 {
     return init_debug();
 }
-#endif /* TFM_FIH_PROFILE_ON */
 
 enum tfm_plat_err_t tfm_spm_hal_nvic_interrupt_target_state_cfg(void)
 {
@@ -244,16 +130,69 @@
     return nvic_interrupt_enable();
 }
 
-#ifdef TFM_FIH_PROFILE_ON
-fih_int tfm_spm_hal_verify_isolation_hw(void)
-{
-    fih_int fih_rc = FIH_INT_INIT(TFM_PLAT_ERR_SYSTEM_ERR);
+#ifndef TFM_PSA_API
 
-    FIH_CALL(verify_isolation_hw, fih_rc);
-    if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
-        FIH_PANIC;
+#include "mpu_armv8m_drv.h"
+#include "region_defs.h"
+
+struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
+
+#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
+#define PARTITION_REGION_PERIPH_START   5
+#define PARTITION_REGION_PERIPH_MAX_NUM 2
+
+uint32_t periph_num_count = 0;
+#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
+
+enum tfm_plat_err_t tfm_spm_hal_configure_default_isolation(
+                  bool privileged,
+                  const struct platform_data_t *platform_data)
+{
+#if defined(CONFIG_TFM_ENABLE_MEMORY_PROTECT) && (TFM_LVL != 1)
+    struct mpu_armv8m_region_cfg_t region_cfg;
+#endif
+
+    if (!platform_data) {
+        return TFM_PLAT_ERR_INVALID_INPUT;
     }
 
-    FIH_RET(fih_int_encode(TFM_PLAT_ERR_SUCCESS));
+#if defined(CONFIG_TFM_ENABLE_MEMORY_PROTECT) && (TFM_LVL != 1)
+    if (!privileged) {
+        region_cfg.region_nr = PARTITION_REGION_PERIPH_START + periph_num_count;
+        periph_num_count++;
+        if (periph_num_count >= PARTITION_REGION_PERIPH_MAX_NUM) {
+            return TFM_PLAT_ERR_MAX_VALUE;
+        }
+        region_cfg.region_base = platform_data->periph_start;
+        region_cfg.region_limit = platform_data->periph_limit;
+        region_cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DEVICE_IDX;
+        region_cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
+        region_cfg.attr_sh = MPU_ARMV8M_SH_NONE;
+        region_cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
+
+        mpu_armv8m_disable(&dev_mpu_s);
+
+        if (mpu_armv8m_region_enable(&dev_mpu_s, &region_cfg)
+            != MPU_ARMV8M_OK) {
+            return TFM_PLAT_ERR_SYSTEM_ERR;
+        }
+        mpu_armv8m_enable(&dev_mpu_s, PRIVILEGED_DEFAULT_ENABLE,
+                          HARDFAULT_NMI_ENABLE);
+    }
+#endif /* defined(CONFIG_TFM_ENABLE_MEMORY_PROTECT) && (TFM_LVL != 1) */
+
+    if (platform_data->periph_ppc_bank != PPC_SP_DO_NOT_CONFIGURE) {
+        ppc_configure_to_secure(platform_data->periph_ppc_bank,
+                                platform_data->periph_ppc_loc);
+        if (privileged) {
+            ppc_clr_secure_unpriv(platform_data->periph_ppc_bank,
+                                  platform_data->periph_ppc_loc);
+        } else {
+            ppc_en_secure_unpriv(platform_data->periph_ppc_bank,
+                                 platform_data->periph_ppc_loc);
+        }
+    }
+
+    return TFM_PLAT_ERR_SUCCESS;
 }
-#endif /* TFM_FIH_PROFILE_ON */
+#endif
diff --git a/platform/ext/target/arm/mps2/an521/target_cfg.c b/platform/ext/target/arm/mps2/an521/target_cfg.c
index 8849ab3..c5432ca 100644
--- a/platform/ext/target/arm/mps2/an521/target_cfg.c
+++ b/platform/ext/target/arm/mps2/an521/target_cfg.c
@@ -21,10 +21,6 @@
 #include "region_defs.h"
 #include "tfm_plat_defs.h"
 #include "region.h"
-#include "fih.h"
-#ifdef TFM_FIH_PROFILE_ON
-#include "mpc_sie200_drv.h"
-#endif
 
 #ifdef PSA_API_TEST_IPC
 #define PSA_FF_TEST_SECURE_UART2
@@ -206,7 +202,7 @@
     return TFM_PLAT_ERR_SUCCESS;
 }
 
-fih_int init_debug(void)
+enum tfm_plat_err_t init_debug(void)
 {
     volatile struct sysctrl_t *sys_ctrl =
                                        (struct sysctrl_t *)CMSDK_SYSCTRL_BASE_S;
@@ -243,7 +239,7 @@
      */
 #endif
 
-    FIH_RET(fih_int_encode(TFM_PLAT_ERR_SUCCESS));
+    return TFM_PLAT_ERR_SUCCESS;
 }
 
 /*----------------- NVIC interrupt target state to NS configuration ----------*/
@@ -371,21 +367,13 @@
 
 #define NR_SAU_INIT_STEP                 3
 
-fih_int sau_and_idau_cfg(void)
+void sau_and_idau_cfg(void)
 {
     struct spctrl_def *spctrl = CMSDK_SPCTRL;
     uint32_t i;
 
-    FIH_CFI_STEP_INIT(NR_SAU_INIT_STEP);
-
     /* Enables SAU */
-#ifdef TFM_FIH_PROFILE_ON
     TZ_SAU_Enable();
-    TZ_SAU_Enable();
-#endif
-    TZ_SAU_Enable();
-
-    FIH_CFI_STEP_DECREMENT();
 
     for (i = 0; i < ARRAY_SIZE(sau_cfg); i++) {
         SAU->RNR = i;
@@ -395,20 +383,8 @@
                     SAU_RLAR_ENABLE_Msk;
     }
 
-    FIH_CFI_STEP_DECREMENT();
-
     /* Allows SAU to define the code region as a NSC */
     spctrl->nsccfg |= NSCCFG_CODENSC;
-
-    FIH_CFI_STEP_DECREMENT();
-
-    FIH_RET(fih_int_encode(TFM_PLAT_ERR_SUCCESS));
-
-    /*
-     * Dummy operation to avoid unused variable warning of the saved FIH counter
-     * variable.
-     */
-    FIH_CFI_STEP_ERR_RESET();
 }
 
 /*------------------- Memory configuration functions -------------------------*/
@@ -418,30 +394,21 @@
 #define NR_MPC_INIT_STEP                 6
 #endif
 
-fih_int mpc_init_cfg(void)
+int32_t mpc_init_cfg(void)
 {
-    int32_t ret = ARM_DRIVER_ERROR;
-    fih_int fih_rc = FIH_FAILURE;
-
-    FIH_CFI_STEP_INIT(NR_MPC_INIT_STEP);
+    int32_t ret = ARM_DRIVER_OK;
 
     ret = Driver_SRAM1_MPC.Initialize();
-    FIH_CFI_STEP_DECREMENT();
     if (ret != ARM_DRIVER_OK) {
-        fih_rc = fih_int_encode(ret);
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
+        return ret;
     }
 
     ret = Driver_SRAM1_MPC.ConfigRegion(
                                       memory_regions.non_secure_partition_base,
                                       memory_regions.non_secure_partition_limit,
                                       ARM_MPC_ATTR_NONSECURE);
-    FIH_CFI_STEP_DECREMENT();
     if (ret != ARM_DRIVER_OK) {
-        fih_rc = fih_int_encode(ret);
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
+        return ret;
     }
 
 #ifdef BL2
@@ -449,46 +416,31 @@
     ret = Driver_SRAM1_MPC.ConfigRegion(memory_regions.secondary_partition_base,
                                   memory_regions.secondary_partition_limit,
                                   ARM_MPC_ATTR_NONSECURE);
-    FIH_CFI_STEP_DECREMENT();
     if (ret != ARM_DRIVER_OK) {
-        fih_rc = fih_int_encode(ret);
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
+        return ret;
     }
 #endif /* BL2 */
 
     ret = Driver_SRAM2_MPC.Initialize();
-    FIH_CFI_STEP_DECREMENT();
     if (ret != ARM_DRIVER_OK) {
-        fih_rc = fih_int_encode(ret);
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
+        return ret;
     }
 
     ret = Driver_SRAM2_MPC.ConfigRegion(NS_DATA_START, NS_DATA_LIMIT,
                                         ARM_MPC_ATTR_NONSECURE);
-    FIH_CFI_STEP_DECREMENT();
     if (ret != ARM_DRIVER_OK) {
-        fih_rc = fih_int_encode(ret);
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
+        return ret;
     }
 
     /* Lock down the MPC configuration */
     ret = Driver_SRAM1_MPC.LockDown();
-    FIH_CFI_STEP_DECREMENT();
     if (ret != ARM_DRIVER_OK) {
-        fih_rc = fih_int_encode(ret);
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
+        return ret;
     }
 
     ret = Driver_SRAM2_MPC.LockDown();
-    FIH_CFI_STEP_DECREMENT();
     if (ret != ARM_DRIVER_OK) {
-        fih_rc = fih_int_encode(ret);
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
+        return ret;
     }
 
     /* Add barriers to assure the MPC configuration is done before continue
@@ -497,22 +449,17 @@
     __DSB();
     __ISB();
 
-    fih_rc = fih_int_encode(ARM_DRIVER_OK);
-
-Done:
-    FIH_RET(fih_rc);
+    return ARM_DRIVER_OK;
 }
 
 /*---------------------- PPC configuration functions -------------------------*/
 #define NR_PPC_INIT_STEP                 4
 
-fih_int ppc_init_cfg(void)
+void ppc_init_cfg(void)
 {
     struct spctrl_def* spctrl = CMSDK_SPCTRL;
     struct nspctrl_def* nspctrl = CMSDK_NSPCTRL;
 
-    FIH_CFI_STEP_INIT(NR_PPC_INIT_STEP);
-
     /* Grant non-secure access to peripherals in the PPC0
      * (timer0 and 1, dualtimer, watchdog, mhu 0 and 1)
      */
@@ -552,8 +499,6 @@
                             (1U << CMSDK_FPGA_AUDIO_PPC_POS) |
                             (1U << CMSDK_FPGA_IO_PPC_POS);
 
-    FIH_CFI_STEP_DECREMENT();
-
     /* Grant non-secure access to all peripherals on AHB EXP:
      * Make sure that all possible peripherals are enabled by default
      */
@@ -569,8 +514,6 @@
                             (1U << CMSDK_DMA2_PPC_POS) |
                             (1U << CMSDK_DMA3_PPC_POS);
 
-    FIH_CFI_STEP_DECREMENT();
-
     /* in NS, grant un-privileged for UART0 */
     nspctrl->apbnspppcexp1 |= (1U << CMSDK_UART0_APB_PPC_POS);
 
@@ -578,56 +521,36 @@
     nspctrl->apbnspppcexp2 |= (1U << CMSDK_FPGA_SCC_PPC_POS) |
                               (1U << CMSDK_FPGA_IO_PPC_POS);
 
-    FIH_CFI_STEP_DECREMENT();
-
     /* Configure the response to a security violation as a
      * bus error instead of RAZ/WI
      */
     spctrl->secrespcfg |= 1U;
-
-    FIH_CFI_STEP_DECREMENT();
-
-    FIH_RET(fih_int_encode(TFM_PLAT_ERR_SUCCESS));
-
-    /*
-     * Dummy operation to avoid unused variable warning of the saved FIH counter
-     * variable.
-     */
-    FIH_CFI_STEP_ERR_RESET();
 }
 
-fih_int ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t pos)
+void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t pos)
 {
     /* Setting NS flag for peripheral to enable NS access */
     struct spctrl_def* spctrl = CMSDK_SPCTRL;
     ((uint32_t*)&(spctrl->ahbnsppc0))[bank] |= (1U << pos);
-
-    FIH_RET(fih_int_encode(TFM_PLAT_ERR_SUCCESS));
 }
 
-fih_int ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t pos)
+void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t pos)
 {
     /* Clear NS flag for peripheral to prevent NS access */
     struct spctrl_def* spctrl = CMSDK_SPCTRL;
     ((uint32_t*)&(spctrl->ahbnsppc0))[bank] &= ~(1U << pos);
-
-    FIH_RET(fih_int_encode(TFM_PLAT_ERR_SUCCESS));
 }
 
-fih_int ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
+void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
 {
     struct spctrl_def* spctrl = CMSDK_SPCTRL;
     ((uint32_t*)&(spctrl->ahbspppc0))[bank] |= (1U << pos);
-
-    FIH_RET(fih_int_encode(TFM_PLAT_ERR_SUCCESS));
 }
 
-fih_int ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
+void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos)
 {
     struct spctrl_def* spctrl = CMSDK_SPCTRL;
     ((uint32_t*)&(spctrl->ahbspppc0))[bank] &= ~(1U << pos);
-
-    FIH_RET(fih_int_encode(TFM_PLAT_ERR_SUCCESS));
 }
 
 void ppc_clear_irq(void)
@@ -636,88 +559,3 @@
     /* Clear APB PPC EXP2 IRQ */
     spctrl->secppcintclr = CMSDK_APB_PPCEXP2_INT_POS_MASK;
 }
-
-#ifdef TFM_FIH_PROFILE_ON
-#ifdef BL2
-#define NR_VERIFY_STEP                 4
-#else
-#define NR_VERIFY_STEP                 3
-#endif
-
-fih_int verify_isolation_hw(void)
-{
-    enum tfm_plat_err_t ret = ARM_DRIVER_ERROR;
-    ARM_MPC_SEC_ATTR attr;
-    fih_int fih_rc = FIH_FAILURE;
-
-    FIH_CFI_STEP_INIT(NR_VERIFY_STEP);
-
-    /* Check SAU config */
-    if (!(SAU->CTRL & SAU_CTRL_ENABLE_Msk ||
-          SAU->CTRL | SAU_CTRL_ALLNS_Msk)) {
-        FIH_PANIC;
-    }
-
-    FIH_CFI_STEP_DECREMENT();
-
-    /* Check MPC config */
-    ret = Driver_SRAM1_MPC.GetRegionConfig(
-                                  memory_regions.non_secure_partition_base,
-                                  memory_regions.non_secure_partition_limit,
-                                  &attr);
-    FIH_CFI_STEP_DECREMENT();
-    if (ret != ARM_DRIVER_OK) {
-        fih_rc = FIH_FAILURE;
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
-    }
-
-    if (attr != ARM_MPC_ATTR_NONSECURE) {
-        fih_rc = FIH_FAILURE;
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
-    }
-
-#ifdef BL2
-    ret = Driver_SRAM1_MPC.GetRegionConfig(
-                                  memory_regions.secondary_partition_base,
-                                  memory_regions.secondary_partition_limit,
-                                  &attr);
-    FIH_CFI_STEP_DECREMENT();
-    if (ret != ARM_DRIVER_OK) {
-        fih_rc = FIH_FAILURE;
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
-    }
-
-    if (attr != ARM_MPC_ATTR_NONSECURE) {
-        fih_rc = FIH_FAILURE;
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
-    }
-#endif
-
-    ret = Driver_SRAM2_MPC.GetRegionConfig(NS_DATA_START, NS_DATA_LIMIT, &attr);
-    FIH_CFI_STEP_DECREMENT();
-    if (ret != ARM_DRIVER_OK) {
-        fih_rc = FIH_FAILURE;
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
-    }
-
-    if (attr != ARM_MPC_ATTR_NONSECURE) {
-        fih_rc = FIH_FAILURE;
-        FIH_CFI_STEP_ERR_RESET();
-        goto Done;
-    }
-
-    /* Todo: Check PPC config */
-
-    /* Todo: Check static MPU config */
-
-    fih_rc = FIH_SUCCESS;
-
-Done:
-    FIH_RET(fih_rc);
-}
-#endif /* TFM_FIH_PROFILE_ON */
diff --git a/platform/ext/target/arm/mps2/an521/target_cfg.h b/platform/ext/target/arm/mps2/an521/target_cfg.h
index 25cc28a..32f9721 100644
--- a/platform/ext/target/arm/mps2/an521/target_cfg.h
+++ b/platform/ext/target/arm/mps2/an521/target_cfg.h
@@ -21,7 +21,6 @@
 #include "tfm_peripherals_def.h"
 #include "tfm_plat_defs.h"
 #include "arm_uart_drv.h"
-#include "fih.h"
 
 #define TFM_DRIVER_STDIO    Driver_USART0
 #define NS_DRIVER_STDIO     Driver_USART0
@@ -82,32 +81,32 @@
  *
  * \return  Returns error code.
  */
-fih_int mpc_init_cfg(void);
+int32_t mpc_init_cfg(void);
 
 /**
  * \brief Configures the Peripheral Protection Controller.
  */
-fih_int ppc_init_cfg(void);
+void ppc_init_cfg(void);
 
 /**
  * \brief Restict access to peripheral to secure
  */
-fih_int ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t loc);
+void ppc_configure_to_secure(enum ppc_bank_e bank, uint16_t loc);
 
 /**
  * \brief Allow non-secure access to peripheral
  */
-fih_int ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t loc);
+void ppc_configure_to_non_secure(enum ppc_bank_e bank, uint16_t loc);
 
 /**
  * \brief Enable secure unprivileged access to peripheral
  */
-fih_int ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
+void ppc_en_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
 
 /**
  * \brief Clear secure unprivileged access to peripheral
  */
-fih_int ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
+void ppc_clr_secure_unpriv(enum ppc_bank_e bank, uint16_t pos);
 
 /**
  * \brief Clears PPC interrupt.
@@ -117,7 +116,7 @@
 /**
  * \brief Configures SAU and IDAU.
  */
-fih_int sau_and_idau_cfg(void);
+void sau_and_idau_cfg(void);
 
 /**
  * \brief Enables the fault handlers and sets priorities.
@@ -138,7 +137,7 @@
  *
  * \return Returns values as specified by the \ref fih_int
  */
-fih_int init_debug(void);
+enum tfm_plat_err_t init_debug(void);
 
 /**
  * \brief Configures all external interrupts to target the
@@ -158,18 +157,4 @@
  */
 enum tfm_plat_err_t nvic_interrupt_enable(void);
 
-#ifdef TFM_FIH_PROFILE_ON
-/**
- * \brief This function verifies the settings of HW used for memory isolation,
- *        to make sure that important settings was not skipped due to fault
- *        injection attacks.
- *
- * This function is called during TF-M core late startup, before passing
- * execution to non-secure code.
- *
- * \return Returns values as specified by the \ref fih_int.
- */
-fih_int verify_isolation_hw(void);
-#endif /* TFM_FIH_PROFILE_ON */
-
 #endif /* __TARGET_CFG_H__ */
diff --git a/platform/ext/target/arm/mps2/an521/tfm_hal_isolation.c b/platform/ext/target/arm/mps2/an521/tfm_hal_isolation.c
index 77ece5f..3027402 100644
--- a/platform/ext/target/arm/mps2/an521/tfm_hal_isolation.c
+++ b/platform/ext/target/arm/mps2/an521/tfm_hal_isolation.c
@@ -5,16 +5,28 @@
  *
  */
 
+#include "array.h"
 #include "cmsis.h"
 #include "Driver_Common.h"
-#include "fih.h"
+#include "mmio_defs.h"
 #include "mpu_armv8m_drv.h"
 #include "region.h"
 #include "target_cfg.h"
 #include "tfm_hal_isolation.h"
+#include "tfm_peripherals_def.h"
+#include "tfm_core_utils.h"
+#include "load/partition_defs.h"
+#include "load/asset_defs.h"
+#include "load/spm_load_api.h"
+
+/* It can be retrieved from the MPU_TYPE register. */
+#define MPU_REGION_NUM                  16
 
 #ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
+static uint32_t n_configured_regions = 0;
+struct mpu_armv8m_dev_t dev_mpu_s = {MPU_BASE};
 #if TFM_LVL == 3
+static uint32_t idx_boundary_handle = 0;
 REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Base);
 REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Limit);
 REGION_DECLARE(Image$$, PT_RO_START, $$Base);
@@ -22,9 +34,7 @@
 REGION_DECLARE(Image$$, PT_PRIV_RWZI_START, $$Base);
 REGION_DECLARE(Image$$, PT_PRIV_RWZI_END, $$Base);
 
-static uint32_t g_static_region_cnt;
-
-static struct mpu_armv8m_region_cfg_t isolation_regions[] = {
+const static struct mpu_armv8m_region_cfg_t isolation_regions[] = {
     {
         0, /* will be updated before using */
         (uint32_t)&REGION_NAME(Load$$LR$$, LR_VENEER, $$Base),
@@ -44,7 +54,7 @@
         MPU_ARMV8M_SH_NONE,
     },
     /* For isolation Level 3, set up static isolation for privileged data.
-     * Unprivileged data is dynamically set during Partition sheduling.
+     * Unprivileged data is dynamically set during Partition scheduling.
      */
     {
         0, /* will be updated before using */
@@ -57,16 +67,6 @@
     },
 };
 #else /* TFM_LVL == 3 */
-#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(arr[0]))
-
-#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 TFM_SP_META_PTR_ENABLE
-#define MPU_REGION_SP_META_PTR          7
-#endif /* TFM_SP_META_PTR_ENABLE */
 
 REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Base);
 REGION_DECLARE(Load$$LR$$, LR_VENEER, $$Limit);
@@ -86,7 +86,7 @@
 const struct mpu_armv8m_region_cfg_t region_cfg[] = {
     /* Veneer region */
     {
-        MPU_REGION_VENEERS,
+        0, /* will be updated before using */
         (uint32_t)&REGION_NAME(Load$$LR$$, LR_VENEER, $$Base),
         (uint32_t)&REGION_NAME(Load$$LR$$, LR_VENEER, $$Limit),
         MPU_ARMV8M_MAIR_ATTR_CODE_IDX,
@@ -96,7 +96,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,
@@ -106,7 +106,7 @@
     },
     /* NSPM PSP */
     {
-        MPU_REGION_NS_STACK,
+        0, /* will be updated before using */
         (uint32_t)&REGION_NAME(Image$$, ER_INITIAL_PSP, $$ZI$$Base),
         (uint32_t)&REGION_NAME(Image$$, ER_INITIAL_PSP, $$ZI$$Limit),
         MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
@@ -116,7 +116,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,
@@ -126,7 +126,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,
@@ -137,7 +137,7 @@
 #ifdef TFM_SP_META_PTR_ENABLE
     /* 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, $$RW$$Base),
         (uint32_t)&REGION_NAME(Image$$, TFM_SP_META_PTR, $$RW$$Limit),
         MPU_ARMV8M_MAIR_ATTR_DATA_IDX,
@@ -150,103 +150,6 @@
 #endif /* TFM_LVL == 3 */
 #endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
 
-#ifdef TFM_FIH_PROFILE_ON
-fih_int tfm_hal_set_up_static_boundaries(void)
-{
-    fih_int fih_rc = fih_int_encode(TFM_HAL_ERROR_GENERIC);
-
-    /* Set up isolation boundaries between SPE and NSPE */
-    FIH_CALL(sau_and_idau_cfg, fih_rc);
-    if (fih_not_eq(fih_rc, fih_int_encode(TFM_PLAT_ERR_SUCCESS))) {
-        FIH_PANIC;
-    }
-
-    FIH_CALL(mpc_init_cfg, fih_rc);
-    if (fih_not_eq(fih_rc, fih_int_encode(TFM_PLAT_ERR_SUCCESS))) {
-        FIH_PANIC;
-    }
-
-    FIH_CALL(ppc_init_cfg, fih_rc);
-    if (fih_not_eq(fih_rc, fih_int_encode(TFM_PLAT_ERR_SUCCESS))) {
-        FIH_PANIC;
-    }
-
-    /* Set up static isolation boundaries inside SPE */
-#ifdef CONFIG_TFM_ENABLE_MEMORY_PROTECT
-    int32_t i;
-    struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
-
-    FIH_CALL(mpu_armv8m_clean, fih_rc, &dev_mpu_s);
-    if (fih_not_eq(fih_rc, fih_int_encode(MPU_ARMV8M_OK))) {
-        FIH_PANIC;
-    }
-
-#if TFM_LVL == 3
-    uint32_t cnt;
-
-    /* Update MPU region numbers. The numbers start from 0 and are continuous */
-    cnt = sizeof(isolation_regions) / sizeof(isolation_regions[0]);
-    g_static_region_cnt = cnt;
-    for (i = 0; i < cnt; i++) {
-        /* Update region number */
-        isolation_regions[i].region_nr = i;
-        /* Enable regions */
-        FIH_CALL(mpu_armv8m_region_enable, fih_rc, &dev_mpu_s,
-                 &isolation_regions[i]);
-        if (fih_not_eq(fih_rc, fih_int_encode(MPU_ARMV8M_OK))) {
-            FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
-        }
-    }
-#else /* TFM_LVL == 3 */
-    for (i = 0; i < ARRAY_SIZE(region_cfg); i++) {
-
-        FIH_CALL(mpu_armv8m_region_enable, fih_rc, &dev_mpu_s,
-                 (struct mpu_armv8m_region_cfg_t *)&region_cfg[i]);
-        if (fih_not_eq(fih_rc, fih_int_encode(MPU_ARMV8M_OK))) {
-            FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
-        }
-    }
-#endif /* TFM_LVL == 3 */
-
-    /* Enable MPU */
-    FIH_CALL(mpu_armv8m_enable, fih_rc, &dev_mpu_s,
-             PRIVILEGED_DEFAULT_ENABLE, HARDFAULT_NMI_ENABLE);
-    if (fih_not_eq(fih_rc, fih_int_encode(MPU_ARMV8M_OK))) {
-        FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
-    }
-#endif /* CONFIG_TFM_ENABLE_MEMORY_PROTECT */
-
-    fih_rc = fih_int_encode(TFM_HAL_SUCCESS);
-    FIH_RET(fih_rc);
-}
-
-#if TFM_LVL == 3
-fih_int tfm_hal_mpu_update_partition_boundary(uintptr_t start,
-                                              uintptr_t end)
-{
-    fih_int fih_rc = fih_int_encode(TFM_HAL_ERROR_GENERIC);
-    struct mpu_armv8m_region_cfg_t cfg;
-    struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
-
-    /* Partition boundary regions is right after static regions */
-    cfg.region_nr = g_static_region_cnt;
-    cfg.region_base = start;
-    cfg.region_limit = end;
-    cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DATA_IDX;
-    cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
-    cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
-    cfg.attr_sh = MPU_ARMV8M_SH_NONE;
-
-    FIH_CALL(mpu_armv8m_region_enable, fih_rc, &dev_mpu_s, &cfg);
-    if (fih_not_eq(fih_rc, fih_int_encode(MPU_ARMV8M_OK))) {
-        FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
-    }
-
-    fih_rc = fih_int_encode(TFM_HAL_SUCCESS);
-    FIH_RET(fih_rc);
-}
-#endif /* TFM_LVL == 3 */
-#else /* TFM_FIH_PROFILE_ON */
 enum tfm_hal_status_t tfm_hal_set_up_static_boundaries(void)
 {
     /* Set up isolation boundaries between SPE and NSPE */
@@ -258,34 +161,44 @@
 
     /* 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
-    uint32_t cnt;
-
-    /* Update MPU region numbers. The numbers start from 0 and are continuous */
-    cnt = sizeof(isolation_regions) / sizeof(isolation_regions[0]);
-    g_static_region_cnt = cnt;
-    for (i = 0; i < cnt; i++) {
+    /*
+     * 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 */
-        isolation_regions[i].region_nr = i;
+        localcfg.region_nr = i;
         /* Enable regions */
-        if (mpu_armv8m_region_enable(&dev_mpu_s, &isolation_regions[i])
-                                                             != MPU_ARMV8M_OK) {
+        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 */
 
     /* Enable MPU */
@@ -299,27 +212,227 @@
     return TFM_HAL_SUCCESS;
 }
 
-#if TFM_LVL == 3
-enum tfm_hal_status_t tfm_hal_mpu_update_partition_boundary(uintptr_t start,
-                                                            uintptr_t end)
+/*
+ * 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)
 {
-    struct mpu_armv8m_region_cfg_t cfg;
-    enum mpu_armv8m_error_t mpu_err;
-    struct mpu_armv8m_dev_t dev_mpu_s = { MPU_BASE };
+    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
 
-    /* Partition boundary regions is right after static regions */
-    cfg.region_nr = g_static_region_cnt;
-    cfg.region_base = start;
-    cfg.region_limit = end;
-    cfg.region_attridx = MPU_ARMV8M_MAIR_ATTR_DATA_IDX;
-    cfg.attr_access = MPU_ARMV8M_AP_RW_PRIV_UNPRIV;
-    cfg.attr_exec = MPU_ARMV8M_XN_EXEC_NEVER;
-    cfg.attr_sh = MPU_ARMV8M_SH_NONE;
-    mpu_err = mpu_armv8m_region_enable(&dev_mpu_s, &cfg);
-    if (mpu_err != MPU_ARMV8M_OK) {
+    if (!p_ldinf || !pp_boundaries) {
         return TFM_HAL_ERROR_GENERIC;
     }
+
+#if TFM_LVL == 1
+    privileged = true;
+#else
+    privileged = !!(p_ldinf->flags & SPM_PART_FLAG_PSA_ROT);
+#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 *);
+
+        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;
 }
-#endif /* TFM_LVL == 3 */
-#endif /* TFM_FIH_PROFILE_ON */
+
+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;
+}
diff --git a/platform/include/tfm_hal_isolation.h b/platform/include/tfm_hal_isolation.h
index 18a8c50..120cdf5 100644
--- a/platform/include/tfm_hal_isolation.h
+++ b/platform/include/tfm_hal_isolation.h
@@ -10,8 +10,9 @@
 
 #include <stddef.h>
 #include <stdint.h>
-#include "fih.h"
 #include "tfm_hal_defs.h"
+#include "load/partition_defs.h"
+#include "load/asset_defs.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -26,6 +27,7 @@
 #define TFM_HAL_ACCESS_NS               (1UL << 5)
 
 #ifdef TFM_FIH_PROFILE_ON
+#include "fih.h"
 /**
  * \brief  Sets up the static isolation boundaries which are constant throughout
  *         the runtime of the system, including the SPE/NSPE and partition
@@ -36,24 +38,20 @@
  */
 fih_int tfm_hal_set_up_static_boundaries(void);
 
-#if TFM_LVL == 3
 /**
- * \brief  Updates the partition isolation boundary for isolation level 3.
- *         The boundary protects the private data of the running partition.
- *         The boundary is updated with SPM switching partition in level 3.
+ * \brief  Update the isolation boundaries.
  *
- * \param[in] start     start address of the partition boundary.
- * \param[in] end       end address of the partition boundary.
+ * \param[in]   p_ldinf         Partition load information.
+ * \param[in]   p_boundaries    Platform boundary handle for partition.
  *
- * \return TFM_HAL_SUCCESS - the isolation boundary has been set up.
- *         TFM_HAL_ERROR_GENERIC - failed to set up the isolation boundary.
+ * \return TFM_HAL_SUCCESS          The isolation boundaries update succeeded.
+ *         TFM_HAL_ERROR_GENERIC    Failed to update the isolation boundaries.
  *
  * \note   When FIH_ENABLE_DOUBLE_VARS is enabled, the return code will be
  *         wrapped and protected in \ref fih_int structure.
  */
-fih_int tfm_hal_mpu_update_partition_boundary(uintptr_t start,
-                                              uintptr_t end);
-#endif
+fih_int tfm_hal_update_boundaries(const struct partition_load_info_t *p_ldinf,
+                                  void *p_boundaries);
 #else /* TFM_FIH_PROFILE_ON */
 /**
  * \brief  Sets up the static isolation boundaries which are constant throughout
@@ -62,30 +60,21 @@
  *
  * \return TFM_HAL_SUCCESS - the isolation boundaries have been set up.
  *         TFM_HAL_ERROR_GENERIC - failed to set up the isolation boundaries.
- *
- * \note   When FIH_ENABLE_DOUBLE_VARS is enabled, the return code will be
- *         wrapped and protected in \ref fih_int structure.
  */
 enum tfm_hal_status_t tfm_hal_set_up_static_boundaries(void);
 
-#if TFM_LVL == 3
 /**
- * \brief  Updates the partition isolation boundary for isolation level 3.
- *         The boundary protects the private data of the running partition.
- *         The boundary is updated with SPM switching partition in level 3.
+ * \brief  Update the isolation boundaries.
  *
- * \param[in] start     start address of the partition boundary.
- * \param[in] end       end address of the partition boundary.
+ * \param[in]   p_ldinf         Partition load information.
+ * \param[in]   p_boundaries    Platform boundary handle for partition.
  *
- * \return TFM_HAL_SUCCESS - the isolation boundary has been set up.
- *         TFM_HAL_ERROR_GENERIC - failed to set up the isolation boundary.
- *
- * \note   When FIH_ENABLE_DOUBLE_VARS is enabled, the return code will be
- *         wrapped and protected in \ref fih_int structure.
+ * \return TFM_HAL_SUCCESS          The isolation boundaries update succeeded.
+ *         TFM_HAL_ERROR_GENERIC    Failed to update the isolation boundaries.
  */
-enum tfm_hal_status_t tfm_hal_mpu_update_partition_boundary(uintptr_t start,
-                                                            uintptr_t end);
-#endif
+enum tfm_hal_status_t tfm_hal_update_boundaries(
+                            const struct partition_load_info_t *p_ldinf,
+                            void *p_boundaries);
 #endif /* TFM_FIH_PROFILE_ON */
 
 /**
@@ -108,6 +97,28 @@
                                                 size_t size,
                                                 uint32_t attr);
 
+/**
+ * \brief  This API binds partition boundaries with the platform. The platform
+ *         maintains the platform-specific settings for SPM further
+ *         usage, such as update partition hardware boundaries or
+ *         check resource accessibility. The platform needs to manage
+ *         the settings with internal mechanism, and return a handle
+ *         to SPM. SPM delivers this handle back to platform when
+ *         necessary. And SPM checks this handle to decide if the
+ *         platform-specific settings need to be updated. Hence
+ *         multiple partitions can have the same handle if they have
+ *         the same platform-specific settings, depending on isolation level.
+ *
+ * \param[in]   p_ldinf           Partition load information.
+ * \param[in]   pp_boundaries     Pointer of the boundary handle
+ *
+ * \return TFM_HAL_SUCCESS          - A platform handle binding success.
+ *         TFM_HAL_ERROR_GENERIC    - Error occured while binding.
+ */
+enum tfm_hal_status_t tfm_hal_bind_boundaries(
+                                    const struct partition_load_info_t *p_ldinf,
+                                    void **pp_boundaries);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/platform/include/tfm_spm_hal.h b/platform/include/tfm_spm_hal.h
index 91e9807..3ea57aa 100644
--- a/platform/include/tfm_spm_hal.h
+++ b/platform/include/tfm_spm_hal.h
@@ -322,8 +322,7 @@
  *
  * \return True if the access is granted, false otherwise.
  */
-bool tfm_spm_hal_has_access_to_region(const void *p, size_t s,
-                                              int flags);
+bool tfm_spm_hal_has_access_to_region(const void *p, size_t s, int flags);
 #endif /* !defined(__SAUREGION_PRESENT) || (__SAUREGION_PRESENT == 0) */
 
 #endif /* __TFM_SPM_HAL_H__ */