From b2ff6c49ec734c32c6735cb653a97af228415fb3 Mon Sep 17 00:00:00 2001
From: Shaojun Wang <shaojun.wang@nxp.com>
Date: Tue, 30 Aug 2022 14:34:05 +0800
Subject: [PATCH 3/4] upgrade to support remoteproc in linux-5.10.72

---
 .../micro_speech/micro_speech_benchmark.cc    |   4 +
 .../make/targets/xtensa_hifi_makefile.inc     |  13 +
 tensorflow/lite/micro/xtensa_hifi/board.h     | 167 +++++++++
 tensorflow/lite/micro/xtensa_hifi/init.c      |  14 +-
 tensorflow/lite/micro/xtensa_hifi/io.c        |  32 ++
 tensorflow/lite/micro/xtensa_hifi/io.h        |  15 +
 .../lite/micro/xtensa_hifi/micro_time.cc      |   5 +
 .../lite/micro/xtensa_hifi/peripheral.c       | 148 ++++++--
 .../lite/micro/xtensa_hifi/peripheral.h       |  57 ++-
 .../lite/micro/xtensa_hifi/remoteproc.h       | 333 ++++++++++++++++++
 tensorflow/lite/micro/xtensa_hifi/rsc_table.c |  51 +++
 tensorflow/lite/micro/xtensa_hifi/rsc_table.h |  57 +++
 12 files changed, 858 insertions(+), 38 deletions(-)
 create mode 100644 tensorflow/lite/micro/xtensa_hifi/board.h
 create mode 100644 tensorflow/lite/micro/xtensa_hifi/io.c
 create mode 100644 tensorflow/lite/micro/xtensa_hifi/io.h
 create mode 100644 tensorflow/lite/micro/xtensa_hifi/remoteproc.h
 create mode 100644 tensorflow/lite/micro/xtensa_hifi/rsc_table.c
 create mode 100644 tensorflow/lite/micro/xtensa_hifi/rsc_table.h

diff --git a/tensorflow/lite/micro/examples/micro_speech/micro_speech_benchmark.cc b/tensorflow/lite/micro/examples/micro_speech/micro_speech_benchmark.cc
index ecb678254de..73caaa13a07 100644
--- a/tensorflow/lite/micro/examples/micro_speech/micro_speech_benchmark.cc
+++ b/tensorflow/lite/micro/examples/micro_speech/micro_speech_benchmark.cc
@@ -26,7 +26,11 @@ limitations under the License.
 #include "tensorflow/lite/version.h"
 #include "tensorflow/lite/micro/micro_time.h"
 
+#ifdef PLATF_8M
 #define XTENSA_CORE_FREQ (800 * 1000 * 1000)
+#else
+#define XTENSA_CORE_FREQ (600 * 1000 * 1000)
+#endif
 
 TF_LITE_MICRO_TESTS_BEGIN
 
