Platform: Add MUSCA_B1_SECURE_ENCLAVE platform

Change-Id: Iffbfe782222332fa0b94fc26c2eb9832d487f63e
Signed-off-by: Gabor Abonyi <gabor.abonyi@arm.com>
Signed-off-by: Mark Horvath <mark.horvath@arm.com>
diff --git a/docs/getting_started/tfm_user_guide.rst b/docs/getting_started/tfm_user_guide.rst
index d834785..58746ef 100644
--- a/docs/getting_started/tfm_user_guide.rst
+++ b/docs/getting_started/tfm_user_guide.rst
@@ -427,6 +427,12 @@
 
     srec_cat bin/tfm_s.bin -Binary -offset 0xA000000 bin/tfm_ns.bin -Binary -offset 0xA080000 -o tfm.hex -Intel
 
+Example application or regression tests on Musca-B1 using the Secure Enclave
+============================================================================
+
+Follow the above procedures, but to create a unified hex please check the
+:doc:`Musca-B1 Secure Enclave readme </platform/ext/target/musca_b1_secure_enclave/readme>`.
+
 ********************************************************
 Execute TF-M example and regression tests on MPS3 boards
 ********************************************************
diff --git a/docs/introduction/readme.rst b/docs/introduction/readme.rst
index 914ea6d..e867ba3 100644
--- a/docs/introduction/readme.rst
+++ b/docs/introduction/readme.rst
@@ -160,6 +160,10 @@
         - `PSoc64.
           <https://www.cypress.com/documentation/product-brochures/cypress-psoc-64-secure-microcontrollers>`_
 
+    - Secure Enclave system:
+
+        - :doc:`Musca-B1 Secure Enclave. </platform/ext/target/musca_b1_secure_enclave/readme>`
+
 The document :doc:`Platform Deprecation and Removal </docs/contributing/platform_deprecation>`
 lists the deprecated platforms planned to be removed from upstream.
 
