Voice Activity Detection secure partition added

Change-Id: Ic1b6b3fbde57a8b52545689c312deb5c6e264c02
Co-authored-by: Gabor Toth <gabor.toth@arm.com>
Signed-off-by: Mark Horvath <mark.horvath@arm.com>
diff --git a/partitions/partitions_readme.rst b/partitions/partitions_readme.rst
index d0de660..a3b3092 100755
--- a/partitions/partitions_readme.rst
+++ b/partitions/partitions_readme.rst
@@ -59,6 +59,21 @@
 -----------
 - David Vincze `<David.Vincze@arm.com>`_
 
+vad_an552_sp
+============
+
+Description
+-----------
+Secure partition for the AN552 FPGA image. It implements voice activity
+detection on the microphone input of the MPS3 board, and if voice detected
+(which can be any noise) a short sample (~100 ms) is recorded. Then it can be
+calculated that which frequency component has the highest energy in the
+recorded sample.
+
+Maintainers
+-----------
+- Gabor Toth `<gabor.toth@arm.com> <gabor.toth@arm.com>`_
+- Mark Horvath `<mark.horvath@arm.com> <mark.horvath@arm.com>`_
 
 ---------------------------
 
diff --git a/partitions/vad_an552_sp/CMakeLists.txt b/partitions/vad_an552_sp/CMakeLists.txt
new file mode 100644
index 0000000..efbf00a
--- /dev/null
+++ b/partitions/vad_an552_sp/CMakeLists.txt
@@ -0,0 +1,106 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+cmake_minimum_required(VERSION 3.15)
+cmake_policy(SET CMP0079 NEW)
+
+# Voice activity algorithm is fetched from external repository
+set(ARM_ENDPOINTAI_SRC_PATH     "DOWNLOAD"  CACHE PATH      "Path to Arm's EndpointAI repository (or DOWNLOAD to fetch automatically")
+add_subdirectory(ext/arm-endpoint-ai)
+
+# CMSIS 5 repository
+set(CMSIS_5_SRC_PATH    "DOWNLOAD"  CACHE PATH      "Path to CMSIS_5 repository (or DOWNLOAD to fetch automatically")
+add_subdirectory(ext/CMSIS)
+
+add_library(tfm_app_rot_partition_vad_an552 STATIC)
+
+target_sources(tfm_app_rot_partition_vad_an552
+    PRIVATE
+        Libraries/audio_codec_mps3.c
+        Libraries/systimer_armv8-m_timeout.c
+        native_drivers/i2c_sbcon_drv.c
+        native_drivers/audio_i2s_mps3_drv.c
+        ${CMAKE_SOURCE_DIR}/platform/ext/target/arm/mps3/an552/native_drivers/systimer_armv8-m_drv.c
+        vad_an552_device_definition.c
+        vad_an552_sp_main.c
+
+        ${ARM_ENDPOINTAI_SRC_PATH}/Kernels/tinyVAD/tinyVAD.c
+
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/StatisticsFunctions/arm_max_q15.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/ComplexMathFunctions/arm_cmplx_mag_q15.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/FastMathFunctions/arm_sqrt_q15.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/TransformFunctions/arm_rfft_q15.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/TransformFunctions/arm_rfft_init_q15.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/TransformFunctions/arm_cfft_q15.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/BasicMathFunctions/arm_shift_q15.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/CommonTables/arm_common_tables.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/CommonTables/arm_const_structs.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/TransformFunctions/arm_cfft_radix4_q15.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/TransformFunctions/arm_bitreversal2.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/TransformFunctions/arm_bitreversal.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/TransformFunctions/arm_cfft_init_q15.c
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Source/CommonTables/arm_mve_tables.c
+)
+
+target_include_directories(tfm_app_rot_partition_vad_an552
+    PRIVATE
+        .
+        Libraries
+        native_drivers
+        ns_interface
+        ${CMAKE_BINARY_DIR}/generated
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/Include
+        ${CMSIS_5_SRC_PATH}/CMSIS/DSP/PrivateInclude
+)
+
+target_compile_definitions(tfm_app_rot_partition_vad_an552
+    INTERFACE
+        CONFIG_TFM_BUILDING_SPE=1
+        ARM_ALL_FFT_TABLES
+)
+
+target_compile_options(tfm_app_rot_partition_vad_an552
+    PRIVATE
+        -flax-vector-conversions
+)
+
+target_include_directories(tfm_partitions
+    INTERFACE
+        .
+        ${CMAKE_BINARY_DIR}/generated
+)
+
+# IRQ handler should be part of SPM, the actual handling of the IRQ is done
+# in the partition
+target_sources(tfm_spm
+    PRIVATE
+        i2s_spm_irq.c
+)
+
+# The generated sources
+target_sources(tfm_app_rot_partition_vad_an552
+    PRIVATE
+        ${CMAKE_BINARY_DIR}/generated/auto_generated/intermedia_vad_an552_sp.c
+)
+target_sources(tfm_partitions
+    INTERFACE
+        ${CMAKE_BINARY_DIR}/generated/auto_generated/load_info_vad_an552_sp.c
+)
+
+target_link_libraries(tfm_app_rot_partition_vad_an552
+    PRIVATE
+        psa_interface
+        platform_s
+        tfm_sprt
+)
+
+############################ Partition Defs ####################################
+
+target_link_libraries(tfm_partitions
+    INTERFACE
+        tfm_app_rot_partition_vad_an552
+)
diff --git a/partitions/vad_an552_sp/Libraries/audio_codec_mps3.c b/partitions/vad_an552_sp/Libraries/audio_codec_mps3.c
new file mode 100644
index 0000000..bfccd05
--- /dev/null
+++ b/partitions/vad_an552_sp/Libraries/audio_codec_mps3.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "audio_codec_mps3.h"
+#include "i2c_sbcon_drv.h"
+#include "audio_i2s_mps3_drv.h"
+#include "timeout.h"
+
+#define CHIP_ADDR_WRITE     0x96
+#define CHIP_ADDR_READ      0x97
+
+/**
+ * \brief CS42L52 Audio Codec registers
+ */
+#define AUDIO_CODEC_MPS3_CHIP_ID     0x01 /*!< Chip ID and Revision Register */
+#define AUDIO_CODEC_MPS3_PWR_CTRL1   0x02 /*!< Power Control 1 */
+#define AUDIO_CODEC_MPS3_PWR_CTRL2   0x03 /*!< Power Control 2 */
+#define AUDIO_CODEC_MPS3_PWR_CTRL3   0x04 /*!< Power Control 3 */
+#define AUDIO_CODEC_MPS3_CLK_CTRL    0x05 /*!< Clocking Control */
+#define AUDIO_CODEC_MPS3_INT_CTRL1   0x06 /*!< Interface Control 1 */
+#define AUDIO_CODEC_MPS3_INT_CTRL2   0x07 /*!< Interface Control 2 */
+#define AUDIO_CODEC_MPS3_INPUT_A     0x08 /*!< Input x Select: ADCA and PGAA */
+#define AUDIO_CODEC_MPS3_INPUT_B     0x09 /*!< Input x Select: ADCB and PGAB */
+#define AUDIO_CODEC_MPS3_AMP_A       0x10 /*!< MICx Amp Control:MIC A */
+#define AUDIO_CODEC_MPS3_AMP_B       0x11 /*!< MICx Amp Control:MIC B */
+#define AUDIO_CODEC_MPS3_MISC_CTRL   0x0E /*!< Miscellaneous Controls */
+
+static void audio_codec_mps3_write(struct i2c_sbcon_dev_t *i2c_sbcon_dev,
+                                   uint8_t map_byte, uint8_t data)
+{
+    uint32_t i;
+    uint8_t to_write[2];
+
+    to_write[0] = map_byte;
+    to_write[1] = data;
+    i2c_sbcon_master_transmit(
+                        i2c_sbcon_dev, CHIP_ADDR_WRITE, to_write, 2, 0, &i);
+}
+
+static uint8_t audio_codec_mps3_read(struct i2c_sbcon_dev_t *i2c_sbcon_dev,
+                                     uint8_t map_byte)
+{
+    uint32_t i;
+    uint8_t data;
+
+    i2c_sbcon_master_transmit(
+                        i2c_sbcon_dev, CHIP_ADDR_WRITE, &map_byte, 1, 0, &i);
+    i2c_sbcon_master_receive(i2c_sbcon_dev, CHIP_ADDR_READ, &data, 1, 0, &i);
+
+    return data;
+}
+
+enum audio_codec_mps3_error_t audio_codec_mps3_init(
+                                    struct i2c_sbcon_dev_t *i2c_sbcon_dev,
+                                    struct audio_i2s_mps3_dev_t *audio_i2s_mps3_dev)
+{
+    uint8_t reg_32;
+
+    i2c_sbcon_init(i2c_sbcon_dev, WAIT_US_FREQ_HZ);
+    audio_i2s_mps3_set_codec_reset(audio_i2s_mps3_dev);
+    wait_ms(1);
+
+    audio_i2s_mps3_clear_codec_reset(audio_i2s_mps3_dev);
+    wait_ms(1);
+
+    /* Initialization with values given in the Reference Manual */
+    audio_codec_mps3_write(i2c_sbcon_dev, 0x00, 0x99);
+    audio_codec_mps3_write(i2c_sbcon_dev, 0x3E, 0xBA);
+    audio_codec_mps3_write(i2c_sbcon_dev, 0x47, 0x80);
+    reg_32 = audio_codec_mps3_read(i2c_sbcon_dev, 0x32);
+    audio_codec_mps3_write(i2c_sbcon_dev, 0x32, reg_32 | 0x80);
+    audio_codec_mps3_write(i2c_sbcon_dev, 0x32, reg_32 & 0x7F);
+    audio_codec_mps3_write(i2c_sbcon_dev, 0x00, 0x00);
+    wait_ms(1);
+
+    /* Single-speed mode */
+    audio_codec_mps3_write(i2c_sbcon_dev, AUDIO_CODEC_MPS3_CLK_CTRL, 0x20);
+    /* ADC charge pump and PGA & ADC channels powered up */
+    audio_codec_mps3_write(i2c_sbcon_dev, AUDIO_CODEC_MPS3_PWR_CTRL1, 0x00);
+    /* MIC powered up */
+    audio_codec_mps3_write(i2c_sbcon_dev, AUDIO_CODEC_MPS3_PWR_CTRL2, 0x00);
+    /* Headphone and Speaker channel always on */
+    audio_codec_mps3_write(i2c_sbcon_dev, AUDIO_CODEC_MPS3_PWR_CTRL3, 0xAA);
+    /* Select analog input for PGA AIN4A and AIN4B */
+    audio_codec_mps3_write(i2c_sbcon_dev, AUDIO_CODEC_MPS3_INPUT_A, 0x90);
+    audio_codec_mps3_write(i2c_sbcon_dev, AUDIO_CODEC_MPS3_INPUT_B, 0x90);
+    /* Select MIC inputs and sets microphone pre-amplifier 32 dB */
+    audio_codec_mps3_write(i2c_sbcon_dev, AUDIO_CODEC_MPS3_AMP_A, 0x5F);
+    audio_codec_mps3_write(i2c_sbcon_dev, AUDIO_CODEC_MPS3_AMP_B, 0x5F);
+    /* De-emphasis filter enabled */
+    audio_codec_mps3_write(i2c_sbcon_dev, AUDIO_CODEC_MPS3_MISC_CTRL, 0x04);
+    wait_ms(1);
+
+    return AUDIO_CODEC_MPS3_ERR_NONE;
+}
diff --git a/partitions/vad_an552_sp/Libraries/audio_codec_mps3.h b/partitions/vad_an552_sp/Libraries/audio_codec_mps3.h
new file mode 100644
index 0000000..f8112eb
--- /dev/null
+++ b/partitions/vad_an552_sp/Libraries/audio_codec_mps3.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/**
+ * \file audio_codec_mps3.h
+ *
+ * \brief CS42L52 Audio Codec configuration.
+ * The control port operates using an I2C interface.
+ */
+
+#ifndef __AUDIO_CODEC_MPS3_H__
+#define __AUDIO_CODEC_MPS3_H__
+
+#include <stdint.h>
+#include "i2c_sbcon_drv.h"
+#include "audio_i2s_mps3_drv.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief CS42L52 Audio Codec error enumeration types
+ */
+enum audio_codec_mps3_error_t {
+    AUDIO_CODEC_MPS3_ERR_NONE = 0,      /*!< No error */
+};
+
+/**
+ * \brief Initializes Audio Codec
+ *
+ * \param[in] i2c_sbcon_dev I2C device struct \ref i2c_sbcon_dev
+ * \param[in] audio_i2s_mps3_dev I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \return Returns error code as specified in \ref audio_codec_mps3_error_t
+ */
+enum audio_codec_mps3_error_t audio_codec_mps3_init(
+                            struct i2c_sbcon_dev_t *i2c_sbcon_dev,
+                            struct audio_i2s_mps3_dev_t *audio_i2s_mps3_dev);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __AUDIO_CODEC_MPS3_H__ */
diff --git a/partitions/vad_an552_sp/Libraries/systimer_armv8-m_timeout.c b/partitions/vad_an552_sp/Libraries/systimer_armv8-m_timeout.c
new file mode 100644
index 0000000..4913e27
--- /dev/null
+++ b/partitions/vad_an552_sp/Libraries/systimer_armv8-m_timeout.c
@@ -0,0 +1,108 @@
+/*
+* Copyright (c) 2019-2022 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 "timeout.h"
+#include "systimer_armv8-m_drv.h"
+#include "vad_an552_device_definition.h"
+
+#define MS_TO_TICK(ms)  ((ms) * (SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ / 1000))
+#define US_TO_TICK(us)  ((us) * (SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ) / 1000000)
+/* Systimer is configured over the 32-bit down-counting Timer view, so maximum
+ * delay is defined by its bit width. */
+#define MAX_DELAY_MS    (UINT32_MAX / \
+                            (SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ / 1000))
+#define MAX_DELAY_US    (UINT32_MAX / \
+                            (SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ / 1000000))
+static uint32_t delay_in_tick;
+
+bool timeout_init(struct timeout_t *timeout, uint32_t delay)
+{
+    struct systimer_armv8_m_dev_t *dev;
+
+    if (!timeout || delay > MAX_DELAY_MS) {
+        return false;
+    }
+
+    if (timeout->is_initialized) {
+        return false;
+    }
+
+    dev = &SYSTIMER3_ARMV8_M_DEV_S;
+    systimer_armv8_m_init(dev);
+
+    delay_in_tick =  MS_TO_TICK(delay);
+    systimer_armv8_m_set_timer_value(dev, delay_in_tick);
+
+    timeout->dev_ptr = (void *)dev;
+    timeout->is_initialized = true;
+
+    return true;
+}
+
+bool timeout_init_us(struct timeout_t *timeout, uint32_t delay)
+{
+    struct systimer_armv8_m_dev_t *dev;
+
+    if (!timeout || delay > MAX_DELAY_US) {
+        return false;
+    }
+
+    if (timeout->is_initialized) {
+        return false;
+    }
+
+    dev = &SYSTIMER3_ARMV8_M_DEV_S;
+    systimer_armv8_m_init(dev);
+
+    delay_in_tick =  US_TO_TICK(delay);
+    systimer_armv8_m_set_timer_value(dev, delay_in_tick);
+
+    timeout->dev_ptr = (void *)dev;
+    timeout->is_initialized = true;
+
+    return true;
+}
+
+bool timeout_delay_is_elapsed(struct timeout_t *timeout)
+{
+    struct systimer_armv8_m_dev_t* dev;
+
+    if (!timeout || !timeout->is_initialized) {
+        return false;
+    }
+
+    dev = (struct systimer_armv8_m_dev_t*)timeout->dev_ptr;
+    if (systimer_armv8_m_is_interrupt_asserted(dev)) {
+        systimer_armv8_m_set_timer_value(dev, delay_in_tick);
+        return true;
+    }
+
+    return false;
+}
+
+void wait_us(uint32_t usec)
+{
+    static struct timeout_t timeout = {false, false};
+    timeout_init_us(&timeout, usec);
+    while (!timeout_delay_is_elapsed(&timeout));
+}
+
+void wait_ms(uint32_t ms)
+{
+    static struct timeout_t timeout = {false, false};
+    timeout_init(&timeout, ms);
+    while (!timeout_delay_is_elapsed(&timeout));
+}
diff --git a/partitions/vad_an552_sp/Libraries/timeout.h b/partitions/vad_an552_sp/Libraries/timeout.h
new file mode 100644
index 0000000..d0998b1
--- /dev/null
+++ b/partitions/vad_an552_sp/Libraries/timeout.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017-2022 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.
+ */
+
+#ifndef __TIMEOUT_H__
+#define __TIMEOUT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include "vad_an552_device_definition.h"
+
+#define WAIT_US_FREQ_HZ SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ
+
+/* Structure to maintain elapsed time */
+struct timeout_t {
+    void *dev_ptr;
+    bool is_initialized;
+};
+
+/**
+ * \brief Initializes timeout structure
+ *
+ * \param[in] timeout Pointer to the timeout structure
+ * \param[in] delay   Delay in ms to check timeout against
+ *
+ * \return Returns true if the delay value was set,
+ *         false otherwise
+ */
+bool timeout_init(struct timeout_t *timeout, uint32_t delay);
+
+/**
+ * \brief Initializes timeout structure
+ *
+ * \param[in] timeout Pointer to the timeout structure
+ * \param[in] delay   Delay in us to check timeout against
+ *
+ * \return Returns true if the delay value was set,
+ *         false otherwise
+ */
+bool timeout_init_us(struct timeout_t *timeout, uint32_t delay);
+
+/**
+ * \brief Checks if the given time has passed or not
+ *
+ * \param[in] timer Pointer to the timer structure
+ *
+ * \details This function compares the timestamp stored in the timeout structure
+ *          and the current time. If the difference is more than the given delay,
+ *          the current time is stored and will be used for the next comparison
+ *
+ * \return 1 if the given time has passed, 0 if not
+ */
+bool timeout_delay_is_elapsed(struct timeout_t *timeout);
+
+/**
+ * \brief Uninitializes timout structure and stops timer operation.
+ *
+ * \param[in] timeout Pointer to the timeout structure
+ */
+void timeout_uninit(struct timeout_t *timeout);
+
+/**
+ * \brief Waits the specified time in milliseconds.
+ *
+ * \param[in] ms Time to wait in milliseconds
+ */
+void wait_ms(uint32_t ms);
+
+/**
+ * \brief Waits the specified time in microseconds.
+ *
+ * \param[in] us Time to wait in microseconds
+ */
+void wait_us(uint32_t us);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __TIMEOUT_H__ */
diff --git a/partitions/vad_an552_sp/ext/CMSIS/CMakeLists.txt b/partitions/vad_an552_sp/ext/CMSIS/CMakeLists.txt
new file mode 100644
index 0000000..d54b898
--- /dev/null
+++ b/partitions/vad_an552_sp/ext/CMSIS/CMakeLists.txt
@@ -0,0 +1,27 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+include(FetchContent)
+set(FETCHCONTENT_QUIET FALSE)
+
+# Needed to specfy submodule list
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0")
+    cmake_policy(SET CMP0097 NEW)
+endif()
+
+if ("${CMSIS_5_SRC_PATH}" STREQUAL "DOWNLOAD")
+    find_package(Git)
+
+    FetchContent_Declare(cmsis_5
+        GIT_REPOSITORY https://github.com/ARM-software/CMSIS_5.git
+        GIT_TAG 5.8.0
+    )
+    FetchContent_GetProperties(cmsis_5)
+    if (NOT cmsis_5)
+        FetchContent_Populate(cmsis_5)
+        set(CMSIS_5_SRC_PATH ${cmsis_5_SOURCE_DIR} CACHE PATH "Path to CMSIS_5 repository (or DOWNLOAD to fetch automatically" FORCE)
+    endif ()
+endif ()
diff --git a/partitions/vad_an552_sp/ext/arm-endpoint-ai/CMakeLists.txt b/partitions/vad_an552_sp/ext/arm-endpoint-ai/CMakeLists.txt
new file mode 100644
index 0000000..1983e5f
--- /dev/null
+++ b/partitions/vad_an552_sp/ext/arm-endpoint-ai/CMakeLists.txt
@@ -0,0 +1,27 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+include(FetchContent)
+set(FETCHCONTENT_QUIET FALSE)
+
+# Needed to specfy submodule list
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0")
+    cmake_policy(SET CMP0097 NEW)
+endif()
+
+if ("${ARM_ENDPOINTAI_SRC_PATH}" STREQUAL "DOWNLOAD")
+    find_package(Git)
+
+    FetchContent_Declare(arm_endpoint_ai
+        GIT_REPOSITORY https://github.com/ARM-software/EndpointAI.git
+        GIT_TAG 80c5b64888ba9f5d26defb4db0ef178786ff65b9
+    )
+    FetchContent_GetProperties(arm_endpoint_ai)
+    if (NOT arm_endpoint_ai)
+        FetchContent_Populate(arm_endpoint_ai)
+        set(ARM_ENDPOINTAI_SRC_PATH ${arm_endpoint_ai_SOURCE_DIR} CACHE PATH "Path to Arm's EndpointAI repository (or DOWNLOAD to fetch automatically" FORCE)
+    endif ()
+endif ()
diff --git a/partitions/vad_an552_sp/extra_manifest_list.yaml b/partitions/vad_an552_sp/extra_manifest_list.yaml
new file mode 100644
index 0000000..a1bde45
--- /dev/null
+++ b/partitions/vad_an552_sp/extra_manifest_list.yaml
@@ -0,0 +1,27 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2018-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+  "description": "Extra manifest list for VAD AN552 example",
+  "type": "manifest_list",
+  "version_major": 0,
+  "version_minor": 1,
+  "manifest_list": [
+    {
+      "description": "VAD AN552 Example Partition",
+      "manifest": "vad_an552_sp.yaml",
+      "version_major": 0,
+      "version_minor": 1,
+      "pid": 274,
+      "linker_pattern": {
+        "library_list": [
+           "*vad_an552.*"
+        ]
+      }
+    }
+  ]
+}
diff --git a/partitions/vad_an552_sp/i2s_spm_irq.c b/partitions/vad_an552_sp/i2s_spm_irq.c
new file mode 100644
index 0000000..bf072f8
--- /dev/null
+++ b/partitions/vad_an552_sp/i2s_spm_irq.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "cmsis.h"
+#include "ffm/interrupt.h"
+#include "load/interrupt_defs.h"
+#include "tfm_peripherals_def.h"
+
+/* Structure for IRQ handling by SPM */
+static struct irq_t i2s_irq = {0};
+
+void I2S_Handler(void)
+{
+    spm_handle_interrupt(i2s_irq.p_pt, i2s_irq.p_ildi);
+}
+
+enum tfm_hal_status_t i2s_irqn_init(void *p_pt,
+                                    struct irq_load_info_t *p_ildi)
+{
+    i2s_irq.p_ildi = p_ildi;
+    i2s_irq.p_pt = p_pt;
+
+    NVIC_SetPriority(I2S_IRQn, DEFAULT_IRQ_PRIORITY);
+    NVIC_ClearTargetState(I2S_IRQn);
+    NVIC_DisableIRQ(I2S_IRQn);
+
+    return TFM_HAL_SUCCESS;
+}
diff --git a/partitions/vad_an552_sp/native_drivers/audio_i2s_mps3_drv.c b/partitions/vad_an552_sp/native_drivers/audio_i2s_mps3_drv.c
new file mode 100644
index 0000000..803b820
--- /dev/null
+++ b/partitions/vad_an552_sp/native_drivers/audio_i2s_mps3_drv.c
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "audio_i2s_mps3_drv.h"
+
+/**
+ * \brief Audio I2S register map structure
+ */
+struct audio_i2s_mps3_reg_map_t{
+        /* Offset: 0x000 (R/W) Control Register    */
+    volatile uint32_t control;
+        /* Offset: 0x004 (R/W) Status Register    */
+    volatile uint32_t status;
+        /* Offset: 0x008 (R/W) Error Register    */
+    volatile uint32_t error;
+        /* Offset: 0x00C (R/W) Clock Divide Ratio Register    */
+    volatile uint32_t divide;
+        /* Offset: 0x010 (W) Transmit Buffer FIFO Data Register    */
+    volatile uint32_t txbuf;
+        /* Offset: 0x014 (R) Receive Buffer FIFO Data Register    */
+    volatile uint32_t rxbuf;
+        /*!< Offset: 0x018-0x2FF Reserved */
+    volatile const uint32_t reserved[14];
+        /* Offset: 0x300 (R/W) Integration Test Control Register    */
+    volatile uint32_t itcr;
+        /* Offset: 0x304 (R/W) Integration Test Input Register    */
+    volatile uint32_t itip1;
+        /* Offset: 0x308 (R/W) Integration Test Output Register    */
+    volatile uint32_t itop1;
+};
+
+/**
+ * \brief Audio I2S Control Register bit fields
+ */
+#define AUDIO_I2S_MPS3_CONTROL_TX_EN_OFF                 0u
+    /*!< Audio I2S Control Register Tx Enable bit field offset */
+#define AUDIO_I2S_MPS3_CONTROL_TX_INTREN_OFF             1u
+    /*!< Audio I2S Control Register Tx Interrupt Enable bit field offset */
+#define AUDIO_I2S_MPS3_CONTROL_RX_EN_OFF                 2u
+    /*!< Audio I2S Control Register Rx Enable bit field offset */
+#define AUDIO_I2S_MPS3_CONTROL_RX_INTREN_OFF             3u
+    /*!< Audio I2S Control Register Rx Interrupt Enable bit field offset */
+#define AUDIO_I2S_MPS3_CONTROL_TX_BUFF_IRQ_WATER_LVL_OFF 8u
+    /*!< Audio I2S Control Register Tx Buffer Interrupt Water Level Offset */
+#define AUDIO_I2S_MPS3_CONTROL_RX_BUFF_IRQ_WATER_LVL_OFF 12u
+    /*!< Audio I2S Control Register Rx Buffer Interrupt Water Level Offset */
+#define AUDIO_I2S_MPS3_CONTROL_FIFO_RESET_OFF            16u
+    /*!< Audio I2S Control Register FIFO Reset bit field offset */
+#define AUDIO_I2S_MPS3_CONTROL_CODEC_RESET_OFF           17u
+    /*!< Audio I2S Control Register Audio Codec Reset bit field offset */
+
+/**
+ * \brief Audio I2S Status Register bit fields
+ */
+#define AUDIO_I2S_MPS3_STATUS_TXBUF_EMPTY_OFF             2u
+    /*!< Audio I2S Status Register Tx Buffer Empty bit field offset */
+#define AUDIO_I2S_MPS3_STATUS_TXBUF_FULL_OFF              3u
+    /*!< Audio I2S Status Register Tx Buffer Full bit field offset */
+#define AUDIO_I2S_MPS3_STATUS_RXBUF_EMPTY_OFF             4u
+    /*!< Audio I2S Status Register Tx Buffer Empty bit field offset */
+#define AUDIO_I2S_MPS3_STATUS_RXBUF_FULL_OFF              5u
+    /*!< Audio I2S Status Register Tx Buffer Full bit field offset */
+
+#define LRDIV_MAX_VALUE     0x3FF
+
+void audio_i2s_mps3_set_codec_reset(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s =
+                (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control |= (1 << AUDIO_I2S_MPS3_CONTROL_CODEC_RESET_OFF);
+}
+
+void audio_i2s_mps3_set_fifo_reset(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s =
+                (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control |= (1 << AUDIO_I2S_MPS3_CONTROL_FIFO_RESET_OFF);
+}
+
+void audio_i2s_mps3_clear_codec_reset(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control &= ~(1 << AUDIO_I2S_MPS3_CONTROL_CODEC_RESET_OFF);
+}
+
+void audio_i2s_mps3_clear_fifo_reset(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control &= ~(1 <<  AUDIO_I2S_MPS3_CONTROL_FIFO_RESET_OFF);
+}
+
+enum audio_i2s_mps3_error_t audio_i2s_mps3_speed_config(struct audio_i2s_mps3_dev_t* dev, uint16_t lrdiv)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+
+    if ( lrdiv > LRDIV_MAX_VALUE ) {
+        return AUDIO_I2S_MPS3_ERR_INVALID_ARG;
+    }
+    p_i2s->divide = lrdiv;
+    return AUDIO_I2S_MPS3_ERR_NONE;
+}
+
+bool audio_i2s_mps3_is_rx_buffer_empty(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    return (bool)((p_i2s->status >> AUDIO_I2S_MPS3_STATUS_RXBUF_EMPTY_OFF) & 0x1);
+}
+
+bool audio_i2s_mps3_is_rx_buffer_full(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    return (bool)((p_i2s->status >> AUDIO_I2S_MPS3_STATUS_RXBUF_FULL_OFF) & 0x1);
+}
+
+bool audio_i2s_mps3_is_tx_buffer_empty(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    return (bool)((p_i2s->status >> AUDIO_I2S_MPS3_STATUS_TXBUF_EMPTY_OFF) & 0x1);
+}
+
+bool audio_i2s_mps3_is_tx_buffer_full(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    return (bool)((p_i2s->status >> AUDIO_I2S_MPS3_STATUS_TXBUF_FULL_OFF) & 0x1);
+}
+
+uint32_t audio_i2s_mps3_get_rxbuf(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    return p_i2s->rxbuf;
+}
+
+void audio_i2s_mps3_set_txbuf(struct audio_i2s_mps3_dev_t* dev, uint16_t left_channel,
+                    uint16_t right_channel)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    uint32_t sample = ((uint32_t)left_channel) << 16;
+    sample += right_channel;
+    p_i2s->txbuf = sample;
+}
+
+uint32_t audio_i2s_mps3_get_control(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    return p_i2s->control;
+}
+
+uint32_t audio_i2s_mps3_get_status(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    return p_i2s->status;
+}
+
+uint32_t audio_i2s_mps3_get_error(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    return p_i2s->error;
+}
+
+void audio_i2s_mps3_enable_rxbuf(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control |= (1 << AUDIO_I2S_MPS3_CONTROL_RX_EN_OFF);
+}
+
+void audio_i2s_mps3_enable_rxinterrupt(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control |= (1 << AUDIO_I2S_MPS3_CONTROL_RX_INTREN_OFF);
+}
+
+void audio_i2s_mps3_enable_txbuf(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control |= (1 << AUDIO_I2S_MPS3_CONTROL_TX_EN_OFF);
+}
+
+void audio_i2s_mps3_enable_txinterrupt(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control |= (1 <<  AUDIO_I2S_MPS3_CONTROL_TX_INTREN_OFF);
+}
+
+void audio_i2s_mps3_disable_rxbuf(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control &= ~(1 <<  AUDIO_I2S_MPS3_CONTROL_RX_EN_OFF);
+}
+
+void audio_i2s_mps3_disable_rxinterrupt(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control &= ~(1 <<  AUDIO_I2S_MPS3_CONTROL_RX_INTREN_OFF);
+}
+
+void audio_i2s_mps3_disable_txbuf(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control &= ~(1 <<  AUDIO_I2S_MPS3_CONTROL_TX_EN_OFF);
+}
+
+void audio_i2s_mps3_disable_txinterrupt(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control &= ~(1 <<  AUDIO_I2S_MPS3_CONTROL_TX_INTREN_OFF);
+}
+
+struct audio_i2s_mps3_sample_t read_sample(struct audio_i2s_mps3_dev_t* dev)
+{
+    struct audio_i2s_mps3_sample_t sample;
+    uint32_t s = audio_i2s_mps3_get_rxbuf(dev);
+    sample.right_channel = s & 0xFFFF;
+    sample.left_channel = s >> 16;
+    return sample;
+}
+
+void write_sample(struct audio_i2s_mps3_dev_t* dev, struct audio_i2s_mps3_sample_t sample)
+{
+    audio_i2s_mps3_set_txbuf(dev, sample.left_channel, sample.right_channel);
+}
+
+void audio_i2s_mps3_set_tx_buff_water_lvl(struct audio_i2s_mps3_dev_t* dev,
+                                          uint8_t level){
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control = (p_i2s->control & ~(0x7 << AUDIO_I2S_MPS3_CONTROL_TX_BUFF_IRQ_WATER_LVL_OFF)) |
+                     ((level & 0x7) << AUDIO_I2S_MPS3_CONTROL_TX_BUFF_IRQ_WATER_LVL_OFF);
+}
+
+uint8_t audio_i2s_mps3_get_tx_buff_water_lvl(struct audio_i2s_mps3_dev_t* dev){
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+
+    return (uint8_t)((p_i2s->control >> AUDIO_I2S_MPS3_CONTROL_TX_BUFF_IRQ_WATER_LVL_OFF) & 0x7);
+}
+
+void audio_i2s_mps3_set_rx_buff_water_lvl(struct audio_i2s_mps3_dev_t* dev,
+                                          uint8_t level){
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+    p_i2s->control = (p_i2s->control & ~(0x7 << AUDIO_I2S_MPS3_CONTROL_RX_BUFF_IRQ_WATER_LVL_OFF)) |
+                     ((level & 0x7) << AUDIO_I2S_MPS3_CONTROL_RX_BUFF_IRQ_WATER_LVL_OFF);
+}
+
+uint8_t audio_i2s_mps3_get_rx_buff_water_lvl(struct audio_i2s_mps3_dev_t* dev){
+    struct audio_i2s_mps3_reg_map_t* p_i2s = (struct audio_i2s_mps3_reg_map_t*)dev->cfg->base;
+
+    return (uint8_t)((p_i2s->control >> AUDIO_I2S_MPS3_CONTROL_RX_BUFF_IRQ_WATER_LVL_OFF) & 0x7);
+}
diff --git a/partitions/vad_an552_sp/native_drivers/audio_i2s_mps3_drv.h b/partitions/vad_an552_sp/native_drivers/audio_i2s_mps3_drv.h
new file mode 100644
index 0000000..e16012f
--- /dev/null
+++ b/partitions/vad_an552_sp/native_drivers/audio_i2s_mps3_drv.h
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/**
+ * \file audio_i2s_mps3_drv.h
+ *
+ * \brief Driver for Audio I2S
+ *
+ * The I2S interface supports transfer of digital audio to and
+ * from the Audio CODEC
+ *
+ * Main features:
+ *   - Clear/Set Control Register bits to enable or disable buffer or interrupt
+ *     and to reset Audio codec or FIFO
+ *   - Check status of receive and transmit buffer
+ *   - Get receive buffer data
+ *   - Set transmit buffer data
+ *   - Get Control, Status, Error register value
+ *   - Write/Read sample
+ */
+
+#ifndef __AUDIO_I2S_MPS3_DRV_H__
+#define __AUDIO_I2S_MPS3_DRV_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Audio I2S device configuration structure
+ */
+struct audio_i2s_mps3_dev_cfg_t{
+    const uint32_t base;
+    /*!< Audio I2S device base address */
+};
+
+/**
+ * \brief Audio I2S device structure
+ */
+struct audio_i2s_mps3_dev_t {
+    const struct audio_i2s_mps3_dev_cfg_t* const cfg;
+    /*!< Audio I2S configuration structure */
+};
+
+/**
+ * \brief I2S audio sample structure
+ */
+struct audio_i2s_mps3_sample_t{
+    uint16_t left_channel;
+    uint16_t right_channel;
+};
+
+/**
+ * \brief Audio I2S error enumeration types
+ */
+enum audio_i2s_mps3_error_t{
+    AUDIO_I2S_MPS3_ERR_NONE = 0,      /*!< No error */
+    AUDIO_I2S_MPS3_ERR_INVALID_ARG,   /*!< Error invalid input argument */
+};
+
+/**
+ * \brief Reset Audio codec
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_set_codec_reset(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Reset FIFO
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_set_fifo_reset(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Clear Audio codec reset
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_clear_codec_reset(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Clear FIFO reset
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_clear_fifo_reset(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Checks if Receive Buffer is empty
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \return True if it is empty, False otherwise
+ */
+bool audio_i2s_mps3_is_rx_buffer_empty(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Checks if Receive Buffer is full
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \return True if it is full, False otherwise
+ */
+bool audio_i2s_mps3_is_rx_buffer_full(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Checks if Transmit Buffer is empty
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \return True if it is empty, False otherwise
+ */
+bool audio_i2s_mps3_is_tx_buffer_empty(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Checks if Transmit Buffer is full
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \return True if it is full, False otherwise
+ */
+bool audio_i2s_mps3_is_tx_buffer_full(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Sets clock divider value
+ *
+ * \param[in] dev   Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ * \param[in] lrdiv divide value
+ *
+ * \return Returns error code as specified in \ref audio_i2s_mps3_error_t
+ */
+enum audio_i2s_mps3_error_t audio_i2s_mps3_speed_config(struct audio_i2s_mps3_dev_t* dev, uint16_t lrdiv);
+
+/**
+ * \brief Get Receive Buffer FIFO Data Register
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \return Returns register value
+ */
+uint32_t audio_i2s_mps3_get_rxbuf(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Set Transmit Buffer Fifo Data Register
+ *
+ * \param[in] dev            Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ * \param[in] left_channel   audio left channel value
+ * \param[in] right_channel  audio right channel value
+ */
+void audio_i2s_mps3_set_txbuf(struct audio_i2s_mps3_dev_t* dev, uint16_t left_channel,
+                    uint16_t right_channel);
+
+/**
+ * \brief Enable Receive Buffer
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_enable_rxbuf(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Enable Receive Interrupt
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_enable_rxinterrupt(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Enable Transmit Buffer
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_enable_txbuf(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Enable Transmit Interrupt
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_enable_txinterrupt(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Disable Receive Buffer
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_disable_rxbuf(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Disable Receive Interrupt
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_disable_rxinterrupt(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Disable Transmit Buffer
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_disable_txbuf(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Disable Transmit Interrupt
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ */
+void audio_i2s_mps3_disable_txinterrupt(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Get Control Register
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \return Returns register value
+ */
+uint32_t audio_i2s_mps3_get_control(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Get Status register
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \return Returns register value
+ */
+uint32_t audio_i2s_mps3_get_status(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Get Error Status Register
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \return Returns register value
+ */
+uint32_t audio_i2s_mps3_get_error(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Reads audio sample from Receive Buffer Register
+ *
+ * \param[in] dev Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \returns Returns an audio_i2s_mps3_sample_t structure
+ */
+struct audio_i2s_mps3_sample_t read_sample(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Writes audio sample to Transmit Buffer Register
+ *  *
+ * \param[in] dev      Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ * \param[in] sample   Value of an audio sample
+ */
+void write_sample(struct audio_i2s_mps3_dev_t* dev,
+                  struct audio_i2s_mps3_sample_t sample);
+
+/**
+ * \brief Set Tx Buffer Interrupt Water Level
+ *
+ * \param[in] dev    Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ * \param[in] level  Water level to be set (0-7)
+ */
+void audio_i2s_mps3_set_tx_buff_water_lvl(struct audio_i2s_mps3_dev_t* dev,
+                                          uint8_t level);
+
+/**
+ * \brief Get Tx Buffer Interrupt Water Level
+ *
+ * \param[in] dev    Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \returns Returns Tx Buffer Interrupt Water Level
+ */
+uint8_t audio_i2s_mps3_get_tx_buff_water_lvl(struct audio_i2s_mps3_dev_t* dev);
+
+/**
+ * \brief Set Rx Buffer Interrupt Water Level
+ *
+ * \param[in] dev    Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ * \param[in] level  Water level to be set (0-7)
+ */
+void audio_i2s_mps3_set_rx_buff_water_lvl(struct audio_i2s_mps3_dev_t* dev,
+                                          uint8_t level);
+
+/**
+ * \brief Get Rx Buffer Interrupt Water Level
+ *
+ * \param[in] dev    Audio I2S device struct \ref audio_i2s_mps3_dev_t
+ *
+ * \returns Returns Rx Buffer Interrupt Water Level
+ */
+uint8_t audio_i2s_mps3_get_rx_buff_water_lvl(struct audio_i2s_mps3_dev_t* dev);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __AUDIO_I2S_MPS3_DRV_H__ */
diff --git a/partitions/vad_an552_sp/native_drivers/i2c_sbcon_drv.c b/partitions/vad_an552_sp/native_drivers/i2c_sbcon_drv.c
new file mode 100644
index 0000000..4d95419
--- /dev/null
+++ b/partitions/vad_an552_sp/native_drivers/i2c_sbcon_drv.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2016-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.
+ */
+
+#include "i2c_sbcon_drv.h"
+
+#define SDA  (1 << 1)
+#define SCL  (1 << 0)
+#define I2C_HIGH(i2c_dev, pin) (i2c_dev->ctrl_reg.set = pin)
+#define I2C_LOW(i2c_dev, pin)  (i2c_dev->clear_reg = pin)
+#define I2C_GET(i2c_dev, pin)  ((i2c_dev->ctrl_reg.status >> (pin-1)) & 0x01)
+
+/* I2C SBCon state definitions */
+#define I2C_SBCON_INITIALIZED  (1 << 0)
+
+/* I2C SBCon register map structure */
+struct i2c_sbcon_ctrl_t {
+    union {
+        /* Offset: 0x000 Control Status Register (r/ ) */
+        volatile uint32_t status;
+        /* Offset: 0x000 Control Set Register    ( /w) */
+        volatile uint32_t set;
+    } ctrl_reg;
+    /* Offset: 0x004 Control Clear Register    ( /w) */
+    volatile uint32_t clear_reg;
+};
+
+/*
+ * \brief Transmits a data bit.
+ *
+ * \param[in] dev  Pointer to the I2C device \ref i2c_sbcon_dev_t
+ * \param[in] bit  Bit to transmit.
+ */
+static void i2c_tx_bit(const struct i2c_sbcon_dev_t* dev,
+                       uint8_t bit)
+{
+    struct i2c_sbcon_ctrl_t* p_i2c = (struct i2c_sbcon_ctrl_t*)dev->cfg->base;
+    if (bit != 0) {
+        I2C_HIGH(p_i2c, SDA);
+    } else {
+        I2C_LOW(p_i2c, SDA);
+    }
+
+    dev->cfg->sleep_us(dev->data->freq_us);
+
+    I2C_HIGH(p_i2c, SCL);
+    dev->cfg->sleep_us(dev->data->freq_us);
+
+    I2C_LOW(p_i2c, SCL);
+    dev->cfg->sleep_us(dev->data->freq_us);
+}
+
+/*
+ * \brief Reads a data bit
+ *
+ * \param[in] dev  Pointer to the I2C device \ref i2c_sbcon_dev_t
+ *
+ * \returns Bit value received.
+ */
+static uint8_t i2c_rx_bit(const struct i2c_sbcon_dev_t* dev)
+{
+    uint8_t bit;
+    struct i2c_sbcon_ctrl_t* p_i2c = (struct i2c_sbcon_ctrl_t*)dev->cfg->base;
+
+    I2C_HIGH(p_i2c, SDA);
+    dev->cfg->sleep_us(dev->data->freq_us);
+
+    I2C_HIGH(p_i2c, SCL);
+    dev->cfg->sleep_us(dev->data->freq_us);
+
+    bit = I2C_GET(p_i2c, SDA);
+
+    I2C_LOW(p_i2c, SCL);
+    dev->cfg->sleep_us(dev->data->freq_us);
+
+    return bit;
+}
+
+enum i2c_sbcon_error_t i2c_sbcon_init(struct i2c_sbcon_dev_t* dev,
+                                              uint32_t sys_clk)
+{
+    if (sys_clk == 0) {
+        return I2C_ERR_INVALID_ARG;
+    }
+
+    dev->data->sys_clk = sys_clk;
+
+    dev->data->freq_us = (sys_clk / dev->cfg->default_freq_hz);
+
+    dev->data->state = I2C_SBCON_INITIALIZED;
+
+    return I2C_ERR_NONE;
+}
+
+enum i2c_sbcon_error_t i2c_sbcon_reset(struct i2c_sbcon_dev_t* dev)
+{
+    uint32_t iter;
+    uint32_t freq_us = dev->data->freq_us;
+    struct i2c_sbcon_ctrl_t* p_i2c = (struct i2c_sbcon_ctrl_t*)dev->cfg->base;
+
+    if(!(dev->data->state & I2C_SBCON_INITIALIZED)) {
+        return I2C_ERR_NOT_INIT;
+    }
+
+    /* The reset sequence is:
+     *  - SDA line low
+     *  - 9 clock pulses
+     *  - SDA line high
+     */
+    I2C_LOW(p_i2c, SDA);
+    dev->cfg->sleep_us(freq_us);
+
+    for(iter=0; iter < 9; iter++) {
+        I2C_LOW(p_i2c, SCL);
+        dev->cfg->sleep_us(freq_us);
+        I2C_HIGH(p_i2c, SCL);
+        dev->cfg->sleep_us(freq_us);
+    }
+
+    I2C_HIGH(p_i2c, SDA);
+    dev->cfg->sleep_us(freq_us);
+
+    return I2C_ERR_NONE;
+}
+
+enum i2c_sbcon_error_t i2c_sbcon_set_freq(struct i2c_sbcon_dev_t* dev,
+                                          uint32_t i2c_hz)
+{
+    if (dev->data->sys_clk < i2c_hz || i2c_hz == 0) {
+        return I2C_ERR_INVALID_ARG;
+    }
+
+    if(!(dev->data->state & I2C_SBCON_INITIALIZED)) {
+        return I2C_ERR_NOT_INIT;
+    }
+
+    dev->data->freq_us = (dev->data->sys_clk / i2c_hz);
+
+    return I2C_ERR_NONE;
+}
+
+uint32_t i2c_sbcon_get_freq(struct i2c_sbcon_dev_t* dev)
+{
+    if(!(dev->data->state & I2C_SBCON_INITIALIZED)) {
+        return 0;
+    }
+
+    return (dev->data->freq_us * dev->data->sys_clk);
+}
+
+enum i2c_sbcon_error_t i2c_sbcon_set_sys_clk( struct i2c_sbcon_dev_t* dev,
+                                                uint32_t sys_clk)
+{
+    uint32_t i2c_hz;
+
+    if (sys_clk == 0) {
+        return I2C_ERR_INVALID_ARG;
+    }
+
+    if(!(dev->data->state & I2C_SBCON_INITIALIZED)) {
+        return I2C_ERR_NOT_INIT;
+    }
+
+    /* Gets I2C frequency in Hz */
+    i2c_hz = dev->data->freq_us * dev->data->sys_clk;
+
+    /* Saves new system clock value */
+    dev->data->sys_clk = sys_clk;
+
+    /* Saves the I2C frequencu in us */
+    dev->data->freq_us = (dev->data->sys_clk / i2c_hz);
+
+    return I2C_ERR_NONE;
+}
+
+void i2c_sbcon_tx_start(const struct i2c_sbcon_dev_t* dev)
+{
+    struct i2c_sbcon_ctrl_t* p_i2c = (struct i2c_sbcon_ctrl_t*)dev->cfg->base;
+
+    /* SDA goes from HIGH to LOW while SCL is HIGH */
+    I2C_HIGH(p_i2c, (SCL | SDA));
+    dev->cfg->sleep_us(dev->data->freq_us);
+
+    I2C_LOW(p_i2c, SDA);
+    dev->cfg->sleep_us(dev->data->freq_us);
+
+    I2C_LOW(p_i2c, SCL);
+    dev->cfg->sleep_us(dev->data->freq_us);
+}
+
+void i2c_sbcon_tx_stop(const struct i2c_sbcon_dev_t* dev)
+{
+    struct i2c_sbcon_ctrl_t* p_i2c = (struct i2c_sbcon_ctrl_t*)dev->cfg->base;
+
+    /* SDA goes from LOW to HIGH while SCL is HIGH */
+    I2C_LOW(p_i2c, SDA);
+    dev->cfg->sleep_us(dev->data->freq_us);
+
+    I2C_HIGH(p_i2c, SCL);
+    dev->cfg->sleep_us(dev->data->freq_us);
+
+    I2C_HIGH(p_i2c, SDA);
+    dev->cfg->sleep_us(dev->data->freq_us);
+}
+
+void i2c_sbcon_tx_ack(const struct i2c_sbcon_dev_t* dev, uint8_t ack)
+{
+    i2c_tx_bit(dev, ack);
+}
+
+void i2c_sbcon_tx_byte(const struct i2c_sbcon_dev_t* dev, uint8_t data)
+{
+    uint8_t nbr_bits  ;
+
+    for(nbr_bits=0; nbr_bits < 8; nbr_bits++) {
+        i2c_tx_bit(dev, data & 0x80);
+        data <<= 1;
+    }
+}
+
+uint8_t i2c_sbcon_rx_ack(const struct i2c_sbcon_dev_t* dev)
+{
+    uint8_t ack;
+
+    ack = i2c_rx_bit(dev);
+
+    return ack;
+}
+
+uint8_t i2c_sbcon_rx_byte(struct i2c_sbcon_dev_t* dev)
+{
+    uint8_t numBits;
+    uint8_t data = 0;
+
+    for (numBits = 0; numBits < 8; numBits++) {
+        data <<= 1;
+        data |= i2c_rx_bit(dev);
+    }
+
+    return data;
+}
+
+enum i2c_sbcon_error_t i2c_sbcon_master_transmit(
+                                                struct i2c_sbcon_dev_t* dev,
+                                                uint16_t addr,
+                                                const uint8_t* data,
+                                                uint32_t len,
+                                                uint8_t xfer_pending,
+                                                uint32_t* nbr_bytes_write)
+{
+    i2c_sbcon_tx_start(dev);
+
+    i2c_sbcon_tx_byte(dev, (uint8_t) addr);
+    i2c_sbcon_rx_ack(dev);
+
+    if(addr & I2C_10BIT) {
+        i2c_sbcon_tx_byte(dev, (uint8_t)(addr >> 8));
+        i2c_sbcon_rx_ack(dev);
+    }
+
+    for (*nbr_bytes_write = 0; *nbr_bytes_write < len; (*nbr_bytes_write)++) {
+        i2c_sbcon_tx_byte(dev, data[*nbr_bytes_write]);
+        i2c_sbcon_rx_ack(dev);
+    }
+
+    if (!xfer_pending) {
+        i2c_sbcon_tx_stop(dev);
+    }
+
+    return I2C_ERR_NONE;
+}
+
+enum i2c_sbcon_error_t i2c_sbcon_master_receive(
+                                              struct i2c_sbcon_dev_t* dev,
+                                              uint16_t addr, uint8_t* data,
+                                              uint32_t len,
+                                              uint8_t xfer_pending,
+                                              uint32_t* nbr_bytes_read)
+{
+    i2c_sbcon_tx_start(dev);
+
+    i2c_sbcon_tx_byte(dev, (uint8_t) (addr | 0x1));
+    i2c_sbcon_rx_ack(dev);
+
+    if(addr & I2C_10BIT) {
+        i2c_sbcon_tx_byte(dev, (uint8_t)(addr >> 8));
+        i2c_sbcon_rx_ack(dev);
+    }
+
+    data[0] = i2c_sbcon_rx_byte(dev);
+    for (*nbr_bytes_read = 1; *nbr_bytes_read < len; (*nbr_bytes_read)++) {
+        i2c_sbcon_tx_ack(dev, 0);
+        data[*nbr_bytes_read] = i2c_sbcon_rx_byte(dev);
+    }
+    i2c_sbcon_tx_ack(dev, 1);
+
+    if (!xfer_pending) {
+        i2c_sbcon_tx_stop(dev);
+    }
+
+    return I2C_ERR_NONE;
+}
diff --git a/partitions/vad_an552_sp/native_drivers/i2c_sbcon_drv.h b/partitions/vad_an552_sp/native_drivers/i2c_sbcon_drv.h
new file mode 100644
index 0000000..b4487aa
--- /dev/null
+++ b/partitions/vad_an552_sp/native_drivers/i2c_sbcon_drv.h
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2016-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 i2c_sbcon_drv.h
+ * \brief Generic driver for I2C SBCon.
+ * The I2C SBCon IP requires a bit banging programing model.
+ */
+
+#ifndef __I2C_SBCON_DRV_H__
+#define __I2C_SBCON_DRV_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+
+#define I2C_10BIT  0x0400
+
+/**
+ * \brief Sleeps for a given amount of microseconds.
+ *
+ * \param[in] us  Microseconds to sleep.
+ */
+typedef void SLEEP_US(uint32_t us);
+
+/* I2C SBCon device configuration structure */
+struct i2c_sbcon_dev_cfg_t {
+    const uint32_t base;             /*!< I2C SBCon base address */
+    const uint32_t default_freq_hz;  /*!< Operational frequence in Hz */
+    SLEEP_US* const sleep_us;        /*!< Sleep function in us */
+};
+
+/* I2C SBCon device data structure */
+struct i2c_sbcon_dev_data_t {
+    uint32_t freq_us;  /*!< Operational frequence in us */
+    uint32_t sys_clk;  /*!< System clock frequency */
+    uint32_t state;    /*!< Indicates if the I2C SBCon driver
+                            is initialized */
+};
+
+/* I2C SBCon device structure */
+struct i2c_sbcon_dev_t {
+    const struct i2c_sbcon_dev_cfg_t* const cfg;      /*!< I2C SBCon
+                                                           configuration */
+    struct i2c_sbcon_dev_data_t* const data;      /*!< I2C SBCon data */
+};
+
+/* Error codes returned by the driver functions */
+enum i2c_sbcon_error_t {
+    I2C_ERR_NONE,         /*!< No error */
+    I2C_ERR_INVALID_ARG,  /*!< I2C invalid input arguments */
+    I2C_ERR_NOT_INIT,     /*!< I2C not initialized */
+};
+
+/**
+ * \brief Initializes I2C controller.
+ *
+ * \param[in] dev      I2C device struct \ref i2c_sbcon_dev_t
+ * \param[in] sys_clk  System clock frequency.
+ *
+ * \return Returns error code as specified in \ref i2c_sbcon_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum i2c_sbcon_error_t i2c_sbcon_init(struct i2c_sbcon_dev_t* dev,
+                                              uint32_t sys_clk);
+
+/**
+ * \brief Resets I2C controller.
+ *
+ * \param[in] dev  I2C device struct \ref i2c_sbcon_dev_t
+ *
+ * \return Returns error code as specified in \ref i2c_sbcon_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum i2c_sbcon_error_t i2c_sbcon_reset(struct i2c_sbcon_dev_t* dev);
+
+/**
+ * \brief Sets I2C speed.
+ *
+ * \param[in] dev     I2C device struct \ref i2c_sbcon_dev_t
+ * \param[in] i2c_hz  I2C frequency in Hz.
+ *
+ * \return Returns error code as specified in \ref i2c_sbcon_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum i2c_sbcon_error_t i2c_sbcon_set_freq(
+                                                struct i2c_sbcon_dev_t* dev,
+                                                uint32_t i2c_hz);
+
+/**
+ * \brief Gets I2C speed.
+ *
+ * \param[in] dev  I2C device struct \ref i2c_sbcon_dev_t
+ *
+ * \return Returns I2C frequency in Hz.
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+uint32_t i2c_sbcon_get_freq(struct i2c_sbcon_dev_t* dev);
+
+/**
+ * \brief Sets system clock frequency.
+ *
+ * \param[in] dev      I2C device struct \ref i2c_sbcon_dev_t
+ * \param[in] sys_clk  System clock frequency.
+ *
+ * \return Returns error code as specified in \ref i2c_sbcon_error_t
+ *
+ * \note This function doesn't check if dev is NULL.
+ */
+enum i2c_sbcon_error_t i2c_sbcon_set_sys_clk(
+                                                struct i2c_sbcon_dev_t* dev,
+                                                uint32_t sys_clk);
+
+/*
+ * \brief Transmits start bit.
+ *
+ * \param[in] dev  Pointer to the I2C device \ref i2c_sbcon_dev_t
+ *
+ * \note For better performance, this function doesn't check if the driver is
+ *       initialized.
+ */
+void i2c_sbcon_tx_start(const struct i2c_sbcon_dev_t* dev);
+
+/*
+ * \brief Transmits stop bit.
+ *
+ * \param[in] dev  Pointer to the I2C device \ref i2c_sbcon_dev_t
+ *
+ * \note For better performance, this function doesn't check if the driver is
+ *       initialized.
+ */
+void i2c_sbcon_tx_stop(const struct i2c_sbcon_dev_t* dev);
+
+/*
+ * \brief Writes acknowledge bit.
+ *
+ * \param[in] dev  Pointer to the I2C device \ref i2c_sbcon_dev_t
+ * \param[in] ack  Ack bit to write.
+ *
+ * \note For better performance, this function doesn't check if the driver is
+ *       initialized.
+ */
+void i2c_sbcon_tx_ack(const struct i2c_sbcon_dev_t* dev, uint8_t ack);
+
+/*
+ * \brief Transmits a byte.
+ *
+ * \param[in] dev   Pointer to the I2C device \ref i2c_sbcon_dev_t
+ * \param[in] data  Byte to transmit.
+ *
+ * \note For better performance, this function doesn't check if the driver is
+ *       initialized.
+ */
+void i2c_sbcon_tx_byte(const struct i2c_sbcon_dev_t* dev, uint8_t data);
+
+/*
+ * \brief Reads acknowledge bit
+ *
+ * \param[in] dev  Pointer to the I2C device \ref i2c_sbcon_dev_t
+ *
+ * \returns Bit value received.
+ *
+ * \note For better performance, this function doesn't check if the driver is
+ *       initialized.
+ */
+uint8_t i2c_sbcon_rx_ack(const struct i2c_sbcon_dev_t* dev);
+
+/*
+ * \brief Reads a byte.
+ *
+ * \param[in] dev  Pointer to the I2C device \ref i2c_sbcon_dev_t
+ *
+ * \returns byte value received.
+ *
+ * \note For better performance, this function doesn't check if the driver is
+ *       initialized.
+ */
+uint8_t i2c_sbcon_rx_byte(struct i2c_sbcon_dev_t* dev);
+
+/**
+ * \brief Writes data to I2C device.
+ *
+ * \param[in] dev               I2C device struct \ref i2c_sbcon_dev_t
+ * \param[in] addr              I2C device address (7 bits or 10 bits).
+ *                              The value can be ORed with I2C_10BIT to
+ *                              identify a 10-bit address value.
+ * \param[in] data              Buffer pointer to store the read data.
+ * \param[in] len               Buffer length.
+ * \param[in] xfer_pending      Transfer operation is pending, stop condition
+ *                              will not be generated
+ * \param[out] nbr_bytes_write  Number of bytes written
+ *
+ * \return Returns error code as specified in \ref i2c_sbcon_error_t
+ *
+ * \note For better performance, this function doesn't check if the pointers
+ *       are NULL and if the driver is initialized.
+ *       If it is on 7 bits, the addr argument has to be shifted by 1 bit to the
+ *       left before being sent to the function. The least significant bit will
+ *       be used to specify READ or WRITE.
+ */
+enum i2c_sbcon_error_t i2c_sbcon_master_transmit(
+                                             struct i2c_sbcon_dev_t* dev,
+                                             uint16_t addr, const uint8_t *data,
+                                             uint32_t len, uint8_t xfer_pending,
+                                             uint32_t* nbr_bytes_write);
+
+/**
+ * \brief Reads data from I2C device.
+ *
+ * \param[in]  dev             I2C device struct \ref i2c_sbcon_dev_t
+ * \param[in]  addr            I2C device address (7 bits or 10 bits).
+ *                             The value can be ORed with I2C_10BIT to
+ *                             identify a 10-bit address value.
+ * \param[out] data            Buffer pointer to store the read data.
+ * \param[in]  len             Buffer length.
+ * \param[in]  xfer_pending    Transfer operation is pending, stop condition
+ *                             will not be generated
+ * \param[out] nbr_bytes_read  Number of bytes read
+ *
+ * \return Returns error code as specified in \ref i2c_sbcon_error_t
+ *
+ * \note For better performance, this function doesn't check if the pointers
+ *       are NULL and if the driver is initialized.
+ *       If it is on 7 bits, the addr argument has to be shifted by 1 bit to the
+ *       left before being sent to the function. The least significant bit will
+ *       be used to specify READ or WRITE.
+ */
+enum i2c_sbcon_error_t i2c_sbcon_master_receive(
+                                                struct i2c_sbcon_dev_t* dev,
+                                                uint16_t addr, uint8_t *data,
+                                                uint32_t len,
+                                                uint8_t xfer_pending,
+                                                uint32_t* nbr_bytes_read);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __I2C_SBCON_DRV_H__ */
diff --git a/partitions/vad_an552_sp/ns_interface/vad_an552.h b/partitions/vad_an552_sp/ns_interface/vad_an552.h
new file mode 100644
index 0000000..bfadfb2
--- /dev/null
+++ b/partitions/vad_an552_sp/ns_interface/vad_an552.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __VAD_API_H__
+#define __VAD_API_H__
+
+#include <stdint.h>
+
+#include "psa/error.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \bried Status of the voice activity detection algorithm
+ */
+#define VAD_STOPPED             (0u)
+#define VAD_NO_VOICE_DETECTED   (1u)
+#define VAD_RECORDING           (2u)
+#define VAD_VOICE_RECORDED      (3u)
+
+/**
+ * \brief Starts running voice activity detection algorithm on the microphone
+ * input.
+ *
+ * Microphone samples are processed in interrupt context. If voice activity is
+ * detected the partition starts recording a short sample.
+ *
+ * \return Returns values as specified by the \ref psa_status_t
+ */
+psa_status_t vad_an552_start_vad(void);
+
+/**
+ * \brief Queries the status of the voice activity detection algorithm.
+ *
+ * \param[out] vad_status   If no voice activity was detected since the
+ *                          algorithm was started \ref VAD_VOICE_DETECTED is
+ *                          given back, if the recording is running
+ *                          \ref VAD_RECORDING, otherwise
+ *                          \ref VAD_VOICE_RECORDED.
+ *
+ * \return Returns values as specified by the \ref psa_status_t
+ */
+psa_status_t vad_an552_query_vad(uint32_t *vad_status);
+
+/**
+ * \brief Returns the frequency of the recorded smaple.
+ *
+ * \param[out] freq         The frequency component with the most energy.
+ *
+ * \return Returns values as specified by the \ref psa_status_t
+ */
+psa_status_t vad_an552_get_freq(uint32_t *freq);
+
+/**
+ * \brief Stops the running voice activity detection algorithm.
+ *
+ * \return Returns values as specified by the \ref psa_status_t
+ */
+psa_status_t vad_an552_stop_vad(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __VAD_API_H__ */
diff --git a/partitions/vad_an552_sp/ns_interface/vad_an552_defs.h b/partitions/vad_an552_sp/ns_interface/vad_an552_defs.h
new file mode 100644
index 0000000..0cc4d32
--- /dev/null
+++ b/partitions/vad_an552_sp/ns_interface/vad_an552_defs.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef __VAD_AN552_DEFS_H__
+#define __VAD_AN552_DEFS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Message types that distinguish VAD services. */
+#define VAD_AN552_START            1001
+#define VAD_AN552_QUERY            1002
+#define VAD_AN552_GET_FREQ         1003
+#define VAD_AN552_STOP             1004
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __VAD_AN552_DEFS_H__ */
diff --git a/partitions/vad_an552_sp/ns_interface/vad_an552_ipc_api.c b/partitions/vad_an552_sp/ns_interface/vad_an552_ipc_api.c
new file mode 100644
index 0000000..b66d8c6
--- /dev/null
+++ b/partitions/vad_an552_sp/ns_interface/vad_an552_ipc_api.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "vad_an552.h"
+
+#include "psa/client.h"
+#include "psa_manifest/sid.h"
+#include "vad_an552_defs.h"
+
+psa_status_t vad_an552_start_vad(void)
+{
+    psa_status_t status;
+
+    status = psa_call(TFM_AN552_VAD_HANDLE, VAD_AN552_START,
+                      NULL, 0, NULL, 0);
+
+    return status;
+}
+
+psa_status_t vad_an552_query_vad(uint32_t* vad_status)
+{
+    psa_status_t status;
+    psa_outvec out_vec[] = {
+        {.base = vad_status, .len = sizeof(uint32_t)}
+    };
+
+    status = psa_call(TFM_AN552_VAD_HANDLE, VAD_AN552_QUERY,
+                      NULL, 0, out_vec, IOVEC_LEN(out_vec));
+
+    return status;
+}
+
+psa_status_t vad_an552_get_freq(uint32_t* freq)
+{
+    psa_status_t status;
+    psa_outvec out_vec[] = {
+        {.base = freq, .len = sizeof(uint32_t)}
+    };
+
+    status = psa_call(TFM_AN552_VAD_HANDLE, VAD_AN552_GET_FREQ,
+                      NULL, 0, out_vec, IOVEC_LEN(out_vec));
+
+    return status;
+}
+
+psa_status_t vad_an552_stop_vad(void)
+{
+    psa_status_t status;
+
+    status = psa_call(TFM_AN552_VAD_HANDLE, VAD_AN552_STOP,
+                      NULL, 0, NULL, 0);
+
+    return status;
+}
diff --git a/partitions/vad_an552_sp/vad_an552_device_definition.c b/partitions/vad_an552_sp/vad_an552_device_definition.c
new file mode 100644
index 0000000..7a66b63
--- /dev/null
+++ b/partitions/vad_an552_sp/vad_an552_device_definition.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2021-2022 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 "vad_an552_device_definition.h"
+#include "platform_base_address.h"
+#include "timeout.h"
+
+static const struct systimer_armv8_m_dev_cfg_t
+SYSTIMER3_ARMV8_M_DEV_CFG_S = {
+    .base = SYSTIMER3_ARMV8_M_BASE_S,
+    .default_freq_hz = SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ
+};
+static struct systimer_armv8_m_dev_data_t
+SYSTIMER3_ARMV8_M_DEV_DATA_S = {
+    .is_initialized = false
+};
+struct systimer_armv8_m_dev_t SYSTIMER3_ARMV8_M_DEV_S = {
+    &(SYSTIMER3_ARMV8_M_DEV_CFG_S),
+    &(SYSTIMER3_ARMV8_M_DEV_DATA_S)
+};
+
+static struct i2c_sbcon_dev_cfg_t I2C0_SBCON_DEV_CFG_S = {
+    .base = FPGA_SBCon_I2C_AUDIO_BASE_S,
+    .default_freq_hz = 100000,
+    .sleep_us = &wait_us
+};
+static struct i2c_sbcon_dev_data_t I2C0_SBCON_DEV_DATA_S ={
+    .freq_us = 0,
+    .sys_clk = 0,
+    .state = 0
+};
+struct i2c_sbcon_dev_t I2C0_SBCON_DEV_S = {
+    .cfg = &(I2C0_SBCON_DEV_CFG_S),
+    .data = &(I2C0_SBCON_DEV_DATA_S)
+};
+
+static const struct audio_i2s_mps3_dev_cfg_t MPS3_I2S_DEV_CFG_S = {
+    .base = FPGA_I2S_BASE_S
+};
+struct audio_i2s_mps3_dev_t MPS3_I2S_DEV_S = {
+    &(MPS3_I2S_DEV_CFG_S),
+};
diff --git a/partitions/vad_an552_sp/vad_an552_device_definition.h b/partitions/vad_an552_sp/vad_an552_device_definition.h
new file mode 100644
index 0000000..7542c04
--- /dev/null
+++ b/partitions/vad_an552_sp/vad_an552_device_definition.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021-2022 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 __VAD_AN552_DEVICE_DEFINITION_H__
+#define __VAD_AN552_DEVICE_DEFINITION_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SYSTIMER3_ARMV8M_DEFAULT_FREQ_HZ    (32000000ul)
+
+#include "systimer_armv8-m_drv.h"
+extern struct systimer_armv8_m_dev_t SYSTIMER3_ARMV8_M_DEV_S;
+
+#include "i2c_sbcon_drv.h"
+extern struct i2c_sbcon_dev_t I2C0_SBCON_DEV_S;
+
+#include "audio_i2s_mps3_drv.h"
+extern struct audio_i2s_mps3_dev_t MPS3_I2S_DEV_S;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* __VAD_AN552_DEVICE_DEFINITION_H__ */
diff --git a/partitions/vad_an552_sp/vad_an552_sp.yaml b/partitions/vad_an552_sp/vad_an552_sp.yaml
new file mode 100644
index 0000000..5a33eed
--- /dev/null
+++ b/partitions/vad_an552_sp/vad_an552_sp.yaml
@@ -0,0 +1,47 @@
+#-------------------------------------------------------------------------------
+# Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+#-------------------------------------------------------------------------------
+
+{
+  "psa_framework_version": 1.1,
+  "name": "TFM_SP_VAD_AN552",
+  "type": "APPLICATION-ROT",
+  "priority": "NORMAL",
+  "model": "IPC",
+  "entry_point": "vad_main",
+  "stack_size": "0x1000",
+  "services": [
+    {
+      "name": "TFM_AN552_VAD",
+      "sid": "0x00000100",
+      "connection_based": false,
+      "non_secure_clients": true,
+      "version": 1,
+      "version_policy": "STRICT"
+    }
+  ],
+  "irqs": [
+    {
+      "source": "I2S_IRQn",
+      "name": "I2S",
+      "handling": "FLIH",
+    }
+  ],
+  "mmio_regions": [
+    {
+      "name": "TFM_PERIPHERAL_FPGA_I2S",
+      "permission": "READ-WRITE"
+    },
+    {
+      "name": "TFM_PERIPHERAL_AUDIO_I2C",
+      "permission": "READ-WRITE"
+    },
+    {
+      "name": "TFM_PERIPHERAL_TIMER3",
+      "permission": "READ-WRITE"
+    }
+  ]
+}
diff --git a/partitions/vad_an552_sp/vad_an552_sp_main.c b/partitions/vad_an552_sp/vad_an552_sp_main.c
new file mode 100644
index 0000000..eae8f96
--- /dev/null
+++ b/partitions/vad_an552_sp/vad_an552_sp_main.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+
+#include "psa/service.h"
+#include "psa_manifest/vad_an552_sp.h"
+#include "vad_an552_defs.h"
+#include "vad_an552.h"
+#include "timeout.h"
+#include "tfm_sp_log.h"
+#include "vad_an552_device_definition.h"
+#include "audio_codec_mps3.h"
+#include "cmsis.h"
+#include "tfm_peripherals_def.h"
+
+/* CMSIS DSP implementations */
+#include "dsp/statistics_functions.h"
+#include "dsp/transform_functions.h"
+#include "dsp/complex_math_functions.h"
+
+/* Voice activity detection algorithm and related defines */
+extern void vad_estimation(long *command, long* vad, short *inputData,
+                           long nbSamples, long samplingRate);
+#define INIT_VAD    1
+#define PROC_VAD    2
+#define FS          48000
+
+/* For voice recording and FFT calculation */
+#define RECORDING_SIZE 4096
+int16_t sample_buffer[RECORDING_SIZE];
+uint32_t sample_buffer_end_idx; /* Index of last element in sample_buffer */
+q15_t fft_result[2 * RECORDING_SIZE];
+q15_t fft_magnitude[RECORDING_SIZE];
+
+/* Status of the secure partition */
+uint32_t vad_status = VAD_STOPPED;
+
+void start_listening()
+{
+    audio_i2s_mps3_set_fifo_reset(&MPS3_I2S_DEV_S);
+    wait_ms(1);
+    audio_i2s_mps3_clear_fifo_reset(&MPS3_I2S_DEV_S);
+    audio_i2s_mps3_enable_rxbuf(&MPS3_I2S_DEV_S);
+    audio_i2s_mps3_enable_rxinterrupt(&MPS3_I2S_DEV_S);
+}
+
+void stop_listening()
+{
+    audio_i2s_mps3_disable_rxbuf(&MPS3_I2S_DEV_S);
+    audio_i2s_mps3_disable_rxinterrupt(&MPS3_I2S_DEV_S);
+    wait_ms(1);
+}
+
+psa_flih_result_t i2s_flih(void)
+{
+    short current_sample;
+    long voice_activity = 0;
+    static long command = PROC_VAD;
+
+    while (audio_i2s_mps3_is_rx_buffer_empty(&MPS3_I2S_DEV_S) == false) {
+        /* Only right channel used, left channel is dropped with the casting */
+        current_sample = (short) audio_i2s_mps3_get_rxbuf(&MPS3_I2S_DEV_S);
+        if (vad_status == VAD_NO_VOICE_DETECTED) {
+            vad_estimation(&command, &voice_activity, &current_sample, 1, FS);
+
+            if (voice_activity == 1) {
+                vad_status = VAD_RECORDING;
+                sample_buffer_end_idx = 0;
+            }
+
+        } else if (vad_status == VAD_RECORDING){
+            sample_buffer[sample_buffer_end_idx++] = current_sample;
+
+            if (sample_buffer_end_idx ==
+                (sizeof(sample_buffer) / sizeof(sample_buffer[0]))) {
+                stop_listening();
+                vad_status = VAD_VOICE_RECORDED;
+            }
+        } else {
+            stop_listening();
+        }
+    }
+
+    return PSA_FLIH_NO_SIGNAL;
+}
+
+static psa_status_t start_vad()
+{
+    long command = INIT_VAD;
+
+    vad_estimation(&command, 0, 0, 0, FS);
+    vad_status = VAD_NO_VOICE_DETECTED;
+    start_listening();
+    psa_irq_enable(I2S_SIGNAL);
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t query_vad(const psa_msg_t *msg)
+{
+    psa_write(msg->handle, 0, &vad_status, sizeof(vad_status));
+
+    return PSA_SUCCESS;
+}
+
+static psa_status_t get_freq(const psa_msg_t *msg)
+{
+    uint32_t freq = 0;
+    arm_rfft_instance_q15 fft_instance;
+    arm_status dsp_status;
+    q15_t max_value;
+    uint32_t max_index;
+
+    if (vad_status == VAD_VOICE_RECORDED) {
+        dsp_status = arm_rfft_init_q15(&fft_instance, RECORDING_SIZE, 0, 1);
+
+        /* No need for conversation between int16_t and q15_t as we are only
+         * interested in which frequency bin has the highest energy.
+         */
+        arm_rfft_q15(&fft_instance, (q15_t *) sample_buffer, fft_result);
+        arm_cmplx_mag_q15(fft_result, fft_magnitude, RECORDING_SIZE);
+        arm_max_q15(fft_magnitude, RECORDING_SIZE/2, &max_value, &max_index);
+
+        if (max_value != 0) {
+            /* A real maximum was found, returning the lower end of the maximum
+             * frequency bin.
+             */
+            freq = (FS / RECORDING_SIZE) * max_index;
+        } else {
+            freq = 0;
+        }
+
+        psa_write(msg->handle, 0, &freq, sizeof(freq));
+
+        /* The FFT calculation updates the recorded sample, so we move to the
+         * intitial state.
+         */
+        vad_status = VAD_STOPPED;
+
+        return PSA_SUCCESS;
+    } else {
+        return PSA_ERROR_BAD_STATE;
+    }
+}
+
+static psa_status_t stop_vad()
+{
+    psa_irq_disable(I2S_SIGNAL);
+    stop_listening();
+    vad_status = VAD_STOPPED;
+
+    return PSA_SUCCESS;
+}
+
+static void vad_signal_handle(psa_signal_t signal)
+{
+    psa_msg_t msg;
+    psa_status_t status;
+
+    status = psa_get(signal, &msg);
+    if (status != PSA_SUCCESS) {
+        return;
+    }
+
+    switch (msg.type) {
+    case VAD_AN552_START:
+        status = start_vad();
+        psa_reply(msg.handle, status);
+        break;
+    case VAD_AN552_QUERY:
+        status = query_vad(&msg);
+        psa_reply(msg.handle, status);
+        break;
+    case VAD_AN552_GET_FREQ:
+        status = get_freq(&msg);
+        psa_reply(msg.handle, status);
+        break;
+    case VAD_AN552_STOP:
+        status = stop_vad();
+        psa_reply(msg.handle, status);
+        break;
+    default:
+        /* Invalid message type */
+        status = PSA_ERROR_PROGRAMMER_ERROR;
+        psa_reply(msg.handle, status);
+        break;
+    }
+}
+
+void vad_main(void)
+{
+    psa_signal_t signals;
+
+    /* Audio initialization */
+    audio_codec_mps3_init(&I2C0_SBCON_DEV_S, &MPS3_I2S_DEV_S);
+
+    /* Set Rx Buffer Irq Water Level. If less than 1 word space is available,
+       IRQ is triggered */
+    audio_i2s_mps3_set_rx_buff_water_lvl(&MPS3_I2S_DEV_S, 1);
+
+    LOG_DBGFMT("[VAD] Secure partition initialized\r\n");
+
+    while (1) {
+        signals = psa_wait(PSA_WAIT_ANY, PSA_BLOCK);
+
+        if (signals & TFM_AN552_VAD_SIGNAL) {
+            vad_signal_handle(TFM_AN552_VAD_SIGNAL);
+        } else {
+            psa_panic();
+        }
+    }
+}