diff --git a/tensorflow/lite/micro/tools/make/targets/xtensa_hifi_makefile.inc b/tensorflow/lite/micro/tools/make/targets/xtensa_hifi_makefile.inc
index 6b0259e7833..92da0c25f88 100644
--- a/tensorflow/lite/micro/tools/make/targets/xtensa_hifi_makefile.inc
+++ b/tensorflow/lite/micro/tools/make/targets/xtensa_hifi_makefile.inc
@@ -63,6 +63,19 @@ $(eval $(call add_third_party_download,$(XTENSA_HIFI5_URL),$(XTENSA_HIFI5_MD5),x
   CXXFLAGS += -stdlib=libc++
   endif
 
+  ifeq ($(PLATF), imx8m)
+  CCFLAGS += -DPLATF_8M
+  endif
+
+  ifeq ($(PLATF), imx8mp_lpa)
+  CCFLAGS += -DPLATF_8M
+  CCFLAGS += -DPLATF_8MP_LPA
+  endif
+
+  ifeq ($(PLATF), imx8ulp)
+  CCFLAGS += -DPLATF_8ULP
+  endif
+
   # TODO(b/150240249): Do not remove -fno-rtti once that works for the Xtensa toolchain.
   CXXFLAGS := $(filter-out -fno-rtti, $(CXXFLAGS))
 
diff --git a/tensorflow/lite/micro/xtensa_hifi/board.h b/tensorflow/lite/micro/xtensa_hifi/board.h
new file mode 100644
index 00000000000..45cc176d895
--- /dev/null
+++ b/tensorflow/lite/micro/xtensa_hifi/board.h
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 NXP
+ */
+
+#ifndef _BOARD_H_
+#define _BOARD_H_
+
+enum {
+	DSP_IMX8QXP_TYPE = 0,
+	DSP_IMX8QM_TYPE,
+	DSP_IMX8MP_TYPE,
+	DSP_IMX8ULP_TYPE,
+};
+
+/*
+ * Memory allocation for reserved memory:
+ * We alway reserve 32M memory from DRAM
+ * The DRAM reserved memory is split into three parts currently.
+ * The front part is used to keep the dsp firmware, the other part is
+ * considered as scratch memory for dsp framework.
+ *
+ *---------------------------------------------------------------------------
+ *| Offset                |  Size    |   Usage                              |
+ *---------------------------------------------------------------------------
+ *| 0x0 ~ 0xEFFFFF        |  15M     |   Code memory of firmware            |
+ *---------------------------------------------------------------------------
+ *| 0xF00000 ~ 0xFFFFFF   |  1M      |   Message buffer + Globle dsp struct |
+ *---------------------------------------------------------------------------
+ *| 0x1000000 ~ 0x1FFFFFF |  16M     |   Scratch memory                     |
+ *---------------------------------------------------------------------------
+ */
+
+/* Cache definition
+ * Every 512M in 4GB space has dedicate cache attribute.
+ * 1: write through
+ * 2: cache bypass
+ * 4: write back
+ * F: invalid access
+ */
+
+#define FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL (1)
+#define RESUME_FLAG (0x1A2B3C4D)
+
+#define RP_MBOX_SUSPEND_SYSTEM  (0xFF11)
+#define RP_MBOX_SUSPEND_ACK     (0xFF12)
+#define RP_MBOX_RESUME_SYSTEM   (0xFF13)
+#define RP_MBOX_RESUME_ACK      (0xFF14)
+
+/* PLATF_8M */
+#ifdef PLATF_8M
+
+#define BOARD_TYPE (DSP_IMX8MP_TYPE)
+
+#define I_CACHE_ATTRIBUTE      0x22242224     //write back mode
+#define D_CACHE_ATTRIBUTE      0x22212221     //write through mode
+#define INT_NUM_MU             7
+#define MU_PADDR               0x30E70000
+
+#define VDEV0_VRING_SA_BASE   (0x942f0000U)
+#define VDEV0_VRING_DA_BASE   (0x942f0000U)
+#define VDEV0_VRING_SIZE      (0x00008000U)
+#define VDEV0_VRING_NUM       (0x00000002U)
+
+#define RESERVED_MEM_ADDR     (0x92400000U)
+#define RESERVED_MEM_SIZE     (0x02000000U)
+#define GLOBAL_DSP_MEM_ADDR   (RESERVED_MEM_ADDR + 0xF00000U)
+#define GLOBAL_DSP_MEM_SIZE   (0x100000U)
+#define SCRATCH_MEM_ADDR      (RESERVED_MEM_ADDR + 0x1000000U)
+#define SCRATCH_MEM_SIZE      (0xef0000U)
+
+#define RPMSG_LITE_SRTM_SHMEM_BASE  (VDEV0_VRING_DA_BASE)
+#define RPMSG_LITE_SRTM_LINK_ID     (0U)
+
+#define MUB_BASE              (MU_PADDR)
+#define SYSTEM_CLOCK          (800000000UL)
+
+#define UART_BASE             (0x30a60000)
+#define UART_CLK_ROOT         (24000000)
+
+#define I2C3_ADDR             0x30A40000
+#define I2C_ADDR              I2C3_ADDR
+#define I2C_CLK               (24000000UL)
+/*
+ * This limit caused by an i.MX7D hardware issue(e7805 in Errata).
+ * If there is no limit, when the bitrate set up to 400KHz, it will
+ * cause the SCK low level period less than 1.3us.
+ */
+#define I2C_BITRATE           (375000)
+
+#else /* PLATF_8M */
+#ifdef PLATF_8ULP
+
+#define BOARD_TYPE (DSP_IMX8ULP_TYPE)
+
+#define I_CACHE_ATTRIBUTE      0x22222224     //write back mode
+#define D_CACHE_ATTRIBUTE      0x22222221     //write through mode
+#define INT_NUM_MU             15
+#define MU_PADDR               0x2DA20000
+
+/* remapping  0x8def0000U   -    0x19ef0000 */
+#define VDEV0_VRING_SA_BASE   (0x8fef0000U)
+#define VDEV0_VRING_DA_BASE   (0x1bef0000U)
+#define VDEV0_VRING_SIZE      (0x00008000U)
+#define VDEV0_VRING_NUM       (0x00000002U)
+
+/* remapping  0x8e000000U   -    0x1a000000 */
+#define RESERVED_MEM_ADDR     (0x1a000000U)
+#define RESERVED_MEM_SIZE     (0x02000000U)
+#define GLOBAL_DSP_MEM_ADDR   (RESERVED_MEM_ADDR + 0xF00000U)
+#define GLOBAL_DSP_MEM_SIZE   (0x100000U)
+#define SCRATCH_MEM_ADDR      (RESERVED_MEM_ADDR + 0x1000000U)
+#define SCRATCH_MEM_SIZE      (0xef0000U)
+
+#define RPMSG_LITE_SRTM_SHMEM_BASE  (VDEV0_VRING_DA_BASE)
+#define RPMSG_LITE_SRTM_LINK_ID     (0U)
+
+#define MUB_BASE              (MU_PADDR)
+#define SYSTEM_CLOCK          (528000000UL)
+
+/*lpuart6 for debug */
+#define LPUART_BASE           (0x29860000)
+#define UART_CLK_ROOT         (48000000)
+
+/* TODO */
+#define I2C_ADDR              0
+#define I2C_CLK               0
+#define I2C_BITRATE           (375000)
+
+#else /* !PLATF_8ULP && ! PLATF_8M  (8QXP || 8QM)*/
+
+#define BOARD_TYPE (DSP_IMX8QXP_TYPE)
+
+#define I_CACHE_ATTRIBUTE      0x22242224     //write back mode
+#define D_CACHE_ATTRIBUTE      0x22212221     //write through mode
+#define INT_NUM_MU             7
+#define MU_PADDR               0x5D310000
+
+#define VDEV0_VRING_SA_BASE   (0x942f0000U)
+#define VDEV0_VRING_DA_BASE   (0x942f0000U)
+#define VDEV0_VRING_SIZE      (0x00008000U)
+#define VDEV0_VRING_NUM       (0x00000002U)
+
+#define RESERVED_MEM_ADDR     (0x92400000U)
+#define RESERVED_MEM_SIZE     (0x02000000U)
+#define GLOBAL_DSP_MEM_ADDR   (RESERVED_MEM_ADDR + 0xF00000U)
+#define GLOBAL_DSP_MEM_SIZE   (0x100000U)
+#define SCRATCH_MEM_ADDR      (RESERVED_MEM_ADDR + 0x1000000U)
+#define SCRATCH_MEM_SIZE      (0xef0000U)
+
+#define RPMSG_LITE_SRTM_SHMEM_BASE  (VDEV0_VRING_DA_BASE)
+#define RPMSG_LITE_SRTM_LINK_ID     (0U)
+
+#define MUB_BASE              (MU_PADDR)
+#define SYSTEM_CLOCK          (600000000UL)
+
+#define LPUART_BASE           (0x5a080000)
+#define UART_CLK_ROOT         (80000000)
+
+/* TODO */
+#define I2C_ADDR              0
+#define I2C_CLK               0
+#define I2C_BITRATE           (375000)
+
+#endif /*PLATF_8ULP */
+#endif /*PLATF_8M */
+
+#endif /* _BOARD_H_ */
diff --git a/tensorflow/lite/micro/xtensa_hifi/init.c b/tensorflow/lite/micro/xtensa_hifi/init.c
index 3c798c155d6..364f9b7d9ce 100644
--- a/tensorflow/lite/micro/xtensa_hifi/init.c
+++ b/tensorflow/lite/micro/xtensa_hifi/init.c
@@ -22,9 +22,9 @@
  *
  *****************************************************************/
 #include "xf-types.h"
-#include "tensorflow/lite/micro/xtensa_hifi/peripheral.h"
-
-#define MU_PADDR  0x30E70000
+#include "peripheral.h"
+#include "board.h"
+#include "io.h"
 
 union icm_header_t {
 	struct {
@@ -54,11 +54,19 @@ enum icm_action_t {
 
 void init_board(void){
 
+	u32 val;
+
 	enable_log();
 
+#if 1
+	val = read32((void *)MU_PADDR + 0x24);
+	val |= 1 << 19;
+	write32((void *)MU_PADDR + 0x24, val);
+#else
 	union icm_header_t msg;
 	msg.allbits = 0;
 	msg.intr = 1;
 	msg.msg  = ICM_CORE_READY;
 	mu_msg_send(MU_PADDR, 0, msg.allbits);
+#endif
 }
diff --git a/tensorflow/lite/micro/xtensa_hifi/io.c b/tensorflow/lite/micro/xtensa_hifi/io.c
new file mode 100644
index 00000000000..568902645a9
--- /dev/null
+++ b/tensorflow/lite/micro/xtensa_hifi/io.c
@@ -0,0 +1,32 @@
+/*
+ * io.c - I/O abstraction layer
+ *
+ * Copyright 2018 NXP
+ */
+#include "io.h"
+
+void write16(volatile void * addr, u16 data) {
+	*(volatile unsigned short *)(addr) = (data);
+}
+
+u16 read16(volatile void * addr) {
+	u16 read_data = *(volatile unsigned short *)(addr);
+	return read_data;
+}
+
+void write32(volatile void * addr, u32 data) {
+	*(volatile unsigned int *)(addr) = (data);
+}
+
+void write32_bit(volatile void * addr, u32 mask, u32 data) {
+	u32 read_data = *(volatile unsigned int *)(addr);
+	read_data = (read_data & (~mask)) | data;
+	*(volatile unsigned int *)(addr) = (read_data);
+}
+
+u32 read32(volatile void * addr) {
+	u32 read_data = *(volatile unsigned int *)(addr);
+	return read_data;
+}
+
+
diff --git a/tensorflow/lite/micro/xtensa_hifi/io.h b/tensorflow/lite/micro/xtensa_hifi/io.h
new file mode 100644
index 00000000000..d6941a1d1bb
--- /dev/null
+++ b/tensorflow/lite/micro/xtensa_hifi/io.h
@@ -0,0 +1,15 @@
+/*
+ * io.h - I/O abstraction header API
+ */
+#ifndef _IO_H
+#define _IO_H
+#include "xf-types.h"
+
+void write16(volatile void * addr, u16 data);
+u16 read16(volatile void * addr);
+void write32(volatile void * addr, u32 data);
+void write32_bit(volatile void * addr, u32 mask, u32 data);
+u32 read32(volatile void * addr);
+
+#endif
+
diff --git a/tensorflow/lite/micro/xtensa_hifi/micro_time.cc b/tensorflow/lite/micro/xtensa_hifi/micro_time.cc
index 4bfb7a9474f..ac271ff25fc 100644
--- a/tensorflow/lite/micro/xtensa_hifi/micro_time.cc
+++ b/tensorflow/lite/micro/xtensa_hifi/micro_time.cc
@@ -23,7 +23,12 @@ limitations under the License.
 
 namespace tflite {
 #ifdef IMX_PATCH
+
+#ifdef PLATF_8M
 #define XTENSA_CORE_FREQ (800 * 1000 * 1000)
+#else
+#define XTENSA_CORE_FREQ (600 * 1000 * 1000)
+#endif
 
 int get_time_us(void)
 {
diff --git a/tensorflow/lite/micro/xtensa_hifi/peripheral.c b/tensorflow/lite/micro/xtensa_hifi/peripheral.c
index 746d8649172..b5559d931c6 100644
--- a/tensorflow/lite/micro/xtensa_hifi/peripheral.c
+++ b/tensorflow/lite/micro/xtensa_hifi/peripheral.c
@@ -1,5 +1,5 @@
 /*****************************************************************
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2020 NXP
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -23,21 +23,38 @@
  *****************************************************************/
 
 #include "peripheral.h"
+#include "board.h"
+#include "io.h"
+#include "rsc_table.h"
 #include <stdarg.h>
 
 /* Enable the specific receive interrupt */
 void mu_enableinterrupt_rx(u32 start_addr, u32 idx)
 {
+#ifdef PLATF_8ULP
+	volatile u32 *reg_rcr = (volatile u32 *)(start_addr + MX8ULP_MU_RCR);
+	*reg_rcr = 1 << idx;
+#else
 	struct mu_regs *regs = (struct mu_regs *)start_addr;
 
 	u32 reg_cr = (regs->MU_CR & ~MU_CR_GIRn_NMI_MASK);
 
 	regs->MU_CR = reg_cr | (MU_CR_RIE0_MASK >> idx);
+#endif
 }
 
 /* Receive the message for specify registers */
 void mu_msg_receive(u32 start_addr, u32 regidx, u32 *msg)
 {
+#ifdef PLATF_8ULP
+	volatile u32 *reg_rsr = (volatile u32 *)(start_addr + MX8ULP_MU_RSR);
+	volatile u32 *reg_rr = (volatile u32 *)(start_addr + MX8ULP_MU_RR0 + (regidx << 2));
+
+	while (!(*reg_rsr & (1 << regidx)))
+                ;
+
+	*msg = *reg_rr;
+#else
 	struct mu_regs *regs = (struct mu_regs *)start_addr;
 
 	u32 mask = MU_SR_RF0_MASK >> regidx;
@@ -46,10 +63,19 @@ void mu_msg_receive(u32 start_addr, u32 regidx, u32 *msg)
 		;
 
 	*msg = regs->MU_RR[regidx];
+#endif
 }
 
 void mu_msg_send(u32 start_addr, u32 regidx, u32 msg)
 {
+#ifdef PLATF_8ULP
+	volatile u32 *reg_tsr = (volatile u32 *)(start_addr + MX8ULP_MU_TSR);
+	volatile u32 *reg_tr = (volatile u32 *)(start_addr + MX8ULP_MU_TR0 + (regidx << 2));
+
+	while (!(*reg_tsr & (1 << regidx)));
+
+	*reg_tr = msg;
+#else
 	struct mu_regs *regs = (struct mu_regs *)start_addr;
 
 	u32 mask = MU_SR_TE0_MASK >> regidx;
@@ -58,8 +84,10 @@ void mu_msg_send(u32 start_addr, u32 regidx, u32 msg)
 		;
 
 	regs->MU_TR[regidx] = msg;
+#endif
 }
 
+#ifdef PLATF_8M
 static void uart_putc(const char c)
 {
 	volatile char *uart_base = (volatile char *)UART_BASE;
@@ -103,16 +131,109 @@ static int uart_init()
 
 	return 0;
 }
+#else
+static void lpuart_putc(struct nxp_lpuart *base, const char c)
+{
+	if (c == '\n')
+		lpuart_putc(base, '\r');
+
+	while (!(base->stat & LPUART_STAT_TDRE))
+		;
+
+	base->data = c;
+}
+
+static int lpuart_init(struct nxp_lpuart *base)
+{
+	u32 tmp;
+	u32 sbr, osr, baud_diff, tmp_osr, tmp_sbr, tmp_diff;
+	u32 clk = UART_CLK_ROOT;
+	u32 baudrate = BAUDRATE;
+
+	tmp = base->ctrl;
+	tmp &= ~(LPUART_CTRL_TE | LPUART_CTRL_RE);
+	base->ctrl = tmp;
+	base->modir = 0;
+	base->fifo = ~(LPUART_FIFO_TXFE | LPUART_FIFO_RXFE);
+	base->match = 0;
+
+	baud_diff = BAUDRATE;
+	osr = 0;
+	sbr = 0;
+	for (tmp_osr = 4; tmp_osr <= 32; tmp_osr++) {
+		tmp_sbr = (clk / (baudrate * tmp_osr));
+		if (tmp_sbr == 0)
+			tmp_sbr = 1;
+
+		tmp_diff = (clk / (tmp_osr * tmp_sbr));
+		tmp_diff = tmp_diff - baudrate;
+
+		if (tmp_diff > (baudrate - (clk / (tmp_osr * (tmp_sbr + 1))))) {
+			tmp_diff = baudrate - (clk / (tmp_osr * (tmp_sbr + 1)));
+			tmp_sbr++;
+		}
+
+		if (tmp_diff <= baud_diff) {
+			baud_diff = tmp_diff;
+			osr = tmp_osr;
+			sbr = tmp_sbr;
+		}
+	}
+
+	tmp = base->baud;
+
+	if ((osr > 3) && (osr < 8))
+		tmp |= LPUART_BAUD_BOTHEDGE_MASK;
+
+	tmp &= ~LPUART_BAUD_OSR_MASK;
+	tmp |= LPUART_BAUD_OSR(osr - 1);
+
+	tmp &= ~LPUART_BAUD_SBR_MASK;
+	tmp |= LPUART_BAUD_SBR(sbr);
+	tmp &= ~(LPUART_BAUD_M10_MASK | LPUART_BAUD_SBNS_MASK);
+
+	base->baud = tmp;
+
+	tmp = base->ctrl;
+	tmp &= ~(LPUART_CTRL_PE_MASK |
+			LPUART_CTRL_PT_MASK  |
+			LPUART_CTRL_M_MASK);
+	base->ctrl = tmp;
+
+	base->ctrl = LPUART_CTRL_RE | LPUART_CTRL_TE;
+
+	return 0;
+}
+#endif
 
+extern struct remote_resource_table resources;
 int enable_log(void)
 {
+#ifdef PLATF_8M
 	uart_init();
+#else
+	volatile int *lpuart1 = (volatile int *)LPUART_BASE;
+	struct nxp_lpuart *base = (struct nxp_lpuart *)lpuart1;
+	int i = 0;
+
+	lpuart_init(base);
+#endif
+
+	resources.version = 1;
+
 	return 0;
 }
 
 void dsp_putc(const char c)
 {
+#ifdef PLATF_8M
 	uart_putc(c);
+#else
+	volatile int *lpuart1 = (volatile int *)LPUART_BASE;
+	struct nxp_lpuart *base = (struct nxp_lpuart *)lpuart1;
+
+	lpuart_putc(base, c);
+#endif
 }
 
 void dsp_puts(const char *s)
@@ -124,28 +245,3 @@ void dsp_puts(const char *s)
 		dsp_putc(ch);
 	}
 }
-
-void write16(volatile void * addr, u16 data) {
-	*(volatile unsigned short *)(addr) = (data);
-}
-
-u16 read16(volatile void * addr) {
-	u16 read_data = *(volatile unsigned short *)(addr);
-	return read_data;
-}
-
-void write32(volatile void * addr, u32 data) {
-	*(volatile unsigned int *)(addr) = (data);
-}
-
-void write32_bit(volatile void * addr, u32 mask, u32 data) {
-	u32 read_data = *(volatile unsigned int *)(addr);
-	read_data = (read_data & (~mask)) | data;
-	*(volatile unsigned int *)(addr) = (read_data);
-}
-
-u32 read32(volatile void * addr) {
-	u32 read_data = *(volatile unsigned int *)(addr);
-	return read_data;
-}
-
diff --git a/tensorflow/lite/micro/xtensa_hifi/peripheral.h b/tensorflow/lite/micro/xtensa_hifi/peripheral.h
index ad6f403ea82..7f1240718ce 100644
--- a/tensorflow/lite/micro/xtensa_hifi/peripheral.h
+++ b/tensorflow/lite/micro/xtensa_hifi/peripheral.h
@@ -1,5 +1,5 @@
 /*****************************************************************
- * Copyright 2018-2021 NXP
+ * Copyright 2018-2020 NXP
  *
  * Permission is hereby granted, free of charge, to any person obtaining
  * a copy of this software and associated documentation files (the
@@ -39,6 +39,12 @@
 #define MU_SR_TE0_MASK				(1U << 23U)
 #define MU_CR_RIE0_MASK				(1U << 27U)
 
+#define MX8ULP_MU_TSR        0x124
+#define MX8ULP_MU_RCR        0x128
+#define MX8ULP_MU_RSR        0x12C
+#define MX8ULP_MU_TR0        0x200
+#define MX8ULP_MU_RR0        0x280
+
 struct mu_regs {
 	volatile u32		MU_TR[4];
 	volatile const  u32	MU_RR[4];
@@ -50,6 +56,46 @@ void mu_enableinterrupt_rx(u32 start_addr, u32 idx);
 void mu_msg_receive(u32 start_addr, u32 regidx, u32 *msg);
 void mu_msg_send(u32 start_addr, u32 regidx, u32 msg);
 
+#define LPUART_STAT_TDRE		(1 << 23)
+#define LPUART_FIFO_TXFE		0x80
+#define LPUART_FIFO_RXFE		0x40
+
+#define LPUART_BAUD_SBR_MASK                     (0x1FFFU)
+#define LPUART_BAUD_SBR_SHIFT                    (0U)
+#define LPUART_BAUD_SBR(x)                       (((u32)(((u32)(x)) << LPUART_BAUD_SBR_SHIFT)) & LPUART_BAUD_SBR_MASK)
+#define LPUART_BAUD_SBNS_MASK                    (0x2000U)
+#define LPUART_BAUD_SBNS_SHIFT                   (13U)
+#define LPUART_BAUD_SBNS(x)                      (((u32)(((u32)(x)) << LPUART_BAUD_SBNS_SHIFT)) & LPUART_BAUD_SBNS_MASK)
+#define LPUART_BAUD_BOTHEDGE_MASK                (0x20000U)
+#define LPUART_BAUD_BOTHEDGE_SHIFT               (17U)
+#define LPUART_BAUD_BOTHEDGE(x)                  (((u32)(((u32)(x)) << LPUART_BAUD_BOTHEDGE_SHIFT)) & LPUART_BAUD_BOTHEDGE_MASK)
+#define LPUART_BAUD_OSR_MASK                     (0x1F000000U)
+#define LPUART_BAUD_OSR_SHIFT                    (24U)
+#define LPUART_BAUD_OSR(x)                       (((u32)(((u32)(x)) << LPUART_BAUD_OSR_SHIFT)) & LPUART_BAUD_OSR_MASK)
+#define LPUART_BAUD_M10_MASK                     (0x20000000U)
+#define LPUART_BAUD_M10_SHIFT                    (29U)
+#define LPUART_BAUD_M10(x)                       (((u32)(((u32)(x)) << LPUART_BAUD_M10_SHIFT)) & LPUART_BAUD_M10_MASK)
+
+#define LPUART_CTRL_TE				(1 << 19)
+#define LPUART_CTRL_RE				(1 << 18)
+#define LPUART_CTRL_PT_MASK			(0x1U)
+#define LPUART_CTRL_PE_MASK			(0x2U)
+#define LPUART_CTRL_M_MASK			(0x10U)
+
+struct nxp_lpuart {
+	volatile u32 verid;
+	volatile u32 param;
+	volatile u32 global;
+	volatile u32 pincfg;
+	volatile u32 baud;
+	volatile u32 stat;
+	volatile u32 ctrl;
+	volatile u32 data;
+	volatile u32 match;
+	volatile u32 modir;
+	volatile u32 fifo;
+	volatile u32 water;
+};
 /* Register definitions */
 #define URXD0 0x0  /* Receiver Register */
 #define URTX0 0x40 /* Transmitter Register */
@@ -73,18 +119,11 @@ void mu_msg_send(u32 start_addr, u32 regidx, u32 msg);
 #define USR1_TRDY	(1<<13) /* Transmitter ready interrupt/dma flag */
 #define USR2_TXDC	 (1<<3)	 /* Transmitter complete */
 
-#define UART_CLK_ROOT (80000000)
 #define BAUDRATE (115200)
 
-#define UART_BASE  (0x30a60000)
-
 void dsp_putc(const char c);
 void dsp_puts(const char *s);
-void write16(volatile void * addr, u16 data);
-u16 read16(volatile void * addr);
-void write32(volatile void * addr, u32 data);
-void write32_bit(volatile void * addr, u32 mask, u32 data);
-u32 read32(volatile void * addr);
+
 int enable_log(void);
 
 #endif
diff --git a/tensorflow/lite/micro/xtensa_hifi/remoteproc.h b/tensorflow/lite/micro/xtensa_hifi/remoteproc.h
new file mode 100644
index 00000000000..5f7c76a4306
--- /dev/null
+++ b/tensorflow/lite/micro/xtensa_hifi/remoteproc.h
@@ -0,0 +1,333 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Remoteproc Framework
+ *
+ * Copyright 2020-2021 NXP.
+ * Copyright(c) 2018 Xilinx Ltd.
+ * Copyright(c) 2011 Texas Instruments, Inc.
+ * Copyright(c) 2011 Google, Inc.
+ * All rights reserved.
+ *
+ */
+
+#ifndef REMOTEPROC_H
+#define REMOTEPROC_H
+
+#include <stdint.h>
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+#define RSC_NOTIFY_ID_ANY 0xFFFFFFFFUL
+
+#define RPROC_MAX_NAME_LEN 32
+
+#ifndef METAL_PACKED_BEGIN
+#define METAL_PACKED_BEGIN
+#endif
+
+#ifndef METAL_PACKED_END
+#define METAL_PACKED_END __attribute__((__packed__))
+#endif
+
+/**
+ * struct resource_table - firmware resource table header
+ * @ver: version number
+ * @num: number of resource entries
+ * @reserved: reserved (must be zero)
+ * @offset: array of offsets pointing at the various resource entries
+ *
+ * A resource table is essentially a list of system resources required
+ * by the remote remoteproc. It may also include configuration entries.
+ * If needed, the remote remoteproc firmware should contain this table
+ * as a dedicated ".resource_table" ELF section.
+ *
+ * Some resources entries are mere announcements, where the host is informed
+ * of specific remoteproc configuration. Other entries require the host to
+ * do something (e.g. allocate a system resource). Sometimes a negotiation
+ * is expected, where the firmware requests a resource, and once allocated,
+ * the host should provide back its details (e.g. address of an allocated
+ * memory region).
+ *
+ * The header of the resource table, as expressed by this structure,
+ * contains a version number (should we need to change this format in the
+ * future), the number of available resource entries, and their offsets
+ * in the table.
+ *
+ * Immediately following this header are the resource entries themselves,
+ * each of which begins with a resource entry header (as described below).
+ */
+METAL_PACKED_BEGIN
+struct resource_table {
+	uint32_t ver;
+	uint32_t num;
+	uint32_t reserved[2];
+	uint32_t offset[0];
+} METAL_PACKED_END;
+
+/**
+ * struct fw_rsc_hdr - firmware resource entry header
+ * @type: resource type
+ * @data: resource data
+ *
+ * Every resource entry begins with a 'struct fw_rsc_hdr' header providing
+ * its @type. The content of the entry itself will immediately follow
+ * this header, and it should be parsed according to the resource type.
+ */
+METAL_PACKED_BEGIN
+struct fw_rsc_hdr {
+	uint32_t type;
+	uint8_t data[0];
+} METAL_PACKED_END;
+
+/**
+ * enum fw_resource_type - types of resource entries
+ *
+ * @RSC_CARVEOUT:   request for allocation of a physically contiguous
+ *          memory region.
+ * @RSC_DEVMEM:     request to iommu_map a memory-based peripheral.
+ * @RSC_TRACE:      announces the availability of a trace buffer into which
+ *          the remote remoteproc will be writing logs.
+ * @RSC_VDEV:       declare support for a virtio device, and serve as its
+ *          virtio header.
+ * @RSC_VENDOR_START: start of the vendor specific resource types range
+ * @RSC_VENDOR_END  : end of the vendor specific resource types range
+ * @RSC_LAST:       just keep this one at the end
+ *
+ * For more details regarding a specific resource type, please see its
+ * dedicated structure below.
+ *
+ * Please note that these values are used as indices to the rproc_handle_rsc
+ * lookup table, so please keep them sane. Moreover, @RSC_LAST is used to
+ * check the validity of an index before the lookup table is accessed, so
+ * please update it as needed.
+ */
+enum fw_resource_type {
+	RSC_CARVEOUT     = 0,
+	RSC_DEVMEM       = 1,
+	RSC_TRACE        = 2,
+	RSC_VDEV         = 3,
+	RSC_LAST         = 4,
+	RSC_VENDOR_START = 128,
+	RSC_VENDOR_END   = 512,
+};
+
+#define FW_RSC_U64_ADDR_ANY 0xFFFFFFFFFFFFFFFFUL
+#define FW_RSC_U32_ADDR_ANY 0xFFFFFFFFUL
+
+/**
+ * struct fw_rsc_carveout - physically contiguous memory request
+ * @da: device address
+ * @pa: physical address
+ * @len: length (in bytes)
+ * @flags: iommu protection flags
+ * @reserved: reserved (must be zero)
+ * @name: human-readable name of the requested memory region
+ *
+ * This resource entry requests the host to allocate a physically contiguous
+ * memory region.
+ *
+ * These request entries should precede other firmware resource entries,
+ * as other entries might request placing other data objects inside
+ * these memory regions (e.g. data/code segments, trace resource entries, ...).
+ *
+ * Allocating memory this way helps utilizing the reserved physical memory
+ * (e.g. CMA) more efficiently, and also minimizes the number of TLB entries
+ * needed to map it (in case @rproc is using an IOMMU). Reducing the TLB
+ * pressure is important; it may have a substantial impact on performance.
+ *
+ * If the firmware is compiled with static addresses, then @da should specify
+ * the expected device address of this memory region. If @da is set to
+ * FW_RSC_ADDR_ANY, then the host will dynamically allocate it, and then
+ * overwrite @da with the dynamically allocated address.
+ *
+ * We will always use @da to negotiate the device addresses, even if it
+ * isn't using an iommu. In that case, though, it will obviously contain
+ * physical addresses.
+ *
+ * Some remote remoteprocs needs to know the allocated physical address
+ * even if they do use an iommu. This is needed, e.g., if they control
+ * hardware accelerators which access the physical memory directly (this
+ * is the case with OMAP4 for instance). In that case, the host will
+ * overwrite @pa with the dynamically allocated physical address.
+ * Generally we don't want to expose physical addresses if we don't have to
+ * (remote remoteprocs are generally _not_ trusted), so we might want to
+ * change this to happen _only_ when explicitly required by the hardware.
+ *
+ * @flags is used to provide IOMMU protection flags, and @name should
+ * (optionally) contain a human readable name of this carveout region
+ * (mainly for debugging purposes).
+ */
+METAL_PACKED_BEGIN
+struct fw_rsc_carveout {
+	uint32_t type;
+	uint32_t da;
+	uint32_t pa;
+	uint32_t len;
+	uint32_t flags;
+	uint32_t reserved;
+	uint8_t name[RPROC_MAX_NAME_LEN];
+} METAL_PACKED_END;
+
+/**
+ * struct fw_rsc_devmem - iommu mapping request
+ * @da: device address
+ * @pa: physical address
+ * @len: length (in bytes)
+ * @flags: iommu protection flags
+ * @reserved: reserved (must be zero)
+ * @name: human-readable name of the requested region to be mapped
+ *
+ * This resource entry requests the host to iommu map a physically contiguous
+ * memory region. This is needed in case the remote remoteproc requires
+ * access to certain memory-based peripherals; _never_ use it to access
+ * regular memory.
+ *
+ * This is obviously only needed if the remote remoteproc is accessing memory
+ * via an iommu.
+ *
+ * @da should specify the required device address, @pa should specify
+ * the physical address we want to map, @len should specify the size of
+ * the mapping and @flags is the IOMMU protection flags. As always, @name may
+ * (optionally) contain a human readable name of this mapping (mainly for
+ * debugging purposes).
+ *
+ * Note: at this point we just "trust" those devmem entries to contain valid
+ * physical addresses, but this isn't safe and will be changed: eventually we
+ * want remoteproc implementations to provide us ranges of physical addresses
+ * the firmware is allowed to request, and not allow firmwares to request
+ * access to physical addresses that are outside those ranges.
+ */
+METAL_PACKED_BEGIN
+struct fw_rsc_devmem {
+	uint32_t type;
+	uint32_t da;
+	uint32_t pa;
+	uint32_t len;
+	uint32_t flags;
+	uint32_t reserved;
+	uint8_t name[RPROC_MAX_NAME_LEN];
+} METAL_PACKED_END;
+
+/**
+ * struct fw_rsc_trace - trace buffer declaration
+ * @da: device address
+ * @len: length (in bytes)
+ * @reserved: reserved (must be zero)
+ * @name: human-readable name of the trace buffer
+ *
+ * This resource entry provides the host information about a trace buffer
+ * into which the remote remoteproc will write log messages.
+ *
+ * @da specifies the device address of the buffer, @len specifies
+ * its size, and @name may contain a human readable name of the trace buffer.
+ *
+ * After booting the remote remoteproc, the trace buffers are exposed to the
+ * user via debugfs entries (called trace0, trace1, etc..).
+ */
+METAL_PACKED_BEGIN
+struct fw_rsc_trace {
+	uint32_t type;
+	uint32_t da;
+	uint32_t len;
+	uint32_t reserved;
+	uint8_t name[RPROC_MAX_NAME_LEN];
+} METAL_PACKED_END;
+
+/**
+ * struct fw_rsc_vdev_vring - vring descriptor entry
+ * @da: device address
+ * @align: the alignment between the consumer and producer parts of the vring
+ * @num: num of buffers supported by this vring (must be power of two)
+ * @notifyid is a unique rproc-wide notify index for this vring. This notify
+ * index is used when kicking a remote remoteproc, to let it know that this
+ * vring is triggered.
+ * @reserved: reserved (must be zero)
+ *
+ * This descriptor is not a resource entry by itself; it is part of the
+ * vdev resource type (see below).
+ *
+ * Note that @da should either contain the device address where
+ * the remote remoteproc is expecting the vring, or indicate that
+ * dynamically allocation of the vring's device address is supported.
+ */
+METAL_PACKED_BEGIN
+struct fw_rsc_vdev_vring {
+	uint32_t da;
+	uint32_t align;
+	uint32_t num;
+	uint32_t notifyid;
+	uint32_t reserved;
+} METAL_PACKED_END;
+
+/**
+ * struct fw_rsc_vdev - virtio device header
+ * @id: virtio device id (as in virtio_ids.h)
+ * @notifyid is a unique rproc-wide notify index for this vdev. This notify
+ * index is used when kicking a remote remoteproc, to let it know that the
+ * status/features of this vdev have changes.
+ * @dfeatures specifies the virtio device features supported by the firmware
+ * @gfeatures is a place holder used by the host to write back the
+ * negotiated features that are supported by both sides.
+ * @config_len is the size of the virtio config space of this vdev. The config
+ * space lies in the resource table immediate after this vdev header.
+ * @status is a place holder where the host will indicate its virtio progress.
+ * @num_of_vrings indicates how many vrings are described in this vdev header
+ * @reserved: reserved (must be zero)
+ * @vring is an array of @num_of_vrings entries of 'struct fw_rsc_vdev_vring'.
+ *
+ * This resource is a virtio device header: it provides information about
+ * the vdev, and is then used by the host and its peer remote remoteprocs
+ * to negotiate and share certain virtio properties.
+ *
+ * By providing this resource entry, the firmware essentially asks remoteproc
+ * to statically allocate a vdev upon registration of the rproc (dynamic vdev
+ * allocation is not yet supported).
+ *
+ * Note: unlike virtualization systems, the term 'host' here means
+ * the Linux side which is running remoteproc to control the remote
+ * remoteprocs. We use the name 'gfeatures' to comply with virtio's terms,
+ * though there isn't really any virtualized guest OS here: it's the host
+ * which is responsible for negotiating the final features.
+ * Yeah, it's a bit confusing.
+ *
+ * Note: immediately following this structure is the virtio config space for
+ * this vdev (which is specific to the vdev; for more info, read the virtio
+ * spec). the size of the config space is specified by @config_len.
+ */
+METAL_PACKED_BEGIN
+struct fw_rsc_vdev {
+	uint32_t type;
+	uint32_t id;
+	uint32_t notifyid;
+	uint32_t dfeatures;
+	uint32_t gfeatures;
+	uint32_t config_len;
+	uint8_t status;
+	uint8_t num_of_vrings;
+	uint8_t reserved[2];
+	struct fw_rsc_vdev_vring vring[0];
+} METAL_PACKED_END;
+
+/**
+ * struct fw_rsc_vendor - remote processor vendor specific resource
+ * @len: length of the resource
+ *
+ * This resource entry tells the host the vendor specific resource
+ * required by the remote.
+ *
+ * These request entries should precede other shared resource entries
+ * such as vdevs, vrings.
+ */
+METAL_PACKED_BEGIN
+struct fw_rsc_vendor {
+	uint32_t type;
+	uint32_t len;
+} METAL_PACKED_END;
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* REMOTEPROC_H_ */
diff --git a/tensorflow/lite/micro/xtensa_hifi/rsc_table.c b/tensorflow/lite/micro/xtensa_hifi/rsc_table.c
new file mode 100644
index 00000000000..e0e29863e02
--- /dev/null
+++ b/tensorflow/lite/micro/xtensa_hifi/rsc_table.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright 2021 NXP.
+ *
+ * This file populates resource table for BM remote
+ * for use by the Linux Master
+ */
+
+#include "board.h"
+#include "rsc_table.h"
+#include <string.h>
+
+#define NUM_VRINGS 0x02
+
+/* Place resource table in special ELF section */
+__attribute__((section(".resource_table")))
+
+struct remote_resource_table resources = {
+	/* Version */
+	1,
+
+	/* NUmber of table entries */
+	NO_RESOURCE_ENTRIES,
+	/* reserved fields */
+	{
+		0,
+		0,
+	},
+
+	/* Offsets of rsc entries */
+	{
+		offsetof(struct remote_resource_table, user_vdev),
+	},
+
+	/* SRTM virtio device entry */
+	{
+		RSC_VDEV,
+		7,
+		0,
+		RSC_VDEV_FEATURE_NS,
+		0,
+		0,
+		0,
+		NUM_VRINGS,
+		{0, 0},
+	},
+
+	/* Vring rsc entry - part of vdev rsc entry */
+	{VDEV0_VRING_DA_BASE, VRING_ALIGN, RL_BUFFER_COUNT, 0, 0},
+	{VDEV0_VRING_DA_BASE + VRING_SIZE, VRING_ALIGN, RL_BUFFER_COUNT, 1, 0},
+};
diff --git a/tensorflow/lite/micro/xtensa_hifi/rsc_table.h b/tensorflow/lite/micro/xtensa_hifi/rsc_table.h
new file mode 100644
index 00000000000..294a8898cae
--- /dev/null
+++ b/tensorflow/lite/micro/xtensa_hifi/rsc_table.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright 2021 NXP
+ *
+ * This file populates resource table for BM remote
+ * for use by the Linux Master
+ */
+
+#ifndef RSC_TABLE_H_
+#define RSC_TABLE_H_
+
+#include <stddef.h>
+#include "remoteproc.h"
+
+#if defined __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Linux requires the ALIGN to 0x1000(4KB) instead of 0x80
+ */
+#ifndef VRING_ALIGN
+#define VRING_ALIGN (0x1000U)
+#endif
+
+/* contains pool of descriptors and two circular buffers */
+#ifndef VRING_SIZE
+#define VRING_SIZE (0x8000UL)
+#endif
+
+//! @def RL_BUFFER_COUNT
+//!
+//! Number of the buffers, it must be power of two (2, 4, ...).
+//! The default value is 2U.
+#define RL_BUFFER_COUNT (256U)
+
+#define NO_RESOURCE_ENTRIES (1)
+#define RSC_VDEV_FEATURE_NS (1) /* Support name service announcement */
+
+/* Resource table for the given remote */
+METAL_PACKED_BEGIN
+struct remote_resource_table {
+	uint32_t version;
+	uint32_t num;
+	uint32_t reserved[2];
+	uint32_t offset[NO_RESOURCE_ENTRIES];
+
+	/* rpmsg vdev entry for user app communication */
+	struct fw_rsc_vdev user_vdev;
+	struct fw_rsc_vdev_vring user_vring0;
+	struct fw_rsc_vdev_vring user_vring1;
+} METAL_PACKED_END;
+
+#if defined __cplusplus
+}
+#endif
+
+#endif /* RSC_TABLE_H_ */
-- 
2.34.1