diff --git a/lib/ext/cryptocell-312-runtime/shared/hw/include/musca_b1_secure_enclave/dx_reg_base_host.h b/lib/ext/cryptocell-312-runtime/shared/hw/include/musca_b1_secure_enclave/dx_reg_base_host.h
new file mode 100644
index 0000000..2cf0368
--- /dev/null
+++ b/lib/ext/cryptocell-312-runtime/shared/hw/include/musca_b1_secure_enclave/dx_reg_base_host.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2001-2020, Arm Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __DX_REG_BASE_HOST_H__
+#define __DX_REG_BASE_HOST_H__
+
+/* Identify platform: ARM MUSCA_B1_SECURE_ENCLAVE */
+#define DX_PLAT_MUSCA_B1_SECURE_ENCLAVE 1
+
+#define DX_BASE_CC 0x50088000
+
+#define DX_BASE_HOST_RGF 0x0UL
+#define DX_BASE_CRY_KERNEL     0x0UL
+
+#define DX_BASE_RNG 0x0000UL
+#endif /*__DX_REG_BASE_HOST_H__*/
diff --git a/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Config/RTE_Device.h b/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Config/RTE_Device.h
new file mode 100644
index 0000000..6303551
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Config/RTE_Device.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2018-2020 Arm Limited. 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.
+ * 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.
+ */
+
+//-------- <<< Use Configuration Wizard in Context Menu >>> --------------------
+
+#ifndef __RTE_DEVICE_H__
+#define __RTE_DEVICE_H__
+
+// <e> QSPI FLASH (Flash Memory) [Driver_QSPI_FLASH0]
+// <i> Configuration settings for Driver_QSPI_FLASH0 in component ::Drivers:FLASH
+#define   RTE_QSPI_FLASH0                 1
+// </e> QSPI FLASH (Flash Memory) [Driver_QSPI_FLASH0]
+
+// <e> EFLASH (Flash Memory) [Driver_EFLASH0]
+// <i> Configuration settings for Driver_EFLASH0 in component ::Drivers:FLASH
+#define   RTE_EFLASH0                     1
+// </e> EFLASH (Flash Memory) [Driver_EFLASH0]
+
+// <e> EFLASH (Flash Memory) [Driver_EFLASH1]
+// <i> Configuration settings for Driver_EFLASH1 in component ::Drivers:FLASH
+#define   RTE_EFLASH1                     1
+// </e> EFLASH (Flash Memory) [Driver_EFLASH1]
+
+#endif  /* __RTE_DEVICE_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Config/cmsis_driver_config.h b/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Config/cmsis_driver_config.h
new file mode 100644
index 0000000..b633da3
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Config/cmsis_driver_config.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018-2020 Arm Limited. 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.
+ * 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.
+ */
+
+#ifndef __CMSIS_DRIVER_CONFIG_H__
+#define __CMSIS_DRIVER_CONFIG_H__
+
+#include "device_cfg.h"
+#include "device_definition.h"
+#include "platform_description.h"
+#include "RTE_Device.h"
+#include "target_cfg.h"
+
+#define FLASH0_DEV          MT25QL_DEV_S
+#define EFLASH0_DEV         GFC100_EFLASH0_DEV_S
+#define EFLASH1_DEV         GFC100_EFLASH1_DEV_S
+
+#endif  /* __CMSIS_DRIVER_CONFIG_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Driver_GFC100_EFlash.c b/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Driver_GFC100_EFlash.c
new file mode 100644
index 0000000..c929e7e
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Driver_GFC100_EFlash.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2018-2020 Arm Limited. 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.
+ * 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 "Driver_Flash.h"
+#include "gfc100_eflash_drv.h"
+#include "RTE_Device.h"
+#include "device_cfg.h"
+#include "device_definition.h"
+#include "system_core_init.h"
+#include "cmsis_driver_config.h"
+
+/**
+ * \file Driver_GFC100_EFlash.c
+ *
+ * \brief CMSIS Flash driver for GFC100 flash controller
+ */
+
+#ifndef ARG_UNUSED
+#define ARG_UNUSED(arg)  (void)arg
+#endif
+
+#ifndef ARG_NOT_USED
+#define ARG_NOT_USED    0U
+#endif
+
+/* Driver version */
+#define ARM_FLASH_DRV_VERSION   ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0)
+
+const ARM_DRIVER_VERSION GFC100_EFlash_Driver_Version = {
+    ARM_FLASH_API_VERSION,  /* Defined in the CMSIS Flash Driver header file */
+    ARM_FLASH_DRV_VERSION
+};
+
+/**
+ * Event ready values for ARM_FLASH_CAPABILITIES::event_ready
+ * \ref ARM_FLASH_CAPABILITIES
+ */
+enum {
+    EVENT_READY_NOT_AVAILABLE = 0u,
+    EVENT_READY_AVAILABLE
+};
+
+/**
+ * Data width values for ARM_FLASH_CAPABILITIES::data_width
+ * \ref ARM_FLASH_CAPABILITIES
+ */
+ enum {
+    DATA_WIDTH_8BIT   = 0u,
+    DATA_WIDTH_16BIT,
+    DATA_WIDTH_32BIT
+};
+
+/**
+ * Erase chip values for ARM_FLASH_CAPABILITIES::erase_chip
+ * \ref ARM_FLASH_CAPABILITIES
+ */
+enum {
+    CHIP_ERASE_NOT_SUPPORTED = 0u,
+    CHIP_ERASE_SUPPORTED
+};
+
+/** Driver Capabilities */
+static const ARM_FLASH_CAPABILITIES DriverCapabilities = {
+    .event_ready = EVENT_READY_NOT_AVAILABLE,
+    .data_width  = DATA_WIDTH_32BIT,
+    .erase_chip  = CHIP_ERASE_SUPPORTED
+};
+
+/**
+ * \brief Flash busy values flash status  \ref ARM_FLASH_STATUS
+ */
+enum {
+    DRIVER_STATUS_IDLE = 0u,
+    DRIVER_STATUS_BUSY
+};
+
+/**
+ * \brief Flash error values flash status  \ref ARM_FLASH_STATUS
+ */
+enum {
+    DRIVER_STATUS_NO_ERROR = 0u,
+    DRIVER_STATUS_ERROR
+};
+
+/**
+ * \brief Arm Flash device structure.
+ */
+typedef struct _FLASHx_Resources {
+    struct gfc100_eflash_dev_t* dev;  /*!< FLASH memory device structure */
+    ARM_FLASH_INFO *data;             /*!< FLASH memory device data */
+    ARM_FLASH_STATUS status;
+} ARM_FLASHx_Resources;
+
+static ARM_DRIVER_VERSION ARM_Flash_GetVersion(void)
+{
+    return GFC100_EFlash_Driver_Version;
+}
+
+static ARM_FLASH_CAPABILITIES ARM_Flash_GetCapabilities(void)
+{
+    return DriverCapabilities;
+}
+
+static int32_t ARM_Flashx_Initialize(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+                                     ARM_Flash_SignalEvent_t cb_event)
+{
+    ARG_UNUSED(cb_event);
+
+    uint32_t page_size = gfc100_get_eflash_page_size(ARM_FLASHx_DEV->dev);
+    uint32_t flash_size = gfc100_get_eflash_size(ARM_FLASHx_DEV->dev);
+
+    /* Validate hardcoded parameters of the flash */
+    if ((ARM_FLASHx_DEV->data->page_size != page_size) ||
+        (ARM_FLASHx_DEV->data->sector_size != page_size) ||
+        (ARM_FLASHx_DEV->data->sector_count != (flash_size / page_size))) {
+        return ARM_DRIVER_ERROR_PARAMETER;
+    }
+
+    gfc100_eflash_init(ARM_FLASHx_DEV->dev, SystemCoreClock);
+
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_Uninitialize(ARM_FLASHx_Resources *ARM_FLASHx_DEV)
+{
+    ARG_UNUSED(ARM_FLASHx_DEV);
+
+    /* Nothing to do */
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_PowerControl(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+                                       ARM_POWER_STATE state)
+{
+    ARG_UNUSED(ARM_FLASHx_DEV);
+
+    switch(state) {
+    case ARM_POWER_FULL:
+        /* Nothing to do */
+        return ARM_DRIVER_OK;
+    case ARM_POWER_OFF:
+    case ARM_POWER_LOW:
+        return ARM_DRIVER_ERROR_UNSUPPORTED;
+    default:
+        return ARM_DRIVER_ERROR_PARAMETER;
+    }
+}
+
+static int32_t ARM_Flashx_ReadData(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+                                   uint32_t addr, void *data, uint32_t cnt)
+{
+    enum gfc100_error_t err = GFC100_ERROR_NONE;
+    uint32_t flash_size = gfc100_get_eflash_size(ARM_FLASHx_DEV->dev);
+
+    ARM_FLASHx_DEV->status.error = DRIVER_STATUS_NO_ERROR;
+
+    /* Check if range is valid */
+    if ((addr + cnt) > flash_size) {
+        ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+        return ARM_DRIVER_ERROR_PARAMETER;
+    }
+
+    ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_BUSY;
+
+    err = gfc100_eflash_read(ARM_FLASHx_DEV->dev, addr, data, &cnt);
+
+    ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_IDLE;
+
+    if(err != GFC100_ERROR_NONE) {
+        ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+        return ARM_DRIVER_ERROR;
+    }
+
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_ProgramData(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+                                      uint32_t addr, const void *data,
+                                      uint32_t cnt)
+{
+    enum gfc100_error_t err = GFC100_ERROR_NONE;
+
+    ARM_FLASHx_DEV->status.error = DRIVER_STATUS_NO_ERROR;
+    ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_BUSY;
+
+    /* Note: There is a significantly faster way to write to the flash using
+     * gfc100_eflash_row_write. It has the disadvantage that all IRQs have
+     * to be disabled, because the implementation is sensitive to timing.
+     * For applications where timing can be guaranteed this can be replaced
+     * with gfc100_eflash_row_write. For generic use, simple write is used here.
+     */
+    err = gfc100_eflash_write(ARM_FLASHx_DEV->dev, addr, data, &cnt);
+
+    ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_IDLE;
+
+    if(err != GFC100_ERROR_NONE) {
+        ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+        if ((err == GFC100_ERROR_OUT_OF_RANGE) ||
+            (err == GFC100_ERROR_UNALIGNED_PARAM)) {
+            /* The native driver checks aligment and range */
+            return ARM_DRIVER_ERROR_PARAMETER;
+        }
+        return ARM_DRIVER_ERROR;
+    }
+
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_EraseSector(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+                                      uint32_t addr)
+{
+    enum gfc100_error_t err = GFC100_ERROR_NONE;
+
+    ARM_FLASHx_DEV->status.error = DRIVER_STATUS_NO_ERROR;
+    ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_BUSY;
+
+    /* The erase function checks whether the address is within the valid flash
+     * address range, and the HW will align the address to page boundary if
+     * it is not aligned.
+     */
+    err = gfc100_eflash_erase(ARM_FLASHx_DEV->dev, addr, GFC100_ERASE_PAGE);
+
+    ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_IDLE;
+
+    if (err != GFC100_ERROR_NONE) {
+        ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+        if (err == GFC100_ERROR_OUT_OF_RANGE) {
+            return ARM_DRIVER_ERROR_PARAMETER;
+        }
+        return ARM_DRIVER_ERROR;
+    }
+
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_EraseChip(ARM_FLASHx_Resources *ARM_FLASHx_DEV)
+{
+    enum gfc100_error_t err = GFC100_ERROR_NONE;
+
+    ARM_FLASHx_DEV->status.error = DRIVER_STATUS_NO_ERROR;
+    ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_BUSY;
+
+    /* The erase function checks whether the address is aligned with
+     * the sector or subsector and checks the Flash memory boundaries.
+     */
+    err = gfc100_eflash_erase(ARM_FLASHx_DEV->dev, ARG_NOT_USED,
+                              GFC100_MASS_ERASE_MAIN_AREA);
+
+    ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_IDLE;
+
+    if(err != GFC100_ERROR_NONE) {
+        ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+        return ARM_DRIVER_ERROR;
+    }
+
+    return ARM_DRIVER_OK;
+}
+
+static ARM_FLASH_STATUS
+ARM_Flashx_GetStatus(ARM_FLASHx_Resources *ARM_FLASHx_DEV)
+{
+    return ARM_FLASHx_DEV->status;
+}
+
+static ARM_FLASH_INFO * ARM_Flashx_GetInfo(ARM_FLASHx_Resources *ARM_FLASHx_DEV)
+{
+    return ARM_FLASHx_DEV->data;
+}
+
+#if (RTE_EFLASH0)
+static ARM_FLASH_INFO ARM_FLASH0_DEV_DATA = {
+    .sector_info    = NULL,     /* Uniform sector layout */
+    .sector_count   = (0x200000u / 0x4000u), /* 2MB (flash size) / 16kB */
+    .sector_size    = 0x4000u,  /* 16kB - as there are no sectors the page size
+                                 *        size is used here
+                                 */
+    .page_size      = 0x4000u,  /* 16kB */
+    .program_unit   = 4u,       /* Minimum write size in bytes */
+    .erased_value   = 0xFF
+};
+
+static ARM_FLASHx_Resources ARM_FLASH0_DEV = {
+    .dev    = &EFLASH0_DEV,
+    .data   = &(ARM_FLASH0_DEV_DATA),
+    .status = {
+       .busy     = DRIVER_STATUS_IDLE,
+       .error    = DRIVER_STATUS_NO_ERROR,
+       .reserved = 0,
+     },
+};
+
+static ARM_DRIVER_VERSION ARM_Flash0_GetVersion(void)
+{
+    return ARM_Flash_GetVersion();
+}
+
+static ARM_FLASH_CAPABILITIES ARM_Flash0_GetCapabilities(void)
+{
+    return ARM_Flash_GetCapabilities();
+}
+
+static int32_t ARM_Flash0_Initialize(ARM_Flash_SignalEvent_t cb_event)
+{
+    return ARM_Flashx_Initialize(&ARM_FLASH0_DEV, cb_event);
+}
+
+static int32_t ARM_Flash0_Uninitialize(void)
+{
+    return ARM_Flashx_Uninitialize(&ARM_FLASH0_DEV);
+}
+
+static int32_t ARM_Flash0_PowerControl(ARM_POWER_STATE state)
+{
+    return ARM_Flashx_PowerControl(&ARM_FLASH0_DEV, state);
+}
+
+static int32_t ARM_Flash0_ReadData(uint32_t addr, void *data, uint32_t cnt)
+{
+    return ARM_Flashx_ReadData(&ARM_FLASH0_DEV, addr, data, cnt);
+}
+
+static int32_t ARM_Flash0_ProgramData(uint32_t addr, const void *data,
+                                      uint32_t cnt)
+{
+    return ARM_Flashx_ProgramData(&ARM_FLASH0_DEV, addr, data, cnt);
+}
+
+static int32_t ARM_Flash0_EraseSector(uint32_t addr)
+{
+    return ARM_Flashx_EraseSector(&ARM_FLASH0_DEV, addr);
+}
+
+static int32_t ARM_Flash0_EraseChip(void)
+{
+    return ARM_Flashx_EraseChip(&ARM_FLASH0_DEV);
+}
+
+static ARM_FLASH_STATUS ARM_Flash0_GetStatus(void)
+{
+    return ARM_Flashx_GetStatus(&ARM_FLASH0_DEV);
+}
+
+static ARM_FLASH_INFO * ARM_Flash0_GetInfo(void)
+{
+    return ARM_Flashx_GetInfo(&ARM_FLASH0_DEV);
+}
+
+ARM_DRIVER_FLASH Driver_EFLASH0 = {
+    ARM_Flash0_GetVersion,
+    ARM_Flash0_GetCapabilities,
+    ARM_Flash0_Initialize,
+    ARM_Flash0_Uninitialize,
+    ARM_Flash0_PowerControl,
+    ARM_Flash0_ReadData,
+    ARM_Flash0_ProgramData,
+    ARM_Flash0_EraseSector,
+    ARM_Flash0_EraseChip,
+    ARM_Flash0_GetStatus,
+    ARM_Flash0_GetInfo
+};
+#endif /* RTE_EFLASH0 */
+
+#if (RTE_EFLASH1)
+static ARM_FLASH_INFO ARM_FLASH1_DEV_DATA = {
+    .sector_info    = NULL,     /* Uniform sector layout */
+    .sector_count   = (0x200000u / 0x4000u), /* 2MB (flash size) / 16kB */
+    .sector_size    = 0x4000u,  /* 16kB - as there are no sectors the page size
+                                 *        size is used here
+                                 */
+    .page_size      = 0x4000u,  /* 16kB */
+    .program_unit   = 4u,       /* Minimum write size in bytes */
+    .erased_value   = 0xFF
+};
+
+static ARM_FLASHx_Resources ARM_FLASH1_DEV = {
+    .dev    = &EFLASH1_DEV,
+    .data   = &ARM_FLASH1_DEV_DATA,
+    .status = {
+       .busy     = DRIVER_STATUS_IDLE,
+       .error    = DRIVER_STATUS_NO_ERROR,
+       .reserved = 0,
+     },
+};
+
+static ARM_DRIVER_VERSION ARM_Flash1_GetVersion(void)
+{
+    return ARM_Flash_GetVersion();
+}
+
+static ARM_FLASH_CAPABILITIES ARM_Flash1_GetCapabilities(void)
+{
+    return ARM_Flash_GetCapabilities();
+}
+
+static int32_t ARM_Flash1_Initialize(ARM_Flash_SignalEvent_t cb_event)
+{
+    return ARM_Flashx_Initialize(&ARM_FLASH1_DEV, cb_event);
+}
+
+static int32_t ARM_Flash1_Uninitialize(void)
+{
+    return ARM_Flashx_Uninitialize(&ARM_FLASH1_DEV);
+}
+
+static int32_t ARM_Flash1_PowerControl(ARM_POWER_STATE state)
+{
+    return ARM_Flashx_PowerControl(&ARM_FLASH1_DEV, state);
+}
+
+static int32_t ARM_Flash1_ReadData(uint32_t addr, void *data, uint32_t cnt)
+{
+    return ARM_Flashx_ReadData(&ARM_FLASH1_DEV, addr, data, cnt);
+}
+
+static int32_t ARM_Flash1_ProgramData(uint32_t addr, const void *data,
+                                      uint32_t cnt)
+{
+    return ARM_Flashx_ProgramData(&ARM_FLASH1_DEV, addr, data, cnt);
+}
+
+static int32_t ARM_Flash1_EraseSector(uint32_t addr)
+{
+    return ARM_Flashx_EraseSector(&ARM_FLASH1_DEV, addr);
+}
+
+static int32_t ARM_Flash1_EraseChip(void)
+{
+    return ARM_Flashx_EraseChip(&ARM_FLASH1_DEV);
+}
+
+static ARM_FLASH_STATUS ARM_Flash1_GetStatus(void)
+{
+    return (ARM_Flashx_GetStatus(&ARM_FLASH1_DEV));
+}
+
+static ARM_FLASH_INFO * ARM_Flash1_GetInfo(void)
+{
+    return ARM_Flashx_GetInfo(&ARM_FLASH1_DEV);
+}
+
+ARM_DRIVER_FLASH Driver_EFLASH1 = {
+    ARM_Flash1_GetVersion,
+    ARM_Flash1_GetCapabilities,
+    ARM_Flash1_Initialize,
+    ARM_Flash1_Uninitialize,
+    ARM_Flash1_PowerControl,
+    ARM_Flash1_ReadData,
+    ARM_Flash1_ProgramData,
+    ARM_Flash1_EraseSector,
+    ARM_Flash1_EraseChip,
+    ARM_Flash1_GetStatus,
+    ARM_Flash1_GetInfo
+};
+#endif /* RTE_EFLASH1 */
diff --git a/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Driver_QSPI_Flash.c b/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Driver_QSPI_Flash.c
new file mode 100644
index 0000000..195cb80
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/CMSIS_Driver/Driver_QSPI_Flash.c
@@ -0,0 +1,328 @@
+/*
+ * Copyright (c) 2013-2020 Arm Limited. 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.
+ * 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 "Driver_Flash.h"
+
+#include <stdbool.h>
+#include "cmsis_driver_config.h"
+#include "RTE_Device.h"
+#include "flash_layout.h"
+
+
+#ifndef ARG_UNUSED
+#define ARG_UNUSED(arg)  ((void)arg)
+#endif
+
+/* Driver version */
+#define ARM_FLASH_DRV_VERSION   ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0)
+
+static const ARM_DRIVER_VERSION DriverVersion = {
+    ARM_FLASH_API_VERSION,  /* Defined in the CMSIS Flash Driver header file */
+    ARM_FLASH_DRV_VERSION
+};
+
+/**
+ * \brief Flash driver capability macro definitions \ref ARM_FLASH_CAPABILITIES
+ */
+/* Flash Ready event generation capability values */
+#define EVENT_READY_NOT_AVAILABLE   (0u)
+#define EVENT_READY_AVAILABLE       (1u)
+/* Data access size values */
+#define DATA_WIDTH_8BIT             (0u)
+#define DATA_WIDTH_16BIT            (1u)
+#define DATA_WIDTH_32BIT            (2u)
+/* Chip erase capability values */
+#define CHIP_ERASE_NOT_SUPPORTED    (0u)
+#define CHIP_ERASE_SUPPORTED        (1u)
+
+/* Driver Capabilities */
+static const ARM_FLASH_CAPABILITIES DriverCapabilities = {
+    EVENT_READY_NOT_AVAILABLE,
+    DATA_WIDTH_32BIT,
+    CHIP_ERASE_SUPPORTED
+};
+
+/**
+ * \brief Flash status macro definitions \ref ARM_FLASH_STATUS
+ */
+/* Busy status values of the Flash driver */
+#define DRIVER_STATUS_IDLE      (0u)
+#define DRIVER_STATUS_BUSY      (1u)
+/* Error status values of the Flash driver */
+#define DRIVER_STATUS_NO_ERROR  (0u)
+#define DRIVER_STATUS_ERROR     (1u)
+
+/**
+ * \brief Arm Flash device structure.
+ */
+struct arm_flash_dev_t {
+    struct mt25ql_dev_t* dev;   /*!< FLASH memory device structure */
+    ARM_FLASH_INFO *data;       /*!< FLASH memory device data */
+};
+
+/**
+ * \brief      Check if the Flash memory boundaries are not violated.
+ * \param[in]  flash_dev  Flash device structure \ref arm_flash_dev_t
+ * \param[in]  offset     Highest Flash memory address which would be accessed.
+ * \return     Returns true if Flash memory boundaries are not violated, false
+ *             otherwise.
+ */
+static bool is_range_valid(struct arm_flash_dev_t *flash_dev,
+                           uint32_t offset)
+{
+    uint32_t flash_limit = 0;
+
+    /* Calculating the highest address of the Flash memory address range */
+    flash_limit = QSPI_FLASH_TOTAL_SIZE - 1;
+
+    return (offset > flash_limit) ? (false) : (true) ;
+}
+
+/**
+ * \brief        Check if the parameter is aligned to program_unit.
+ * \param[in]    flash_dev  Flash device structure \ref arm_flash_dev_t
+ * \param[in]    param      Any number that can be checked against the
+ *                          program_unit, e.g. Flash memory address or
+ *                          data length in bytes.
+ * \return       Returns true if param is aligned to program_unit, false
+ *               otherwise.
+ */
+static bool is_write_aligned(struct arm_flash_dev_t *flash_dev,
+                             uint32_t param)
+{
+    return ((param % flash_dev->data->program_unit) != 0) ? (false) : (true);
+}
+
+#if (RTE_QSPI_FLASH0)
+static ARM_FLASH_INFO ARM_FLASH0_DEV_DATA = {
+    .sector_info    = NULL,     /* Uniform sector layout */
+    .sector_count   = QSPI_FLASH_TOTAL_SIZE / SUBSECTOR_4KB,
+    .sector_size    = SUBSECTOR_4KB,
+    .page_size      = FLASH_PAGE_SIZE,
+    .program_unit   = 1u,       /* Minimum write size in bytes */
+    .erased_value   = 0xFF
+};
+
+static struct arm_flash_dev_t ARM_FLASH0_DEV = {
+    .dev    = &FLASH0_DEV,
+    .data   = &(ARM_FLASH0_DEV_DATA)
+};
+
+/* Flash Status */
+static ARM_FLASH_STATUS ARM_FLASH0_STATUS = {0, 0, 0};
+
+static ARM_DRIVER_VERSION ARM_Flash_GetVersion(void)
+{
+    return DriverVersion;
+}
+
+static ARM_FLASH_CAPABILITIES ARM_Flash_GetCapabilities(void)
+{
+    return DriverCapabilities;
+}
+
+static int32_t ARM_Flash_Initialize(ARM_Flash_SignalEvent_t cb_event)
+{
+    enum mt25ql_error_t err = MT25QL_ERR_NONE;
+
+    ARG_UNUSED(cb_event);
+
+    qspi_ip6514e_enable(ARM_FLASH0_DEV.dev->controller);
+
+    /* Configure QSPI Flash controller to operate in single SPI mode and
+     * to use fast Flash commands */
+    err = mt25ql_config_mode(ARM_FLASH0_DEV.dev, MT25QL_FUNC_STATE_FAST);
+    if(err != MT25QL_ERR_NONE) {
+        return ARM_DRIVER_ERROR;
+    }
+
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flash_Uninitialize(void)
+{
+    enum mt25ql_error_t err = MT25QL_ERR_NONE;
+
+    /* Restores the QSPI Flash controller and MT25QL to reset state */
+    err = mt25ql_restore_reset_state(ARM_FLASH0_DEV.dev);
+    if(err != MT25QL_ERR_NONE) {
+        return ARM_DRIVER_ERROR;
+    }
+
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flash_PowerControl(ARM_POWER_STATE state)
+{
+    switch(state) {
+    case ARM_POWER_FULL:
+        /* Nothing to be done */
+        return ARM_DRIVER_OK;
+    case ARM_POWER_OFF:
+    case ARM_POWER_LOW:
+        return ARM_DRIVER_ERROR_UNSUPPORTED;
+    default:
+        return ARM_DRIVER_ERROR_PARAMETER;
+    }
+}
+
+static int32_t ARM_Flash_ReadData(uint32_t addr, void *data, uint32_t cnt)
+{
+    enum mt25ql_error_t err = MT25QL_ERR_NONE;
+    bool is_valid = true;
+
+    ARM_FLASH0_STATUS.error = DRIVER_STATUS_NO_ERROR;
+
+    /* Check Flash memory boundaries */
+    is_valid = is_range_valid(&ARM_FLASH0_DEV, addr + cnt);
+    if(is_valid != true) {
+        ARM_FLASH0_STATUS.error = DRIVER_STATUS_ERROR;
+        return ARM_DRIVER_ERROR_PARAMETER;
+    }
+
+    ARM_FLASH0_STATUS.busy = DRIVER_STATUS_BUSY;
+
+    err = mt25ql_command_read(ARM_FLASH0_DEV.dev, addr, data, cnt);
+
+    ARM_FLASH0_STATUS.busy = DRIVER_STATUS_IDLE;
+
+    if(err != MT25QL_ERR_NONE) {
+        ARM_FLASH0_STATUS.error = DRIVER_STATUS_ERROR;
+        return ARM_DRIVER_ERROR;
+    }
+
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flash_ProgramData(uint32_t addr,
+                                     const void *data, uint32_t cnt)
+{
+    enum mt25ql_error_t err = MT25QL_ERR_NONE;
+
+    ARM_FLASH0_STATUS.error = DRIVER_STATUS_NO_ERROR;
+
+    /* Check Flash memory boundaries and alignment with minimum write size
+     * (program_unit), data size also needs to be a multiple of program_unit.
+     */
+    if(!(is_range_valid(&ARM_FLASH0_DEV, addr + cnt) &&
+         is_write_aligned(&ARM_FLASH0_DEV, addr)     &&
+         is_write_aligned(&ARM_FLASH0_DEV, cnt)      )) {
+
+        ARM_FLASH0_STATUS.error = DRIVER_STATUS_ERROR;
+        return ARM_DRIVER_ERROR_PARAMETER;
+    }
+
+    ARM_FLASH0_STATUS.busy = DRIVER_STATUS_BUSY;
+
+    err = mt25ql_command_write(ARM_FLASH0_DEV.dev, addr, data, cnt);
+
+    ARM_FLASH0_STATUS.busy = DRIVER_STATUS_IDLE;
+
+    if(err != MT25QL_ERR_NONE) {
+        ARM_FLASH0_STATUS.error = DRIVER_STATUS_ERROR;
+        return ARM_DRIVER_ERROR;
+    }
+
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flash_EraseSector(uint32_t addr)
+{
+    enum mt25ql_error_t err = MT25QL_ERR_NONE;
+
+    ARM_FLASH0_STATUS.error = DRIVER_STATUS_NO_ERROR;
+    ARM_FLASH0_STATUS.busy = DRIVER_STATUS_BUSY;
+
+    /* The erase function checks whether the address is aligned with
+     * the sector or subsector and checks the Flash memory boundaries.
+     */
+    err = mt25ql_erase(ARM_FLASH0_DEV.dev,
+                       addr, ARM_FLASH0_DEV.data->sector_size);
+
+    ARM_FLASH0_STATUS.busy = DRIVER_STATUS_IDLE;
+
+    if(err != MT25QL_ERR_NONE) {
+        ARM_FLASH0_STATUS.error = DRIVER_STATUS_ERROR;
+
+        if((err == MT25QL_ERR_ADDR_NOT_ALIGNED) ||
+           (err == MT25QL_ERR_ADDR_TOO_BIG)     ||
+           (err == MT25QL_ERR_WRONG_ARGUMENT)    ) {
+            return ARM_DRIVER_ERROR_PARAMETER;
+        }
+        return ARM_DRIVER_ERROR;
+    }
+
+    return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flash_EraseChip(void)
+{
+    enum mt25ql_error_t err = MT25QL_ERR_NONE;
+
+    if(DriverCapabilities.erase_chip == 1) {
+
+        ARM_FLASH0_STATUS.error = DRIVER_STATUS_NO_ERROR;
+        ARM_FLASH0_STATUS.busy = DRIVER_STATUS_BUSY;
+
+        /* The erase function checks whether the address is aligned with
+         * the sector or subsector and checks the Flash memory boundaries.
+         */
+        err = mt25ql_erase(ARM_FLASH0_DEV.dev, 0, MT25QL_ERASE_ALL_FLASH);
+
+        ARM_FLASH0_STATUS.busy = DRIVER_STATUS_IDLE;
+
+        if(err != MT25QL_ERR_NONE) {
+            ARM_FLASH0_STATUS.error = DRIVER_STATUS_ERROR;
+
+            if((err == MT25QL_ERR_ADDR_NOT_ALIGNED) ||
+               (err == MT25QL_ERR_ADDR_TOO_BIG)     ||
+               (err == MT25QL_ERR_WRONG_ARGUMENT)    ) {
+                return ARM_DRIVER_ERROR_PARAMETER;
+            }
+            return ARM_DRIVER_ERROR;
+        }
+
+        return ARM_DRIVER_OK;
+
+    } else {
+        return ARM_DRIVER_ERROR_UNSUPPORTED;
+    }
+}
+
+static ARM_FLASH_STATUS ARM_Flash_GetStatus(void)
+{
+    return ARM_FLASH0_STATUS;
+}
+
+static ARM_FLASH_INFO * ARM_Flash_GetInfo(void)
+{
+    return ARM_FLASH0_DEV.data;
+}
+
+ARM_DRIVER_FLASH Driver_QSPI_FLASH0 = {
+    ARM_Flash_GetVersion,
+    ARM_Flash_GetCapabilities,
+    ARM_Flash_Initialize,
+    ARM_Flash_Uninitialize,
+    ARM_Flash_PowerControl,
+    ARM_Flash_ReadData,
+    ARM_Flash_ProgramData,
+    ARM_Flash_EraseSector,
+    ARM_Flash_EraseChip,
+    ARM_Flash_GetStatus,
+    ARM_Flash_GetInfo
+};
+#endif /* RTE_QSPI_FLASH0 */
diff --git a/platform/ext/target/musca_b1_secure_enclave/CMakeLists.txt b/platform/ext/target/musca_b1_secure_enclave/CMakeLists.txt
new file mode 100644
index 0000000..f8253d3
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/CMakeLists.txt
@@ -0,0 +1,126 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_policy(SET CMP0076 NEW)
+set(CMAKE_CURRENT_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+#========================= Platform region defs ===============================#
+
+target_include_directories(platform_region_defs
+    INTERFACE
+        partition
+)
+
+#========================= Platform common defs ===============================#
+
+# Specify the location of platform specific build dependencies.
+target_sources(tfm_s
+    PRIVATE
+    $<$<C_COMPILER_ID:ARMClang>:${CMAKE_CURRENT_SOURCE_DIR}/Device/Source/armclang/startup_musca_b1_secure_enclave_s.s>
+    $<$<C_COMPILER_ID:GNU>:${CMAKE_CURRENT_SOURCE_DIR}/Device/Source/gcc/startup_musca_b1_secure_enclave_s.S>
+    # This file contains an IRQ handler. Linking it from a different library to
+    # overwrite the default weak function would require intrusive cmake hacks.
+    mailbox/mailbox_ipc_intr.c
+)
+target_add_scatter_file(tfm_s
+    $<$<C_COMPILER_ID:ARMClang>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/armclang/tfm_common_s.sct>
+    $<$<C_COMPILER_ID:GNU>:${CMAKE_BINARY_DIR}/generated/platform/ext/common/gcc/tfm_common_s.ld>
+)
+
+if(BL2)
+    target_sources(bl2
+        PRIVATE
+            $<$<C_COMPILER_ID:ARMClang>:${CMAKE_CURRENT_SOURCE_DIR}/Device/Source/armclang/startup_musca_b1_secure_enclave_bl2.s>
+            $<$<C_COMPILER_ID:GNU>:${CMAKE_CURRENT_SOURCE_DIR}/Device/Source/gcc/startup_musca_b1_secure_enclave_bl2.S>
+    )
+    target_add_scatter_file(bl2
+            $<$<C_COMPILER_ID:ARMClang>:${CMAKE_CURRENT_SOURCE_DIR}/Device/Source/armclang/musca_b1_secure_enclave_bl2.sct>
+            $<$<C_COMPILER_ID:GNU>:${CMAKE_CURRENT_SOURCE_DIR}/Device/Source/gcc/musca_b1_secure_enclave_bl2.ld>
+    )
+endif()
+
+#========================= Platform Secure ====================================#
+
+target_include_directories(platform_s
+    PUBLIC
+        .
+        CMSIS_Driver
+        CMSIS_Driver/Config
+        Device/Config
+        Device/Include
+        Native_Driver
+        partition
+        services/include
+        Libraries
+        mailbox
+)
+
+target_sources(platform_s
+    PRIVATE
+        CMSIS_Driver/Driver_GFC100_EFlash.c
+        Native_Driver/musca_b1_eflash_drv.c
+        Native_Driver/gfc100_eflash_drv.c
+        CMSIS_Driver/Driver_QSPI_Flash.c
+        Native_Driver/qspi_ip6514e_drv.c
+        Libraries/mt25ql_flash_lib.c
+        Native_Driver/mhu_v2_x.c
+        Device/Source/device_definition.c
+        Device/Source/system_core_init.c
+        mailbox/platform_multicore.c
+        mailbox/platform_spe_mailbox.c
+        spm_hal.c
+        target_cfg.c
+        tfm_hal_isolation.c
+        uart_stdout.c
+        $<$<BOOL:TFM_PARTITION_PLATFORM>:${CMAKE_CURRENT_SOURCE_DIR}/services/src/tfm_platform_system.c>
+)
+
+target_link_libraries(platform_s
+    PUBLIC
+        tfm_spm
+)
+#========================= Platform Non-Secure ================================#
+
+# FIXME: platform_ns must have at least 1 source, even if it is not used
+target_sources(platform_ns
+    PRIVATE
+        Device/Source/system_core_init.c
+)
+
+target_include_directories(platform_ns
+    PUBLIC
+        Device/Include
+)
+
+#========================= Platform BL2 =======================================#
+
+if(BL2)
+    target_sources(platform_bl2
+        PRIVATE
+            boot_hal.c
+            Device/Source/system_core_init.c
+            Device/Source/device_definition.c
+            CMSIS_Driver/Driver_GFC100_EFlash.c
+            Native_Driver/gfc100_eflash_drv.c
+            Native_Driver/musca_b1_eflash_drv.c
+            uart_stdout.c
+    )
+
+    target_include_directories(platform_bl2
+        PUBLIC
+            partition
+            Device/Include
+        PRIVATE
+            .
+            CMSIS_Driver/Config
+            Device/Config
+            Native_Driver
+            Libraries
+            ${MCUBOOT_PATH}/boot/bootutil/include # for fault_injection_hardening.h only
+            ${CMAKE_CURRENT_BINARY_DIR}/../../../../bl2/ext/mcuboot # for mcuboot_con
+    )
+endif()
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Config/device_cfg.h b/platform/ext/target/musca_b1_secure_enclave/Device/Config/device_cfg.h
new file mode 100644
index 0000000..b093b19
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Config/device_cfg.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017-2020 Arm Limited. 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.
+ * 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.
+ */
+
+#ifndef __MUSCA_B1_SECURE_ENCLAVE_DEVICE_CFG_H__
+#define __MUSCA_B1_SECURE_ENCLAVE_DEVICE_CFG_H__
+
+/**
+ * \file device_cfg.h
+ * \brief Configuration file native driver re-targeting
+ *
+ * \details This file can be used to add native driver specific macro
+ *          definitions to select which peripherals are available in the build.
+ *
+ * This is a default device configuration file with all peripherals enabled.
+ */
+
+/* GFC-100 EFlash controller */
+#define GFC100_EFLASH0_S
+#define GFC100_EFLASH1_S
+
+/* Cadence QSPI Flash Controller */
+#define QSPI_IP6514E_S
+
+/* MT25QL Flash memory library */
+#define MT25QL_S
+
+/* MHU */
+#define MHU0_SENDER
+#define MHU0_RECEIVER
+
+#endif  /* __MUSCA_B1_SECURE_ENCLAVE_DEVICE_CFG_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Include/cmsis.h b/platform/ext/target/musca_b1_secure_enclave/Device/Include/cmsis.h
new file mode 100644
index 0000000..97e5643
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Include/cmsis.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2009-2020 Arm Limited. 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.
+ * 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.
+ */
+
+#ifndef __CMSIS_H__
+#define __CMSIS_H__
+
+/* Configuration of the ARM Cortex-M0+ Processor and Core Peripherals */
+#define __CM0PLUS_REV                   0x0001U /* CM0PLUS Core Revision */
+#define __NVIC_PRIO_BITS                2       /* Number of Bits used for Priority Levels */
+#define __Vendor_SysTickConfig          0       /* Set to 1 if different SysTick Config is used */
+#define __VTOR_PRESENT                  1       /* Set to 1 if CPU supports Vector Table Offset Register */
+#define __MPU_PRESENT                   1       /* MPU present */
+
+#include "cmsis_compiler.h"
+#include "platform_base_address.h"
+#include "system_core_init.h"
+#include "platform_irq.h"
+#include "core_cm0plus.h"
+
+#endif /*__CMSIS_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Include/device_definition.h b/platform/ext/target/musca_b1_secure_enclave/Device/Include/device_definition.h
new file mode 100644
index 0000000..2f1c02e
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Include/device_definition.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017-2020 Arm Limited. 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.
+ * 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 device_definition.h
+ * \brief The structure definitions in this file are exported based on the
+ * peripheral definitions from device_cfg.h.
+ * This file is meant to be used as a helper for baremetal
+ * applications and/or as an example of how to configure the generic
+ * driver structures.
+ */
+
+#ifndef __MUSCA_B1_SECURE_ENCLAVE_DEVICE_DEFINITION_H__
+#define __MUSCA_B1_SECURE_ENCLAVE_DEVICE_DEFINITION_H__
+
+#include "device_cfg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef GFC100_EFLASH0_S
+#include "gfc100_eflash_drv.h"
+extern struct gfc100_eflash_dev_t GFC100_EFLASH0_DEV_S;
+#endif
+#ifdef GFC100_EFLASH1_S
+#include "gfc100_eflash_drv.h"
+extern struct gfc100_eflash_dev_t GFC100_EFLASH1_DEV_S;
+#endif
+
+/* QSPI Flash Controller driver structures */
+#ifdef QSPI_IP6514E_S
+#include "qspi_ip6514e_drv.h"
+extern struct qspi_ip6514e_dev_t QSPI_DEV_S;
+#endif
+
+/* MT25QL Flash memory library structures */
+#if (defined(MT25QL_S) && defined(QSPI_IP6514E_S))
+#include "mt25ql_flash_lib.h"
+extern struct mt25ql_dev_t MT25QL_DEV_S;
+#endif
+
+/* MHU driver structures */
+#ifdef MHU0_SENDER
+#include "mhu_v2_x.h"
+extern struct mhu_v2_x_dev_t MHU0_SENDER_DEV;
+#endif
+
+#ifdef MHU0_RECEIVER
+#include "mhu_v2_x.h"
+extern struct mhu_v2_x_dev_t MHU0_RECEIVER_DEV;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __MUSCA_B1_SECURE_ENCLAVE_DEVICE_DEFINITION_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Include/platform_base_address.h b/platform/ext/target/musca_b1_secure_enclave/Device/Include/platform_base_address.h
new file mode 100644
index 0000000..a0ee419
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Include/platform_base_address.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2020 Arm Limited. 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.
+ * 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.
+ */
+
+#ifndef __MUSCA_B1_SECURE_ENCLAVE_BASE_ADDRESS_H__
+#define __MUSCA_B1_SECURE_ENCLAVE_BASE_ADDRESS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Peripheries from Secure Enclave subsystem */
+#define MHU0_SENDER_FRAME_BASE                    (0x50003000UL)
+#define MHU0_RECEIVER_FRAME_BASE                  (0x50004000UL)
+
+/* Peripheries remapped from SSE-200 subsystem with SYS remap
+ * SYS remap offset should be set to 0x5200_0000
+ * SYS remap mask   should be set to 0x00FF_FFFF */
+#define REMAPPED_MUSCA_B1_EFLASH0_REG_MAP_S_BASE  (0xA0400000UL)
+#define REMAPPED_MUSCA_B1_EFLASH1_REG_MAP_S_BASE  (0xA0500000UL)
+#define REMAPPED_MUSCA_B1_QSPI_REG_S_BASE         (0xA0800000UL)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __MUSCA_B1_SECURE_ENCLAVE_BASE_ADDRESS_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Include/platform_description.h b/platform/ext/target/musca_b1_secure_enclave/Device/Include/platform_description.h
new file mode 100644
index 0000000..6ea03ba
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Include/platform_description.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018-2020 Arm Limited. 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.
+ * 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.
+ */
+
+#ifndef __MUSCA_B1_SECURE_ENCLAVE_PLATFORM_DESCRIPTION_H__
+#define __MUSCA_B1_SECURE_ENCLAVE_PLATFORM_DESCRIPTION_H__
+
+#include "platform_base_address.h"
+#include "cmsis.h"
+
+#endif  /* __MUSCA_B1_SECURE_ENCLAVE_PLATFORM_DESCRIPTION_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Include/platform_irq.h b/platform/ext/target/musca_b1_secure_enclave/Device/Include/platform_irq.h
new file mode 100644
index 0000000..a5df3f7
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Include/platform_irq.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019-2020 Arm Limited. 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.
+ * 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.
+ */
+
+#ifndef __PLATFORM_IRQ_H__
+#define __PLATFORM_IRQ_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ========================================================================== */
+/* =============         Interrupt Number Definition         ================ */
+/* ========================================================================== */
+
+typedef enum IRQn
+{
+  Reset_IRQn                   = -15, /*    !< -15  Reset Vector, invoked on Power up and warm reset                           */
+  NonMaskableInt_IRQn          = -14, /*    !< -14  Non maskable Interrupt, cannot be stopped or preempted                     */
+  HardFault_IRQn               = -13, /*    !< -13  Hard Fault, all classes of Fault                                           */
+  SVCall_IRQn                  =  -5, /*    !< -5 System Service Call via SVC instruction                                      */
+  PendSV_IRQn                  =  -2, /*    !< -2 Pendable request for system service                                          */
+  SysTick_IRQn                 =  -1, /*    !< -1 System Tick Timer                                                            */
+
+  ExternalIRQ_IRQn             =   0,
+  CC312_IRQn                   =   1,
+  CC312_APB_C_IRQn             =   2,
+  Watchdog_IRQn                =   3,
+  /* reserved                  =   4, */
+  Timer0_IRQn                  =   5,
+  Timer1_IRQn                  =   6,
+  /* reserved                  =   7, */
+  /* reserved                  =   8, */
+  GPIO_IRQn                    =   9,
+  GPIO_0_IRQn                  =  10,
+  GPIO_1_IRQn                  =  11,
+  GPIO_2_IRQn                  =  12,
+  GPIO_3_IRQn                  =  13,
+  GPIO_4_IRQn                  =  14,
+  GPIO_5_IRQn                  =  15,
+  GPIO_6_IRQn                  =  16,
+  GPIO_7_IRQn                  =  17,
+  /* reserved                  =  18, */
+  /* reserved                  =  19, */
+  /* reserved                  =  20, */
+  MHU0_NR2R_IRQn               =  21,
+  MHU0_R2NR_IRQn               =  22,
+  MHU0_COMB_IRQn               =  23,
+  MHU0_MSG_0_IRQn              =  24,
+  MHU0_MSG_1_IRQn              =  25,
+  MHU1_NR2R_IRQn               =  26,
+  MHU1_R2NR_IRQn               =  27,
+  MHU1_COMB_IRQn               =  28,
+  MHU1_MSG_0_IRQn              =  29,
+  MHU1_MSG_1_IRQn              =  30,
+  /* reserved                  =  31, */
+} IRQn_Type;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __PLATFORM_IRQ_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Include/system_core_init.h b/platform/ext/target/musca_b1_secure_enclave/Device/Include/system_core_init.h
new file mode 100644
index 0000000..8f4d33c
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Include/system_core_init.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2009-2020 Arm Limited. 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.
+ * 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.
+ *
+ * This file is derivative of CMSIS V5.01 \Device\ARM\ARMCM0plus\Include\system_ARMCM0plus.h
+ * Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75
+ *
+ */
+
+#ifndef __MUSCA_B1_SECURE_ENCLAVE_SYSTEM_CORE_INIT_H__
+#define __MUSCA_B1_SECURE_ENCLAVE_SYSTEM_CORE_INIT_H__
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint32_t SystemCoreClock;     /*!< System Clock Frequency (Core Clock) */
+extern uint32_t PeripheralClock;     /*!< Peripheral Clock Frequency */
+
+/**
+  \brief Setup the microcontroller system.
+
+   Initialize the System and update the SystemCoreClock variable.
+   It should be called from Reset Handler within the first few steps.
+   The minimal feature set should be initialised for successful exit
+   from Reset Handler to main entry point.
+ */
+extern void SystemInit (void);
+
+
+/**
+  \brief  Update SystemCoreClock variable.
+
+   Updates the SystemCoreClock with current core Clock retrieved from cpu registers.
+ */
+extern void SystemCoreClockUpdate (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MUSCA_B1_SECURE_ENCLAVE_SYSTEM_CORE_INIT_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Source/armclang/musca_b1_secure_enclave_bl2.sct b/platform/ext/target/musca_b1_secure_enclave/Device/Source/armclang/musca_b1_secure_enclave_bl2.sct
new file mode 100644
index 0000000..430dd79
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Source/armclang/musca_b1_secure_enclave_bl2.sct
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2018-2020 Arm Limited. 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.
+ * 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 "region_defs.h"
+
+LR_CODE BL2_CODE_START {
+    ER_CODE BL2_CODE_START BL2_CODE_SIZE {
+        *.o (RESET +First)
+        * (+RO)
+    }
+
+    /* eFlash driver code that gets copied from Flash to SRAM */
+    ER_CODE_SRAM EFLASH_DRIVER_REGION_BASE EFLASH_DRIVER_REGION_SIZE {
+        Driver_GFC100_EFlash.o (+RO)
+        gfc100_eflash_drv.o (+RO)
+        musca_b1_eflash_drv.o (+RO)
+    }
+
+    /* Base address of bootloader data area */
+    BL2_DATA_START S_DATA_START {
+    }
+
+    TFM_SHARED_DATA BOOT_TFM_SHARED_DATA_BASE ALIGN 32 EMPTY BOOT_TFM_SHARED_DATA_SIZE {
+    }
+
+    ER_DATA +0 {
+        * (+ZI +RW)
+    }
+
+    /* MSP */
+    ARM_LIB_STACK +0 ALIGN 32 EMPTY BL2_MSP_STACK_SIZE {
+    }
+
+    ARM_LIB_HEAP +0 ALIGN 8 EMPTY BL2_HEAP_SIZE {
+    }
+
+    /* This empty, zero long execution region is here to mark the limit address
+     * of the last execution region that is allocated in SRAM.
+     */
+    SRAM_WATERMARK +0 EMPTY 0x0 {
+    }
+
+    /* Make sure that the sections allocated in the SRAM does not exceed the
+     * size of the SRAM available.
+     */
+    ScatterAssert(ImageLimit(SRAM_WATERMARK) <= BL2_DATA_START + BL2_DATA_SIZE)
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Source/armclang/startup_musca_b1_secure_enclave_bl2.s b/platform/ext/target/musca_b1_secure_enclave/Device/Source/armclang/startup_musca_b1_secure_enclave_bl2.s
new file mode 100644
index 0000000..dd92be5
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Source/armclang/startup_musca_b1_secure_enclave_bl2.s
@@ -0,0 +1,154 @@
+;/*
+; * Copyright (c) 2009-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.
+; * 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.
+; */
+;
+; This file is derivative of CMSIS V5.01 startup_ARMv8MML.s
+; Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75
+
+;/*
+;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
+;*/
+
+
+; <h> Stack Configuration
+;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+                IMPORT |Image$$ARM_LIB_STACK$$ZI$$Limit|
+
+; Vector Table Mapped to Address 0 at Reset
+
+                AREA    RESET, DATA, READONLY
+                EXPORT  __Vectors
+                EXPORT  __Vectors_End
+                EXPORT  __Vectors_Size
+
+__Vectors       ;Core Interrupts
+                DCD     |Image$$ARM_LIB_STACK$$ZI$$Limit|    ; Top of Stack
+                DCD      Reset_Handler                       ;     Reset Handler
+                DCD      NMI_Handler                         ; -14 NMI Handler
+                DCD      HardFault_Handler                   ; -13 Hard Fault Handler
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      SVC_Handler                         ;  -5 SVCall Handler
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      PendSV_Handler                      ;  -2 PendSV Handler
+                DCD      SysTick_Handler                     ;  -1 SysTick Handler
+
+                ;musca_b1_secure_enclave Interrupts
+                DCD      ExternalIRQ_Handler                 ;   0:
+                DCD      CC312_Handler                       ;   1:
+                DCD      CC312_APB_C_Handler                 ;   2:
+                DCD      Watchdog_Handler                    ;   3:
+                DCD      0                                   ;   4: Reserved
+                DCD      Timer0_Handler                      ;   5:
+                DCD      Timer1_Handler                      ;   6:
+                DCD      0                                   ;   7: Reserved
+                DCD      0                                   ;   8: Reserved
+                DCD      GPIO_Handler                        ;   9:
+                DCD      GPIO_0_Handler                      ;  10:
+                DCD      GPIO_1_Handler                      ;  11:
+                DCD      GPIO_2_Handler                      ;  12:
+                DCD      GPIO_3_Handler                      ;  13:
+                DCD      GPIO_4_Handler                      ;  14:
+                DCD      GPIO_5_Handler                      ;  15:
+                DCD      GPIO_6_Handler                      ;  16:
+                DCD      GPIO_7_Handler                      ;  17:
+                DCD      0                                   ;  18:
+                DCD      0                                   ;  19:
+                DCD      0                                   ;  20:
+                DCD      MHU0_NR2R_Handler                   ;  21:
+                DCD      MHU0_R2NR_Handler                   ;  22:
+                DCD      MHU0_COMB_Handler                   ;  23:
+                DCD      MHU0_MSG_0_Handler                  ;  24:
+                DCD      MHU0_MSG_1_Handler                  ;  25:
+                DCD      MHU1_NR2R_Handler                   ;  26:
+                DCD      MHU1_R2NR_Handler                   ;  27:
+                DCD      MHU1_COMB_Handler                   ;  28:
+                DCD      MHU1_MSG_0_Handler                  ;  29:
+                DCD      MHU1_MSG_1_Handler                  ;  30:
+                DCD      0                                   ;  31:
+
+__Vectors_End
+
+__Vectors_Size  EQU     __Vectors_End - __Vectors
+
+; Reset Handler
+                AREA    |.text|, CODE, READONLY
+Reset_Handler   PROC
+                EXPORT  Reset_Handler             [WEAK]
+                IMPORT  SystemInit
+                IMPORT  __main
+                LDR     R0, =SystemInit
+                BLX     R0
+                LDR     R0, =__main
+                BX      R0
+                ENDP
+End_Of_Main
+                B       .
+
+
+; Dummy Exception Handlers (infinite loops which can be modified)
+                MACRO
+                Default_Handler $handler_name
+$handler_name   PROC
+                EXPORT  $handler_name             [WEAK]
+                B       .
+                ENDP
+                MEND
+
+                Default_Handler NMI_Handler
+                Default_Handler HardFault_Handler
+                Default_Handler SVC_Handler
+                Default_Handler PendSV_Handler
+                Default_Handler SysTick_Handler
+
+                Default_Handler ExternalIRQ_Handler
+                Default_Handler CC312_Handler
+                Default_Handler CC312_APB_C_Handler
+                Default_Handler Watchdog_Handler
+
+                Default_Handler Timer0_Handler
+                Default_Handler Timer1_Handler
+
+                Default_Handler GPIO_Handler
+                Default_Handler GPIO_0_Handler
+                Default_Handler GPIO_1_Handler
+                Default_Handler GPIO_2_Handler
+                Default_Handler GPIO_3_Handler
+                Default_Handler GPIO_4_Handler
+                Default_Handler GPIO_5_Handler
+                Default_Handler GPIO_6_Handler
+                Default_Handler GPIO_7_Handler
+
+                Default_Handler MHU0_NR2R_Handler
+                Default_Handler MHU0_R2NR_Handler
+                Default_Handler MHU0_COMB_Handler
+                Default_Handler MHU0_MSG_0_Handler
+                Default_Handler MHU0_MSG_1_Handler
+                Default_Handler MHU1_NR2R_Handler
+                Default_Handler MHU1_R2NR_Handler
+                Default_Handler MHU1_COMB_Handler
+                Default_Handler MHU1_MSG_0_Handler
+                Default_Handler MHU1_MSG_1_Handler
+                ALIGN
+
+                END
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Source/armclang/startup_musca_b1_secure_enclave_s.s b/platform/ext/target/musca_b1_secure_enclave/Device/Source/armclang/startup_musca_b1_secure_enclave_s.s
new file mode 100644
index 0000000..95c505d
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Source/armclang/startup_musca_b1_secure_enclave_s.s
@@ -0,0 +1,162 @@
+;/*
+; * Copyright (c) 2009-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.
+; * 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.
+; */
+;
+; This file is derivative of CMSIS V5.01 startup_ARMv8MML.s
+; Git SHA: 8a1d9d6ee18b143ae5befefa14d89fb5b3f99c75
+
+;/*
+;//-------- <<< Use Configuration Wizard in Context Menu >>> ------------------
+;*/
+
+
+; <h> Stack Configuration
+;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
+; </h>
+
+                IMPORT |Image$$ARM_LIB_STACK_MSP$$ZI$$Limit|
+
+; Vector Table Mapped to Address 0 at Reset
+
+                PRESERVE8
+                AREA    RESET, DATA, READONLY
+                EXPORT  __Vectors
+                EXPORT  __Vectors_End
+                EXPORT  __Vectors_Size
+
+__Vectors       ;Core Interrupts
+                DCD     |Image$$ARM_LIB_STACK_MSP$$ZI$$Limit|    ; Top of Stack
+                DCD      Reset_Handler                       ;     Reset Handler
+                DCD      NMI_Handler                         ; -14 NMI Handler
+                DCD      HardFault_Handler                   ; -13 Hard Fault Handler
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      SVC_Handler                         ;  -5 SVCall Handler
+                DCD      0                                   ;     Reserved
+                DCD      0                                   ;     Reserved
+                DCD      PendSV_Handler                      ;  -2 PendSV Handler
+                DCD      SysTick_Handler                     ;  -1 SysTick Handler
+
+                ;musca_b1_secure_enclave Interrupts
+                DCD      ExternalIRQ_Handler                 ;   0:
+                DCD      CC312_Handler                       ;   1:
+                DCD      CC312_APB_C_Handler                 ;   2:
+                DCD      Watchdog_Handler                    ;   3:
+                DCD      0                                   ;   4: Reserved
+                DCD      TFM_TIMER0_IRQ_Handler              ;   5:
+                DCD      Timer1_Handler                      ;   6:
+                DCD      0                                   ;   7: Reserved
+                DCD      0                                   ;   8: Reserved
+                DCD      GPIO_Handler                        ;   9:
+                DCD      GPIO_0_Handler                      ;  10:
+                DCD      GPIO_1_Handler                      ;  11:
+                DCD      GPIO_2_Handler                      ;  12:
+                DCD      GPIO_3_Handler                      ;  13:
+                DCD      GPIO_4_Handler                      ;  14:
+                DCD      GPIO_5_Handler                      ;  15:
+                DCD      GPIO_6_Handler                      ;  16:
+                DCD      GPIO_7_Handler                      ;  17:
+                DCD      0                                   ;  18:
+                DCD      0                                   ;  19:
+                DCD      0                                   ;  20:
+                DCD      MHU0_NR2R_Handler                   ;  21:
+                DCD      MHU0_R2NR_Handler                   ;  22:
+                DCD      MHU0_COMB_Handler                   ;  23:
+                DCD      MHU0_MSG_0_Handler                  ;  24:
+                DCD      MHU0_MSG_1_Handler                  ;  25:
+                DCD      MHU1_NR2R_Handler                   ;  26:
+                DCD      MHU1_R2NR_Handler                   ;  27:
+                DCD      MHU1_COMB_Handler                   ;  28:
+                DCD      MHU1_MSG_0_Handler                  ;  29:
+                DCD      MHU1_MSG_1_Handler                  ;  30:
+                DCD      0                                   ;  31:
+
+__Vectors_End
+
+__Vectors_Size  EQU     __Vectors_End - __Vectors
+
+; Reset Handler
+                AREA    |.text|, CODE, READONLY
+Reset_Handler   PROC
+                EXPORT  Reset_Handler             [WEAK]
+                IMPORT  SystemInit
+                IMPORT  __main
+                CPSID   i              ; Disable IRQs
+                LDR     R0, =SystemInit
+                BLX     R0
+
+                MRS     R0, control    ; Get control value
+                MOVS    R1, #2
+                ORRS    R0, R0, R1     ; Select switch to PSP
+                MSR     control, R0
+
+                LDR     R0, =__main
+                BX      R0
+                ENDP
+End_Of_Main
+                B       .
+
+
+; Dummy Exception Handlers (infinite loops which can be modified)
+                MACRO
+                Default_Handler $handler_name
+$handler_name   PROC
+                EXPORT  $handler_name             [WEAK]
+                B       .
+                ENDP
+                MEND
+
+                Default_Handler NMI_Handler
+                Default_Handler HardFault_Handler
+                Default_Handler SVC_Handler
+                Default_Handler PendSV_Handler
+                Default_Handler SysTick_Handler
+
+                Default_Handler ExternalIRQ_Handler
+                Default_Handler CC312_Handler
+                Default_Handler CC312_APB_C_Handler
+                Default_Handler Watchdog_Handler
+
+                Default_Handler TFM_TIMER0_IRQ_Handler
+                Default_Handler Timer1_Handler
+
+                Default_Handler GPIO_Handler
+                Default_Handler GPIO_0_Handler
+                Default_Handler GPIO_1_Handler
+                Default_Handler GPIO_2_Handler
+                Default_Handler GPIO_3_Handler
+                Default_Handler GPIO_4_Handler
+                Default_Handler GPIO_5_Handler
+                Default_Handler GPIO_6_Handler
+                Default_Handler GPIO_7_Handler
+
+                Default_Handler MHU0_NR2R_Handler
+                Default_Handler MHU0_R2NR_Handler
+                Default_Handler MHU0_COMB_Handler
+                Default_Handler MHU0_MSG_0_Handler
+                Default_Handler MHU0_MSG_1_Handler
+                Default_Handler MHU1_NR2R_Handler
+                Default_Handler MHU1_R2NR_Handler
+                Default_Handler MHU1_COMB_Handler
+                Default_Handler MHU1_MSG_0_Handler
+                Default_Handler MHU1_MSG_1_Handler
+                ALIGN
+
+                END
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Source/device_definition.c b/platform/ext/target/musca_b1_secure_enclave/Device/Source/device_definition.c
new file mode 100644
index 0000000..192400c
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Source/device_definition.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017-2020 Arm Limited. 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.
+ * 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 device_definition.c
+ * \brief This file defines exports the structures based on the peripheral
+ * definitions from device_cfg.h.
+ * This retarget file is meant to be used as a helper for baremetal
+ * applications and/or as an example of how to configure the generic
+ * driver structures.
+ */
+
+#include "device_cfg.h"
+#include "device_definition.h"
+#include "platform_base_address.h"
+#include "tfm_plat_defs.h"
+
+/** GFC-100 eflash driver structures */
+#ifdef GFC100_EFLASH0_S
+static const struct gfc100_eflash_dev_cfg_t GFC100_EFLASH0_CFG_S = {
+    .base = REMAPPED_MUSCA_B1_EFLASH0_REG_MAP_S_BASE};
+static struct gfc100_eflash_dev_data_t GFC100_EFLASH0_DATA_S = {
+    .is_initialized = false,
+    .flash_size = 0};
+struct gfc100_eflash_dev_t GFC100_EFLASH0_DEV_S = {&(GFC100_EFLASH0_CFG_S),
+                                                   &(GFC100_EFLASH0_DATA_S)};
+#endif
+
+#ifdef GFC100_EFLASH1_S
+static const struct gfc100_eflash_dev_cfg_t GFC100_EFLASH1_CFG_S = {
+    .base = REMAPPED_MUSCA_B1_EFLASH1_REG_MAP_S_BASE};
+static struct gfc100_eflash_dev_data_t GFC100_EFLASH1_DATA_S = {
+    .is_initialized = false,
+    .flash_size = 0};
+struct gfc100_eflash_dev_t GFC100_EFLASH1_DEV_S = {&(GFC100_EFLASH1_CFG_S),
+                                                   &(GFC100_EFLASH1_DATA_S)};
+#endif
+
+/* QSPI IP6514E driver structures */
+#ifdef QSPI_IP6514E_S
+static const struct qspi_ip6514e_dev_cfg_t QSPI_DEV_CFG_S = {
+    .base = REMAPPED_MUSCA_B1_QSPI_REG_S_BASE,
+    .addr_mask = (1U << 23) - 1, /* 8MiB minus 1 byte */
+};
+struct qspi_ip6514e_dev_t QSPI_DEV_S = {
+    &QSPI_DEV_CFG_S
+};
+#endif
+
+/* MT25QL Flash memory library structures */
+#if (defined(MT25QL_S) && defined(QSPI_IP6514E_S))
+struct mt25ql_dev_t MT25QL_DEV_S = {
+    .controller = &QSPI_DEV_S,
+    /* Direct access not possible from Secure Enclave, so dummy address set */
+    .direct_access_start_addr = 0xFFFFFFFF,
+    .baud_rate_div = 4U,
+    .size = 0x00800000U, /* 8 MiB */
+    .config_state = { 0 },
+};
+#endif
+
+/* MHU */
+#ifdef MHU0_SENDER
+struct mhu_v2_x_dev_t MHU0_SENDER_DEV = {
+        .base = MHU0_SENDER_FRAME_BASE,
+        .frame = MHU_V2_X_SENDER_FRAME
+};
+#endif
+
+#ifdef MHU0_RECEIVER
+struct mhu_v2_x_dev_t MHU0_RECEIVER_DEV = {
+        .base = MHU0_RECEIVER_FRAME_BASE,
+        .frame = MHU_V2_X_RECEIVER_FRAME
+};
+#endif
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Source/gcc/musca_b1_secure_enclave_bl2.ld b/platform/ext/target/musca_b1_secure_enclave/Device/Source/gcc/musca_b1_secure_enclave_bl2.ld
new file mode 100644
index 0000000..d614fb1
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Source/gcc/musca_b1_secure_enclave_bl2.ld
@@ -0,0 +1,214 @@
+;/*
+; * Copyright (c) 2009-2020 Arm Limited. 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.
+; * 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.
+; *
+; *
+; * This file is derivative of CMSIS V5.00 gcc_arm.ld
+; */
+
+/* Linker script to configure memory regions. */
+/* This file will be run trough the pre-processor. */
+
+#include "region_defs.h"
+
+MEMORY
+{
+    FLASH (rx)  : ORIGIN = BL2_CODE_START, LENGTH = BL2_CODE_SIZE
+    EFLASH_DRIVER_REGION (rwx) : ORIGIN = EFLASH_DRIVER_REGION_BASE, LENGTH = EFLASH_DRIVER_REGION_SIZE
+    RAM   (rwx) : ORIGIN = BL2_DATA_START, LENGTH = BL2_DATA_SIZE
+}
+
+__heap_size__  = BL2_HEAP_SIZE;
+__msp_stack_size__ = BL2_MSP_STACK_SIZE;
+
+/* Library configurations */
+GROUP(libgcc.a libc.a libm.a libnosys.a)
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+    /* Startup section is loaded to Flash and runs from Flash */
+    .startup :
+    {
+        KEEP(*(.vectors))
+        __Vectors_End = .;
+        __Vectors_Size = __Vectors_End - __Vectors;
+        __end__ = .;
+
+        *startup_musca_b1_secure_enclave_bl2.*
+    } > FLASH
+
+    /* eFlash driver code that gets copied from Flash to SRAM */
+    .ER_EFLASH_DRIVER : ALIGN(4)
+    {
+        *Driver_GFC100_EFlash.o(.text*)
+        *Driver_GFC100_EFlash.o(.rodata*)
+        *gfc100_eflash_drv.o(.text*)
+        *gfc100_eflash_drv.o(.rodata*)
+        *musca_b1_eflash_drv.o(.text*)
+        *musca_b1_eflash_drv.o(.rodata*)
+        . = ALIGN(4); /* This alignment is needed to make the section size 4 bytes aligned */
+    } > EFLASH_DRIVER_REGION AT > FLASH
+    Image$$ER_EFLASH_DRIVER$$Base = ADDR(.ER_EFLASH_DRIVER);
+    Image$$ER_EFLASH_DRIVER$$Limit = ADDR(.ER_EFLASH_DRIVER) + SIZEOF(.ER_EFLASH_DRIVER);
+
+    .text :
+    {
+        *(.text*)
+
+        KEEP(*(.init))
+        KEEP(*(.fini))
+
+        /* .ctors */
+        *crtbegin.o(.ctors)
+        *crtbegin?.o(.ctors)
+        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
+        *(SORT(.ctors.*))
+        *(.ctors)
+
+        /* .dtors */
+         *crtbegin.o(.dtors)
+         *crtbegin?.o(.dtors)
+         *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
+         *(SORT(.dtors.*))
+         *(.dtors)
+
+        *(.rodata*)
+
+        KEEP(*(.eh_frame*))
+    } > FLASH
+
+    .ARM.extab :
+    {
+        *(.ARM.extab* .gnu.linkonce.armextab.*)
+    } > FLASH
+
+    __exidx_start = .;
+    .ARM.exidx :
+    {
+        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+    } > FLASH
+    __exidx_end = .;
+
+    /* To copy multiple ROM to RAM sections,
+     * define etext2/data2_start/data2_end and
+     * define __STARTUP_COPY_MULTIPLE in startup_cmsdk_musca_bl2.S */
+    .copy.table :
+    {
+        . = ALIGN(4);
+        __copy_table_start__ = .;
+        LONG (__etext)
+        LONG (__data_start__)
+        LONG (__data_end__ - __data_start__)
+        LONG (LOADADDR(.ER_EFLASH_DRIVER))
+        LONG (ADDR(.ER_EFLASH_DRIVER))
+        LONG (SIZEOF(.ER_EFLASH_DRIVER))
+        LONG (DEFINED(__etext2) ? __etext2 : 0)
+        LONG (DEFINED(__data2_start__) ? __data2_start__ : 0)
+        LONG (DEFINED(__data2_start__) ? __data2_end__ - __data2_start__ : 0)
+        __copy_table_end__ = .;
+    } > FLASH
+
+    /* To clear multiple BSS sections,
+     * uncomment .zero.table section and,
+     * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_cmsdk_musca_bl2.S */
+    .zero.table :
+    {
+        . = ALIGN(4);
+        __zero_table_start__ = .;
+        LONG (__bss_start__)
+        LONG (__bss_end__ - __bss_start__)
+        LONG (DEFINED(__bss2_start__) ? __bss2_start__ : 0)
+        LONG (DEFINED(__bss2_start__) ? __bss2_end__ - __bss2_start__ : 0)
+        __zero_table_end__ = .;
+    } > FLASH
+
+    __etext = .;
+
+    .tfm_bl2_shared_data BOOT_TFM_SHARED_DATA_BASE : ALIGN(32)
+    {
+        . += BOOT_TFM_SHARED_DATA_SIZE;
+    } > RAM
+    Image$$SHARED_DATA$$RW$$Base = ADDR(.tfm_bl2_shared_data);
+    Image$$SHARED_DATA$$RW$$Limit = ADDR(.tfm_bl2_shared_data) + SIZEOF(.tfm_bl2_shared_data);
+
+    .data : AT (__etext)
+    {
+        __data_start__ = .;
+        *(vtable)
+        *(.data*)
+
+        . = ALIGN(4);
+        /* preinit data */
+        PROVIDE_HIDDEN (__preinit_array_start = .);
+        KEEP(*(.preinit_array))
+        PROVIDE_HIDDEN (__preinit_array_end = .);
+
+        . = ALIGN(4);
+        /* init data */
+        PROVIDE_HIDDEN (__init_array_start = .);
+        KEEP(*(SORT(.init_array.*)))
+        KEEP(*(.init_array))
+        PROVIDE_HIDDEN (__init_array_end = .);
+
+
+        . = ALIGN(4);
+        /* finit data */
+        PROVIDE_HIDDEN (__fini_array_start = .);
+        KEEP(*(SORT(.fini_array.*)))
+        KEEP(*(.fini_array))
+        PROVIDE_HIDDEN (__fini_array_end = .);
+
+        KEEP(*(.jcr*))
+        . = ALIGN(4);
+        /* All data end */
+        __data_end__ = .;
+
+    } > RAM
+    Image$$ER_DATA$$Base = ADDR(.data);
+
+    .bss :
+    {
+        . = ALIGN(4);
+        __bss_start__ = .;
+        *(.bss*)
+        *(COMMON)
+        . = ALIGN(4);
+        __bss_end__ = .;
+    } > RAM
+
+    bss_size = __bss_end__ - __bss_start__;
+
+    .msp_stack : ALIGN(32)
+    {
+        . += __msp_stack_size__;
+    } > RAM
+    Image$$ARM_LIB_STACK$$ZI$$Base = ADDR(.msp_stack);
+    Image$$ARM_LIB_STACK$$ZI$$Limit = ADDR(.msp_stack) + SIZEOF(.msp_stack);
+
+    .heap : ALIGN(8)
+    {
+        . = ALIGN(8);
+        __end__ = .;
+        PROVIDE(end = .);
+        __HeapBase = .;
+        . += __heap_size__;
+        __HeapLimit = .;
+        __heap_limit = .; /* Add for _sbrk */
+    } > RAM
+    Image$$ARM_LIB_HEAP$$ZI$$Limit = ADDR(.heap) + SIZEOF(.heap);
+
+    PROVIDE(__stack = Image$$ARM_LIB_STACK$$ZI$$Limit);
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Source/gcc/startup_musca_b1_secure_enclave_bl2.S b/platform/ext/target/musca_b1_secure_enclave/Device/Source/gcc/startup_musca_b1_secure_enclave_bl2.S
new file mode 100644
index 0000000..a124c46
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Source/gcc/startup_musca_b1_secure_enclave_bl2.S
@@ -0,0 +1,278 @@
+;/*
+; * Copyright (c) 2009-2020 Arm Limited. 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.
+; * 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.
+; *
+; *
+; * This file is derivative of CMSIS V5.00 startup_ARMCM33.S
+; */
+
+#include "tfm_plat_config.h"
+
+    .syntax    unified
+    .arch    armv6-m
+
+    .section .vectors
+    .align 2
+    .globl    __Vectors
+__Vectors:
+    .long    Image$$ARM_LIB_STACK$$ZI$$Limit   /* Top of Stack */
+    .long    Reset_Handler                     /*     Reset Handler */
+    .long    NMI_Handler                       /* -14 NMI Handler */
+    .long    HardFault_Handler                 /* -13 Hard Fault Handler */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    SVC_Handler                       /*  -5 SVCall Handler */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    PendSV_Handler                    /*  -2 PendSV Handler */
+    .long    SysTick_Handler                   /*  -1 SysTick Handler */
+
+    /* Core interrupts */
+    .long    ExternalIRQ_Handler               /*   0: */
+    .long    CC312_Handler                     /*   1: */
+    .long    CC312_APB_C_Handler               /*   2: */
+    .long    Watchdog_Handler                  /*   3: */
+    .long    0                                 /*   4: Reserved */
+    .long    Timer0_Handler                    /*   5: */
+    .long    Timer1_Handler                    /*   6: */
+    .long    0                                 /*   7: Reserved */
+    .long    0                                 /*   8: Reserved */
+    .long    GPIO_Handler                      /*   9: */
+    .long    GPIO_0_Handler                    /*  10: */
+    .long    GPIO_1_Handler                    /*  11: */
+    .long    GPIO_2_Handler                    /*  12: */
+    .long    GPIO_3_Handler                    /*  13: */
+    .long    GPIO_4_Handler                    /*  14: */
+    .long    GPIO_5_Handler                    /*  15: */
+    .long    GPIO_6_Handler                    /*  16: */
+    .long    GPIO_7_Handler                    /*  17: */
+    .long    0                                 /*  18: */
+    .long    0                                 /*  19: */
+    .long    0                                 /*  20: */
+    .long    MHU0_NR2R_Handler                 /*  21: */
+    .long    MHU0_R2NR_Handler                 /*  22: */
+    .long    MHU0_COMB_Handler                 /*  23: */
+    .long    MHU0_MSG_0_Handler                /*  24: */
+    .long    MHU0_MSG_1_Handler                /*  25: */
+    .long    MHU1_NR2R_Handler                 /*  26: */
+    .long    MHU1_R2NR_Handler                 /*  27: */
+    .long    MHU1_COMB_Handler                 /*  28: */
+    .long    MHU1_MSG_0_Handler                /*  29: */
+    .long    MHU1_MSG_1_Handler                /*  30: */
+    .long    0                                 /*  31: */
+
+    .size    __Vectors, . - __Vectors
+
+    .text
+    .thumb
+    .thumb_func
+    .align    2
+    .globl    Reset_Handler
+    .type    Reset_Handler, %function
+Reset_Handler:
+/*  Firstly it copies data from read only memory to RAM. There are two schemes
+ *  to copy. One can copy more than one sections. Another can only copy
+ *  one section.  The former scheme needs more instructions and read-only
+ *  data to implement than the latter.
+ *  Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes.  */
+
+#ifdef __STARTUP_COPY_MULTIPLE
+/*  Multiple sections scheme.
+ *
+ *  Between symbol address __copy_table_start__ and __copy_table_end__,
+ *  there are array of triplets, each of which specify:
+ *    offset 0: LMA of start of a section to copy from
+ *    offset 4: VMA of start of a section to copy to
+ *    offset 8: size of the section to copy. Must be multiply of 4
+ *
+ *  All addresses must be aligned to 4 bytes boundary.
+ */
+    ldr    r4, =__copy_table_start__
+    ldr    r5, =__copy_table_end__
+
+.L_loop0:
+    cmp    r4, r5
+    bge    .L_loop0_done
+    ldr    r1, [r4]
+    ldr    r2, [r4, #4]
+    ldr    r3, [r4, #8]
+
+.L_loop0_0:
+    subs    r3, #4
+    blt    .L_loop0_0_done
+    ldr    r0, [r1, r3]
+    str    r0, [r2, r3]
+    b    .L_loop0_0
+
+.L_loop0_0_done:
+    adds    r4, #12
+    b    .L_loop0
+
+.L_loop0_done:
+#else
+/*  Single section scheme.
+ *
+ *  The ranges of copy from/to are specified by following symbols
+ *    __etext: LMA of start of the section to copy from. Usually end of text
+ *    __data_start__: VMA of start of the section to copy to
+ *    __data_end__: VMA of end of the section to copy to
+ *
+ *  All addresses must be aligned to 4 bytes boundary.
+ */
+    ldr    r1, =__etext
+    ldr    r2, =__data_start__
+    ldr    r3, =__data_end__
+
+    subs    r3, r2
+    ble    .L_loop1_done
+
+.L_loop1:
+    subs    r3, #4
+    ldr    r0, [r1,r3]
+    str    r0, [r2,r3]
+    bgt    .L_loop1
+
+.L_loop1_done:
+#endif /*__STARTUP_COPY_MULTIPLE */
+
+/*  This part of work usually is done in C library startup code. Otherwise,
+ *  define this macro to enable it in this startup.
+ *
+ *  There are two schemes too. One can clear multiple BSS sections. Another
+ *  can only clear one section. The former is more size expensive than the
+ *  latter.
+ *
+ *  Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
+ *  Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
+ */
+#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
+/*  Multiple sections scheme.
+ *
+ *  Between symbol address __copy_table_start__ and __copy_table_end__,
+ *  there are array of tuples specifying:
+ *    offset 0: Start of a BSS section
+ *    offset 4: Size of this BSS section. Must be multiply of 4
+ */
+    ldr    r3, =__zero_table_start__
+    ldr    r4, =__zero_table_end__
+
+.L_loop2:
+    cmp    r3, r4
+    bge    .L_loop2_done
+    ldr    r1, [r3]
+    ldr    r2, [r3, #4]
+    movs    r0, 0
+
+.L_loop2_0:
+    subs    r2, #4
+    blt    .L_loop2_0_done
+    str    r0, [r1, r2]
+    b    .L_loop2_0
+.L_loop2_0_done:
+
+    adds    r3, #8
+    b    .L_loop2
+.L_loop2_done:
+#elif defined (__STARTUP_CLEAR_BSS)
+/*  Single BSS section scheme.
+ *
+ *  The BSS section is specified by following symbols
+ *    __bss_start__: start of the BSS section.
+ *    __bss_end__: end of the BSS section.
+ *
+ *  Both addresses must be aligned to 4 bytes boundary.
+ */
+    ldr    r1, =__bss_start__
+    ldr    r2, =__bss_end__
+
+    movs    r0, 0
+
+    subs    r2, r1
+    ble    .L_loop3_done
+
+.L_loop3:
+    subs    r2, #4
+    str    r0, [r1, r2]
+    bgt    .L_loop3
+.L_loop3_done:
+#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
+
+    bl    SystemInit
+
+#ifndef __START
+#define __START _start
+#endif
+    bl    __START
+
+    .pool
+    .size    Reset_Handler, . - Reset_Handler
+
+
+    .align    1
+    .thumb_func
+    .type    Default_Handler, %function
+Default_Handler:
+    b        Default_Handler
+    .size    Default_Handler, . - Default_Handler
+
+/* Macro to define default exception/interrupt handlers.
+ * Default handler are weak symbols with an endless loop.
+ * They can be overwritten by real handlers.
+ */
+    .macro   def_irq_handler  Handler_Name
+    .weak    \Handler_Name
+    .set     \Handler_Name, Default_Handler
+    .endm
+
+    def_irq_handler NMI_Handler
+    def_irq_handler HardFault_Handler
+    def_irq_handler SVC_Handler
+    def_irq_handler PendSV_Handler
+    def_irq_handler SysTick_Handler
+
+    def_irq_handler ExternalIRQ_Handler
+    def_irq_handler CC312_Handler
+    def_irq_handler CC312_APB_C_Handler
+    def_irq_handler Watchdog_Handler
+
+    def_irq_handler Timer0_Handler
+    def_irq_handler Timer1_Handler
+
+    def_irq_handler GPIO_Handler
+    def_irq_handler GPIO_0_Handler
+    def_irq_handler GPIO_1_Handler
+    def_irq_handler GPIO_2_Handler
+    def_irq_handler GPIO_3_Handler
+    def_irq_handler GPIO_4_Handler
+    def_irq_handler GPIO_5_Handler
+    def_irq_handler GPIO_6_Handler
+    def_irq_handler GPIO_7_Handler
+
+    def_irq_handler MHU0_NR2R_Handler
+    def_irq_handler MHU0_R2NR_Handler
+    def_irq_handler MHU0_COMB_Handler
+    def_irq_handler MHU0_MSG_0_Handler
+    def_irq_handler MHU0_MSG_1_Handler
+    def_irq_handler MHU1_NR2R_Handler
+    def_irq_handler MHU1_R2NR_Handler
+    def_irq_handler MHU1_COMB_Handler
+    def_irq_handler MHU1_MSG_0_Handler
+    def_irq_handler MHU1_MSG_1_Handler
+
+    .end
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Source/gcc/startup_musca_b1_secure_enclave_s.S b/platform/ext/target/musca_b1_secure_enclave/Device/Source/gcc/startup_musca_b1_secure_enclave_s.S
new file mode 100644
index 0000000..bd4c1d9
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Source/gcc/startup_musca_b1_secure_enclave_s.S
@@ -0,0 +1,286 @@
+;/*
+; * Copyright (c) 2009-2020 Arm Limited. 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.
+; * 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.
+; *
+; *
+; * This file is derivative of CMSIS V5.00 startup_ARMCM33.S
+; */
+
+#include "tfm_plat_config.h"
+
+    .syntax    unified
+    .arch    armv6-m
+
+    .section .vectors
+    .align 2
+    .globl    __Vectors
+__Vectors:
+    .long    Image$$ARM_LIB_STACK_MSP$$ZI$$Limit   /* Top of Stack */
+    .long    Reset_Handler                     /*     Reset Handler */
+    .long    NMI_Handler                       /* -14 NMI Handler */
+    .long    HardFault_Handler                 /* -13 Hard Fault Handler */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    SVC_Handler                       /*  -5 SVCall Handler */
+    .long    0                                 /*     Reserved */
+    .long    0                                 /*     Reserved */
+    .long    PendSV_Handler                    /*  -2 PendSV Handler */
+    .long    SysTick_Handler                   /*  -1 SysTick Handler */
+
+    /* Core interrupts */
+    .long    ExternalIRQ_Handler               /*   0: */
+    .long    CC312_Handler                     /*   1: */
+    .long    CC312_APB_C_Handler               /*   2: */
+    .long    Watchdog_Handler                  /*   3: */
+    .long    0                                 /*   4: Reserved */
+    .long    TFM_TIMER0_IRQ_Handler            /*   5: */
+    .long    Timer1_Handler                    /*   6: */
+    .long    0                                 /*   7: Reserved */
+    .long    0                                 /*   8: Reserved */
+    .long    GPIO_Handler                      /*   9: */
+    .long    GPIO_0_Handler                    /*  10: */
+    .long    GPIO_1_Handler                    /*  11: */
+    .long    GPIO_2_Handler                    /*  12: */
+    .long    GPIO_3_Handler                    /*  13: */
+    .long    GPIO_4_Handler                    /*  14: */
+    .long    GPIO_5_Handler                    /*  15: */
+    .long    GPIO_6_Handler                    /*  16: */
+    .long    GPIO_7_Handler                    /*  17: */
+    .long    0                                 /*  18: */
+    .long    0                                 /*  19: */
+    .long    0                                 /*  20: */
+    .long    MHU0_NR2R_Handler                 /*  21: */
+    .long    MHU0_R2NR_Handler                 /*  22: */
+    .long    MHU0_COMB_Handler                 /*  23: */
+    .long    MHU0_MSG_0_Handler                /*  24: */
+    .long    MHU0_MSG_1_Handler                /*  25: */
+    .long    MHU1_NR2R_Handler                 /*  26: */
+    .long    MHU1_R2NR_Handler                 /*  27: */
+    .long    MHU1_COMB_Handler                 /*  28: */
+    .long    MHU1_MSG_0_Handler                /*  29: */
+    .long    MHU1_MSG_1_Handler                /*  30: */
+    .long    0                                 /*  31: */
+
+    .size    __Vectors, . - __Vectors
+
+    .text
+    .thumb
+    .thumb_func
+    .align    2
+    .globl    Reset_Handler
+    .type    Reset_Handler, %function
+Reset_Handler:
+    cpsid i
+/*  Firstly it copies data from read only memory to RAM. There are two schemes
+ *  to copy. One can copy more than one sections. Another can only copy
+ *  one section.  The former scheme needs more instructions and read-only
+ *  data to implement than the latter.
+ *  Macro __STARTUP_COPY_MULTIPLE is used to choose between two schemes.  */
+
+#ifdef __STARTUP_COPY_MULTIPLE
+/*  Multiple sections scheme.
+ *
+ *  Between symbol address __copy_table_start__ and __copy_table_end__,
+ *  there are array of triplets, each of which specify:
+ *    offset 0: LMA of start of a section to copy from
+ *    offset 4: VMA of start of a section to copy to
+ *    offset 8: size of the section to copy. Must be multiply of 4
+ *
+ *  All addresses must be aligned to 4 bytes boundary.
+ */
+    ldr    r4, =__copy_table_start__
+    ldr    r5, =__copy_table_end__
+
+.L_loop0:
+    cmp    r4, r5
+    bge    .L_loop0_done
+    ldr    r1, [r4]
+    ldr    r2, [r4, #4]
+    ldr    r3, [r4, #8]
+
+.L_loop0_0:
+    subs    r3, #4
+    blt    .L_loop0_0_done
+    ldr    r0, [r1, r3]
+    str    r0, [r2, r3]
+    b    .L_loop0_0
+
+.L_loop0_0_done:
+    adds    r4, #12
+    b    .L_loop0
+
+.L_loop0_done:
+#else
+/*  Single section scheme.
+ *
+ *  The ranges of copy from/to are specified by following symbols
+ *    __etext: LMA of start of the section to copy from. Usually end of text
+ *    __data_start__: VMA of start of the section to copy to
+ *    __data_end__: VMA of end of the section to copy to
+ *
+ *  All addresses must be aligned to 4 bytes boundary.
+ */
+    ldr    r1, =__etext
+    ldr    r2, =__data_start__
+    ldr    r3, =__data_end__
+
+    subs    r3, r2
+    ble    .L_loop1_done
+
+.L_loop1:
+    subs    r3, #4
+    ldr    r0, [r1,r3]
+    str    r0, [r2,r3]
+    bgt    .L_loop1
+
+.L_loop1_done:
+#endif /*__STARTUP_COPY_MULTIPLE */
+
+/*  This part of work usually is done in C library startup code. Otherwise,
+ *  define this macro to enable it in this startup.
+ *
+ *  There are two schemes too. One can clear multiple BSS sections. Another
+ *  can only clear one section. The former is more size expensive than the
+ *  latter.
+ *
+ *  Define macro __STARTUP_CLEAR_BSS_MULTIPLE to choose the former.
+ *  Otherwise efine macro __STARTUP_CLEAR_BSS to choose the later.
+ */
+#ifdef __STARTUP_CLEAR_BSS_MULTIPLE
+/*  Multiple sections scheme.
+ *
+ *  Between symbol address __copy_table_start__ and __copy_table_end__,
+ *  there are array of tuples specifying:
+ *    offset 0: Start of a BSS section
+ *    offset 4: Size of this BSS section. Must be multiply of 4
+ */
+    ldr    r3, =__zero_table_start__
+    ldr    r4, =__zero_table_end__
+
+.L_loop2:
+    cmp    r3, r4
+    bge    .L_loop2_done
+    ldr    r1, [r3]
+    ldr    r2, [r3, #4]
+    movs    r0, 0
+
+.L_loop2_0:
+    subs    r2, #4
+    blt    .L_loop2_0_done
+    str    r0, [r1, r2]
+    b    .L_loop2_0
+.L_loop2_0_done:
+
+    adds    r3, #8
+    b    .L_loop2
+.L_loop2_done:
+#elif defined (__STARTUP_CLEAR_BSS)
+/*  Single BSS section scheme.
+ *
+ *  The BSS section is specified by following symbols
+ *    __bss_start__: start of the BSS section.
+ *    __bss_end__: end of the BSS section.
+ *
+ *  Both addresses must be aligned to 4 bytes boundary.
+ */
+    ldr    r1, =__bss_start__
+    ldr    r2, =__bss_end__
+
+    movs    r0, 0
+
+    subs    r2, r1
+    ble    .L_loop3_done
+
+.L_loop3:
+    subs    r2, #4
+    str    r0, [r1, r2]
+    bgt    .L_loop3
+.L_loop3_done:
+#endif /* __STARTUP_CLEAR_BSS_MULTIPLE || __STARTUP_CLEAR_BSS */
+
+    bl    SystemInit
+
+    mrs     r0, control    /* Get control value */
+    movs    r1, #2
+    orrs    r0, r0, r1     /* Select switch to PSP */
+    msr     control, r0
+    ldr     r0, =Image$$ARM_LIB_STACK$$ZI$$Limit
+    msr     psp, r0
+
+#ifndef __START
+#define __START _start
+#endif
+    bl    __START
+
+    .pool
+    .size    Reset_Handler, . - Reset_Handler
+
+
+    .align    1
+    .thumb_func
+    .type    Default_Handler, %function
+Default_Handler:
+    b        Default_Handler
+    .size    Default_Handler, . - Default_Handler
+
+/* Macro to define default exception/interrupt handlers.
+ * Default handler are weak symbols with an endless loop.
+ * They can be overwritten by real handlers.
+ */
+    .macro   def_irq_handler  Handler_Name
+    .weak    \Handler_Name
+    .set     \Handler_Name, Default_Handler
+    .endm
+
+    def_irq_handler NMI_Handler
+    def_irq_handler HardFault_Handler
+    def_irq_handler SVC_Handler
+    def_irq_handler PendSV_Handler
+    def_irq_handler SysTick_Handler
+
+    def_irq_handler ExternalIRQ_Handler
+    def_irq_handler CC312_Handler
+    def_irq_handler CC312_APB_C_Handler
+    def_irq_handler Watchdog_Handler
+
+    def_irq_handler TFM_TIMER0_IRQ_Handler
+    def_irq_handler Timer1_Handler
+
+    def_irq_handler GPIO_Handler
+    def_irq_handler GPIO_0_Handler
+    def_irq_handler GPIO_1_Handler
+    def_irq_handler GPIO_2_Handler
+    def_irq_handler GPIO_3_Handler
+    def_irq_handler GPIO_4_Handler
+    def_irq_handler GPIO_5_Handler
+    def_irq_handler GPIO_6_Handler
+    def_irq_handler GPIO_7_Handler
+
+    def_irq_handler MHU0_NR2R_Handler
+    def_irq_handler MHU0_R2NR_Handler
+    def_irq_handler MHU0_COMB_Handler
+    def_irq_handler MHU0_MSG_0_Handler
+    def_irq_handler MHU0_MSG_1_Handler
+    def_irq_handler MHU1_NR2R_Handler
+    def_irq_handler MHU1_R2NR_Handler
+    def_irq_handler MHU1_COMB_Handler
+    def_irq_handler MHU1_MSG_0_Handler
+    def_irq_handler MHU1_MSG_1_Handler
+
+    .end
diff --git a/platform/ext/target/musca_b1_secure_enclave/Device/Source/system_core_init.c b/platform/ext/target/musca_b1_secure_enclave/Device/Source/system_core_init.c
new file mode 100644
index 0000000..2c45fd7
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Device/Source/system_core_init.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2009-2020 Arm Limited. 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.
+ * 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.
+ */
+
+/*
+ * This file is derivative of CMSIS V5.01:
+ * \Device\ARM\ARMCM0plus\Source\system_ARMCM0plus.c
+ */
+
+#include "system_core_init.h"
+#include "cmsis.h"
+
+/*----------------------------------------------------------------------------
+  Define clocks
+ *----------------------------------------------------------------------------*/
+#define  SYSTEM_CLOCK       (40960000UL)
+#define  PERIPHERAL_CLOCK   (40960000UL)
+
+/*----------------------------------------------------------------------------
+  Externals
+ *----------------------------------------------------------------------------*/
+
+/*----------------------------------------------------------------------------
+  System Core Clock Variable
+ *----------------------------------------------------------------------------*/
+uint32_t SystemCoreClock = SYSTEM_CLOCK;
+uint32_t PeripheralClock = PERIPHERAL_CLOCK;
+
+/*----------------------------------------------------------------------------
+  System Core Clock update function
+ *----------------------------------------------------------------------------*/
+void SystemCoreClockUpdate (void)
+{
+    SystemCoreClock = SYSTEM_CLOCK;
+    PeripheralClock = PERIPHERAL_CLOCK;
+}
+
+/*----------------------------------------------------------------------------
+  System initialization function
+ *----------------------------------------------------------------------------*/
+void SystemInit (void)
+{
+#if defined (__VTOR_PRESENT) && (__VTOR_PRESENT == 1U)
+    extern uint32_t __Vectors;
+    SCB->VTOR = (uint32_t) &__Vectors;
+#endif
+    SystemCoreClockUpdate();
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/Libraries/mt25ql_flash_lib.c b/platform/ext/target/musca_b1_secure_enclave/Libraries/mt25ql_flash_lib.c
new file mode 100644
index 0000000..578cc5b
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Libraries/mt25ql_flash_lib.c
@@ -0,0 +1,901 @@
+/*
+ * Copyright (c) 2018-2019 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 <stdlib.h>
+/* Use memcpy function */
+#include <string.h>
+
+#include "mt25ql_flash_lib.h"
+#include "qspi_ip6514e_drv.h"
+
+/** Setter bit manipulation macro */
+#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
+/** Clearing bit manipulation macro */
+#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
+/** Getter bit manipulation macro */
+#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
+
+#define BITS_PER_WORD  32U
+#define BYTES_PER_WORD 4U
+
+#define ARG_NOT_USED     0
+#define ARG_PTR_NOT_USED NULL
+
+/** MT25QL used command */
+#define WRITE_ENABLE_CMD                    0x06U
+#define READ_ENHANCED_VOLATILE_CFG_REG_CMD  0x65U
+#define WRITE_ENHANCED_VOLATILE_CFG_REG_CMD 0x61U
+#define READ_VOLATILE_CFG_REG_CMD           0x85U
+#define WRITE_VOLATILE_CFG_REG_CMD          0x81U
+#define READ_FLAG_STATUS_REG_CMD            0x70U
+#define SUBSECTOR_ERASE_32KB_CMD            0x52U
+#define SUBSECTOR_ERASE_4KB_CMD             0x20U
+#define SECTOR_ERASE_CMD                    0xD8U
+#define BULK_ERASE_CMD                      0xC7U
+/*
+ * The baud rate divisor in \ref mt25ql_dev_t needs to be configured adequately
+ * to handle those commands.
+ */
+#define QUAD_OUTPUT_FAST_READ_CMD           0x6BU
+#define FAST_READ_CMD                       0x0BU
+#define READ_CMD                            0x03U
+#define QUAD_INPUT_FAST_PROGRAM_CMD         0x32U
+#define PAGE_PROGRAM_CMD                    0x02U
+
+/** MT25QL Enhanced Volatile Configuration Register access */
+#define ENHANCED_VOLATILE_CFG_REG_LEN      1U
+#define ENHANCED_VOLATILE_CFG_REG_QSPI_POS 7U
+#define ENHANCED_VOLATILE_CFG_REG_DSPI_POS 6U
+
+/** MT25QL Volatile Configuration Register access */
+#define VOLATILE_CFG_REG_LEN               1U
+#define VOLATILE_CFG_REG_DUMMY_CYCLES_POS  4U
+#define VOLATILE_CFG_REG_DUMMY_CYCLES_BITS 4U
+
+/** MT25QL Flag Status Register access */
+#define FLAG_STATUS_REG_LEN       1U
+#define FLAG_STATUS_REG_READY_POS 7U
+
+/*
+ * 10 is the minimal number of dummy clock cycles needed to reach the maximal
+ * frequency of the Quad Output Fast Read Command.
+ */
+#define QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES    10U
+#define FAST_READ_DUMMY_CYCLES                8U
+#define RESET_STATE_DUMMY_CYCLES              8U
+#define DEFAULT_READ_DUMMY_CYCLES             0U
+#define QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES  0U
+#define PAGE_PROGRAM_DUMMY_CYCLES             0U
+
+/* Only up to 8 bytes can be read or written using the Flash commands. */
+#define CMD_DATA_MAX_SIZE 8U
+
+/**
+ * \brief Change specific bits in a 32 bits word.
+ *
+ * \param[in,out] word         Pointer of the word to change
+ * \param[in]     bits         bits_length bits to put at bits_pos in the word
+ *                             pointed
+ * \param[in]     bits_length  Number of bits to change
+ * \param[in]     bits_pos     Position of the bits to change
+ *
+ * \note This function will do nothing if the parameters given are incorrect:
+ *         * word is NULL
+ *         * bits_length + bits_pos > 32
+ *         * bits_length is 0
+ */
+static void change_bits_in_word(volatile uint32_t *word,
+                                uint32_t bits,
+                                uint32_t bits_length,
+                                uint32_t bits_pos)
+{
+    uint32_t mask;
+
+    if ((word == NULL) ||
+        ((bits_length + bits_pos) > BITS_PER_WORD) ||
+        (bits_length == 0U)) {
+        /* Silently fail */
+        return;
+    }
+
+    /* Change all the bits */
+    if (bits_length == BITS_PER_WORD) {
+        *word = bits;
+        return;
+    }
+
+    mask = ((1U << bits_length) - 1);
+    /*
+     * We change the bits in three steps:
+     *   - clear bits_length bits with zeroes at bits_pos in the word
+     *   - mask bits in case it contains more than bits_length bits
+     *   - set the new bits in the cleared word
+     * Because the data pointed by word is only read once, the data will still
+     * be coherent after an interruption that changes it.
+     */
+    *word = ((*word & ~(mask << bits_pos)) | ((bits & mask) << bits_pos));
+}
+
+/**
+ * \brief Send the Write Enable command, needed before any write.
+ *
+ * \param[in] dev     Pointer to MT25QL device structure \ref mt25ql_dev_t
+ */
+static void send_write_enable(struct mt25ql_dev_t* dev)
+{
+    qspi_ip6514e_send_simple_cmd(dev->controller, WRITE_ENABLE_CMD);
+}
+
+/**
+ * \brief Set SPI mode on the flash device and on the controller.
+ *
+ * \param[in] dev       Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in] spi_mode  SPI mode to be set on flash device and controller
+ *                      \ref qspi_ip6514e_spi_mode_t
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ */
+static enum mt25ql_error_t set_spi_mode(struct mt25ql_dev_t* dev,
+                                        enum qspi_ip6514e_spi_mode_t spi_mode)
+{
+    uint8_t enhanced_volatile_cfg_reg = 0;
+    enum qspi_ip6514e_error_t controller_error;
+
+    /* Read the Enhanced Volatile Configuration Register, modify it according
+     * to the requested SPI mode then write back the modified value to the
+     * register. This will activate the SPI mode on the flash side.
+     */
+    controller_error = qspi_ip6514e_send_read_cmd(
+                                             dev->controller,
+                                             READ_ENHANCED_VOLATILE_CFG_REG_CMD,
+                                             &enhanced_volatile_cfg_reg,
+                                             ENHANCED_VOLATILE_CFG_REG_LEN,
+                                             ARG_NOT_USED,
+                                             ARG_NOT_USED,
+                                             0); /* No dummy cycles needed for
+                                                    this command. */
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    switch(spi_mode) {
+    case QSPI_IP6514E_SPI_MODE:
+        /* Disable the Dual- and Quad-SPI modes.
+         * Clearing the bit enables the mode, setting it disables it.
+         */
+        SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
+        SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
+        break;
+    case QSPI_IP6514E_DSPI_MODE:
+        /* Disable the Quad-SPI mode and activate DSPI mode.
+         * Clearing the bit enables the mode, setting it disables it.
+         */
+        CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
+        SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
+        break;
+    case QSPI_IP6514E_QSPI_MODE:
+        /* Disable the Dual-SPI mode and activate QSPI mode.
+         * Clearing the bit enables the mode, setting it disables it.
+         */
+        SET_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_DSPI_POS);
+        CLR_BIT(enhanced_volatile_cfg_reg, ENHANCED_VOLATILE_CFG_REG_QSPI_POS);
+        break;
+    default:
+        return MT25QL_ERR_WRONG_ARGUMENT;
+    }
+
+    send_write_enable(dev);
+
+    controller_error = qspi_ip6514e_send_write_cmd(
+                                            dev->controller,
+                                            WRITE_ENHANCED_VOLATILE_CFG_REG_CMD,
+                                            &enhanced_volatile_cfg_reg,
+                                            ENHANCED_VOLATILE_CFG_REG_LEN,
+                                            ARG_NOT_USED,
+                                            ARG_NOT_USED,
+                                            0); /* No dummy cycles needed for
+                                                   this command. */
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    /* Activate the requested SPI mode on the controller side as well. */
+    controller_error = qspi_ip6514e_set_spi_mode(dev->controller,
+                                                 spi_mode,
+                                                 spi_mode,
+                                                 spi_mode);
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    return MT25QL_ERR_NONE;
+}
+
+/**
+ * \brief Change the number of dummy clock cycles subsequent to all FAST READ
+ *        commands.
+ *
+ * \param[in] dev          Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in] dummy_cycles Dummy clock cycles to set
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ */
+static enum mt25ql_error_t change_dummy_cycles(struct mt25ql_dev_t* dev,
+                                               uint32_t dummy_cycles)
+{
+    uint32_t volatile_cfg_reg = 0;
+    enum qspi_ip6514e_error_t controller_error;
+
+    /*
+     * Changes the number of dummy cycles in the Volatile Configuration
+     * Register.
+     */
+    controller_error = qspi_ip6514e_send_read_cmd(dev->controller,
+                                                  READ_VOLATILE_CFG_REG_CMD,
+                                                  &volatile_cfg_reg,
+                                                  VOLATILE_CFG_REG_LEN,
+                                                  ARG_NOT_USED,
+                                                  ARG_NOT_USED,
+                                                  0); /* No dummy cycles needed
+                                                         for this command. */
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    change_bits_in_word(&volatile_cfg_reg,
+                        dummy_cycles,
+                        VOLATILE_CFG_REG_DUMMY_CYCLES_BITS,
+                        VOLATILE_CFG_REG_DUMMY_CYCLES_POS);
+
+    send_write_enable(dev);
+
+    controller_error = qspi_ip6514e_send_write_cmd(dev->controller,
+                                                   WRITE_VOLATILE_CFG_REG_CMD,
+                                                   &volatile_cfg_reg,
+                                                   VOLATILE_CFG_REG_LEN,
+                                                   ARG_NOT_USED,
+                                                   ARG_NOT_USED,
+                                                   0); /* No dummy cycles needed
+                                                          for this command. */
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    return MT25QL_ERR_NONE;
+}
+
+/**
+ * \brief Wait until the current program/erase is finished.
+ *
+ * \param[in] dev     Pointer to MT25QL device structure \ref mt25ql_dev_t
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ */
+static enum mt25ql_error_t wait_program_or_erase_complete(
+                                                       struct mt25ql_dev_t* dev)
+{
+    enum qspi_ip6514e_error_t controller_error;
+    uint8_t flag_status_reg = 0;
+
+    /* Wait until the ready bit of the Flag Status Register is set */
+    while (!GET_BIT(flag_status_reg, FLAG_STATUS_REG_READY_POS)) {
+        controller_error = qspi_ip6514e_send_read_cmd(dev->controller,
+                                                      READ_FLAG_STATUS_REG_CMD,
+                                                      &flag_status_reg,
+                                                      FLAG_STATUS_REG_LEN,
+                                                      ARG_NOT_USED,
+                                                      ARG_NOT_USED,
+                                                      0); /* No dummy cycles
+                                                             needed for this
+                                                             command. */
+        if (controller_error != QSPI_IP6514E_ERR_NONE) {
+            return (enum mt25ql_error_t)controller_error;
+        }
+    }
+
+    return MT25QL_ERR_NONE;
+}
+
+/**
+ * \brief Execute a program command that crosses the page size boundary.
+ *
+ * \param[in]  dev               Pointer to MT25QL device structure
+ *                               \ref mt25ql_dev_t
+ * \param[in]  opcode            Opcode for the command.
+ * \param[in]  write_data        Pointer to a memory zone where the write_len
+ *                               number of bytes are located to write for this
+ *                               command.
+ * \param[in]  write_len         Number of bytes to write for the command.
+ *                               Between 1 and 8 bytes (both included) can be
+ *                               written.
+ * \param[in]  addr              Address used for the command
+ * \param[in]  addr_bytes_number Number of address bytes for this command.
+ *                               If an address is not needed for the command,
+ *                               use 0 for argument, otherwise between 1 and
+ *                               4 bytes (both included) can be used.
+ * \param[in]  dummy_cycles      Number of dummy cycles required for the
+ *                               command, between 0 and 31 (both included).
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ *
+ * \note This function will execute two commands: one to program the bytes up to
+ *       the page boundary and another one to program the rest. It will wait
+ *       that bytes are programmed from first command before triggering the
+ *       second one.
+ * \note This function does not send a write enable command before the first
+ *       command and does not check that bytes were programmed after the second
+ *       command.
+ */
+static enum mt25ql_error_t send_boundary_cross_write_cmd(
+                                                     struct mt25ql_dev_t* dev,
+                                                     uint8_t opcode,
+                                                     const void *write_data,
+                                                     uint32_t write_len,
+                                                     uint32_t addr,
+                                                     uint32_t addr_bytes_number,
+                                                     uint32_t dummy_cycles)
+{
+    enum qspi_ip6514e_error_t controller_error;
+    enum mt25ql_error_t library_error;
+    /*
+     * Remaining bytes between the current address and the end of the current
+     * page.
+     */
+    uint32_t page_remainder = FLASH_PAGE_SIZE - (addr % FLASH_PAGE_SIZE);
+
+    /* First write up to the end of the current page. */
+    controller_error = qspi_ip6514e_send_write_cmd(dev->controller, opcode,
+                                                   write_data, page_remainder,
+                                                   addr, addr_bytes_number,
+                                                   dummy_cycles);
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    write_data = (void *)((uint32_t)write_data + page_remainder);
+    addr += page_remainder;
+
+    /* Wait for the page to be written before sending new commands. */
+    library_error = wait_program_or_erase_complete(dev);
+    if (library_error != MT25QL_ERR_NONE) {
+        return library_error;
+    }
+
+    /* Then write the remaining data of the write_len bytes. */
+    send_write_enable(dev);
+    controller_error = qspi_ip6514e_send_write_cmd(dev->controller, opcode,
+                                                   write_data,
+                                                   write_len - page_remainder,
+                                                   addr, addr_bytes_number,
+                                                   dummy_cycles);
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    return MT25QL_ERR_NONE;
+}
+
+enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev,
+                                       enum mt25ql_functional_state_t f_state)
+{
+    enum qspi_ip6514e_error_t controller_error;
+    enum mt25ql_error_t library_error;
+
+    switch(f_state) {
+    case MT25QL_FUNC_STATE_DEFAULT:
+        dev->config_state.spi_mode            = QSPI_IP6514E_SPI_MODE;
+        dev->config_state.opcode_read         = READ_CMD;
+        dev->config_state.dummy_cycles_read   = DEFAULT_READ_DUMMY_CYCLES;
+        dev->config_state.opcode_write        = PAGE_PROGRAM_CMD;
+        dev->config_state.dummy_cycles_write  = PAGE_PROGRAM_DUMMY_CYCLES;
+        break;
+    case MT25QL_FUNC_STATE_FAST:
+        dev->config_state.spi_mode            = QSPI_IP6514E_SPI_MODE;
+        dev->config_state.opcode_read         = FAST_READ_CMD;
+        dev->config_state.dummy_cycles_read   = FAST_READ_DUMMY_CYCLES;
+        dev->config_state.opcode_write        = PAGE_PROGRAM_CMD;
+        dev->config_state.dummy_cycles_write  = PAGE_PROGRAM_DUMMY_CYCLES;
+        break;
+    case MT25QL_FUNC_STATE_QUAD_FAST:
+        dev->config_state.spi_mode            = QSPI_IP6514E_QSPI_MODE;
+        dev->config_state.opcode_read         = QUAD_OUTPUT_FAST_READ_CMD;
+        dev->config_state.dummy_cycles_read   =
+                                             QUAD_OUTPUT_FAST_READ_DUMMY_CYCLES;
+        dev->config_state.opcode_write        = QUAD_INPUT_FAST_PROGRAM_CMD;
+        dev->config_state.dummy_cycles_write  =
+                                           QUAD_INPUT_FAST_PROGRAM_DUMMY_CYCLES;
+        break;
+    default:
+        return MT25QL_ERR_WRONG_ARGUMENT;
+    }
+
+    dev->config_state.func_state = f_state;
+
+    /* This function will first set the Flash memory SPI mode and then set
+     * the controller's SPI mode. It will fail if the two sides do not have
+     * the same mode when this function is called.
+     */
+    library_error = set_spi_mode(dev, dev->config_state.spi_mode);
+    if (library_error != MT25QL_ERR_NONE) {
+        return library_error;
+    }
+
+    /* Set the number of dummy cycles for read commands. */
+    library_error = change_dummy_cycles(
+                                      dev, dev->config_state.dummy_cycles_read);
+    if (library_error != MT25QL_ERR_NONE) {
+        return library_error;
+    }
+
+    /* The rest of the configuration needs the controller to be disabled */
+    while(!qspi_ip6514e_is_idle(dev->controller));
+    qspi_ip6514e_disable(dev->controller);
+
+    /* Set the baud rate divisor as configured in the device structure. */
+    controller_error = qspi_ip6514e_set_baud_rate_div(dev->controller,
+                                                      dev->baud_rate_div);
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    /* Set opcode and dummy cycles needed for read commands. */
+    controller_error = qspi_ip6514e_cfg_reads(
+                                 dev->controller, dev->config_state.opcode_read,
+                                 dev->config_state.dummy_cycles_read);
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    /* Set opcode and dummy cycles needed for write commands. */
+    controller_error = qspi_ip6514e_cfg_writes(
+                                dev->controller, dev->config_state.opcode_write,
+                                dev->config_state.dummy_cycles_write);
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    /* Set Flash memory constants: bytes per page and address bytes. */
+    controller_error = qspi_ip6514e_cfg_page_size(dev->controller,
+                                                  FLASH_PAGE_SIZE);
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    controller_error = qspi_ip6514e_cfg_addr_bytes(dev->controller,
+                                                   ADDR_BYTES);
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    qspi_ip6514e_enable(dev->controller);
+
+    return MT25QL_ERR_NONE;
+}
+
+enum mt25ql_error_t mt25ql_restore_reset_state(struct mt25ql_dev_t* dev)
+{
+    enum mt25ql_error_t library_error;
+
+    /*
+     * This function will first change the Flash memory mode to single SPI and
+     * then change the controller to single SPI. It will fail if the two sides
+     * do not have the same mode when this function is called.
+     */
+    library_error = set_spi_mode(dev, QSPI_IP6514E_SPI_MODE);
+    if (library_error != MT25QL_ERR_NONE) {
+        return library_error;
+    }
+
+    /* Set the default number of dummy cycles for direct read commands. */
+    library_error = change_dummy_cycles(dev, RESET_STATE_DUMMY_CYCLES);
+    if (library_error != MT25QL_ERR_NONE) {
+        return library_error;
+    }
+
+    /* The rest of the configuration needs the controller to be disabled */
+    while(!qspi_ip6514e_is_idle(dev->controller));
+    qspi_ip6514e_disable(dev->controller);
+
+    /* Restore the default value of the QSPI controller registers. */
+    qspi_ip6514e_reset_regs(dev->controller);
+
+    qspi_ip6514e_enable(dev->controller);
+
+    dev->config_state = (struct mt25ql_config_state_t){ 0 };
+    dev->config_state.func_state = MT25QL_FUNC_STATE_NOT_INITED;
+
+    return MT25QL_ERR_NONE;
+}
+
+enum mt25ql_error_t mt25ql_direct_read(struct mt25ql_dev_t* dev,
+                                       uint32_t addr,
+                                       void *data,
+                                       uint32_t len)
+{
+    /*
+     * The direct access window size is the size of the memory that can be
+     * accessed with a direct access.
+     */
+    uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1;
+    /*
+     * The window number is the number of times it will be needed to remap the
+     * address with the remap register. We move this Direct Access window first
+     * window_number times starting at the beginning address to read full
+     * windows of direct_access_window_size bytes. Then we read the remainder
+     * bytes.
+     */
+    uint32_t window_number = len / direct_access_window_size;
+
+    if (data == NULL || len == 0) {
+        return MT25QL_ERR_WRONG_ARGUMENT;
+    }
+
+    if ((addr + len) >= dev->size) {
+        return MT25QL_ERR_ADDR_TOO_BIG;
+    }
+
+    /*
+     * There is no limitation reading through a Flash page boundary hence we
+     * do not add the same logic here than in the write function.
+     */
+
+    /* Transfer the bytes for the window_number windows first. */
+    for (uint32_t window = 0; window < window_number; window++) {
+        qspi_ip6514e_remap_addr(dev->controller, addr);
+
+        /*
+         * The AHB address to access the Flash memory does not change but it
+         * will be translated differently thanks to the remap function.
+         */
+        memcpy(data,
+               (void *)dev->direct_access_start_addr,
+               direct_access_window_size);
+
+        len -= direct_access_window_size;
+        data = (void *)((uint32_t)data + direct_access_window_size);
+        addr += direct_access_window_size;
+    }
+
+    if (len) {
+        /* Transfer the reminder bytes */
+        qspi_ip6514e_remap_addr(dev->controller, addr);
+
+        memcpy(data, (void *)dev->direct_access_start_addr, len);
+    }
+
+    /* Disable remapping for direct accesses outside of this function. */
+    qspi_ip6514e_disable_remap(dev->controller);
+
+    return MT25QL_ERR_NONE;
+}
+
+enum mt25ql_error_t mt25ql_direct_write(struct mt25ql_dev_t* dev,
+                                        uint32_t addr,
+                                        const void *data,
+                                        uint32_t len)
+{
+    enum mt25ql_error_t library_error;
+    /*
+     * The direct access window size is the size of the memory that can be
+     * accessed with a direct access.
+     */
+    uint32_t direct_access_window_size = dev->controller->cfg->addr_mask + 1;
+    uint32_t window_number;
+    /* Offset between address and the previous 32 bits aligned word */
+    uint32_t word_offset;
+
+    if (data == NULL || len == 0) {
+        return MT25QL_ERR_WRONG_ARGUMENT;
+    }
+
+    if ((addr + len) >= dev->size) {
+        return MT25QL_ERR_ADDR_TOO_BIG;
+    }
+
+    /*
+     * If the remapping address is not aligned on a 32 bits boundary, a direct
+     * access of one word could cross a Flash page boundary. If that happens,
+     * the bytes of that word that are over the page boundary will instead be
+     * written at the beginning of the same page.
+     * To counter this problem, we align the remapping address and add the word
+     * offset to the address of the direct access for the first window only.
+     */
+    word_offset = addr % BYTES_PER_WORD;
+    /* Make address aligned on a 32 bits alignment. */
+    addr -= word_offset;
+    /*
+     * Only direct_access_window_size address locations are available by direct
+     * access. We calculate the number of windows that we will need to transfer
+     * len bytes. We have to add in the window the offset that we add in the
+     * beginning.
+     */
+    window_number = (len + word_offset) / direct_access_window_size;
+
+    /*
+     * This function assumes that the flash has already been erased.
+     * Transfer the bytes for the window_number windows first.
+     */
+    for (uint32_t window = 0; window < window_number; window++) {
+        /* The controller needs to be disabled while remapping is done. */
+        qspi_ip6514e_remap_addr(dev->controller, addr);
+
+        /*
+         * The AHB address to access the Flash memory does not change but it
+         * will be translated differently thanks to the remap function.
+         */
+        memcpy((void *)(dev->direct_access_start_addr + word_offset),
+               data,
+               direct_access_window_size - word_offset);
+
+        len -= (direct_access_window_size - word_offset);
+        data = (void *)((uint32_t)data +
+                        (direct_access_window_size - word_offset));
+        addr += direct_access_window_size;
+
+        /*
+         * The address is now aligned, there is no need to add an offset for the
+         * remaining windows.
+         */
+        word_offset = 0;
+
+        /*
+         * Wait until the last program operation is complete before changing
+         * the remap address.
+         */
+        library_error = wait_program_or_erase_complete(dev);
+        if (library_error != MT25QL_ERR_NONE) {
+            return library_error;
+        }
+    }
+
+    if (len) {
+        /* Transfer the reminder bytes */
+        qspi_ip6514e_remap_addr(dev->controller, addr);
+
+        memcpy((void *)(dev->direct_access_start_addr + word_offset),
+               data,
+               len);
+
+        /* Wait until the last program operation is complete */
+        library_error = wait_program_or_erase_complete(dev);
+        if (library_error != MT25QL_ERR_NONE) {
+            return library_error;
+        }
+    }
+
+    /*
+     * Disable the default remap address for direct accesses outside of this
+     * function.
+     */
+    qspi_ip6514e_disable_remap(dev->controller);
+
+    return MT25QL_ERR_NONE;
+}
+
+enum mt25ql_error_t mt25ql_command_read(struct mt25ql_dev_t* dev,
+                                        uint32_t addr,
+                                        void *data,
+                                        uint32_t len)
+{
+    /* With one single command only 8 bytes can be read. */
+    uint32_t cmd_number = len / CMD_DATA_MAX_SIZE;
+    enum qspi_ip6514e_error_t controller_error;
+
+    if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
+        return MT25QL_ERR_NOT_INITED;
+    }
+
+    for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
+        controller_error = qspi_ip6514e_send_read_cmd(
+                                           dev->controller,
+                                           dev->config_state.opcode_read,
+                                           data, CMD_DATA_MAX_SIZE, addr,
+                                           ADDR_BYTES,
+                                           dev->config_state.dummy_cycles_read);
+        if (controller_error != QSPI_IP6514E_ERR_NONE) {
+            return (enum mt25ql_error_t)controller_error;
+        }
+
+        data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE);
+        addr += CMD_DATA_MAX_SIZE;
+        len -= CMD_DATA_MAX_SIZE;
+    }
+
+    if (len) {
+        /* Read the remainder. */
+        controller_error = qspi_ip6514e_send_read_cmd(
+                                           dev->controller,
+                                           dev->config_state.opcode_read,
+                                           data, len, addr, ADDR_BYTES,
+                                           dev->config_state.dummy_cycles_read);
+        if (controller_error != QSPI_IP6514E_ERR_NONE) {
+            return (enum mt25ql_error_t)controller_error;
+        }
+    }
+
+    return MT25QL_ERR_NONE;
+
+}
+
+enum mt25ql_error_t mt25ql_command_write(struct mt25ql_dev_t* dev,
+                                         uint32_t addr,
+                                         const void *data,
+                                         uint32_t len)
+{
+    /* With one single command only 8 bytes can be written. */
+    uint32_t cmd_number = len / CMD_DATA_MAX_SIZE;
+    enum qspi_ip6514e_error_t controller_error;
+    enum mt25ql_error_t library_error;
+
+    if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
+        return MT25QL_ERR_NOT_INITED;
+    }
+
+    for (uint32_t cmd_index = 0; cmd_index < cmd_number; cmd_index++) {
+        send_write_enable(dev);
+
+        /*
+         * Check if this command is not writing over a page boundary: first and
+         * last bytes are in the same page.
+         */
+        if ((addr / FLASH_PAGE_SIZE) !=
+            ((addr + CMD_DATA_MAX_SIZE - 1) / FLASH_PAGE_SIZE)) {
+            /* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */
+            library_error = send_boundary_cross_write_cmd(
+                                          dev, dev->config_state.opcode_write,
+                                          data, CMD_DATA_MAX_SIZE, addr,
+                                          ADDR_BYTES,
+                                          dev->config_state.dummy_cycles_write);
+            if (library_error != MT25QL_ERR_NONE) {
+                return library_error;
+            }
+        } else {
+            /* Normal case: not crossing the boundary. */
+            controller_error = qspi_ip6514e_send_write_cmd(
+                                          dev->controller,
+                                          dev->config_state.opcode_write,
+                                          data, CMD_DATA_MAX_SIZE, addr,
+                                          ADDR_BYTES,
+                                          dev->config_state.dummy_cycles_write);
+            if (controller_error != QSPI_IP6514E_ERR_NONE) {
+                return (enum mt25ql_error_t)controller_error;
+            }
+        }
+
+        /* Wait until the write operation is complete. */
+        library_error = wait_program_or_erase_complete(dev);
+        if (library_error != MT25QL_ERR_NONE) {
+            return library_error;
+        }
+
+        data = (void *)((uint32_t)data + CMD_DATA_MAX_SIZE);
+        addr += CMD_DATA_MAX_SIZE;
+        len -= CMD_DATA_MAX_SIZE;
+    }
+
+    if (len) {
+        /* Write the remainder. */
+        send_write_enable(dev);
+        /*
+         * Check if this command is not writing over a page boundary: first and
+         * last bytes are in the same page.
+         */
+        if ((addr / FLASH_PAGE_SIZE) != ((addr + len - 1) / FLASH_PAGE_SIZE)) {
+            /* The CMD_DATA_MAX_SIZE bytes written are crossing the boundary. */
+            library_error = send_boundary_cross_write_cmd(
+                                          dev, dev->config_state.opcode_write,
+                                          data, len, addr, ADDR_BYTES,
+                                          dev->config_state.dummy_cycles_write);
+            if (library_error != MT25QL_ERR_NONE) {
+                return library_error;
+            }
+        } else {
+            /* Normal case: not crossing the boundary. */
+            controller_error = qspi_ip6514e_send_write_cmd(
+                                          dev->controller,
+                                          dev->config_state.opcode_write,
+                                          data, len, addr, ADDR_BYTES,
+                                          dev->config_state.dummy_cycles_write);
+            if (controller_error != QSPI_IP6514E_ERR_NONE) {
+                return (enum mt25ql_error_t)controller_error;
+            }
+        }
+
+        /* Wait until the write operation is complete. */
+        library_error = wait_program_or_erase_complete(dev);
+        if (library_error != MT25QL_ERR_NONE) {
+            return library_error;
+        }
+    }
+
+    return MT25QL_ERR_NONE;
+
+}
+
+enum mt25ql_error_t mt25ql_erase(struct mt25ql_dev_t* dev,
+                                 uint32_t addr,
+                                 enum mt25ql_erase_t erase_type)
+{
+    enum qspi_ip6514e_error_t controller_error;
+    enum mt25ql_error_t library_error;
+    uint8_t erase_cmd;
+    uint32_t addr_bytes;
+
+    if (dev->config_state.func_state == MT25QL_FUNC_STATE_NOT_INITED) {
+        return MT25QL_ERR_NOT_INITED;
+    }
+
+    send_write_enable(dev);
+
+    switch (erase_type) {
+    case MT25QL_ERASE_ALL_FLASH:
+        if (addr != 0) {
+            return MT25QL_ERR_ADDR_NOT_ALIGNED;
+        }
+        erase_cmd = BULK_ERASE_CMD;
+        addr_bytes = ARG_NOT_USED;
+        break;
+    case MT25QL_ERASE_SECTOR_64K:
+        erase_cmd = SECTOR_ERASE_CMD;
+        addr_bytes = ADDR_BYTES;
+        if ((addr % SECTOR_64KB) != 0) {
+            return MT25QL_ERR_ADDR_NOT_ALIGNED;
+        }
+        break;
+    case MT25QL_ERASE_SUBSECTOR_32K:
+        erase_cmd = SUBSECTOR_ERASE_32KB_CMD;
+        addr_bytes = ADDR_BYTES;
+        if ((addr % SUBSECTOR_32KB) != 0) {
+            return MT25QL_ERR_ADDR_NOT_ALIGNED;
+        }
+        break;
+    case MT25QL_ERASE_SUBSECTOR_4K:
+        erase_cmd = SUBSECTOR_ERASE_4KB_CMD;
+        addr_bytes = ADDR_BYTES;
+        if ((addr % SUBSECTOR_4KB) != 0) {
+            return MT25QL_ERR_ADDR_NOT_ALIGNED;
+        }
+        break;
+    default:
+        return MT25QL_ERR_WRONG_ARGUMENT;
+    }
+
+    if (addr >= dev->size) {
+        return MT25QL_ERR_ADDR_TOO_BIG;
+    }
+
+    controller_error = qspi_ip6514e_send_cmd(dev->controller,
+                                             erase_cmd,
+                                             ARG_PTR_NOT_USED,
+                                             ARG_NOT_USED,
+                                             ARG_PTR_NOT_USED,
+                                             ARG_NOT_USED,
+                                             addr,
+                                             addr_bytes,
+                                             0); /* No dummy cycles needed for
+                                                    any erase command. */
+    if (controller_error != QSPI_IP6514E_ERR_NONE) {
+        return (enum mt25ql_error_t)controller_error;
+    }
+
+    /* Wait until the erase operation is complete */
+    library_error = wait_program_or_erase_complete(dev);
+    if (library_error != MT25QL_ERR_NONE) {
+         return (enum mt25ql_error_t)controller_error;
+    }
+
+    return MT25QL_ERR_NONE;
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/Libraries/mt25ql_flash_lib.h b/platform/ext/target/musca_b1_secure_enclave/Libraries/mt25ql_flash_lib.h
new file mode 100644
index 0000000..c2dac2c
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Libraries/mt25ql_flash_lib.h
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2018-2019 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.
+ */
+
+/*
+ * This library provides functions to control the MT25QL256ABA-1EW7-OSIT flash
+ * memory from Micron and should work for similar devices from the same vendor.
+ */
+
+#ifndef __MT25QL_H__
+#define __MT25QL_H__
+
+#include "qspi_ip6514e_drv.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief MT25QL Flash Memory documentation defined values.
+ */
+#define FLASH_PAGE_SIZE     (256U)          /* 256B */
+#define SUBSECTOR_4KB       (0x00001000U)   /* 4KB */
+#define SUBSECTOR_32KB      (0x00008000U)   /* 32KB */
+#define SECTOR_64KB         (0x00010000U)   /* 64KB */
+#define ADDR_BYTES          (3U)
+
+enum mt25ql_error_t {
+    MT25QL_ERR_NONE               = QSPI_IP6514E_ERR_NONE,
+    MT25QL_ERR_WRONG_ARGUMENT     = QSPI_IP6514E_ERR_WRONG_ARGUMENT,
+    MT25QL_ERR_CTRL_NOT_DISABLED  = QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED,
+    MT25QL_ERR_READ_IN_PROGRESS   = QSPI_IP6514E_ERR_READ_IN_PROGRESS,
+    MT25QL_ERR_WRITE_IN_PROGRESS  = QSPI_IP6514E_ERR_WRITE_IN_PROGRESS,
+    MT25QL_ERR_ADDR_NOT_ALIGNED,
+    MT25QL_ERR_NOT_INITED,
+    MT25QL_ERR_ADDR_TOO_BIG,
+};
+
+enum mt25ql_erase_t {
+    MT25QL_ERASE_ALL_FLASH     = 0U,             /*!< Erase all flash */
+    MT25QL_ERASE_SUBSECTOR_4K  = SUBSECTOR_4KB,  /*!< Erase a 4 KB subsector */
+    MT25QL_ERASE_SUBSECTOR_32K = SUBSECTOR_32KB, /*!< Erase a 32 KB subsector */
+    MT25QL_ERASE_SECTOR_64K    = SECTOR_64KB,    /*!< Erase a sector (64 KB) */
+};
+
+enum mt25ql_functional_state_t {
+    MT25QL_FUNC_STATE_NOT_INITED    = 0U,
+        /*!< QSPI Flash controller is not initialized, only direct read
+         * is guaranteed to be working
+         */
+    MT25QL_FUNC_STATE_DEFAULT       = 1U,
+        /*!< The QSPI Flash controller and memory is in default state,
+         *   using basic read/write commands
+         */
+    MT25QL_FUNC_STATE_FAST          = 2U,
+        /*!< The QSPI Flash controller and memory is configured to operate in
+         *   single SPI mode and fast Flash commands could be used for read and
+         *   program operations.
+         */
+    MT25QL_FUNC_STATE_QUAD_FAST     = 3U,
+        /*!< The QSPI Flash controller and memory is configured to operate in
+         *   Quad SPI mode and fast Flash commands could be used for read and
+         *   program operations.
+         */
+};
+
+struct mt25ql_config_state_t {
+    enum mt25ql_functional_state_t func_state;
+    /*!< Functional state id */
+    enum qspi_ip6514e_spi_mode_t spi_mode;
+    /*!< SPI mode for the current functional state */
+    uint8_t opcode_read;
+    /*!< Read opcode for the current functional state */
+    uint8_t opcode_write;
+    /*!< Write opcode for the current functional state */
+    uint32_t dummy_cycles_read;
+    /*!< Dummy cycles for the read command for the current functional state */
+    uint32_t dummy_cycles_write;
+    /*!< Dummy cycles for the write command for the current functional state */
+};
+
+struct mt25ql_dev_t {
+    struct qspi_ip6514e_dev_t *controller;
+        /*!< QSPI Flash controller. */
+    uint32_t direct_access_start_addr;
+        /*!< AHB address to directly access the contents of the Flash memory
+         *   through the QSPI Controller.
+         */
+    uint32_t baud_rate_div;
+        /*!< Clock divisor that will be used to configure the QSPI Flash
+         *   Controller to access the Flash memory. The clock which frequency is
+         *   divived is the one linked to the QSPI Flash controller. It can only
+         *   be an even number between 2 and 32 (both included). It needs to be
+         *   high enough to support the Quad Output Fast Read command with 8
+         *   dummy cycles and the Quad Input Fast Program with 0 dummy cycles.
+         */
+    uint32_t size; /*!< Total size of the MT25QL Flash memory */
+    struct mt25ql_config_state_t config_state;
+        /*!< Configured functional state (with parameter settings) of the
+         *   QSPI Flash controller and memory.
+         */
+
+};
+
+/**
+ * \brief Change configuration of the QSPI Flash controller and MT25QL memory
+ *
+ *        Changes the configuration of the QSPI Flash controller and MT25QL
+ *        Flash memory to operate in the specified SPI mode and to use the
+ *        appropriate Flash commands for read and program operations.
+ *        It also sets:
+ *          + The number of dummy cycles for each operation
+ *          + The bytes per page constant to 256 (MT25QL Flash specific)
+ *          + The number of address bytes to 3
+ *
+ * \param[in] dev       Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in] f_state   Functional state to be set on flash controller
+ *                      and device \ref mt25ql_functional_state_t
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ *
+ * \note This function assumes that the Flash memory device and the QSPI Flash
+ *       controller operates with the same SPI protocol. This function will fail
+ *       if the Flash device is in a different configuration.
+ */
+enum mt25ql_error_t mt25ql_config_mode(struct mt25ql_dev_t* dev,
+                                       enum mt25ql_functional_state_t f_state);
+
+/**
+ * \brief Restore the QSPI Flash controller and MT25QL to reset state.
+ *
+ * \param[in] dev     Pointer to MT25QL device structure \ref mt25ql_dev_t
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ *
+ * \note This function assumes that the Flash memory device and the QSPI Flash
+ *       controller operates with the same SPI protocol. This function will fail
+ *       if the Flash device is in a different configuration.
+ */
+enum mt25ql_error_t mt25ql_restore_reset_state(struct mt25ql_dev_t* dev);
+
+/**
+ * \brief Read bytes from the flash memory (direct access)
+ *
+ * \param[in]  dev   Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in]  addr  Flash memory address for the read operation
+ * \param[out] data  Pointer where len bytes read from the flash memory will be
+ *                   written to
+ * \param[in]  len   Number of bytes to read
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ *
+ * \note This function will use direct access to read from the Flash memory. It
+ *       can be used to access above the direct accessible memory zone if
+ *       not all the AHB address wires are connected.
+ * \note The address given should be the address of the data inside the flash
+ *       memory. To read the first byte inside the memory, use 0x00000000.
+ */
+enum mt25ql_error_t mt25ql_direct_read(struct mt25ql_dev_t* dev,
+                                       uint32_t addr,
+                                       void *data,
+                                       uint32_t len);
+
+/**
+ * \brief Write bytes in the flash memory, at a location where data has already
+ *        been erased (direct access)
+ *
+ * \param[in] dev   Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in] addr  Flash memory address for the write operation
+ * \param[in] data  Pointer to the len bytes that will be written to the flash
+ *                  memory
+ * \param[in] len   Number of bytes to write
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ *
+ * \note This function will use direct access to write to the Flash memory. It
+ *       can be used to access outside of the direct accessible memory zone if
+ *       not all the AHB address wires are connected.
+ * \note The address given should be the address of the data inside the flash
+ *       memory. To write the first byte inside the memory, use 0x00000000.
+ * \note Writing bytes in the flash memory clear them from 1 to 0, for that
+ *       matter the location where data is written needs to be erased
+ *       beforehand.
+ */
+enum mt25ql_error_t mt25ql_direct_write(struct mt25ql_dev_t* dev,
+                                        uint32_t addr,
+                                        const void *data,
+                                        uint32_t len);
+
+/**
+ * \brief Read bytes from the flash memory (using Flash commands)
+ *
+ * \param[in]  dev   Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in]  addr  Flash memory address for the read operation
+ * \param[out] data  Pointer where len bytes read from the flash memory will be
+ *                   written to
+ * \param[in]  len   Number of bytes to read
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ *
+ * \note This function will use the Software Triggered Instruction Generator to
+ *       read from the Flash memory using Flash commands.
+ * \note The address given should be the address of the data inside the flash
+ *       memory. To read the first byte inside the memory, use 0x00000000.
+ */
+enum mt25ql_error_t mt25ql_command_read(struct mt25ql_dev_t* dev,
+                                        uint32_t addr,
+                                        void *data,
+                                        uint32_t len);
+
+/**
+ * \brief Write bytes in the flash memory, at a location where data has already
+ *        been erased (using Flash commands)
+ *
+ * \param[in] dev   Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in] addr  Flash memory address for the write operation
+ * \param[in] data  Pointer to the len bytes that will be written to the flash
+ *                  memory
+ * \param[in] len   Number of bytes to write
+ *
+ * \return Return error code as specified in \ref mt25ql_error_t
+ *
+ * \note This function will use the Software Triggered Instruction Generator to
+ *       write to the Flash memory using Flash commands.
+ * \note The address given should be the address of the data inside the flash
+ *       memory. To write the first byte inside the memory, use 0x00000000.
+ * \note Writing bytes in the flash memory clear them from 1 to 0, for that
+ *       matter the location where data is written needs to be erased
+ *       beforehand.
+ */
+enum mt25ql_error_t mt25ql_command_write(struct mt25ql_dev_t* dev,
+                                         uint32_t addr,
+                                         const void *data,
+                                         uint32_t len);
+
+/**
+ * \brief Erase all flash memory, a sector (64 KiB) or a subsector
+ *        (32 KiB or 4 KiB)
+ *
+ * \param[in] dev        Pointer to MT25QL device structure \ref mt25ql_dev_t
+ * \param[in] addr       Address where to erase in the flash memory
+ * \param[in] erase_type Type of what to erase at the specified address:
+ *                         * whole flash memory
+ *                         * a subsector (4 KiB or 32 KiB)
+ *                         * a sector (64 KiB)
+ * \return Return error code as specified in \ref mt25ql_error_t
+ *
+ * \note The address need to be aligned with the size of what is erased or 0 if
+ *       all flash memory is to be erased.
+ */
+enum mt25ql_error_t mt25ql_erase(struct mt25ql_dev_t* dev,
+                                 uint32_t addr,
+                                 enum mt25ql_erase_t erase_type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MT25QL_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/Native_Driver/gfc100_eflash_drv.c b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/gfc100_eflash_drv.c
new file mode 100644
index 0000000..b8bf522
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/gfc100_eflash_drv.c
@@ -0,0 +1,558 @@
+/*
+ * Copyright (c) 2018-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.
+ * 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 gfc100_eflash_drv.c
+ *
+ * \brief Generic driver for GFC100 flash controller
+ */
+
+#include "gfc100_eflash_drv.h"
+#include "gfc100_process_spec_api.h"
+
+#define BITMASK(width) ((1U<<(width))-1)
+
+/** The MSB Addr[21] selects between memory ranges*/
+#define GFC100_EXTENDED_AREA_OFFSET      (1U << 21)
+
+/* Process specific register map offset */
+#define GFC100_PROCESS_SPEC_REG_MAP_OFF  0x1000U
+
+#define WORD_ALIGN_16B_MASK              0xFU /* Masks the first 4 bits */
+#define WORD_ALIGN_4B_MASK               0x3U /* Masks the first 2 bits */
+#define IS_ADDR_4B_ALIGNED(addr) (((uint32_t)addr & WORD_ALIGN_4B_MASK) == 0U)
+
+/** Currently only 128 bit word width is supported by the driver */
+#define GFC100_SUPPORTED_WORD_BIT_WIDTH   128U
+
+/** Read is done with maximum word width */
+#define BITS_IN_BYTE                      8U
+#define GFC100_READ_BYTE_SIZE             \
+                               (GFC100_SUPPORTED_WORD_BIT_WIDTH / BITS_IN_BYTE)
+
+/** Write is done in 4 byte chunks */
+#define GFC100_WRITE_BYTE_SIZE            4U
+
+/** GFC100 generic controller register map */
+struct gfc100_reg_map_t {
+    volatile uint32_t irq_enable_set;    /* 0x000 RW Interrupt enable */
+    volatile uint32_t irq_enable_clr;    /* 0x004 RW Interrupt disable */
+    volatile uint32_t irq_status_set;    /* 0x008 RW Interrupt status set */
+    volatile uint32_t irq_status_clr;    /* 0x00C RW Interrupt status clear */
+    volatile uint32_t irq_masked_status; /* 0x010 RO Interrupt masked status */
+    volatile uint32_t ctrl;              /* 0x014 RW Control */
+    volatile uint32_t status;            /* 0x018 RO Status */
+    volatile uint32_t addr;              /* 0x01C RW Address */
+    volatile uint32_t data0;             /* 0x020 RW Data 0 */
+    volatile uint32_t data1;             /* 0x024 RO Data 1 */
+    volatile uint32_t data2;             /* 0x028 RO Data 2 */
+    volatile uint32_t data3;             /* 0x02C RO Data 3 */
+    volatile uint32_t reserved[1000];    /* 0x030 Reserved */
+    volatile uint32_t pidr4;             /* 0xFD0 RO Peripheral id register 4 */
+    volatile uint32_t reserved2[3];      /* 0xFD4 Reserved */
+    volatile uint32_t pidr0;             /* 0xFE0 RO Peripheral id register 0 */
+    volatile uint32_t pidr1;             /* 0xFE4 RO Peripheral id register 1 */
+    volatile uint32_t pidr2;             /* 0xFE8 RO Peripheral id register 2 */
+    volatile uint32_t pidr3;             /* 0xFEC RO Peripheral id register 3 */
+    volatile uint32_t cidr0;             /* 0xFF0 RO Component id register 0 */
+    volatile uint32_t cidr1;             /* 0xFF4 RO Component id register 1 */
+    volatile uint32_t cidr2;             /* 0xFF8 RO Component id register 2 */
+    volatile uint32_t cidr3;             /* 0xFFC RO Component id register 3 */
+};
+
+/* Bit definition for the interrupt registers */
+#define GFC100_CMD_ACCEPT_IRQ_POS       0U
+#define GFC100_CMD_ACCEPT_IRQ_MASK      (1U<<GFC100_CMD_ACCEPT_IRQ_POS)
+#define GFC100_CMD_SUCCESS_IRQ_POS      1U
+#define GFC100_CMD_SUCCESS_IRQ_MASK     (1U<<GFC100_CMD_SUCCESS_IRQ_POS)
+#define GFC100_CMD_FAIL_IRQ_POS         2U
+#define GFC100_CMD_FAIL_IRQ_MASK        (1U<<GFC100_CMD_FAIL_IRQ_POS)
+#define GFC100_CMD_REJECT_IRQ_POS       3U
+#define GFC100_CMD_REJECT_IRQ_MASK      (1U<<GFC100_CMD_REJECT_IRQ_POS)
+#define GFC100_CMD_OVERFLOW_IRQ_POS     4U
+#define GFC100_CMD_OVERFLOW_IRQ_MASK    (1U<<GFC100_CMD_OVERFLOW_IRQ_POS)
+
+#define GFC100_IRQ_MAX_NUMBER           5U
+#define GFC100_ALL_IRQ_MASK             BITMASK(GFC100_IRQ_MAX_NUMBER)
+
+/* Bit definitons for the control register */
+#define GFC100_CTRL_CMD_POS             0U
+#define GFC100_CTRL_CMD_WIDTH           3U
+#define GFC100_CTRL_CMD_MASK            \
+        (BITMASK(GFC100_CTRL_CMD_WIDTH)<<GFC100_CTRL_CMD_POS)
+    #define CMD_READ                    0x1U
+    #define CMD_WRITE                   0x2U
+    #define CMD_ROW_WRITE               0x3U
+    #define CMD_ERASE                   0x4U
+    #define CMD_MASS_ERASE              0x7U
+#define GFC100_CTRL_CMD_ABORT_POS       4U
+#define GFC100_CTRL_CMD_ABORT_WIDTH     1U
+#define GFC100_CTRL_CMD_ABORT_MASK      \
+        (BITMASK(GFC100_CTRL_CMD_ABORT_WIDTH)<<GFC100_CTRL_CMD_ABORT_POS)
+
+/* Bit definition for the status registers */
+#define GFC100_CMD_STAT_PENDING_POS     0U
+#define GFC100_CMD_STAT_PENDING_MASK    (1U<<GFC100_CMD_STAT_PENDING_POS)
+#define GFC100_CMD_STAT_ACCEPT_POS      1U
+#define GFC100_CMD_STAT_ACCEPT_MASK     (1U<<GFC100_CMD_STAT_ACCEPT_POS)
+#define GFC100_CMD_STAT_SUCCESS_POS     2U
+#define GFC100_CMD_STAT_SUCCESS_MASK    (1U<<GFC100_CMD_STAT_SUCCESS_POS)
+#define GFC100_CMD_STAT_FAIL_POS        3U
+#define GFC100_CMD_STAT_FAIL_MASK       (1U<<GFC100_CMD_STAT_FAIL_POS)
+#define GFC100_CMD_STAT_FINISH_POS      4U
+#define GFC100_CMD_STAT_FINISH_MASK     (1U<<GFC100_CMD_STAT_FINISH_POS)
+#define GFC100_CMD_STAT_ARB_LOCKED_POS  5U
+#define GFC100_CMD_STAT_ARB_LOCKED_MASK (1U<<GFC100_CMD_STAT_ARB_LOCKED_POS)
+
+#define GFC100_CMD_SUCCEEDED_OR_FAILED \
+                  (GFC100_CMD_STAT_SUCCESS_MASK | GFC100_CMD_STAT_FAIL_MASK)
+#define GFC100_CMD_HAS_FINISHED        \
+                  (GFC100_CMD_SUCCEEDED_OR_FAILED | GFC100_CMD_STAT_FINISH_MASK)
+
+/**
+ * \brief Enables or disables IRQs
+ *
+ * \param[in] dev       GFC100 device struct \ref gfc100_eflash_dev_t
+ * \param[in] irq_mask  IRQs to enable/disable
+ * \param[in] enable    True if the given IRQs need to be enabled, false
+ *                      if they need to be disabled
+ */
+static void gfc100_eflash_irq_enable(struct gfc100_eflash_dev_t *dev,
+                                    uint32_t irq_mask, bool enable)
+{
+    struct gfc100_reg_map_t *reg_map =
+                             (struct gfc100_reg_map_t *)dev->cfg->base;
+
+    if (enable) {
+        reg_map->irq_enable_set = (irq_mask & GFC100_ALL_IRQ_MASK);
+    } else {
+        reg_map->irq_enable_clr = (irq_mask & GFC100_ALL_IRQ_MASK);
+    }
+}
+
+void gfc100_eflash_init(struct gfc100_eflash_dev_t *dev, uint32_t sys_clk)
+{
+    /* The driver polls the status register of the controller rather
+     * than using interrupts, so interrupts need to be disabled.
+     */
+    gfc100_eflash_irq_enable(dev, GFC100_ALL_IRQ_MASK, false);
+
+    /* Call process specific API to the set timing parameters */
+    gfc100_proc_spec_set_eflash_timing(
+                   dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF, sys_clk);
+
+    /* Store flash size */
+    dev->data->flash_size = gfc100_get_eflash_size(dev);
+
+    dev->data->is_initialized = true;
+}
+
+/**
+ * \brief Clears IRQ status
+ *
+ * \param[in] reg_map   GFC100 register map struct \ref gfc100_reg_map_t
+ */
+static inline void clear_irq_status(struct gfc100_reg_map_t *reg_map)
+{
+    reg_map->irq_status_clr = GFC100_ALL_IRQ_MASK;
+}
+
+/**
+ * \brief Waits for command ready flags after issuing a command
+ *
+ * \param[in] reg_map   GFC100 register map struct \ref gfc100_reg_map_t
+ *
+ * \return Returns status register of the device
+ */
+static uint32_t check_cmd_result(struct gfc100_reg_map_t *reg_map)
+{
+    uint32_t status = 0;
+
+    while (!(status = (reg_map->status & GFC100_CMD_HAS_FINISHED))) {};
+
+    if (status & GFC100_CMD_STAT_FINISH_MASK) {
+        /* FINISH bit means the FAIL and SUCCESS status cannot be updated
+         * as the interrupt status register still holds the status
+         * of the previous command.
+         * Clearing the interrupts is needed to the get the result
+         * of the current command.
+         */
+        clear_irq_status(reg_map);
+
+        /* Wait for the SUCCESS or FAIL bit to get set */
+        while (!(status =
+                        (reg_map->status & GFC100_CMD_SUCCEEDED_OR_FAILED))) {};
+    }
+
+    return status;
+}
+
+/**
+ * \brief Triggers read command and blocks until command has finished
+ *
+ * \param[in] reg_map   GFC100 register map struct \ref gfc100_reg_map_t
+ *
+ * \return Returns status regster of the device
+ */
+static uint32_t trigger_read_cmd(struct gfc100_reg_map_t *reg_map,
+                                 uint32_t addr)
+{
+    /* Wait until the previous command is pending */
+    while ((reg_map->status & GFC100_CMD_STAT_PENDING_MASK)) {};
+
+    /* Set the address to read from */
+    reg_map->addr = addr;
+
+    /* Initiate read command */
+    reg_map->ctrl = (CMD_READ << GFC100_CTRL_CMD_POS);
+
+    return (check_cmd_result(reg_map));
+}
+
+/**
+ * \brief Copies data from GFC100 data registers
+ *
+ * \param[in]  reg_map  GFC100 register map struct \ref gfc100_reg_map_t
+ * \param[out] to_ptr   Pointer to copy the data to
+ * \param[in]  size     Number of bytes that needs to be copied
+ * \param[in]  offset   Offset to the first byte that needs to be copied
+ *
+ * \return Returns the number of bytes that were copied
+ *
+ * \note The function checks the offset and the maximum size the data
+ *       registers can hold and adjusts the size with them, so copies only
+ *       the number of available bytes
+ */
+static uint32_t copy_from_data_regs(struct gfc100_reg_map_t *reg_map,
+                                    void *to_ptr, uint32_t size,
+                                    uint32_t offset)
+{
+    offset &= (GFC100_READ_BYTE_SIZE - 1);
+    uint8_t *dst = (uint8_t *)to_ptr;
+    volatile uint8_t *src = ((uint8_t *)&reg_map->data0) + offset;
+    uint32_t i;
+
+    /* Read is always done in 16 bytes chunks from a 16 byte aligned address.
+     * If address is not aligned then HW will align it, so the SW needs to make
+     * sure the right bytes are read from the right location.
+     */
+
+    /* Maximum 16 bytes can be copied from the 16 byte aligned address.
+     * If the read size with the offset overlaps the 16 byte boundary,
+     * only the bytes up to the boundary can be copied. */
+    if (size + offset > GFC100_READ_BYTE_SIZE) {
+        size = GFC100_READ_BYTE_SIZE - offset;
+    }
+
+    /* If the address or the size is not aligned then memcpy can
+     * generate unaligned accesses which is not desired
+     * on the APB, so instead of using memcpy this for cycle is used.
+     */
+    for (i=0; i<size; i++) {
+        *dst = *src;
+        src++;
+        dst++;
+    }
+
+    return size;
+}
+
+enum gfc100_error_t gfc100_eflash_read(struct gfc100_eflash_dev_t *dev,
+                                      uint32_t addr, void *data, uint32_t *len)
+{
+    struct gfc100_reg_map_t *reg_map =
+                            (struct gfc100_reg_map_t *)dev->cfg->base;
+    uint32_t remaining_len = *len;
+    uint32_t status = 0U;
+    uint32_t curr_read_len = 0U;
+    uint32_t addr_align_off = 0U;
+
+    if (dev->data->is_initialized == false) {
+        return GFC100_ERROR_NOT_INITED;
+    }
+
+    if ((addr + *len) > dev->data->flash_size) {
+        return GFC100_ERROR_OUT_OF_RANGE;
+    }
+
+    if (reg_map->status & GFC100_CMD_STAT_PENDING_MASK) {
+        /* Previous command is still pending */
+        return GFC100_ERROR_CMD_PENDING;
+    }
+
+    if (gfc100_proc_spec_get_eflash_word_width(dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF)
+                                           != GFC100_SUPPORTED_WORD_BIT_WIDTH) {
+        /* Curently only 128 bit word width is supported by the driver */
+        return GFC100_ERROR_INVALID_WORD_WIDTH;
+    }
+
+    while (remaining_len && !(status & GFC100_CMD_STAT_FAIL_MASK)) {
+        status = trigger_read_cmd(reg_map, addr);
+
+        addr_align_off = addr & WORD_ALIGN_16B_MASK;
+
+        curr_read_len = copy_from_data_regs(reg_map, data, remaining_len,
+                                            addr_align_off);
+        remaining_len -= curr_read_len;
+        addr += curr_read_len;
+        data = (void *)((uintptr_t)data + curr_read_len);
+
+        /* Clear IRQ status before issuing the next command */
+        clear_irq_status(reg_map);
+    }
+
+    if (status & GFC100_CMD_STAT_FAIL_MASK) {
+        /* If there was error, then this last read was not successful */
+        remaining_len += curr_read_len;
+    }
+
+    /* Adjust length to sign how many bytes were actually read */
+    *len -= remaining_len;
+
+    return ((status & GFC100_CMD_STAT_FAIL_MASK) ?
+                       GFC100_ERROR_CMD_FAIL : GFC100_ERROR_NONE);
+}
+
+/**
+ * \brief Triggers write command and blocks until command has finished
+ *
+ * \param[in] reg_map   GFC100 register map struct \ref gfc100_reg_map_t
+ * \param[in] addr      Flash address to write to
+ * \param[in] data      Data to write to the flash
+ *
+ * \return Returns status regster of the device
+ */
+static uint32_t trigger_write_cmd(struct gfc100_reg_map_t *reg_map,
+                                  uint32_t addr, uint32_t data)
+{
+    uint32_t status;
+
+    /* Set address and data to write */
+    reg_map->addr = addr;
+    reg_map->data0 = data;
+
+    /* Initiate write command */
+    reg_map->ctrl = (CMD_WRITE << GFC100_CTRL_CMD_POS);
+
+    status = check_cmd_result(reg_map);
+
+    return status;
+}
+
+enum gfc100_error_t gfc100_eflash_write(struct gfc100_eflash_dev_t *dev,
+                                        uint32_t addr, const void *data,
+                                        uint32_t *len)
+{
+    struct gfc100_reg_map_t *reg_map =
+                                    (struct gfc100_reg_map_t *)dev->cfg->base;
+    uint32_t status = 0U;
+    uint32_t remaining_len = *len;
+
+    if (dev->data->is_initialized == false) {
+        return GFC100_ERROR_NOT_INITED;
+    }
+
+    if ((addr + *len) > dev->data->flash_size) {
+        return GFC100_ERROR_OUT_OF_RANGE;
+    }
+
+    if (reg_map->status & GFC100_CMD_STAT_PENDING_MASK) {
+        /* Previous command is still pending */
+        return GFC100_ERROR_CMD_PENDING;
+    }
+
+    if (!IS_ADDR_4B_ALIGNED(addr) || !IS_ADDR_4B_ALIGNED(*len)) {
+        /* Both address and length needs to be 4 byte aligned */
+        return GFC100_ERROR_UNALIGNED_PARAM;
+    }
+
+    while (remaining_len && !(status & GFC100_CMD_STAT_FAIL_MASK)) {
+        status = trigger_write_cmd(reg_map, addr, *(uint32_t *)data);
+        addr += GFC100_WRITE_BYTE_SIZE;
+        data = (void *)((uint32_t)data + GFC100_WRITE_BYTE_SIZE);
+        remaining_len -= GFC100_WRITE_BYTE_SIZE;
+        /* Clear IRQ status before issuing the next command */
+        clear_irq_status(reg_map);
+    }
+
+    if (status & GFC100_CMD_STAT_FAIL_MASK) {
+        /* If there was error, then this last write was not successful */
+        remaining_len += GFC100_WRITE_BYTE_SIZE;
+    }
+
+    /* Adjust length to sign how many bytes were actually read */
+    *len -= remaining_len;
+
+    return ((status & GFC100_CMD_STAT_FAIL_MASK) ?
+                       GFC100_ERROR_CMD_FAIL : GFC100_ERROR_NONE);
+}
+
+
+enum gfc100_error_t gfc100_eflash_row_write(struct gfc100_eflash_dev_t *dev,
+                                           uint32_t addr, const void *data,
+                                           uint32_t *len)
+{
+    struct gfc100_reg_map_t *reg_map =
+                                    (struct gfc100_reg_map_t *)dev->cfg->base;
+    uint32_t status = 0U;
+    uint32_t remaining_len = *len;
+    uint32_t flag = GFC100_CMD_STAT_ACCEPT_MASK;
+
+    if (dev->data->is_initialized == false) {
+        return GFC100_ERROR_NOT_INITED;
+    }
+
+    if ((addr + *len) > dev->data->flash_size) {
+        return GFC100_ERROR_OUT_OF_RANGE;
+    }
+
+    if (reg_map->status & GFC100_CMD_STAT_PENDING_MASK) {
+        /* Previous command is still pending */
+        return GFC100_ERROR_CMD_PENDING;
+    }
+
+    if (!IS_ADDR_4B_ALIGNED(addr) || !IS_ADDR_4B_ALIGNED(*len)) {
+        /* Both address and length needs to be 4 byte aligned */
+        return GFC100_ERROR_UNALIGNED_PARAM;
+    }
+
+    while (remaining_len) {
+        /* Set address and data to write */
+        reg_map->addr = addr;
+        reg_map->data0 = *(uint32_t *)data;
+
+        /* Initiate write command */
+        reg_map->ctrl = (CMD_ROW_WRITE << GFC100_CTRL_CMD_POS);
+
+        /* When the first command is sent we only need accept flag to be set.
+         * After the first command we need two flags, accept flag from the
+         * current, and success flag from the previous command.
+         * Note: If interrupts are enabled or execution speed is limited for
+         * other reason, there is a chance that the requested row write command
+         * is not only accepted but executed already before the ACCEPT flag
+         * is checked. If this happens, the code execution will stall.
+         */
+        while (!(((status = reg_map->status) & flag) == flag)) {
+            if (status & GFC100_CMD_STAT_FAIL_MASK) {
+                /* Adjust length to sign how many bytes were actually read */
+                *len -= remaining_len;
+                clear_irq_status(reg_map);
+                return GFC100_ERROR_CMD_FAIL;
+            }
+         }
+        flag = (GFC100_CMD_STAT_ACCEPT_MASK | GFC100_CMD_STAT_SUCCESS_MASK);
+
+        /* Adjust data pointers and the length */
+        addr += GFC100_WRITE_BYTE_SIZE;
+        data = (void *)((uintptr_t)data + GFC100_WRITE_BYTE_SIZE);
+        remaining_len -= GFC100_WRITE_BYTE_SIZE;
+
+        /* Clear IRQ status before issuing the next command */
+        clear_irq_status(reg_map);
+    }
+
+    /* Wait for the success flag of the last command to arrive */
+    while (!(reg_map->status & GFC100_CMD_STAT_SUCCESS_MASK)) {};
+
+    /* Adjust length to sign how many bytes were actually read */
+    *len -= remaining_len;
+
+    clear_irq_status(reg_map);
+
+    return GFC100_ERROR_NONE;
+}
+
+enum gfc100_error_t gfc100_eflash_erase(struct gfc100_eflash_dev_t *dev,
+                                       uint32_t addr,
+                                       enum gfc100_erase_type_t erase)
+{
+    struct gfc100_reg_map_t *reg_map =
+                                     (struct gfc100_reg_map_t *)dev->cfg->base;
+    uint32_t status = 0U;
+
+    if (dev->data->is_initialized == false) {
+        return GFC100_ERROR_NOT_INITED;
+    }
+
+    if (reg_map->status & GFC100_CMD_STAT_PENDING_MASK) {
+        /* Previous command is still pending */
+        return GFC100_ERROR_CMD_PENDING;
+    }
+
+    switch (erase) {
+        case GFC100_ERASE_PAGE:
+            if (addr > dev->data->flash_size) {
+                return GFC100_ERROR_OUT_OF_RANGE;
+            }
+            reg_map->addr = addr;
+            reg_map->ctrl = (CMD_ERASE << GFC100_CTRL_CMD_POS);
+            status = check_cmd_result(reg_map);
+            /* Clear IRQ status before issuing the next command */
+            clear_irq_status(reg_map);
+            break;
+        case GFC100_MASS_ERASE_MAIN_AREA:
+            reg_map->addr = 0U;
+            reg_map->ctrl = (CMD_MASS_ERASE << GFC100_CTRL_CMD_POS);
+            status = check_cmd_result(reg_map);
+            /* Clear IRQ status before issuing the next command */
+            clear_irq_status(reg_map);
+            break;
+        case GFC100_MASS_ERASE_ALL:
+            reg_map->addr = GFC100_EXTENDED_AREA_OFFSET;
+            reg_map->ctrl = (CMD_MASS_ERASE << GFC100_CTRL_CMD_POS);
+            status = check_cmd_result(reg_map);
+            /* Clear IRQ status before issuing the next command */
+            clear_irq_status(reg_map);
+            break;
+        default:
+            return GFC100_ERROR_INVALID_PARAM;
+    }
+
+    return ((status == GFC100_CMD_STAT_FAIL_MASK) ?
+                       GFC100_ERROR_CMD_FAIL : GFC100_ERROR_NONE);
+}
+
+bool gfc100_is_controller_locked(struct gfc100_eflash_dev_t *dev)
+{
+    struct gfc100_reg_map_t *reg_map =
+                                     (struct gfc100_reg_map_t *)dev->cfg->base;
+
+    return (bool)(reg_map->status & GFC100_CMD_STAT_ARB_LOCKED_MASK);
+}
+
+uint32_t gfc100_get_eflash_size(struct gfc100_eflash_dev_t *dev)
+{
+    return (gfc100_proc_spec_get_eflash_size(
+                             dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF));
+}
+
+uint32_t gfc100_get_eflash_page_size(struct gfc100_eflash_dev_t *dev)
+{
+    return (gfc100_proc_spec_get_eflash_page_size(
+                            dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF));
+}
+
+uint32_t gfc100_get_num_of_info_pages(struct gfc100_eflash_dev_t *dev)
+{
+    return (gfc100_proc_spec_get_num_of_info_pages(
+                             dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF));
+}
+
+uint32_t gfc100_get_proc_spec_error(struct gfc100_eflash_dev_t *dev)
+{
+    return (gfc100_proc_spec_get_error_cause(
+                             dev->cfg->base + GFC100_PROCESS_SPEC_REG_MAP_OFF));
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/Native_Driver/gfc100_eflash_drv.h b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/gfc100_eflash_drv.h
new file mode 100644
index 0000000..b4d6cfb
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/gfc100_eflash_drv.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2018-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.
+ * 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 gfc100_eflash_drv.h
+ *
+ * \brief Generic driver for GFC100 flash controller
+ */
+
+#ifndef __GFC100_FLASH_DRV_H__
+#define __GFC100_FLASH_DRV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+enum gfc100_error_t {
+    GFC100_ERROR_NONE = 0U,          /*!< No error */
+    GFC100_ERROR_NOT_INITED,         /*!< Device not inited error */
+    GFC100_ERROR_CMD_PENDING,        /*!< Previous cmd is still pending error */
+    GFC100_ERROR_INVALID_WORD_WIDTH, /*!< Invalid word width error */
+    GFC100_ERROR_INVALID_PARAM,      /*!< Invalid parameter error */
+    GFC100_ERROR_OUT_OF_RANGE,       /*!< Flash address out of range error */
+    GFC100_ERROR_CMD_FAIL,           /*!< Command failed error */
+    GFC100_ERROR_UNALIGNED_PARAM     /*!< Unaligned parameter error */
+};
+
+/** GFC100 Flash controller device configuration structure */
+struct gfc100_eflash_dev_cfg_t {
+    const uint32_t base;  /*!< GFC100 base address */
+};
+
+/** GFC100 Flash controller device data structure */
+struct gfc100_eflash_dev_data_t {
+    bool is_initialized;     /*!< Indicates if the device is initialized */
+    uint32_t flash_size;     /*!< Size of the flash area */
+};
+
+/** GFC100 Flash controller device structure */
+struct gfc100_eflash_dev_t {
+    const struct gfc100_eflash_dev_cfg_t* const cfg;
+                                                    /*!< GFC100 configuration */
+    struct gfc100_eflash_dev_data_t* const data;    /*!< GFC100 data */
+};
+
+enum gfc100_erase_type_t {
+    GFC100_ERASE_PAGE = 0U,        /*!< Erase 1 page */
+    GFC100_MASS_ERASE_MAIN_AREA,   /*!< Erase main area */
+    GFC100_MASS_ERASE_ALL          /*!< Erase main + extended area */
+};
+
+/**
+ * \brief Initializes GFC100 flash controller
+ *
+ * \param[in] dev      GFC100 device struct \ref gfc100_eflash_dev_t
+ * \param[in] sys_clk  System clock in Hz
+ *
+ * \note This API needs to be called prior to any other APIs.
+ * \note For better performance, this function doesn't check if dev is NULL
+ */
+void gfc100_eflash_init(struct gfc100_eflash_dev_t *dev, uint32_t sys_clk);
+
+/**
+ * \brief Reads data from the flash in a blocking call
+ *
+ * \param[in]     dev   GFC100 device struct \ref gfc100_eflash_dev_t
+ * \param[in]     addr  Address to read data from the flash
+ * \param[out]    data  Pointer to store data read from the flash
+ * \param[in,out] len   Number of bytes to read, number of bytes read
+ *
+ * \return Returns error code as specified in \ref gfc100_error_t
+ *
+ * \note This API reads the flash memory by sending read commands with the
+ *       controller, but reading through the AHB directly mapped address gives
+ *       better performance (if flash is mapped for direct read).
+ * \note Addr is expected to be within the [0x0 - Flash size] range
+ * \note For better performance, this function doesn't check if dev is NULL
+ * \note Addr, data and len can have any aligment
+ */
+enum gfc100_error_t gfc100_eflash_read(struct gfc100_eflash_dev_t *dev,
+                                      uint32_t addr, void *data, uint32_t *len);
+
+/**
+ * \brief Writes data to the flash in a blocking call
+ *
+ * \param[in] dev      GFC100 device struct \ref gfc100_eflash_dev_t
+ * \param[in] addr     Address to write data to the flash
+ * \param[in] data     Pointer to the data to be written
+ * \param[in] len      Number of bytes to write
+ *
+ * \return Returns error code as specified in \ref gfc100_error_t
+ *
+ * \note Flash area needs to be pre-erased before writing to it
+ * \note Addr is expected to be within the [0x0 - Flash size] range
+ * \note For better performance, this function doesn't check if dev is NULL
+ * \note Addr and len must be 4 bytes aligned
+ */
+enum gfc100_error_t gfc100_eflash_write(struct gfc100_eflash_dev_t *dev,
+                                        uint32_t addr, const void *data,
+                                        uint32_t *len);
+
+/**
+ * \brief Writes data to the flash in a blocking call
+ *
+ * \param[in] dev      GFC100 device struct \ref gfc100_eflash_dev_t
+ * \param[in] addr     Address to write data to the flash
+ * \param[in] data     Pointer to the data to be written
+ * \param[in] len      Number of bytes to write
+ *
+ * \return Returns error code as specified in \ref gfc100_error_t
+ *
+ * \note This API uses the Row Write command by sending the commands
+ *       continuously so the controller won't close the transfer and start a new
+ *       for the next 4 bytes.This gives much better performance
+ *       than simple Write command, so this API is preferred to use if many
+ *       bytes needs to be written to the flash.
+ * \note Addr is expected to be within the [0x0 - Flash size] range
+ * \note For better performance, this function doesn't check if dev is NULL
+ * \note Addr and len must be 4 bytes aligned
+ */
+enum gfc100_error_t gfc100_eflash_row_write(struct gfc100_eflash_dev_t *dev,
+                                           uint32_t addr, const void *data,
+                                           uint32_t *len);
+
+/**
+ * \brief Erases the flash
+ *
+ * \param[in] dev      GFC100 device struct \ref gfc100_eflash_dev_t
+ * \param[in] addr     Address of the page to erase
+ * \param[in] erase    Erase type \ref gfc100_erase_type_t
+ *
+ * \return Returns error code as specified in \ref gfc100_error_t
+ *
+ * \note For better performance, this function doesn't check if dev is NULL
+ * \note Addr is expected to be within the [0x0 - Flash size] range
+ * \note Addr is only used for page erase, and is automatically aligned
+ *       to page size.
+ */
+enum gfc100_error_t gfc100_eflash_erase(struct gfc100_eflash_dev_t *dev,
+                                       uint32_t addr,
+                                       enum gfc100_erase_type_t erase);
+
+/**
+ * \brief Checks if controller is locked
+ *
+ * \param[in] dev      GFC100 device struct \ref gfc100_eflash_dev_t
+ *
+ * \return Returns true is controller is locked, false otherwise
+ *
+ * \note For better performance, this function doesn't check if dev is NULL
+ * \note This can be used by the software to detect why the APB request
+ *       is being held up.
+ */
+bool gfc100_is_controller_locked(struct gfc100_eflash_dev_t *dev);
+
+/**
+ * \brief Gets flash memory size in bytes
+ *
+ * \param[in] dev      GFC100 device struct \ref gfc100_eflash_dev_t
+ *
+ * \return Returns the size of the flash memory in bytes
+ *
+ * \note For better performance, this function doesn't check if dev is NULL
+ */
+uint32_t gfc100_get_eflash_size(struct gfc100_eflash_dev_t *dev);
+
+/**
+ * \brief Gets flash page size in bytes
+ *
+ * \param[in] dev      GFC100 device struct \ref gfc100_eflash_dev_t
+ *
+ * \return Returns the page size of the flash memory in bytes
+ *
+ * \note For better performance, this function doesn't check if dev is NULL
+ */
+uint32_t gfc100_get_eflash_page_size(struct gfc100_eflash_dev_t *dev);
+
+/**
+ * \brief Gets number of info pages
+ *
+ * \param[in] dev      GFC100 device struct \ref gfc100_eflash_dev_t
+ *
+ * \return Returns the number of info pages from the extended area
+ *
+ * \note For better performance, this function doesn't check if dev is NULL.
+ */
+uint32_t gfc100_get_num_of_info_pages(struct gfc100_eflash_dev_t *dev);
+
+/**
+ * \brief Gets process specific error bits
+ *
+ * \param[in] dev      GFC100 device struct \ref gfc100_eflash_dev_t
+ *
+ * \return Returns the error bits specified by the process specific part
+ *         of the controller.
+ *
+ * \note For better performance, this function doesn't check if dev is NULL.
+ * \note Can be used for debug purposes.
+ */
+uint32_t gfc100_get_proc_spec_error(struct gfc100_eflash_dev_t *dev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __GFC100_FLASH_DRV_H__ */
+
diff --git a/platform/ext/target/musca_b1_secure_enclave/Native_Driver/gfc100_process_spec_api.h b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/gfc100_process_spec_api.h
new file mode 100644
index 0000000..723ea25
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/gfc100_process_spec_api.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018 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 gfc100_process_specific_api.h
+*
+* \brief Header file for the process specific part of the
+*        GFC100 flash controller
+*/
+
+#ifndef __GFC100_PROCESS_SPEC_API_H__
+#define __GFC100_PROCESS_SPEC_API_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+/**
+ * \brief Sets timing parameters on the process specific part
+ *
+ * \param[in] reg_map_base  Process specific register map base
+ * \param[in] sys_clk       System clock in Hz
+ */
+void gfc100_proc_spec_set_eflash_timing(uint32_t reg_map_base,
+                                        uint32_t sys_clk);
+
+/**
+ * \brief Gets flash memory size
+ *
+ * \param[in] reg_map_base  Process specific register map base
+ *
+ * \return Returns the size of the flash memory
+ */
+uint32_t gfc100_proc_spec_get_eflash_size(uint32_t reg_map_base);
+
+/**
+ * \brief Gets flash page size
+ *
+ * \param[in] reg_map_base  Process specific register map base
+ *
+ * \return Returns the page size of the flash memory
+ */
+uint32_t gfc100_proc_spec_get_eflash_page_size(uint32_t reg_map_base);
+
+/**
+ * \brief Gets word width of the process specific part
+ *
+ * \param[in] reg_map_base  Process specific register map base
+ *
+ * \return Returns word width of the process specific part
+ */
+uint32_t gfc100_proc_spec_get_eflash_word_width(uint32_t reg_map_base);
+
+/**
+ * \brief Gets number of info pages
+ *
+ * \param[in] reg_map_base  Process specific register map base
+ *
+ * \return Returns the number of info pages from the extended area
+ */
+uint32_t gfc100_proc_spec_get_num_of_info_pages(uint32_t reg_map_base);
+
+/**
+ * \brief Gets process specific error bits
+ *
+ * \param[in] reg_map_base  Process specific register map base
+ *
+ * \return Returns the error bits specified by the process specific part
+ *         of the controller.
+ */
+uint32_t gfc100_proc_spec_get_error_cause(uint32_t reg_map_base);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GFC100_PROCESS_SPEC_API_H__ */
+
diff --git a/platform/ext/target/musca_b1_secure_enclave/Native_Driver/mhu_v2_x.c b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/mhu_v2_x.c
new file mode 100644
index 0000000..b228c3f
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/mhu_v2_x.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 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.
+ * 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 <stdint.h>
+#include <stdbool.h>
+#include "mhu_v2_x.h"
+
+#define _MHU_V2_X_MAX_CHANNELS    124
+#define _MHU_V2_1_MAX_CHCOMB_INT  4
+#define ENABLE                    0x1
+#define DISABLE                   0x0
+#define CLEAR_INTR                0x1
+#define CH_PER_CH_COMB            0x20
+#define SEND_FRAME(p_mhu)       ((struct _mhu_v2_x_send_frame_t *)p_mhu)
+#define RECV_FRAME(p_mhu)       ((struct _mhu_v2_x_recv_frame_t *)p_mhu)
+
+#define MHU_MAJOR_REV_V2      0x1u
+#define MHU_MINOR_REV_2_0     0x0u
+#define MHU_MINOR_REV_2_1     0x1u
+
+struct _mhu_v2_x_send_ch_window_t {
+    /* Offset: 0x00 (R/ ) Channel Status */
+    volatile uint32_t ch_st;
+    /* Offset: 0x04 (R/ ) Reserved */
+    volatile uint32_t reserved_0;
+    /* Offset: 0x08 (R/ ) Reserved */
+    volatile uint32_t reserved_1;
+    /* Offset: 0x0C ( /W) Channel Set */
+    volatile uint32_t ch_set;
+    /* Offset: 0x10 (R/ ) Channel Interrupt Status (Reserved in 2.0) */
+    volatile uint32_t ch_int_st;
+    /* Offset: 0x14 ( /W) Channel Interrupt Clear  (Reserved in 2.0) */
+    volatile uint32_t ch_int_clr;
+    /* Offset: 0x18 (R/W) Channel Interrupt Enable (Reserved in 2.0) */
+    volatile uint32_t ch_int_en;
+    /* Offset: 0x1C (R/ ) Reserved */
+    volatile uint32_t reserved_2;
+};
+
+struct _mhu_v2_x_send_frame_t {
+    /* Offset: 0x000 ( / ) Sender Channel Window 0 -123 */
+    struct _mhu_v2_x_send_ch_window_t send_ch_window[_MHU_V2_X_MAX_CHANNELS];
+    /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
+    volatile uint32_t mhu_cfg;
+    /* Offset: 0xF84 (R/W) Response Configuration */
+    volatile uint32_t resp_cfg;
+    /* Offset: 0xF88 (R/W) Access Request */
+    volatile uint32_t access_request;
+    /* Offset: 0xF8C (R/ ) Access Ready */
+    volatile uint32_t access_ready;
+    /* Offset: 0xF90 (R/ ) Interrupt Status */
+    volatile uint32_t int_st;
+    /* Offset: 0xF94 ( /W) Interrupt Clear */
+    volatile uint32_t int_clr;
+    /* Offset: 0xF98 (R/W) Interrupt Enable */
+    volatile uint32_t int_en;
+    /* Offset: 0xF9C (R/ ) Reserved */
+    volatile uint32_t reserved_0;
+    /* Offset: 0xFA0 (R/W) Channel Combined Interrupt Stat (Reserved in 2.0) */
+    volatile uint32_t ch_comb_int_st[_MHU_V2_1_MAX_CHCOMB_INT];
+    /* Offset: ‭0xFC4‬ (R/ ) Reserved */
+    volatile uint32_t reserved_1[6];
+    /* Offset: 0xFC8 (R/ ) Implementer Identification Register */
+    volatile uint32_t iidr;
+    /* Offset: 0xFCC (R/ ) Architecture Identification Register */
+    volatile uint32_t aidr;
+    /* Offset: 0xFD0 (R/ )  */
+    volatile uint32_t pid_1[4];
+    /* Offset: 0xFE0 (R/ )  */
+    volatile uint32_t pid_0[4];
+    /* Offset: 0xFF0 (R/ )  */
+    volatile uint32_t cid[4];
+};
+
+struct _mhu_v2_x_rec_ch_window_t {
+    /* Offset: 0x00 (R/ ) Channel Status */
+    volatile uint32_t ch_st;
+    /* Offset: 0x04 (R/ ) Channel Status Masked */
+    volatile uint32_t ch_st_msk;
+    /* Offset: 0x08 ( /W) Channel Clear */
+    volatile uint32_t ch_clr;
+    /* Offset: 0x0C (R/ ) Reserved */
+    volatile uint32_t reserved_0;
+    /* Offset: 0x10 (R/ ) Channel Mask Status */
+    volatile uint32_t ch_msk_st;
+    /* Offset: 0x14 ( /W) Channel Mask Set */
+    volatile uint32_t ch_msk_set;
+    /* Offset: 0x18 ( /W) Channel Mask Clear */
+    volatile uint32_t ch_msk_clr;
+    /* Offset: 0x1C (R/ ) Reserved */
+    volatile uint32_t reserved_1;
+};
+
+struct _mhu_v2_x_recv_frame_t {
+    /* Offset: 0x000 ( / ) Receiver Channel Window 0 -123 */
+    struct _mhu_v2_x_rec_ch_window_t rec_ch_window[_MHU_V2_X_MAX_CHANNELS];
+    /* Offset: 0xF80 (R/ ) Message Handling Unit Configuration */
+    volatile uint32_t mhu_cfg;
+    /* Offset: 0xF84 (R/ ) Reserved */
+    volatile uint32_t reserved_0[3];
+    /* Offset: 0xF90 (R/ ) Interrupt Status (Reserved in 2.0) */
+    volatile uint32_t int_st;
+    /* Offset: 0xF94 (R/ ) Interrupt Clear  (Reserved in 2.0) */
+    volatile uint32_t int_clr;
+    /* Offset: 0xF98 (R/W) Interrupt Enable (Reserved in 2.0) */
+    volatile uint32_t int_en;
+    /* Offset: 0xF9C (R/ ) Reserved  */
+    volatile uint32_t reserved_1;
+    /* Offset: 0xFA0 (R/ ) Channel Combined Interrupt Stat (Reserved in 2.0) */
+    volatile uint32_t ch_comb_int_st[_MHU_V2_1_MAX_CHCOMB_INT];
+    /* Offset: 0xFB0 (R/ ) Reserved */
+    volatile uint32_t reserved_2[6];
+    /* Offset: 0xFC8 (R/ ) Implementer Identification Register */
+    volatile uint32_t iidr;
+    /* Offset: 0xFCC (R/ ) Architecture Identification Register */
+    volatile uint32_t aidr;
+    /* Offset: 0xFD0 (R/ )  */
+    volatile uint32_t pid_1[4];
+    /* Offset: 0xFE0 (R/ )  */
+    volatile uint32_t pid_0[4];
+    /* Offset: 0xFF0 (R/ )  */
+    volatile uint32_t cid[4];
+};
+
+union _mhu_v2_x_frame_t {
+    struct _mhu_v2_x_send_frame_t send_frame;
+    struct _mhu_v2_x_recv_frame_t recv_frame;
+};
+
+enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
+     enum mhu_v2_x_supported_revisions rev)
+{
+    uint32_t AIDR = 0;
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if (dev->is_initialized) {
+        return MHU_V_2_X_ERR_ALREADY_INIT;
+    }
+
+    if (rev == MHU_REV_READ_FROM_HW) {
+        /* Read revision from HW */
+        if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+            AIDR = p_mhu->recv_frame.aidr;
+        } else {
+            AIDR = p_mhu->send_frame.aidr;
+        }
+
+        /* Get bits 7:4 to read major revision */
+        if ( ((AIDR >> 4) & 0b1111) != MHU_MAJOR_REV_V2) {
+            /* Unsupported MHU version */
+            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+        } /* No need to save major version, driver only supports MHUv2 */
+
+        /* Get bits 3:0 to read minor revision */
+        dev->subversion = AIDR & 0b1111;
+
+        if (dev->subversion != MHU_MINOR_REV_2_0 &&
+            dev->subversion != MHU_MINOR_REV_2_1) {
+            /* Unsupported subversion */
+            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+        }
+    } else {
+        /* Revisions were provided by caller */
+        if (rev == MHU_REV_2_0) {
+            dev->subversion = MHU_MINOR_REV_2_0;
+        } else if (rev == MHU_REV_2_1) {
+            dev->subversion = MHU_MINOR_REV_2_1;
+        } else {
+            /* Unsupported subversion */
+            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+        }/* No need to save major version, driver only supports MHUv2 */
+    }
+
+    dev->is_initialized = true;
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+uint32_t mhu_v2_x_get_num_channel_implemented(const struct mhu_v2_x_dev_t *dev)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+        return (SEND_FRAME(p_mhu))->mhu_cfg;
+    } else {
+        return (RECV_FRAME(p_mhu))->mhu_cfg;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
+     uint32_t channel, uint32_t val)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+        (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_set = val;
+        return MHU_V_2_X_ERR_NONE;
+    } else {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
+     uint32_t channel)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+        (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_clr = UINT32_MAX;
+        return MHU_V_2_X_ERR_NONE;
+    } else {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+        *value = (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_st;
+        return MHU_V_2_X_ERR_NONE;
+    } else {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+        (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_set = mask;
+        return MHU_V_2_X_ERR_NONE;
+    } else {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+        (RECV_FRAME(p_mhu))->rec_ch_window[channel].ch_msk_clr = mask;
+        return MHU_V_2_X_ERR_NONE;
+    } else {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_enable(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if (dev->subversion == MHU_MINOR_REV_2_1) {
+        return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+    }
+
+    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+        (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_int_en = ENABLE;
+        return MHU_V_2_X_ERR_NONE;
+    } else {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_disable(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if (dev->subversion == MHU_MINOR_REV_2_1) {
+        return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+    }
+
+    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+        (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_int_en = DISABLE;
+        return MHU_V_2_X_ERR_NONE;
+    } else {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_clear(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if (dev->subversion == MHU_MINOR_REV_2_1) {
+        return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+    }
+
+    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+        (SEND_FRAME(p_mhu))->send_ch_window[channel].ch_int_clr = CLEAR_INTR;
+        return MHU_V_2_X_ERR_NONE;
+    } else {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
+     const struct mhu_v2_x_dev_t *dev)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+
+    (SEND_FRAME(p_mhu))->access_request = ENABLE;
+
+    while ( !((SEND_FRAME(p_mhu))->access_ready) ) {
+        /* Wait in a loop for access ready signal to be high */
+        ;
+    }
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_close_transfer(const struct mhu_v2_x_dev_t *dev)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+
+    (SEND_FRAME(p_mhu))->access_request = DISABLE;
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_get_access_request(
+     const struct mhu_v2_x_dev_t *dev, uint32_t *val)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+
+    *val = (SEND_FRAME(p_mhu))->access_request;
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_set_access_request(
+     const struct mhu_v2_x_dev_t *dev)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+
+    (SEND_FRAME(p_mhu))->access_request = ENABLE;
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_reset_access_request(
+     const struct mhu_v2_x_dev_t *dev)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+
+    (SEND_FRAME(p_mhu))->access_request = DISABLE;
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_get_access_ready(
+     const struct mhu_v2_x_dev_t *dev, uint32_t *val)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame != MHU_V2_X_SENDER_FRAME) {
+        return MHU_V_2_X_ERR_INVALID_ARG;
+    }
+
+    *val = (SEND_FRAME(p_mhu))->access_ready;
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+uint32_t mhu_v2_x_get_interrupt_status(const struct mhu_v2_x_dev_t *dev)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+        return (SEND_FRAME(p_mhu))->int_st;
+    } else {
+        return (RECV_FRAME(p_mhu))->int_st;
+    }
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_interrupt_enable(
+     const struct mhu_v2_x_dev_t *dev, uint32_t mask)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if (dev->subversion == MHU_MINOR_REV_2_0) {
+        if (mask & MHU_2_1_INTR_CHCOMB_MASK) {
+            /* Combined channel IRQ is not present in v2.0 */
+            return MHU_V_2_X_ERR_INVALID_ARG;
+        }
+
+        if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+            /* Only sender frame has these registers */
+            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+        }
+    }
+
+    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+        (SEND_FRAME(p_mhu))->int_en |= mask;
+    } else {
+        (RECV_FRAME(p_mhu))->int_en |= mask;
+    }
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_interrupt_disable(
+     const struct mhu_v2_x_dev_t *dev, uint32_t mask)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if (dev->subversion == MHU_MINOR_REV_2_0) {
+        if (mask & MHU_2_1_INTR_CHCOMB_MASK) {
+            /* Combined channel IRQ is not present in v2.0 */
+            return MHU_V_2_X_ERR_INVALID_ARG;
+        }
+
+        if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+            /* Only sender frame has these registers */
+            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+        }
+    }
+
+    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+        (SEND_FRAME(p_mhu))->int_en &= ~mask;
+    } else {
+        (RECV_FRAME(p_mhu))->int_en &= ~mask;
+    }
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+enum mhu_v2_x_error_t mhu_v2_x_interrupt_clear(
+     const struct mhu_v2_x_dev_t *dev, uint32_t mask)
+{
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if (dev->subversion == MHU_MINOR_REV_2_0) {
+        if (mask & MHU_2_1_INTR_CHCOMB_MASK) {
+            /* Combined channel IRQ is not present in v2.0 */
+            return MHU_V_2_X_ERR_INVALID_ARG;
+        }
+
+        if (dev->frame == MHU_V2_X_RECEIVER_FRAME) {
+            /* Only sender frame has these registers */
+            return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+        }
+    }
+
+    if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+        (SEND_FRAME(p_mhu))->int_clr = mask;
+    } else {
+        (RECV_FRAME(p_mhu))->int_clr = mask;
+    }
+
+    return MHU_V_2_X_ERR_NONE;
+}
+
+enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
+     const struct mhu_v2_x_dev_t *dev, uint32_t *channel)
+{
+    uint32_t i, j, status;
+    union _mhu_v2_x_frame_t *p_mhu = (union _mhu_v2_x_frame_t *)dev->base;
+
+    if ( !(dev->is_initialized) ) {
+        return MHU_V_2_X_ERR_NOT_INIT;
+    }
+
+    if (dev->subversion != MHU_MINOR_REV_2_1) {
+        /* Feature is only supported in MHU v2.1 */
+        return MHU_V_2_X_ERR_UNSUPPORTED_VERSION;
+    }
+
+    for(i = 0; i < _MHU_V2_1_MAX_CHCOMB_INT; i++) {
+        if(dev->frame == MHU_V2_X_SENDER_FRAME) {
+            status = (SEND_FRAME(p_mhu))->ch_comb_int_st[i];
+        } else {
+            status = (RECV_FRAME(p_mhu))->ch_comb_int_st[i];
+        }
+
+        for(j = 0; j < CH_PER_CH_COMB; j++) {
+            if (status & ENABLE) {
+                *channel = (j + (i * CH_PER_CH_COMB));
+                return MHU_V_2_X_ERR_NONE;
+            }
+            status >>= 1;
+        }
+    }
+
+    return MHU_V_2_X_ERR_GENERAL;
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/Native_Driver/mhu_v2_x.h b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/mhu_v2_x.h
new file mode 100644
index 0000000..08e0dd3
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/mhu_v2_x.h
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 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.
+ * 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 mhu_v2_x.h
+ * \brief Driver for Arm MHU v2.0 and v2.1
+ */
+
+#ifndef __MHU_V2_X_H__
+#define __MHU_V2_X_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MHU_2_X_INTR_NR2R_OFF             (0x0u)
+#define MHU_2_X_INTR_R2NR_OFF             (0x1u)
+#define MHU_2_1_INTR_CHCOMB_OFF           (0x2u)
+
+#define MHU_2_X_INTR_NR2R_MASK            (0x1u << MHU_2_X_INTR_NR2R_OFF)
+#define MHU_2_X_INTR_R2NR_MASK            (0x1u << MHU_2_X_INTR_R2NR_OFF)
+#define MHU_2_1_INTR_CHCOMB_MASK          (0x1u << MHU_2_1_INTR_CHCOMB_OFF)
+
+enum mhu_v2_x_frame_t {
+    MHU_V2_X_SENDER_FRAME   = 0x0u,
+    MHU_V2_X_RECEIVER_FRAME = 0x1u,
+};
+
+enum mhu_v2_x_supported_revisions {
+     MHU_REV_READ_FROM_HW = 0,
+     MHU_REV_2_0,
+     MHU_REV_2_1,
+};
+
+struct mhu_v2_x_dev_t {
+    const uint32_t base;
+    enum mhu_v2_x_frame_t frame;
+    uint32_t subversion;    /*!< Hardware subversion: v2.X */
+    bool is_initialized;    /*!< Indicates if the MHU driver
+                             *   is initialized and enabled
+                             */
+};
+
+/**
+ * \brief MHU v2 error enumeration types.
+ */
+enum mhu_v2_x_error_t {
+    MHU_V_2_X_ERR_NONE                =  0,
+    MHU_V_2_X_ERR_NOT_INIT            = -1,
+    MHU_V_2_X_ERR_ALREADY_INIT        = -2,
+    MHU_V_2_X_ERR_UNSUPPORTED_VERSION = -3,
+    MHU_V_2_X_ERR_INVALID_ARG         = -4,
+    MHU_V_2_X_ERR_GENERAL             = -5
+};
+
+/**
+ * \brief Initializes the driver
+ *
+ * \param[in] dev   MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] rev   MHU revision (if can't be identified from HW)
+ *
+ * Reads the MHU hardware version
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note MHU revision only has to be specified when versions can't be read
+ *       from HW (ARCH_MAJOR_REV reg reads as 0x0).
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_driver_init(struct mhu_v2_x_dev_t *dev,
+     enum mhu_v2_x_supported_revisions rev);
+
+/**
+ * \brief Returns the number of channels implemented.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ *
+ * Returns the number of channels implemented.
+ *
+ * \return Returns the number of channels implemented.
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+uint32_t mhu_v2_x_get_num_channel_implemented(
+         const struct mhu_v2_x_dev_t *dev);
+
+/**
+ * \brief Sends the value over a channel.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] channel     Channel to send the value over.
+ * \param[in] val         Value to send.
+ *
+ * Sends the value over a channel.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_send(const struct mhu_v2_x_dev_t *dev,
+     uint32_t channel, uint32_t val);
+
+/**
+ * \brief Clears the channel after the value is send over it.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] channel     Channel to clear.
+ *
+ * Clears the channel after the value is send over it.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_clear(const struct mhu_v2_x_dev_t *dev,
+     uint32_t channel);
+
+/**
+ * \brief Receives the value over a channel.
+ *
+ * \param[in]  dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in]  channel     Channel to receive the value from.
+ * \param[out] value       Pointer to variable that will store the value.
+ *
+ * Receives the value over a channel.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_receive(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t *value);
+
+/**
+ * \brief Sets bits in the Channel Mask.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] channel     Which channel's mask to set.
+ * \param[in] mask        Mask to be set over a receiver frame.
+ *
+ * Sets bits in the Channel Mask.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_set(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
+
+/**
+ * \brief Clears bits in the Channel Mask.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] channel     Which channel's mask to clear.
+ * \param[in] mask        Mask to be clear over a receiver frame.
+ *
+ * Clears bits in the Channel Mask.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_mask_clear(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel, uint32_t mask);
+
+/**
+ * \brief Enables the Channel interrupt.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] channel     Which channel's interrupt to enable.
+ *
+ * Enables the Channel clear interrupt.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_enable(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel);
+
+/**
+ * \brief Disables the Channel interrupt.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] channel     Which channel's interrupt to disable.
+ *
+ * Disables the Channel interrupt.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_disable(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel);
+
+/**
+ * \brief Cleares the Channel interrupt.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] channel     Which channel's interrupt to clear.
+ *
+ * Cleares the Channel interrupt.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ * \note This function doesn't check if channel is implemented.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_channel_interrupt_clear(
+     const struct mhu_v2_x_dev_t *dev, uint32_t channel);
+
+/**
+ * \brief Initiates a MHU transfer with the handshake signals.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ *
+ * Initiates a MHU transfer with the handshake signals in a blocking mode.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_initiate_transfer(
+     const struct mhu_v2_x_dev_t *dev);
+
+/**
+ * \brief Closes a MHU transfer with the handshake signals.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ *
+ * Closes a MHU transfer with the handshake signals in a blocking mode.
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_close_transfer(
+     const struct mhu_v2_x_dev_t *dev);
+
+/**
+ * \brief Returns the value of access request signal.
+ *
+ * \param[in]  dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[out] val         Pointer to variable that will store the value.
+ *
+ * For more information please read the MHU v2 user guide
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_get_access_request(
+     const struct mhu_v2_x_dev_t *dev, uint32_t *val);
+
+/**
+ * \brief Sets the value of access request signal to high.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ *
+ * For more information please read the MHU v2 user guide
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_set_access_request(
+     const struct mhu_v2_x_dev_t *dev);
+
+/**
+ * \brief Sets the value of access request signal to low.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ *
+ * For more information please read the MHU v2 user guide
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_reset_access_request(
+     const struct mhu_v2_x_dev_t *dev);
+
+/**
+ * \brief Returns the value of access ready signal.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[out] val        Pointer to variable that will store the value.
+ *
+ * For more information please read the MHU v2 user guide
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_get_access_ready(
+     const struct mhu_v2_x_dev_t *dev, uint32_t *val);
+
+/**
+ * \brief Returns the MHU interrupt status.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ *
+ * \return Interrupt status register value. Masking is needed for individual
+ *         interrupts.
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+uint32_t mhu_v2_x_get_interrupt_status(const struct mhu_v2_x_dev_t *dev);
+
+/**
+ * \brief Enables MHU interrupts.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] mask        Bit mask for enabling/disabling interrupts
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_interrupt_enable(
+     const struct mhu_v2_x_dev_t *dev, uint32_t mask);
+
+/**
+ * \brief Disables MHU interrupts.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] mask        Bit mask for enabling/disabling interrupts
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_interrupt_disable(
+     const struct mhu_v2_x_dev_t *dev, uint32_t mask);
+
+/**
+ * \brief Clears MHU interrupts.
+ *
+ * \param[in] dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[in] mask        Bit mask for clearing interrupts
+ *
+ * \return Returns mhu_v2_x_error_t error code
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_x_interrupt_clear(
+     const struct mhu_v2_x_dev_t *dev, uint32_t mask);
+
+/**
+ * \brief Returns the first channel number whose interrupt bit is high.
+ *
+ * \param[in]  dev         MHU device struct \ref mhu_v2_x_dev_t
+ * \param[out] channel     Pointer to variable that will have the channel value.
+ *
+ * \return Returns the first channel number whose interrupt bit is high.
+ * \return Returns mhu_v2_x_error_t error code.
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum mhu_v2_x_error_t mhu_v2_1_get_ch_interrupt_num(
+     const struct mhu_v2_x_dev_t *dev, uint32_t *channel);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MHU_V2_X_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/Native_Driver/musca_b1_eflash_drv.c b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/musca_b1_eflash_drv.c
new file mode 100644
index 0000000..ccfde9c
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/musca_b1_eflash_drv.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2018-2019 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 musca_b1_eflash_drv.c
+ *
+ * \brief Process specifinc implementation of GFC100 flash controller for
+ *        Musca B1 board.
+ */
+
+#include "gfc100_process_spec_api.h"
+
+void gfc100_proc_spec_set_eflash_timing(uint32_t reg_map_base,
+                                        uint32_t sys_clk)
+{
+    (void)sys_clk;
+
+    *(uint32_t *)reg_map_base = 0x11082801;
+    *(uint32_t *)(reg_map_base + 4U) = 0x64050208;
+    *(uint32_t *)(reg_map_base + 8U) = 0xa0a0a08;
+}
+
+uint32_t gfc100_proc_spec_get_eflash_word_width(uint32_t reg_map_base)
+{
+    (void)reg_map_base;
+
+    return 128U;
+}
+
+uint32_t gfc100_proc_spec_get_eflash_size(uint32_t reg_map_base)
+{
+    (void)reg_map_base;
+
+    return 0x200000U;
+}
+
+uint32_t gfc100_proc_spec_get_eflash_page_size(uint32_t reg_map_base)
+{
+    (void)reg_map_base;
+
+    return 0x4000;
+}
+
+uint32_t gfc100_proc_spec_get_num_of_info_pages(uint32_t reg_map_base)
+{
+    (void)reg_map_base;
+
+    return 3U;
+}
+
+uint32_t gfc100_proc_spec_get_error_cause(uint32_t reg_map_base)
+{
+    return *(uint32_t *)(reg_map_base + 0x18);
+}
+
diff --git a/platform/ext/target/musca_b1_secure_enclave/Native_Driver/qspi_ip6514e_drv.c b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/qspi_ip6514e_drv.c
new file mode 100644
index 0000000..bb13a42
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/qspi_ip6514e_drv.c
@@ -0,0 +1,755 @@
+/*
+ * Copyright (c) 2018-2019 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 <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+/* Use memcpy */
+#include <string.h>
+
+#include "qspi_ip6514e_drv.h"
+
+/** Setter bit manipulation macro */
+#define SET_BIT(WORD, BIT_INDEX) ((WORD) |= (1U << (BIT_INDEX)))
+/** Clearing bit manipulation macro */
+#define CLR_BIT(WORD, BIT_INDEX) ((WORD) &= ~(1U << (BIT_INDEX)))
+/** Getter bit manipulation macro */
+#define GET_BIT(WORD, BIT_INDEX) (bool)(((WORD) & (1U << (BIT_INDEX))))
+
+#define WORD_ALIGN_4B_MASK    0x3U /* Mask the first 2 bits */
+#define IS_ADDR_ALIGNED(ADDR) (((uint32_t)(ADDR) & (WORD_ALIGN_4B_MASK)) == 0U)
+
+#define BITS_PER_BYTE               8U
+#define BITS_PER_WORD               32U
+
+#define CFG_READS  true
+#define CFG_WRITES false
+
+#define ARG_NOT_USED     0
+#define ARG_PTR_NOT_USED NULL
+
+#define DATA_REG_NUMBER 2U
+#define DATA_REG_LOWER  0U
+#define DATA_REG_UPPER  1U
+
+#define ERROR_VALUE 0xFFFFFFFFU
+
+/**
+ * \brief QSPI IP6514E register map structure
+ */
+struct _qspi_ip6514e_reg_map_t {
+    volatile uint32_t qspi_cfg;                           /*!< 0x00 (R/W) */
+    volatile uint32_t device_read_inst;                   /*!< 0x04 (R/W) */
+    volatile uint32_t device_write_inst;                  /*!< 0x08 (R/W) */
+    volatile uint32_t hidden1[2];
+    volatile uint32_t device_size;                        /*!< 0x14 (R/W) */
+    volatile uint32_t hidden2[3];
+    volatile uint32_t remap_addr;                         /*!< 0x24 (R/W) */
+    volatile uint32_t hidden3[26];
+    volatile uint32_t flash_cmd_ctrl;                     /*!< 0x90 (R/W) */
+    volatile uint32_t flash_cmd_addr;                     /*!< 0x94 (R/W) */
+    volatile uint32_t hidden4[2];
+    volatile uint32_t flash_cmd_read_data_lower;          /*!< 0xA0 (R/ ) */
+    volatile uint32_t flash_cmd_read_data_upper;          /*!< 0xA4 (R/ ) */
+    volatile uint32_t flash_cmd_write_data_lower;         /*!< 0xA8 (R/W) */
+    volatile uint32_t flash_cmd_write_data_upper;         /*!< 0xAC (R/W) */
+    volatile uint32_t hidden5[2];
+};
+
+/** QSPI Configuration register description (offset 0x00) */
+#define QSPI_CFG_ENABLE_POS            0U
+#define QSPI_CFG_ENABLE_ADDR_REMAP_POS 16U
+#define QSPI_CFG_BAUD_DIV_POS          19U
+    #define QSPI_CFG_BAUD_DIV_MIN          2U
+    #define QSPI_CFG_BAUD_DIV_MAX          32U
+    #define QSPI_CFG_BAUD_DIV_BITS         4U
+#define QSPI_CFG_IDLE_POS              31U
+
+/**
+ * Device Read/Write Instruction registers description (offset 0x04 and 0x08).
+ * These values are the same for the Device Read Instruction register at offset
+ * 0x04 and the Device Write Instruction register at offset 0x08.
+ */
+#define DEVICE_READ_WRITE_INST_OPCODE_POS        0U
+#define DEVICE_READ_INST_INST_TYPE_POS           8U /* Only applies to the Read
+                                                     * register. */
+#define DEVICE_READ_WRITE_INST_ADDR_TYPE_POS     12U
+#define DEVICE_READ_WRITE_INST_DATA_TYPE_POS     16U
+    #define DEVICE_READ_WRITE_INST_MODE_QSPI         2U
+    #define DEVICE_READ_WRITE_INST_MODE_DSPI         1U
+    #define DEVICE_READ_WRITE_INST_MODE_SPI          0U
+    #define DEVICE_READ_WRITE_INST_MODE_BITS         2U
+#define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_POS  24U
+    #define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_BITS 5U
+    #define DEVICE_READ_WRITE_INST_DUMMY_CYCLES_MAX  31U
+
+/** Device Size Configuration register description (offset 0x14) */
+#define DEVICE_SIZE_ADDR_BYTES_POS  0U
+    #define DEVICE_SIZE_ADDR_BYTES_MIN  1U
+    #define DEVICE_SIZE_ADDR_BYTES_MAX  16U
+    #define DEVICE_SIZE_ADDR_BYTES_BITS 4U
+#define DEVICE_SIZE_PAGE_BYTES_POS  4U
+    #define DEVICE_SIZE_PAGE_BYTES_MAX  4095U
+    #define DEVICE_SIZE_PAGE_BYTES_BITS 12U
+
+/** Flash Command Control register description (offset 0x90) */
+#define FLASH_CMD_CTRL_EXECUTE_POS        0U
+#define FLASH_CMD_CTRL_BUSY_POS           1U
+#define FLASH_CMD_CTRL_DUMMY_CYCLES_POS   7U
+    #define FLASH_CMD_CTRL_DUMMY_CYCLES_MAX   31U
+    #define FLASH_CMD_CTRL_DUMMY_CYCLES_BITS  5U
+#define FLASH_CMD_CTRL_WRITE_BYTES_POS    12U
+    #define FLASH_CMD_CTRL_WRITE_BYTES_MAX    8U
+    #define FLASH_CMD_CTRL_WRITE_BYTES_BITS   3U
+#define FLASH_CMD_CTRL_WRITE_ENABLE_POS   15U
+#define FLASH_CMD_CTRL_ADDR_BYTES_POS     16U
+    #define FLASH_CMD_CTRL_ADDR_BYTES_MAX     4U
+    #define FLASH_CMD_CTRL_ADDR_BYTES_BITS    2U
+#define FLASH_CMD_CTRL_ADDR_ENABLE_POS    19U
+#define FLASH_CMD_CTRL_READ_BYTES_POS     20U
+    #define FLASH_CMD_CTRL_READ_BYTES_MAX     8U
+    #define FLASH_CMD_CTRL_READ_BYTES_BITS    3U
+#define FLASH_CMD_CTRL_READ_ENABLE_POS    23U
+#define FLASH_CMD_CTRL_OPCODE_POS         24U
+
+/** Default register values of the QSPI Flash controller */
+#define QSPI_CFG_REG_RESET_VALUE              (0x80080080U)
+#define DEVICE_READ_INSTR_REG_RESET_VALUE     (0x080220EBU)
+#define DEVICE_WRITE_INSTR_REG_RESET_VALUE    (0x00000002U)
+#define DEVICE_SIZE_CFG_REG_RESET_VALUE       (0x00101002U)
+#define REMAP_ADDR_REG_RESET_VALUE            (0x00000000U)
+#define FLASH_CMD_CONTROL_REG_RESET_VALUE     (0x00000000U)
+#define FLASH_CMD_ADDRESS_REG_RESET_VALUE     (0x00000000U)
+#define FLASH_CMD_WRITE_DATA_REG_RESET_VALUE  (0x00000000U)
+
+/**
+ * \brief Change specific bits in a 32 bits word.
+ *
+ * \param[in,out] word         Pointer of the word to change
+ * \param[in]     bits         bits_length bits to put at bits_pos in the word
+ *                             pointed
+ * \param[in]     bits_length  Number of bits to change
+ * \param[in]     bits_pos     Position of the bits to change
+ *
+ * \note This function will do nothing if the parameters given are incorret:
+ *         * word is NULL
+ *         * bits_length + bits_pos > 32
+ *         * bits_length is 0
+ */
+static void change_bits_in_word(volatile uint32_t *word,
+                                uint32_t bits,
+                                uint32_t bits_length,
+                                uint32_t bits_pos)
+{
+    uint32_t mask;
+
+    if ((word == NULL) ||
+        ((bits_length + bits_pos) > BITS_PER_WORD) ||
+        (bits_length == 0U)) {
+        /* Silently fail */
+        return;
+    }
+
+    /* Change all the bits */
+    if (bits_length == BITS_PER_WORD) {
+        *word = bits;
+        return;
+    }
+
+    mask = ((1U << bits_length) - 1);
+    /*
+     * We change the bits in three steps:
+     *   - clear bits_length bits with zeroes at bits_pos in the word
+     *   - mask bits in case it contains more than bits_length bits
+     *   - set the new bits in the cleared word
+     * Because the data pointed by word is only read once, the data will still
+     * be coherent after an interruption that changes it.
+     */
+    *word = ((*word & ~(mask << bits_pos)) | ((bits & mask) << bits_pos));
+}
+
+/**
+ * \brief Configure reads or writes commands for direct operations.
+ *
+ * \param[in] dev             QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ * \param[in] opcode          Read/write opcode that will be used for every
+ *                            direct read/write
+ * \param[in] dummy_cycles    Number of dummy cycles to wait before triggering
+ *                            the command, this value must be between 0 and 31
+ *                            (both included)
+ * \param[in] is_reads_cfg    true to configure direct reads, false to configure
+ *                            direct writes
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note The QSPI controller should be idle before calling this function.
+ */
+static enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads_writes(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint8_t opcode,
+                                                 uint32_t dummy_cycles,
+                                                 bool is_reads_cfg)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+    /*
+     * Select the good register address if we want to configure reads or writes.
+     */
+    volatile uint32_t *device_read_write_inst_reg = is_reads_cfg ?
+                                                  &(reg_map->device_read_inst) :
+                                                  &(reg_map->device_write_inst);
+    uint32_t device_read_write_inst_reg_copy = *device_read_write_inst_reg;
+
+    /*
+     * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+     * all low level synchronization has been done.
+     */
+    while(!qspi_ip6514e_is_idle(dev));
+
+    if (dummy_cycles > DEVICE_READ_WRITE_INST_DUMMY_CYCLES_MAX) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    change_bits_in_word(&device_read_write_inst_reg_copy,
+                        (uint32_t)opcode,
+                        BITS_PER_BYTE,
+                        DEVICE_READ_WRITE_INST_OPCODE_POS);
+    change_bits_in_word(&device_read_write_inst_reg_copy,
+                        dummy_cycles,
+                        DEVICE_READ_WRITE_INST_DUMMY_CYCLES_BITS,
+                        DEVICE_READ_WRITE_INST_DUMMY_CYCLES_POS);
+
+    *device_read_write_inst_reg = device_read_write_inst_reg_copy;
+
+    return QSPI_IP6514E_ERR_NONE;
+}
+
+/**
+ * \brief Given the public SPI mode enumeration, returns the private value it
+ *        maps to in the register field.
+ *
+ * \param[in] spi_mode Read/write opcode that will be used for every direct
+ *            read/write
+ *
+ * \return Return the correct DEVICE_READ_WRITE_INST_MODE value.
+ */
+static uint32_t spi_mode_field_value(enum qspi_ip6514e_spi_mode_t spi_mode)
+{
+    switch (spi_mode) {
+        case QSPI_IP6514E_SPI_MODE:
+            return DEVICE_READ_WRITE_INST_MODE_SPI;
+        case QSPI_IP6514E_DSPI_MODE:
+            return DEVICE_READ_WRITE_INST_MODE_DSPI;
+        case QSPI_IP6514E_QSPI_MODE:
+            return DEVICE_READ_WRITE_INST_MODE_QSPI;
+        default:
+            return ERROR_VALUE;
+    }
+}
+
+bool qspi_ip6514e_is_idle(struct qspi_ip6514e_dev_t* dev)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+
+    return GET_BIT(reg_map->qspi_cfg, QSPI_CFG_IDLE_POS);
+}
+
+bool qspi_ip6514e_is_enabled(struct qspi_ip6514e_dev_t* dev)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+
+    return GET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS);
+}
+
+void qspi_ip6514e_disable(struct qspi_ip6514e_dev_t* dev)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+
+    CLR_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS);
+}
+
+void qspi_ip6514e_enable(struct qspi_ip6514e_dev_t* dev)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+
+    SET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_POS);
+}
+
+enum qspi_ip6514e_error_t qspi_ip6514e_set_baud_rate_div(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint32_t div)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+
+    /*
+     * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+     * all low level synchronization has been done.
+     */
+    while(!qspi_ip6514e_is_idle(dev));
+
+    /* div should be an even number. */
+    if (((div & 1U) == 1) ||
+        (div < QSPI_CFG_BAUD_DIV_MIN) ||
+        (div > QSPI_CFG_BAUD_DIV_MAX)) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    /*
+     * The div value (between 2 and 32) needs to be stored in the register on a
+     * 4 bits field.
+     */
+    change_bits_in_word(&(reg_map->qspi_cfg),
+                        (div / 2) - 1,
+                        QSPI_CFG_BAUD_DIV_BITS,
+                        QSPI_CFG_BAUD_DIV_POS);
+
+    return QSPI_IP6514E_ERR_NONE;
+}
+
+enum qspi_ip6514e_error_t qspi_ip6514e_set_spi_mode(
+                                         struct qspi_ip6514e_dev_t* dev,
+                                         enum qspi_ip6514e_spi_mode_t inst_type,
+                                         enum qspi_ip6514e_spi_mode_t addr_type,
+                                         enum qspi_ip6514e_spi_mode_t data_type)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+    uint32_t inst_spi_mode, addr_spi_mode, data_spi_mode;
+    /*
+     * A local copy of the Device Read Instruction and Device Write Instruction
+     * registers is used to limit APB accesses.
+     */
+    uint32_t device_read_inst_cpy = reg_map->device_read_inst;
+    uint32_t device_write_inst_cpy = reg_map->device_write_inst;
+
+    /*
+     * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+     * all low level synchronization has been done.
+     */
+    while(!qspi_ip6514e_is_idle(dev));
+
+    /*
+     * First check that the instruction mode is not SPI. If that is the case,
+     * the address and data mode register fields become DO NOT CARE.
+     */
+    inst_spi_mode = spi_mode_field_value(inst_type);
+    if (inst_spi_mode == ERROR_VALUE) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+    if (inst_type != QSPI_IP6514E_SPI_MODE) {
+        change_bits_in_word(&(reg_map->device_read_inst),
+                            inst_spi_mode,
+                            DEVICE_READ_WRITE_INST_MODE_BITS,
+                            DEVICE_READ_INST_INST_TYPE_POS);
+        return QSPI_IP6514E_ERR_NONE;
+    }
+
+    /* Now check and set address and data modes. */
+    addr_spi_mode = spi_mode_field_value(addr_type);
+    data_spi_mode = spi_mode_field_value(data_type);
+    if ((addr_spi_mode == ERROR_VALUE) || (data_spi_mode == ERROR_VALUE)) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    /* Change the Device Read Instruction register. */
+    change_bits_in_word(&device_read_inst_cpy,
+                        inst_spi_mode,
+                        DEVICE_READ_WRITE_INST_MODE_BITS,
+                        DEVICE_READ_INST_INST_TYPE_POS);
+    change_bits_in_word(&device_read_inst_cpy,
+                        addr_spi_mode,
+                        DEVICE_READ_WRITE_INST_MODE_BITS,
+                        DEVICE_READ_WRITE_INST_ADDR_TYPE_POS);
+    change_bits_in_word(&device_read_inst_cpy,
+                        data_spi_mode,
+                        DEVICE_READ_WRITE_INST_MODE_BITS,
+                        DEVICE_READ_WRITE_INST_DATA_TYPE_POS);
+
+    /* Change the Device Write Instruction register. */
+    change_bits_in_word(&device_write_inst_cpy,
+                        addr_spi_mode,
+                        DEVICE_READ_WRITE_INST_MODE_BITS,
+                        DEVICE_READ_WRITE_INST_ADDR_TYPE_POS);
+    change_bits_in_word(&device_write_inst_cpy,
+                        data_spi_mode,
+                        DEVICE_READ_WRITE_INST_MODE_BITS,
+                        DEVICE_READ_WRITE_INST_DATA_TYPE_POS);
+
+    /* Save the changes. */
+    reg_map->device_read_inst = device_read_inst_cpy;
+    reg_map->device_write_inst = device_write_inst_cpy;
+
+    return QSPI_IP6514E_ERR_NONE;
+}
+
+enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads(struct qspi_ip6514e_dev_t* dev,
+                                                 uint8_t opcode,
+                                                 uint32_t dummy_cycles)
+{
+    return qspi_ip6514e_cfg_reads_writes(dev, opcode, dummy_cycles, CFG_READS);
+}
+
+enum qspi_ip6514e_error_t qspi_ip6514e_cfg_writes(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint8_t opcode,
+                                                 uint32_t dummy_cycles)
+{
+    return qspi_ip6514e_cfg_reads_writes(dev, opcode, dummy_cycles, CFG_WRITES);
+}
+
+enum qspi_ip6514e_error_t qspi_ip6514e_cfg_page_size(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint32_t page_size)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+
+    /*
+     * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+     * all low level synchronization has been done.
+     */
+    while(!qspi_ip6514e_is_idle(dev));
+
+    if (page_size > DEVICE_SIZE_PAGE_BYTES_MAX) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    change_bits_in_word(&(reg_map->device_size),
+                        page_size,
+                        DEVICE_SIZE_PAGE_BYTES_BITS,
+                        DEVICE_SIZE_PAGE_BYTES_POS);
+
+    return QSPI_IP6514E_ERR_NONE;
+}
+
+enum qspi_ip6514e_error_t qspi_ip6514e_cfg_addr_bytes(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint32_t bytes_number)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+
+    /*
+     * Wait for the Serial Interface and QSPI pipeline to be IDLE when
+     * all low level synchronization has been done.
+     */
+    while(!qspi_ip6514e_is_idle(dev));
+
+    if (bytes_number < DEVICE_SIZE_ADDR_BYTES_MIN ||
+        bytes_number > DEVICE_SIZE_ADDR_BYTES_MAX) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    change_bits_in_word(&(reg_map->device_size),
+                        bytes_number - 1,
+                        DEVICE_SIZE_ADDR_BYTES_BITS,
+                        DEVICE_SIZE_ADDR_BYTES_POS);
+
+
+    return QSPI_IP6514E_ERR_NONE;
+}
+
+void qspi_ip6514e_remap_addr(struct qspi_ip6514e_dev_t* dev, uint32_t offset)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+    /* Save the enable state to restore it after. */
+    bool is_enabled = qspi_ip6514e_is_enabled(dev);
+
+    if (is_enabled) {
+        qspi_ip6514e_disable(dev);
+    }
+
+    reg_map->remap_addr = offset;
+    SET_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_ADDR_REMAP_POS);
+
+    if (is_enabled) {
+        qspi_ip6514e_enable(dev);
+    }
+}
+
+void qspi_ip6514e_disable_remap(struct qspi_ip6514e_dev_t* dev)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+    /* Save the enable state to restore it after. */
+    bool is_enabled = qspi_ip6514e_is_enabled(dev);
+
+    if (is_enabled) {
+        qspi_ip6514e_disable(dev);
+    }
+
+    CLR_BIT(reg_map->qspi_cfg, QSPI_CFG_ENABLE_ADDR_REMAP_POS);
+
+    if (is_enabled) {
+        qspi_ip6514e_enable(dev);
+    }
+}
+
+void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+
+    /* Restore the default value of the QSPI Configuration register. */
+    reg_map->qspi_cfg = QSPI_CFG_REG_RESET_VALUE;
+
+    /* Restore the default value of the Device R/W Instruction registers. */
+    reg_map->device_read_inst = DEVICE_READ_INSTR_REG_RESET_VALUE;
+    reg_map->device_write_inst = DEVICE_WRITE_INSTR_REG_RESET_VALUE;
+
+    /* Restore the default value of the Device Size Configuration register. */
+    reg_map->device_size = DEVICE_SIZE_CFG_REG_RESET_VALUE;
+
+    /* Restore the default value of the Remap Address register. */
+    reg_map->remap_addr = REMAP_ADDR_REG_RESET_VALUE;
+
+    /* Restore the default value of the Flash Command Control register. */
+    reg_map->flash_cmd_ctrl = FLASH_CMD_CONTROL_REG_RESET_VALUE;
+    /* Restore the default value of the Flash Command Address register. */
+    reg_map->flash_cmd_addr = FLASH_CMD_ADDRESS_REG_RESET_VALUE;
+
+    /* Restore the default value of the Flash Command Write Data registers. */
+    reg_map->flash_cmd_write_data_lower = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE;
+    reg_map->flash_cmd_write_data_upper = FLASH_CMD_WRITE_DATA_REG_RESET_VALUE;
+
+    /*
+     * This function does not affect the Flash Command Read Data registers
+     * which are completely Read-Only.
+     */
+}
+
+enum qspi_ip6514e_error_t qspi_ip6514e_send_cmd(struct qspi_ip6514e_dev_t* dev,
+                                                uint8_t opcode,
+                                                void *read_data,
+                                                uint32_t read_len,
+                                                const void *write_data,
+                                                uint32_t write_len,
+                                                uint32_t addr,
+                                                uint32_t addr_bytes_number,
+                                                uint32_t dummy_cycles)
+{
+    struct _qspi_ip6514e_reg_map_t *reg_map =
+                               (struct _qspi_ip6514e_reg_map_t *)dev->cfg->base;
+    /* To limit APB accesses, we set this reg up locally before */
+    uint32_t flash_cmd_ctrl = 0U;
+    bool read_requested = ((read_data != NULL) && (read_len != 0));
+    bool write_requested = ((write_data != NULL) && (write_len != 0));
+    bool addr_requested = (addr_bytes_number != 0);
+    /*
+     * To prevent unaligned and byte or halfbyte accesses to the APB registers,
+     * a word aligned buffer is used to temporary transfer the data before doing
+     * word accesses on these registers from that buffer.
+     */
+    uint32_t data_regs[DATA_REG_NUMBER] = {0};
+
+    if (read_len > FLASH_CMD_CTRL_READ_BYTES_MAX) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    if (write_len > FLASH_CMD_CTRL_WRITE_BYTES_MAX) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    if (addr_bytes_number > FLASH_CMD_CTRL_ADDR_BYTES_MAX) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    if (dummy_cycles > FLASH_CMD_CTRL_DUMMY_CYCLES_MAX) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    if (read_requested && write_requested) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    change_bits_in_word(&flash_cmd_ctrl,
+                        (uint32_t)opcode,
+                        BITS_PER_BYTE,
+                        FLASH_CMD_CTRL_OPCODE_POS);
+
+    /* Enable read if requested */
+    if (read_requested) {
+        SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_READ_ENABLE_POS);
+        change_bits_in_word(&flash_cmd_ctrl,
+                            read_len - 1,
+                            FLASH_CMD_CTRL_READ_BYTES_BITS,
+                            FLASH_CMD_CTRL_READ_BYTES_POS);
+    }
+
+    /* Enable write if requested */
+    if (write_requested) {
+        SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_WRITE_ENABLE_POS);
+        change_bits_in_word(&flash_cmd_ctrl,
+                            write_len - 1,
+                            FLASH_CMD_CTRL_WRITE_BYTES_BITS,
+                            FLASH_CMD_CTRL_WRITE_BYTES_POS);
+
+        if (IS_ADDR_ALIGNED(write_data) && IS_ADDR_ALIGNED(write_len)) {
+            /*
+             * Optimised case when write_data is word aligned and write_len is
+             * 4 or 8.
+             */
+            reg_map->flash_cmd_write_data_lower = *(uint32_t *)write_data;
+            if (write_len == FLASH_CMD_CTRL_WRITE_BYTES_MAX) {
+                reg_map->flash_cmd_write_data_upper =
+                                                  *((uint32_t *)write_data + 1);
+            }
+        } else {
+            /*
+             * data_regs is used as a buffer to only do unaligned access on the
+             * AHB bus and word aligned accesses to the APB registers.
+             */
+            memcpy((void *)data_regs, write_data, write_len);
+            /*
+             * Only write_len bytes will be written even if both data registers
+             * are written.
+             */
+            reg_map->flash_cmd_write_data_lower = data_regs[DATA_REG_LOWER];
+            reg_map->flash_cmd_write_data_upper = data_regs[DATA_REG_UPPER];
+        }
+    }
+
+    /* Enable the address if requested */
+    if (addr_requested) {
+        SET_BIT(flash_cmd_ctrl, FLASH_CMD_CTRL_ADDR_ENABLE_POS);
+        reg_map->flash_cmd_addr = addr;
+        change_bits_in_word(&flash_cmd_ctrl,
+                            addr_bytes_number - 1,
+                            FLASH_CMD_CTRL_ADDR_BYTES_BITS,
+                            FLASH_CMD_CTRL_ADDR_BYTES_POS);
+    }
+
+    /* Put dummy cycles number */
+    change_bits_in_word(&flash_cmd_ctrl,
+                        dummy_cycles,
+                        FLASH_CMD_CTRL_DUMMY_CYCLES_BITS,
+                        FLASH_CMD_CTRL_DUMMY_CYCLES_POS);
+
+    /* Copy the Flash Command Control register and execute the command */
+    reg_map->flash_cmd_ctrl = flash_cmd_ctrl;
+    SET_BIT(reg_map->flash_cmd_ctrl, FLASH_CMD_CTRL_EXECUTE_POS);
+
+    /* Wait for termination */
+    while (GET_BIT(reg_map->flash_cmd_ctrl, FLASH_CMD_CTRL_BUSY_POS));
+
+    /*
+     * Recolt the read data if it was requested. read_len validity has already
+     * been verified at this point.
+     */
+    if (read_requested) {
+        if (IS_ADDR_ALIGNED(read_data) && IS_ADDR_ALIGNED(read_len)) {
+            /*
+             * Optimised case when read_data is word aligned and read_len is
+             * 4 or 8.
+             */
+            *(uint32_t *)read_data = reg_map->flash_cmd_read_data_lower;
+            if (read_len == FLASH_CMD_CTRL_READ_BYTES_MAX) {
+                *((uint32_t *)read_data + 1) =
+                                             reg_map->flash_cmd_read_data_upper;
+            }
+        } else {
+            /*
+             * Only read_len bytes have been written even if both data registers
+             * are written.
+             */
+            data_regs[DATA_REG_LOWER] = reg_map->flash_cmd_read_data_lower;
+            data_regs[DATA_REG_UPPER] = reg_map->flash_cmd_read_data_upper;
+            /*
+             * data_regs is used as a buffer to only do unaligned access on the
+             * AHB bus and word aligned accesses to the APB registers.
+             */
+            memcpy(read_data, (void *)data_regs, read_len);
+        }
+    }
+
+    return QSPI_IP6514E_ERR_NONE;
+}
+
+void qspi_ip6514e_send_simple_cmd(struct qspi_ip6514e_dev_t* dev,
+                                      uint8_t opcode)
+{
+    /*
+     * No read/write data, no address, no dummy cycles.
+     * Given the arguments, this function can not fail.
+     */
+    (void)qspi_ip6514e_send_cmd(dev,
+                                opcode,
+                                ARG_PTR_NOT_USED,
+                                ARG_NOT_USED,
+                                ARG_PTR_NOT_USED,
+                                ARG_NOT_USED,
+                                ARG_NOT_USED,
+                                ARG_NOT_USED,
+                                0);
+}
+
+enum qspi_ip6514e_error_t qspi_ip6514e_send_read_cmd(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint8_t opcode,
+                                                 void *read_data,
+                                                 uint32_t read_len,
+                                                 uint32_t addr,
+                                                 uint32_t addr_bytes_number,
+                                                 uint32_t dummy_cycles)
+{
+    /* Read arguments are expected */
+    if (read_data == ARG_PTR_NOT_USED || read_len == ARG_NOT_USED) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    /* No write data */
+    return qspi_ip6514e_send_cmd(dev,
+                                 opcode,
+                                 read_data,
+                                 read_len,
+                                 ARG_PTR_NOT_USED,
+                                 ARG_NOT_USED,
+                                 addr,
+                                 addr_bytes_number,
+                                 dummy_cycles);
+}
+
+enum qspi_ip6514e_error_t qspi_ip6514e_send_write_cmd(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint8_t opcode,
+                                                 const void *write_data,
+                                                 uint32_t write_len,
+                                                 uint32_t addr,
+                                                 uint32_t addr_bytes_number,
+                                                 uint32_t dummy_cycles)
+{
+    /* Write arguments are expected */
+    if (write_data == ARG_PTR_NOT_USED || write_len == ARG_NOT_USED) {
+        return QSPI_IP6514E_ERR_WRONG_ARGUMENT;
+    }
+
+    /* No read data, no dummy cycles */
+    return qspi_ip6514e_send_cmd(dev,
+                                 opcode,
+                                 ARG_PTR_NOT_USED,
+                                 ARG_NOT_USED,
+                                 write_data,
+                                 write_len,
+                                 addr,
+                                 addr_bytes_number,
+                                 dummy_cycles);
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/Native_Driver/qspi_ip6514e_drv.h b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/qspi_ip6514e_drv.h
new file mode 100644
index 0000000..6992925
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/Native_Driver/qspi_ip6514e_drv.h
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2018 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 qspi_ip6514e_drv.h
+ * \brief Driver for Cadence QSPI Flash Controller IP.
+ *        There are two ways to communicate with the flash memory device:
+ *         - issue AHB requests for direct read and writes in the Flash memory
+ *           mapped address zone. The commands used for those can be configured
+ *           by the driver
+ *         - send a command to the device to access his internal registers and
+ *           do other operations like erasing a sector
+ *        At reset, the QSPI controller will work in a default mode which will
+ *        allow to do basic commands. It should be configured with the
+ *        flash memory device specifications for optimal use for commands and
+ *        direct reads/writes. Here is an example of configuration:
+ *         - send command to activate QSPI mode on the flash memory device
+ *         - send command to change dummy cycles on the flash memory device
+ *         - check if any operation is ungoing
+ *         - disable the QSPI controller
+ *         - change the baud rate divisor
+ *         - activate the QSPI mode on the controller
+ *         - change the dummy cycles number and opcode for reads/writes
+ *         - change the number of bytes per page
+ *         - change the number of address bytes
+ *         - activate the QSPI controller
+ *
+ *        Warning: none of the functions declared here check if the dev
+ *        argument points to NULL.
+ */
+
+#ifndef __QSPI_IP6514E_DRV_H__
+#define __QSPI_IP6514E_DRV_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Cadence QSPI IP6514E error enumeration types
+ */
+enum qspi_ip6514e_error_t {
+    QSPI_IP6514E_ERR_NONE,
+    QSPI_IP6514E_ERR_WRONG_ARGUMENT,
+    QSPI_IP6514E_ERR_CONTROLLER_NOT_DISABLED,
+    QSPI_IP6514E_ERR_READ_IN_PROGRESS,
+    QSPI_IP6514E_ERR_WRITE_IN_PROGRESS,
+    /* Any new error should be added to the enumeration type error of
+     * the corresponding Flash device library as well.
+     */
+};
+
+/**
+ * \brief Cadence QSPI IP6514E SPI modes
+ */
+enum qspi_ip6514e_spi_mode_t {
+    QSPI_IP6514E_SPI_MODE,
+        /*!< Use 1 line for Instruction, Address and Data */
+    QSPI_IP6514E_DSPI_MODE,
+        /*!< Use 2 lines for Instruction, Address and Data */
+    QSPI_IP6514E_QSPI_MODE,
+        /*!< Use 4 lines for Instruction, Address and Data */
+};
+
+/**
+ * \brief Cadence QSPI IP6514E device configuration structure
+ */
+struct qspi_ip6514e_dev_cfg_t {
+    const uint32_t base; /*!< QSPI IP6514E base address */
+    /*
+     * If not all the AHB wires are connected to the QSPI Flash Controller the
+     * driver can still access all of the Flash memory. The bits of this value
+     * should be put to 1 for every wire that is connected. Set it to
+     * 0xFFFFFFFFU if all AHB address wires are connected to the
+     * QSPI Flash Controller.
+     */
+    uint32_t addr_mask;
+};
+
+/**
+ * \brief Cadence QSPI IP6514E device structure
+ */
+struct qspi_ip6514e_dev_t {
+    const struct qspi_ip6514e_dev_cfg_t* const cfg;
+                                              /*!< QSPI IP6514E configuration */
+};
+
+/**
+ * \brief Check if the controller is idle.
+ *
+ * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ *
+ * \return true if the controller is idle, false otherwise.
+ */
+bool qspi_ip6514e_is_idle(struct qspi_ip6514e_dev_t* dev);
+
+/**
+ * \brief Check if the controller is enabled.
+ *
+ * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ *
+ * \return true if the controller is enabled, false otherwise.
+ */
+bool qspi_ip6514e_is_enabled(struct qspi_ip6514e_dev_t* dev);
+
+/**
+ * \brief Disable the QSPI controller.
+ *
+ * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ */
+void qspi_ip6514e_disable(struct qspi_ip6514e_dev_t* dev);
+
+/**
+ * \brief Enable the QSPI controller.
+ *
+ * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ */
+void qspi_ip6514e_enable(struct qspi_ip6514e_dev_t* dev);
+
+/**
+ * \brief Change the baud rate divisor.
+ *
+ * \param[in] dev QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ * \param[in] div Baud rate divisor value. It can only be an even number
+ *                    between 2 and 32 (both included).
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note The QSPI frequency is calculated dividing the QSPI controller clock by
+ *       this divisor. Please check Flash memory device specifications to know
+ *       the maximal frequency that can be used.
+ * \note The QSPI controller should be disabled before calling this function.
+ */
+enum qspi_ip6514e_error_t qspi_ip6514e_set_baud_rate_div(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint32_t div);
+
+/**
+ * \brief Set SPI mode for instruction, address and data.
+ *
+ * \param[in] dev       QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ * \param[in] inst_type SPI mode to use for the instruction part of the command
+ * \param[in] addr_type SPI mode to use for the address part of the command
+ * \param[in] data_type SPI mode to use for the data part of the command
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note The QSPI controller should be idle before calling this function.
+ * \note Changing this setting will affect commands and direct operations.
+ */
+enum qspi_ip6514e_error_t qspi_ip6514e_set_spi_mode(
+                                        struct qspi_ip6514e_dev_t* dev,
+                                        enum qspi_ip6514e_spi_mode_t inst_type,
+                                        enum qspi_ip6514e_spi_mode_t addr_type,
+                                        enum qspi_ip6514e_spi_mode_t data_type);
+
+/**
+ * \brief Configure read commands for direct reads.
+ *
+ * \param[in] dev          QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ * \param[in] opcode       Read opcode that will be used for every direct read
+ * \param[in] dummy_cycles Number of dummy cycles to wait before triggering the
+ *                         command, this value must be between 0 and 31
+ *                         (both included)
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note The QSPI controller should be idle before calling this function.
+ */
+enum qspi_ip6514e_error_t qspi_ip6514e_cfg_reads(struct qspi_ip6514e_dev_t* dev,
+                                                 uint8_t opcode,
+                                                 uint32_t dummy_cycles);
+
+/**
+ * \brief Configure write commands for direct writes.
+ *
+ * \param[in] dev          QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ * \param[in] opcode       Write opcode that will be used for every direct write
+ * \param[in] dummy_cycles Number of dummy cycles to wait before triggering the
+ *                         command, this value must be between 0 and 31
+ *                         (both included)
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note The QSPI controller should be idle before calling this function.
+ */
+enum qspi_ip6514e_error_t qspi_ip6514e_cfg_writes(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint8_t opcode,
+                                                 uint32_t dummy_cycles);
+
+/**
+ * \brief Change the number of bytes per device page.
+ *
+ * \param[in] dev          QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ * \param[in] page_size    Number of bytes per device page, must be between 0
+ *                         and 4095 (both included)
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note The QSPI controller should be idle before calling this function.
+ * \note This function will affect direct reads/writes.
+ */
+enum qspi_ip6514e_error_t qspi_ip6514e_cfg_page_size(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint32_t page_size);
+
+/**
+ * \brief Change the number of device address bytes.
+ *
+ * \param[in] dev          QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ * \param[in] bytes_number Number of device address bytes, must be between 1
+ *                         and 16 (both included)
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note The QSPI controller should be idle before calling this function.
+ * \note This function will affect direct reads/writes.
+ */
+enum qspi_ip6514e_error_t qspi_ip6514e_cfg_addr_bytes(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint32_t bytes_number);
+
+/**
+ * \brief Remap the incoming AHB address with an offset for direct accesses.
+ *
+ * \param[in] dev    QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ * \param[in] offset Offset that will be added to the incoming AHB address to
+ *                   access the Flash memory
+ *
+ * \note This function will only affect direct reads/writes.
+ * \note This function does not check if the resulting address is out of memory
+ *       bounds.
+ */
+void qspi_ip6514e_remap_addr(struct qspi_ip6514e_dev_t* dev, uint32_t offset);
+
+/**
+ * \brief Disable AHB address remapping for direct accesses.
+ *
+ * \param[in] dev    QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ *
+ * \note This function will disable the controller if it is not already
+ *       disabled and enable it again (if it was).
+ * \note This function will only affect direct reads/writes.
+ */
+void qspi_ip6514e_disable_remap(struct qspi_ip6514e_dev_t* dev);
+
+/**
+ * \brief Restore the default value of the QSPI controller registers.
+ *
+ * \param[in] dev    QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ *
+ * \note The QSPI controller should be disabled before calling this function.
+ */
+void qspi_ip6514e_reset_regs(struct qspi_ip6514e_dev_t* dev);
+
+/**
+ * \brief Send a command to the flash memory device using the Software Triggered
+ *        Instruction Generator (STIG).
+ *
+ * \param[in]  dev               QSPI IP6514E device struct
+ *                               \ref qspi_ip6514e_dev_t
+ * \param[in]  opcode            Opcode for the command.
+ * \param[out] read_data         Pointer to a memory zone where the read_len
+ *                               bytes read will be written to. If no data is to
+ *                               be read for the command,
+ *                               this argument should be NULL.
+ * \param[in]  read_len          Number of bytes to read for the command. If
+ *                               no bytes are to be read, use 0 for argument
+ *                               otherwise between 1 and 8 bytes (both
+ *                               included) can be read.
+ * \param[in]  write_data        Pointer to a memory zone where are
+ *                               located the write_len bytes to write for
+ *                               this command. If no bytes are to be written,
+ *                               use NULL as argument.
+ * \param[in]  write_len         Number of bytes to write for the command. If
+ *                               no bytes are to be written, use 0 for
+ *                               argument otherwise between 1 and 8 bytes
+ *                               (both included) can be written.
+ * \param[in]  addr              Address used for the command
+ * \param[in]  addr_bytes_number Number of address bytes for this command.
+ *                               If an address is not needed for the command,
+ *                               use 0 for argument, otherwise between 1 and
+ *                               4 bytes (both included) can be used.
+ * \param[in]  dummy_cycles      Number of dummy cycles required for the
+ *                               command, between 0 and 31 (both included).
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note Check the flash memory device specifications for the possible opcodes
+ *       that can be used and the other informations needed for this function.
+ * \note The SPI mode used for this command is the one set with the
+ *       \ref qspi_ip6514e_activate_qspi_mode function or the default one.
+ */
+enum qspi_ip6514e_error_t qspi_ip6514e_send_cmd(struct qspi_ip6514e_dev_t* dev,
+                                                uint8_t opcode,
+                                                void *read_data,
+                                                uint32_t read_len,
+                                                const void *write_data,
+                                                uint32_t write_len,
+                                                uint32_t addr,
+                                                uint32_t addr_bytes_number,
+                                                uint32_t dummy_cycles);
+
+/**
+ * \brief Send a simple command to the flash memory device using the Software
+ *        Triggered Instruction Generator (STIG) with no data arguments.
+ *        This command can be used for example to send the WRITE ENABLE command.
+ *
+ * \param[in]  dev    QSPI IP6514E device struct \ref qspi_ip6514e_dev_t
+ * \param[in]  opcode Opcode for the command.
+ *
+ * \note Check the flash memory device specifications for the possible opcodes
+ *       that can be used and the other informations needed for this function.
+ * \note The SPI mode used for this command is the one set with the
+ *       \ref qspi_ip6514e_activate_qspi_mode function or the default one.
+ */
+void qspi_ip6514e_send_simple_cmd(struct qspi_ip6514e_dev_t* dev,
+                                  uint8_t opcode);
+
+/**
+ * \brief Send a read command to the flash memory device using the Software
+ *        Triggered Instruction Generator (STIG). This command can be used to
+ *        read Flash memory data or registers.
+ *
+ * \param[in]  dev               QSPI IP6514E device struct
+ *                               \ref qspi_ip6514e_dev_t
+ * \param[in]  opcode            Opcode for the command.
+ * \param[out] read_data         Pointer to a memory zone where the
+ *                               read_len bytes read will be written to.
+ * \param[in]  read_len          Number of bytes to read for the command.
+ *                               Between 1 and 8 bytes (both included) can be
+ *                               read.
+ * \param[in]  addr              Address used for the command
+ * \param[in]  addr_bytes_number Number of address bytes for this command.
+ *                               If an address is not needed for the command,
+ *                               use 0 for argument, otherwise between 1 and
+ *                               4 bytes (both included) can be used.
+ * \param[in]  dummy_cycles      Number of dummy cycles required for the
+ *                               command, between 0 and 31 (both included).
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note Check the flash memory device specifications for the possible opcodes
+ *       that can be used and the other informations needed for this function.
+ * \note The SPI mode used for this command is the one set with the
+ *       \ref qspi_ip6514e_activate_qspi_mode function or the default one.
+ */
+enum qspi_ip6514e_error_t qspi_ip6514e_send_read_cmd(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint8_t opcode,
+                                                 void *read_data,
+                                                 uint32_t read_len,
+                                                 uint32_t addr,
+                                                 uint32_t addr_bytes_number,
+                                                 uint32_t dummy_cycles);
+
+/**
+ * \brief Send a write command to the flash memory device using the Software
+ *        Triggered Instruction Generator (STIG). This command can be used to
+ *        write Flash memory or registers.
+ *
+ * \param[in]  dev               QSPI IP6514E device struct
+ *                               \ref qspi_ip6514e_dev_t
+ * \param[in]  opcode            Opcode for the command.
+ * \param[in]  write_data        Pointer to a memory zone where are
+ *                               located the write_len bytes to write for
+ *                               this command.
+ * \param[in]  write_len         Number of bytes to write for the command.
+ *                               Between 1 and 8 bytes (both included) can be
+ *                               written.
+ * \param[in]  addr              Address used for the command
+ * \param[in]  addr_bytes_number Number of address bytes for this command.
+ *                               If an address is not needed for the command,
+ *                               use 0 for argument, otherwise between 1 and
+ *                               4 bytes (both included) can be used.
+ * \param[in]  dummy_cycles      Number of dummy cycles required for the
+ *                               command, between 0 and 31 (both included).
+ *
+ * \return Returns error code as specified in \ref qspi_ip6514e_error_t
+ *
+ * \note Check the flash memory device specifications for the possible opcodes
+ *       that can be used and the other informations needed for this function.
+ * \note The SPI mode used for this command is the one set with the
+ *       \ref qspi_ip6514e_activate_qspi_mode function or the default one.
+ */
+enum qspi_ip6514e_error_t qspi_ip6514e_send_write_cmd(
+                                                 struct qspi_ip6514e_dev_t* dev,
+                                                 uint8_t opcode,
+                                                 const void *write_data,
+                                                 uint32_t write_len,
+                                                 uint32_t addr,
+                                                 uint32_t addr_bytes_number,
+                                                 uint32_t dummy_cycles);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __QSPI_IP6514E_DRV_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/boot_hal.c b/platform/ext/target/musca_b1_secure_enclave/boot_hal.c
new file mode 100644
index 0000000..5673bd0
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/boot_hal.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdio.h>
+#include "cmsis.h"
+#include "region.h"
+#include "target_cfg.h"
+#include "boot_hal.h"
+#include "Driver_Flash.h"
+#include "flash_layout.h"
+#include "bootutil/fault_injection_hardening.h"
+
+#if defined(CRYPTO_HW_ACCELERATOR) || \
+    defined(CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING)
+#include "crypto_hw.h"
+#endif
+
+/* Flash device name must be specified by target */
+extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
+
+REGION_DECLARE(Image$$, ER_DATA, $$Base)[];
+REGION_DECLARE(Image$$, ARM_LIB_HEAP, $$ZI$$Limit)[];
+
+__attribute__((naked)) void boot_clear_bl2_ram_area(void)
+{
+    __ASM volatile(
+#ifndef __ICCARM__
+        ".syntax unified                             \n"
+#endif
+        "movs    r0, #0                              \n"
+        "subs    %1, %1, %0                          \n"
+        "Loop:                                       \n"
+        "subs    %1, #4                              \n"
+        "blt     Clear_done                          \n"
+        "str     r0, [%0, %1]                        \n"
+        "b       Loop                                \n"
+        "Clear_done:                                 \n"
+        "bx      lr                                  \n"
+        :
+        : "r" (REGION_NAME(Image$$, ER_DATA, $$Base)),
+          "r" (REGION_NAME(Image$$, ARM_LIB_HEAP, $$ZI$$Limit))
+        : "r0", "memory"
+    );
+}
+
+int32_t boot_platform_init(void)
+{
+    int32_t result;
+
+    result = FLASH_DEV_NAME.Initialize(NULL);
+    if (result != ARM_DRIVER_OK) {
+        return 1;
+    }
+
+#ifdef CRYPTO_HW_ACCELERATOR
+    result = crypto_hw_accelerator_init();
+    if (result) {
+        return 1;
+    }
+#endif /* CRYPTO_HW_ACCELERATOR */
+
+/* This is a workaround to program the TF-M related cryptographic keys
+ * to CC312 OTP memory. This functionality is independent from secure boot,
+ * this is usually done on the factory floor during chip manufacturing.
+ */
+#ifdef CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING
+    printf("OTP provisioning started.");
+    result = crypto_hw_accelerator_otp_provisioning();
+    if (result) {
+        printf("OTP provisioning FAILED: 0x%X", result);
+        return 1;
+    } else {
+        printf("OTP provisioning succeeded. TF-M won't be loaded.");
+
+        /* We don't need to boot - the only aim is provisioning. */
+        while (1);
+    }
+#endif /* CRYPTO_HW_ACCELERATOR_OTP_PROVISIONING */
+
+    return 0;
+}
+
+void boot_platform_quit(struct boot_arm_vector_table *vt)
+{
+    /* Clang at O0, stores variables on the stack with SP relative addressing.
+     * When manually set the SP then the place of reset vector is lost.
+     * Static variables are stored in 'data' or 'bss' section, change of SP has
+     * no effect on them.
+     */
+    static struct boot_arm_vector_table *vt_cpy;
+    int32_t result;
+
+#ifdef CRYPTO_HW_ACCELERATOR
+    result = crypto_hw_accelerator_finish();
+    if (result) {
+        while (1);
+    }
+
+    (void)fih_delay_init();
+#endif /* CRYPTO_HW_ACCELERATOR */
+
+    result = FLASH_DEV_NAME.Uninitialize();
+    if (result != ARM_DRIVER_OK) {
+        while (1);
+    }
+
+    vt_cpy = vt;
+
+    __set_MSP(vt->msp);
+    __DSB();
+    __ISB();
+
+    boot_jump_to_next_image(vt_cpy->reset);
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/config.cmake b/platform/ext/target/musca_b1_secure_enclave/config.cmake
new file mode 100644
index 0000000..0b923c2
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/config.cmake
@@ -0,0 +1,25 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+# Configuration values forced due to the Secure Enclave topology
+set(TFM_MULTI_CORE_TOPOLOGY             ON           CACHE BOOL      "Whether to build for a dual-cpu architecture" FORCE)
+set(TFM_PSA_API                         ON           CACHE BOOL      "Use PSA api (IPC mode) instead of secure library mode" FORCE)
+set(NS                                  FALSE        CACHE BOOL      "Whether to build NS app" FORCE)
+set(TEST_NS                             OFF          CACHE BOOL      "Whether to build NS regression tests" FORCE)
+
+# Serial output is not available for Secure Enclave
+set(PLATFORM_DEFAULT_UART_STDOUT        FALSE        CACHE BOOL      "Use default uart stdout implementation." FORCE)
+set(MCUBOOT_LOG_LEVEL                   "NONE"       CACHE STRING    "Level of logging to use for MCUboot [OFF, ERROR, WARNING, INFO, DEBUG]" FORCE)
+
+# Test services are inaccessible via Proxy service
+set(TEST_S                              OFF          CACHE BOOL      "Whether to build S regression tests" FORCE)
+
+# Currently only level 1 isolation is supported
+set(TFM_ISOLATION_LEVEL                 1            CACHE STRING    "Isolation level" FORCE)
+
+# Crypto hardware accelerator is turned on by default
+set(CRYPTO_HW_ACCELERATOR               ON           CACHE BOOL      "Whether to enable the crypto hardware accelerator on supported platforms")
diff --git a/platform/ext/target/musca_b1_secure_enclave/mailbox/mailbox_ipc_intr.c b/platform/ext/target/musca_b1_secure_enclave/mailbox/mailbox_ipc_intr.c
new file mode 100644
index 0000000..283d3bb
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/mailbox/mailbox_ipc_intr.c
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "cmsis.h"
+#include "platform_multicore.h"
+
+__STATIC_INLINE void tfm_trigger_pendsv(void)
+{
+    SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
+}
+
+void MHU0_MSG_0_Handler(void)
+{
+    uint32_t magic;
+
+    platform_mailbox_fetch_msg_data(&magic);
+
+    /* Sanity check based on predefined arbitrary value */
+    if (magic == PSA_CLIENT_CALL_REQ_MAGIC) {
+        tfm_trigger_pendsv();
+    }
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/mailbox/platform_multicore.c b/platform/ext/target/musca_b1_secure_enclave/mailbox/platform_multicore.c
new file mode 100644
index 0000000..e568449
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/mailbox/platform_multicore.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "platform_multicore.h"
+#include "cmsis.h"
+#include "mhu_v2_x.h"
+#include "device_definition.h"
+
+void platform_init_mailbox_hw(void)
+{
+    mhu_v2_x_driver_init(&MHU0_SENDER_DEV, MHU_REV_2_0);
+    mhu_v2_x_driver_init(&MHU0_RECEIVER_DEV, MHU_REV_2_0);
+}
+
+void platform_mailbox_send_msg_data(uint32_t data)
+{
+    mhu_v2_x_initiate_transfer(&MHU0_SENDER_DEV);
+    mhu_v2_x_channel_send(&MHU0_SENDER_DEV, 0, data);
+    mhu_v2_x_close_transfer(&MHU0_SENDER_DEV);
+}
+
+void platform_mailbox_fetch_msg_data(uint32_t *data_ptr)
+{
+    mhu_v2_x_channel_receive(&MHU0_RECEIVER_DEV, 0, data_ptr);
+    mhu_v2_x_channel_clear(&MHU0_RECEIVER_DEV, 0);
+
+    NVIC_ClearPendingIRQ(PSA_CLIENT_CALL_NVIC_IRQn);
+}
+
+void platform_mailbox_fetch_msg_ptr(void **msg_ptr)
+{
+    mhu_v2_x_channel_receive(&MHU0_RECEIVER_DEV, 0, (uint32_t*)(msg_ptr));
+    mhu_v2_x_channel_clear(&MHU0_RECEIVER_DEV, 0);
+
+    NVIC_ClearPendingIRQ(PSA_CLIENT_CALL_NVIC_IRQn);
+}
+
+void platform_mailbox_wait_for_notify(void)
+{
+    while(NVIC_GetPendingIRQ(PSA_CLIENT_CALL_NVIC_IRQn) == 0);
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/mailbox/platform_multicore.h b/platform/ext/target/musca_b1_secure_enclave/mailbox/platform_multicore.h
new file mode 100644
index 0000000..c8e5871
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/mailbox/platform_multicore.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef _PLATFORM_MULTICORE_H_
+#define _PLATFORM_MULTICORE_H_
+
+#include <stdint.h>
+
+/* Arbitrary predefined values to sync between Host and Secure Enclave */
+#define IPC_SYNC_MAGIC                   (0x7DADE011)
+
+#define NS_MAILBOX_INIT_ENABLE           (0xAE)
+#define S_MAILBOX_READY                  (0xC3)
+
+#define PLATFORM_MAILBOX_SUCCESS         (0x0)
+
+#define PSA_CLIENT_CALL_REQ_MAGIC        (0xA5CF50C6)
+#define PSA_CLIENT_CALL_REPLY_MAGIC      (0xC605FC5A)
+
+#define PSA_CLIENT_CALL_NVIC_IRQn        (MHU0_MSG_0_IRQn)
+
+/**
+ * \brief Initialize mailbox HW
+ */
+void platform_init_mailbox_hw(void);
+
+/**
+ * \brief Fetch a pointer from mailbox
+ *
+ * \param[out] msg_ptr     The address to write the pointer value to.
+ *
+ * \retval 0               The operation succeeds.
+ * \retval else            The operation fails.
+ */
+void platform_mailbox_fetch_msg_ptr(void **msg_ptr);
+
+/**
+ * \brief Fetch a data value from mailbox
+ *
+ * \param[out] data_ptr    The address to write the pointer value to.
+ *
+ * \retval 0               The operation succeeds.
+ * \retval else            The operation fails.
+ */
+void platform_mailbox_fetch_msg_data(uint32_t *data_ptr);
+
+/**
+ * \brief Send a data value via mailbox
+ *
+ * \param[in] data         The data value to be sent
+ *
+ * \retval 0               The operation succeeds.
+ * \retval else            The operation fails.
+ */
+void platform_mailbox_send_msg_data(uint32_t data);
+
+/**
+ * \brief Wait for a mailbox notify event.
+ */
+void platform_mailbox_wait_for_notify(void);
+
+#endif /* _PLATFORM_MULTICORE_H_ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/mailbox/platform_spe_mailbox.c b/platform/ext/target/musca_b1_secure_enclave/mailbox/platform_spe_mailbox.c
new file mode 100644
index 0000000..1ccdfce
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/mailbox/platform_spe_mailbox.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2019, Cypress Semiconductor Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "platform_multicore.h"
+#include "tfm_spe_mailbox.h"
+#include "cmsis.h"
+
+static void mailbox_ipc_config(void)
+{
+    /* 2 NVIC bits present on this platform, setting the almost lowest priority. */
+    NVIC_SetPriority(PSA_CLIENT_CALL_NVIC_IRQn, 2);
+
+    NVIC_EnableIRQ(PSA_CLIENT_CALL_NVIC_IRQn);
+}
+
+int32_t tfm_mailbox_hal_notify_peer(void)
+{
+    platform_mailbox_send_msg_data(PSA_CLIENT_CALL_REPLY_MAGIC);
+
+    return MAILBOX_SUCCESS;
+}
+
+int32_t tfm_mailbox_hal_init(struct secure_mailbox_queue_t *s_queue)
+{
+    struct ns_mailbox_queue_t *ns_queue = NULL;
+
+    /* Inform NSPE that NSPE mailbox initialization can start */
+    platform_mailbox_send_msg_data(NS_MAILBOX_INIT_ENABLE);
+
+    platform_mailbox_wait_for_notify();
+
+    /* Receive the address of NSPE mailbox queue */
+    platform_mailbox_fetch_msg_ptr((void **)&ns_queue);
+
+    /*
+     * FIXME
+     * Necessary sanity check of the address of NPSE mailbox queue should
+     * be implemented there.
+     */
+    s_queue->ns_queue = ns_queue;
+
+    mailbox_ipc_config();
+
+    /* Inform NSPE that SPE mailbox service is ready */
+    platform_mailbox_send_msg_data(S_MAILBOX_READY);
+
+    return MAILBOX_SUCCESS;
+}
+
+void tfm_mailbox_hal_enter_critical(void)
+{
+    /* Protection against concurrent access should be added
+     * if more messages are sent parallel. */
+}
+
+void tfm_mailbox_hal_exit_critical(void)
+{
+    /* Protection against concurrent access should be added
+     * if more messages are sent parallel. */
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/partition/flash_layout.h b/platform/ext/target/musca_b1_secure_enclave/partition/flash_layout.h
new file mode 100644
index 0000000..80815f2
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/partition/flash_layout.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2018-2020 Arm Limited. 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.
+ * 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.
+ */
+
+#ifndef __FLASH_LAYOUT_H__
+#define __FLASH_LAYOUT_H__
+
+/* Flash (and Code SRAM) layout on Musca-B1 if Secure Enclave (SE) is used
+ * BL2 is mandatory in this case, and MCUBOOT_IMAGE_NUMBER must be 2
+ *
+ * SE images are placed in eFlash 0 and eFlash 1 and remapped to SE's memory
+ * space by ROM and CODE remap.
+ * ROM  remap offset should be set to 0x1A02_0000
+ * ROM  remap mask   should be set to 0x0001_FFFF
+ * CODE remap offset should be set to 0x1A20_0000
+ * CODE remap mask   should be set to 0x003F_FFFF
+ *
+ * Some memory areas are not accessible for SE over the remap address ranges.
+ * ITS, PS, and NV counters are accessible for SE over the flash controllers.
+ * The image base addresses for both subsystems can be found in the following
+ * table, N/A for unaccessible addresses:
+ *
+*                                                  SSE-200 address  SE address
+ * eFlash 0:
+ * SSE-200 BL0 (128 KiB)                           0x1A000000       N/A
+ * SE MCUBoot (128 KiB)                            0x1A020000       0x00000000
+ * Internal Trusted Storage Area (32 KiB)          0x1A040000       N/A
+ * NV counters area (16 KiB)                       0x1A048000       N/A
+ * Unused (196 KiB)                                0x1A04C000       N/A
+ *
+ * eFlash 1:
+ * SE TF-M image          primary slot (384 KiB)   0x1A200000       0x38000000
+ * SSE-200 combined image primary slot (512 KiB)   0x1A260000       0x38060000
+ * SE TF-M image          secondary slot (384 KiB) 0x1A2E0000       0x380E0000
+ * SSE-200 combined image secondary slot (512 KiB) 0x1A360000       0x38160000
+ * Scratch area (64 KiB)                           0x1A3C0000       0x381C0000
+ * Unused (196 KiB)                                0x1A3D0000       0x381D0000
+ *
+ * Code SRAM:
+ * SSE-200 BL0 ramload area (16 KiB)               0x1A400000       0x38200000
+ * SE MCUBoot eFlash driver ramload area (16 KiB)  0x1A404000       0x38204000
+ * IPC Shared memory area (476 KiB)                0x1A408000       0x38208000
+ *
+ * The SE MCUBoot eFlash driver is copied into Code SRAM. If the driver would
+ * run from eFlash0 it would not be possible to write the NV counters also
+ * placed in eFlash0. It is not advisable to write to and fetch instructions
+ * from flash at the same time. For the same reason SSE-200 BL0 is running
+ * from Code SRAM.
+ */
+
+/* This header file is included from linker scatter file as well, where only a
+ * limited C constructs are allowed. Therefore it is not possible to include
+ * here the platform_base_address.h to access flash related defines. To resolve this
+ * some of the values are redefined here with different names, these are marked
+ * with comment.
+ */
+
+/* The size of partitions */
+#define FLASH_S_PARTITION_SIZE          (0x60000)      /* 384 KiB */
+#define FLASH_SSE_200_PARTITION_SIZE    (0x80000)      /* 512 KiB */
+#define FLASH_MAX_PARTITION_SIZE        ((FLASH_S_PARTITION_SIZE >   \
+                                          FLASH_SSE_200_PARTITION_SIZE) ? \
+                                         FLASH_S_PARTITION_SIZE :    \
+                                         FLASH_SSE_200_PARTITION_SIZE)
+
+/* Sector size of the embedded flash hardware */
+#define FLASH_AREA_IMAGE_SECTOR_SIZE    (0x4000)   /* 16 KB */
+#define FLASH_TOTAL_SIZE                (0x200000) /* 2 MB */
+
+/* Sector size of the QSPI flash hardware */
+#define QSPI_FLASH_AREA_IMAGE_SECTOR_SIZE (0x1000)   /* 4 KB */
+#define QSPI_FLASH_TOTAL_SIZE             (0x800000) /* 8 MB */
+
+
+/* Flash layout info for BL2 bootloader, images are placed in eFlash1 */
+#define FLASH_BASE_ADDRESS              (0x38000000)
+
+#if !defined(MCUBOOT_IMAGE_NUMBER) || (MCUBOOT_IMAGE_NUMBER == 2)
+/* SE TF-M image primary slot */
+#define FLASH_AREA_0_ID            (1)
+#define FLASH_AREA_0_OFFSET        (0)
+#define FLASH_AREA_0_SIZE          (FLASH_S_PARTITION_SIZE)
+
+/* SSE-200 image primary slot */
+#define FLASH_AREA_1_ID            (FLASH_AREA_0_ID + 1)
+#define FLASH_AREA_1_OFFSET        (FLASH_AREA_0_OFFSET + FLASH_AREA_0_SIZE)
+#define FLASH_AREA_1_SIZE          (FLASH_SSE_200_PARTITION_SIZE)
+
+/* SE TF-M image secondary slot */
+#define FLASH_AREA_2_ID            (FLASH_AREA_1_ID + 1)
+#define FLASH_AREA_2_OFFSET        (FLASH_AREA_1_OFFSET + FLASH_AREA_1_SIZE)
+#define FLASH_AREA_2_SIZE          (FLASH_S_PARTITION_SIZE)
+
+/* SSE-200 image secondary slot */
+#define FLASH_AREA_3_ID            (FLASH_AREA_2_ID + 1)
+#define FLASH_AREA_3_OFFSET        (FLASH_AREA_2_OFFSET + FLASH_AREA_2_SIZE)
+#define FLASH_AREA_3_SIZE          (FLASH_SSE_200_PARTITION_SIZE)
+
+/* Scratch area */
+#define FLASH_AREA_SCRATCH_ID      (FLASH_AREA_3_ID + 1)
+#define FLASH_AREA_SCRATCH_OFFSET  (FLASH_AREA_3_OFFSET + FLASH_AREA_3_SIZE)
+#define FLASH_AREA_SCRATCH_SIZE    (4 * FLASH_AREA_IMAGE_SECTOR_SIZE)
+
+/* The maximum number of status entries supported by the bootloader. */
+#define MCUBOOT_STATUS_MAX_ENTRIES (FLASH_MAX_PARTITION_SIZE / \
+                                    FLASH_AREA_SCRATCH_SIZE)
+
+/* Maximum number of image sectors supported by the bootloader. */
+#define NEEDED_MCUBOOT_IMG_SECTORS (FLASH_MAX_PARTITION_SIZE / \
+                                    FLASH_AREA_IMAGE_SECTOR_SIZE)
+#define MCUBOOT_MAX_IMG_SECTORS    (NEEDED_MCUBOOT_IMG_SECTORS > 32 ? \
+                                    NEEDED_MCUBOOT_IMG_SECTORS :      \
+                                    32)
+
+#else /* MCUBOOT_IMAGE_NUMBER == 2 */
+#error "Only MCUBOOT_IMAGE_NUMBER 2 is supported!"
+#endif /* MCUBOOT_IMAGE_NUMBER */
+
+/* Flash device name used by BL2
+ * Name is defined in flash driver file: Driver_Flash.c
+ */
+#define FLASH_DEV_NAME Driver_EFLASH1
+
+
+/* Assets in eFlash0 */
+/* SSE-200 BL0 component */
+#define SSE200_BL0_OFFSET               (0x0)
+#define SSE200_BL0_SIZE                 (0x20000) /* 128 KB */
+
+/* SE BL2 image */
+#define FLASH_AREA_BL2_OFFSET            (SSE200_BL0_OFFSET + \
+                                         SSE200_BL0_SIZE)
+/* Maximum memory window size with ROM remap */
+#define FLASH_AREA_BL2_SIZE              (0x20000) /* 128 KB */
+
+/* Internal Trusted Storage (ITS) Service definitions */
+#define FLASH_ITS_AREA_OFFSET           (FLASH_AREA_BL2_OFFSET + \
+                                         FLASH_AREA_BL2_SIZE)
+#define FLASH_ITS_AREA_SIZE             (2 * FLASH_AREA_IMAGE_SECTOR_SIZE)
+
+/* NV Counters definitions */
+#define FLASH_NV_COUNTERS_AREA_OFFSET   (FLASH_ITS_AREA_OFFSET + \
+                                         FLASH_ITS_AREA_SIZE)
+#define FLASH_NV_COUNTERS_AREA_SIZE     (FLASH_AREA_IMAGE_SECTOR_SIZE)
+
+
+/* Internal Trusted Storage (ITS) Service definitions
+ * Note: Further documentation of these definitions can be found in the
+ * TF-M ITS Integration Guide.
+ */
+#define ITS_FLASH_DEV_NAME Driver_EFLASH0
+
+/* In this target the CMSIS driver requires only the offset from the base
+ * address instead of the full memory address.
+ */
+#define ITS_FLASH_AREA_ADDR     FLASH_ITS_AREA_OFFSET
+/* Dedicated flash area for ITS */
+#define ITS_FLASH_AREA_SIZE     FLASH_ITS_AREA_SIZE
+#define ITS_RAM_FS_SIZE         ITS_FLASH_AREA_SIZE
+#define ITS_SECTOR_SIZE         FLASH_AREA_IMAGE_SECTOR_SIZE
+/* Number of ITS_SECTOR_SIZE per block */
+#define ITS_SECTORS_PER_BLOCK   (0x1)
+/* Specifies the smallest flash programmable unit in bytes */
+#define ITS_FLASH_PROGRAM_UNIT  (0x4)
+
+/* NV Counters definitions */
+#define NV_COUNTERS_FLASH_DEV_NAME Driver_EFLASH0
+#define TFM_NV_COUNTERS_AREA_ADDR    FLASH_NV_COUNTERS_AREA_OFFSET
+#define TFM_NV_COUNTERS_AREA_SIZE    (0x18) /* 24 Bytes */
+#define TFM_NV_COUNTERS_SECTOR_ADDR  FLASH_NV_COUNTERS_AREA_OFFSET
+#define TFM_NV_COUNTERS_SECTOR_SIZE  FLASH_NV_COUNTERS_AREA_SIZE
+
+
+/* Protected Storage (PS) Service definitions. PS is placed in QSPI flash */
+#define FLASH_PS_AREA_OFFSET            (0x0)
+#define FLASH_PS_AREA_SIZE              (5 * QSPI_FLASH_AREA_IMAGE_SECTOR_SIZE)
+
+/* Protected Storage (PS) Service definitions
+ * Note: Further documentation of these definitions can be found in the
+ * TF-M PS Integration Guide.
+ */
+#define PS_FLASH_DEV_NAME Driver_QSPI_FLASH0
+
+/* In this target the CMSIS driver requires only the offset from the base
+ * address instead of the full memory address.
+ */
+#define PS_FLASH_AREA_ADDR     FLASH_PS_AREA_OFFSET
+/* Dedicated flash area for PS */
+#define PS_FLASH_AREA_SIZE     FLASH_PS_AREA_SIZE
+#define PS_RAM_FS_SIZE         PS_FLASH_AREA_SIZE
+#define PS_SECTOR_SIZE         QSPI_FLASH_AREA_IMAGE_SECTOR_SIZE
+/* Number of PS_SECTOR_SIZE per block */
+#define PS_SECTORS_PER_BLOCK   (0x1)
+/* Specifies the smallest flash programmable unit in bytes */
+#define PS_FLASH_PROGRAM_UNIT  (0x1)
+/* The maximum asset size to be stored in the PS area */
+
+#endif /* __FLASH_LAYOUT_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/partition/region_defs.h b/platform/ext/target/musca_b1_secure_enclave/partition/region_defs.h
new file mode 100644
index 0000000..a85cba3
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/partition/region_defs.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017-2020 Arm Limited. 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.
+ * 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.
+ */
+
+#ifndef __REGION_DEFS_H__
+#define __REGION_DEFS_H__
+
+#include "flash_layout.h"
+
+#define BL2_HEAP_SIZE           (0x0001000)
+#define BL2_MSP_STACK_SIZE      (0x0001800)
+
+#define S_HEAP_SIZE             (0x0000200)
+#define S_MSP_STACK_SIZE_INIT   (0x0000400)
+#define S_MSP_STACK_SIZE        (0x0000800)
+#define S_PSP_STACK_SIZE        (0x0000800)
+
+/* This size of buffer is big enough to store an attestation
+ * token produced by initial attestation service
+ */
+#define PSA_INITIAL_ATTEST_TOKEN_MAX_SIZE   (0x250)
+
+#ifndef LINK_TO_SECONDARY_PARTITION
+#define S_IMAGE_PRIMARY_PARTITION_OFFSET   (FLASH_AREA_0_OFFSET)
+#define S_IMAGE_SECONDARY_PARTITION_OFFSET (FLASH_AREA_2_OFFSET)
+#else
+#define S_IMAGE_PRIMARY_PARTITION_OFFSET   (FLASH_AREA_2_OFFSET)
+#define S_IMAGE_SECONDARY_PARTITION_OFFSET (FLASH_AREA_0_OFFSET)
+#endif /* !LINK_TO_SECONDARY_PARTITION */
+
+#define BL2_HEADER_SIZE      (0x400)       /* 1 KB */
+#define BL2_TRAILER_SIZE     (0x800)       /* 2 KB */
+
+#define IMAGE_S_CODE_SIZE \
+            (FLASH_S_PARTITION_SIZE - BL2_HEADER_SIZE - BL2_TRAILER_SIZE)
+
+/* Code SRAM area */
+#define CODE_SRAM_BASE              (0x38200000)
+#define CODE_SRAM_SIZE              (0x00080000) /* 512 KiB */
+
+/* Reserved area for SSE-200 BL0 */
+#define SSE200_BL0_RAM_BASE         CODE_SRAM_BASE
+#define SSE200_BL0_RAM_SIZE         (0x00004000) /* 16 KiB */
+
+/* eFlash drivers are copied to Code SRAM in BL2 */
+#define EFLASH_DRIVER_REGION_BASE   (SSE200_BL0_RAM_BASE + SSE200_BL0_RAM_SIZE)
+#define EFLASH_DRIVER_REGION_SIZE   (0x00004000) /* 16 KiB */
+
+/* Memory area used as shared memory between SSE-200 and SE */
+#define IPC_SHARED_MEMORY_BASE      (EFLASH_DRIVER_REGION_BASE + \
+                                     EFLASH_DRIVER_REGION_SIZE)
+#define IPC_SHARED_MEMORY_SIZE      (CODE_SRAM_SIZE - \
+                                     SSE200_BL0_SIZE - \
+                                     EFLASH_DRIVER_REGION_SIZE) /* 476 KiB */
+
+/* Secure Enclave internal SRAM */
+#define SRAM_BASE               (0x30000000)
+#define SRAM_SIZE               (0x00010000)     /* 64 KiB */
+
+/* Secure regions */
+#define S_CODE_START            (FLASH_BASE_ADDRESS + \
+                                 S_IMAGE_PRIMARY_PARTITION_OFFSET + \
+                                 BL2_HEADER_SIZE)
+#define S_CODE_SIZE             (IMAGE_S_CODE_SIZE)
+#define S_CODE_LIMIT            (S_CODE_START + S_CODE_SIZE - 1)
+
+#define S_DATA_START            (SRAM_BASE)
+#define S_DATA_SIZE             (SRAM_SIZE)
+#define S_UNPRIV_DATA_SIZE      (0x3000)
+#define S_DATA_LIMIT            (S_DATA_START + S_DATA_SIZE - 1)
+#define S_DATA_PRIV_START       (S_DATA_START + S_UNPRIV_DATA_SIZE)
+
+/* Shared data area between bootloader and runtime firmware.
+ * Shared data area is allocated at the beginning of the privileged data area,
+ * it is overlapping with TF-M Secure code's MSP stack
+ */
+#define BOOT_TFM_SHARED_DATA_BASE (S_DATA_PRIV_START)
+#define BOOT_TFM_SHARED_DATA_SIZE (0x400)
+#define BOOT_TFM_SHARED_DATA_LIMIT (BOOT_TFM_SHARED_DATA_BASE + \
+                                    BOOT_TFM_SHARED_DATA_SIZE - 1)
+
+/* Whole SSE-200 image treated as Non-secure */
+#ifndef LINK_TO_SECONDARY_PARTITION
+#define NS_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_1_OFFSET)
+#else
+#define NS_IMAGE_PRIMARY_PARTITION_OFFSET (FLASH_AREA_3_OFFSET)
+#endif /* !LINK_TO_SECONDARY_PARTITION */
+
+#define NS_PARTITION_START (FLASH_BASE_ADDRESS + \
+                            NS_IMAGE_PRIMARY_PARTITION_OFFSET)
+#define NS_PARTITION_SIZE (FLASH_SSE_200_PARTITION_SIZE)
+
+/* The shared memory is treated as NS memory */
+#define NS_DATA_START   IPC_SHARED_MEMORY_BASE
+#define NS_DATA_SIZE    IPC_SHARED_MEMORY_SIZE
+#define NS_DATA_LIMIT   (NS_DATA_START + NS_DATA_SIZE - 1)
+
+#define NS_CODE_START   (NS_PARTITION_START)
+#define NS_CODE_SIZE    (NS_PARTITION_SIZE)
+#define NS_CODE_LIMIT   (NS_CODE_START + NS_CODE_SIZE - 1)
+
+/* Secondary partition for new images in case of firmware upgrade.
+ * This area is reserved for both secondary images. */
+#define SECONDARY_PARTITION_START (S_IMAGE_SECONDARY_PARTITION_OFFSET)
+#define SECONDARY_PARTITION_SIZE  (FLASH_S_PARTITION_SIZE + \
+                                   FLASH_SSE_200_PARTITION_SIZE)
+
+/* Bootloader regions */
+/* ROM remap is mapped to 0x0 in SE */
+#define BL2_CODE_START    (0x0)
+#define BL2_CODE_SIZE     (FLASH_AREA_BL2_SIZE)
+#define BL2_CODE_LIMIT    (BL2_CODE_START + BL2_CODE_SIZE - 1)
+
+#define BL2_DATA_START    (S_DATA_START)
+#define BL2_DATA_SIZE     (S_DATA_SIZE)
+#define BL2_DATA_LIMIT    (BL2_DATA_START + BL2_DATA_SIZE - 1)
+
+
+#endif /* __REGION_DEFS_H__ */
+
diff --git a/platform/ext/target/musca_b1_secure_enclave/preload.cmake b/platform/ext/target/musca_b1_secure_enclave/preload.cmake
new file mode 100644
index 0000000..f334999
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/preload.cmake
@@ -0,0 +1,18 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+# preload.cmake is used to set things that related to the platform that are both
+# immutable and global, which is to say they should apply to any kind of project
+# that uses this plaform. In practise this is normally compiler definitions and
+# variables related to hardware.
+
+# Set architecture and CPU
+set(TFM_SYSTEM_PROCESSOR cortex-m0plus)
+set(TFM_SYSTEM_ARCHITECTURE armv6-m)
+
+# The Musca-B1 Secure Enclave has a CryptoCell-312 as an accelerator.
+set(CRYPTO_HW_ACCELERATOR_TYPE cc312)
diff --git a/platform/ext/target/musca_b1_secure_enclave/preload_ns.cmake b/platform/ext/target/musca_b1_secure_enclave/preload_ns.cmake
new file mode 100644
index 0000000..3b9601f
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/preload_ns.cmake
@@ -0,0 +1,9 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2020, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+# Placeholder because of interface include rule when TFM_MULTI_CORE_TOPOLOGY is
+# set.
diff --git a/platform/ext/target/musca_b1_secure_enclave/readme.rst b/platform/ext/target/musca_b1_secure_enclave/readme.rst
new file mode 100644
index 0000000..fa58bf8
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/readme.rst
@@ -0,0 +1,96 @@
+#################################
+Musca-B1 Secure Enclave Specifics
+#################################
+
+************
+Introduction
+************
+
+The Musca-B1 System-on-Chip contains two subsystems:
+
+- SSE-200 subsystem to host the main application.
+- CryptoIsland-300 subsystem can be used as a Secure Enclave (mentioned as *SE*
+  in the document).
+
+If TF-M is built with default configuration to the MUSCA-B1 platform only the
+SSE-200 subsystem used. But if the ``FORWARD_PROT_MSG`` cmake flag is turned
+on, the TF-M instance running on SSE-200 will communicate with the SE.
+
+For more information you can check the
+:doc:`Secure Enclave design document <docs/design_documents/secure_enclave_solution.rst>`.
+
+***********
+System boot
+***********
+
+The desired boot flow would be to start up SE first at power on as SE is the
+Root of Trust in the system, and SSE-200 should be started up by SE. But the
+current Musca-B1 DAPLink FW releases the SSE-200 subsystem from reset first,
+and it would require complex changes to modify this boot order. So an
+additional SSE-200 BL0 component was added to the system to imitate that SE is
+the subsystem started up first.
+
+.. uml::
+
+  @startuml
+
+  title Implemented boot flow
+
+  start
+  :Power On button pressed.;
+  :DAPLink Starts up SSE-200.;
+  :SSE-200 BL0 starts up the SE (through SCC), then enters wait state.;
+  :SE starts to run its MCUBoot image and authenticates all images (SE TF-M
+  image and the combined SSE-200 image). If all images are valid, control jumps
+  to SE’s TF-M image.;
+  :SE's TF-M image starts up, when initialization finishes, SSE-200 is
+  virtually released from reset by sending the start address of the combined
+  SSE-200 image over MHU;
+  :SSE-200 TF-M image starts up and synchronizes with SE over MHU;
+  :SSE-200 and SE are ready to communicate;
+  stop
+
+  @enduml
+
+.. Note::
+
+   Without the SSE-200 BL0 component, the boot flow can be treated as a valid
+   reference solution.
+
+*****
+Build
+*****
+
+To produce all the images, TF-M build needs to be executed twice:
+
+- One build needed to create the SSE-200 images (BL0 and the combined SSE-200
+  image containing TF-M and the non-secure application), target platform needs
+  to be set to ``MUSCA_B1`` and the ``FORWARD_PROT_MSG`` cmake flag also needs
+  to be set.
+- One build needed to create the SE images (MCUBoot and TF-M), target platform
+  needs to be set to ``MUSCA_B1_SECURE_ENCLAVE``.
+
+The order of the two builds is indifferent. The BL2 setting is mandatory for
+both builds, but MCUBoot image is only built for the SE platform.
+
+To create a unified hex file:
+
+- Windows::
+
+    srec_cat.exe TBD
+
+- Linux::
+
+    srec_cat TBD
+
+*****************
+Known limitations
+*****************
+- Musca-B1 Secure Enclave cannot reset the whole SoC, only itself. So if SE
+  does a system reset it will stuck in a state waiting for a handshake signal
+  from SSE-200. (It will never come, as SSE-200 is not reseted in such a
+  situation.)
+
+--------------
+
+*Copyright (c) 2020, Arm Limited. All rights reserved.*
diff --git a/platform/ext/target/musca_b1_secure_enclave/services/src/tfm_platform_system.c b/platform/ext/target/musca_b1_secure_enclave/services/src/tfm_platform_system.c
new file mode 100644
index 0000000..283af84
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/services/src/tfm_platform_system.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_platform_system.h"
+#include "cmsis.h"
+
+void tfm_platform_hal_system_reset(void)
+{
+    /* Reset the system */
+    NVIC_SystemReset();
+}
+
+enum tfm_platform_err_t tfm_platform_hal_ioctl(tfm_platform_ioctl_req_t request,
+                                               psa_invec  *in_vec,
+                                               psa_outvec *out_vec)
+{
+    (void)in_vec;
+    (void)out_vec;
+    return TFM_PLATFORM_ERR_NOT_SUPPORTED;
+}
+
diff --git a/platform/ext/target/musca_b1_secure_enclave/spm_hal.c b/platform/ext/target/musca_b1_secure_enclave/spm_hal.c
new file mode 100644
index 0000000..fceb6d1
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/spm_hal.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2019-2020, Cypress Semiconductor Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "tfm_spm_hal.h"
+#include "device_definition.h"
+#include "region_defs.h"
+#include "target_cfg.h"
+#include "tfm_multi_core.h"
+#include "platform_multicore.h"
+
+#include "cmsis.h"
+
+/* Declared in target_cfg.c */
+extern const struct memory_region_limits memory_regions;
+
+enum tfm_plat_err_t tfm_spm_hal_init_isolation_hw(void)
+{
+    /* Nothing to do, there is no isolation HW in this platform to be
+     * configured by Secure Enclave */
+    return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_spm_hal_configure_default_isolation(
+        uint32_t partition_idx,
+        const struct tfm_spm_partition_platform_data_t *platform_data)
+{
+    /* Nothing to do, there is no isolation HW in this platform to be
+     * configured by Secure Enclave */
+    (void) partition_idx;
+    (void) platform_data;
+    return TFM_PLAT_ERR_SUCCESS;
+}
+
+void tfm_spm_hal_boot_ns_cpu(uintptr_t start_addr)
+{
+    uint32_t translated_address = 0;
+
+    platform_init_mailbox_hw();
+
+    translated_address = (uint32_t) start_addr
+            + 0x1A200000 /* eFlash 1 base from SSE-200's point of view */
+            - 0x38000000 /* eFlash 1 base from SE's point of view */;
+
+    platform_mailbox_send_msg_data(translated_address);
+}
+
+void tfm_spm_hal_wait_for_ns_cpu_ready(void)
+{
+    uint32_t data = 0;
+
+    while (data != IPC_SYNC_MAGIC) {
+        platform_mailbox_wait_for_notify();
+        platform_mailbox_fetch_msg_data(&data);
+    }
+}
+
+enum tfm_plat_err_t tfm_spm_hal_set_secure_irq_priority(IRQn_Type irq_line,
+                                                        uint32_t priority)
+{
+    uint32_t quantized_priority = priority >> (8U - __NVIC_PRIO_BITS);
+    NVIC_SetPriority(irq_line, quantized_priority);
+
+    return TFM_PLAT_ERR_SUCCESS;
+}
+
+void tfm_spm_hal_get_mem_security_attr(const void *p, size_t s,
+                                       struct security_attr_info_t *p_attr)
+{
+    /* Check static memory layout to get memory attributes */
+    tfm_get_mem_region_security_attr(p, s, p_attr);
+}
+
+void tfm_spm_hal_get_secure_access_attr(const void *p, size_t s,
+                                        struct mem_attr_info_t *p_attr)
+{
+    /* Check static memory layout to get memory attributes */
+    tfm_get_secure_mem_region_attr(p, s, p_attr);
+
+}
+
+void tfm_spm_hal_get_ns_access_attr(const void *p, size_t s,
+                                    struct mem_attr_info_t *p_attr)
+{
+    /* Check static memory layout to get memory attributes */
+    tfm_get_ns_mem_region_attr(p, s, p_attr);
+}
+
+enum tfm_plat_err_t tfm_spm_hal_nvic_interrupt_enable(void)
+{
+    /* Nothing to do, mailbox interrupt enabled at mailbox initialization,
+     * no other interrupt source used in Secure Enclave */
+    return TFM_PLAT_ERR_SUCCESS;
+}
+
+void tfm_spm_hal_clear_pending_irq(IRQn_Type irq_line)
+{
+    NVIC_ClearPendingIRQ(irq_line);
+}
+
+void tfm_spm_hal_enable_irq(IRQn_Type irq_line)
+{
+    NVIC_EnableIRQ(irq_line);
+}
+
+void tfm_spm_hal_disable_irq(IRQn_Type irq_line)
+{
+    NVIC_DisableIRQ(irq_line);
+}
+
+enum irq_target_state_t tfm_spm_hal_set_irq_target_state(
+                                          IRQn_Type irq_line,
+                                          enum irq_target_state_t target_state)
+{
+    /* Nothing to do, target state of interrupts cannot be set on Armv6-m */
+    (void)irq_line;
+    (void)target_state;
+
+    return TFM_IRQ_TARGET_STATE_SECURE;
+}
+
+enum tfm_plat_err_t tfm_spm_hal_nvic_interrupt_target_state_cfg(void)
+{
+    /* Nothing to do, target state of interrupts cannot be set on Armv6-m */
+    return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_spm_hal_enable_fault_handlers(void)
+{
+    /* Nothing to do, fault handlers are not implemented on Armv6-m */
+    return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_spm_hal_system_reset_cfg(void)
+{
+    /* Nothing to do, system reset do no require any initialization */
+    return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_spm_hal_init_debug(void)
+{
+    /* Nothing to do, no initialization options for the debug subsystem on
+     * Armv6-m */
+    return TFM_PLAT_ERR_SUCCESS;
+}
+
+uint32_t tfm_spm_hal_get_ns_VTOR(void)
+{
+    return memory_regions.non_secure_code_start;
+}
+
+uint32_t tfm_spm_hal_get_ns_entry_point(void)
+{
+    return *((uint32_t *)(memory_regions.non_secure_code_start+ 4));
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/target_cfg.c b/platform/ext/target/musca_b1_secure_enclave/target_cfg.c
new file mode 100644
index 0000000..c1986ae
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/target_cfg.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. 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.
+ * 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 "target_cfg.h"
+#include "region.h"
+#include "region_defs.h"
+
+REGION_DECLARE(Load$$LR$$, LR_NS_PARTITION, $$Base);
+
+const struct memory_region_limits memory_regions = {
+    .non_secure_code_start =
+        (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
+        BL2_HEADER_SIZE,
+
+    .non_secure_partition_base =
+        (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base),
+
+    .non_secure_partition_limit =
+        (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
+        NS_PARTITION_SIZE - 1,
+};
diff --git a/platform/ext/target/musca_b1_secure_enclave/target_cfg.h b/platform/ext/target/musca_b1_secure_enclave/target_cfg.h
new file mode 100644
index 0000000..eccde58
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/target_cfg.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. 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.
+ * 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.
+ */
+
+#ifndef __TARGET_CFG_H__
+#define __TARGET_CFG_H__
+
+/**
+ * \brief Store the addresses of memory regions
+ */
+
+#include <stdint.h>
+
+struct memory_region_limits {
+    uint32_t non_secure_code_start;
+    uint32_t non_secure_partition_base;
+    uint32_t non_secure_partition_limit;
+};
+#endif /* __TARGET_CFG_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/tfm_hal_isolation.c b/platform/ext/target/musca_b1_secure_enclave/tfm_hal_isolation.c
new file mode 100644
index 0000000..e120795
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/tfm_hal_isolation.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2020, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "tfm_api.h"
+#include "tfm_hal_defs.h"
+#include "tfm_multi_core.h"
+
+enum tfm_hal_status_t tfm_hal_set_up_static_boundaries(void)
+{
+    /* Nothing to do, there is no isolation HW in this platform to be
+     * configured by Secure Enclave */
+    return TFM_HAL_SUCCESS;
+}
+
+enum tfm_hal_status_t tfm_hal_memory_has_access(uintptr_t base,
+                                                size_t size,
+                                                uint32_t attr)
+{
+    enum tfm_status_e status;
+
+    status = tfm_has_access_to_region((const void *)base, size, attr);
+    if (status != TFM_SUCCESS) {
+         return TFM_HAL_ERROR_MEM_FAULT;
+    }
+
+    return TFM_HAL_SUCCESS;
+}
diff --git a/platform/ext/target/musca_b1_secure_enclave/tfm_peripherals_def.h b/platform/ext/target/musca_b1_secure_enclave/tfm_peripherals_def.h
new file mode 100644
index 0000000..6775553
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/tfm_peripherals_def.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020, Cypress Semiconductor Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __TFM_PERIPHERALS_DEF_H__
+#define __TFM_PERIPHERALS_DEF_H__
+
+#include "cmsis.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Empty header needed for compilation */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TFM_PERIPHERALS_DEF_H__ */
diff --git a/platform/ext/target/musca_b1_secure_enclave/uart_stdout.c b/platform/ext/target/musca_b1_secure_enclave/uart_stdout.c
new file mode 100644
index 0000000..48ef7b9
--- /dev/null
+++ b/platform/ext/target/musca_b1_secure_enclave/uart_stdout.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017-2020, Arm Limited. All rights reserved.
+ *
+ * Licensed under the Apace 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.apace.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 "uart_stdout.h"
+#include <stdio.h>
+
+int stdio_output_string(const unsigned char *str, uint32_t len)
+{
+    /* Nothing to do as there is no serial output */
+    (void)str;
+    return len;
+}
+
+/* Redirects printf to STDIO_DRIVER in case of ARMCLANG*/
+#if defined(__ARMCC_VERSION)
+/* Struct FILE is implemented in stdio.h. Used to redirect printf to
+ * STDIO_DRIVER
+ */
+FILE __stdout;
+/* __ARMCC_VERSION is only defined starting from Arm compiler version 6 */
+int fputc(int ch, FILE *f)
+{
+    (void)f;
+
+    /* Send byte to USART */
+    (void)stdio_output_string((const unsigned char *)&ch, 1);
+
+    /* Return character written */
+    return ch;
+}
+#elif defined(__GNUC__)
+/* Redirects printf to STDIO_DRIVER in case of GNUARM */
+int _write(int fd, char *str, int len)
+{
+    (void)fd;
+
+    /* Send string and return the number of characters written */
+    return stdio_output_string((const unsigned char *)str, (uint32_t)len);
+}
+#elif defined(__ICCARM__)
+int putchar(int ch)
+{
+    /* Send byte to USART */
+    (void)stdio_output_string((const unsigned char *)&ch, 1);
+
+    /* Return character written */
+    return ch;
+}
+#endif
+
+void stdio_init(void)
+{
+    /* Nothing to do as there is no serial output */
+}
+
+void stdio_uninit(void)
+{
+    /* Nothing to do as there is no serial output */
+}