[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/devtools/met-driver/4.14/mt2731/Kbuild.platform.include b/src/devtools/met-driver/4.14/mt2731/Kbuild.platform.include
new file mode 100644
index 0000000..1061e98
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/Kbuild.platform.include
@@ -0,0 +1,33 @@
+################################################################################
+# Include Path
+################################################################################
+MET_VCOREDVFS_INC := $(KERNEL_SRC)/drivers/misc/mediatek/base/power/include/vcorefs_v3
+MET_PTPOD_INC := $(KERNEL_SRC)/drivers/misc/mediatek/base/power/cpufreq_v1/src/mach/$(MTK_PLATFORM)/
+
+
+################################################################################
+# Feature Spec
+# CPUPMU_VERSION: V8_0/V8_2
+# EMI_SEDA_VERSION: SEDA2/SEDA3/SEDA3_5
+# EMI_DRAMC_VERSION: V1/V2
+################################################################################
+CPUPMU_VERSION := V8_0
+EMI_SEDA_VERSION := SEDA3_5
+EMI_DRAMC_VERSION := V2
+
+
+################################################################################
+# Feature On/Off
+################################################################################
+FEATURE_SPMTWAM := n
+FEATURE_CPUDSU := n
+FEATURE_SSPM_EMI := n
+FEATURE_AP_EMI := y
+FEATURE_GPU := n
+FEATURE_VCOREDVFS := n
+FEATURE_PTPOD := n
+FEATURE_WALLTIME := n
+FEATURE_SMI=n
+FEATURE_EVENT_POWER=n
+FEATURE_ONDIEMET := n
+
diff --git a/src/devtools/met-driver/4.14/mt2731/Kbuild.yocto b/src/devtools/met-driver/4.14/mt2731/Kbuild.yocto
new file mode 100644
index 0000000..57f6fa6
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/Kbuild.yocto
@@ -0,0 +1,45 @@
+MET_PLF := $(MTK_PLATFORM)
+
+met-y += $(MET_PLF)/plf_trace.o
+
+################################################################################
+# MET_AP_EMI
+################################################################################
+FEATURE_AP_EMI := $(if $(FEATURE_AP_EMI),$(FEATURE_AP_EMI),y)
+$(info FEATURE_AP_EMI = $(FEATURE_AP_EMI))
+ifneq ($(FEATURE_AP_EMI), n)
+    MET_AP_EMI := y
+    # for mtk_dramc.h
+    ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/dramc/$(MTK_PLATFORM)/mtk_dramc.h)","")
+        ccflags-y += -I$(srctree)/drivers/misc/mediatek/dramc/$(MTK_PLATFORM)/
+    else
+        MET_AP_EMI = n
+        $(info ======== Missing $(srctree)/drivers/misc/mediatek/dramc/$(MTK_PLATFORM)/mtk_dramc.h ========)
+        $(info ======== disable MET_AP_EMI ========)
+    endif
+else
+    MET_AP_EMI := n
+endif
+
+$(info EMI_SEDA_VERSION = $(EMI_SEDA_VERSION))
+$(info EMI_DRAMC_VERSION = $(EMI_DRAMC_VERSION))
+ifeq ("$(EMI_DRAMC_VERSION)", "V1")
+    ccflags-y += -I$(MET_PLF_DIR)/dramc/V1/
+    met-$(MET_AP_EMI) += $(MET_PLF)/dramc/V1/mtk_dramc.o
+endif
+ifeq ("$(EMI_DRAMC_VERSION)", "V2")
+    ccflags-y += -I$(MET_PLF_DIR)/dramc/V2/
+    met-$(MET_AP_EMI) += $(MET_PLF)/dramc/V2/mtk_dramc.o
+endif
+ifeq ("$(EMI_SEDA_VERSION)", "SEDA2")
+    met-$(MET_AP_EMI) += $(MET_PLF)/emi/SEDA2/met_emi.o
+    met-$(MET_AP_EMI) += $(MET_PLF)/emi/SEDA2/mtk_emi_bm.o
+endif
+ifeq ("$(EMI_SEDA_VERSION)", "SEDA3")
+    met-$(MET_AP_EMI) += $(MET_PLF)/emi/SEDA3/met_emi.o
+    met-$(MET_AP_EMI) += $(MET_PLF)/emi/SEDA3/mtk_emi_bm.o
+endif
+ifeq ("$(EMI_SEDA_VERSION)", "SEDA3_5")
+    met-$(MET_AP_EMI) += $(MET_PLF)/emi/SEDA3_5/met_emi.o
+    met-$(MET_AP_EMI) += $(MET_PLF)/emi/SEDA3_5/mtk_emi_bm.o
+endif
diff --git a/src/devtools/met-driver/4.14/mt2731/dramc/V1/mtk_dramc.c b/src/devtools/met-driver/4.14/mt2731/dramc/V1/mtk_dramc.c
new file mode 100644
index 0000000..210f200
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/dramc/V1/mtk_dramc.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <mt-plat/sync_write.h>
+#include <mt-plat/mtk_io.h>
+
+#include "mtk_dramc_reg.h"
+
+#define BM_REQ_OK				(0)
+#define BM_ERR_WRONG_REQ			(-1)
+#define BM_ERR_OVERRUN				(-2)
+
+
+void __iomem *BaseAddrDRAMC[MAX_DRAMC_CHANN];
+void __iomem *BaseAddrDDRPHY_AO[2];
+void __iomem *BaseAddrDRAMC0_AO;
+
+
+unsigned int MET_DRAMC_GetPageHitCount(enum DRAMC_Cnt_Type CountType, int chann)
+{
+	unsigned int iCount;
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	switch (CountType) {
+	case DRAMC_R2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_PAGE_HIT));
+		break;
+	case DRAMC_R2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2W_PAGE_HIT));
+		break;
+	case DRAMC_W2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2R_PAGE_HIT));
+		break;
+	case DRAMC_W2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2W_PAGE_HIT));
+		break;
+	case DRAMC_ALL:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_PAGE_HIT)) +
+			 readl(IOMEM(addr_base + DRAMC_R2W_PAGE_HIT)) +
+			 readl(IOMEM(addr_base + DRAMC_W2R_PAGE_HIT)) +
+			 readl(IOMEM(addr_base + DRAMC_W2W_PAGE_HIT));
+		break;
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+unsigned int MET_DRAMC_GetPageMissCount(enum DRAMC_Cnt_Type CountType, int chann)
+{
+	unsigned int iCount;
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	switch (CountType) {
+	case DRAMC_R2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_PAGE_MISS));
+		break;
+	case DRAMC_R2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2W_PAGE_MISS));
+		break;
+	case DRAMC_W2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2R_PAGE_MISS));
+		break;
+	case DRAMC_W2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2W_PAGE_MISS));
+		break;
+	case DRAMC_ALL:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_PAGE_MISS)) +
+			 readl(IOMEM(addr_base + DRAMC_R2W_PAGE_MISS)) +
+			 readl(IOMEM(addr_base + DRAMC_W2R_PAGE_MISS)) +
+			 readl(IOMEM(addr_base + DRAMC_W2W_PAGE_MISS));
+		break;
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+unsigned int MET_DRAMC_GetInterbankCount(enum DRAMC_Cnt_Type CountType, int chann)
+{
+	unsigned int iCount;
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	switch (CountType) {
+	case DRAMC_R2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_INTERBANK));
+		break;
+	case DRAMC_R2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2W_INTERBANK));
+		break;
+	case DRAMC_W2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2R_INTERBANK));
+		break;
+	case DRAMC_W2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2W_INTERBANK));
+		break;
+	case DRAMC_ALL:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_INTERBANK)) +
+			 readl(IOMEM(addr_base + DRAMC_R2W_INTERBANK)) +
+			 readl(IOMEM(addr_base + DRAMC_W2R_INTERBANK)) +
+			 readl(IOMEM(addr_base + DRAMC_W2W_INTERBANK));
+		break;
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+unsigned int MET_DRAMC_GetIdleCount(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_IDLE_COUNT));
+}
+
+
+unsigned int MET_DRAMC_Misc_Status(int chann)
+{
+	return 0;
+}
+
+
+unsigned int MET_DRAMC_SPCMDRESP(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_MISC_SPCMDRESP));
+}
+
+
+unsigned int MET_DRAMC_RefPop(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_REFRESH_POP));
+}
+
+
+unsigned int MET_DRAMC_Free26M(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_FREERUN_26M));
+}
+
+
+unsigned int MET_DRAMC_RByte(int chann)
+{
+	return 0;
+}
+
+
+unsigned int MET_DRAMC_WByte(int chann)
+{
+	return 0;
+}
+
+
+unsigned int MET_DRAMC_DCM_CTRL(int chann)
+{
+	return 0;
+}
+
+
+void MET_DRAMC_GetDebugCounter(int *value, int chann)
+{
+	int i;
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	for (i = 0; i < chann; i++) {
+		if (i == 0)
+			addr_base = ADDR_DRAMC0;
+		else if (i == 1)
+			addr_base = ADDR_DRAMC1;
+		else if (i == 2)
+			addr_base = ADDR_DRAMC2;
+		else if (i == 3)
+			addr_base = ADDR_DRAMC3;
+		else
+			return;
+
+		value[DRAMC_Debug_MAX_CNT * i + BM_FREERUN_26M] = MET_DRAMC_Free26M(i);
+
+		/*not support these register , set the initial value 0*/
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK0_PRE_STANDBY] =   0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK0_PRE_POWERDOWN] = 0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK0_ACT_STANDBY] =   0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK0_ACT_POWERDOWN] = 0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK1_PRE_STANDBY] =   0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK1_PRE_POWERDOWN] = 0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK1_ACT_STANDBY] =   0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK1_ACT_POWERDOWN] = 0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK2_PRE_STANDBY] =   0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK2_PRE_POWERDOWN] = 0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK2_ACT_STANDBY] =   0;
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK2_ACT_POWERDOWN] = 0;
+	}
+}
diff --git a/src/devtools/met-driver/4.14/mt2731/dramc/V1/mtk_dramc_reg.h b/src/devtools/met-driver/4.14/mt2731/dramc/V1/mtk_dramc_reg.h
new file mode 100644
index 0000000..5a2c7c8
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/dramc/V1/mtk_dramc_reg.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MTK_DRAMC_REG_H__
+#define __MTK_DRAMC_REG_H__
+#include <linux/compiler.h>
+
+#define DRAMC_VER 1
+
+#define MAX_DRAMC_CHANN 4
+extern void __iomem *BaseAddrDRAMC[MAX_DRAMC_CHANN];
+extern void __iomem *BaseAddrDDRPHY_AO[2];
+extern void __iomem *BaseAddrDRAMC0_AO;
+
+enum BM_DRAMC_DTS_INDEX {
+	DRAMC_DTS_DRAMC0_AO = 0x0,
+	DRAMC_DTS_DRAMC0_NAO = 0x4,
+	DRAMC_DTS_DRAMC1_NAO = 0x5,
+	DRAMC_DTS_DRAMC2_NAO = 0x6,
+	DRAMC_DTS_DRAMC3_NAO = 0x7,
+	DRAMC_DTS_DDRPHY0_AO = 0x8,
+};
+
+enum DRAMC_Debug_Type {
+	BM_FREERUN_26M = 0x0,
+	BM_RK0_PRE_STANDBY,
+	BM_RK0_PRE_POWERDOWN,
+	BM_RK0_ACT_STANDBY,
+	BM_RK0_ACT_POWERDOWN,
+	BM_RK1_PRE_STANDBY,
+	BM_RK1_PRE_POWERDOWN,
+	BM_RK1_ACT_STANDBY,
+	BM_RK1_ACT_POWERDOWN,
+	BM_RK2_PRE_STANDBY,
+	BM_RK2_PRE_POWERDOWN,
+	BM_RK2_ACT_STANDBY,
+	BM_RK2_ACT_POWERDOWN,
+	DRAMC_Debug_MAX_CNT
+};
+
+enum DRAMC_Cnt_Type {
+	DRAMC_R2R,
+	DRAMC_R2W,
+	DRAMC_W2R,
+	DRAMC_W2W,
+	DRAMC_ALL
+};
+
+#define ADDR_DRAMC0     ((unsigned long)BaseAddrDRAMC[0])
+#define ADDR_DRAMC1     ((unsigned long)BaseAddrDRAMC[1])
+#define ADDR_DRAMC2     ((unsigned long)BaseAddrDRAMC[2])
+#define ADDR_DRAMC3     ((unsigned long)BaseAddrDRAMC[3])
+#define DRAMC_REFRESH_POP       0x2b8
+#define DRAMC_FREERUN_26M       0x2b4
+#define DRAMC_R2R_PAGE_HIT      0x280
+#define DRAMC_R2R_PAGE_MISS     0x284
+#define DRAMC_R2R_INTERBANK     0x288
+#define DRAMC_R2W_PAGE_HIT      0x28c
+#define DRAMC_R2W_PAGE_MISS     0x290
+#define DRAMC_R2W_INTERBANK     0x294
+#define DRAMC_W2R_PAGE_HIT      0x298
+#define DRAMC_W2R_PAGE_MISS     0x29c
+#define DRAMC_W2R_INTERBANK     0x2a0
+#define DRAMC_W2W_PAGE_HIT      0x2a4
+#define DRAMC_W2W_PAGE_MISS     0x2a8
+#define DRAMC_W2W_INTERBANK     0x2ac
+#define DRAMC_IDLE_COUNT        0x2b0
+#define DRAMC_MISC_SPCMDRESP    0x3b8
+
+extern unsigned int MET_DRAMC_GetPageHitCount(enum DRAMC_Cnt_Type CountType, int chann);
+extern unsigned int MET_DRAMC_GetPageMissCount(enum DRAMC_Cnt_Type CountType, int chann);
+extern unsigned int MET_DRAMC_GetInterbankCount(enum DRAMC_Cnt_Type CountType, int chann);
+extern unsigned int MET_DRAMC_GetIdleCount(int chann);
+extern unsigned int MET_DRAMC_Misc_Status(int chann);
+extern unsigned int MET_DRAMC_SPCMDRESP(int chann);
+extern unsigned int MET_DRAMC_RefPop(int chann);
+extern unsigned int MET_DRAMC_Free26M(int chann);
+extern unsigned int MET_DRAMC_RByte(int chann);
+extern unsigned int MET_DRAMC_WByte(int chann);
+extern unsigned int MET_DRAMC_DCM_CTRL(int chann);
+
+/* Debug Counter status */
+extern void MET_DRAMC_GetDebugCounter(int *value, int chann);
+
+
+#endif /* __MTK_DRAMC_REG_H__ */
diff --git a/src/devtools/met-driver/4.14/mt2731/dramc/V2/mtk_dramc.c b/src/devtools/met-driver/4.14/mt2731/dramc/V2/mtk_dramc.c
new file mode 100644
index 0000000..7d4762c
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/dramc/V2/mtk_dramc.c
@@ -0,0 +1,355 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <mt-plat/sync_write.h>
+#include <mt-plat/mtk_io.h>
+
+#include "mtk_dramc_reg.h"
+
+#define BM_REQ_OK				(0)
+#define BM_ERR_WRONG_REQ			(-1)
+#define BM_ERR_OVERRUN				(-2)
+
+
+void __iomem *BaseAddrDRAMC[MAX_DRAMC_CHANN];
+void __iomem *BaseAddrDDRPHY_AO[2];
+void __iomem *BaseAddrDRAMC0_AO;
+
+
+unsigned int MET_DRAMC_GetPageHitCount(enum DRAMC_Cnt_Type CountType, int chann)
+{
+	unsigned int iCount;
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	switch (CountType) {
+	case DRAMC_R2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_PAGE_HIT));
+		break;
+	case DRAMC_R2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2W_PAGE_HIT));
+		break;
+	case DRAMC_W2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2R_PAGE_HIT));
+		break;
+	case DRAMC_W2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2W_PAGE_HIT));
+		break;
+	case DRAMC_ALL:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_PAGE_HIT)) +
+			 readl(IOMEM(addr_base + DRAMC_R2W_PAGE_HIT)) +
+			 readl(IOMEM(addr_base + DRAMC_W2R_PAGE_HIT)) +
+			 readl(IOMEM(addr_base + DRAMC_W2W_PAGE_HIT));
+		break;
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+unsigned int MET_DRAMC_GetPageMissCount(enum DRAMC_Cnt_Type CountType, int chann)
+{
+	unsigned int iCount;
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	switch (CountType) {
+	case DRAMC_R2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_PAGE_MISS));
+		break;
+	case DRAMC_R2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2W_PAGE_MISS));
+		break;
+	case DRAMC_W2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2R_PAGE_MISS));
+		break;
+	case DRAMC_W2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2W_PAGE_MISS));
+		break;
+	case DRAMC_ALL:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_PAGE_MISS)) +
+			 readl(IOMEM(addr_base + DRAMC_R2W_PAGE_MISS)) +
+			 readl(IOMEM(addr_base + DRAMC_W2R_PAGE_MISS)) +
+			 readl(IOMEM(addr_base + DRAMC_W2W_PAGE_MISS));
+		break;
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+unsigned int MET_DRAMC_GetInterbankCount(enum DRAMC_Cnt_Type CountType, int chann)
+{
+	unsigned int iCount;
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	switch (CountType) {
+	case DRAMC_R2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_INTERBANK));
+		break;
+	case DRAMC_R2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2W_INTERBANK));
+		break;
+	case DRAMC_W2R:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2R_INTERBANK));
+		break;
+	case DRAMC_W2W:
+		iCount = readl(IOMEM(addr_base + DRAMC_W2W_INTERBANK));
+		break;
+	case DRAMC_ALL:
+		iCount = readl(IOMEM(addr_base + DRAMC_R2R_INTERBANK)) +
+			 readl(IOMEM(addr_base + DRAMC_R2W_INTERBANK)) +
+			 readl(IOMEM(addr_base + DRAMC_W2R_INTERBANK)) +
+			 readl(IOMEM(addr_base + DRAMC_W2W_INTERBANK));
+		break;
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+unsigned int MET_DRAMC_GetIdleCount(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_IDLE_COUNT));
+}
+
+
+unsigned int MET_DRAMC_Misc_Status(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_MISC_STATUSA));
+}
+
+
+unsigned int MET_DRAMC_SPCMDRESP(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_MISC_SPCMDRESP));
+}
+
+
+unsigned int MET_DRAMC_RefPop(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_REFRESH_POP));
+}
+
+
+unsigned int MET_DRAMC_Free26M(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_FREERUN_26M));
+}
+
+
+unsigned int MET_DRAMC_RByte(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_READ_BYTES));
+}
+
+
+unsigned int MET_DRAMC_WByte(int chann)
+{
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	if (chann == 0)
+		addr_base = ADDR_DRAMC0;
+	else if (chann == 1)
+		addr_base = ADDR_DRAMC1;
+	else if (chann == 2)
+		addr_base = ADDR_DRAMC2;
+	else if (chann == 3)
+		addr_base = ADDR_DRAMC3;
+	else
+		return BM_ERR_WRONG_REQ;
+
+	return readl(IOMEM(addr_base + DRAMC_WRITE_BYTES));
+}
+
+
+unsigned int MET_DRAMC_DCM_CTRL(int chann)
+{
+	unsigned long addr_base;
+
+	if (chann == 0)
+		addr_base = (unsigned long)BaseAddrDDRPHY_AO[0];
+	else if (chann == 1)
+		addr_base = (unsigned long)BaseAddrDDRPHY_AO[1];
+	else
+		return BM_ERR_WRONG_REQ;
+
+	/* CH0_MEM_DCM_CTRL[25:21] DCM slowdown factor */
+	return ((readl(IOMEM(addr_base + DRAMC_DCM_CTRL)) & 0x03E00000) >> 21);
+}
+
+
+void MET_DRAMC_GetDebugCounter(int *value, int chann)
+{
+	int i;
+	unsigned long addr_base = ADDR_DRAMC0;
+
+	for (i = 0; i < chann; i++) {
+		if (i == 0)
+			addr_base = ADDR_DRAMC0;
+		else if (i == 1)
+			addr_base = ADDR_DRAMC1;
+		else if (i == 2)
+			addr_base = ADDR_DRAMC2;
+		else if (i == 3)
+			addr_base = ADDR_DRAMC3;
+		else
+			return;
+
+		value[DRAMC_Debug_MAX_CNT * i + BM_FREERUN_26M] = MET_DRAMC_Free26M(i);
+
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK0_PRE_STANDBY] =
+			readl(IOMEM(addr_base + DRAMC_RK0_PRE_STANDBY));
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK0_PRE_POWERDOWN] =
+			readl(IOMEM(addr_base + DRAMC_RK0_PRE_POWERDOWN));
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK0_ACT_STANDBY] =
+			readl(IOMEM(addr_base + DRAMC_RK0_ACT_STANDBY));
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK0_ACT_POWERDOWN] =
+			readl(IOMEM(addr_base + DRAMC_RK0_ACT_POWERDOWN));
+
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK1_PRE_STANDBY] =
+			readl(IOMEM(addr_base + DRAMC_RK1_PRE_STANDBY));
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK1_PRE_POWERDOWN] =
+			readl(IOMEM(addr_base + DRAMC_RK1_PRE_POWERDOWN));
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK1_ACT_STANDBY] =
+			readl(IOMEM(addr_base + DRAMC_RK1_ACT_STANDBY));
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK1_ACT_POWERDOWN] =
+			readl(IOMEM(addr_base + DRAMC_RK1_ACT_POWERDOWN));
+
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK2_PRE_STANDBY] =
+			readl(IOMEM(addr_base + DRAMC_RK2_PRE_STANDBY));
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK2_PRE_POWERDOWN] =
+			readl(IOMEM(addr_base + DRAMC_RK2_PRE_POWERDOWN));
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK2_ACT_STANDBY] =
+			readl(IOMEM(addr_base + DRAMC_RK2_ACT_STANDBY));
+		value[DRAMC_Debug_MAX_CNT * i + BM_RK2_ACT_POWERDOWN] =
+			readl(IOMEM(addr_base + DRAMC_RK2_ACT_POWERDOWN));
+	}
+}
diff --git a/src/devtools/met-driver/4.14/mt2731/dramc/V2/mtk_dramc_reg.h b/src/devtools/met-driver/4.14/mt2731/dramc/V2/mtk_dramc_reg.h
new file mode 100644
index 0000000..44c30fe
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/dramc/V2/mtk_dramc_reg.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MTK_DRAMC_REG_H__
+#define __MTK_DRAMC_REG_H__
+#include <linux/compiler.h>
+
+#define DRAMC_VER 2
+
+#define MAX_DRAMC_CHANN 4
+extern void __iomem *BaseAddrDRAMC[MAX_DRAMC_CHANN];
+extern void __iomem *BaseAddrDDRPHY_AO[2];
+extern void __iomem *BaseAddrDRAMC0_AO;
+
+enum BM_DRAMC_DTS_INDEX {
+	DRAMC_DTS_DRAMC0_AO = 0x0,
+	DRAMC_DTS_DRAMC0_NAO = 0x4,
+	DRAMC_DTS_DRAMC1_NAO = 0x5,
+	DRAMC_DTS_DRAMC2_NAO = 0x6,
+	DRAMC_DTS_DRAMC3_NAO = 0x7,
+	DRAMC_DTS_DDRPHY0_AO = 0x8,
+};
+
+enum DRAMC_Debug_Type {
+	BM_FREERUN_26M = 0x0,
+	BM_RK0_PRE_STANDBY,
+	BM_RK0_PRE_POWERDOWN,
+	BM_RK0_ACT_STANDBY,
+	BM_RK0_ACT_POWERDOWN,
+	BM_RK1_PRE_STANDBY,
+	BM_RK1_PRE_POWERDOWN,
+	BM_RK1_ACT_STANDBY,
+	BM_RK1_ACT_POWERDOWN,
+	BM_RK2_PRE_STANDBY,
+	BM_RK2_PRE_POWERDOWN,
+	BM_RK2_ACT_STANDBY,
+	BM_RK2_ACT_POWERDOWN,
+	DRAMC_Debug_MAX_CNT
+};
+
+enum DRAMC_Cnt_Type {
+	DRAMC_R2R,
+	DRAMC_R2W,
+	DRAMC_W2R,
+	DRAMC_W2W,
+	DRAMC_ALL
+};
+
+#define ADDR_DRAMC0     ((unsigned long)BaseAddrDRAMC[0])
+#define ADDR_DRAMC1     ((unsigned long)BaseAddrDRAMC[1])
+#define ADDR_DRAMC2     ((unsigned long)BaseAddrDRAMC[2])
+#define ADDR_DRAMC3     ((unsigned long)BaseAddrDRAMC[3])
+
+#define DRAMC_MISC_STATUSA      0x80
+#define DRAMC_DCM_CTRL		0x28C
+#define DRAMC_REFRESH_POP       0x300
+#define DRAMC_FREERUN_26M       0x304
+#define DRAMC_R2R_PAGE_HIT      0x30C
+#define DRAMC_R2R_PAGE_MISS     0x310
+#define DRAMC_R2R_INTERBANK     0x314
+#define DRAMC_R2W_PAGE_HIT      0x318
+#define DRAMC_R2W_PAGE_MISS     0x31C
+#define DRAMC_R2W_INTERBANK     0x320
+#define DRAMC_W2R_PAGE_HIT      0x324
+#define DRAMC_W2R_PAGE_MISS     0x328
+#define DRAMC_W2R_INTERBANK     0x32C
+#define DRAMC_W2W_PAGE_HIT      0x330
+#define DRAMC_W2W_PAGE_MISS     0x334
+#define DRAMC_W2W_INTERBANK     0x338
+#define DRAMC_IDLE_COUNT        0x308
+#define DRAMC_RK0_PRE_STANDBY   0x33c
+#define DRAMC_RK0_PRE_POWERDOWN 0x340
+#define DRAMC_RK0_ACT_STANDBY   0x344
+#define DRAMC_RK0_ACT_POWERDOWN 0x348
+#define DRAMC_RK1_PRE_STANDBY   0x34c
+#define DRAMC_RK1_PRE_POWERDOWN 0x350
+#define DRAMC_RK1_ACT_STANDBY   0x354
+#define DRAMC_RK1_ACT_POWERDOWN 0x358
+#define DRAMC_RK2_PRE_STANDBY   0x35c
+#define DRAMC_RK2_PRE_POWERDOWN 0x360
+#define DRAMC_RK2_ACT_STANDBY   0x364
+#define DRAMC_RK2_ACT_POWERDOWN 0x368
+#define DRAMC_READ_BYTES        0x38c
+#define DRAMC_WRITE_BYTES       0x390
+#define DRAMC_MISC_SPCMDRESP    0x3b8
+
+extern unsigned int MET_DRAMC_GetPageHitCount(enum DRAMC_Cnt_Type CountType, int chann);
+extern unsigned int MET_DRAMC_GetPageMissCount(enum DRAMC_Cnt_Type CountType, int chann);
+extern unsigned int MET_DRAMC_GetInterbankCount(enum DRAMC_Cnt_Type CountType, int chann);
+extern unsigned int MET_DRAMC_GetIdleCount(int chann);
+extern unsigned int MET_DRAMC_Misc_Status(int chann);
+extern unsigned int MET_DRAMC_SPCMDRESP(int chann);
+extern unsigned int MET_DRAMC_RefPop(int chann);
+extern unsigned int MET_DRAMC_Free26M(int chann);
+extern unsigned int MET_DRAMC_RByte(int chann);
+extern unsigned int MET_DRAMC_WByte(int chann);
+extern unsigned int MET_DRAMC_DCM_CTRL(int chann);
+
+/* Debug Counter status */
+extern void MET_DRAMC_GetDebugCounter(int *value, int chann);
+
+
+#endif /* __MTK_DRAMC_REG_H__ */
diff --git a/src/devtools/met-driver/4.14/mt2731/emi/SEDA2/met_emi.c b/src/devtools/met-driver/4.14/mt2731/emi/SEDA2/met_emi.c
new file mode 100644
index 0000000..554fc05
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/emi/SEDA2/met_emi.c
@@ -0,0 +1,1549 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#ifdef CONFIG_ARM
+//#include <asm/dma-mapping.h> /* arm_coherent_dma_ops */
+#endif /* CONFIG_ARM */
+#include <linux/dma-mapping.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "plf_init.h"
+#include "plf_trace.h"
+#include "mtk_emi_bm.h"
+#include "mtk_dramc_reg.h"
+#include "interface.h"
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+#include "sspm/ondiemet_sspm.h"
+#endif
+
+
+/*======================================================================*/
+/*	Global variable definitions					*/
+/*======================================================================*/
+/*ondiemet emi sampling interval in us */
+int emi_tsct_enable;
+int emi_mdct_enable;
+int emi_TP_busfiltr_enable;
+
+int emi_use_ondiemet;
+int metemi_func_opt;
+
+int met_emi_regdump;
+/* Dynamic MonitorCounter selection !!!EXPERIMENT!!! */
+static int msel_enable;
+static unsigned int msel_group1 = BM_MASTER_ALL;
+static unsigned int msel_group2 = BM_MASTER_ALL;
+static unsigned int msel_group3 = BM_MASTER_ALL;
+
+/* CVS Added changeable buffer for testing */
+static int mdmcu_sel_enable;
+static unsigned int rd_mdmcu_rsv_num = 0x5;
+
+/* Global variables */
+static struct kobject *kobj_emi;
+static int rwtype = BM_BOTH_READ_WRITE;
+
+/* BW Limiter */
+/*#define CNT_COUNTDOWN	(1000-1)*/		/* 1000 * 1ms = 1sec */
+#define CNT_COUNTDOWN   (0)                     /* 1ms */
+static int countdown;
+static int bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+
+/* TTYPE counter */
+static int ttype1_16_en = BM_TTYPE1_16_DISABLE;
+static int ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+static int dramc_pdir_enable;
+static int dram_chann_num = 1;
+
+enum SSPM_Mode {
+	CUSTOMER_MODE = 0x0,
+	UNDEFINE_MODE = 0x1,
+	INTERNAL_MODE = 0X2780
+};
+
+
+/*======================================================================*/
+/*	EMI Test Operations						*/
+/*======================================================================*/
+static int times;
+
+static ssize_t test_apmcu_store(struct kobject *kobj,
+				struct kobj_attribute *attr,
+				const char *buf,
+				size_t n)
+{
+	int i;
+	unsigned int    *src_addr_v = NULL;
+	dma_addr_t src_addr_p;
+#ifdef CONFIG_ARM
+	struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_dma_ops);
+#endif /* CONFIG_ARM */
+
+	if ((n == 0) || (buf == NULL))
+		return -EINVAL;
+	if (kstrtoint(buf, 10, &times) != 0)
+		return -EINVAL;
+	if (times < 0)
+		return -EINVAL;
+
+	if (times > 5000)       /* Less than 20MB */
+		return -EINVAL;
+
+#ifdef CONFIG_ARM
+	if (ops && ops->alloc) {
+		(met_device.this_device)->coherent_dma_mask = DMA_BIT_MASK(32);
+		src_addr_v = ops->alloc(met_device.this_device,
+						PAGE_SIZE,
+						&src_addr_p,
+						GFP_KERNEL,
+						0);
+	}
+#endif /* CONFIG_ARM */
+ 
+#ifdef CONFIG_ARM64
+	/* dma_alloc */
+ 	src_addr_v = dma_alloc_coherent(met_device.this_device,
+ 					PAGE_SIZE,
+ 					&src_addr_p,
+ 					GFP_KERNEL);
+#endif /* CONFIG_ARM64 */
+
+	if (src_addr_v == NULL) {
+#ifdef CONFIG_MET_MODULE
+		met_tag_oneshot_real(0, "test_apmcu dma alloc fail", PAGE_SIZE);
+#else
+		met_tag_oneshot(0, "test_apmcu dma alloc fail", PAGE_SIZE);
+#endif
+		return -ENOMEM;
+	}
+	/* testing */
+	preempt_disable();
+#ifdef CONFIG_MET_MODULE
+	met_tag_start_real(0, "TEST_EMI_APMCU");
+#else
+	met_tag_start(0, "TEST_EMI_APMCU");
+#endif
+	for (i = 0; i < times; i++) {
+		memset(src_addr_v, 2 * i, PAGE_SIZE);
+#ifdef CONFIG_MET_MODULE
+		met_tag_oneshot_real(0, "TEST_EMI_APMCU", PAGE_SIZE);
+#else
+		met_tag_oneshot(0, "TEST_EMI_APMCU", PAGE_SIZE);
+#endif
+	}
+#ifdef CONFIG_MET_MODULE
+	met_tag_end_real(0, "TEST_EMI_APMCU");
+#else
+	met_tag_end(0, "TEST_EMI_APMCU");
+#endif
+	/* the following function has no defined if MET is built as module */
+	/* preempt_enable_no_resched(); */
+	/* use this one to replace it: see met_drv.h */
+	my_preempt_enable();
+
+#ifdef CONFIG_ARM
+	/* dma_free */
+	if (ops && ops->free) {
+		ops->free(met_device.this_device,
+				  PAGE_SIZE,
+				  src_addr_v,
+				  src_addr_p,
+			0);
+	}
+#endif /* CONFIG_ARM */
+
+#ifdef CONFIG_ARM64
+	/* dma_free */
+ 	if (src_addr_v != NULL)
+ 		dma_free_coherent(met_device.this_device,
+ 				  PAGE_SIZE,
+ 				  src_addr_v,
+				  src_addr_p);
+#endif /* CONFIG_ARM64 */
+
+	return n;
+}
+
+/*======================================================================*/
+/*	KOBJ Declarations						*/
+/*======================================================================*/
+DECLARE_KOBJ_ATTR_INT(emi_tsct_enable, emi_tsct_enable);
+DECLARE_KOBJ_ATTR_INT(emi_mdct_enable, emi_mdct_enable);
+DECLARE_KOBJ_ATTR_INT(emi_TP_busfiltr_enable, emi_TP_busfiltr_enable);
+DECLARE_KOBJ_ATTR_INT(metemi_func_opt, metemi_func_opt);
+DECLARE_KOBJ_ATTR_INT(emi_regdump, met_emi_regdump);
+DECLARE_KOBJ_ATTR_INT(msel_enable, msel_enable);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group1, msel_group1, msel_group1 > 0 && msel_group1 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group2, msel_group2, msel_group2 > 0 && msel_group2 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group3, msel_group3, msel_group3 > 0 && msel_group3 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_INT(mdmcu_sel_enable, mdmcu_sel_enable);
+DECLARE_KOBJ_ATTR_INT(rd_mdmcu_rsv_num, rd_mdmcu_rsv_num);
+
+
+/* KOBJ: rwtype */
+DECLARE_KOBJ_ATTR_INT_CHECK(rwtype, rwtype, rwtype >= 0 && rwtype <= BM_WRITE_ONLY);
+
+static unsigned int get_emi_clock_rate(unsigned int dram_data_rate_MHz)
+{
+	/*
+	 *	the ddr type define :
+	 *	enum DDRTYPE {
+	 *	TYPE_LPDDR3 = 1,
+	 *	TYPE_LPDDR4,
+	 *	TYPE_LPDDR4X,
+	 *	TYPE_LPDDR2
+	 *	};
+	 */
+
+	unsigned int DRAM_TYPE;
+
+	if (get_ddr_type_symbol) {
+		DRAM_TYPE = get_ddr_type_symbol();
+
+		if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+			return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP4 / DRAM_DATARATE;
+		else
+			return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP3 / DRAM_DATARATE;
+	} else {
+		METERROR("[%s][%d]get_ddr_type_symbol = NULL , use the TYPE_LPDDR3 setting\n", __func__, __LINE__);
+		return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP3 / DRAM_DATARATE;
+	}
+}
+
+/* KOBJ: emi_clock_rate */
+static ssize_t emi_clock_rate_show(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   char *buf)
+{
+	unsigned int dram_data_rate_MHz;
+
+	if (get_dram_data_rate_symbol) {
+		dram_data_rate_MHz = get_dram_data_rate_symbol();
+	} else {
+		METERROR("get_dram_data_rate_symbol = NULL\n");
+		dram_data_rate_MHz = 0;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			get_emi_clock_rate(dram_data_rate_MHz));
+}
+
+DECLARE_KOBJ_ATTR_RO(emi_clock_rate);
+
+/* KOBJ: ttype1_16_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype1_16_en,
+	KOBJ_ITEM_LIST(
+		{ BM_TTYPE1_16_ENABLE,   "ENABLE" },
+		{ BM_TTYPE1_16_DISABLE,  "DISABLE" }
+		)
+	);
+DECLARE_KOBJ_ATTR_STR_LIST(ttype1_16_en, ttype1_16_en, ttype1_16_en);
+
+/* KOBJ: ttype17_21_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype17_21_en,
+	KOBJ_ITEM_LIST(
+		{ BM_TTYPE17_21_ENABLE,  "ENABLE" },
+		{ BM_TTYPE17_21_DISABLE, "DISABLE" }
+		)
+	);
+DECLARE_KOBJ_ATTR_STR_LIST(ttype17_21_en, ttype17_21_en, ttype17_21_en);
+
+/* KOBJ: bw_limiter_enable */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	bw_limiter_enable,
+	KOBJ_ITEM_LIST(
+		{ BM_BW_LIMITER_ENABLE,  "ENABLE" },
+		{ BM_BW_LIMITER_DISABLE, "DISABLE" }
+		)
+	);
+
+DECLARE_KOBJ_ATTR_STR_LIST(bw_limiter_enable, bw_limiter_enable, bw_limiter_enable);
+
+/* KOBJ: ttype_master */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype_master,
+	KOBJ_ITEM_LIST(
+		{ BM_MASTER_M0,  "M0" },
+		{ BM_MASTER_M1,  "M1" },
+		{ BM_MASTER_M2,  "M2" },
+		{ BM_MASTER_M3,  "M3" },
+		{ BM_MASTER_M4,  "M4" },
+		{ BM_MASTER_M5,  "M5" },
+		{ BM_MASTER_M6,  "M6" },
+		{ BM_MASTER_M7,  "M7" }
+		)
+	);
+
+
+/* KOBJ: ttypeX_nbeat, ttypeX_nbyte, ttypeX_burst */
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+	ttype_nbeat,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_TYPE_1BEAT,   1 },
+		{ BM_TRANS_TYPE_2BEAT,   2 },
+		{ BM_TRANS_TYPE_3BEAT,   3 },
+		{ BM_TRANS_TYPE_4BEAT,   4 },
+		{ BM_TRANS_TYPE_5BEAT,   5 },
+		{ BM_TRANS_TYPE_6BEAT,   6 },
+		{ BM_TRANS_TYPE_7BEAT,   7 },
+		{ BM_TRANS_TYPE_8BEAT,   8 },
+		{ BM_TRANS_TYPE_9BEAT,   9 },
+		{ BM_TRANS_TYPE_10BEAT,  10 },
+		{ BM_TRANS_TYPE_11BEAT,  11 },
+		{ BM_TRANS_TYPE_12BEAT,  12 },
+		{ BM_TRANS_TYPE_13BEAT,  13 },
+		{ BM_TRANS_TYPE_14BEAT,  14 },
+		{ BM_TRANS_TYPE_15BEAT,  15 },
+		{ BM_TRANS_TYPE_16BEAT,  16 }
+		)
+	);
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+	ttype_nbyte,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_TYPE_1Byte,   1 },
+		{ BM_TRANS_TYPE_2Byte,   2 },
+		{ BM_TRANS_TYPE_4Byte,   4 },
+		{ BM_TRANS_TYPE_8Byte,   8 },
+		{ BM_TRANS_TYPE_16Byte,  16 },
+		{ BM_TRANS_TYPE_32Byte,  32 }
+		)
+	);
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype_burst,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_TYPE_BURST_INCR,      "INCR" },
+		{ BM_TRANS_TYPE_BURST_WRAP,      "WRAP" }
+		)
+	);
+
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype_rw,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_RW_DEFAULT,   "DEFAULT" },
+		{ BM_TRANS_RW_READONLY,  "R" },
+		{ BM_TRANS_RW_WRITEONLY, "W" },
+		{ BM_TRANS_RW_RWBOTH,    "BOTH" }
+		)
+	);
+
+/* KOBJ: test_apmcu */
+DECLARE_KOBJ_ATTR_SHOW_INT(test_apmcu, times);
+/* please refer to session: "EMI Test Operations" for store operation */
+DECLARE_KOBJ_ATTR(test_apmcu);
+
+DECLARE_KOBJ_ATTR_INT(dramc_pdir_enable, dramc_pdir_enable);
+
+/*enable high priority filter*/
+static int high_priority_filter;
+DECLARE_KOBJ_ATTR_HEX(high_priority_filter, high_priority_filter);
+
+
+/**/
+static int ttype_master_val[21];
+static int ttype_busid_val[21];
+static int ttype_nbeat_val[21];
+static int ttype_nbyte_val[21];
+static int ttype_burst_val[21];
+static int ttype_rw_val[21];
+
+#define DECLARE_KOBJ_TTYPE_MASTER(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _master, ttype_master_val[nr - 1], ttype_master)
+
+#define DECLARE_KOBJ_TTYPE_NBEAT(nr) \
+	DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbeat, ttype_nbeat_val[nr - 1], ttype_nbeat)
+
+#define DECLARE_KOBJ_TTYPE_NBYTE(nr) \
+	DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbyte, ttype_nbyte_val[nr - 1], ttype_nbyte)
+
+#define DECLARE_KOBJ_TTYPE_BURST(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _burst, ttype_burst_val[nr - 1], ttype_burst)
+
+#define DECLARE_KOBJ_TTYPE_RW(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _rw, ttype_rw_val[nr - 1], ttype_rw)
+
+#define DECLARE_KOBJ_TTYPE_BUSID_VAL(nr) \
+	DECLARE_KOBJ_ATTR_HEX(ttype ## nr ## _busid, ttype_busid_val[nr - 1])
+
+DECLARE_KOBJ_TTYPE_MASTER(1);
+DECLARE_KOBJ_TTYPE_NBEAT(1);
+DECLARE_KOBJ_TTYPE_NBYTE(1);
+DECLARE_KOBJ_TTYPE_BURST(1);
+DECLARE_KOBJ_TTYPE_RW(1);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(1);
+
+DECLARE_KOBJ_TTYPE_MASTER(2);
+DECLARE_KOBJ_TTYPE_NBEAT(2);
+DECLARE_KOBJ_TTYPE_NBYTE(2);
+DECLARE_KOBJ_TTYPE_BURST(2);
+DECLARE_KOBJ_TTYPE_RW(2);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(2);
+
+DECLARE_KOBJ_TTYPE_MASTER(3);
+DECLARE_KOBJ_TTYPE_NBEAT(3);
+DECLARE_KOBJ_TTYPE_NBYTE(3);
+DECLARE_KOBJ_TTYPE_BURST(3);
+DECLARE_KOBJ_TTYPE_RW(3);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(3);
+
+DECLARE_KOBJ_TTYPE_MASTER(4);
+DECLARE_KOBJ_TTYPE_NBEAT(4);
+DECLARE_KOBJ_TTYPE_NBYTE(4);
+DECLARE_KOBJ_TTYPE_BURST(4);
+DECLARE_KOBJ_TTYPE_RW(4);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(4);
+
+DECLARE_KOBJ_TTYPE_MASTER(5);
+DECLARE_KOBJ_TTYPE_NBEAT(5);
+DECLARE_KOBJ_TTYPE_NBYTE(5);
+DECLARE_KOBJ_TTYPE_BURST(5);
+DECLARE_KOBJ_TTYPE_RW(5);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(5);
+
+DECLARE_KOBJ_TTYPE_MASTER(6);
+DECLARE_KOBJ_TTYPE_NBEAT(6);
+DECLARE_KOBJ_TTYPE_NBYTE(6);
+DECLARE_KOBJ_TTYPE_BURST(6);
+DECLARE_KOBJ_TTYPE_RW(6);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(6);
+
+DECLARE_KOBJ_TTYPE_MASTER(7);
+DECLARE_KOBJ_TTYPE_NBEAT(7);
+DECLARE_KOBJ_TTYPE_NBYTE(7);
+DECLARE_KOBJ_TTYPE_BURST(7);
+DECLARE_KOBJ_TTYPE_RW(7);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(7);
+
+DECLARE_KOBJ_TTYPE_MASTER(8);
+DECLARE_KOBJ_TTYPE_NBEAT(8);
+DECLARE_KOBJ_TTYPE_NBYTE(8);
+DECLARE_KOBJ_TTYPE_BURST(8);
+DECLARE_KOBJ_TTYPE_RW(8);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(8);
+
+DECLARE_KOBJ_TTYPE_MASTER(9);
+DECLARE_KOBJ_TTYPE_NBEAT(9);
+DECLARE_KOBJ_TTYPE_NBYTE(9);
+DECLARE_KOBJ_TTYPE_BURST(9);
+DECLARE_KOBJ_TTYPE_RW(9);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(9);
+
+DECLARE_KOBJ_TTYPE_MASTER(10);
+DECLARE_KOBJ_TTYPE_NBEAT(10);
+DECLARE_KOBJ_TTYPE_NBYTE(10);
+DECLARE_KOBJ_TTYPE_BURST(10);
+DECLARE_KOBJ_TTYPE_RW(10);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(10);
+
+DECLARE_KOBJ_TTYPE_MASTER(11);
+DECLARE_KOBJ_TTYPE_NBEAT(11);
+DECLARE_KOBJ_TTYPE_NBYTE(11);
+DECLARE_KOBJ_TTYPE_BURST(11);
+DECLARE_KOBJ_TTYPE_RW(11);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(11);
+
+DECLARE_KOBJ_TTYPE_MASTER(12);
+DECLARE_KOBJ_TTYPE_NBEAT(12);
+DECLARE_KOBJ_TTYPE_NBYTE(12);
+DECLARE_KOBJ_TTYPE_BURST(12);
+DECLARE_KOBJ_TTYPE_RW(12);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(12);
+
+DECLARE_KOBJ_TTYPE_MASTER(13);
+DECLARE_KOBJ_TTYPE_NBEAT(13);
+DECLARE_KOBJ_TTYPE_NBYTE(13);
+DECLARE_KOBJ_TTYPE_BURST(13);
+DECLARE_KOBJ_TTYPE_RW(13);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(13);
+
+DECLARE_KOBJ_TTYPE_MASTER(14);
+DECLARE_KOBJ_TTYPE_NBEAT(14);
+DECLARE_KOBJ_TTYPE_NBYTE(14);
+DECLARE_KOBJ_TTYPE_BURST(14);
+DECLARE_KOBJ_TTYPE_RW(14);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(14);
+
+DECLARE_KOBJ_TTYPE_MASTER(15);
+DECLARE_KOBJ_TTYPE_NBEAT(15);
+DECLARE_KOBJ_TTYPE_NBYTE(15);
+DECLARE_KOBJ_TTYPE_BURST(15);
+DECLARE_KOBJ_TTYPE_RW(15);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(15);
+
+DECLARE_KOBJ_TTYPE_MASTER(16);
+DECLARE_KOBJ_TTYPE_NBEAT(16);
+DECLARE_KOBJ_TTYPE_NBYTE(16);
+DECLARE_KOBJ_TTYPE_BURST(16);
+DECLARE_KOBJ_TTYPE_RW(16);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(16);
+
+DECLARE_KOBJ_TTYPE_MASTER(17);
+DECLARE_KOBJ_TTYPE_NBEAT(17);
+DECLARE_KOBJ_TTYPE_NBYTE(17);
+DECLARE_KOBJ_TTYPE_BURST(17);
+DECLARE_KOBJ_TTYPE_RW(17);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(17);
+
+DECLARE_KOBJ_TTYPE_MASTER(18);
+DECLARE_KOBJ_TTYPE_NBEAT(18);
+DECLARE_KOBJ_TTYPE_NBYTE(18);
+DECLARE_KOBJ_TTYPE_BURST(18);
+DECLARE_KOBJ_TTYPE_RW(18);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(18);
+
+DECLARE_KOBJ_TTYPE_MASTER(19);
+DECLARE_KOBJ_TTYPE_NBEAT(19);
+DECLARE_KOBJ_TTYPE_NBYTE(19);
+DECLARE_KOBJ_TTYPE_BURST(19);
+DECLARE_KOBJ_TTYPE_RW(19);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(19);
+
+DECLARE_KOBJ_TTYPE_MASTER(20);
+DECLARE_KOBJ_TTYPE_NBEAT(20);
+DECLARE_KOBJ_TTYPE_NBYTE(20);
+DECLARE_KOBJ_TTYPE_BURST(20);
+DECLARE_KOBJ_TTYPE_RW(20);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(20);
+
+DECLARE_KOBJ_TTYPE_MASTER(21);
+DECLARE_KOBJ_TTYPE_NBEAT(21);
+DECLARE_KOBJ_TTYPE_NBYTE(21);
+DECLARE_KOBJ_TTYPE_BURST(21);
+DECLARE_KOBJ_TTYPE_RW(21);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(21);
+
+/**/
+#define KOBJ_ATTR_ITEM_SERIAL_FNODE(nr) \
+	do { \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _master); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _nbeat); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _nbyte); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _burst); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _busid); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _rw); \
+	} while (0)
+
+#define KOBJ_ATTR_LIST \
+	do { \
+		KOBJ_ATTR_ITEM(high_priority_filter); \
+		KOBJ_ATTR_ITEM(metemi_func_opt); \
+		KOBJ_ATTR_ITEM(emi_tsct_enable); \
+		KOBJ_ATTR_ITEM(emi_mdct_enable); \
+		KOBJ_ATTR_ITEM(emi_TP_busfiltr_enable); \
+		KOBJ_ATTR_ITEM(emi_regdump); \
+		KOBJ_ATTR_ITEM(msel_enable); \
+		KOBJ_ATTR_ITEM(msel_group1); \
+		KOBJ_ATTR_ITEM(msel_group2); \
+		KOBJ_ATTR_ITEM(msel_group3); \
+		KOBJ_ATTR_ITEM(emi_clock_rate); \
+		KOBJ_ATTR_ITEM(rwtype); \
+		KOBJ_ATTR_ITEM(ttype17_21_en); \
+		KOBJ_ATTR_ITEM(ttype1_16_en); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(1); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(2); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(3); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(4); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(5); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(6); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(7); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(8); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(9); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(10); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(11); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(12); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(13); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(14); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(15); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(16); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(17); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(18); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(19); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(20); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(21); \
+		KOBJ_ATTR_ITEM(test_apmcu); \
+		KOBJ_ATTR_ITEM(bw_limiter_enable); \
+		KOBJ_ATTR_ITEM(dramc_pdir_enable); \
+		KOBJ_ATTR_ITEM(mdmcu_sel_enable); \
+		KOBJ_ATTR_ITEM(rd_mdmcu_rsv_num); \
+	} while (0)
+
+
+/*======================================================================*/
+/*	EMI Operations							*/
+/*======================================================================*/
+static void emi_init(void)
+{
+	unsigned int bmrw0_val, bmrw1_val, i, enable;
+	unsigned int msel_group_val[4];
+
+	/*save origianl EMI config*/
+	MET_BM_SaveCfg();
+
+	/* get dram channel number */
+	dram_chann_num = MET_EMI_GetDramChannNum();
+
+	/* Init. EMI bus monitor */
+	MET_BM_SetReadWriteType(rwtype);
+
+	if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+		if (msel_enable) {
+			msel_group_val[0] = BM_MASTER_ALL;
+			msel_group_val[1] = msel_group1;
+			msel_group_val[2] = msel_group2;
+			msel_group_val[3] = msel_group3;
+		} else {
+			msel_group_val[0] = BM_MASTER_ALL;
+			msel_group_val[1] = BM_MASTER_ALL;
+			msel_group_val[2] = BM_MASTER_ALL;
+			msel_group_val[3] = BM_MASTER_ALL;
+		}
+
+		MET_BM_SetLatencyCounter(1);    /*enable latency count*/
+
+		for (i = 1; i <= 4; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 msel_group_val[i - 1] & BM_MASTER_ALL,
+						 BM_TRANS_TYPE_4BEAT |
+						 BM_TRANS_TYPE_8Byte |
+						 BM_TRANS_TYPE_BURST_WRAP);
+			MET_BM_SetbusID(i, 0);
+			MET_BM_SetbusID_En(i, 0);       /*disable ttype bus sel*/
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 0);       /*disable tp filter*/
+
+	} else if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable == 1)) {
+		MET_BM_SetLatencyCounter(1);    /*enable latency count*/
+
+		for (i = 1; i <= 4; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			MET_BM_SetbusID_En(i, 0);       /*disable ttype bus sel*/
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 1);       /*enable tp filter*/
+
+	} else if ((ttype1_16_en == BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+		MET_BM_SetLatencyCounter(0);    /*disable latency count*/
+
+		for (i = 1; i <= 16; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			/*disenable ttype bus sel if busid > 0xff_ff*/
+			MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 0);       /*disable tp filter*/
+	} else {	/* (ttype1_16_en == BM_TTYPE1_16_ENABLE)  &&  (emi_TP_busfiltr_enable == 1) */
+		MET_BM_SetLatencyCounter(0);    /*disable latency count*/
+
+		for (i = 1; i <= 16; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			/*disable ttype bus sel if busid > 0xff_ff*/
+			MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 1);       /*enable tp filter*/
+	}
+
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+		for (i = 17; i <= 21; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			/*disable ttype bus sel if busid > 0xff_ff*/
+			MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+		}
+	}
+
+	bmrw0_val = 0;
+	for (i = 0; i < 16; i++)
+		bmrw0_val |= (ttype_rw_val[i] << (i * 2));
+
+	bmrw1_val = 0;
+	for (i = 16; i < 21; i++)
+		bmrw1_val |= (ttype_rw_val[i] << ((i-16) * 2));
+
+	MET_BM_SetTtypeCounterRW(bmrw0_val, bmrw1_val);
+
+	for (i = 0; i < BM_COUNTER_MAX; i++) {
+		if ((high_priority_filter & (1 << i)) == 0)
+			enable = 0;
+		else
+			enable = 1;
+
+		MET_BM_SetUltraHighFilter(i + 1, enable);
+	}
+
+	met_record_dramc_dcm_enable_flag();
+
+	if (met_emi_regdump == 1)
+		emi_dump_reg();
+}
+
+
+static void emi_uninit(void)
+{
+	MET_BM_RestoreCfg();
+}
+
+static inline void emi_start(void)
+{
+	MET_BM_Enable(1);
+}
+
+
+static inline void emi_stop(void)
+{
+	MET_BM_Enable(0);
+}
+
+
+static inline int do_emi(void)
+{
+	return met_emi.mode;
+}
+
+
+noinline void DRAM_DVFS(unsigned int dram_data_rate_MHz)
+{
+	MET_TRACE("%u\n", dram_data_rate_MHz);
+}
+
+
+static unsigned int emi_bw_limiter(unsigned int *__restrict__ array)
+{
+	int idx = 0;
+	unsigned int dram_data_rate_MHz;
+
+	if (get_dram_data_rate_symbol) {
+		dram_data_rate_MHz = get_dram_data_rate_symbol();
+	} else {
+		METERROR("get_dram_data_rate_symbol = NULL\n");
+		dram_data_rate_MHz = 0;
+	}
+
+	/* print dram data rate */
+	DRAM_DVFS(dram_data_rate_MHz);
+
+	/* get correct dram_clock_rate */
+	array[idx++] = dram_data_rate_MHz;
+
+	/* get correct ARB A->LAST */
+	array[idx++] = MET_EMI_GetARBA();
+	array[idx++] = MET_EMI_GetARBB();
+	array[idx++] = MET_EMI_GetARBC();
+	array[idx++] = MET_EMI_GetARBD();
+	array[idx++] = MET_EMI_GetARBE();
+	array[idx++] = MET_EMI_GetARBF();
+	array[idx++] = MET_EMI_GetARBG();
+	array[idx++] = MET_EMI_GetARBH();
+	/* EMI Total BW Thresholds */
+	array[idx++] = MET_EMI_GetBWCT0();
+	array[idx++] = MET_EMI_GetBWCT1();
+	array[idx++] = MET_EMI_GetBWCT2();
+	array[idx++] = MET_EMI_GetBWCT3();
+	array[idx++] = MET_EMI_GetBWCT4();
+	array[idx++] = MET_EMI_GetBWST0();
+	array[idx++] = MET_EMI_GetBWST1();
+	/* EMI C+G BW Thresholds */
+	array[idx++] = MET_EMI_GetBWCT0_2ND();
+	array[idx++] = MET_EMI_GetBWCT1_2ND();
+	array[idx++] = MET_EMI_GetBWST_2ND();
+
+	return idx;
+}
+
+
+static void _ms_dramc(unsigned int *__restrict__ dramc_pdir_value, int dram_chann_num)
+{
+	MET_DRAMC_GetDebugCounter(dramc_pdir_value, dram_chann_num);
+}
+
+
+static unsigned int emi_polling(unsigned int *__restrict__ emi_value, unsigned int *__restrict__ emi_tsct,
+				unsigned int *__restrict__ emi_ttype_value, unsigned int *__restrict__ dramc_pdir_value,
+				unsigned int *__restrict__ emi_mdct_value)
+{
+	int j = 4;              /* skip 4 WSCTs */
+	int i = 0;              /* ttype start at 0 */
+	int k = 0;              /* tsct start at 0 */
+	int n;
+
+	MET_BM_Pause();
+
+	/* Get Word Count */
+
+	emi_value[0] = MET_BM_GetWordCount(1);  /* All */
+	emi_value[1] = MET_BM_GetWordCount(2);  /* Group 1 */
+	emi_value[2] = MET_BM_GetWordCount(3);  /* Group 2 */
+	emi_value[3] = MET_BM_GetWordCount(4);  /* Group 3 */
+
+	if (ttype1_16_en != BM_TTYPE1_16_ENABLE) {      /*1~21 NOT for ttype*/
+		/* Get Latency */
+		j += MET_BM_GetLatencyCycle(emi_value + j, 1, 8);
+
+		/* Get Trans. */
+		j += MET_BM_GetLatencyCycle(emi_value + j, 9, 16);
+	} else {
+		for (n = 4; n < 20; n++)
+			emi_value[n] = 0;
+		j = 20;
+
+		i += MET_BM_GetLatencyCycle(emi_ttype_value + i, 1, 8);
+
+		/* Get Trans. */
+		i += MET_BM_GetLatencyCycle(emi_ttype_value + i, 9, 16);
+	}
+
+	/* Get BACT/BSCT/BCNT/WACT/DCM_CTRL */
+	emi_value[j++] = MET_BM_GetBandwidthWordCount(); /* 20 */
+	emi_value[j++] = MET_BM_GetOverheadWordCount();
+	emi_value[j++] = MET_BM_GetBusCycCount();
+	emi_value[j++] = MET_BM_GetWordAllCount();
+	emi_value[j++] = MET_DRAMC_DCM_CTRL(0);
+
+	/* Get TACT */
+	emi_value[j++] = MET_BM_GetTransAllCount();
+
+	/* Get PageHist/PageMiss/InterBank/Idle */
+	for (n = 0; n < dram_chann_num; n++) {
+		emi_value[j++] = MET_DRAMC_GetPageHitCount(DRAMC_ALL, n);
+		emi_value[j++] = MET_DRAMC_GetPageMissCount(DRAMC_ALL, n);
+		emi_value[j++] = MET_DRAMC_GetInterbankCount(DRAMC_ALL, n);
+		emi_value[j++] = MET_DRAMC_GetIdleCount(n);
+		emi_value[j++] = ((MET_DRAMC_SPCMDRESP(n) >> 8) & 0x7); /* refresh rate */
+		emi_value[j++] = MET_DRAMC_RefPop(n);
+		emi_value[j++] = MET_DRAMC_Free26M(n);
+		emi_value[j++] = MET_DRAMC_RByte(n);
+		emi_value[j++] = MET_DRAMC_WByte(n);
+	}
+	/* TTYPE */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE)    /*17~21 for ttype*/
+		MET_BM_GetLatencyCycle(emi_ttype_value + 16, 17, 21);
+
+	/* Get tsct */
+	if (emi_tsct_enable == 1) {
+		emi_tsct[k++] = MET_BM_GetTransCount(1);
+		emi_tsct[k++] = MET_BM_GetTransCount(2);
+		emi_tsct[k++] = MET_BM_GetTransCount(3);
+	}
+	/*get mdct rsv buffer*/
+	if (emi_mdct_enable == 1) {
+		emi_mdct_value[0] = (MET_BM_GetMDCT() >> 16) & 0x7;
+		emi_mdct_value[1] = (MET_BM_GetMDCT_2() & 0x7);
+	}
+
+	if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 )
+		_ms_dramc(dramc_pdir_value, dram_chann_num);
+
+	MET_BM_Continue();
+	MET_BM_Clear_Start();
+
+	return j;
+}
+
+
+/*======================================================================*/
+/*	MET Device Operations						*/
+/*======================================================================*/
+static int emi_inited;
+
+static int met_emi_create(struct kobject *parent)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < 21; i++) {
+		ttype_master_val[i] = BM_MASTER_M0;
+		ttype_nbeat_val[i] = BM_TRANS_TYPE_1BEAT;
+		ttype_nbyte_val[i] = BM_TRANS_TYPE_8Byte;
+		ttype_burst_val[i] = BM_TRANS_TYPE_BURST_INCR;
+		ttype_busid_val[i] = 0xfffff;   /*default disable ttype bus sel if busid > 0xff_ff */
+		ttype_rw_val[i] =  BM_TRANS_RW_DEFAULT;
+	}
+
+	ret = MET_BM_Init();
+	if (ret != 0) {
+		pr_notice("MET_BM_Init failed!!!\n");
+		ret = 0;        /* will retry later */
+	} else {
+		emi_inited = 1;
+	}
+
+	kobj_emi = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+	do { \
+		ret = sysfs_create_file(kobj_emi, &attr_name ## _attr.attr); \
+		if (ret != 0) { \
+			pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+			return ret; \
+		} \
+	} while (0)
+	KOBJ_ATTR_LIST;
+#undef  KOBJ_ATTR_ITEM
+
+	return ret;
+}
+
+
+static void met_emi_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+	sysfs_remove_file(kobj_emi, &attr_name ## _attr.attr)
+	if (kobj_emi != NULL) {
+		KOBJ_ATTR_LIST;
+		kobj_emi = NULL;
+	}
+#undef  KOBJ_ATTR_ITEM
+
+	if (emi_inited)
+		MET_BM_DeInit();
+}
+
+
+static void met_emi_start(void)
+{
+	unsigned int bw_limiter[NIDX_BL];
+
+	if (!emi_inited) {
+		if (MET_BM_Init() != 0) {
+			met_emi.mode = 0;
+			pr_notice("MET_BM_Init failed!!!\n");
+			return;
+		}
+		emi_inited = 1;
+	}
+
+	if (do_emi()) {
+		emi_init();
+		MET_BM_Clear_Start();
+
+		/* Draw the first BW Limiter point */
+		if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+			emi_bw_limiter(bw_limiter);
+			ms_bw_limiter(NIDX_BL, bw_limiter);
+			/* init countdown value */
+			countdown = CNT_COUNTDOWN;
+		}
+	}
+}
+
+
+static void met_emi_stop(void)
+{
+	unsigned int bw_limiter[NIDX_BL];
+
+	if (!emi_inited)
+		return;
+
+	if (met_emi_regdump == 1)
+		emi_dump_reg();
+
+	if (do_emi()) {
+		/* Draw the last BW Limiter point */
+		if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+			/*
+			 * Skip drawing when we just draw
+			 * the point at last polling.
+			 */
+			if (countdown < CNT_COUNTDOWN) {
+				emi_bw_limiter(bw_limiter);
+				ms_bw_limiter(NIDX_BL, bw_limiter);
+			}
+		}
+
+		emi_stop();
+		emi_uninit();
+	}
+}
+
+
+static void met_emi_polling(unsigned long long stamp, int cpu)
+{
+	unsigned int emi_value[NIDX];
+	unsigned int emi_tsct[3];
+	unsigned int emi_ttype_value[21];
+	unsigned int dramc_pdir_value[DRAMC_Debug_MAX_CNT * NCH];
+	unsigned int emi_mdct_value[2];
+	unsigned int chn_emi_drs[6];
+
+	if (!do_emi())
+		return;
+
+	/* get emi & dramc counters */
+	emi_value[0] = 0;       /* 0: pure linux MET , 0xa5: OnDieMET*/
+	emi_value[1] = 0;       /* EBM pause duration (ns)*/
+	emi_polling(emi_value + 2, emi_tsct, emi_ttype_value, dramc_pdir_value, emi_mdct_value);
+
+	/* get and output BW Limiter */
+	if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+		unsigned int bw_limiter[NIDX_BL];
+
+		if (countdown > 0) {
+			countdown--;
+		} else {
+			emi_bw_limiter(bw_limiter);
+			ms_bw_limiter(NIDX_BL, bw_limiter);
+			/* reload countdown value */
+			countdown = CNT_COUNTDOWN;
+		}
+	}
+
+	/* output emi */
+	ms_emi(NIDX_EMI - NTTYPE + (NCNT * dram_chann_num), emi_value);
+
+	/* output tsct*/
+	if (emi_tsct_enable == 1)
+		ms_emi_tsct(3, emi_tsct);
+
+	/* output mdct*/
+	if (emi_mdct_enable == 1)
+		ms_emi_mdct(2, emi_mdct_value);
+
+	/* output dramc*/
+	if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 )
+		ms_dramc(DRAMC_Debug_MAX_CNT * dram_chann_num, dramc_pdir_value);
+
+	/* output ms_ttype */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE)
+		ms_ttype(21, emi_ttype_value);
+
+	/* adjust MDMCU buffer */
+	if (mdmcu_sel_enable == 1)
+		MET_BM_SetMDCT_MDMCU(rd_mdmcu_rsv_num);
+}
+
+
+static void met_emi_resume(void)
+{
+	/* return directly when emi was closed */
+	if (!do_emi())
+		return;
+
+	/* remap EMI_BM related reg*/
+	emi_init();
+
+	/* restarn counting */
+	MET_BM_Clear_Start();
+}
+
+
+static const char help[] = "  --emi                                 monitor EMI banwidth\n";
+static int emi_print_help(char *buf, int len)
+{
+	return snprintf(buf, PAGE_SIZE, help);
+}
+
+
+#define TTYPE_NAME_STR_LEN  64
+/* static char ttype_name[21][TTYPE_NAME_STR_LEN]; */
+static int emi_print_header(char *buf, int len)
+{
+	int ret = 0;
+/*	int ret_m[21]; */
+	int i = 0;
+	unsigned int dram_data_rate_MHz;
+	unsigned int DRAM_TYPE;
+
+#if 0
+	/*ttype header info*/
+	for (i = 0; i < 21; i++) {
+		int k;
+
+		/*busid > 0xffff    not specific bus id , show all on specificmaster*/
+		if (ttype_busid_val[i] > 0xffff) {
+			int j;
+
+			for (j = 0; j < ARRAY_SIZE(ttype_master_list_item); j++) {
+				if (ttype_master_val[i] == ttype_master_list_item[j].key) {
+					ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttype%d_%s",
+							    i + 1, ttype_master_list_item[j].val);/*master*/
+					break;
+				}
+			}
+			if (j == ARRAY_SIZE(ttype_master_list_item))
+				ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttype%d_%s",
+						    i + 1, "unknown");
+		} else {
+			ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttype%d_%x",
+					    i + 1, ttype_busid_val[i]);/*busID*/
+		}
+
+		/*show beat type*/
+		for (k = 0; k < ARRAY_SIZE(ttype_nbeat_list_item); k++) {
+
+			if (ttype_nbeat_val[i] == ttype_nbeat_list_item[k].key)
+				ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "_%d",
+						     ttype_nbeat_list_item[k].val); /*beat*/
+		}
+
+		/*show byte type*/
+		for (k = 0; k < ARRAY_SIZE(ttype_nbyte_list_item); k++) {
+
+			if (ttype_nbyte_val[i] == ttype_nbyte_list_item[k].key)
+				ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "x%d",
+						     ttype_nbyte_list_item[k].val); /*byte*/
+		}
+
+		/*show burst type*/
+		for (k = 0; k < ARRAY_SIZE(ttype_burst_list_item); k++) {
+
+			if (ttype_burst_val[i] == ttype_burst_list_item[k].key)
+				ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "_%s",
+						     ttype_burst_list_item[k].val); /*burst*/
+		}
+
+		/*show rw type*/
+		for (k = 0; k < ARRAY_SIZE(ttype_rw_list_item); k++) {
+
+			if (ttype_rw_val[i] == ttype_rw_list_item[k].key)
+				ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "_%s",
+						     ttype_rw_list_item[k].val); /*rw*/
+		}
+	}
+#endif
+
+	if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+		/* master selection header */
+		if (msel_enable) {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+					msel_group1 & BM_MASTER_ALL,
+					msel_group2 & BM_MASTER_ALL,
+					msel_group3 & BM_MASTER_ALL);
+		} else {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+					BM_MASTER_ALL & BM_MASTER_ALL,
+					BM_MASTER_ALL & BM_MASTER_ALL,
+					BM_MASTER_ALL & BM_MASTER_ALL);
+		}
+	} else {
+		/*ttype master if BM_TTYPE1_16_ENABLE or emi_TP_busfiltr_enable*/
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: met_emi_ttype_master: %x,%x,%x,%x\n",
+				ttype_master_val[0], ttype_master_val[1], ttype_master_val[2], ttype_master_val[3]);
+
+		if (emi_TP_busfiltr_enable == 1) {
+			/* busID if emi_TP_busfiltr_enable*/
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"met-info [000] 0.0: met_emi_ttype_busid: %x,%x,%x,%x\n",
+					ttype_busid_val[0], ttype_busid_val[1], ttype_busid_val[2], ttype_busid_val[3]);
+		}
+	}
+
+	/*RW type header*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_rw_cfg: ");
+	if (rwtype == BM_READ_ONLY)
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "R");
+	else if (rwtype == BM_WRITE_ONLY)
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "W");
+	else
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "BOTH");
+
+	for (i = 0; i < 21; i++) {
+		if (ttype_rw_val[i] == BM_TRANS_RW_DEFAULT)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",DEFAULT");
+		else if (ttype_rw_val[i] == BM_TRANS_RW_READONLY)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",R");
+		else if (ttype_rw_val[i] == BM_TRANS_RW_WRITEONLY)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",W");
+		else    /*BM_TRANS_RW_RWBOTH*/
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",BOTH");
+	}
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+	/*ultra header*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_emi_ultra_filter: %x\n", high_priority_filter);
+
+#if 0
+	/*ttype header (user define format)*/
+	if ((ttype1_16_en == BM_TTYPE1_16_ENABLE) && (ttype17_21_en == BM_TTYPE17_21_ENABLE)) {
+		/*header = ttype1~21t*/
+		int i;
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ms_ud_sys_header: ms_ttype,");
+		for (i = 0; i < 21; i++)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_name[i]);
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x\n");
+
+	} else if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+		/*header = ttype17~21t*/
+		int i;
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ms_ud_sys_header: ms_ttype,");
+
+		for (i = 16; i < 21; i++)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_name[i]);
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "x,x,x,x,x\n");
+	}
+#else
+#if 1
+	/* ttype header */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+		int i = 0;
+		int j = 0;
+
+		/* ttype master list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_master_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_master_list_item); j++) {
+				if (ttype_master_val[i] == ttype_master_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_master_list_item[j].val);
+				}
+			}
+		}
+		/* remove the last comma */
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype busid list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_busid_list: ");
+		for (i = 0; i < 21; i++)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,", ttype_busid_val[i]);
+
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype nbeat list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_nbeat_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_nbeat_list_item); j++) {
+				if (ttype_nbeat_val[i] == ttype_nbeat_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,", ttype_nbeat_list_item[j].val);
+				}
+			}
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype nbyte list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_nbyte_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_nbyte_list_item); j++) {
+				if (ttype_nbyte_val[i] == ttype_nbyte_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,", ttype_nbyte_list_item[j].val);
+				}
+			}
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype burst list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_burst_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_burst_list_item); j++) {
+				if (ttype_burst_val[i] == ttype_burst_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_burst_list_item[j].val);
+				}
+			}
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype enable */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_enable: %d,%d\n",ttype1_16_en, ttype17_21_en);
+
+
+	}
+#endif
+#endif
+	/*IP version*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: DRAMC_VER: %d\n", DRAMC_VER);
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: EMI_VER: %d.%d\n", EMI_VER_MAJOR, EMI_VER_MINOR);
+
+#ifndef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
+	dram_chann_num = MET_EMI_GetDramChannNum();
+	/*	met_dram_chann_num_header
+	 *	channel number
+	 *	LP4: 2, LP3: 1
+	 */
+
+	/*
+	 *	the ddr type define :
+	 *	enum DDRTYPE {
+	 *	TYPE_LPDDR3 = 1,
+	 *	TYPE_LPDDR4,
+	 *	TYPE_LPDDR4X,
+	 *	TYPE_LPDDR2
+	 *	};
+	 */
+	if (get_ddr_type_symbol) {
+		DRAM_TYPE = get_ddr_type_symbol();
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_type: %d\n", DRAM_TYPE);
+
+		if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+					dram_chann_num, DRAM_EMI_BASECLOCK_RATE_LP4,
+					DRAM_IO_BUS_WIDTH_LP4, DRAM_DATARATE);
+		else
+			ret += snprintf(buf + ret , PAGE_SIZE -ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+					dram_chann_num, DRAM_EMI_BASECLOCK_RATE_LP3,
+					DRAM_IO_BUS_WIDTH_LP3, DRAM_DATARATE);
+	} else
+		METERROR("[%s][%d]get_ddr_type_symbol = NULL , use the TYPE_LPDDR3 setting\n", __func__, __LINE__);
+
+	/* metemi_func_opt for middleware */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: metemi_func_opt_header: %d\n",
+			metemi_func_opt);
+
+	/* met_emi_clockrate */
+	if (get_dram_data_rate_symbol) {
+		dram_data_rate_MHz = get_dram_data_rate_symbol();
+	} else {
+		METERROR("get_dram_data_rate_symbol = NULL\n");
+		dram_data_rate_MHz = 0;
+	}
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_dram_clockrate: %d\n",
+			dram_data_rate_MHz);
+
+	/* 1 : by ondiemet, 0: by pure linux */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: emi_use_ondiemet: %u\n",
+			emi_use_ondiemet);
+
+	/*dram bank num*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_dram_rank_num_header: %u,%u\n", MET_EMI_GetDramRankNum(),
+				MET_EMI_GetDramRankNum());
+
+	/* ms_emi header */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"# ms_emi: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+	for (i = 0; i < dram_chann_num; i++) {
+		if (i != 0)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					",");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"read_bytes_%d,write_bytes_%d", i, i);
+	}
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_emi_header: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+	for (i = 0; i < dram_chann_num; i++) {
+		if (i != 0)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					",");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"read_bytes_%d,write_bytes_%d", i, i);
+	}
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+	/*TSCT header*/
+	if (emi_tsct_enable == 1) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: ms_emi_tsct_header: ms_emi_tsct,");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"tsct1,tsct2,tsct3\n");
+	}
+
+	/*MDCT header*/
+	if (emi_mdct_enable == 1) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: ms_emi_mdct_header: ms_emi_mdct,");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"RD_ULTRA,RD_MDMCU\n");
+	}
+
+	/* met_bw_limiter_header */
+	if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: met_bw_limiter_header: CLK,");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"ARBA,ARBB,ARBC,ARBD,ARBE,ARBF,ARBG,ARBH,BWCT0,BWCT1,BWCT2,BWCT3,BWCT4,BWST0,BWST1,BWCT0_2ND,BWCT1_2ND,BWST_2ND\n");
+	}
+
+	/* DRAM DVFS header */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: DRAM_DVFS_header: datarate(MHz)\n");
+
+	/*PDIR met_dramc_header*/
+	if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 ) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: met_dramc_header: ");
+		for (i = 0; i < dram_chann_num; i++) {
+			if (i != 0)
+				ret += snprintf(buf + ret, PAGE_SIZE - ret,
+						",");
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "freerun_26m_%d,", i);
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"rk0_pre_sb_%d,rk0_pre_pd_%d,rk0_act_sb_%d,rk0_act_pd_%d,", i, i, i, i);
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"rk1_pre_sb_%d,rk1_pre_pd_%d,rk1_act_sb_%d,rk1_act_pd_%d,", i, i, i, i);
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"rk2_pre_sb_%d,rk2_pre_pd_%d,rk2_act_sb_%d,rk2_act_pd_%d", i, i, i, i);
+		}
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+	}
+#endif
+
+	return ret;
+}
+
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+static int ondiemet_emi_print_header(char *buf, int len)
+{
+	emi_use_ondiemet = 1;
+	/* return emi_print_ondiemet_header(buf, len); */
+	return emi_print_header(buf, len);
+}
+
+
+static void MET_BM_IPI_REGISTER_CB(void)
+{
+	int ret, i;
+	unsigned int rdata;
+	unsigned int ipi_buf[4];
+
+	for (i = 0; i < 4; i++)
+		ipi_buf[i] = 0;
+
+	if (sspm_buf_available == 1) {
+		ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_REGISTER_CB;
+		ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+	}
+}
+
+
+static void MET_BM_IPI_configs(void)
+{
+	int ret, i;
+	unsigned int rdata;
+	unsigned int ipi_buf[4];
+
+	for (i = 0; i < 4; i++)
+		ipi_buf[i] = 0;
+
+	if (sspm_buf_available == 1) {
+		ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_EBM_CONFIGS1;
+		ipi_buf[1] = INTERNAL_MODE << 16;
+		ipi_buf[2] = EMI_VER_MAJOR << 24 | EMI_VER_MINOR << 16 | DRAMC_VER << 8 | 0;
+		ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+	}
+}
+
+
+static void ondiemet_emi_start(void)
+{
+	MET_BM_IPI_REGISTER_CB();
+	if (!emi_inited) {
+		if (MET_BM_Init() != 0) {
+			met_emi.mode = 0;
+			pr_notice("MET_BM_Init failed!!!\n");
+			return;
+		}
+		emi_inited = 1;
+	}
+	MET_BM_IPI_configs();
+
+	if (do_emi())
+		emi_init();
+
+	ondiemet_module[ONDIEMET_SSPM] |= ID_EMI;
+}
+
+
+static void ondiemet_emi_stop(void)
+{
+	if (!emi_inited)
+		return;
+
+	if (do_emi())
+		emi_uninit();
+}
+#endif
+
+
+struct metdevice met_emi = {
+	.name			= "emi",
+	.owner			= THIS_MODULE,
+	.type			= MET_TYPE_BUS,
+	.create_subfs		= met_emi_create,
+	.delete_subfs		= met_emi_delete,
+	.cpu_related		= 0,
+	.start			= met_emi_start,
+	.stop			= met_emi_stop,
+	.resume			= met_emi_resume,
+	.timed_polling		= met_emi_polling,
+	.print_help		= emi_print_help,
+	.print_header		= emi_print_header,
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+	.ondiemet_mode		= 1,
+	.ondiemet_start		= ondiemet_emi_start,
+	.ondiemet_stop		= ondiemet_emi_stop,
+	.ondiemet_print_help	= emi_print_help,
+	.ondiemet_print_header	= ondiemet_emi_print_header,
+#else
+	.ondiemet_mode		= 0,
+#endif
+};
diff --git a/src/devtools/met-driver/4.14/mt2731/emi/SEDA2/mtk_emi_bm.c b/src/devtools/met-driver/4.14/mt2731/emi/SEDA2/mtk_emi_bm.c
new file mode 100644
index 0000000..3ef0c99
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/emi/SEDA2/mtk_emi_bm.c
@@ -0,0 +1,1038 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <mt-plat/sync_write.h>
+#include <mt-plat/mtk_io.h>
+#include "mtk_typedefs.h"
+#include "plf_init.h"
+#include "mtk_emi_bm.h"
+#include "mtk_dramc_reg.h"
+#include "met_drv.h"
+#include "interface.h"
+
+#undef	DEBUG
+#undef	debug_reg
+#ifdef	debug_reg
+static inline unsigned int emi_readl(void __iomem *padr)
+{
+	unsigned int tmp;
+
+	tmp = readl(padr);
+	MET_TRACE("[MET_EMI] RD_Reg: %p: %08x\n", padr, tmp);
+	return tmp;
+}
+
+
+static inline void __emi_reg_sync_writel(unsigned int data, void __iomem *padr)
+{
+	unsigned int tmp;
+
+	mt_reg_sync_writel(data, padr);
+	tmp = readl(padr);
+	MET_TRACE("[MET_EMI] WR_Reg: %p: %08x, %08x\n", padr, data, tmp);
+}
+
+
+#define emi_reg_sync_writel(data, adr)  __emi_reg_sync_writel(data, IOMEM(adr))
+
+#else
+#define emi_readl               readl
+#define emi_reg_sync_writel     mt_reg_sync_writel
+#endif
+
+#define MASK_MASTER     0xFF
+#define MASK_TRANS_TYPE 0xFF
+
+static int dram_chann_num;
+static void __iomem *BaseAddrEMI;
+static void __iomem *BaseAddrCHN_EMI[2];
+
+static int dramc0_dcm_enable;
+static int dramc1_dcm_enable;
+
+#define CH0_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[0]) + 0x284)
+#define CH1_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[1]) + 0x284)
+const unsigned int emi_config[] = {
+	EMI_BMEN,
+	EMI_MSEL,
+	EMI_MSEL2,
+	EMI_MSEL3,
+	EMI_MSEL4,
+	EMI_MSEL5,
+	EMI_MSEL6,
+	EMI_MSEL7,
+	EMI_MSEL8,
+	EMI_MSEL9,
+	EMI_MSEL10,
+	EMI_BMID0,
+	EMI_BMID1,
+	EMI_BMID2,
+	EMI_BMID3,
+	EMI_BMID4,
+	EMI_BMID5,
+	EMI_BMID6,
+	EMI_BMID7,
+	EMI_BMID8,
+	EMI_BMID9,
+	EMI_BMID10,
+	EMI_BMEN1,
+	EMI_BMEN2,
+	EMI_BMRW0,
+	EMI_BMRW1
+};
+#define EMI_CONFIG_MX_NR (sizeof(emi_config)/sizeof(unsigned int))
+static unsigned int emi_config_val[EMI_CONFIG_MX_NR];
+
+
+/*
+ *   MET_REG_BSET/MET_REG_BCLR:
+ *   reading value before set and clear
+ */
+static inline void MET_REG_BSET(unsigned long reg, u32 shift)
+{
+	unsigned int read_val = 0;
+
+	read_val = emi_readl(IOMEM(reg));
+	emi_reg_sync_writel(read_val | (1 << shift), reg);
+}
+
+
+static inline void MET_REG_BCLR(unsigned long reg, u32 shift)
+{
+	unsigned int read_val = 0;
+
+	read_val = emi_readl(IOMEM(reg));
+	emi_reg_sync_writel(read_val & (~((1 << shift) & 0xFFFFFFFF)), reg);
+}
+
+
+int MET_BM_Init(void)
+{
+	int i;
+	int idx;
+
+	/*emi*/
+	if (!mt_cen_emi_base_get_symbol) {
+		METERROR("[%d]mt_cen_emi_base_get_symbol = NULL\n", __LINE__);
+		PR_BOOTMSG_ONCE("[%d]mt_cen_emi_base_get_symbol = NULL\n", __LINE__);
+		return -1;
+	}
+
+	BaseAddrEMI = mt_cen_emi_base_get_symbol();
+	if (BaseAddrEMI == 0) {
+		METERROR("BaseAddrEMI = 0\n");
+		PR_BOOTMSG_ONCE("BaseAddrEMI = 0\n");
+		return -1;
+	}
+
+	METINFO("MET EMI: map emi to %p\n", BaseAddrEMI);
+	PR_BOOTMSG("MET EMI: map emi to %p\n", BaseAddrEMI);
+
+	/* get dram channel number */
+	dram_chann_num = MET_EMI_GetDramChannNum();
+	METINFO("[%s][%d]dram_chann_num = %d\n", __func__, __LINE__, dram_chann_num);
+
+	if (dram_chann_num > MAX_DRAMC_CHANN) {
+		METERROR("dram_chann_num %d > %d\n", dram_chann_num, MAX_DRAMC_CHANN);
+		PR_BOOTMSG("dram_chann_num %d > %d\n", dram_chann_num, MAX_DRAMC_CHANN);
+		return -1;
+	}
+
+	if (!mt_dramc_nao_chn_base_get_symbol) {
+		METERROR("mt_dramc_nao_cha_base_get = NULL\n");
+		PR_BOOTMSG_ONCE("mt_dramc_nao_cha_base_get = NULL\n");
+		return -1;
+	}
+
+	for (i = 0; i < dram_chann_num; i++) {
+		BaseAddrDRAMC[i] = mt_dramc_nao_chn_base_get_symbol(i);
+		if (BaseAddrDRAMC[i] == 0) {
+			METERROR("BaseAddrDRAMC%d = 0\n", i);
+			PR_BOOTMSG_ONCE("BaseAddrDRAMC%d = 0\n", i);
+			return -1;
+		}
+
+		METINFO("MET EMI: map nao dramc%c to %p\n",'A'+i, BaseAddrDRAMC[i]);
+		PR_BOOTMSG("MET EMI: map nao dramc%c to %p\n", 'A'+i, BaseAddrDRAMC[i]);
+	}
+
+	/*dram DRAMC_DTS_DDRPHY_AO*/
+	/* get DRS base address */
+	if (!mt_ddrphy_chn_base_get_symbol) {
+		METERROR("mt_ddrphy_chn_base_get = NULL\n");
+		PR_BOOTMSG_ONCE("mt_ddrphy_chn_base_get = NULL\n");
+		return -1;
+	}
+
+	if (!mt_chn_emi_base_get_symbol) {
+		METERROR("mt_chn_emi_base_get_symbol = NULL\n");
+		PR_BOOTMSG_ONCE("mt_chn_emi_base_get_symbol = NULL\n");
+		return -1;
+	}
+
+	for (i = 1; i <= dram_chann_num && i < 3; i++) {
+		idx = i - 1;
+		BaseAddrDDRPHY_AO[idx] = mt_ddrphy_chn_base_get_symbol(idx);
+		if (BaseAddrDDRPHY_AO[idx] == 0) {
+			METERROR("BaseAddrDDRPHY_AO[%d] = 0\n", idx);
+			PR_BOOTMSG_ONCE("BaseAddrDDRPHY_AO[%d] = 0\n", idx);
+			return -1;
+		}
+
+		METINFO("MET EMI: map ddrphy%d AO to %p\n", idx, BaseAddrDDRPHY_AO[idx]);
+		PR_BOOTMSG("MET EMI: map ddrphy%d AO to %p\n", idx, BaseAddrDDRPHY_AO[idx]);
+
+		BaseAddrCHN_EMI[idx] = mt_chn_emi_base_get_symbol(idx);
+		if (BaseAddrCHN_EMI[idx] == 0) {
+			METERROR("BaseAddrCHN_EMI[%d] = 0\n", idx);
+			PR_BOOTMSG_ONCE("BaseAddrCHN_EMI[%d] = 0\n", idx);
+			return -1;
+		}
+
+		METINFO("MET EMI: map BaseAddrCHN_EMI[%d] to %p\n", idx, BaseAddrCHN_EMI[idx]);
+		PR_BOOTMSG("MET EMI: map BaseAddrCHN_EMI[%d] to %p\n", idx, BaseAddrCHN_EMI[idx]);
+	}
+
+	/*dram DRAMC_DTS_DRAMC0_AO*/
+	if (!mt_dramc_chn_base_get_symbol) {
+		METERROR("mt_dramc_chn_base_get = NULL\n");
+		PR_BOOTMSG_ONCE("mt_dramc_chn_base_get = NULL\n");
+		return -1;
+	}
+
+	BaseAddrDRAMC0_AO = mt_dramc_chn_base_get_symbol(0);
+	if (BaseAddrDRAMC0_AO == 0) {
+		METERROR("BaseAddrDRAMC0_AO = 0\n");
+		PR_BOOTMSG_ONCE("BaseAddrDRAMC0_AO = 0\n");
+		return -1;
+	}
+
+	METINFO("MET EMI: map AO dramcA to %p\n", BaseAddrDRAMC0_AO);
+	PR_BOOTMSG("MET EMI: map AO dramcA to %p\n", BaseAddrDRAMC0_AO);
+
+	return 0;
+}
+
+
+void MET_BM_DeInit(void)
+{
+}
+
+
+void MET_BM_SaveCfg(void)
+{
+	int i;
+
+	for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+		emi_config_val[i] = emi_readl(IOMEM(ADDR_EMI + emi_config[i]));
+}
+
+
+void MET_BM_RestoreCfg(void)
+{
+	int i;
+
+	for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+		emi_reg_sync_writel(emi_config_val[i], ADDR_EMI + emi_config[i]);
+}
+
+
+void MET_BM_Clear_Start(void)
+{
+	/* Force EMI idle low */
+	MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+	/* Disable dramc dcm */
+	switch (dram_chann_num) {
+	case 1:
+		MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	case 2:
+		MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	default:
+		METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+	}
+
+	/* Disable EBM */
+	MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+
+	/* Enable EBM */
+	MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+
+	/* Enable EMI dcm */
+	MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+	/* restore dramc dcm */
+	switch (dram_chann_num) {
+	case 1:
+		if (dramc0_dcm_enable)
+			MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		else
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	case 2:
+		if (dramc0_dcm_enable)
+			MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		else
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+
+		if (dramc1_dcm_enable)
+			MET_REG_BCLR(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		else
+			MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	default:
+		METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+	}
+}
+
+
+void MET_BM_Enable(const unsigned int enable)
+{
+	unsigned long int value_check;
+	int i = 0;
+
+	while (i < 100) {
+		/* Force EMI idle low */
+		MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+		/* disable dramc dcm */
+		switch (dram_chann_num) {
+		case 1:
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		case 2:
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		default:
+			METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+		}
+
+		if (enable == 0)
+			/* Disable EBM */
+			MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+		else
+			/* Enable EBM */
+			MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+
+		/* Enable EMI dcm */
+		MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+		/* restore dramc dcm */
+		switch (dram_chann_num) {
+		case 1:
+			if (dramc0_dcm_enable)
+				MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			else
+				MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		case 2:
+			if (dramc0_dcm_enable)
+				MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			else
+				MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+
+			if (dramc1_dcm_enable)
+				MET_REG_BCLR(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			else
+				MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		default:
+			METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+		}
+
+		value_check = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+		if (enable == 0) {
+			/* EN == 0, IDLE == 0 when EMI RESET */
+			if (!test_bit(BUS_MON_EN_SHIFT, &value_check)
+			    && !test_bit(BUS_MON_IDLE_SHIFT, &value_check)) {
+				break;
+			}
+		} else {
+			/* EN == 1, IDLE == 0 when EMI START */
+			if (test_bit(BUS_MON_EN_SHIFT, &value_check)
+			    && !test_bit(BUS_MON_IDLE_SHIFT, &value_check)) {
+				break;
+			}
+		}
+		i++;
+	}
+
+	/*MET_TRACE("[MET_BM_ENABLE] value_check: %lx, enable = %d\n", value_check, enable); */
+
+}
+
+
+#if 0
+void BM_Disable(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	emi_reg_sync_writel(value & (~BUS_MON_EN), ADDR_EMI + EMI_BMEN);
+}
+#endif
+
+
+void MET_BM_Pause(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	emi_reg_sync_writel(value | (1 << BUS_MON_PAUSE_SHIFT), ADDR_EMI + EMI_BMEN);
+}
+
+
+void MET_BM_Continue(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	emi_reg_sync_writel(value & (~(1 << BUS_MON_PAUSE_SHIFT)), ADDR_EMI + EMI_BMEN);
+}
+
+
+unsigned int MET_BM_IsOverrun(void)
+{
+	/*
+	 * return 0 if EMI_BCNT(bus cycle counts) or
+	 * EMI_WACT(total word counts) is overrun,
+	 * otherwise return an !0 value
+	 */
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	return (value & (1 << BC_OVERRUN_SHIFT));
+}
+
+
+unsigned int MET_BM_GetReadWriteType(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	return ((value & 0xFFFFFFCF) >> 4);
+}
+
+
+void MET_BM_SetReadWriteType(const unsigned int ReadWriteType)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	/*
+	 * ReadWriteType: 00/11 --> both R/W
+	 *                   01 --> only R
+	 *                   10 --> only W
+	 */
+	emi_reg_sync_writel((value & 0xFFFFFFCF) | (ReadWriteType << 4), ADDR_EMI + EMI_BMEN);
+}
+
+
+int MET_BM_GetBusCycCount(void)
+{
+	return MET_BM_IsOverrun() ? BM_ERR_OVERRUN : emi_readl(IOMEM(ADDR_EMI + EMI_BCNT));	/*Bus cycle counter */
+}
+
+
+unsigned int MET_BM_GetTransAllCount(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_TACT));
+}
+
+
+int MET_BM_GetTransCount(const unsigned int counter_num)
+{
+	unsigned int iCount;
+
+	switch (counter_num) {
+	case 1:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_TSCT));
+		break;
+
+	case 2:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_TSCT2));
+		break;
+
+	case 3:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_TSCT3));
+		break;
+
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+int MET_BM_GetWordAllCount(void)
+{
+	return MET_BM_IsOverrun() ? BM_ERR_OVERRUN : emi_readl(IOMEM(ADDR_EMI + EMI_WACT));
+}
+
+
+int MET_BM_GetWordCount(const unsigned int counter_num)
+{
+	unsigned int iCount;
+
+	switch (counter_num) {
+	case 1:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT));
+		break;
+
+	case 2:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT2));
+		break;
+
+	case 3:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT3));
+		break;
+
+	case 4:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT4));
+		break;
+
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+unsigned int MET_BM_GetBandwidthWordCount(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BACT));	/*Bandwidth counter for access */
+}
+
+
+unsigned int MET_BM_GetOverheadWordCount(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BSCT));	/*Overhead counter */
+}
+
+
+int MET_BM_GetTransTypeCount(const unsigned int counter_num)
+{
+	return (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+	    ? BM_ERR_WRONG_REQ : emi_readl(IOMEM(ADDR_EMI + EMI_TTYPE1 + (counter_num - 1) * 8));
+}
+
+
+int MET_BM_GetMDCT(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT));
+}
+
+
+int MET_BM_GetMDCT_2(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT_2ND));
+}
+
+
+int MET_BM_SetMDCT_MDMCU(unsigned int mdmcu_rd_buf)
+{
+	unsigned int value_origin;
+
+	value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_MDCT_2ND));
+	MET_TRACE("[MET_BM_SetMDCT_MDMCU] value_origin: %x\n", value_origin);
+
+	value_origin = value_origin & ~(0x7);
+	value_origin = value_origin | ((mdmcu_rd_buf) & 0x7);
+
+	emi_reg_sync_writel(value_origin, ADDR_EMI + EMI_MDCT_2ND);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_GetMonitorCounter(const unsigned int counter_num,
+			     unsigned int *master, unsigned int *trans_type)
+{
+	unsigned int value, addr;
+
+	if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+		return BM_ERR_WRONG_REQ;
+
+
+	if (counter_num == 1) {
+		addr = EMI_BMEN;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+		*master = (value >> 16) & MASK_MASTER;
+		*trans_type = (value >> 24) & MASK_TRANS_TYPE;
+	} else {
+		addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+		value = emi_readl(IOMEM(ADDR_EMI + addr)) >> ((counter_num % 2) * 16);
+		*master = value & MASK_MASTER;
+		*trans_type = (value >> 8) & MASK_TRANS_TYPE;
+	}
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+			     const unsigned int master, const unsigned int trans_type)
+{
+	unsigned int value, addr;
+	const unsigned int iMask = (MASK_TRANS_TYPE << 8) | MASK_MASTER;
+
+	if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+		return BM_ERR_WRONG_REQ;
+
+
+	if (counter_num == 1) {
+		addr = EMI_BMEN;
+		value = (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) |
+		    ((trans_type & MASK_TRANS_TYPE) << 24) | ((master & MASK_MASTER) << 16);
+	} else {
+		addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+		/* clear master and transaction type fields */
+		value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+		/* set master and transaction type fields */
+		value |= (((trans_type & MASK_TRANS_TYPE) << 8) |
+			  (master & MASK_MASTER)) << ((counter_num % 2) * 16);
+	}
+
+	emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val)
+{
+
+	unsigned int value_origin;
+
+	value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW0));
+	MET_TRACE("[MET_EMI_settype1] value_origin: %x\n", value_origin);
+	if (value_origin != bmrw0_val) {
+		emi_reg_sync_writel(bmrw0_val, ADDR_EMI + EMI_BMRW0);
+		MET_TRACE("[MET_EMI_settype1] bmrw0_val: %x, value_origin: %x\n", bmrw0_val,
+			   value_origin);
+	}
+
+
+	value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW1));
+	MET_TRACE("[MET_EMI_settype2] value_origin: %x\n", value_origin);
+	if (value_origin != bmrw1_val) {
+		emi_reg_sync_writel(bmrw1_val, ADDR_EMI + EMI_BMRW1);
+		MET_TRACE("[MET_EMI_settype2] bmrw0_val: %x, value_origin: %x\n", bmrw1_val,
+			   value_origin);
+
+	}
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable)
+{
+	unsigned int value;
+
+	if (counter_num > 3)
+		return BM_ERR_WRONG_REQ;
+
+	value =
+	    ((emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & (~(1 << (28 + counter_num)))) |
+	     (enable << (28 + counter_num)));
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master)
+{
+	unsigned int value, addr;
+	const unsigned int iMask = 0x7F;
+
+	if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+		return BM_ERR_WRONG_REQ;
+
+
+	if (counter_num == 1) {
+		addr = EMI_BMEN;
+		value =
+		    (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) | ((master & iMask) << 16);
+	} else {
+		addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+		/* clear master and transaction type fields */
+		value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+		/* set master and transaction type fields */
+		value |= ((master & iMask) << ((counter_num % 2) * 16));
+	}
+
+	emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID_En(const unsigned int counter_num,
+		       const unsigned int enable)
+{
+	unsigned int value;
+
+	if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+		return BM_ERR_WRONG_REQ;
+
+	if (enable == 0) {
+		/* clear  EMI ID selection Enabling   SEL_ID_EN */
+		value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+			 & ~(1 << (counter_num - 1)));
+	} else {
+		/* enable  EMI ID selection Enabling   SEL_ID_EN */
+		value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+			 | (1 << (counter_num - 1)));
+	}
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID(const unsigned int counter_num,
+		    const unsigned int id)
+{
+	unsigned int value, addr, shift_num;
+
+	if ((counter_num < 1 || counter_num > BM_COUNTER_MAX))
+		return BM_ERR_WRONG_REQ;
+
+	/* offset of EMI_BMIDx register */
+	addr = EMI_BMID0 + (counter_num - 1) / 2 * 4;
+	shift_num = ((counter_num - 1) % 2) * 16;
+	/* clear SELx_ID field */
+	value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(EMI_BMID_MASK << shift_num);
+
+	/* set SELx_ID field */
+	if (id <= 0xffff)       /*bigger then 0xff_ff : no select busid in master, reset busid as 0*/
+		value |= id << shift_num;
+
+	emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable)
+{
+	unsigned int value;
+
+	if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+		return BM_ERR_WRONG_REQ;
+
+
+	value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN1))
+		 & ~(1 << (counter_num - 1)))
+		| (enable << (counter_num - 1));
+
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN1);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetLatencyCounter(unsigned int enable)
+{
+	unsigned int value;
+
+	value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & ~(0x3 << 24);
+	/*
+	 * emi_ttype1 -- emi_ttype8 change as total latencies
+	 * for m0 -- m7,
+	 * and emi_ttype9 -- emi_ttype16 change as total transaction counts
+	 * for m0 -- m7
+	 */
+	if (enable == 1)
+		value |= (0x2 << 24);
+
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_GetLatencyCycle(unsigned int *__restrict__ emi_value,
+				const unsigned int begin, const unsigned int end)
+{
+	int i, j = 0;
+
+	for (i = begin - 1; i < end; i++)
+		emi_value[j++] = emi_readl(IOMEM(ADDR_EMI + (EMI_TTYPE1 + i * 8)));
+
+	return j;
+}
+
+
+unsigned int MET_BM_GetEmiDcm(void)
+{
+	return (emi_readl(IOMEM(ADDR_EMI + EMI_CONM)) >> 24);
+}
+
+
+int MET_BM_SetEmiDcm(const unsigned int setting)
+{
+	unsigned int value;
+
+	value = emi_readl(IOMEM(ADDR_EMI + EMI_CONM));
+	emi_reg_sync_writel((value & 0x00FFFFFF) | (setting << 24), ADDR_EMI + EMI_CONM);
+
+	return BM_REQ_OK;
+}
+
+
+unsigned int MET_EMI_GetMDCT(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT));
+}
+
+
+unsigned int MET_EMI_GetMDCT_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT_2ND));
+}
+
+
+unsigned int MET_EMI_GetARBA(void)
+{
+	/* EMI_ARBA EMI Bandwidth Filter Control M0/1 */
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBA));
+}
+
+
+unsigned int MET_EMI_GetARBB(void)
+{
+	/* need the ATBB for mt6739 */
+	return emi_readl(IOMEM(ADDR_EMI+EMI_ARBB));
+}
+
+
+unsigned int MET_EMI_GetARBC(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBC));
+}
+
+
+unsigned int MET_EMI_GetARBD(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBD));
+}
+
+
+unsigned int MET_EMI_GetARBE(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBE));
+}
+
+
+unsigned int MET_EMI_GetARBF(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBF));
+}
+
+
+unsigned int MET_EMI_GetARBG(void)
+{
+	return 0;
+}
+
+
+unsigned int MET_EMI_GetARBH(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBH));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT0(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT0));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT1(void)
+{
+	return 0;
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT2(void)
+{
+	return 0;
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT3(void)
+{
+	return 0;
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT4(void)
+{
+	return 0;
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWST0(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWST0));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWST1(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWST1));
+}
+
+
+/* C+G BW status*/
+unsigned int MET_EMI_GetBWCT0_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT0_2ND));
+}
+
+
+/* C+G BW status*/
+unsigned int MET_EMI_GetBWCT1_2ND(void)
+{
+	return 0;
+}
+
+
+/* C+G BW status*/
+unsigned int MET_EMI_GetBWST_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWST_2ND));
+}
+
+
+unsigned int MET_EMI_GetBMRW0(void)
+{
+	return readl(IOMEM(ADDR_EMI + EMI_BMRW0));
+}
+
+
+void emi_dump_reg(void)
+{
+	int i;
+
+	MET_TRACE("[emi_regdump]\n");
+	for (i = 0x400; i < 0x500; i = i + 16)
+		MET_TRACE("%4x__ %8x %8x %8x %8x\n", i, readl(IOMEM(ADDR_EMI + i)),
+			   readl(IOMEM(ADDR_EMI + i + 4)), readl(IOMEM(ADDR_EMI + i + 8)),
+			   readl(IOMEM(ADDR_EMI + i + 12)));
+}
+
+
+unsigned int MET_EMI_GetDramChannNum(void)
+{
+	int num = -1;
+
+	if (BaseAddrEMI) {
+		num = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+		num = ((num >> 8) & 0x0000003);
+	} else {
+		return 1;
+	}
+
+	if (num == M0_DOUBLE_HALF_BW_1CH)
+		return 1;
+	else if (num == M0_DOUBLE_HALF_BW_2CH)
+		return 2;
+	else if (num == M0_DOUBLE_HALF_BW_4CH)
+		return 4;
+	else                    /* default return single channel */
+		return 1;
+}
+
+
+unsigned int MET_EMI_GetDramRankNum(void)
+{
+	int dual_rank = 0;
+
+	if (BaseAddrEMI) {
+		dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+		dual_rank = ((dual_rank >> 17) & RANK_MASK);
+	} else {
+		return DUAL_RANK;
+	}
+
+	if (dual_rank == DISABLE_DUAL_RANK_MODE)
+		return ONE_RANK;
+	else			/* default return dual rank */
+		return DUAL_RANK;
+}
+
+
+/*
+ * Dual Channel:
+ * Enables two rank for CHB
+ * Quad Channel:
+ * Enables two rank  for CHC and CHD
+ * 0: Disable dual rank mode
+ * 1: Enable dual rank mode
+ */
+unsigned int MET_EMI_GetDramRankNum_CHN1(void)
+{
+	int dual_rank = 0;
+
+	if (BaseAddrEMI) {
+		dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+		dual_rank = ((dual_rank >> 16) & RANK_MASK);
+	} else {
+		return DUAL_RANK;
+	}
+
+	if (dual_rank == DISABLE_DUAL_RANK_MODE)
+		return ONE_RANK;
+	else			/* default return dual rank */
+		return DUAL_RANK;
+}
+
+
+void met_record_dramc_dcm_enable_flag(void)
+{
+	int reg_val;
+
+	switch (dram_chann_num) {
+	case 1:
+		reg_val = emi_readl(IOMEM(CH0_MISC_CG_CTRL0));
+		dramc0_dcm_enable = !((reg_val >> DRAMC_CG_SHIFT) & 0x1);
+		break;
+	case 2:
+		reg_val = emi_readl(IOMEM(CH0_MISC_CG_CTRL0));
+		dramc0_dcm_enable = !((reg_val >> DRAMC_CG_SHIFT) & 0x1);
+
+		reg_val = emi_readl(IOMEM(CH1_MISC_CG_CTRL0));
+		dramc1_dcm_enable = !((reg_val >> DRAMC_CG_SHIFT) & 0x1);
+		break;
+	default:
+		METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+	}
+}
diff --git a/src/devtools/met-driver/4.14/mt2731/emi/SEDA2/mtk_emi_bm.h b/src/devtools/met-driver/4.14/mt2731/emi/SEDA2/mtk_emi_bm.h
new file mode 100644
index 0000000..514b396
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/emi/SEDA2/mtk_emi_bm.h
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MT_MET_EMI_BM_H__
+#define __MT_MET_EMI_BM_H__
+
+#define EMI_VER_MAJOR  2
+#define EMI_VER_MINOR  0
+
+#define DEF_BM_RW_TYPE          (BM_BOTH_READ_WRITE)
+#define NTS                     2
+#define NWSCT                   4
+#define NLATENCY                8
+#define NTRANS                  8
+#define NALL                    (3 + 2 + 1)
+#define NTTYPE                  5
+#define NIDX_EMI                (NTS + NWSCT + NLATENCY + NTRANS + NALL + NTTYPE)
+
+#define NCNT                    9
+#define NCH                     2
+#define NIDX_DRAMC              (NCNT * NCH)
+#define NIDX                    (NIDX_EMI + NIDX_DRAMC)
+
+#define NCLK                    1
+#define NARB                    8
+#define NBW                     10
+#define NIDX_BL                 (NCLK + NARB + NBW)
+
+/* 1000 To Khz and 4x freq & 2x data rate for LPDDR4 */
+/* 1000 To Khz and 2x freq & 2x data rate for LPDDR3*/
+/* TBD: calculate emi clock rate from DRAM DATA RATE */
+
+/*dram baseclock/EMI clock  :	LP4=4	LP3=2	*/
+#define DRAM_EMI_BASECLOCK_RATE_LP4     4
+#define DRAM_EMI_BASECLOCK_RATE_LP3     2
+/*dram io width  :	LP4=x16		LP3=x32 */
+#define DRAM_IO_BUS_WIDTH_LP4           16
+#define DRAM_IO_BUS_WIDTH_LP3           32
+/*dram datarate  :	DDR=double */
+#define DRAM_DATARATE   2
+
+#define ADDR_EMI        ((unsigned long)BaseAddrEMI)
+
+static const char of_emi_desc[] = "mediatek,emi";
+static const char of_chn_emi_desc[] = "mediatek,chn_emi";
+static const char of_dramc_desc[] = "mediatek,dramc";
+
+#define BM_MASTER_M0            (0x01)
+#define BM_MASTER_M1            (0x02)
+#define BM_MASTER_M2            (0x04)
+#define BM_MASTER_M3            (0x08)
+#define BM_MASTER_M4            (0x10)
+#define BM_MASTER_M5            (0x20)
+#define BM_MASTER_M6            (0x40)
+#define BM_MASTER_M7            (0x80)
+#define BM_MASTER_ALL           (0xFF)
+
+
+enum BM_RW_Type {
+	BM_BOTH_READ_WRITE,
+	BM_READ_ONLY,
+	BM_WRITE_ONLY
+};
+
+enum {
+	BM_TRANS_TYPE_1BEAT = 0x0,
+	BM_TRANS_TYPE_2BEAT,
+	BM_TRANS_TYPE_3BEAT,
+	BM_TRANS_TYPE_4BEAT,
+	BM_TRANS_TYPE_5BEAT,
+	BM_TRANS_TYPE_6BEAT,
+	BM_TRANS_TYPE_7BEAT,
+	BM_TRANS_TYPE_8BEAT,
+	BM_TRANS_TYPE_9BEAT,
+	BM_TRANS_TYPE_10BEAT,
+	BM_TRANS_TYPE_11BEAT,
+	BM_TRANS_TYPE_12BEAT,
+	BM_TRANS_TYPE_13BEAT,
+	BM_TRANS_TYPE_14BEAT,
+	BM_TRANS_TYPE_15BEAT,
+	BM_TRANS_TYPE_16BEAT,
+	BM_TRANS_TYPE_1Byte = 0 << 4,
+	BM_TRANS_TYPE_2Byte = 1 << 4,
+	BM_TRANS_TYPE_4Byte = 2 << 4,
+	BM_TRANS_TYPE_8Byte = 3 << 4,
+	BM_TRANS_TYPE_16Byte = 4 << 4,
+	BM_TRANS_TYPE_32Byte = 5 << 4,
+	BM_TRANS_TYPE_BURST_WRAP = 0 << 7,
+	BM_TRANS_TYPE_BURST_INCR = 1 << 7
+};
+
+enum {
+	BM_TRANS_RW_DEFAULT = 0x0,
+	BM_TRANS_RW_READONLY,
+	BM_TRANS_RW_WRITEONLY,
+	BM_TRANS_RW_RWBOTH
+};
+
+
+/*coda busid 12bit, but HW support 16 bit*/
+#define EMI_BMID_MASK				(0xFFFF)
+#define BM_COUNTER_MAX				(21)
+
+/*
+*#define BUS_MON_EN		(0x00000001)
+*#define BUS_MON_PAUSE		(0x00000002)
+*#define BUS_MON_IDLE		(0x00000008)
+*#define BC_OVERRUN		(0x00000100)
+*/
+enum {
+	BUS_MON_EN_SHIFT = 0,
+	BUS_MON_PAUSE_SHIFT = 1,
+	BUS_MON_IDLE_SHIFT = 3,
+	BC_OVERRUN_SHIFT = 8,
+	DRAMC_CG_SHIFT = 9,
+};
+
+#define BM_REQ_OK				(0)
+#define BM_ERR_WRONG_REQ			(-1)
+#define BM_ERR_OVERRUN				(-2)
+
+#define BM_WSCT_TSCT_IDSEL_ENABLE		(0)
+#define BM_WSCT_TSCT_IDSEL_DISABLE		(-1)
+#define BM_TTYPE1_16_ENABLE			(0)
+#define BM_TTYPE1_16_DISABLE			(-1)
+#define BM_TTYPE17_21_ENABLE			(0)
+#define BM_TTYPE17_21_DISABLE			(-1)
+#define BM_BW_LIMITER_ENABLE			(0)
+#define BM_BW_LIMITER_DISABLE			(-1)
+
+#define M0_DOUBLE_HALF_BW_1CH	(0x0)
+#define M0_DOUBLE_HALF_BW_2CH	(0x1)
+#define M0_DOUBLE_HALF_BW_4CH	(0x2)
+
+/* EMI Rank configuration */
+enum {
+	DISABLE_DUAL_RANK_MODE = 0,
+	ENABLE_DUAL_RANK_MODE,
+};
+
+#define RANK_MASK 0x1
+#define ONE_RANK 1
+#define DUAL_RANK 2
+
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+/*ondiemet emi ipi command*/
+enum BM_EMI_IPI_Type {
+	SET_BASE_EMI = 0x0,
+	SET_BASE_DRAMC0,
+	SET_BASE_DRAMC1,
+	SET_BASE_DRAMC2,
+	SET_BASE_DRAMC3,
+	SET_BASE_DDRPHY0AO,
+	SET_BASE_DRAMC0_AO,
+	SET_EBM_CONFIGS1,
+	SET_EBM_CONFIGS2,
+	SET_REGISTER_CB,
+};
+#endif
+
+#define	EMI_OFF			0x0000
+#define EMI_CONA		(0x000-EMI_OFF)
+#define EMI_CONH		(0x038-EMI_OFF)
+#define EMI_CONM		(0x060-EMI_OFF)
+#define EMI_CONO		(0x070-EMI_OFF)
+
+#define EMI_MDCT		(0x078 - EMI_OFF)
+#define EMI_MDCT_2ND		(0x07C - EMI_OFF)
+
+#define EMI_ARBA                (0x100 - EMI_OFF)
+#define EMI_ARBB                (0x108 - EMI_OFF)
+#define EMI_ARBC                (0x110 - EMI_OFF)
+#define EMI_ARBD                (0x118 - EMI_OFF)
+#define EMI_ARBE                (0x120 - EMI_OFF)
+#define EMI_ARBF                (0x128 - EMI_OFF)
+#define EMI_ARBH                (0x138 - EMI_OFF)
+
+#define EMI_BMEN                (0x400 - EMI_OFF)
+#define EMI_BCNT                (0x408 - EMI_OFF)
+#define EMI_TACT                (0x410 - EMI_OFF)
+#define EMI_TSCT                (0x418 - EMI_OFF)
+#define EMI_WACT                (0x420 - EMI_OFF)
+#define EMI_WSCT                (0x428 - EMI_OFF)
+#define EMI_BACT                (0x430 - EMI_OFF)
+#define EMI_BSCT                (0x438 - EMI_OFF)
+
+#define EMI_MSEL                (0x440 - EMI_OFF)
+#define EMI_TSCT2               (0x448 - EMI_OFF)
+#define EMI_TSCT3               (0x450 - EMI_OFF)
+#define EMI_WSCT2               (0x458 - EMI_OFF)
+#define EMI_WSCT3               (0x460 - EMI_OFF)
+#define EMI_WSCT4               (0x464 - EMI_OFF)
+#define EMI_MSEL2               (0x468 - EMI_OFF)
+#define EMI_MSEL3               (0x470 - EMI_OFF)
+#define EMI_MSEL4               (0x478 - EMI_OFF)
+#define EMI_MSEL5               (0x480 - EMI_OFF)
+#define EMI_MSEL6               (0x488 - EMI_OFF)
+#define EMI_MSEL7               (0x490 - EMI_OFF)
+#define EMI_MSEL8               (0x498 - EMI_OFF)
+#define EMI_MSEL9               (0x4A0 - EMI_OFF)
+#define EMI_MSEL10              (0x4A8 - EMI_OFF)
+
+#define EMI_BMID0               (0x4B0 - EMI_OFF)
+#define EMI_BMID1               (0x4B4 - EMI_OFF)
+#define EMI_BMID2               (0x4B8 - EMI_OFF)
+#define EMI_BMID3               (0x4BC - EMI_OFF)
+#define EMI_BMID4               (0x4C0 - EMI_OFF)
+#define EMI_BMID5               (0x4C4 - EMI_OFF)
+#define EMI_BMID6               (0x4C8 - EMI_OFF)
+#define EMI_BMID7               (0x4CC - EMI_OFF)
+#define EMI_BMID8               (0x4D0 - EMI_OFF)
+#define EMI_BMID9               (0x4D4 - EMI_OFF)
+#define EMI_BMID10              (0x4D8 - EMI_OFF)
+
+#define EMI_BMEN1               (0x4E0 - EMI_OFF)
+#define EMI_BMEN2               (0x4E8 - EMI_OFF)
+#define EMI_BMRW0               (0x4F8 - EMI_OFF)
+#define EMI_BMRW1               (0x4FC - EMI_OFF)
+#define EMI_TTYPE1              (0x500 - EMI_OFF)
+#define EMI_TTYPE2              (0x508 - EMI_OFF)
+#define EMI_TTYPE3              (0x510 - EMI_OFF)
+#define EMI_TTYPE4              (0x518 - EMI_OFF)
+#define EMI_TTYPE5              (0x520 - EMI_OFF)
+#define EMI_TTYPE6              (0x528 - EMI_OFF)
+#define EMI_TTYPE7              (0x530 - EMI_OFF)
+#define EMI_TTYPE8              (0x538 - EMI_OFF)
+#define EMI_TTYPE9              (0x540 - EMI_OFF)
+#define EMI_TTYPE10             (0x548 - EMI_OFF)
+#define EMI_TTYPE11             (0x550 - EMI_OFF)
+#define EMI_TTYPE12             (0x558 - EMI_OFF)
+#define EMI_TTYPE13             (0x560 - EMI_OFF)
+#define EMI_TTYPE14             (0x568 - EMI_OFF)
+#define EMI_TTYPE15             (0x570 - EMI_OFF)
+#define EMI_TTYPE16             (0x578 - EMI_OFF)
+#define EMI_TTYPE17             (0x580 - EMI_OFF)
+#define EMI_TTYPE18             (0x588 - EMI_OFF)
+#define EMI_TTYPE19             (0x590 - EMI_OFF)
+#define EMI_TTYPE20             (0x598 - EMI_OFF)
+#define EMI_TTYPE21             (0x5A0 - EMI_OFF)
+
+#define EMI_BWCT0               (0x5B0 - EMI_OFF)
+#define EMI_BWST0               (0x5C4 - EMI_OFF)
+#define EMI_BWST1               (0x5C8 - EMI_OFF)
+
+#define EMI_BWCT0_2ND   (0x6A0 - EMI_OFF)
+#define EMI_BWST_2ND    (0x6A8 - EMI_OFF)
+
+
+extern void emi_dump_reg(void);
+extern int MET_BM_Init(void);
+extern void MET_BM_DeInit(void);
+extern void MET_BM_SaveCfg(void);
+extern void MET_BM_RestoreCfg(void);
+extern void MET_BM_Enable(const unsigned int enable);
+extern void MET_BM_Pause(void);
+extern void MET_BM_Continue(void);
+extern unsigned int MET_BM_IsOverrun(void);
+extern unsigned int MET_BM_GetReadWriteType(void);
+extern void MET_BM_SetReadWriteType(const unsigned int ReadWriteType);
+extern int MET_BM_GetBusCycCount(void);
+extern unsigned int MET_BM_GetTransAllCount(void);
+extern int MET_BM_GetTransCount(const unsigned int counter_num);
+extern int MET_BM_GetWordAllCount(void);
+extern int MET_BM_GetWordCount(const unsigned int counter_num);
+extern unsigned int MET_BM_GetBandwidthWordCount(void);
+extern unsigned int MET_BM_GetOverheadWordCount(void);
+extern int MET_BM_GetTransTypeCount(const unsigned int counter_num);
+extern int MET_BM_GetMDCT(void);
+extern int MET_BM_GetMDCT_2(void);
+extern int MET_BM_GetMonitorCounter(const unsigned int counter_num,
+				    unsigned int *master, unsigned int *trans_type);
+extern int MET_BM_SetMDCT_MDMCU(unsigned int mdmcu_rd_buf);
+extern int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+				    const unsigned int master, const unsigned int trans_type);
+extern int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val);
+extern int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable);
+extern int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master);
+extern int MET_BM_SetbusID_En(const unsigned int counter_num,
+			      const unsigned int enable);
+extern int MET_BM_SetbusID(const unsigned int counter_num,
+			   const unsigned int id);
+extern int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable);
+extern int MET_BM_SetLatencyCounter(unsigned int enable);
+int MET_BM_GetLatencyCycle(unsigned int *__restrict__ emi_value,
+				const unsigned int begin, const unsigned int end);
+extern unsigned int MET_BM_GetEmiDcm(void);
+extern int MET_BM_SetEmiDcm(const unsigned int setting);
+extern void MET_BM_Clear_Start(void);
+extern unsigned int MET_EMI_GetDramRankNum(void);
+extern unsigned int MET_EMI_GetDramRankNum_CHN1(void);
+
+
+/* Config */
+unsigned int MET_EMI_GetARBA(void);
+unsigned int MET_EMI_GetARBB(void);
+unsigned int MET_EMI_GetARBC(void);
+unsigned int MET_EMI_GetARBD(void);
+unsigned int MET_EMI_GetARBE(void);
+unsigned int MET_EMI_GetARBF(void);
+unsigned int MET_EMI_GetARBG(void);
+unsigned int MET_EMI_GetARBH(void);
+
+/* Total BW status */
+extern unsigned int MET_EMI_GetBWCT0(void);
+extern unsigned int MET_EMI_GetBWCT1(void);
+extern unsigned int MET_EMI_GetBWCT2(void);
+extern unsigned int MET_EMI_GetBWCT3(void);
+extern unsigned int MET_EMI_GetBWCT4(void);
+extern unsigned int MET_EMI_GetBWST0(void);
+extern unsigned int MET_EMI_GetBWST1(void);
+/* C+G BW */
+extern unsigned int MET_EMI_GetBWCT0_2ND(void);
+extern unsigned int MET_EMI_GetBWCT1_2ND(void);
+extern unsigned int MET_EMI_GetBWST_2ND(void);
+
+unsigned int MET_EMI_GetBMRW0(void);
+unsigned int MET_EMI_GetDramChannNum(void);
+
+/* ondiemet*/
+void MET_BM_IPI_baseaddr(void);
+void met_emi_phyaddr_debug(void);
+
+
+extern void met_record_dramc_dcm_enable_flag(void);
+
+#endif                          /* !__MT_MET_EMI_BM_H__ */
diff --git a/src/devtools/met-driver/4.14/mt2731/emi/SEDA3/met_emi.c b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3/met_emi.c
new file mode 100644
index 0000000..a529ae5
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3/met_emi.c
@@ -0,0 +1,1570 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#ifdef CONFIG_ARM
+//#include <asm/dma-mapping.h> /* arm_coherent_dma_ops */
+#endif /* CONFIG_ARM */
+
+#include <linux/dma-mapping.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "plf_init.h"
+#include "plf_trace.h"
+#include "mtk_emi_bm.h"
+#include "mtk_dramc_reg.h"
+#include "interface.h"
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+#include "sspm/ondiemet_sspm.h"
+#endif
+
+
+/*======================================================================*/
+/*	Global variable definitions					*/
+/*======================================================================*/
+/*ondiemet emi sampling interval in us */
+int emi_tsct_enable;
+int emi_mdct_enable;
+int emi_TP_busfiltr_enable;
+
+int emi_use_ondiemet;
+int metemi_func_opt;
+
+int met_emi_regdump;
+/* Dynamic MonitorCounter selection !!!EXPERIMENT!!! */
+static int msel_enable;
+static unsigned int msel_group1 = BM_MASTER_ALL;
+static unsigned int msel_group2 = BM_MASTER_ALL;
+static unsigned int msel_group3 = BM_MASTER_ALL;
+
+/* CVS Added changeable buffer for testing */
+static int mdmcu_sel_enable;
+static unsigned int rd_mdmcu_rsv_num = 0x5;
+
+/* Global variables */
+static struct kobject *kobj_emi;
+static int rwtype = BM_BOTH_READ_WRITE;
+
+/* BW Limiter */
+/*#define CNT_COUNTDOWN	(1000-1)*/		/* 1000 * 1ms = 1sec */
+#define CNT_COUNTDOWN   (0)                     /* 1ms */
+static int countdown;
+static int bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+
+/* TTYPE counter */
+static int ttype1_16_en = BM_TTYPE1_16_DISABLE;
+static int ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+static int dramc_pdir_enable;
+static int dram_chann_num = 1;
+
+enum SSPM_Mode {
+	CUSTOMER_MODE = 0x0,
+	UNDEFINE_MODE = 0x1,
+	INTERNAL_MODE = 0X2780
+};
+
+
+/*======================================================================*/
+/*	EMI Test Operations						*/
+/*======================================================================*/
+static int times;
+
+static ssize_t test_apmcu_store(struct kobject *kobj,
+				struct kobj_attribute *attr,
+				const char *buf,
+				size_t n)
+{
+	int i;
+	unsigned int    *src_addr_v = NULL;
+	dma_addr_t src_addr_p;
+#ifdef CONFIG_ARM
+	struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_dma_ops);
+#endif /* CONFIG_ARM */
+
+	if ((n == 0) || (buf == NULL))
+		return -EINVAL;
+	if (kstrtoint(buf, 10, &times) != 0)
+		return -EINVAL;
+	if (times < 0)
+		return -EINVAL;
+
+	if (times > 5000)       /* Less than 20MB */
+		return -EINVAL;
+
+#ifdef CONFIG_ARM
+	if (ops && ops->alloc) {
+		(met_device.this_device)->coherent_dma_mask = DMA_BIT_MASK(32);
+		src_addr_v = ops->alloc(met_device.this_device,
+						PAGE_SIZE,
+						&src_addr_p,
+						GFP_KERNEL,
+						0);
+	}
+#endif /* CONFIG_ARM */
+ 
+#ifdef CONFIG_ARM64
+	/* dma_alloc */
+ 	src_addr_v = dma_alloc_coherent(met_device.this_device,
+ 					PAGE_SIZE,
+ 					&src_addr_p,
+ 					GFP_KERNEL);
+#endif /* CONFIG_ARM64 */
+
+	if (src_addr_v == NULL) {
+#ifdef CONFIG_MET_MODULE
+		met_tag_oneshot_real(0, "test_apmcu dma alloc fail", PAGE_SIZE);
+#else
+		met_tag_oneshot(0, "test_apmcu dma alloc fail", PAGE_SIZE);
+#endif
+		return -ENOMEM;
+	}
+	/* testing */
+	preempt_disable();
+#ifdef CONFIG_MET_MODULE
+	met_tag_start_real(0, "TEST_EMI_APMCU");
+#else
+	met_tag_start(0, "TEST_EMI_APMCU");
+#endif
+	for (i = 0; i < times; i++) {
+		memset(src_addr_v, 2 * i, PAGE_SIZE);
+#ifdef CONFIG_MET_MODULE
+		met_tag_oneshot_real(0, "TEST_EMI_APMCU", PAGE_SIZE);
+#else
+		met_tag_oneshot(0, "TEST_EMI_APMCU", PAGE_SIZE);
+#endif
+	}
+#ifdef CONFIG_MET_MODULE
+	met_tag_end_real(0, "TEST_EMI_APMCU");
+#else
+	met_tag_end(0, "TEST_EMI_APMCU");
+#endif
+	/* the following function has no defined if MET is built as module */
+	/* preempt_enable_no_resched(); */
+	/* use this one to replace it: see met_drv.h */
+	my_preempt_enable();
+
+#ifdef CONFIG_ARM
+	/* dma_free */
+	if (ops && ops->free) {
+		ops->free(met_device.this_device,
+				  PAGE_SIZE,
+				  src_addr_v,
+				  src_addr_p,
+			0);
+	}
+#endif /* CONFIG_ARM */
+
+#ifdef CONFIG_ARM64
+	/* dma_free */
+ 	if (src_addr_v != NULL)
+ 		dma_free_coherent(met_device.this_device,
+ 				  PAGE_SIZE,
+ 				  src_addr_v,
+				  src_addr_p);
+#endif /* CONFIG_ARM64 */
+
+	return n;
+}
+
+/*======================================================================*/
+/*	KOBJ Declarations						*/
+/*======================================================================*/
+DECLARE_KOBJ_ATTR_INT(emi_tsct_enable, emi_tsct_enable);
+DECLARE_KOBJ_ATTR_INT(emi_mdct_enable, emi_mdct_enable);
+DECLARE_KOBJ_ATTR_INT(emi_TP_busfiltr_enable, emi_TP_busfiltr_enable);
+DECLARE_KOBJ_ATTR_INT(metemi_func_opt, metemi_func_opt);
+DECLARE_KOBJ_ATTR_INT(emi_regdump, met_emi_regdump);
+DECLARE_KOBJ_ATTR_INT(msel_enable, msel_enable);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group1, msel_group1, msel_group1 > 0 && msel_group1 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group2, msel_group2, msel_group2 > 0 && msel_group2 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group3, msel_group3, msel_group3 > 0 && msel_group3 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_INT(mdmcu_sel_enable, mdmcu_sel_enable);
+DECLARE_KOBJ_ATTR_INT(rd_mdmcu_rsv_num, rd_mdmcu_rsv_num);
+
+
+/* KOBJ: rwtype */
+DECLARE_KOBJ_ATTR_INT_CHECK(rwtype, rwtype, rwtype >= 0 && rwtype <= BM_WRITE_ONLY);
+
+static unsigned int get_emi_clock_rate(unsigned int dram_data_rate_MHz)
+{
+	/*
+	 *	the ddr type define :
+	 *	enum DDRTYPE {
+	 *	TYPE_LPDDR3 = 1,
+	 *	TYPE_LPDDR4,
+	 *	TYPE_LPDDR4X,
+	 *	TYPE_LPDDR2
+	 *	};
+	 */
+
+	unsigned int DRAM_TYPE;
+
+	if (get_ddr_type_symbol) {
+		DRAM_TYPE = get_ddr_type_symbol();
+
+		if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+			return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP4 / DRAM_DATARATE;
+		else
+			return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP3 / DRAM_DATARATE;
+	} else {
+		METERROR("[%s][%d]get_ddr_type_symbol = NULL , use the TYPE_LPDDR3 setting\n", __func__, __LINE__);
+		return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP3 / DRAM_DATARATE;
+	}
+}
+
+/* KOBJ: emi_clock_rate */
+static ssize_t emi_clock_rate_show(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   char *buf)
+{
+	unsigned int dram_data_rate_MHz;
+
+	if (get_dram_data_rate_symbol) {
+		dram_data_rate_MHz = get_dram_data_rate_symbol();
+	} else {
+		METERROR("get_dram_data_rate_symbol = NULL\n");
+		dram_data_rate_MHz = 0;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			get_emi_clock_rate(dram_data_rate_MHz));
+}
+
+DECLARE_KOBJ_ATTR_RO(emi_clock_rate);
+
+/* KOBJ: ttype1_16_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype1_16_en,
+	KOBJ_ITEM_LIST(
+		{ BM_TTYPE1_16_ENABLE,   "ENABLE" },
+		{ BM_TTYPE1_16_DISABLE,  "DISABLE" }
+		)
+	);
+DECLARE_KOBJ_ATTR_STR_LIST(ttype1_16_en, ttype1_16_en, ttype1_16_en);
+
+/* KOBJ: ttype17_21_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype17_21_en,
+	KOBJ_ITEM_LIST(
+		{ BM_TTYPE17_21_ENABLE,  "ENABLE" },
+		{ BM_TTYPE17_21_DISABLE, "DISABLE" }
+		)
+	);
+DECLARE_KOBJ_ATTR_STR_LIST(ttype17_21_en, ttype17_21_en, ttype17_21_en);
+
+/* KOBJ: bw_limiter_enable */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	bw_limiter_enable,
+	KOBJ_ITEM_LIST(
+		{ BM_BW_LIMITER_ENABLE,  "ENABLE" },
+		{ BM_BW_LIMITER_DISABLE, "DISABLE" }
+		)
+	);
+
+DECLARE_KOBJ_ATTR_STR_LIST(bw_limiter_enable, bw_limiter_enable, bw_limiter_enable);
+
+/* KOBJ: ttype_master */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype_master,
+	KOBJ_ITEM_LIST(
+		{ BM_MASTER_M0,  "M0" },
+		{ BM_MASTER_M1,  "M1" },
+		{ BM_MASTER_M2,  "M2" },
+		{ BM_MASTER_M3,  "M3" },
+		{ BM_MASTER_M4,  "M4" },
+		{ BM_MASTER_M5,  "M5" },
+		{ BM_MASTER_M6,  "M6" },
+		{ BM_MASTER_M7,  "M7" }
+		)
+	);
+
+
+/* KOBJ: ttypeX_nbeat, ttypeX_nbyte, ttypeX_burst */
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+	ttype_nbeat,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_TYPE_1BEAT,   1 },
+		{ BM_TRANS_TYPE_2BEAT,   2 },
+		{ BM_TRANS_TYPE_3BEAT,   3 },
+		{ BM_TRANS_TYPE_4BEAT,   4 },
+		{ BM_TRANS_TYPE_5BEAT,   5 },
+		{ BM_TRANS_TYPE_6BEAT,   6 },
+		{ BM_TRANS_TYPE_7BEAT,   7 },
+		{ BM_TRANS_TYPE_8BEAT,   8 },
+		{ BM_TRANS_TYPE_9BEAT,   9 },
+		{ BM_TRANS_TYPE_10BEAT,  10 },
+		{ BM_TRANS_TYPE_11BEAT,  11 },
+		{ BM_TRANS_TYPE_12BEAT,  12 },
+		{ BM_TRANS_TYPE_13BEAT,  13 },
+		{ BM_TRANS_TYPE_14BEAT,  14 },
+		{ BM_TRANS_TYPE_15BEAT,  15 },
+		{ BM_TRANS_TYPE_16BEAT,  16 }
+		)
+	);
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+	ttype_nbyte,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_TYPE_1Byte,   1 },
+		{ BM_TRANS_TYPE_2Byte,   2 },
+		{ BM_TRANS_TYPE_4Byte,   4 },
+		{ BM_TRANS_TYPE_8Byte,   8 },
+		{ BM_TRANS_TYPE_16Byte,  16 },
+		{ BM_TRANS_TYPE_32Byte,  32 }
+		)
+	);
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype_burst,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_TYPE_BURST_INCR,      "INCR" },
+		{ BM_TRANS_TYPE_BURST_WRAP,      "WRAP" }
+		)
+	);
+
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype_rw,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_RW_DEFAULT,   "DEFAULT" },
+		{ BM_TRANS_RW_READONLY,  "R" },
+		{ BM_TRANS_RW_WRITEONLY, "W" },
+		{ BM_TRANS_RW_RWBOTH,    "BOTH" }
+		)
+	);
+
+/* KOBJ: test_apmcu */
+DECLARE_KOBJ_ATTR_SHOW_INT(test_apmcu, times);
+/* please refer to session: "EMI Test Operations" for store operation */
+DECLARE_KOBJ_ATTR(test_apmcu);
+
+DECLARE_KOBJ_ATTR_INT(dramc_pdir_enable, dramc_pdir_enable);
+
+/*enable high priority filter*/
+static int high_priority_filter;
+DECLARE_KOBJ_ATTR_HEX(high_priority_filter, high_priority_filter);
+
+
+/**/
+static int ttype_master_val[21];
+static int ttype_busid_val[21];
+static int ttype_nbeat_val[21];
+static int ttype_nbyte_val[21];
+static int ttype_burst_val[21];
+static int ttype_rw_val[21];
+
+#define DECLARE_KOBJ_TTYPE_MASTER(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _master, ttype_master_val[nr - 1], ttype_master)
+
+#define DECLARE_KOBJ_TTYPE_NBEAT(nr) \
+	DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbeat, ttype_nbeat_val[nr - 1], ttype_nbeat)
+
+#define DECLARE_KOBJ_TTYPE_NBYTE(nr) \
+	DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbyte, ttype_nbyte_val[nr - 1], ttype_nbyte)
+
+#define DECLARE_KOBJ_TTYPE_BURST(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _burst, ttype_burst_val[nr - 1], ttype_burst)
+
+#define DECLARE_KOBJ_TTYPE_RW(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _rw, ttype_rw_val[nr - 1], ttype_rw)
+
+#define DECLARE_KOBJ_TTYPE_BUSID_VAL(nr) \
+	DECLARE_KOBJ_ATTR_HEX(ttype ## nr ## _busid, ttype_busid_val[nr - 1])
+
+DECLARE_KOBJ_TTYPE_MASTER(1);
+DECLARE_KOBJ_TTYPE_NBEAT(1);
+DECLARE_KOBJ_TTYPE_NBYTE(1);
+DECLARE_KOBJ_TTYPE_BURST(1);
+DECLARE_KOBJ_TTYPE_RW(1);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(1);
+
+DECLARE_KOBJ_TTYPE_MASTER(2);
+DECLARE_KOBJ_TTYPE_NBEAT(2);
+DECLARE_KOBJ_TTYPE_NBYTE(2);
+DECLARE_KOBJ_TTYPE_BURST(2);
+DECLARE_KOBJ_TTYPE_RW(2);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(2);
+
+DECLARE_KOBJ_TTYPE_MASTER(3);
+DECLARE_KOBJ_TTYPE_NBEAT(3);
+DECLARE_KOBJ_TTYPE_NBYTE(3);
+DECLARE_KOBJ_TTYPE_BURST(3);
+DECLARE_KOBJ_TTYPE_RW(3);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(3);
+
+DECLARE_KOBJ_TTYPE_MASTER(4);
+DECLARE_KOBJ_TTYPE_NBEAT(4);
+DECLARE_KOBJ_TTYPE_NBYTE(4);
+DECLARE_KOBJ_TTYPE_BURST(4);
+DECLARE_KOBJ_TTYPE_RW(4);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(4);
+
+DECLARE_KOBJ_TTYPE_MASTER(5);
+DECLARE_KOBJ_TTYPE_NBEAT(5);
+DECLARE_KOBJ_TTYPE_NBYTE(5);
+DECLARE_KOBJ_TTYPE_BURST(5);
+DECLARE_KOBJ_TTYPE_RW(5);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(5);
+
+DECLARE_KOBJ_TTYPE_MASTER(6);
+DECLARE_KOBJ_TTYPE_NBEAT(6);
+DECLARE_KOBJ_TTYPE_NBYTE(6);
+DECLARE_KOBJ_TTYPE_BURST(6);
+DECLARE_KOBJ_TTYPE_RW(6);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(6);
+
+DECLARE_KOBJ_TTYPE_MASTER(7);
+DECLARE_KOBJ_TTYPE_NBEAT(7);
+DECLARE_KOBJ_TTYPE_NBYTE(7);
+DECLARE_KOBJ_TTYPE_BURST(7);
+DECLARE_KOBJ_TTYPE_RW(7);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(7);
+
+DECLARE_KOBJ_TTYPE_MASTER(8);
+DECLARE_KOBJ_TTYPE_NBEAT(8);
+DECLARE_KOBJ_TTYPE_NBYTE(8);
+DECLARE_KOBJ_TTYPE_BURST(8);
+DECLARE_KOBJ_TTYPE_RW(8);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(8);
+
+DECLARE_KOBJ_TTYPE_MASTER(9);
+DECLARE_KOBJ_TTYPE_NBEAT(9);
+DECLARE_KOBJ_TTYPE_NBYTE(9);
+DECLARE_KOBJ_TTYPE_BURST(9);
+DECLARE_KOBJ_TTYPE_RW(9);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(9);
+
+DECLARE_KOBJ_TTYPE_MASTER(10);
+DECLARE_KOBJ_TTYPE_NBEAT(10);
+DECLARE_KOBJ_TTYPE_NBYTE(10);
+DECLARE_KOBJ_TTYPE_BURST(10);
+DECLARE_KOBJ_TTYPE_RW(10);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(10);
+
+DECLARE_KOBJ_TTYPE_MASTER(11);
+DECLARE_KOBJ_TTYPE_NBEAT(11);
+DECLARE_KOBJ_TTYPE_NBYTE(11);
+DECLARE_KOBJ_TTYPE_BURST(11);
+DECLARE_KOBJ_TTYPE_RW(11);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(11);
+
+DECLARE_KOBJ_TTYPE_MASTER(12);
+DECLARE_KOBJ_TTYPE_NBEAT(12);
+DECLARE_KOBJ_TTYPE_NBYTE(12);
+DECLARE_KOBJ_TTYPE_BURST(12);
+DECLARE_KOBJ_TTYPE_RW(12);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(12);
+
+DECLARE_KOBJ_TTYPE_MASTER(13);
+DECLARE_KOBJ_TTYPE_NBEAT(13);
+DECLARE_KOBJ_TTYPE_NBYTE(13);
+DECLARE_KOBJ_TTYPE_BURST(13);
+DECLARE_KOBJ_TTYPE_RW(13);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(13);
+
+DECLARE_KOBJ_TTYPE_MASTER(14);
+DECLARE_KOBJ_TTYPE_NBEAT(14);
+DECLARE_KOBJ_TTYPE_NBYTE(14);
+DECLARE_KOBJ_TTYPE_BURST(14);
+DECLARE_KOBJ_TTYPE_RW(14);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(14);
+
+DECLARE_KOBJ_TTYPE_MASTER(15);
+DECLARE_KOBJ_TTYPE_NBEAT(15);
+DECLARE_KOBJ_TTYPE_NBYTE(15);
+DECLARE_KOBJ_TTYPE_BURST(15);
+DECLARE_KOBJ_TTYPE_RW(15);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(15);
+
+DECLARE_KOBJ_TTYPE_MASTER(16);
+DECLARE_KOBJ_TTYPE_NBEAT(16);
+DECLARE_KOBJ_TTYPE_NBYTE(16);
+DECLARE_KOBJ_TTYPE_BURST(16);
+DECLARE_KOBJ_TTYPE_RW(16);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(16);
+
+DECLARE_KOBJ_TTYPE_MASTER(17);
+DECLARE_KOBJ_TTYPE_NBEAT(17);
+DECLARE_KOBJ_TTYPE_NBYTE(17);
+DECLARE_KOBJ_TTYPE_BURST(17);
+DECLARE_KOBJ_TTYPE_RW(17);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(17);
+
+DECLARE_KOBJ_TTYPE_MASTER(18);
+DECLARE_KOBJ_TTYPE_NBEAT(18);
+DECLARE_KOBJ_TTYPE_NBYTE(18);
+DECLARE_KOBJ_TTYPE_BURST(18);
+DECLARE_KOBJ_TTYPE_RW(18);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(18);
+
+DECLARE_KOBJ_TTYPE_MASTER(19);
+DECLARE_KOBJ_TTYPE_NBEAT(19);
+DECLARE_KOBJ_TTYPE_NBYTE(19);
+DECLARE_KOBJ_TTYPE_BURST(19);
+DECLARE_KOBJ_TTYPE_RW(19);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(19);
+
+DECLARE_KOBJ_TTYPE_MASTER(20);
+DECLARE_KOBJ_TTYPE_NBEAT(20);
+DECLARE_KOBJ_TTYPE_NBYTE(20);
+DECLARE_KOBJ_TTYPE_BURST(20);
+DECLARE_KOBJ_TTYPE_RW(20);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(20);
+
+DECLARE_KOBJ_TTYPE_MASTER(21);
+DECLARE_KOBJ_TTYPE_NBEAT(21);
+DECLARE_KOBJ_TTYPE_NBYTE(21);
+DECLARE_KOBJ_TTYPE_BURST(21);
+DECLARE_KOBJ_TTYPE_RW(21);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(21);
+
+/**/
+#define KOBJ_ATTR_ITEM_SERIAL_FNODE(nr) \
+	do { \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _master); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _nbeat); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _nbyte); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _burst); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _busid); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _rw); \
+	} while (0)
+
+#define KOBJ_ATTR_LIST \
+	do { \
+		KOBJ_ATTR_ITEM(high_priority_filter); \
+		KOBJ_ATTR_ITEM(metemi_func_opt); \
+		KOBJ_ATTR_ITEM(emi_tsct_enable); \
+		KOBJ_ATTR_ITEM(emi_mdct_enable); \
+		KOBJ_ATTR_ITEM(emi_TP_busfiltr_enable); \
+		KOBJ_ATTR_ITEM(emi_regdump); \
+		KOBJ_ATTR_ITEM(msel_enable); \
+		KOBJ_ATTR_ITEM(msel_group1); \
+		KOBJ_ATTR_ITEM(msel_group2); \
+		KOBJ_ATTR_ITEM(msel_group3); \
+		KOBJ_ATTR_ITEM(emi_clock_rate); \
+		KOBJ_ATTR_ITEM(rwtype); \
+		KOBJ_ATTR_ITEM(ttype17_21_en); \
+		KOBJ_ATTR_ITEM(ttype1_16_en); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(1); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(2); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(3); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(4); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(5); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(6); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(7); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(8); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(9); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(10); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(11); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(12); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(13); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(14); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(15); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(16); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(17); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(18); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(19); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(20); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(21); \
+		KOBJ_ATTR_ITEM(test_apmcu); \
+		KOBJ_ATTR_ITEM(bw_limiter_enable); \
+		KOBJ_ATTR_ITEM(dramc_pdir_enable); \
+		KOBJ_ATTR_ITEM(mdmcu_sel_enable); \
+		KOBJ_ATTR_ITEM(rd_mdmcu_rsv_num); \
+	} while (0)
+
+
+/*======================================================================*/
+/*	EMI Operations							*/
+/*======================================================================*/
+static void emi_init(void)
+{
+	unsigned int bmrw0_val, bmrw1_val, i, enable;
+	unsigned int msel_group_val[4];
+
+	/*save origianl EMI config*/
+	MET_BM_SaveCfg();
+
+	/* get dram channel number */
+	dram_chann_num = MET_EMI_GetDramChannNum();
+
+	/* Init. EMI bus monitor */
+	MET_BM_SetReadWriteType(rwtype);
+
+	if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+		if (msel_enable) {
+			msel_group_val[0] = BM_MASTER_ALL;
+			msel_group_val[1] = msel_group1;
+			msel_group_val[2] = msel_group2;
+			msel_group_val[3] = msel_group3;
+		} else {
+			msel_group_val[0] = BM_MASTER_ALL;
+			msel_group_val[1] = BM_MASTER_ALL;
+			msel_group_val[2] = BM_MASTER_ALL;
+			msel_group_val[3] = BM_MASTER_ALL;
+		}
+
+		MET_BM_SetLatencyCounter(1);    /*enable latency count*/
+
+		for (i = 1; i <= 4; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 msel_group_val[i - 1] & BM_MASTER_ALL,
+						 BM_TRANS_TYPE_4BEAT |
+						 BM_TRANS_TYPE_8Byte |
+						 BM_TRANS_TYPE_BURST_WRAP);
+			MET_BM_SetbusID(i, 0);
+			MET_BM_SetbusID_En(i, 0);       /*disable ttype bus sel*/
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 0);       /*disable tp filter*/
+
+	} else if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable == 1)) {
+		MET_BM_SetLatencyCounter(1);    /*enable latency count*/
+
+		for (i = 1; i <= 4; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			MET_BM_SetbusID_En(i, 0);       /*disable ttype bus sel*/
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 1);       /*enable tp filter*/
+
+	} else if ((ttype1_16_en == BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+		MET_BM_SetLatencyCounter(0);    /*disable latency count*/
+
+		for (i = 1; i <= 16; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			/*disenable ttype bus sel if busid > 0xff_ff*/
+			MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 0);       /*disable tp filter*/
+	} else {	/* (ttype1_16_en == BM_TTYPE1_16_ENABLE)  &&  (emi_TP_busfiltr_enable == 1) */
+		MET_BM_SetLatencyCounter(0);    /*disable latency count*/
+
+		for (i = 1; i <= 16; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			/*disable ttype bus sel if busid > 0xff_ff*/
+			MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 1);       /*enable tp filter*/
+	}
+
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+		for (i = 17; i <= 21; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			/*disable ttype bus sel if busid > 0xff_ff*/
+			MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+		}
+	}
+
+	bmrw0_val = 0;
+	for (i = 0; i < 16; i++)
+		bmrw0_val |= (ttype_rw_val[i] << (i * 2));
+
+	bmrw1_val = 0;
+	for (i = 16; i < 21; i++)
+		bmrw1_val |= (ttype_rw_val[i] << ((i-16) * 2));
+
+	MET_BM_SetTtypeCounterRW(bmrw0_val, bmrw1_val);
+
+	for (i = 0; i < BM_COUNTER_MAX; i++) {
+		if ((high_priority_filter & (1 << i)) == 0)
+			enable = 0;
+		else
+			enable = 1;
+
+		MET_BM_SetUltraHighFilter(i + 1, enable);
+	}
+
+	met_record_dramc_dcm_enable_flag();
+
+	if (met_emi_regdump == 1)
+		emi_dump_reg();
+}
+
+
+static void emi_uninit(void)
+{
+	MET_BM_RestoreCfg();
+}
+
+static inline void emi_start(void)
+{
+	MET_BM_Enable(1);
+}
+
+
+static inline void emi_stop(void)
+{
+	MET_BM_Enable(0);
+}
+
+
+static inline int do_emi(void)
+{
+	return met_emi.mode;
+}
+
+
+noinline void DRAM_DVFS(unsigned int dram_data_rate_MHz)
+{
+	MET_TRACE("%u\n", dram_data_rate_MHz);
+}
+
+
+static unsigned int emi_bw_limiter(unsigned int *__restrict__ array)
+{
+	int idx = 0;
+	unsigned int dram_data_rate_MHz;
+
+	if (get_dram_data_rate_symbol) {
+		dram_data_rate_MHz = get_dram_data_rate_symbol();
+	} else {
+		METERROR("get_dram_data_rate_symbol = NULL\n");
+		dram_data_rate_MHz = 0;
+	}
+
+	/* print dram data rate */
+	DRAM_DVFS(dram_data_rate_MHz);
+
+	/* get correct dram_clock_rate */
+	array[idx++] = dram_data_rate_MHz;
+
+	/* get correct ARB A->LAST */
+	array[idx++] = MET_EMI_GetARBA();
+	array[idx++] = MET_EMI_GetARBB();
+	array[idx++] = MET_EMI_GetARBC();
+	array[idx++] = MET_EMI_GetARBD();
+	array[idx++] = MET_EMI_GetARBE();
+	array[idx++] = MET_EMI_GetARBF();
+	array[idx++] = MET_EMI_GetARBG();
+	array[idx++] = MET_EMI_GetARBH();
+	/* EMI Total BW Thresholds */
+	array[idx++] = MET_EMI_GetBWCT0();
+	array[idx++] = MET_EMI_GetBWCT1();
+	array[idx++] = MET_EMI_GetBWCT2();
+	array[idx++] = MET_EMI_GetBWCT3();
+	array[idx++] = MET_EMI_GetBWCT4();
+	array[idx++] = MET_EMI_GetBWST0();
+	array[idx++] = MET_EMI_GetBWST1();
+	/* EMI C+G BW Thresholds */
+	array[idx++] = MET_EMI_GetBWCT0_2ND();
+	array[idx++] = MET_EMI_GetBWCT1_2ND();
+	array[idx++] = MET_EMI_GetBWST_2ND();
+
+	return idx;
+}
+
+
+static void _ms_dramc(unsigned int *__restrict__ dramc_pdir_value, int dram_chann_num)
+{
+	MET_DRAMC_GetDebugCounter(dramc_pdir_value, dram_chann_num);
+}
+
+
+static unsigned int emi_polling(unsigned int *__restrict__ emi_value, unsigned int *__restrict__ emi_tsct,
+				unsigned int *__restrict__ emi_ttype_value, unsigned int *__restrict__ dramc_pdir_value,
+				unsigned int *__restrict__ emi_mdct_value)
+{
+	int j = 4;              /* skip 4 WSCTs */
+	int i = 0;              /* ttype start at 0 */
+	int k = 0;              /* tsct start at 0 */
+	int n;
+
+	MET_BM_Pause();
+
+	/* Get Word Count */
+
+	emi_value[0] = MET_BM_GetWordCount(1);  /* All */
+	emi_value[1] = MET_BM_GetWordCount(2);  /* Group 1 */
+	emi_value[2] = MET_BM_GetWordCount(3);  /* Group 2 */
+	emi_value[3] = MET_BM_GetWordCount(4);  /* Group 3 */
+
+	if (ttype1_16_en != BM_TTYPE1_16_ENABLE) {      /*1~21 NOT for ttype*/
+		/* Get Latency */
+		j += MET_BM_GetLatencyCycle(emi_value + j, 1, 8);
+
+		/* Get Trans. */
+		j += MET_BM_GetLatencyCycle(emi_value + j, 9, 16);
+	} else {
+		for (n = 4; n < 20; n++)
+			emi_value[n] = 0;
+		j = 20;
+
+		i += MET_BM_GetLatencyCycle(emi_ttype_value + i, 1, 8);
+
+		/* Get Trans. */
+		i += MET_BM_GetLatencyCycle(emi_ttype_value + i, 9, 16);
+	}
+
+	/* Get BACT/BSCT/BCNT/WACT/DCM_CTRL */
+	emi_value[j++] = MET_BM_GetBandwidthWordCount(); /* 20 */
+	emi_value[j++] = MET_BM_GetOverheadWordCount();
+	emi_value[j++] = MET_BM_GetBusCycCount();
+	emi_value[j++] = MET_BM_GetWordAllCount();
+	emi_value[j++] = MET_DRAMC_DCM_CTRL(0);
+
+	/* Get TACT */
+	emi_value[j++] = MET_BM_GetTransAllCount();
+
+	/* Get PageHist/PageMiss/InterBank/Idle */
+	for (n = 0; n < dram_chann_num; n++) {
+		emi_value[j++] = MET_DRAMC_GetPageHitCount(DRAMC_ALL, n);
+		emi_value[j++] = MET_DRAMC_GetPageMissCount(DRAMC_ALL, n);
+		emi_value[j++] = MET_DRAMC_GetInterbankCount(DRAMC_ALL, n);
+		emi_value[j++] = MET_DRAMC_GetIdleCount(n);
+		emi_value[j++] = ((MET_DRAMC_SPCMDRESP(n) >> 8) & 0x7); /* refresh rate */
+		emi_value[j++] = MET_DRAMC_RefPop(n);
+		emi_value[j++] = MET_DRAMC_Free26M(n);
+		emi_value[j++] = MET_DRAMC_RByte(n);
+		emi_value[j++] = MET_DRAMC_WByte(n);
+	}
+	/* TTYPE */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE)    /*17~21 for ttype*/
+		MET_BM_GetLatencyCycle(emi_ttype_value + 16, 17, 21);
+
+	/* Get tsct */
+	if (emi_tsct_enable == 1) {
+		emi_tsct[k++] = MET_BM_GetTransCount(1);
+		emi_tsct[k++] = MET_BM_GetTransCount(2);
+		emi_tsct[k++] = MET_BM_GetTransCount(3);
+	}
+	/*get mdct rsv buffer*/
+	if (emi_mdct_enable == 1) {
+		emi_mdct_value[0] = (MET_BM_GetMDCT() >> 16) & 0x7;
+		emi_mdct_value[1] = (MET_BM_GetMDCT_2() & 0x7);
+	}
+
+	if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 )
+		_ms_dramc(dramc_pdir_value, dram_chann_num);
+
+	MET_BM_Continue();
+	MET_BM_Clear_Start();
+
+	return j;
+}
+
+
+/*======================================================================*/
+/*	MET Device Operations						*/
+/*======================================================================*/
+static int emi_inited;
+
+static int met_emi_create(struct kobject *parent)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < 21; i++) {
+		ttype_master_val[i] = BM_MASTER_M0;
+		ttype_nbeat_val[i] = BM_TRANS_TYPE_1BEAT;
+		ttype_nbyte_val[i] = BM_TRANS_TYPE_8Byte;
+		ttype_burst_val[i] = BM_TRANS_TYPE_BURST_INCR;
+		ttype_busid_val[i] = 0xfffff;   /*default disable ttype bus sel if busid > 0xff_ff */
+		ttype_rw_val[i] =  BM_TRANS_RW_DEFAULT;
+	}
+
+	ret = MET_BM_Init();
+	if (ret != 0) {
+		pr_notice("MET_BM_Init failed!!!\n");
+		ret = 0;        /* will retry later */
+	} else {
+		emi_inited = 1;
+	}
+
+	kobj_emi = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+	do { \
+		ret = sysfs_create_file(kobj_emi, &attr_name ## _attr.attr); \
+		if (ret != 0) { \
+			pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+			return ret; \
+		} \
+	} while (0)
+	KOBJ_ATTR_LIST;
+#undef  KOBJ_ATTR_ITEM
+
+	return ret;
+}
+
+
+static void met_emi_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+	sysfs_remove_file(kobj_emi, &attr_name ## _attr.attr)
+	if (kobj_emi != NULL) {
+		KOBJ_ATTR_LIST;
+		kobj_emi = NULL;
+	}
+#undef  KOBJ_ATTR_ITEM
+
+	if (emi_inited)
+		MET_BM_DeInit();
+}
+
+
+static void met_emi_start(void)
+{
+	unsigned int bw_limiter[NIDX_BL];
+
+	if (!emi_inited) {
+		if (MET_BM_Init() != 0) {
+			met_emi.mode = 0;
+			pr_notice("MET_BM_Init failed!!!\n");
+			return;
+		}
+		emi_inited = 1;
+	}
+
+	if (do_emi()) {
+		emi_init();
+		MET_BM_Clear_Start();
+
+		/* Draw the first BW Limiter point */
+		if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+			emi_bw_limiter(bw_limiter);
+			ms_bw_limiter(NIDX_BL, bw_limiter);
+			/* init countdown value */
+			countdown = CNT_COUNTDOWN;
+		}
+	}
+}
+
+
+static void met_emi_stop(void)
+{
+	unsigned int bw_limiter[NIDX_BL];
+
+	if (!emi_inited)
+		return;
+
+	if (met_emi_regdump == 1)
+		emi_dump_reg();
+
+	if (do_emi()) {
+		/* Draw the last BW Limiter point */
+		if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+			/*
+			 * Skip drawing when we just draw
+			 * the point at last polling.
+			 */
+			if (countdown < CNT_COUNTDOWN) {
+				emi_bw_limiter(bw_limiter);
+				ms_bw_limiter(NIDX_BL, bw_limiter);
+			}
+		}
+
+		emi_stop();
+		emi_uninit();
+	}
+}
+
+
+/* DRS output */
+noinline void emi_drs(uint32_t *value)
+{
+	MET_TRACE("%u,%u,%u,%u,%u,%u\n", value[0], value[1], value[2], value[3], value[4], value[5]);
+}
+
+
+static void met_emi_polling(unsigned long long stamp, int cpu)
+{
+	unsigned int emi_value[NIDX];
+	unsigned int emi_tsct[3];
+	unsigned int emi_ttype_value[21];
+	unsigned int dramc_pdir_value[DRAMC_Debug_MAX_CNT * NCH];
+	unsigned int emi_mdct_value[2];
+	unsigned int chn_emi_drs[6];
+
+	if (!do_emi())
+		return;
+
+	/* get emi & dramc counters */
+	emi_value[0] = 0;       /* 0: pure linux MET , 0xa5: OnDieMET*/
+	emi_value[1] = 0;       /* EBM pause duration (ns)*/
+	emi_polling(emi_value + 2, emi_tsct, emi_ttype_value, dramc_pdir_value, emi_mdct_value);
+
+	/* get and output BW Limiter */
+	if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+		unsigned int bw_limiter[NIDX_BL];
+
+		if (countdown > 0) {
+			countdown--;
+		} else {
+			emi_bw_limiter(bw_limiter);
+			ms_bw_limiter(NIDX_BL, bw_limiter);
+			/* reload countdown value */
+			countdown = CNT_COUNTDOWN;
+		}
+	}
+
+	/* output emi */
+	ms_emi(NIDX_EMI - NTTYPE + (NCNT * dram_chann_num), emi_value);
+
+	/* output tsct*/
+	if (emi_tsct_enable == 1)
+		ms_emi_tsct(3, emi_tsct);
+
+	/* output mdct*/
+	if (emi_mdct_enable == 1)
+		ms_emi_mdct(2, emi_mdct_value);
+
+	/* output dramc*/
+	if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 )
+		ms_dramc(DRAMC_Debug_MAX_CNT * dram_chann_num, dramc_pdir_value);
+
+	/* output ms_ttype */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE)
+		ms_ttype(21, emi_ttype_value);
+
+	/* adjust MDMCU buffer */
+	if (mdmcu_sel_enable == 1)
+		MET_BM_SetMDCT_MDMCU(rd_mdmcu_rsv_num);
+
+	/* DRS handling */
+	met_get_drs_registers(chn_emi_drs);
+	emi_drs(chn_emi_drs);
+}
+
+
+static void met_emi_resume(void)
+{
+	/* return directly when emi was closed */
+	if (!do_emi())
+		return;
+
+	/* remap EMI_BM related reg*/
+	emi_init();
+
+	/* restarn counting */
+	MET_BM_Clear_Start();
+}
+
+
+static const char help[] = "  --emi                                 monitor EMI banwidth\n";
+static int emi_print_help(char *buf, int len)
+{
+	return snprintf(buf, PAGE_SIZE, help);
+}
+
+
+#define TTYPE_NAME_STR_LEN  64
+/* static char ttype_name[21][TTYPE_NAME_STR_LEN]; */
+static int emi_print_header(char *buf, int len)
+{
+	int ret = 0;
+/*	int ret_m[21]; */
+	int i = 0;
+
+#if 1 /* move to AP side print header */
+//#ifndef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
+	unsigned int dram_data_rate_MHz;
+	unsigned int DRAM_TYPE;
+#endif
+
+#if 0
+	/*ttype header info*/
+	for (i = 0; i < 21; i++) {
+		int k;
+
+		/*busid > 0xffff    not specific bus id , show all on specificmaster*/
+		if (ttype_busid_val[i] > 0xffff) {
+			int j;
+
+			for (j = 0; j < ARRAY_SIZE(ttype_master_list_item); j++) {
+				if (ttype_master_val[i] == ttype_master_list_item[j].key) {
+					ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttype%d_%s",
+							    i + 1, ttype_master_list_item[j].val);/*master*/
+					break;
+				}
+			}
+			if (j == ARRAY_SIZE(ttype_master_list_item))
+				ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttype%d_%s",
+						    i + 1, "unknown");
+		} else {
+			ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttype%d_%x",
+					    i + 1, ttype_busid_val[i]);/*busID*/
+		}
+
+		/*show beat type*/
+		for (k = 0; k < ARRAY_SIZE(ttype_nbeat_list_item); k++) {
+
+			if (ttype_nbeat_val[i] == ttype_nbeat_list_item[k].key)
+				ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "_%d",
+						     ttype_nbeat_list_item[k].val); /*beat*/
+		}
+
+		/*show byte type*/
+		for (k = 0; k < ARRAY_SIZE(ttype_nbyte_list_item); k++) {
+
+			if (ttype_nbyte_val[i] == ttype_nbyte_list_item[k].key)
+				ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "x%d",
+						     ttype_nbyte_list_item[k].val); /*byte*/
+		}
+
+		/*show burst type*/
+		for (k = 0; k < ARRAY_SIZE(ttype_burst_list_item); k++) {
+
+			if (ttype_burst_val[i] == ttype_burst_list_item[k].key)
+				ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "_%s",
+						     ttype_burst_list_item[k].val); /*burst*/
+		}
+
+		/*show rw type*/
+		for (k = 0; k < ARRAY_SIZE(ttype_rw_list_item); k++) {
+
+			if (ttype_rw_val[i] == ttype_rw_list_item[k].key)
+				ret_m[i] += snprintf(ttype_name[i] + ret_m[i], TTYPE_NAME_STR_LEN - ret_m[i], "_%s",
+						     ttype_rw_list_item[k].val); /*rw*/
+		}
+	}
+#endif
+
+	if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+		/* master selection header */
+		if (msel_enable) {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+					msel_group1 & BM_MASTER_ALL,
+					msel_group2 & BM_MASTER_ALL,
+					msel_group3 & BM_MASTER_ALL);
+		} else {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+					BM_MASTER_ALL & BM_MASTER_ALL,
+					BM_MASTER_ALL & BM_MASTER_ALL,
+					BM_MASTER_ALL & BM_MASTER_ALL);
+		}
+	} else {
+		/*ttype master if BM_TTYPE1_16_ENABLE or emi_TP_busfiltr_enable*/
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: met_emi_ttype_master: %x,%x,%x,%x\n",
+				ttype_master_val[0], ttype_master_val[1], ttype_master_val[2], ttype_master_val[3]);
+
+		if (emi_TP_busfiltr_enable == 1) {
+			/* busID if emi_TP_busfiltr_enable*/
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"met-info [000] 0.0: met_emi_ttype_busid: %x,%x,%x,%x\n",
+					ttype_busid_val[0], ttype_busid_val[1], ttype_busid_val[2], ttype_busid_val[3]);
+		}
+	}
+
+	/*RW type header*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_rw_cfg: ");
+	if (rwtype == BM_READ_ONLY)
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "R");
+	else if (rwtype == BM_WRITE_ONLY)
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "W");
+	else
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "BOTH");
+
+	for (i = 0; i < 21; i++) {
+		if (ttype_rw_val[i] == BM_TRANS_RW_DEFAULT)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",DEFAULT");
+		else if (ttype_rw_val[i] == BM_TRANS_RW_READONLY)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",R");
+		else if (ttype_rw_val[i] == BM_TRANS_RW_WRITEONLY)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",W");
+		else    /*BM_TRANS_RW_RWBOTH*/
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",BOTH");
+	}
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+	/*ultra header*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_emi_ultra_filter: %x\n", high_priority_filter);
+
+#if 0
+	/*ttype header (user define format)*/
+	if ((ttype1_16_en == BM_TTYPE1_16_ENABLE) && (ttype17_21_en == BM_TTYPE17_21_ENABLE)) {
+		/*header = ttype1~21t*/
+		int i;
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ms_ud_sys_header: ms_ttype,");
+		for (i = 0; i < 21; i++)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_name[i]);
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x\n");
+
+	} else if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+		/*header = ttype17~21t*/
+		int i;
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ms_ud_sys_header: ms_ttype,");
+
+		for (i = 16; i < 21; i++)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_name[i]);
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "x,x,x,x,x\n");
+	}
+#else
+#if 1
+	/* ttype header */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+		int i = 0;
+		int j = 0;
+
+		/* ttype master list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_master_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_master_list_item); j++) {
+				if (ttype_master_val[i] == ttype_master_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_master_list_item[j].val);
+				}
+			}
+		}
+		/* remove the last comma */
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype busid list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_busid_list: ");
+		for (i = 0; i < 21; i++)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,", ttype_busid_val[i]);
+
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype nbeat list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_nbeat_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_nbeat_list_item); j++) {
+				if (ttype_nbeat_val[i] == ttype_nbeat_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,", ttype_nbeat_list_item[j].val);
+				}
+			}
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype nbyte list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_nbyte_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_nbyte_list_item); j++) {
+				if (ttype_nbyte_val[i] == ttype_nbyte_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,", ttype_nbyte_list_item[j].val);
+				}
+			}
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype burst list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_burst_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_burst_list_item); j++) {
+				if (ttype_burst_val[i] == ttype_burst_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_burst_list_item[j].val);
+				}
+			}
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype enable */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_enable: %d,%d\n",ttype1_16_en, ttype17_21_en);
+
+
+	}
+#endif
+#endif
+	/*IP version*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: DRAMC_VER: %d\n", DRAMC_VER);
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: EMI_VER: %d.%d\n", EMI_VER_MAJOR, EMI_VER_MINOR);
+
+#if 1 /* move to AP side print header */
+//#ifndef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
+	dram_chann_num = MET_EMI_GetDramChannNum();
+	/*	met_dram_chann_num_header
+	 *	channel number
+	 *	LP4: 2, LP3: 1
+	 */
+
+	/*
+	 *	the ddr type define :
+	 *	enum DDRTYPE {
+	 *	TYPE_LPDDR3 = 1,
+	 *	TYPE_LPDDR4,
+	 *	TYPE_LPDDR4X,
+	 *	TYPE_LPDDR2
+	 *	};
+	 */
+	if (get_ddr_type_symbol) {
+		DRAM_TYPE = get_ddr_type_symbol();
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_type: %d\n", DRAM_TYPE);
+
+		if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+					dram_chann_num, DRAM_EMI_BASECLOCK_RATE_LP4,
+					DRAM_IO_BUS_WIDTH_LP4, DRAM_DATARATE);
+		else
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+					dram_chann_num, DRAM_EMI_BASECLOCK_RATE_LP3,
+					DRAM_IO_BUS_WIDTH_LP3, DRAM_DATARATE);
+	} else
+		METERROR("[%s][%d]get_ddr_type_symbol = NULL , use the TYPE_LPDDR3 setting\n", __func__, __LINE__);
+
+	/* metemi_func_opt for middleware */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: metemi_func_opt_header: %d\n",
+			metemi_func_opt);
+
+	/* met_emi_clockrate */
+	if (get_dram_data_rate_symbol) {
+		dram_data_rate_MHz = get_dram_data_rate_symbol();
+	} else {
+		METERROR("get_dram_data_rate_symbol = NULL\n");
+		dram_data_rate_MHz = 0;
+	}
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_dram_clockrate: %d\n",
+			dram_data_rate_MHz);
+
+	/* 1 : by ondiemet, 0: by pure linux */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: emi_use_ondiemet: %u\n",
+			emi_use_ondiemet);
+
+	/*dram bank num*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_dram_rank_num_header: %u,%u\n", MET_EMI_GetDramRankNum(),
+				MET_EMI_GetDramRankNum());
+
+	/* ms_emi header */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"# ms_emi: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+	for (i = 0; i < dram_chann_num; i++) {
+		if (i != 0)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					",");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"read_bytes_%d,write_bytes_%d", i, i);
+	}
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_emi_header: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+	for (i = 0; i < dram_chann_num; i++) {
+		if (i != 0)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					",");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"read_bytes_%d,write_bytes_%d", i, i);
+	}
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+	/*TSCT header*/
+	if (emi_tsct_enable == 1) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: ms_emi_tsct_header: ms_emi_tsct,");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"tsct1,tsct2,tsct3\n");
+	}
+
+	/*MDCT header*/
+	if (emi_mdct_enable == 1) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: ms_emi_mdct_header: ms_emi_mdct,");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"RD_ULTRA,RD_MDMCU\n");
+	}
+
+	/* met_bw_limiter_header */
+	if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: met_bw_limiter_header: CLK,");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"ARBA,ARBB,ARBC,ARBD,ARBE,ARBF,ARBG,ARBH,BWCT0,BWCT1,BWCT2,BWCT3,BWCT4,BWST0,BWST1,BWCT0_2ND,BWCT1_2ND,BWST_2ND\n");
+	}
+
+	/* DRAM DVFS header */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: DRAM_DVFS_header: datarate(MHz)\n");
+
+	/*PDIR met_dramc_header*/
+	if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 ) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: met_dramc_header: ");
+		for (i = 0; i < dram_chann_num; i++) {
+			if (i != 0)
+				ret += snprintf(buf + ret, PAGE_SIZE - ret,
+						",");
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "freerun_26m_%d,", i);
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"rk0_pre_sb_%d,rk0_pre_pd_%d,rk0_act_sb_%d,rk0_act_pd_%d,", i, i, i, i);
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"rk1_pre_sb_%d,rk1_pre_pd_%d,rk1_act_sb_%d,rk1_act_pd_%d,", i, i, i, i);
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"rk2_pre_sb_%d,rk2_pre_pd_%d,rk2_act_sb_%d,rk2_act_pd_%d", i, i, i, i);
+		}
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+	}
+
+	/* DRS header */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: emi_drs_header: ch0_RANK1_GP(%%),ch0_RANK1_SF(%%),ch0_ALL_SF(%%),ch1_RANK1_GP(%%),ch1_RANK1_SF(%%),ch1_ALL_SF(%%)\n");
+#endif
+
+	return ret;
+}
+
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+static int ondiemet_emi_print_header(char *buf, int len)
+{
+	emi_use_ondiemet = 1;
+	/* return emi_print_ondiemet_header(buf, len); */
+	return emi_print_header(buf, len);
+}
+
+
+static void MET_BM_IPI_REGISTER_CB(void)
+{
+	int ret, i;
+	unsigned int rdata;
+	unsigned int ipi_buf[4];
+
+	for (i = 0; i < 4; i++)
+		ipi_buf[i] = 0;
+
+	if (sspm_buf_available == 1) {
+		ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_REGISTER_CB;
+		ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+	}
+}
+
+
+static void MET_BM_IPI_configs(void)
+{
+	int ret, i;
+	unsigned int rdata;
+	unsigned int ipi_buf[4];
+
+	for (i = 0; i < 4; i++)
+		ipi_buf[i] = 0;
+
+	if (sspm_buf_available == 1) {
+		ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_EBM_CONFIGS1;
+		ipi_buf[1] = INTERNAL_MODE << 16;
+		ipi_buf[2] = EMI_VER_MAJOR << 24 | EMI_VER_MINOR << 16 | DRAMC_VER << 8 | 0;
+		ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+	}
+}
+
+
+static void ondiemet_emi_start(void)
+{
+	MET_BM_IPI_REGISTER_CB();
+	if (!emi_inited) {
+		if (MET_BM_Init() != 0) {
+			met_emi.mode = 0;
+			pr_notice("MET_BM_Init failed!!!\n");
+			return;
+		}
+		emi_inited = 1;
+	}
+	MET_BM_IPI_configs();
+
+	if (do_emi())
+		emi_init();
+
+	ondiemet_module[ONDIEMET_SSPM] |= ID_EMI;
+}
+
+
+static void ondiemet_emi_stop(void)
+{
+	if (!emi_inited)
+		return;
+
+	if (do_emi())
+		emi_uninit();
+}
+#endif
+
+
+struct metdevice met_emi = {
+	.name			= "emi",
+	.owner			= THIS_MODULE,
+	.type			= MET_TYPE_BUS,
+	.create_subfs		= met_emi_create,
+	.delete_subfs		= met_emi_delete,
+	.cpu_related		= 0,
+	.start			= met_emi_start,
+	.stop			= met_emi_stop,
+	.resume			= met_emi_resume,
+	.timed_polling		= met_emi_polling,
+	.print_help		= emi_print_help,
+	.print_header		= emi_print_header,
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+	.ondiemet_mode		= 1,
+	.ondiemet_start		= ondiemet_emi_start,
+	.ondiemet_stop		= ondiemet_emi_stop,
+	.ondiemet_print_help	= emi_print_help,
+	.ondiemet_print_header	= ondiemet_emi_print_header,
+#else
+	.ondiemet_mode		= 0,
+#endif
+};
diff --git a/src/devtools/met-driver/4.14/mt2731/emi/SEDA3/mtk_emi_bm.c b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3/mtk_emi_bm.c
new file mode 100644
index 0000000..a77be27
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3/mtk_emi_bm.c
@@ -0,0 +1,1067 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <mt-plat/sync_write.h>
+#include <mt-plat/mtk_io.h>
+#include "mtk_typedefs.h"
+#include "plf_init.h"
+#include "mtk_emi_bm.h"
+#include "mtk_dramc_reg.h"
+#include "met_drv.h"
+#include "interface.h"
+
+#undef	DEBUG
+#undef	debug_reg
+#ifdef	debug_reg
+static inline unsigned int emi_readl(void __iomem *padr)
+{
+	unsigned int tmp;
+
+	tmp = readl(padr);
+	MET_TRACE("[MET_EMI] RD_Reg: %p: %08x\n", padr, tmp);
+	return tmp;
+}
+
+static inline void __emi_reg_sync_writel(unsigned int data, void __iomem *padr)
+{
+	unsigned int tmp;
+
+	mt_reg_sync_writel(data, padr);
+	tmp = readl(padr);
+	MET_TRACE("[MET_EMI] WR_Reg: %p: %08x, %08x\n", padr, data, tmp);
+}
+
+#define emi_reg_sync_writel(data, adr)  __emi_reg_sync_writel(data, IOMEM(adr))
+
+#else
+#define emi_readl               readl
+#define emi_reg_sync_writel     mt_reg_sync_writel
+#endif
+
+#define MASK_MASTER     0xFF
+#define MASK_TRANS_TYPE 0xFF
+
+static int dram_chann_num;
+static void __iomem *BaseAddrEMI;
+static void __iomem *BaseAddrCHN_EMI[2];
+
+static int dramc0_dcm_enable;
+static int dramc1_dcm_enable;
+
+#define CH0_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[0]) + 0x284)
+#define CH1_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[1]) + 0x284)
+const unsigned int emi_config[] = {
+	EMI_BMEN,
+	EMI_MSEL,
+	EMI_MSEL2,
+	EMI_MSEL3,
+	EMI_MSEL4,
+	EMI_MSEL5,
+	EMI_MSEL6,
+	EMI_MSEL7,
+	EMI_MSEL8,
+	EMI_MSEL9,
+	EMI_MSEL10,
+	EMI_BMID0,
+	EMI_BMID1,
+	EMI_BMID2,
+	EMI_BMID3,
+	EMI_BMID4,
+	EMI_BMID5,
+	EMI_BMID6,
+	EMI_BMID7,
+	EMI_BMID8,
+	EMI_BMID9,
+	EMI_BMID10,
+	EMI_BMEN1,
+	EMI_BMEN2,
+	EMI_BMRW0,
+	EMI_BMRW1
+};
+#define EMI_CONFIG_MX_NR (sizeof(emi_config)/sizeof(unsigned int))
+static unsigned int emi_config_val[EMI_CONFIG_MX_NR];
+
+/*
+ *   MET_REG_BSET/MET_REG_BCLR:
+ *   reading value before set and clear
+ */
+static inline void MET_REG_BSET(unsigned long reg, u32 shift)
+{
+	unsigned int read_val = 0;
+
+	read_val = emi_readl(IOMEM(reg));
+	emi_reg_sync_writel(read_val | (1 << shift), reg);
+}
+
+
+static inline void MET_REG_BCLR(unsigned long reg, u32 shift)
+{
+	unsigned int read_val = 0;
+
+	read_val = emi_readl(IOMEM(reg));
+	emi_reg_sync_writel(read_val & (~((1 << shift) & 0xFFFFFFFF)), reg);
+}
+
+
+int MET_BM_Init(void)
+{
+	int i;
+	int idx;
+
+	/*emi*/
+	if (!mt_cen_emi_base_get_symbol) {
+		METERROR("[%d]mt_cen_emi_base_get_symbol = NULL\n", __LINE__);
+		PR_BOOTMSG_ONCE("[%d]mt_cen_emi_base_get_symbol = NULL\n", __LINE__);
+		return -1;
+	}
+
+	BaseAddrEMI = mt_cen_emi_base_get_symbol();
+	if (BaseAddrEMI == 0) {
+		METERROR("BaseAddrEMI = 0\n");
+		PR_BOOTMSG_ONCE("BaseAddrEMI = 0\n");
+		return -1;
+	}
+
+	METINFO("MET EMI: map emi to %p\n", BaseAddrEMI);
+	PR_BOOTMSG("MET EMI: map emi to %p\n", BaseAddrEMI);
+
+	/* get dram channel number */
+	dram_chann_num = MET_EMI_GetDramChannNum();
+	METINFO("[%s][%d]dram_chann_num = %d\n", __func__, __LINE__, dram_chann_num);
+
+	if (dram_chann_num > MAX_DRAMC_CHANN) {
+		METERROR("dram_chann_num %d > %d\n", dram_chann_num, MAX_DRAMC_CHANN);
+		PR_BOOTMSG("dram_chann_num %d > %d\n", dram_chann_num, MAX_DRAMC_CHANN);
+		return -1;
+	}
+
+	if (!mt_dramc_nao_chn_base_get_symbol) {
+		METERROR("mt_dramc_nao_cha_base_get = NULL\n");
+		PR_BOOTMSG_ONCE("mt_dramc_nao_cha_base_get = NULL\n");
+		return -1;
+	}
+
+	for (i = 0; i < dram_chann_num; i++) {
+		BaseAddrDRAMC[i] = mt_dramc_nao_chn_base_get_symbol(i);
+		if (BaseAddrDRAMC[i] == 0) {
+			METERROR("BaseAddrDRAMC%d = 0\n", i);
+			PR_BOOTMSG_ONCE("BaseAddrDRAMC%d = 0\n", i);
+			return -1;
+		}
+
+		METINFO("MET EMI: map nao dramc%c to %p\n",'A'+i, BaseAddrDRAMC[i]);
+		PR_BOOTMSG("MET EMI: map nao dramc%c to %p\n", 'A'+i, BaseAddrDRAMC[i]);
+	}
+
+	/*dram DRAMC_DTS_DDRPHY_AO*/
+	/* get DRS base address */
+	if (!mt_ddrphy_chn_base_get_symbol) {
+		METERROR("mt_ddrphy_chn_base_get = NULL\n");
+		PR_BOOTMSG_ONCE("mt_ddrphy_chn_base_get = NULL\n");
+		return -1;
+	}
+
+	if (!mt_chn_emi_base_get_symbol) {
+		METERROR("mt_chn_emi_base_get_symbol = NULL\n");
+		PR_BOOTMSG_ONCE("mt_chn_emi_base_get_symbol = NULL\n");
+		return -1;
+	}
+
+	for (i = 1; i <= dram_chann_num && i < 3; i++) {
+		idx = i - 1;
+		BaseAddrDDRPHY_AO[idx] = mt_ddrphy_chn_base_get_symbol(idx);
+		if (BaseAddrDDRPHY_AO[idx] == 0) {
+			METERROR("BaseAddrDDRPHY_AO[%d] = 0\n", idx);
+			PR_BOOTMSG_ONCE("BaseAddrDDRPHY_AO[%d] = 0\n", idx);
+			return -1;
+		}
+
+		METINFO("MET EMI: map ddrphy%d AO to %p\n", idx, BaseAddrDDRPHY_AO[idx]);
+		PR_BOOTMSG("MET EMI: map ddrphy%d AO to %p\n", idx, BaseAddrDDRPHY_AO[idx]);
+
+		BaseAddrCHN_EMI[idx] = mt_chn_emi_base_get_symbol(idx);
+		if (BaseAddrCHN_EMI[idx] == 0) {
+			METERROR("BaseAddrCHN_EMI[%d] = 0\n", idx);
+			PR_BOOTMSG_ONCE("BaseAddrCHN_EMI[%d] = 0\n", idx);
+			return -1;
+		}
+
+		METINFO("MET EMI: map BaseAddrCHN_EMI[%d] to %p\n", idx, BaseAddrCHN_EMI[idx]);
+		PR_BOOTMSG("MET EMI: map BaseAddrCHN_EMI[%d] to %p\n", idx, BaseAddrCHN_EMI[idx]);
+	}
+
+	/*dram DRAMC_DTS_DRAMC0_AO*/
+	if (!mt_dramc_chn_base_get_symbol) {
+		METERROR("mt_dramc_chn_base_get = NULL\n");
+		PR_BOOTMSG_ONCE("mt_dramc_chn_base_get = NULL\n");
+		return -1;
+	}
+
+	BaseAddrDRAMC0_AO = mt_dramc_chn_base_get_symbol(0);
+	if (BaseAddrDRAMC0_AO == 0) {
+		METERROR("BaseAddrDRAMC0_AO = 0\n");
+		PR_BOOTMSG_ONCE("BaseAddrDRAMC0_AO = 0\n");
+		return -1;
+	}
+
+	METINFO("MET EMI: map AO dramcA to %p\n", BaseAddrDRAMC0_AO);
+	PR_BOOTMSG("MET EMI: map AO dramcA to %p\n", BaseAddrDRAMC0_AO);
+
+	return 0;
+}
+
+
+void MET_BM_DeInit(void)
+{
+}
+
+
+void MET_BM_SaveCfg(void)
+{
+	int i;
+
+	for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+		emi_config_val[i] = emi_readl(IOMEM(ADDR_EMI + emi_config[i]));
+}
+
+
+void MET_BM_RestoreCfg(void)
+{
+	int i;
+
+	for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+		emi_reg_sync_writel(emi_config_val[i], ADDR_EMI + emi_config[i]);
+}
+
+
+void MET_BM_Clear_Start(void)
+{
+	/* Force EMI idle low */
+	MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+	/* Disable dramc dcm */
+	switch (dram_chann_num) {
+	case 1:
+		MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	case 2:
+		MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	default:
+		METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+	}
+
+	/* Disable EBM */
+	MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+
+	/* Enable EBM */
+	MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+
+	/* Enable EMI dcm */
+	MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+	/* restore dramc dcm */
+	switch (dram_chann_num) {
+	case 1:
+		if (dramc0_dcm_enable)
+			MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		else
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	case 2:
+		if (dramc0_dcm_enable)
+			MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		else
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+
+		if (dramc1_dcm_enable)
+			MET_REG_BCLR(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		else
+			MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	default:
+		METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+	}
+}
+
+
+void MET_BM_Enable(const unsigned int enable)
+{
+	unsigned long int value_check;
+	int i = 0;
+
+	while (i < 100) {
+		/* Force EMI idle low */
+		MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+		/* disable dramc dcm */
+		switch (dram_chann_num) {
+		case 1:
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		case 2:
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		default:
+			METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+		}
+
+		if (enable == 0)
+			/* Disable EBM */
+			MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+		else
+			/* Enable EBM */
+			MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+
+		/* Enable EMI dcm */
+		MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+		/* restore dramc dcm */
+		switch (dram_chann_num) {
+		case 1:
+			if (dramc0_dcm_enable)
+				MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			else
+				MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		case 2:
+			if (dramc0_dcm_enable)
+				MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			else
+				MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+
+			if (dramc1_dcm_enable)
+				MET_REG_BCLR(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			else
+				MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		default:
+			METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+		}
+
+		value_check = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+		if (enable == 0) {
+			/* EN == 0, IDLE == 0 when EMI RESET */
+			if (!test_bit(BUS_MON_EN_SHIFT, &value_check)
+			    && !test_bit(BUS_MON_IDLE_SHIFT, &value_check)) {
+				break;
+			}
+		} else {
+			/* EN == 1, IDLE == 0 when EMI START */
+			if (test_bit(BUS_MON_EN_SHIFT, &value_check)
+			    && !test_bit(BUS_MON_IDLE_SHIFT, &value_check)) {
+				break;
+			}
+		}
+		i++;
+	}
+
+	/*MET_TRACE("[MET_BM_ENABLE] value_check: %lx, enable = %d\n", value_check, enable); */
+
+}
+
+
+#if 0
+void BM_Disable(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	emi_reg_sync_writel(value & (~BUS_MON_EN), ADDR_EMI + EMI_BMEN);
+}
+#endif
+
+
+void MET_BM_Pause(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	emi_reg_sync_writel(value | (1 << BUS_MON_PAUSE_SHIFT), ADDR_EMI + EMI_BMEN);
+}
+
+
+void MET_BM_Continue(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	emi_reg_sync_writel(value & (~(1 << BUS_MON_PAUSE_SHIFT)), ADDR_EMI + EMI_BMEN);
+}
+
+
+unsigned int MET_BM_IsOverrun(void)
+{
+	/*
+	 * return 0 if EMI_BCNT(bus cycle counts) or
+	 * EMI_WACT(total word counts) is overrun,
+	 * otherwise return an !0 value
+	 */
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	return (value & (1 << BC_OVERRUN_SHIFT));
+}
+
+
+unsigned int MET_BM_GetReadWriteType(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	return ((value & 0xFFFFFFCF) >> 4);
+}
+
+
+void MET_BM_SetReadWriteType(const unsigned int ReadWriteType)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	/*
+	 * ReadWriteType: 00/11 --> both R/W
+	 *                   01 --> only R
+	 *                   10 --> only W
+	 */
+	emi_reg_sync_writel((value & 0xFFFFFFCF) | (ReadWriteType << 4), ADDR_EMI + EMI_BMEN);
+}
+
+
+int MET_BM_GetBusCycCount(void)
+{
+	return MET_BM_IsOverrun() ? BM_ERR_OVERRUN : emi_readl(IOMEM(ADDR_EMI + EMI_BCNT));	/*Bus cycle counter */
+}
+
+
+unsigned int MET_BM_GetTransAllCount(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_TACT));
+}
+
+
+int MET_BM_GetTransCount(const unsigned int counter_num)
+{
+	unsigned int iCount;
+
+	switch (counter_num) {
+	case 1:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_TSCT));
+		break;
+
+	case 2:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_TSCT2));
+		break;
+
+	case 3:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_TSCT3));
+		break;
+
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+int MET_BM_GetWordAllCount(void)
+{
+	return MET_BM_IsOverrun() ? BM_ERR_OVERRUN : emi_readl(IOMEM(ADDR_EMI + EMI_WACT));
+}
+
+
+int MET_BM_GetWordCount(const unsigned int counter_num)
+{
+	unsigned int iCount;
+
+	switch (counter_num) {
+	case 1:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT));
+		break;
+
+	case 2:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT2));
+		break;
+
+	case 3:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT3));
+		break;
+
+	case 4:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT4));
+		break;
+
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+unsigned int MET_BM_GetBandwidthWordCount(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BACT));	/*Bandwidth counter for access */
+}
+
+
+unsigned int MET_BM_GetOverheadWordCount(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BSCT));	/*Overhead counter */
+}
+
+
+int MET_BM_GetTransTypeCount(const unsigned int counter_num)
+{
+	return (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+	    ? BM_ERR_WRONG_REQ : emi_readl(IOMEM(ADDR_EMI + EMI_TTYPE1 + (counter_num - 1) * 8));
+}
+
+
+int MET_BM_GetMDCT(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT));
+}
+
+
+int MET_BM_GetMDCT_2(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT_2ND));
+}
+
+
+int MET_BM_SetMDCT_MDMCU(unsigned int mdmcu_rd_buf)
+{
+	unsigned int value_origin;
+
+	value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_MDCT_2ND));
+	MET_TRACE("[MET_BM_SetMDCT_MDMCU] value_origin: %x\n", value_origin);
+
+	value_origin = value_origin & ~(0x7);
+	value_origin = value_origin | ((mdmcu_rd_buf) & 0x7);
+
+	emi_reg_sync_writel(value_origin, ADDR_EMI + EMI_MDCT_2ND);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_GetMonitorCounter(const unsigned int counter_num,
+			     unsigned int *master, unsigned int *trans_type)
+{
+	unsigned int value, addr;
+
+	if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+		return BM_ERR_WRONG_REQ;
+
+
+	if (counter_num == 1) {
+		addr = EMI_BMEN;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+		*master = (value >> 16) & MASK_MASTER;
+		*trans_type = (value >> 24) & MASK_TRANS_TYPE;
+	} else {
+		addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+		value = emi_readl(IOMEM(ADDR_EMI + addr)) >> ((counter_num % 2) * 16);
+		*master = value & MASK_MASTER;
+		*trans_type = (value >> 8) & MASK_TRANS_TYPE;
+	}
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+			     const unsigned int master, const unsigned int trans_type)
+{
+	unsigned int value, addr;
+	const unsigned int iMask = (MASK_TRANS_TYPE << 8) | MASK_MASTER;
+
+	if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+		return BM_ERR_WRONG_REQ;
+
+
+	if (counter_num == 1) {
+		addr = EMI_BMEN;
+		value = (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) |
+		    ((trans_type & MASK_TRANS_TYPE) << 24) | ((master & MASK_MASTER) << 16);
+	} else {
+		addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+		/* clear master and transaction type fields */
+		value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+		/* set master and transaction type fields */
+		value |= (((trans_type & MASK_TRANS_TYPE) << 8) |
+			  (master & MASK_MASTER)) << ((counter_num % 2) * 16);
+	}
+
+	emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val)
+{
+
+	unsigned int value_origin;
+
+	value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW0));
+	MET_TRACE("[MET_EMI_settype1] value_origin: %x\n", value_origin);
+	if (value_origin != bmrw0_val) {
+		emi_reg_sync_writel(bmrw0_val, ADDR_EMI + EMI_BMRW0);
+		MET_TRACE("[MET_EMI_settype1] bmrw0_val: %x, value_origin: %x\n", bmrw0_val,
+			   value_origin);
+	}
+
+
+	value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW1));
+	MET_TRACE("[MET_EMI_settype2] value_origin: %x\n", value_origin);
+	if (value_origin != bmrw1_val) {
+		emi_reg_sync_writel(bmrw1_val, ADDR_EMI + EMI_BMRW1);
+		MET_TRACE("[MET_EMI_settype2] bmrw0_val: %x, value_origin: %x\n", bmrw1_val,
+			   value_origin);
+
+	}
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable)
+{
+	unsigned int value;
+
+	if (counter_num > 3)
+		return BM_ERR_WRONG_REQ;
+
+	value =
+	    ((emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & (~(1 << (28 + counter_num)))) |
+	     (enable << (28 + counter_num)));
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master)
+{
+	unsigned int value, addr;
+	const unsigned int iMask = 0x7F;
+
+	if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+		return BM_ERR_WRONG_REQ;
+
+
+	if (counter_num == 1) {
+		addr = EMI_BMEN;
+		value =
+		    (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) | ((master & iMask) << 16);
+	} else {
+		addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+		/* clear master and transaction type fields */
+		value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+		/* set master and transaction type fields */
+		value |= ((master & iMask) << ((counter_num % 2) * 16));
+	}
+
+	emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID_En(const unsigned int counter_num,
+		       const unsigned int enable)
+{
+	unsigned int value;
+
+	if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+		return BM_ERR_WRONG_REQ;
+
+	if (enable == 0) {
+		/* clear  EMI ID selection Enabling   SEL_ID_EN */
+		value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+			 & ~(1 << (counter_num - 1)));
+	} else {
+		/* enable  EMI ID selection Enabling   SEL_ID_EN */
+		value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+			 | (1 << (counter_num - 1)));
+	}
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID(const unsigned int counter_num,
+		    const unsigned int id)
+{
+	unsigned int value, addr, shift_num;
+
+	if ((counter_num < 1 || counter_num > BM_COUNTER_MAX))
+		return BM_ERR_WRONG_REQ;
+
+	/* offset of EMI_BMIDx register */
+	addr = EMI_BMID0 + (counter_num - 1) / 2 * 4;
+	shift_num = ((counter_num - 1) % 2) * 16;
+	/* clear SELx_ID field */
+	value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(EMI_BMID_MASK << shift_num);
+
+	/* set SELx_ID field */
+	if (id <= 0xffff)       /*bigger then 0xff_ff : no select busid in master, reset busid as 0*/
+		value |= id << shift_num;
+
+	emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable)
+{
+	unsigned int value;
+
+	if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+		return BM_ERR_WRONG_REQ;
+
+
+	value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN1))
+		 & ~(1 << (counter_num - 1)))
+		| (enable << (counter_num - 1));
+
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN1);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetLatencyCounter(unsigned int enable)
+{
+	unsigned int value;
+
+	value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & ~(0x3 << 24);
+	/*
+	 * emi_ttype1 -- emi_ttype8 change as total latencies
+	 * for m0 -- m7,
+	 * and emi_ttype9 -- emi_ttype16 change as total transaction counts
+	 * for m0 -- m7
+	 */
+	if (enable == 1)
+		value |= (0x2 << 24);
+
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_GetLatencyCycle(unsigned int *__restrict__ emi_value,
+				const unsigned int begin, const unsigned int end)
+{
+	int i, j = 0;
+
+	for (i = begin - 1; i < end; i++)
+		emi_value[j++] = emi_readl(IOMEM(ADDR_EMI + (EMI_TTYPE1 + i * 8)));
+
+	return j;
+}
+
+
+unsigned int MET_BM_GetEmiDcm(void)
+{
+	return (emi_readl(IOMEM(ADDR_EMI + EMI_CONM)) >> 24);
+}
+
+
+int MET_BM_SetEmiDcm(const unsigned int setting)
+{
+	unsigned int value;
+
+	value = emi_readl(IOMEM(ADDR_EMI + EMI_CONM));
+	emi_reg_sync_writel((value & 0x00FFFFFF) | (setting << 24), ADDR_EMI + EMI_CONM);
+
+	return BM_REQ_OK;
+}
+
+
+unsigned int MET_EMI_GetMDCT(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT));
+}
+
+
+unsigned int MET_EMI_GetMDCT_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT_2ND));
+}
+
+
+unsigned int MET_EMI_GetARBA(void)
+{
+	/* EMI_ARBA EMI Bandwidth Filter Control M0/1 */
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBA));
+}
+
+
+unsigned int MET_EMI_GetARBB(void)
+{
+	/* need the ATBB for mt6739 */
+	return emi_readl(IOMEM(ADDR_EMI+EMI_ARBB));
+}
+
+
+unsigned int MET_EMI_GetARBC(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBC));
+}
+
+
+unsigned int MET_EMI_GetARBD(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBD));
+}
+
+
+unsigned int MET_EMI_GetARBE(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBE));
+}
+
+
+unsigned int MET_EMI_GetARBF(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBF));
+}
+
+
+unsigned int MET_EMI_GetARBG(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBG));
+}
+
+
+unsigned int MET_EMI_GetARBH(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBH));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT0(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT0));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT1(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT1));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT2(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT2));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT3(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT3));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT4(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT4));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWST0(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWST0));
+}
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWST1(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWST1));
+}
+
+
+/* C+G BW status*/
+unsigned int MET_EMI_GetBWCT0_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT0_2ND));
+}
+
+/* C+G BW status*/
+unsigned int MET_EMI_GetBWCT1_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT1_2ND));
+}
+
+
+/* C+G BW status*/
+unsigned int MET_EMI_GetBWST_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWST_2ND));
+}
+
+
+unsigned int MET_EMI_GetBMRW0(void)
+{
+	return readl(IOMEM(ADDR_EMI + EMI_BMRW0));
+}
+
+
+void emi_dump_reg(void)
+{
+	int i;
+
+	MET_TRACE("[emi_regdump]\n");
+	for (i = 0x400; i < 0x500; i = i + 16)
+		MET_TRACE("%4x__ %8x %8x %8x %8x\n", i, readl(IOMEM(ADDR_EMI + i)),
+			   readl(IOMEM(ADDR_EMI + i + 4)), readl(IOMEM(ADDR_EMI + i + 8)),
+			   readl(IOMEM(ADDR_EMI + i + 12)));
+}
+
+
+unsigned int MET_EMI_GetDramChannNum(void)
+{
+	int num = -1;
+
+	if (BaseAddrEMI) {
+		num = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+		num = ((num >> 8) & 0x0000003);
+	} else {
+		return 1;
+	}
+
+	if (num == M0_DOUBLE_HALF_BW_1CH)
+		return 1;
+	else if (num == M0_DOUBLE_HALF_BW_2CH)
+		return 2;
+	else if (num == M0_DOUBLE_HALF_BW_4CH)
+		return 4;
+	else                    /* default return single channel */
+		return 1;
+}
+
+
+unsigned int MET_EMI_GetDramRankNum(void)
+{
+	int dual_rank = 0;
+
+	if (BaseAddrEMI) {
+		dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+		dual_rank = ((dual_rank >> 17) & RANK_MASK);
+	} else {
+		return DUAL_RANK;
+	}
+
+	if (dual_rank == DISABLE_DUAL_RANK_MODE)
+		return ONE_RANK;
+	else			/* default return dual rank */
+		return DUAL_RANK;
+}
+
+
+/*
+ * Dual Channel:
+ * Enables two rank for CHB
+ * Quad Channel:
+ * Enables two rank  for CHC and CHD
+ * 0: Disable dual rank mode
+ * 1: Enable dual rank mode
+ */
+unsigned int MET_EMI_GetDramRankNum_CHN1(void)
+{
+	int dual_rank = 0;
+
+	if (BaseAddrEMI) {
+		dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+		dual_rank = ((dual_rank >> 16) & RANK_MASK);
+	} else {
+		return DUAL_RANK;
+	}
+
+	if (dual_rank == DISABLE_DUAL_RANK_MODE)
+		return ONE_RANK;
+	else			/* default return dual rank */
+		return DUAL_RANK;
+}
+
+
+void met_get_drs_registers(uint32_t *value)
+{
+	uint32_t tmp;
+
+	memset(value, 0, sizeof(uint32_t) * 6);
+
+	if (BaseAddrCHN_EMI[0] == NULL)
+		return;
+	if (dram_chann_num > 1 && BaseAddrCHN_EMI[1] == NULL)
+		return;
+
+	tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[0] + CHN_EMI_DRS_ST2)) & ((1 << 23) - 1);
+	/* working unit:38.5ns, the counter is update every 16ms */
+	value[0] = (tmp * 3850) / 16000000;
+
+	tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[0] + CHN_EMI_DRS_ST3)) & ((1 << 23) - 1);
+	value[1] = (tmp * 3850) / 16000000;
+
+	tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[0] + CHN_EMI_DRS_ST4)) & ((1 << 23) - 1);
+	value[2] = (tmp * 3850) / 16000000;
+
+	if (dram_chann_num > 1) {
+		tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[1] + CHN_EMI_DRS_ST2)) & ((1 << 23) - 1);
+		value[3] = (tmp * 3850) / 16000000;
+
+		tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[1] + CHN_EMI_DRS_ST3)) & ((1 << 23) - 1);
+		value[4] = (tmp * 3850) / 16000000;
+
+		tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[1] + CHN_EMI_DRS_ST4)) & ((1 << 23) - 1);
+		value[5] = (tmp * 3850) / 16000000;
+	}
+}
+
+
+void met_record_dramc_dcm_enable_flag(void)
+{
+	int reg_val;
+
+	switch (dram_chann_num) {
+	case 1:
+		reg_val = emi_readl(IOMEM(CH0_MISC_CG_CTRL0));
+		dramc0_dcm_enable = !((reg_val >> DRAMC_CG_SHIFT) & 0x1);
+		break;
+	case 2:
+		reg_val = emi_readl(IOMEM(CH0_MISC_CG_CTRL0));
+		dramc0_dcm_enable = !((reg_val >> DRAMC_CG_SHIFT) & 0x1);
+
+		reg_val = emi_readl(IOMEM(CH1_MISC_CG_CTRL0));
+		dramc1_dcm_enable = !((reg_val >> DRAMC_CG_SHIFT) & 0x1);
+		break;
+	default:
+		METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+	}
+}
diff --git a/src/devtools/met-driver/4.14/mt2731/emi/SEDA3/mtk_emi_bm.h b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3/mtk_emi_bm.h
new file mode 100644
index 0000000..1a7a632
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3/mtk_emi_bm.h
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MT_MET_EMI_BM_H__
+#define __MT_MET_EMI_BM_H__
+
+#define EMI_VER_MAJOR  3
+#define EMI_VER_MINOR  0
+
+#define DEF_BM_RW_TYPE          (BM_BOTH_READ_WRITE)
+#define NTS                     2
+#define NWSCT                   4
+#define NLATENCY                8
+#define NTRANS                  8
+#define NALL                    (3 + 2 + 1)
+#define NTTYPE                  5
+#define NIDX_EMI                (NTS + NWSCT + NLATENCY + NTRANS + NALL + NTTYPE)
+
+#define NCNT                    9
+#define NCH                     2
+#define NIDX_DRAMC              (NCNT * NCH)
+#define NIDX                            (NIDX_EMI + NIDX_DRAMC)
+
+#define NCLK                    1
+#define NARB                    8
+#define NBW                     10
+#define NIDX_BL                 (NCLK + NARB + NBW)
+
+/* 1000 To Khz and 4x freq & 2x data rate for LPDDR4 */
+/* 1000 To Khz and 2x freq & 2x data rate for LPDDR3*/
+/* TBD: calculate emi clock rate from DRAM DATA RATE */
+
+/*dram baseclock/EMI clock  :	LP4=4	LP3=2	*/
+#define DRAM_EMI_BASECLOCK_RATE_LP4     4
+#define DRAM_EMI_BASECLOCK_RATE_LP3     2
+/*dram io width  :	LP4=x16		LP3=x32 */
+#define DRAM_IO_BUS_WIDTH_LP4           16
+#define DRAM_IO_BUS_WIDTH_LP3           32
+/*dram datarate  :	DDR=double */
+#define DRAM_DATARATE   2
+
+#define ADDR_EMI        ((unsigned long)BaseAddrEMI)
+
+static const char of_emi_desc[] = "mediatek,emi";
+static const char of_chn_emi_desc[] = "mediatek,chn_emi";
+static const char of_dramc_desc[] = "mediatek,dramc";
+
+#define BM_MASTER_M0            (0x01)
+#define BM_MASTER_M1            (0x02)
+#define BM_MASTER_M2            (0x04)
+#define BM_MASTER_M3            (0x08)
+#define BM_MASTER_M4            (0x10)
+#define BM_MASTER_M5            (0x20)
+#define BM_MASTER_M6            (0x40)
+#define BM_MASTER_M7            (0x80)
+#define BM_MASTER_ALL           (0xFF)
+
+
+enum BM_RW_Type {
+	BM_BOTH_READ_WRITE,
+	BM_READ_ONLY,
+	BM_WRITE_ONLY
+};
+
+enum {
+	BM_TRANS_TYPE_1BEAT = 0x0,
+	BM_TRANS_TYPE_2BEAT,
+	BM_TRANS_TYPE_3BEAT,
+	BM_TRANS_TYPE_4BEAT,
+	BM_TRANS_TYPE_5BEAT,
+	BM_TRANS_TYPE_6BEAT,
+	BM_TRANS_TYPE_7BEAT,
+	BM_TRANS_TYPE_8BEAT,
+	BM_TRANS_TYPE_9BEAT,
+	BM_TRANS_TYPE_10BEAT,
+	BM_TRANS_TYPE_11BEAT,
+	BM_TRANS_TYPE_12BEAT,
+	BM_TRANS_TYPE_13BEAT,
+	BM_TRANS_TYPE_14BEAT,
+	BM_TRANS_TYPE_15BEAT,
+	BM_TRANS_TYPE_16BEAT,
+	BM_TRANS_TYPE_1Byte = 0 << 4,
+	BM_TRANS_TYPE_2Byte = 1 << 4,
+	BM_TRANS_TYPE_4Byte = 2 << 4,
+	BM_TRANS_TYPE_8Byte = 3 << 4,
+	BM_TRANS_TYPE_16Byte = 4 << 4,
+	BM_TRANS_TYPE_32Byte = 5 << 4,
+	BM_TRANS_TYPE_BURST_WRAP = 0 << 7,
+	BM_TRANS_TYPE_BURST_INCR = 1 << 7
+};
+
+enum {
+	BM_TRANS_RW_DEFAULT = 0x0,
+	BM_TRANS_RW_READONLY,
+	BM_TRANS_RW_WRITEONLY,
+	BM_TRANS_RW_RWBOTH
+};
+
+
+/*coda busid 12bit, but HW support 16 bit*/
+#define EMI_BMID_MASK				(0xFFFF)
+#define BM_COUNTER_MAX				(21)
+
+/*
+*#define BUS_MON_EN		(0x00000001)
+*#define BUS_MON_PAUSE		(0x00000002)
+*#define BUS_MON_IDLE		(0x00000008)
+*#define BC_OVERRUN		(0x00000100)
+*/
+enum {
+	BUS_MON_EN_SHIFT = 0,
+	BUS_MON_PAUSE_SHIFT = 1,
+	BUS_MON_IDLE_SHIFT = 3,
+	BC_OVERRUN_SHIFT = 8,
+	DRAMC_CG_SHIFT = 9,
+};
+
+#define BM_REQ_OK				(0)
+#define BM_ERR_WRONG_REQ			(-1)
+#define BM_ERR_OVERRUN				(-2)
+
+#define BM_WSCT_TSCT_IDSEL_ENABLE		(0)
+#define BM_WSCT_TSCT_IDSEL_DISABLE		(-1)
+#define BM_TTYPE1_16_ENABLE			(0)
+#define BM_TTYPE1_16_DISABLE			(-1)
+#define BM_TTYPE17_21_ENABLE			(0)
+#define BM_TTYPE17_21_DISABLE			(-1)
+#define BM_BW_LIMITER_ENABLE			(0)
+#define BM_BW_LIMITER_DISABLE			(-1)
+
+#define M0_DOUBLE_HALF_BW_1CH	(0x0)
+#define M0_DOUBLE_HALF_BW_2CH	(0x1)
+#define M0_DOUBLE_HALF_BW_4CH	(0x2)
+
+/* EMI Rank configuration */
+enum {
+	DISABLE_DUAL_RANK_MODE = 0,
+	ENABLE_DUAL_RANK_MODE,
+};
+
+#define RANK_MASK 0x1
+#define ONE_RANK 1
+#define DUAL_RANK 2
+
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+/*ondiemet emi ipi command*/
+enum BM_EMI_IPI_Type {
+	SET_BASE_EMI = 0x0,
+	SET_BASE_DRAMC0,
+	SET_BASE_DRAMC1,
+	SET_BASE_DRAMC2,
+	SET_BASE_DRAMC3,
+	SET_BASE_DDRPHY0AO,
+	SET_BASE_DRAMC0_AO,
+	SET_EBM_CONFIGS1,
+	SET_EBM_CONFIGS2,
+	SET_REGISTER_CB,
+};
+#endif
+
+
+#define	EMI_OFF			0x0000
+#define EMI_CONA		(0x000-EMI_OFF)
+#define EMI_CONH		(0x038-EMI_OFF)
+#define EMI_CONH_2ND		(0x03C-EMI_OFF)
+#define EMI_CONM		(0x060-EMI_OFF)
+#define EMI_CONO		(0x070-EMI_OFF)
+
+#define EMI_MDCT		(0x078 - EMI_OFF)
+#define EMI_MDCT_2ND		(0x07C - EMI_OFF)
+
+#define EMI_ARBA		(0x100 - EMI_OFF)
+#define EMI_ARBB		(0x108 - EMI_OFF)
+#define EMI_ARBC		(0x110 - EMI_OFF)
+#define EMI_ARBD		(0x118 - EMI_OFF)
+#define EMI_ARBE		(0x120 - EMI_OFF)
+#define EMI_ARBF		(0x128 - EMI_OFF)
+#define EMI_ARBG		(0x130 - EMI_OFF)
+#define EMI_ARBG_2ND		(0x134 - EMI_OFF)
+#define EMI_ARBH		(0x138 - EMI_OFF)
+
+#define EMI_BMEN		(0x400 - EMI_OFF)
+#define EMI_BCNT		(0x408 - EMI_OFF)
+#define EMI_TACT		(0x410 - EMI_OFF)
+#define EMI_TSCT		(0x418 - EMI_OFF)
+#define EMI_WACT		(0x420 - EMI_OFF)
+#define EMI_WSCT		(0x428 - EMI_OFF)
+#define EMI_BACT		(0x430 - EMI_OFF)
+#define EMI_BSCT		(0x438 - EMI_OFF)
+
+#define EMI_MSEL		(0x440 - EMI_OFF)
+#define EMI_TSCT2		(0x448 - EMI_OFF)
+#define EMI_TSCT3		(0x450 - EMI_OFF)
+#define EMI_WSCT2		(0x458 - EMI_OFF)
+#define EMI_WSCT3		(0x460 - EMI_OFF)
+#define EMI_WSCT4		(0x464 - EMI_OFF)
+#define EMI_MSEL2		(0x468 - EMI_OFF)
+#define EMI_MSEL3		(0x470 - EMI_OFF)
+#define EMI_MSEL4		(0x478 - EMI_OFF)
+#define EMI_MSEL5		(0x480 - EMI_OFF)
+#define EMI_MSEL6		(0x488 - EMI_OFF)
+#define EMI_MSEL7		(0x490 - EMI_OFF)
+#define EMI_MSEL8		(0x498 - EMI_OFF)
+#define EMI_MSEL9		(0x4A0 - EMI_OFF)
+#define EMI_MSEL10		(0x4A8 - EMI_OFF)
+
+#define EMI_BMID0		(0x4B0 - EMI_OFF)
+#define EMI_BMID1		(0x4B4 - EMI_OFF)
+#define EMI_BMID2		(0x4B8 - EMI_OFF)
+#define EMI_BMID3		(0x4BC - EMI_OFF)
+#define EMI_BMID4		(0x4C0 - EMI_OFF)
+#define EMI_BMID5		(0x4C4 - EMI_OFF)
+#define EMI_BMID6		(0x4C8 - EMI_OFF)
+#define EMI_BMID7		(0x4CC - EMI_OFF)
+#define EMI_BMID8		(0x4D0 - EMI_OFF)
+#define EMI_BMID9		(0x4D4 - EMI_OFF)
+#define EMI_BMID10		(0x4D8 - EMI_OFF)
+
+#define EMI_BMEN1		(0x4E0 - EMI_OFF)
+#define EMI_BMEN2		(0x4E8 - EMI_OFF)
+#define EMI_BMRW0		(0x4F8 - EMI_OFF)
+#define EMI_BMRW1		(0x4FC - EMI_OFF)
+#define EMI_TTYPE1		(0x500 - EMI_OFF)
+#define EMI_TTYPE2		(0x508 - EMI_OFF)
+#define EMI_TTYPE3		(0x510 - EMI_OFF)
+#define EMI_TTYPE4		(0x518 - EMI_OFF)
+#define EMI_TTYPE5		(0x520 - EMI_OFF)
+#define EMI_TTYPE6		(0x528 - EMI_OFF)
+#define EMI_TTYPE7		(0x530 - EMI_OFF)
+#define EMI_TTYPE8		(0x538 - EMI_OFF)
+#define EMI_TTYPE9		(0x540 - EMI_OFF)
+#define EMI_TTYPE10		(0x548 - EMI_OFF)
+#define EMI_TTYPE11		(0x550 - EMI_OFF)
+#define EMI_TTYPE12		(0x558 - EMI_OFF)
+#define EMI_TTYPE13		(0x560 - EMI_OFF)
+#define EMI_TTYPE14		(0x568 - EMI_OFF)
+#define EMI_TTYPE15		(0x570 - EMI_OFF)
+#define EMI_TTYPE16		(0x578 - EMI_OFF)
+#define EMI_TTYPE17		(0x580 - EMI_OFF)
+#define EMI_TTYPE18		(0x588 - EMI_OFF)
+#define EMI_TTYPE19		(0x590 - EMI_OFF)
+#define EMI_TTYPE20		(0x598 - EMI_OFF)
+#define EMI_TTYPE21		(0x5A0 - EMI_OFF)
+
+#define EMI_BWCT0		(0x5B0 - EMI_OFF)
+#define EMI_BWCT1		(0x5B4 - EMI_OFF)
+#define EMI_BWCT2		(0x5B8 - EMI_OFF)
+#define EMI_BWCT3		(0x5BC - EMI_OFF)
+#define EMI_BWCT4		(0x5C0 - EMI_OFF)
+#define EMI_BWST0		(0x5C4 - EMI_OFF)
+#define EMI_BWST1		(0x5C8 - EMI_OFF)
+
+#define EMI_BWCT0_2ND		(0x6A0 - EMI_OFF)
+#define EMI_BWCT1_2ND		(0x6A4 - EMI_OFF)
+#define EMI_BWST_2ND		(0x6A8 - EMI_OFF)
+
+
+extern void emi_dump_reg(void);
+extern int MET_BM_Init(void);
+extern void MET_BM_DeInit(void);
+extern void MET_BM_SaveCfg(void);
+extern void MET_BM_RestoreCfg(void);
+extern void MET_BM_Enable(const unsigned int enable);
+extern void MET_BM_Pause(void);
+extern void MET_BM_Continue(void);
+extern unsigned int MET_BM_IsOverrun(void);
+extern unsigned int MET_BM_GetReadWriteType(void);
+extern void MET_BM_SetReadWriteType(const unsigned int ReadWriteType);
+extern int MET_BM_GetBusCycCount(void);
+extern unsigned int MET_BM_GetTransAllCount(void);
+extern int MET_BM_GetTransCount(const unsigned int counter_num);
+extern int MET_BM_GetWordAllCount(void);
+extern int MET_BM_GetWordCount(const unsigned int counter_num);
+extern unsigned int MET_BM_GetBandwidthWordCount(void);
+extern unsigned int MET_BM_GetOverheadWordCount(void);
+extern int MET_BM_GetTransTypeCount(const unsigned int counter_num);
+extern int MET_BM_GetMDCT(void);
+extern int MET_BM_GetMDCT_2(void);
+extern int MET_BM_GetMonitorCounter(const unsigned int counter_num,
+				    unsigned int *master, unsigned int *trans_type);
+extern int MET_BM_SetMDCT_MDMCU(unsigned int mdmcu_rd_buf);
+extern int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+				    const unsigned int master, const unsigned int trans_type);
+extern int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val);
+extern int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable);
+extern int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master);
+extern int MET_BM_SetbusID_En(const unsigned int counter_num,
+			      const unsigned int enable);
+extern int MET_BM_SetbusID(const unsigned int counter_num,
+			   const unsigned int id);
+extern int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable);
+extern int MET_BM_SetLatencyCounter(unsigned int enable);
+int MET_BM_GetLatencyCycle(unsigned int *__restrict__ emi_value,
+				const unsigned int begin, const unsigned int end);
+extern unsigned int MET_BM_GetEmiDcm(void);
+extern int MET_BM_SetEmiDcm(const unsigned int setting);
+extern void MET_BM_Clear_Start(void);
+extern unsigned int MET_EMI_GetDramRankNum(void);
+extern unsigned int MET_EMI_GetDramRankNum_CHN1(void);
+
+/* Config */
+unsigned int MET_EMI_GetARBA(void);
+unsigned int MET_EMI_GetARBB(void);
+unsigned int MET_EMI_GetARBC(void);
+unsigned int MET_EMI_GetARBD(void);
+unsigned int MET_EMI_GetARBE(void);
+unsigned int MET_EMI_GetARBF(void);
+unsigned int MET_EMI_GetARBG(void);
+unsigned int MET_EMI_GetARBH(void);
+
+/* Total BW status */
+extern unsigned int MET_EMI_GetBWCT0(void);
+extern unsigned int MET_EMI_GetBWCT1(void);
+extern unsigned int MET_EMI_GetBWCT2(void);
+extern unsigned int MET_EMI_GetBWCT3(void);
+extern unsigned int MET_EMI_GetBWCT4(void);
+extern unsigned int MET_EMI_GetBWST0(void);
+extern unsigned int MET_EMI_GetBWST1(void);
+/* C+G BW */
+extern unsigned int MET_EMI_GetBWCT0_2ND(void);
+extern unsigned int MET_EMI_GetBWCT1_2ND(void);
+extern unsigned int MET_EMI_GetBWST_2ND(void);
+
+unsigned int MET_EMI_GetBMRW0(void);
+unsigned int MET_EMI_GetDramChannNum(void);
+
+/* ondiemet*/
+void MET_BM_IPI_baseaddr(void);
+void met_emi_phyaddr_debug(void);
+
+extern void met_record_dramc_dcm_enable_flag(void);
+
+/* get DRS registers content */
+#define CHN_EMI_DRS_ST2 0x17C
+#define CHN_EMI_DRS_ST3 0x180
+#define CHN_EMI_DRS_ST4 0x184
+extern void met_get_drs_registers(uint32_t *value);
+
+#endif                          /* !__MT_MET_EMI_BM_H__ */
diff --git a/src/devtools/met-driver/4.14/mt2731/emi/SEDA3_5/met_emi.c b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3_5/met_emi.c
new file mode 100644
index 0000000..b00dc8b
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3_5/met_emi.c
@@ -0,0 +1,2887 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#ifdef CONFIG_ARM
+//#include <asm/dma-mapping.h> /* arm_coherent_dma_ops */
+#endif /* CONFIG_ARM */
+
+#include <linux/dma-mapping.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "plf_init.h"
+#include "plf_trace.h"
+#include "mtk_emi_bm.h"
+#include "mtk_dramc_reg.h"
+#include "interface.h"
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+#include "sspm/ondiemet_sspm.h"
+#endif
+
+#define FILE_NODE_DBG
+
+/*======================================================================*/
+/*	Global variable definitions					*/
+/*======================================================================*/
+/*ondiemet emi sampling interval in us */
+int emi_tsct_enable;
+int emi_mdct_enable;
+int emi_TP_busfiltr_enable;
+
+int emi_use_ondiemet;
+int metemi_func_opt;
+
+int met_emi_regdump;
+/* Dynamic MonitorCounter selection !!!EXPERIMENT!!! */
+static int msel_enable;
+static unsigned int msel_group1 = BM_MASTER_ALL;
+static unsigned int msel_group2 = BM_MASTER_ALL;
+static unsigned int msel_group3 = BM_MASTER_ALL;
+
+/* CVS Added changeable buffer for testing */
+static int mdmcu_sel_enable;
+static unsigned int rd_mdmcu_rsv_num = 0x5;
+
+/* Global variables */
+static struct kobject *kobj_emi;
+static int rwtype = BM_BOTH_READ_WRITE;
+
+/* BW Limiter */
+/*#define CNT_COUNTDOWN	(1000-1)*/		/* 1000 * 1ms = 1sec */
+#define CNT_COUNTDOWN   (0)                     /* 1ms */
+static int countdown;
+static int bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+
+/* TTYPE counter */
+static int ttype1_16_en = BM_TTYPE1_16_DISABLE;
+static int ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+static int dramc_pdir_enable;
+static int dram_chann_num = 1;
+
+enum SSPM_Mode {
+	CUSTOMER_MODE = 0x0,
+	UNDEFINE_MODE = 0x1,
+	INTERNAL_MODE = 0X2780
+};
+
+
+/*======================================================================*/
+/*	EMI Test Operations						*/
+/*======================================================================*/
+static int times;
+
+static ssize_t test_apmcu_store(struct kobject *kobj,
+				struct kobj_attribute *attr,
+				const char *buf,
+				size_t n)
+{
+	int i;
+	unsigned int    *src_addr_v = NULL;
+	dma_addr_t src_addr_p;
+#ifdef CONFIG_ARM
+	struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_dma_ops);
+#endif /* CONFIG_ARM */
+
+	if ((n == 0) || (buf == NULL))
+		return -EINVAL;
+	if (kstrtoint(buf, 10, &times) != 0)
+		return -EINVAL;
+	if (times < 0)
+		return -EINVAL;
+
+	if (times > 5000)       /* Less than 20MB */
+		return -EINVAL;
+
+#ifdef CONFIG_ARM
+	if (ops && ops->alloc) {
+		(met_device.this_device)->coherent_dma_mask = DMA_BIT_MASK(32);
+		src_addr_v = ops->alloc(met_device.this_device,
+						PAGE_SIZE,
+						&src_addr_p,
+						GFP_KERNEL,
+						0);
+	}
+#endif /* CONFIG_ARM */
+
+#ifdef CONFIG_ARM64
+	/* dma_alloc */
+ 	src_addr_v = dma_alloc_coherent(met_device.this_device,
+ 					PAGE_SIZE,
+ 					&src_addr_p,
+ 					GFP_KERNEL);
+#endif /* CONFIG_ARM64 */
+
+	if (src_addr_v == NULL) {
+#ifdef CONFIG_MET_MODULE
+		met_tag_oneshot_real(0, "test_apmcu dma alloc fail", PAGE_SIZE);
+#else
+		met_tag_oneshot(0, "test_apmcu dma alloc fail", PAGE_SIZE);
+#endif
+		return -ENOMEM;
+	}
+	/* testing */
+	preempt_disable();
+#ifdef CONFIG_MET_MODULE
+	met_tag_start_real(0, "TEST_EMI_APMCU");
+#else
+	met_tag_start(0, "TEST_EMI_APMCU");
+#endif
+	for (i = 0; i < times; i++) {
+		memset(src_addr_v, 2 * i, PAGE_SIZE);
+#ifdef CONFIG_MET_MODULE
+		met_tag_oneshot_real(0, "TEST_EMI_APMCU", PAGE_SIZE);
+#else
+		met_tag_oneshot(0, "TEST_EMI_APMCU", PAGE_SIZE);
+#endif
+	}
+#ifdef CONFIG_MET_MODULE
+	met_tag_end_real(0, "TEST_EMI_APMCU");
+#else
+	met_tag_end(0, "TEST_EMI_APMCU");
+#endif
+	/* the following function has no defined if MET is built as module */
+	/* preempt_enable_no_resched(); */
+	/* use this one to replace it: see met_drv.h */
+	my_preempt_enable();
+
+#ifdef CONFIG_ARM
+	/* dma_free */
+	if (ops && ops->free) {
+		ops->free(met_device.this_device,
+				  PAGE_SIZE,
+				  src_addr_v,
+				  src_addr_p,
+			0);
+	}
+#endif /* CONFIG_ARM */
+
+#ifdef CONFIG_ARM64
+	/* dma_free */
+ 	if (src_addr_v != NULL)
+ 		dma_free_coherent(met_device.this_device,
+ 				  PAGE_SIZE,
+ 				  src_addr_v,
+				  src_addr_p);
+#endif /* CONFIG_ARM64 */
+
+	return n;
+}
+
+/*======================================================================*/
+/*	KOBJ Declarations						*/
+/*======================================================================*/
+DECLARE_KOBJ_ATTR_INT(emi_tsct_enable, emi_tsct_enable);
+DECLARE_KOBJ_ATTR_INT(emi_mdct_enable, emi_mdct_enable);
+DECLARE_KOBJ_ATTR_INT(emi_TP_busfiltr_enable, emi_TP_busfiltr_enable);
+DECLARE_KOBJ_ATTR_INT(metemi_func_opt, metemi_func_opt);
+DECLARE_KOBJ_ATTR_INT(emi_regdump, met_emi_regdump);
+DECLARE_KOBJ_ATTR_INT(msel_enable, msel_enable);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group1, msel_group1, msel_group1 > 0 && msel_group1 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group2, msel_group2, msel_group2 > 0 && msel_group2 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group3, msel_group3, msel_group3 > 0 && msel_group3 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_INT(mdmcu_sel_enable, mdmcu_sel_enable);
+DECLARE_KOBJ_ATTR_INT(rd_mdmcu_rsv_num, rd_mdmcu_rsv_num);
+
+
+/* KOBJ: rwtype */
+DECLARE_KOBJ_ATTR_INT_CHECK(rwtype, rwtype, rwtype >= 0 && rwtype <= BM_WRITE_ONLY);
+
+static unsigned int get_emi_clock_rate(unsigned int dram_data_rate_MHz)
+{
+	/*
+	 *	the ddr type define :
+	 *	enum DDRTYPE {
+	 *	TYPE_LPDDR3 = 1,
+	 *	TYPE_LPDDR4,
+	 *	TYPE_LPDDR4X,
+	 *	TYPE_LPDDR2
+	 *	};
+	 */
+
+	unsigned int DRAM_TYPE;
+
+	if (get_ddr_type_symbol) {
+		DRAM_TYPE = get_ddr_type_symbol();
+
+		if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+			return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP4 / DRAM_DATARATE;
+		else
+			return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP3 / DRAM_DATARATE;
+	} else {
+		METERROR("[%s][%d]get_ddr_type_symbol = NULL , use the TYPE_LPDDR3 setting\n", __func__, __LINE__);
+		return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP3 / DRAM_DATARATE;
+	}
+}
+
+/* KOBJ: emi_clock_rate */
+static ssize_t emi_clock_rate_show(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   char *buf)
+{
+	unsigned int dram_data_rate_MHz;
+
+	if (get_dram_data_rate_symbol) {
+		dram_data_rate_MHz = get_dram_data_rate_symbol();
+	} else {
+		METERROR("get_dram_data_rate_symbol = NULL\n");
+		dram_data_rate_MHz = 0;
+	}
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			get_emi_clock_rate(dram_data_rate_MHz));
+}
+
+DECLARE_KOBJ_ATTR_RO(emi_clock_rate);
+
+/* KOBJ: ttype1_16_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype1_16_en,
+	KOBJ_ITEM_LIST(
+		{ BM_TTYPE1_16_ENABLE,   "ENABLE" },
+		{ BM_TTYPE1_16_DISABLE,  "DISABLE" }
+		)
+	);
+DECLARE_KOBJ_ATTR_STR_LIST(ttype1_16_en, ttype1_16_en, ttype1_16_en);
+
+/* KOBJ: ttype17_21_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype17_21_en,
+	KOBJ_ITEM_LIST(
+		{ BM_TTYPE17_21_ENABLE,  "ENABLE" },
+		{ BM_TTYPE17_21_DISABLE, "DISABLE" }
+		)
+	);
+DECLARE_KOBJ_ATTR_STR_LIST(ttype17_21_en, ttype17_21_en, ttype17_21_en);
+
+/* KOBJ: bw_limiter_enable */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	bw_limiter_enable,
+	KOBJ_ITEM_LIST(
+		{ BM_BW_LIMITER_ENABLE,  "ENABLE" },
+		{ BM_BW_LIMITER_DISABLE, "DISABLE" }
+		)
+	);
+
+DECLARE_KOBJ_ATTR_STR_LIST(bw_limiter_enable, bw_limiter_enable, bw_limiter_enable);
+
+/* KOBJ: ttype_master */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype_master,
+	KOBJ_ITEM_LIST(
+		{ BM_MASTER_M0,  "M0" },
+		{ BM_MASTER_M1,  "M1" },
+		{ BM_MASTER_M2,  "M2" },
+		{ BM_MASTER_M3,  "M3" },
+		{ BM_MASTER_M4,  "M4" },
+		{ BM_MASTER_M5,  "M5" },
+		{ BM_MASTER_M6,  "M6" },
+		{ BM_MASTER_M7,  "M7" }
+		)
+	);
+
+
+/* KOBJ: ttypeX_nbeat, ttypeX_nbyte, ttypeX_burst */
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+	ttype_nbeat,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_TYPE_1BEAT,   1 },
+		{ BM_TRANS_TYPE_2BEAT,   2 },
+		{ BM_TRANS_TYPE_3BEAT,   3 },
+		{ BM_TRANS_TYPE_4BEAT,   4 },
+		{ BM_TRANS_TYPE_5BEAT,   5 },
+		{ BM_TRANS_TYPE_6BEAT,   6 },
+		{ BM_TRANS_TYPE_7BEAT,   7 },
+		{ BM_TRANS_TYPE_8BEAT,   8 },
+		{ BM_TRANS_TYPE_9BEAT,   9 },
+		{ BM_TRANS_TYPE_10BEAT,  10 },
+		{ BM_TRANS_TYPE_11BEAT,  11 },
+		{ BM_TRANS_TYPE_12BEAT,  12 },
+		{ BM_TRANS_TYPE_13BEAT,  13 },
+		{ BM_TRANS_TYPE_14BEAT,  14 },
+		{ BM_TRANS_TYPE_15BEAT,  15 },
+		{ BM_TRANS_TYPE_16BEAT,  16 }
+		)
+	);
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+	ttype_nbyte,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_TYPE_1Byte,   1 },
+		{ BM_TRANS_TYPE_2Byte,   2 },
+		{ BM_TRANS_TYPE_4Byte,   4 },
+		{ BM_TRANS_TYPE_8Byte,   8 },
+		{ BM_TRANS_TYPE_16Byte,  16 },
+		{ BM_TRANS_TYPE_32Byte,  32 }
+		)
+	);
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype_burst,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_TYPE_BURST_INCR,      "INCR" },
+		{ BM_TRANS_TYPE_BURST_WRAP,      "WRAP" }
+		)
+	);
+
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+	ttype_rw,
+	KOBJ_ITEM_LIST(
+		{ BM_TRANS_RW_DEFAULT,   "DEFAULT" },
+		{ BM_TRANS_RW_READONLY,  "R" },
+		{ BM_TRANS_RW_WRITEONLY, "W" },
+		{ BM_TRANS_RW_RWBOTH,    "BOTH" }
+		)
+	);
+
+/* KOBJ: test_apmcu */
+DECLARE_KOBJ_ATTR_SHOW_INT(test_apmcu, times);
+/* please refer to session: "EMI Test Operations" for store operation */
+DECLARE_KOBJ_ATTR(test_apmcu);
+
+DECLARE_KOBJ_ATTR_INT(dramc_pdir_enable, dramc_pdir_enable);
+
+/*enable high priority filter*/
+static int high_priority_filter;
+DECLARE_KOBJ_ATTR_HEX(high_priority_filter, high_priority_filter);
+
+
+
+/**/
+static int ttype_master_val[21];
+static int ttype_busid_val[21];
+static int ttype_nbeat_val[21];
+static int ttype_nbyte_val[21];
+static int ttype_burst_val[21];
+static int ttype_rw_val[21];
+
+#define DECLARE_KOBJ_TTYPE_MASTER(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _master, ttype_master_val[nr - 1], ttype_master)
+
+#define DECLARE_KOBJ_TTYPE_NBEAT(nr) \
+	DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbeat, ttype_nbeat_val[nr - 1], ttype_nbeat)
+
+#define DECLARE_KOBJ_TTYPE_NBYTE(nr) \
+	DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbyte, ttype_nbyte_val[nr - 1], ttype_nbyte)
+
+#define DECLARE_KOBJ_TTYPE_BURST(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _burst, ttype_burst_val[nr - 1], ttype_burst)
+
+#define DECLARE_KOBJ_TTYPE_RW(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _rw, ttype_rw_val[nr - 1], ttype_rw)
+
+#define DECLARE_KOBJ_TTYPE_BUSID_VAL(nr) \
+	DECLARE_KOBJ_ATTR_HEX(ttype ## nr ## _busid, ttype_busid_val[nr - 1])
+
+DECLARE_KOBJ_TTYPE_MASTER(1);
+DECLARE_KOBJ_TTYPE_NBEAT(1);
+DECLARE_KOBJ_TTYPE_NBYTE(1);
+DECLARE_KOBJ_TTYPE_BURST(1);
+DECLARE_KOBJ_TTYPE_RW(1);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(1);
+
+DECLARE_KOBJ_TTYPE_MASTER(2);
+DECLARE_KOBJ_TTYPE_NBEAT(2);
+DECLARE_KOBJ_TTYPE_NBYTE(2);
+DECLARE_KOBJ_TTYPE_BURST(2);
+DECLARE_KOBJ_TTYPE_RW(2);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(2);
+
+DECLARE_KOBJ_TTYPE_MASTER(3);
+DECLARE_KOBJ_TTYPE_NBEAT(3);
+DECLARE_KOBJ_TTYPE_NBYTE(3);
+DECLARE_KOBJ_TTYPE_BURST(3);
+DECLARE_KOBJ_TTYPE_RW(3);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(3);
+
+DECLARE_KOBJ_TTYPE_MASTER(4);
+DECLARE_KOBJ_TTYPE_NBEAT(4);
+DECLARE_KOBJ_TTYPE_NBYTE(4);
+DECLARE_KOBJ_TTYPE_BURST(4);
+DECLARE_KOBJ_TTYPE_RW(4);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(4);
+
+DECLARE_KOBJ_TTYPE_MASTER(5);
+DECLARE_KOBJ_TTYPE_NBEAT(5);
+DECLARE_KOBJ_TTYPE_NBYTE(5);
+DECLARE_KOBJ_TTYPE_BURST(5);
+DECLARE_KOBJ_TTYPE_RW(5);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(5);
+
+DECLARE_KOBJ_TTYPE_MASTER(6);
+DECLARE_KOBJ_TTYPE_NBEAT(6);
+DECLARE_KOBJ_TTYPE_NBYTE(6);
+DECLARE_KOBJ_TTYPE_BURST(6);
+DECLARE_KOBJ_TTYPE_RW(6);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(6);
+
+DECLARE_KOBJ_TTYPE_MASTER(7);
+DECLARE_KOBJ_TTYPE_NBEAT(7);
+DECLARE_KOBJ_TTYPE_NBYTE(7);
+DECLARE_KOBJ_TTYPE_BURST(7);
+DECLARE_KOBJ_TTYPE_RW(7);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(7);
+
+DECLARE_KOBJ_TTYPE_MASTER(8);
+DECLARE_KOBJ_TTYPE_NBEAT(8);
+DECLARE_KOBJ_TTYPE_NBYTE(8);
+DECLARE_KOBJ_TTYPE_BURST(8);
+DECLARE_KOBJ_TTYPE_RW(8);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(8);
+
+DECLARE_KOBJ_TTYPE_MASTER(9);
+DECLARE_KOBJ_TTYPE_NBEAT(9);
+DECLARE_KOBJ_TTYPE_NBYTE(9);
+DECLARE_KOBJ_TTYPE_BURST(9);
+DECLARE_KOBJ_TTYPE_RW(9);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(9);
+
+DECLARE_KOBJ_TTYPE_MASTER(10);
+DECLARE_KOBJ_TTYPE_NBEAT(10);
+DECLARE_KOBJ_TTYPE_NBYTE(10);
+DECLARE_KOBJ_TTYPE_BURST(10);
+DECLARE_KOBJ_TTYPE_RW(10);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(10);
+
+DECLARE_KOBJ_TTYPE_MASTER(11);
+DECLARE_KOBJ_TTYPE_NBEAT(11);
+DECLARE_KOBJ_TTYPE_NBYTE(11);
+DECLARE_KOBJ_TTYPE_BURST(11);
+DECLARE_KOBJ_TTYPE_RW(11);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(11);
+
+DECLARE_KOBJ_TTYPE_MASTER(12);
+DECLARE_KOBJ_TTYPE_NBEAT(12);
+DECLARE_KOBJ_TTYPE_NBYTE(12);
+DECLARE_KOBJ_TTYPE_BURST(12);
+DECLARE_KOBJ_TTYPE_RW(12);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(12);
+
+DECLARE_KOBJ_TTYPE_MASTER(13);
+DECLARE_KOBJ_TTYPE_NBEAT(13);
+DECLARE_KOBJ_TTYPE_NBYTE(13);
+DECLARE_KOBJ_TTYPE_BURST(13);
+DECLARE_KOBJ_TTYPE_RW(13);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(13);
+
+DECLARE_KOBJ_TTYPE_MASTER(14);
+DECLARE_KOBJ_TTYPE_NBEAT(14);
+DECLARE_KOBJ_TTYPE_NBYTE(14);
+DECLARE_KOBJ_TTYPE_BURST(14);
+DECLARE_KOBJ_TTYPE_RW(14);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(14);
+
+DECLARE_KOBJ_TTYPE_MASTER(15);
+DECLARE_KOBJ_TTYPE_NBEAT(15);
+DECLARE_KOBJ_TTYPE_NBYTE(15);
+DECLARE_KOBJ_TTYPE_BURST(15);
+DECLARE_KOBJ_TTYPE_RW(15);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(15);
+
+DECLARE_KOBJ_TTYPE_MASTER(16);
+DECLARE_KOBJ_TTYPE_NBEAT(16);
+DECLARE_KOBJ_TTYPE_NBYTE(16);
+DECLARE_KOBJ_TTYPE_BURST(16);
+DECLARE_KOBJ_TTYPE_RW(16);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(16);
+
+DECLARE_KOBJ_TTYPE_MASTER(17);
+DECLARE_KOBJ_TTYPE_NBEAT(17);
+DECLARE_KOBJ_TTYPE_NBYTE(17);
+DECLARE_KOBJ_TTYPE_BURST(17);
+DECLARE_KOBJ_TTYPE_RW(17);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(17);
+
+DECLARE_KOBJ_TTYPE_MASTER(18);
+DECLARE_KOBJ_TTYPE_NBEAT(18);
+DECLARE_KOBJ_TTYPE_NBYTE(18);
+DECLARE_KOBJ_TTYPE_BURST(18);
+DECLARE_KOBJ_TTYPE_RW(18);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(18);
+
+DECLARE_KOBJ_TTYPE_MASTER(19);
+DECLARE_KOBJ_TTYPE_NBEAT(19);
+DECLARE_KOBJ_TTYPE_NBYTE(19);
+DECLARE_KOBJ_TTYPE_BURST(19);
+DECLARE_KOBJ_TTYPE_RW(19);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(19);
+
+DECLARE_KOBJ_TTYPE_MASTER(20);
+DECLARE_KOBJ_TTYPE_NBEAT(20);
+DECLARE_KOBJ_TTYPE_NBYTE(20);
+DECLARE_KOBJ_TTYPE_BURST(20);
+DECLARE_KOBJ_TTYPE_RW(20);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(20);
+
+DECLARE_KOBJ_TTYPE_MASTER(21);
+DECLARE_KOBJ_TTYPE_NBEAT(21);
+DECLARE_KOBJ_TTYPE_NBYTE(21);
+DECLARE_KOBJ_TTYPE_BURST(21);
+DECLARE_KOBJ_TTYPE_RW(21);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(21);
+
+
+/* SEDA 3.5 ext */
+static unsigned int msel_group_ext_val[WSCT_AMOUNT];
+static unsigned int wsct_rw_val[WSCT_AMOUNT];
+
+char* const delim_comma = ",";
+char* const delim_coclon = ":";
+
+
+char msel_group_ext[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_msel_group_ext(void) {
+	int i;
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		msel_group_ext_val[i] = BM_MASTER_ALL;
+	}
+
+	/*WSCT 4~5 default is ultra, pre-ultra total*/
+	msel_group_ext[0] = '\0';
+}
+
+static ssize_t msel_group_ext_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	/*parse wsct_id:group,
+	1. split data  by ","
+	2. split subdata by ":"
+	3. check the value is OK
+
+	don't clear the setting, do this by echo 1 > clear_setting
+	*/
+
+	char *token, *cur= msel_group_ext;
+	char *_id = NULL, *_master_group = NULL;
+	int id_int = 0;
+
+	_clear_msel_group_ext();
+
+	snprintf(msel_group_ext, FILE_NODE_DATA_LEN, "%s", buf);
+	msel_group_ext[n-1]='\0';
+
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:0xff , (ID,master_group)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_master_group = strsep(&token, delim_coclon);
+
+		PR_BOOTMSG("_id[%s] _master_group[%s]\n",_id,_master_group);
+
+		if (_id == NULL || _master_group == NULL) {
+			PR_BOOTMSG("err: _id[%s] _master_group[%s], para can't be NULL\n",_id,_master_group);
+			_clear_msel_group_ext();
+			return -EINVAL;
+		}
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_msel_group_ext();
+			return -EINVAL;
+		}
+
+
+		if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+			if (kstrtouint(_master_group, 0, &msel_group_ext_val[id_int]) != 0) {
+				PR_BOOTMSG("master_group[%s] trans to hex err\n",_master_group);
+				_clear_msel_group_ext();
+				return -EINVAL;
+			}
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+			_clear_msel_group_ext();
+			return -EINVAL;
+		}
+	}
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("input data [%s]\n",msel_group_ext);
+	/*PR_BOOTMSG("msel_group_ext_store size para n[%d]\n",n);*/
+	int i;
+	PR_BOOTMSG("save data\n");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		PR_BOOTMSG("id[%d]=%X\n",i,msel_group_ext_val[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t msel_group_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", msel_group_ext);
+}
+
+
+char wsct_rw[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_rw(void) {
+	int i;
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		wsct_rw_val[i] = BM_WSCT_RW_RWBOTH;
+	}
+	wsct_rw[0] = '\0';
+}
+
+static ssize_t wsct_rw_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= wsct_rw;
+	char *_id = NULL, *_rw_type = NULL;
+	int id_int = 0;
+
+	_clear_wsct_rw();
+
+	snprintf(wsct_rw, FILE_NODE_DATA_LEN, "%s", buf);
+	wsct_rw[n-1]='\0';
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:R , 5:W (ID,RW)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_rw_type = strsep(&token, delim_coclon);
+
+		if (_id == NULL || _rw_type == NULL) {
+			PR_BOOTMSG("err: _id[%s] _rw_type[%s], para can't be NULL\n",_id, _rw_type);
+			_clear_wsct_rw();
+			return -EINVAL;
+		}
+
+		PR_BOOTMSG("_id[%s] _rw_type[%s]\n",_id, _rw_type);
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_wsct_rw();
+			return -EINVAL;
+		}
+
+
+		if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+			if ( 0 == strncmp("NONE",_rw_type,4))
+				wsct_rw_val[id_int] = BM_WSCT_RW_DISABLE;
+			else if (0 == strncmp("R",_rw_type,4))
+				wsct_rw_val[id_int] = BM_WSCT_RW_READONLY;
+			else if (0 == strncmp("W",_rw_type,4))
+				wsct_rw_val[id_int] = BM_WSCT_RW_WRITEONLY;
+			else if (0 == strncmp("RW",_rw_type,4))
+				wsct_rw_val[id_int] = BM_WSCT_RW_RWBOTH;
+			else {
+				PR_BOOTMSG("_id[%s] has err rwtype[%s]\n", _id, _rw_type);
+				_clear_wsct_rw();
+				return -EINVAL;
+			}
+
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+			_clear_wsct_rw();
+			return -EINVAL;
+		}
+	}
+
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("wsct_rw_store input data [%s]\n",wsct_rw);
+	int i;
+	PR_BOOTMSG("rwtype save data\n");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		PR_BOOTMSG("id[%d]=%d\n",i,wsct_rw_val[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t wsct_rw_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", wsct_rw);
+}
+
+
+static unsigned int WSCT_HPRI_DIS[WSCT_AMOUNT];
+static unsigned int WSCT_HPRI_SEL[WSCT_AMOUNT];
+char wsct_high_priority_enable[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_high_priority_enable(void) {
+	int i;
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		WSCT_HPRI_DIS[i] = 1;
+		WSCT_HPRI_SEL[i] = 0xF;
+	}
+
+	WSCT_HPRI_DIS[4] = 0;
+	WSCT_HPRI_SEL[4] = 0x8;  /* ultra */
+
+	WSCT_HPRI_DIS[5] = 0;
+	WSCT_HPRI_SEL[5] = 0x4; /* pre_ultra */
+
+
+	wsct_high_priority_enable[0] = '\0';
+}
+
+static ssize_t wsct_high_priority_enable_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= wsct_high_priority_enable;
+	char *_id = NULL, *_enable = NULL,  *_level = NULL;
+	int  id_int = 0, level_int = 0;
+
+	_clear_wsct_high_priority_enable();
+
+	snprintf(wsct_high_priority_enable, FILE_NODE_DATA_LEN, "%s", buf);
+	wsct_high_priority_enable[n-1]='\0';
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:R , 5:W (ID,RW)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_enable = strsep(&token, delim_coclon);
+		_level = strsep(&token, delim_coclon);
+
+		PR_BOOTMSG("_id[%s] _enable[%s] _level[%s]\n",_id, _enable, _level);
+
+		if (_id == NULL || _enable == NULL || _level == NULL ) {
+			PR_BOOTMSG("err : _id[%s] _enable[%s] _level[%s], para can't be NULL\n",_id, _enable, _level);
+			_clear_wsct_high_priority_enable();
+			return -EINVAL;
+		}
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_wsct_high_priority_enable();
+			return -EINVAL;
+		}
+
+
+		if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+			if ( 0 == strncmp("disable", _enable, 7)) {
+
+				WSCT_HPRI_DIS[id_int] = 1;
+				WSCT_HPRI_SEL[id_int] = 0xf;
+			} else if ( 0 == strncmp("enable", _enable, 6)) {
+
+				WSCT_HPRI_DIS[id_int] = 0;
+				if (kstrtouint(_level, 0, &level_int) != 0) {
+					PR_BOOTMSG("_id[%s] trans ultraLevel[%s] to hex err\n",_id, _level);
+					_clear_wsct_high_priority_enable();
+					return -EINVAL;
+				}
+				WSCT_HPRI_SEL[id_int] = level_int & 0xF;
+			} else {
+				PR_BOOTMSG("_id[%s] has err enable[%s] (enable/disable)\n", _id, _enable);
+				_clear_wsct_high_priority_enable();
+				return -EINVAL;
+			}
+
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+			_clear_wsct_high_priority_enable();
+			return -EINVAL;
+		}
+	}
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("input data [%s]\n",wsct_high_priority_enable);
+	int i;
+	PR_BOOTMSG("wsct_high_priority_enable save data\n");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		PR_BOOTMSG("id[%d]=(%X,%X)\n", i, WSCT_HPRI_DIS[i], WSCT_HPRI_SEL[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t wsct_high_priority_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", wsct_high_priority_enable);
+}
+
+
+static unsigned int wsct_busid_val[WSCT_AMOUNT];
+static unsigned int wsct_idMask_val[WSCT_AMOUNT];
+
+char wsct_busid[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_busid(void) {
+	int i;
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		wsct_busid_val[i] = 0xfffff;
+		wsct_idMask_val[i] = 0x1FFF;
+	}
+	wsct_busid[0] = '\0';
+}
+
+static ssize_t wsct_busid_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= wsct_busid;
+
+	char *_id = NULL, *_busid = NULL, *_idMask = NULL;
+	int id_int = 0, busid_int = 0, idMask_int = 0;
+
+	_clear_wsct_busid();
+
+	snprintf(wsct_busid, FILE_NODE_DATA_LEN, "%s", buf);
+	wsct_busid[n-1]='\0';
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:R , 5:W (ID,RW)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_busid = strsep(&token, delim_coclon);
+		_idMask = strsep(&token, delim_coclon);
+
+		PR_BOOTMSG("_id[%s] _busid[%s] _idMask[%s]\n",_id, _busid, _idMask);
+
+		if (_id == NULL || _busid == NULL || _idMask == NULL) {
+			PR_BOOTMSG("err: _id[%s] _busid[%s] _idMask[%s] ,parameter can't be NULL\n",_id, _busid, _idMask);
+			_clear_wsct_busid();
+			return -EINVAL;
+		}
+
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_wsct_busid();
+			return -EINVAL;
+		}
+		if (kstrtouint(_busid, 0, &busid_int) != 0) {
+			PR_BOOTMSG("_busid[%s] trans to hex err\n",_busid);
+			_clear_wsct_busid();
+			return -EINVAL;
+		}
+		if (kstrtouint(_idMask, 0, &idMask_int) != 0) {
+			PR_BOOTMSG("_idMask[%s] trans to hex err\n",_idMask);
+			_clear_wsct_busid();
+			return -EINVAL;
+		}
+
+
+		if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+			wsct_busid_val[id_int] = busid_int;
+			wsct_idMask_val[id_int] = idMask_int;
+
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+			_clear_wsct_busid();
+			return -EINVAL;
+		}
+	}
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("input data [%s]\n",wsct_busid);
+	int i;
+	PR_BOOTMSG("wsct_busid save data\n");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		PR_BOOTMSG("id[%d](busid,idMask)=(%X,%X)\n", i, wsct_busid_val[i], wsct_idMask_val[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t wsct_busid_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", wsct_busid);
+}
+
+
+static unsigned int  wsct_chn_rank_sel_val[WSCT_AMOUNT];
+char wsct_chn_rank_sel[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_chn_rank_sel(void) {
+	int i;
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		wsct_chn_rank_sel_val[i] = 0xF;
+	}
+	wsct_chn_rank_sel[0] = '\0';
+}
+
+static ssize_t wsct_chn_rank_sel_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= wsct_chn_rank_sel;
+	char *_id = NULL, *_chn_rank = NULL;
+	int id_int = 0, chn_rank_int = 0;
+
+	_clear_wsct_chn_rank_sel();
+
+	snprintf(wsct_chn_rank_sel, FILE_NODE_DATA_LEN, "%s", buf);
+	wsct_chn_rank_sel[n-1]='\0';
+
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_chn_rank = strsep(&token, delim_coclon);
+
+		PR_BOOTMSG("_id[%s] _chn_rank[%s]\n",_id, _chn_rank);
+
+		if (_id == NULL || _chn_rank == NULL) {
+			PR_BOOTMSG("err : _id[%s] _chn_rank[%s], para can't be NULL\n",_id, _chn_rank);
+			_clear_wsct_chn_rank_sel();
+			return -EINVAL;
+		}
+
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_wsct_chn_rank_sel();
+			return -EINVAL;
+		}
+		if (kstrtouint(_chn_rank, 0, &chn_rank_int) != 0) {
+			PR_BOOTMSG("_chn_rank[%s] trans to hex err\n",_id);
+			_clear_wsct_chn_rank_sel();
+			return -EINVAL;
+		}
+
+		if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+			wsct_chn_rank_sel_val[id_int] = chn_rank_int;
+
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+			_clear_wsct_chn_rank_sel();
+			return -EINVAL;
+		}
+	}
+
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("wsct_chn_rank_sel input data [%s]\n",wsct_chn_rank_sel);
+	int i;
+	PR_BOOTMSG("wsct_chn_rank_sel_val save data\n");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		PR_BOOTMSG("id[%d]=%X\n",i,wsct_chn_rank_sel_val[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t wsct_chn_rank_sel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", wsct_chn_rank_sel);
+}
+
+static unsigned int  wsct_byte_low_bnd_val[WSCT_AMOUNT];
+static unsigned int  wsct_byte_up_bnd_val[WSCT_AMOUNT];
+static unsigned int  wsct_byte_bnd_dis[WSCT_AMOUNT];
+char wsct_burst_range[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_burst_range(void) {
+	int i;
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		wsct_byte_low_bnd_val[i] = 0x0;
+		wsct_byte_up_bnd_val[i] = 0x1FF;
+		wsct_byte_bnd_dis[i] = 1;
+	}
+	wsct_burst_range[0] = '\0';
+}
+
+static ssize_t wsct_burst_range_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= wsct_burst_range;
+	char *_id = NULL, *_low_bnd = NULL, *_up_bnd = NULL;
+	int id_int = 0, low_bnd_int = 0, up_bnd_int = 0;
+
+	_clear_wsct_burst_range();
+
+	snprintf(wsct_burst_range, FILE_NODE_DATA_LEN, "%s", buf);
+	wsct_burst_range[n-1]='\0';
+
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_low_bnd = strsep(&token, delim_coclon);
+		_up_bnd = strsep(&token, delim_coclon);
+
+		PR_BOOTMSG("_id[%s] _low_bnd[%s] _up_bnd[%s]\n",_id, _low_bnd, _up_bnd);
+
+		if (_id == NULL || _low_bnd == NULL || _up_bnd == NULL) {
+			PR_BOOTMSG("err : _id[%s] _low_bnd[%s] _up_bnd[%s], para can't be NULL\n",_id, _low_bnd, _up_bnd);
+			_clear_wsct_burst_range();
+			return -EINVAL;
+		}
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_wsct_burst_range();
+			return -EINVAL;
+		}
+		if (kstrtouint(_low_bnd, 0, &low_bnd_int) != 0) {
+			PR_BOOTMSG("_low_bnd[%s] trans to hex err\n",_id);
+			_clear_wsct_burst_range();
+			return -EINVAL;
+		}
+		if (kstrtouint(_up_bnd, 0, &up_bnd_int) != 0) {
+			PR_BOOTMSG("_up_bnd[%s] trans to hex err\n",_id);
+			_clear_wsct_burst_range();
+			return -EINVAL;
+		}
+
+		if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+			wsct_byte_low_bnd_val[id_int] = low_bnd_int;
+			wsct_byte_up_bnd_val[id_int] = up_bnd_int;
+			wsct_byte_bnd_dis[id_int] = 0;
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+			_clear_wsct_burst_range();
+			return -EINVAL;
+		}
+	}
+
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("wsct_burst_range_store input data [%s]\n",wsct_burst_range);
+	int i;
+	PR_BOOTMSG("wsct_burst_range save data\n");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		PR_BOOTMSG("id[%d](low_bnd,up_bnd)=(%X,%X)\n",i,wsct_byte_low_bnd_val[i],wsct_byte_up_bnd_val[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t wsct_burst_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", wsct_burst_range);
+}
+
+
+
+static unsigned int tsct_busid_enable_val[TSCT_AMOUNT];
+char tsct_busid_enable[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_tsct_busid_enable(void) {
+	int i;
+
+	for (i=0;i<TSCT_AMOUNT;i++) {
+		tsct_busid_enable_val[i] = 0;
+	}
+	tsct_busid_enable[0] = '\0';
+}
+
+static ssize_t tsct_busid_enable_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= tsct_busid_enable;
+	char *_id = NULL, *_enable = NULL;
+	int  id_int = 0;
+
+	_clear_tsct_busid_enable();
+
+	snprintf(tsct_busid_enable, FILE_NODE_DATA_LEN, "%s", buf);
+	tsct_busid_enable[n-1]='\0';
+
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:R , 5:W (ID,RW)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_enable = strsep(&token, delim_coclon);
+
+
+		PR_BOOTMSG("_id[%s] _enable[%s]\n",_id, _enable);
+
+		if (_id == NULL || _enable == NULL) {
+			PR_BOOTMSG("err : _id[%s] _enable[%s], para can't be NULL\n",_id, _enable);
+			_clear_tsct_busid_enable();
+			return -EINVAL;
+		}
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_tsct_busid_enable();
+			return -EINVAL;
+		}
+
+
+		if ( id_int >= 0 && id_int < TSCT_AMOUNT) {
+			if ( 0 == strncmp("disable", _enable, 7)) {
+				tsct_busid_enable_val[id_int] = 0;
+			} else if ( 0 == strncmp("enable", _enable, 6)) {
+				tsct_busid_enable_val[id_int] = 1;
+			} else {
+				PR_BOOTMSG("_id[%s] has err enable[%s] (enable/disable)\n", _id, _enable);
+				_clear_tsct_busid_enable();
+				return -EINVAL;
+			}
+
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, TSCT_AMOUNT-1);
+			_clear_tsct_busid_enable();
+			return -EINVAL;
+		}
+	}
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("tsct_busid_enable input data [%s]\n",tsct_busid_enable);
+	int i;
+	PR_BOOTMSG("wsct_high_priority_enable save data\n");
+	for (i=0;i<TSCT_AMOUNT;i++) {
+		PR_BOOTMSG("id[%d]=(%d)\n", i, tsct_busid_enable_val[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t tsct_busid_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", tsct_busid_enable);
+}
+
+
+/* use the origin para high_priority_filter to save the en/dis setting */
+static unsigned int TTYPE_HPRI_SEL[BM_COUNTER_MAX];
+char ttype_high_priority_ext[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_ttype_high_priority_ext(void) {
+	int i;
+
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+		TTYPE_HPRI_SEL[i] = 0xf;
+	}
+
+	high_priority_filter = 0x0;
+	ttype_high_priority_ext[0] = '\0';
+}
+
+static ssize_t ttype_high_priority_ext_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= ttype_high_priority_ext;
+	char *_id = NULL, *_enable = NULL,  *_level = NULL;
+	int  id_int = 0, level_int = 0;
+
+	_clear_ttype_high_priority_ext();
+
+	snprintf(ttype_high_priority_ext, FILE_NODE_DATA_LEN, "%s", buf);
+	ttype_high_priority_ext[n-1]='\0';
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:R , 5:W (ID,RW)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_enable = strsep(&token, delim_coclon);
+		_level = strsep(&token, delim_coclon);
+
+		PR_BOOTMSG("_id[%s] _enable[%s] _level[%s]\n",_id, _enable, _level);
+
+		if (_id == NULL || _enable == NULL || _level == NULL ) {
+			PR_BOOTMSG("err : _id[%s] _enable[%s] _level[%s], para can't be NULL\n",_id, _enable, _level);
+			_clear_ttype_high_priority_ext();
+			return -EINVAL;
+		}
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_ttype_high_priority_ext();
+			return -EINVAL;
+		}
+
+		id_int = id_int - 1;
+		if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+			if ( 0 == strncmp("disable", _enable, 7)) {
+
+				high_priority_filter = ( high_priority_filter & ~(1<<id_int) ) | ( 0<<id_int );
+				TTYPE_HPRI_SEL[id_int] = 0xf;
+			} else if ( 0 == strncmp("enable", _enable, 6)) {
+
+				high_priority_filter = ( high_priority_filter & ~(1<<id_int) ) | ( 1<<id_int );
+				if (kstrtouint(_level, 0, &level_int) != 0) {
+					PR_BOOTMSG("_id[%s] trans ultraLevel[%s] to hex err\n",_id, _level);
+					_clear_ttype_high_priority_ext();
+					return -EINVAL;
+				}
+				TTYPE_HPRI_SEL[id_int] = level_int & 0xF;
+			} else {
+				PR_BOOTMSG("ttype_high_priority_ext: _id[%s] has err enable[%s] (enable/disable)\n", _id, _enable);
+				_clear_ttype_high_priority_ext();
+				return -EINVAL;
+			}
+
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 1~%d\n",id_int+1, BM_COUNTER_MAX);
+			_clear_ttype_high_priority_ext();
+			return -EINVAL;
+		}
+	}
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("input data [%s]\n",ttype_high_priority_ext);
+
+	int i;
+	PR_BOOTMSG("wsct_high_priority_enable save data\n");
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+		PR_BOOTMSG("id[%d]=(%X,%X)\n", i+1, high_priority_filter>>i & 0x1, TTYPE_HPRI_SEL[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t ttype_high_priority_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", ttype_high_priority_ext);
+}
+
+
+static unsigned int ttype_idMask_val[BM_COUNTER_MAX];
+char ttype_busid_ext[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_ttype_busid_ext(void) {
+	int i;
+
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+		ttype_busid_val[i] = 0xfffff;
+		ttype_idMask_val[i] = 0x1FFF;
+	}
+	ttype_busid_ext[0] = '\0';
+}
+
+/*id: 1~21*/
+static ssize_t ttype_busid_ext_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= ttype_busid_ext;
+
+	char *_id = NULL, *_busid = NULL, *_idMask = NULL;
+	int id_int = 0, busid_int = 0, idMask_int = 0;
+
+	_clear_ttype_busid_ext();
+
+	snprintf(ttype_busid_ext, FILE_NODE_DATA_LEN, "%s", buf);
+	ttype_busid_ext[n-1]='\0';
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:R , 5:W (ID,RW)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_busid = strsep(&token, delim_coclon);
+		_idMask = strsep(&token, delim_coclon);
+
+		PR_BOOTMSG("_id[%s] _busid[%s] _idMask[%s]\n",_id, _busid, _idMask);
+
+		if (_id == NULL || _busid == NULL || _idMask == NULL) {
+			PR_BOOTMSG("err: ttype_busid_ext _id[%s] _busid[%s] _idMask[%s] ,parameter can't be NULL\n",_id, _busid, _idMask);
+			_clear_ttype_busid_ext();
+			return -EINVAL;
+		}
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_ttype_busid_ext();
+			return -EINVAL;
+		}
+		if (kstrtouint(_busid, 0, &busid_int) != 0) {
+			PR_BOOTMSG("_busid[%s] trans to hex err\n",_busid);
+			_clear_ttype_busid_ext();
+			return -EINVAL;
+		}
+		if (kstrtouint(_idMask, 0, &idMask_int) != 0) {
+			PR_BOOTMSG("_idMask[%s] trans to hex err\n",_idMask);
+			_clear_ttype_busid_ext();
+			return -EINVAL;
+		}
+
+		id_int = id_int - 1;
+		if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+			ttype_busid_val[id_int] = busid_int;
+			ttype_idMask_val[id_int] = idMask_int;
+
+		} else {
+			PR_BOOTMSG("ttype_busid_ext id[%d] exceed the range, it must be 1~%d\n",id_int+1, BM_COUNTER_MAX);
+			_clear_ttype_busid_ext();
+			return -EINVAL;
+		}
+	}
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("ttype_busid_ext input data [%s]\n",ttype_busid_ext);
+
+	int i;
+	PR_BOOTMSG("ttype_busid_ext save data\n");
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+		PR_BOOTMSG("id[%d](busid,idMask)=(%X,%X)\n", i+1, ttype_busid_val[i], ttype_idMask_val[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t ttype_busid_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", ttype_busid_ext);
+}
+
+
+static unsigned int  ttype_chn_rank_sel_val[BM_COUNTER_MAX];
+char ttype_chn_rank_sel[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_ttype_chn_rank_sel(void) {
+	int i;
+
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+		ttype_chn_rank_sel_val[i] = 0xF;
+	}
+	ttype_chn_rank_sel[0] = '\0';
+}
+
+static ssize_t ttype_chn_rank_sel_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= ttype_chn_rank_sel;
+	char *_id = NULL, *_chn_rank = NULL;
+	int id_int = 0, chn_rank_int = 0;
+
+	_clear_ttype_chn_rank_sel();
+
+	snprintf(ttype_chn_rank_sel, FILE_NODE_DATA_LEN, "%s", buf);
+	ttype_chn_rank_sel[n-1]='\0';
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_chn_rank = strsep(&token, delim_coclon);
+
+		PR_BOOTMSG("_id[%s] _chn_rank[%s]\n",_id, _chn_rank);
+
+		if (_id == NULL || _chn_rank == NULL) {
+			PR_BOOTMSG("err (ttype_chn_rank_sel): _id[%s] _chn_rank[%s], para can't be NULL\n",_id, _chn_rank);
+			_clear_ttype_chn_rank_sel();
+			return -EINVAL;
+		}
+
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_ttype_chn_rank_sel();
+			return -EINVAL;
+		}
+		if (kstrtouint(_chn_rank, 0, &chn_rank_int) != 0) {
+			PR_BOOTMSG("_chn_rank[%s] trans to hex err\n",_id);
+			_clear_ttype_chn_rank_sel();
+			return -EINVAL;
+		}
+
+		id_int = id_int -1;
+
+		if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+			ttype_chn_rank_sel[id_int] = chn_rank_int;
+
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 1~%d\n",id_int+1, BM_COUNTER_MAX);
+			_clear_ttype_chn_rank_sel();
+			return -EINVAL;
+		}
+	}
+
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("ttype_chn_rank_sel input data [%s]\n",ttype_chn_rank_sel);
+
+	int i;
+	PR_BOOTMSG("wsct_chn_rank_sel_val save data\n");
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+		PR_BOOTMSG("id[%d]=%X\n",i+1,ttype_chn_rank_sel[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t ttype_chn_rank_sel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", ttype_chn_rank_sel);
+}
+
+
+static unsigned int  ttype_byte_low_bnd_val[BM_COUNTER_MAX];
+static unsigned int  ttype_byte_up_bnd_val[BM_COUNTER_MAX];
+static unsigned int  ttype_byte_bnd_dis[BM_COUNTER_MAX];
+char ttype_burst_range[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_ttype_burst_range(void) {
+	int i;
+
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+		ttype_byte_low_bnd_val[i] = 0x0;
+		ttype_byte_up_bnd_val[i] = 0x1FF;
+		ttype_byte_bnd_dis[i] = 1;
+	}
+	ttype_burst_range[0] = '\0';
+}
+
+static ssize_t ttype_burst_range_store(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		const char *buf,
+		size_t n)
+{
+	char *token, *cur= ttype_burst_range;
+	char *_id = NULL, *_low_bnd = NULL, *_up_bnd = NULL;
+	int id_int = 0, low_bnd_int = 0, up_bnd_int = 0;
+
+	_clear_ttype_burst_range();
+
+	snprintf(ttype_burst_range, FILE_NODE_DATA_LEN, "%s", buf);
+	ttype_burst_range[n-1]='\0';
+
+
+	while (cur != NULL) {
+		token = strsep(&cur, delim_comma);
+		PR_BOOTMSG("token: %s\n",token);
+		/*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+		_id = strsep(&token, delim_coclon); // ID
+		_low_bnd = strsep(&token, delim_coclon);
+		_up_bnd = strsep(&token, delim_coclon);
+
+		PR_BOOTMSG("_id[%s] _low_bnd[%s] _up_bnd[%s]\n",_id, _low_bnd, _up_bnd);
+
+		if (_id == NULL || _low_bnd == NULL || _up_bnd == NULL) {
+			PR_BOOTMSG("err (ttype_burst_range): _id[%s] _low_bnd[%s] _up_bnd[%s], para can't be NULL\n",
+				        _id, _low_bnd, _up_bnd);
+			_clear_ttype_burst_range();
+			return -EINVAL;
+		}
+
+		if (kstrtouint(_id, 0, &id_int) != 0) {
+			PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+			_clear_ttype_burst_range();
+			return -EINVAL;
+		}
+		if (kstrtouint(_low_bnd, 0, &low_bnd_int) != 0) {
+			PR_BOOTMSG("_low_bnd[%s] trans to hex err\n",_id);
+			_clear_ttype_burst_range();
+			return -EINVAL;
+		}
+		if (kstrtouint(_up_bnd, 0, &up_bnd_int) != 0) {
+			PR_BOOTMSG("_up_bnd[%s] trans to hex err\n",_id);
+			_clear_ttype_burst_range();
+			return -EINVAL;
+		}
+
+		id_int = id_int - 1;
+		if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+			ttype_byte_low_bnd_val[id_int] = low_bnd_int;
+			ttype_byte_up_bnd_val[id_int] = up_bnd_int;
+			ttype_byte_bnd_dis[id_int] = 0;
+		} else {
+			PR_BOOTMSG("id[%d] exceed the range, it must be 1~%d\n",id_int, BM_COUNTER_MAX);
+			_clear_ttype_burst_range();
+			return -EINVAL;
+		}
+	}
+
+#ifdef FILE_NODE_DBG
+	PR_BOOTMSG("ttype_burst_range_store input data [%s]\n",ttype_burst_range);
+
+	int i;
+	PR_BOOTMSG("ttype_burst_range save data\n");
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+		PR_BOOTMSG("id[%d](low_bnd,up_bnd)=(%X,%X)\n",i+1,ttype_byte_low_bnd_val[i],ttype_byte_up_bnd_val[i]);
+	}
+#endif
+	return n;
+}
+
+static ssize_t ttype_burst_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", ttype_burst_range);
+}
+
+static int reserve_wsct_setting;
+DECLARE_KOBJ_ATTR_INT(reserve_wsct_setting, reserve_wsct_setting);
+
+static void _clear_setting(void) {
+	/*clear all file node para here*/
+
+
+	PR_BOOTMSG("clear EMI file node setting\n");
+
+	_clear_msel_group_ext();
+	_clear_wsct_rw();
+	_clear_wsct_high_priority_enable();
+	_clear_wsct_busid();
+	_clear_wsct_chn_rank_sel();
+	_clear_wsct_burst_range();
+
+	_clear_tsct_busid_enable();
+	_clear_ttype_high_priority_ext();
+	_clear_ttype_busid_ext();
+	_clear_ttype_chn_rank_sel();
+	_clear_ttype_burst_range();
+	reserve_wsct_setting = 0;
+
+	emi_tsct_enable = 0;
+	emi_mdct_enable = 0;
+	emi_TP_busfiltr_enable = 0;
+	metemi_func_opt = 0xf00e;
+	high_priority_filter = 0x0;
+	rwtype = BM_BOTH_READ_WRITE;
+	dramc_pdir_enable = 1;
+
+	met_emi_regdump = 0;
+	rd_mdmcu_rsv_num = 0;
+
+	msel_enable = 0;
+	msel_group1 = BM_MASTER_ALL;
+	msel_group2 = BM_MASTER_ALL;
+	msel_group3 = BM_MASTER_ALL;
+
+	mdmcu_sel_enable = 0;
+
+	bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+	ttype1_16_en = BM_TTYPE1_16_DISABLE;
+	ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+
+
+	/*ttype TBD*/
+}
+
+static ssize_t clear_setting_store(struct kobject *kobj,
+			struct kobj_attribute *attr,
+			const char *buf,
+			size_t n)
+{
+	int value;
+
+	if ((n == 0) || (buf == NULL))
+		return -EINVAL;
+
+	if (kstrtoint(buf, 0, &value) != 0)
+		return -EINVAL;
+
+	if (value == 1)
+		_clear_setting();
+
+	return n;
+}
+
+static struct kobj_attribute clear_setting_attr = __ATTR_WO(clear_setting); // OK
+static struct kobj_attribute msel_group_ext_attr = __ATTR(msel_group_ext, 0664, msel_group_ext_show, msel_group_ext_store); //OK
+static struct kobj_attribute wsct_rw_attr = __ATTR(wsct_rw, 0664, wsct_rw_show, wsct_rw_store);
+static struct kobj_attribute wsct_high_priority_enable_attr = __ATTR(wsct_high_priority_enable, 0664, wsct_high_priority_enable_show, wsct_high_priority_enable_store);
+static struct kobj_attribute wsct_busid_attr = __ATTR(wsct_busid, 0664, wsct_busid_show, wsct_busid_store);
+static struct kobj_attribute wsct_chn_rank_sel_attr = __ATTR(wsct_chn_rank_sel, 0664, wsct_chn_rank_sel_show, wsct_chn_rank_sel_store);
+static struct kobj_attribute wsct_burst_range_attr = __ATTR(wsct_burst_range, 0664, wsct_burst_range_show, wsct_burst_range_store);
+static struct kobj_attribute tsct_busid_enable_attr = __ATTR(tsct_busid_enable, 0664, tsct_busid_enable_show, tsct_busid_enable_store);
+static struct kobj_attribute ttype_high_priority_ext_attr = __ATTR(ttype_high_priority_ext, 0664, ttype_high_priority_ext_show, ttype_high_priority_ext_store);
+static struct kobj_attribute ttype_busid_ext_attr = __ATTR(ttype_busid_ext, 0664, ttype_busid_ext_show, ttype_busid_ext_store);
+static struct kobj_attribute ttype_chn_rank_sel_attr = __ATTR(ttype_chn_rank_sel, 0664, ttype_chn_rank_sel_show, ttype_chn_rank_sel_store);
+static struct kobj_attribute ttype_burst_range_attr = __ATTR(ttype_burst_range, 0664, ttype_burst_range_show, ttype_burst_range_store);
+
+
+
+
+
+
+/**/
+#define KOBJ_ATTR_ITEM_SERIAL_FNODE(nr) \
+	do { \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _master); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _nbeat); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _nbyte); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _burst); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _busid); \
+		KOBJ_ATTR_ITEM(ttype ## nr ## _rw); \
+	} while (0)
+
+#define KOBJ_ATTR_LIST \
+	do { \
+		KOBJ_ATTR_ITEM(high_priority_filter); \
+		KOBJ_ATTR_ITEM(metemi_func_opt); \
+		KOBJ_ATTR_ITEM(emi_tsct_enable); \
+		KOBJ_ATTR_ITEM(emi_mdct_enable); \
+		KOBJ_ATTR_ITEM(emi_TP_busfiltr_enable); \
+		KOBJ_ATTR_ITEM(emi_regdump); \
+		KOBJ_ATTR_ITEM(msel_enable); \
+		KOBJ_ATTR_ITEM(msel_group1); \
+		KOBJ_ATTR_ITEM(msel_group2); \
+		KOBJ_ATTR_ITEM(msel_group3); \
+		KOBJ_ATTR_ITEM(emi_clock_rate); \
+		KOBJ_ATTR_ITEM(rwtype); \
+		KOBJ_ATTR_ITEM(ttype17_21_en); \
+		KOBJ_ATTR_ITEM(ttype1_16_en); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(1); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(2); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(3); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(4); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(5); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(6); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(7); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(8); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(9); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(10); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(11); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(12); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(13); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(14); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(15); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(16); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(17); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(18); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(19); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(20); \
+		KOBJ_ATTR_ITEM_SERIAL_FNODE(21); \
+		KOBJ_ATTR_ITEM(test_apmcu); \
+		KOBJ_ATTR_ITEM(bw_limiter_enable); \
+		KOBJ_ATTR_ITEM(dramc_pdir_enable); \
+		KOBJ_ATTR_ITEM(mdmcu_sel_enable); \
+		KOBJ_ATTR_ITEM(rd_mdmcu_rsv_num); \
+		KOBJ_ATTR_ITEM(clear_setting);\
+		KOBJ_ATTR_ITEM(msel_group_ext);\
+		KOBJ_ATTR_ITEM(wsct_rw);\
+		KOBJ_ATTR_ITEM(wsct_high_priority_enable);\
+		KOBJ_ATTR_ITEM(wsct_busid);\
+		KOBJ_ATTR_ITEM(wsct_chn_rank_sel);\
+		KOBJ_ATTR_ITEM(wsct_burst_range);\
+		KOBJ_ATTR_ITEM(tsct_busid_enable);\
+		KOBJ_ATTR_ITEM(ttype_high_priority_ext);\
+		KOBJ_ATTR_ITEM(ttype_busid_ext);\
+		KOBJ_ATTR_ITEM(ttype_chn_rank_sel);\
+		KOBJ_ATTR_ITEM(ttype_burst_range);\
+		KOBJ_ATTR_ITEM(reserve_wsct_setting);\
+	} while (0)
+
+
+
+/*======================================================================*/
+/*	EMI Operations							*/
+/*======================================================================*/
+static void emi_init(void)
+{
+	unsigned int bmrw0_val, bmrw1_val, i, enable;
+	/*unsigned int msel_group_val[4];*/
+
+	/*save origianl EMI config*/
+	MET_BM_SaveCfg();
+
+	/* get dram channel number */
+	dram_chann_num = MET_EMI_GetDramChannNum();
+
+	/* Init. EMI bus monitor */
+	MET_BM_SetReadWriteType(rwtype);
+
+#if 1 /* SEDA 3.5 */
+	/*handle the ori */
+
+	if (ttype1_16_en != BM_TTYPE1_16_ENABLE) {
+		MET_BM_SetLatencyCounter(1);    /*enable latency count*/
+	}
+	else {
+		MET_BM_SetLatencyCounter(0);    /*disable latency count*/
+
+		for (i = 1; i <= 16; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+		}
+	}
+
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+		for (i = 17; i <= 21; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+		}
+	}
+
+	PR_BOOTMSG("[%s]reserve_wsct_setting=%d\n",__func__,reserve_wsct_setting);
+
+	if (reserve_wsct_setting == 0) {
+		/* wsct 0 : total-all*/
+		msel_group_ext_val[0] = BM_MASTER_ALL;
+		wsct_rw_val[0] = BM_WSCT_RW_RWBOTH;
+		WSCT_HPRI_DIS[0] = 1;
+		WSCT_HPRI_SEL[0] = 0xF;
+		wsct_busid_val[0] = 0xFFFFF;
+		wsct_idMask_val[0] = 0x1FFF;
+		wsct_chn_rank_sel_val[0] = 0xF;
+		wsct_byte_bnd_dis[0] = 1;
+
+		/* wsct 4 : total-ultra*/
+		msel_group_ext_val[4] = BM_MASTER_ALL;
+		wsct_rw_val[4] = BM_WSCT_RW_RWBOTH;
+		WSCT_HPRI_DIS[4] = 0;
+		WSCT_HPRI_SEL[4] = 0x8;  /* ultra */
+		wsct_busid_val[4] = 0xFFFFF;
+		wsct_idMask_val[4] = 0x1FFF;
+		wsct_chn_rank_sel_val[4] = 0xF;
+		wsct_byte_bnd_dis[4] = 1;
+
+
+		/* wsct 5 : total-pre_ultra*/
+		msel_group_ext_val[5] = BM_MASTER_ALL;
+		wsct_rw_val[5] = BM_WSCT_RW_RWBOTH;
+		WSCT_HPRI_DIS[5] = 0;
+		WSCT_HPRI_SEL[5] = 0x4; /* pre_ultra */
+		wsct_busid_val[5] = 0xFFFFF;
+		wsct_idMask_val[5] = 0x1FFF;
+		wsct_chn_rank_sel_val[5] = 0xF;
+		wsct_byte_bnd_dis[5] = 1;
+	}
+
+	if (msel_enable) {
+		/* if ole file node set, use the value */
+		if ( msel_group1 != BM_MASTER_ALL )
+			msel_group_ext_val[1] = msel_group1;
+
+		if ( msel_group2 != BM_MASTER_ALL )
+			msel_group_ext_val[2] = msel_group2;
+
+		if ( msel_group3 != BM_MASTER_ALL )
+			msel_group_ext_val[3] = msel_group3;
+
+	} else {
+		for ( i=1; i<=3; i++) {
+			msel_group_ext_val[i] = BM_MASTER_ALL;
+		}
+	}
+
+	MET_BM_SetWSCT_master_rw(msel_group_ext_val, wsct_rw_val);
+	MET_BM_SetWSCT_high_priority(WSCT_HPRI_DIS, WSCT_HPRI_SEL);
+	MET_BM_SetWSCT_busid_idmask(wsct_busid_val, wsct_idMask_val);
+	MET_BM_SetWSCT_chn_rank_sel(wsct_chn_rank_sel_val);
+	MET_BM_SetWSCT_burst_range(wsct_byte_bnd_dis, wsct_byte_low_bnd_val, wsct_byte_up_bnd_val);
+	MET_BM_SetTSCT_busid_enable(tsct_busid_enable_val);
+
+	MET_BM_SetTtype_high_priority_sel(high_priority_filter, TTYPE_HPRI_SEL);
+	MET_BM_SetTtype_busid_idmask(ttype_busid_val, ttype_idMask_val, ttype1_16_en, ttype17_21_en);
+	MET_BM_SetTtype_chn_rank_sel(ttype_chn_rank_sel_val);
+	MET_BM_SetTtype_burst_range(ttype_byte_bnd_dis, ttype_byte_low_bnd_val, ttype_byte_up_bnd_val);
+
+
+	bmrw0_val = 0;
+	for (i = 0; i < 16; i++)
+		bmrw0_val |= (ttype_rw_val[i] << (i * 2));
+
+	bmrw1_val = 0;
+	for (i = 16; i < 21; i++)
+		bmrw1_val |= (ttype_rw_val[i] << ((i-16) * 2));
+
+	MET_BM_SetTtypeCounterRW(bmrw0_val, bmrw1_val);
+
+#else
+	if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+		if (msel_enable) {
+			msel_group_val[0] = BM_MASTER_ALL;
+			msel_group_val[1] = msel_group1;
+			msel_group_val[2] = msel_group2;
+			msel_group_val[3] = msel_group3;
+		} else {
+			msel_group_val[0] = BM_MASTER_ALL;
+			msel_group_val[1] = BM_MASTER_ALL;
+			msel_group_val[2] = BM_MASTER_ALL;
+			msel_group_val[3] = BM_MASTER_ALL;
+		}
+
+		MET_BM_SetLatencyCounter(1);    /*enable latency count*/
+
+		for (i = 1; i <= 4; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 msel_group_val[i - 1] & BM_MASTER_ALL,
+						 BM_TRANS_TYPE_4BEAT |
+						 BM_TRANS_TYPE_8Byte |
+						 BM_TRANS_TYPE_BURST_WRAP);
+			MET_BM_SetbusID(i, 0);
+			MET_BM_SetbusID_En(i, 0);       /*disable ttype bus sel*/
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 0);       /*disable tp filter*/
+
+	} else if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable == 1)) {
+		MET_BM_SetLatencyCounter(1);    /*enable latency count*/
+
+		for (i = 1; i <= 4; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			MET_BM_SetbusID_En(i, 0);       /*disable ttype bus sel*/
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 1);       /*enable tp filter*/
+
+	} else if ((ttype1_16_en == BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+		MET_BM_SetLatencyCounter(0);    /*disable latency count*/
+
+		for (i = 1; i <= 16; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			/*disenable ttype bus sel if busid > 0xff_ff*/
+			MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 0);       /*disable tp filter*/
+	} else {	/* (ttype1_16_en == BM_TTYPE1_16_ENABLE)  &&  (emi_TP_busfiltr_enable == 1) */
+		MET_BM_SetLatencyCounter(0);    /*disable latency count*/
+
+		for (i = 1; i <= 16; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			/*disable ttype bus sel if busid > 0xff_ff*/
+			MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+		}
+		for (i = 0; i < 4; i++)
+			MET_BM_Set_WsctTsct_id_sel(i, 1);       /*enable tp filter*/
+	}
+
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+		for (i = 17; i <= 21; i++) {
+			MET_BM_SetMonitorCounter(i,
+						 ttype_master_val[i - 1],
+						 ttype_nbeat_val[i - 1] |
+						 ttype_nbyte_val[i - 1] |
+						 ttype_burst_val[i - 1]);
+			MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+			/*disable ttype bus sel if busid > 0xff_ff*/
+			MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+		}
+	}
+
+	bmrw0_val = 0;
+	for (i = 0; i < 16; i++)
+		bmrw0_val |= (ttype_rw_val[i] << (i * 2));
+
+	bmrw1_val = 0;
+	for (i = 16; i < 21; i++)
+		bmrw1_val |= (ttype_rw_val[i] << ((i-16) * 2));
+
+	MET_BM_SetTtypeCounterRW(bmrw0_val, bmrw1_val);
+
+	for (i = 0; i < BM_COUNTER_MAX; i++) {
+		if ((high_priority_filter & (1 << i)) == 0)
+			enable = 0;
+		else
+			enable = 1;
+
+		MET_BM_SetUltraHighFilter(i + 1, enable);
+	}
+
+
+#endif
+	met_record_dramc_dcm_enable_flag();
+
+	if (met_emi_regdump == 1)
+		emi_dump_reg();
+}
+
+
+static void emi_uninit(void)
+{
+	MET_BM_RestoreCfg();
+}
+
+static inline void emi_start(void)
+{
+	MET_BM_Enable(1);
+}
+
+
+static inline void emi_stop(void)
+{
+	MET_BM_Enable(0);
+}
+
+
+static inline int do_emi(void)
+{
+	return met_emi.mode;
+}
+
+
+noinline void DRAM_DVFS(unsigned int dram_data_rate_MHz)
+{
+	MET_TRACE("%u\n", dram_data_rate_MHz);
+}
+
+
+static unsigned int emi_bw_limiter(unsigned int *__restrict__ array)
+{
+	int idx = 0;
+	unsigned int dram_data_rate_MHz;
+
+	if (get_dram_data_rate_symbol) {
+		dram_data_rate_MHz = get_dram_data_rate_symbol();
+	} else {
+		METERROR("get_dram_data_rate_symbol = NULL\n");
+		dram_data_rate_MHz = 0;
+	}
+
+	/* print dram data rate */
+	DRAM_DVFS(dram_data_rate_MHz);
+
+	/* get correct dram_clock_rate */
+	array[idx++] = dram_data_rate_MHz;
+
+	/* get correct ARB A->LAST */
+	array[idx++] = MET_EMI_GetARBA();
+	array[idx++] = MET_EMI_GetARBB();
+	array[idx++] = MET_EMI_GetARBC();
+	array[idx++] = MET_EMI_GetARBD();
+	array[idx++] = MET_EMI_GetARBE();
+	array[idx++] = MET_EMI_GetARBF();
+	array[idx++] = MET_EMI_GetARBG();
+	array[idx++] = MET_EMI_GetARBH();
+	/* EMI Total BW Thresholds */
+	array[idx++] = MET_EMI_GetBWCT0();
+	array[idx++] = MET_EMI_GetBWCT1();
+	array[idx++] = MET_EMI_GetBWCT2();
+	array[idx++] = MET_EMI_GetBWCT3();
+	array[idx++] = MET_EMI_GetBWCT4();
+	array[idx++] = MET_EMI_GetBWST0();
+	array[idx++] = MET_EMI_GetBWST1();
+	/* EMI C+G BW Thresholds */
+	array[idx++] = MET_EMI_GetBWCT0_2ND();
+	array[idx++] = MET_EMI_GetBWCT1_2ND();
+	array[idx++] = MET_EMI_GetBWST_2ND();
+
+	return idx;
+}
+
+
+static void _ms_dramc(unsigned int *__restrict__ dramc_pdir_value, int dram_chann_num)
+{
+	MET_DRAMC_GetDebugCounter(dramc_pdir_value, dram_chann_num);
+}
+
+static unsigned int emi_polling_ext(unsigned int *__restrict__ emi_value_ext)
+{
+	int i = 0;
+	int emi_value_ext_amount = WSCT_AMOUNT - NWSCT;
+
+
+	for ( i=0; i< emi_value_ext_amount; i++) {
+		emi_value_ext[i] = MET_BM_GetWordCount(NWSCT + i + 1);
+	}
+
+	return i;
+}
+
+static unsigned int emi_polling(unsigned int *__restrict__ emi_value, unsigned int *__restrict__ emi_tsct,
+				unsigned int *__restrict__ emi_ttype_value, unsigned int *__restrict__ dramc_pdir_value,
+				unsigned int *__restrict__ emi_mdct_value)
+{
+	int j = 4;              /* skip 4 WSCTs */
+	int i = 0;              /* ttype start at 0 */
+	int k = 0;              /* tsct start at 0 */
+	int n;
+
+	/* Get Word Count */
+
+	emi_value[0] = MET_BM_GetWordCount(1);  /* All */
+	emi_value[1] = MET_BM_GetWordCount(2);  /* Group 1 */
+	emi_value[2] = MET_BM_GetWordCount(3);  /* Group 2 */
+	emi_value[3] = MET_BM_GetWordCount(4);  /* Group 3 */
+
+	if (ttype1_16_en != BM_TTYPE1_16_ENABLE) {      /*1~21 NOT for ttype*/
+		/* Get Latency */
+		j += MET_BM_GetLatencyCycle(emi_value + j, 1, 8);
+
+		/* Get Trans. */
+		j += MET_BM_GetLatencyCycle(emi_value + j, 9, 16);
+	} else {
+		for (n = 4; n < 20; n++)
+			emi_value[n] = 0;
+		j = 20;
+
+		i += MET_BM_GetLatencyCycle(emi_ttype_value + i, 1, 8);
+
+		/* Get Trans. */
+		i += MET_BM_GetLatencyCycle(emi_ttype_value + i, 9, 16);
+	}
+
+	/* Get BACT/BSCT/BCNT/WACT/DCM_CTRL */
+	emi_value[j++] = MET_BM_GetBandwidthWordCount(); /* 20 */
+	emi_value[j++] = MET_BM_GetOverheadWordCount();
+	emi_value[j++] = MET_BM_GetBusCycCount();
+	emi_value[j++] = MET_BM_GetWordAllCount();
+	emi_value[j++] = MET_DRAMC_DCM_CTRL(0);
+
+	/* Get TACT */
+	emi_value[j++] = MET_BM_GetTransAllCount();
+
+	/* Get PageHist/PageMiss/InterBank/Idle */
+	for (n = 0; n < dram_chann_num; n++) {
+		emi_value[j++] = MET_DRAMC_GetPageHitCount(DRAMC_ALL, n);
+		emi_value[j++] = MET_DRAMC_GetPageMissCount(DRAMC_ALL, n);
+		emi_value[j++] = MET_DRAMC_GetInterbankCount(DRAMC_ALL, n);
+		emi_value[j++] = MET_DRAMC_GetIdleCount(n);
+		emi_value[j++] = ((MET_DRAMC_Misc_Status(n) >> 8) & 0x7); /* refresh rate */
+		emi_value[j++] = MET_DRAMC_RefPop(n);
+		emi_value[j++] = MET_DRAMC_Free26M(n);
+		emi_value[j++] = MET_DRAMC_RByte(n);
+		emi_value[j++] = MET_DRAMC_WByte(n);
+	}
+	/* TTYPE */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE)    /*17~21 for ttype*/
+		MET_BM_GetLatencyCycle(emi_ttype_value + 16, 17, 21);
+
+	/* Get tsct */
+	if (emi_tsct_enable == 1) {
+		emi_tsct[k++] = MET_BM_GetTransCount(1);
+		emi_tsct[k++] = MET_BM_GetTransCount(2);
+		emi_tsct[k++] = MET_BM_GetTransCount(3);
+	}
+	/*get mdct rsv buffer*/
+	if (emi_mdct_enable == 1) {
+		emi_mdct_value[0] = (MET_BM_GetMDCT() >> 16) & 0x7;
+		emi_mdct_value[1] = (MET_BM_GetMDCT_2() & 0x7);
+	}
+
+	if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 )
+		_ms_dramc(dramc_pdir_value, dram_chann_num);
+
+	return j;
+}
+
+
+/*======================================================================*/
+/*	MET Device Operations						*/
+/*======================================================================*/
+static int emi_inited;
+
+static int met_emi_create(struct kobject *parent)
+{
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < 21; i++) {
+		ttype_master_val[i] = BM_MASTER_M0;
+		ttype_nbeat_val[i] = BM_TRANS_TYPE_1BEAT;
+		ttype_nbyte_val[i] = BM_TRANS_TYPE_8Byte;
+		ttype_burst_val[i] = BM_TRANS_TYPE_BURST_INCR;
+		ttype_busid_val[i] = 0xfffff;   /*default disable ttype bus sel if busid > 0xff_ff */
+		ttype_rw_val[i] =  BM_TRANS_RW_DEFAULT;
+	}
+
+	_clear_msel_group_ext();
+	_clear_wsct_rw();
+	_clear_wsct_high_priority_enable();
+	_clear_wsct_busid();
+	_clear_wsct_chn_rank_sel();
+	_clear_wsct_burst_range();
+
+	_clear_tsct_busid_enable();
+	_clear_ttype_high_priority_ext();
+	_clear_ttype_high_priority_ext();
+	_clear_ttype_busid_ext();
+	_clear_ttype_chn_rank_sel();
+	_clear_ttype_burst_range();
+
+	reserve_wsct_setting = 0;
+
+
+	ret = MET_BM_Init();
+	if (ret != 0) {
+		pr_notice("MET_BM_Init failed!!!\n");
+		ret = 0;        /* will retry later */
+	} else {
+		emi_inited = 1;
+	}
+
+	kobj_emi = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+	do { \
+		ret = sysfs_create_file(kobj_emi, &attr_name ## _attr.attr); \
+		if (ret != 0) { \
+			pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+			return ret; \
+		} \
+	} while (0)
+	KOBJ_ATTR_LIST;
+#undef  KOBJ_ATTR_ITEM
+
+	return ret;
+}
+
+
+static void met_emi_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+	sysfs_remove_file(kobj_emi, &attr_name ## _attr.attr)
+	if (kobj_emi != NULL) {
+		KOBJ_ATTR_LIST;
+		kobj_emi = NULL;
+	}
+#undef  KOBJ_ATTR_ITEM
+
+	if (emi_inited)
+		MET_BM_DeInit();
+}
+
+
+static void met_emi_start(void)
+{
+	unsigned int bw_limiter[NIDX_BL];
+
+	if (!emi_inited) {
+		if (MET_BM_Init() != 0) {
+			met_emi.mode = 0;
+			pr_notice("MET_BM_Init failed!!!\n");
+			return;
+		}
+		emi_inited = 1;
+	}
+
+	if (do_emi()) {
+		emi_init();
+		MET_BM_Clear_Start();
+		/* Draw the first BW Limiter point */
+		if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+			emi_bw_limiter(bw_limiter);
+			ms_bw_limiter(NIDX_BL, bw_limiter);
+			/* init countdown value */
+			countdown = CNT_COUNTDOWN;
+		}
+	}
+}
+
+
+static void met_emi_stop(void)
+{
+	unsigned int bw_limiter[NIDX_BL];
+
+	if (!emi_inited)
+		return;
+
+	if (met_emi_regdump == 1)
+		emi_dump_reg();
+
+	if (do_emi()) {
+		/* Draw the last BW Limiter point */
+		if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+			/*
+			 * Skip drawing when we just draw
+			 * the point at last polling.
+			 */
+			if (countdown < CNT_COUNTDOWN) {
+				emi_bw_limiter(bw_limiter);
+				ms_bw_limiter(NIDX_BL, bw_limiter);
+			}
+		}
+
+		emi_stop();
+		emi_uninit();
+	}
+}
+
+
+/* DRS output */
+noinline void emi_drs(uint32_t *value)
+{
+	MET_TRACE("%u,%u,%u,%u,%u,%u\n", value[0], value[1], value[2], value[3], value[4], value[5]);
+}
+
+/* DRS output */
+noinline void emi_ddr_ratio(unsigned int ddr_ratio)
+{
+	MET_TRACE("%u\n", ddr_ratio);
+}
+
+static void met_emi_polling(unsigned long long stamp, int cpu)
+{
+	unsigned int emi_value[NIDX];
+	unsigned int emi_tsct[3];
+	unsigned int emi_ttype_value[21];
+	unsigned int dramc_pdir_value[DRAMC_Debug_MAX_CNT * NCH];
+	unsigned int emi_mdct_value[2];
+	unsigned int chn_emi_drs[6];
+	unsigned int emi_value_ext[WSCT_AMOUNT - NWSCT];
+	unsigned int emi_ddr_ratio_val;
+
+	if (!do_emi())
+		return;
+
+	/* print the dram div ratio first */
+	emi_ddr_ratio_val = MET_EMI_Get_BaseClock_Rate();
+	emi_ddr_ratio(emi_ddr_ratio_val);
+
+
+	/* get emi & dramc counters */
+	emi_value[0] = 0;       /* 0: pure linux MET , 0xa5: OnDieMET*/
+	emi_value[1] = 0;       /* EBM pause duration (ns)*/
+
+	MET_BM_Pause();
+
+	emi_polling(emi_value + 2, emi_tsct, emi_ttype_value, dramc_pdir_value, emi_mdct_value);
+	emi_polling_ext(emi_value_ext);
+
+	MET_BM_Continue();
+	MET_BM_Clear_Start();
+
+	/* get and output BW Limiter */
+	if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+		unsigned int bw_limiter[NIDX_BL];
+
+		if (countdown > 0) {
+			countdown--;
+		} else {
+			emi_bw_limiter(bw_limiter);
+			ms_bw_limiter(NIDX_BL, bw_limiter);
+			/* reload countdown value */
+			countdown = CNT_COUNTDOWN;
+		}
+	}
+
+	/* output emi */
+	ms_emi(NIDX_EMI - NTTYPE + (NCNT * dram_chann_num), emi_value);
+	ms_emi_ext(WSCT_AMOUNT - NWSCT, emi_value_ext);
+
+	/* output tsct*/
+	if (emi_tsct_enable == 1)
+		ms_emi_tsct(TSCT_AMOUNT, emi_tsct);
+
+	/* output mdct*/
+	if (emi_mdct_enable == 1)
+		ms_emi_mdct(2, emi_mdct_value);
+
+	/* output dramc*/
+	if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 )
+		ms_dramc(DRAMC_Debug_MAX_CNT * dram_chann_num, dramc_pdir_value);
+
+	/* output ms_ttype */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE)
+		ms_ttype(21, emi_ttype_value);
+
+	/* adjust MDMCU buffer */
+	if (mdmcu_sel_enable == 1)
+		MET_BM_SetMDCT_MDMCU(rd_mdmcu_rsv_num);
+
+	/* DRS handling */
+	met_get_drs_registers(chn_emi_drs);
+	emi_drs(chn_emi_drs);
+}
+
+
+static void met_emi_resume(void)
+{
+	/* return directly when emi was closed */
+	if (!do_emi())
+		return;
+
+	/* remap EMI_BM related reg*/
+	emi_init();
+
+	/* restarn counting */
+	MET_BM_Clear_Start();
+}
+
+
+static const char help[] = "  --emi                                 monitor EMI banwidth\n";
+static int emi_print_help(char *buf, int len)
+{
+	return snprintf(buf, PAGE_SIZE, help);
+}
+
+
+#define TTYPE_NAME_STR_LEN  64
+/* static char ttype_name[21][TTYPE_NAME_STR_LEN]; */
+static int emi_print_header(char *buf, int len)
+{
+	int ret = 0;
+/*	int ret_m[21]; */
+	int i = 0;
+
+#if 1 /* move to AP side print header */
+/*#ifndef CONFIG_MTK_TINYSYS_SSPM_SUPPORT*/
+	unsigned int dram_data_rate_MHz;
+	unsigned int DRAM_TYPE;
+	unsigned int base_clock_rate;
+#endif
+
+#if 0 /* SEDA 3.0 and early*/
+	if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+		/* master selection header */
+		if (msel_enable) {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+					msel_group1 & BM_MASTER_ALL,
+					msel_group2 & BM_MASTER_ALL,
+					msel_group3 & BM_MASTER_ALL);
+		} else {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+					BM_MASTER_ALL & BM_MASTER_ALL,
+					BM_MASTER_ALL & BM_MASTER_ALL,
+					BM_MASTER_ALL & BM_MASTER_ALL);
+		}
+	} else {
+		/*ttype master if BM_TTYPE1_16_ENABLE or emi_TP_busfiltr_enable*/
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: met_emi_ttype_master: %x,%x,%x,%x\n",
+				ttype_master_val[0], ttype_master_val[1], ttype_master_val[2], ttype_master_val[3]);
+
+		if (emi_TP_busfiltr_enable == 1) {
+			/* busID if emi_TP_busfiltr_enable*/
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"met-info [000] 0.0: met_emi_ttype_busid: %x,%x,%x,%x\n",
+					ttype_busid_val[0], ttype_busid_val[1], ttype_busid_val[2], ttype_busid_val[3]);
+		}
+	}
+#endif
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+		"met-info [000] 0.0: met_emi_wsct_amount: %d\n",WSCT_AMOUNT);
+
+	/* master selection header */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+		"met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+		msel_group_ext_val[1] & BM_MASTER_ALL,
+		msel_group_ext_val[2] & BM_MASTER_ALL,
+		msel_group_ext_val[3] & BM_MASTER_ALL);
+
+	/*Ttype RW type header*/
+	PR_BOOTMSG("rwtype=%d\n",rwtype);
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_rw_cfg: ");
+	if (rwtype == BM_READ_ONLY)
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "R");
+	else if (rwtype == BM_WRITE_ONLY)
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "W");
+	else
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "BOTH");
+
+	for (i = 0; i < 21; i++) {
+		if (ttype_rw_val[i] == BM_TRANS_RW_DEFAULT)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",DEFAULT");
+		else if (ttype_rw_val[i] == BM_TRANS_RW_READONLY)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",R");
+		else if (ttype_rw_val[i] == BM_TRANS_RW_WRITEONLY)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",W");
+		else    /*BM_TRANS_RW_RWBOTH*/
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, ",BOTH");
+	}
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+	/*ultra header*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_emi_ultra_filter: %x\n", high_priority_filter);
+
+	/* ttype header */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+		int i = 0;
+		int j = 0;
+
+		/* ttype master list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_master_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_master_list_item); j++) {
+				if (ttype_master_val[i] == ttype_master_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_master_list_item[j].val);
+				}
+			}
+		}
+		/* remove the last comma */
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype busid list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_busid_list: ");
+		for (i = 0; i < 21; i++)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,", ttype_busid_val[i]);
+
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype nbeat list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_nbeat_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_nbeat_list_item); j++) {
+				if (ttype_nbeat_val[i] == ttype_nbeat_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,", ttype_nbeat_list_item[j].val);
+				}
+			}
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype nbyte list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_nbyte_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_nbyte_list_item); j++) {
+				if (ttype_nbyte_val[i] == ttype_nbyte_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,", ttype_nbyte_list_item[j].val);
+				}
+			}
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		/* ttype burst list */
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_burst_list: ");
+		for (i = 0; i < 21; i++) {
+			for (j = 0; j < ARRAY_SIZE(ttype_burst_list_item); j++) {
+				if (ttype_burst_val[i] == ttype_burst_list_item[j].key) {
+					ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_burst_list_item[j].val);
+				}
+			}
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+	}
+	/* ttype enable */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_enable: %d,%d\n",ttype1_16_en, ttype17_21_en);
+
+
+#if 1 /*SEDA 3.5*/
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+		"met-info [000] 0.0: met_emi_msel_ext: %x,%x,%x\n",
+		msel_group_ext_val[0] & BM_MASTER_ALL,
+		msel_group_ext_val[4] & BM_MASTER_ALL,
+		msel_group_ext_val[5] & BM_MASTER_ALL);
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_wsct_rw: ");
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		if (wsct_rw_val[i] == BM_WSCT_RW_RWBOTH)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "RW,");
+		else if (wsct_rw_val[i] == BM_WSCT_RW_READONLY)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "R,");
+		else if (wsct_rw_val[i] == BM_WSCT_RW_WRITEONLY)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "W,");
+		else    /*disable*/
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "NONE,");
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_wsct_HPRI_DIS: ");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,",WSCT_HPRI_DIS[i]);
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_wsct_HPRI_SEL: ");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",WSCT_HPRI_SEL[i]);
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_wsct_busid: ");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",wsct_busid_val[i]);
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_wsct_idMask: ");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",wsct_idMask_val[i]);
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: wsct_chn_rank_sel: ");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",wsct_chn_rank_sel_val[i]);
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: wsct_byte_bnd_dis: ");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,",wsct_byte_bnd_dis[i]);
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: wsct_byte_low_bnd: ");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",wsct_byte_low_bnd_val[i]);
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: wsct_byte_up_bnd: ");
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",wsct_byte_up_bnd_val[i]);
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: tsct_busid_enable: ");
+	for (i=0;i<TSCT_AMOUNT;i++) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,",tsct_busid_enable_val[i]);
+	}
+	snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+	/***************************** ttype ****************************************/
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: TTYPE_HPRI_SEL: ");
+		for (i=0;i<BM_COUNTER_MAX;i++) {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",TTYPE_HPRI_SEL[i]);
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ttype_idMask: ");
+		for (i=0;i<BM_COUNTER_MAX;i++) {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",ttype_idMask_val[i]);
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ttype_chn_rank_sel: ");
+		for (i=0;i<BM_COUNTER_MAX;i++) {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",ttype_chn_rank_sel_val[i]);
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ttype_byte_bnd_dis: ");
+		for (i=0;i<BM_COUNTER_MAX;i++) {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,",ttype_byte_bnd_dis[i]);
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ttype_byte_low_bnd_val: ");
+		for (i=0;i<BM_COUNTER_MAX;i++) {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",ttype_byte_low_bnd_val[i]);
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: ttype_byte_up_bnd_val: ");
+		for (i=0;i<BM_COUNTER_MAX;i++) {
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,",ttype_byte_up_bnd_val[i]);
+		}
+		snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+	}
+#endif
+
+	/*IP version*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: DRAMC_VER: %d\n", DRAMC_VER);
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: EMI_VER: %d.%d\n", EMI_VER_MAJOR, EMI_VER_MINOR);
+
+#if 1 /* SEDA3.5 header print move to AP side */
+/*#ifndef CONFIG_MTK_TINYSYS_SSPM_SUPPORT*/
+	dram_chann_num = MET_EMI_GetDramChannNum();
+	/*	met_dram_chann_num_header
+	 *	channel number
+	 *	LP4: 2, LP3: 1
+	 */
+
+	/*
+	 *	the ddr type define :
+	 *	enum DDRTYPE {
+	 *	TYPE_LPDDR3 = 1,
+	 *	TYPE_LPDDR4,
+	 *	TYPE_LPDDR4X,
+	 *	TYPE_LPDDR2
+	 *	};
+	 */
+	if (!get_cur_ddr_ratio_symbol)
+		PR_BOOTMSG("[%s][%d]get_cur_ddr_ratio_symbol = NULL , use the TYPE_LPDDR4 get_cur_ddr_ratio_symbol\n", __func__, __LINE__);
+
+	if (get_ddr_type_symbol) {
+		DRAM_TYPE = get_ddr_type_symbol();
+
+		base_clock_rate = MET_EMI_Get_BaseClock_Rate();
+
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_type: %d\n", DRAM_TYPE);
+
+		if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+					dram_chann_num, base_clock_rate,
+					DRAM_IO_BUS_WIDTH_LP4, DRAM_DATARATE);
+		else
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+					dram_chann_num, base_clock_rate,
+					DRAM_IO_BUS_WIDTH_LP3, DRAM_DATARATE);
+	} else
+		METERROR("[%s][%d]get_ddr_type_symbol = NULL , use the TYPE_LPDDR3 setting\n", __func__, __LINE__);
+
+	/* metemi_func_opt for middleware */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: metemi_func_opt_header: %d\n",
+			metemi_func_opt);
+
+	/* met_emi_clockrate */
+	if (get_dram_data_rate_symbol) {
+		dram_data_rate_MHz = get_dram_data_rate_symbol();
+	} else {
+		METERROR("get_dram_data_rate_symbol = NULL\n");
+		dram_data_rate_MHz = 0;
+	}
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_dram_clockrate: %d\n",
+			dram_data_rate_MHz);
+
+	/* 1 : by ondiemet, 0: by pure linux */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: emi_use_ondiemet: %u\n",
+			emi_use_ondiemet);
+
+	/*dram bank num*/
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_dram_rank_num_header: %u,%u\n", MET_EMI_GetDramRankNum(),
+				MET_EMI_GetDramRankNum());
+
+	/* ms_emi header */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"# ms_emi: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+	for (i = 0; i < dram_chann_num; i++) {
+		if (i != 0)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					",");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"read_bytes_%d,write_bytes_%d", i, i);
+	}
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: met_emi_header: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+	for (i = 0; i < dram_chann_num; i++) {
+		if (i != 0)
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					",");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"read_bytes_%d,write_bytes_%d", i, i);
+	}
+	ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+	/*TSCT header*/
+	if (emi_tsct_enable == 1) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: ms_emi_tsct_header: ms_emi_tsct,");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"tsct1,tsct2,tsct3\n");
+	}
+
+	/*MDCT header*/
+	if (emi_mdct_enable == 1) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: ms_emi_mdct_header: ms_emi_mdct,");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"RD_ULTRA,RD_MDMCU\n");
+	}
+
+	/* met_bw_limiter_header */
+	if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: met_bw_limiter_header: CLK,");
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"ARBA,ARBB,ARBC,ARBD,ARBE,ARBF,ARBG,ARBH,BWCT0,BWCT1,BWCT2,BWCT3,BWCT4,BWST0,BWST1,BWCT0_2ND,BWCT1_2ND,BWST_2ND\n");
+	}
+
+	/* DRAM DVFS header */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: DRAM_DVFS_header: datarate(MHz)\n");
+
+	/*PDIR met_dramc_header*/
+	if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 ) {
+		ret += snprintf(buf + ret, PAGE_SIZE - ret,
+				"met-info [000] 0.0: met_dramc_header: ");
+		for (i = 0; i < dram_chann_num; i++) {
+			if (i != 0)
+				ret += snprintf(buf + ret, PAGE_SIZE - ret,
+						",");
+			ret += snprintf(buf + ret, PAGE_SIZE - ret, "freerun_26m_%d,", i);
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"rk0_pre_sb_%d,rk0_pre_pd_%d,rk0_act_sb_%d,rk0_act_pd_%d,", i, i, i, i);
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"rk1_pre_sb_%d,rk1_pre_pd_%d,rk1_act_sb_%d,rk1_act_pd_%d,", i, i, i, i);
+			ret += snprintf(buf + ret, PAGE_SIZE - ret,
+					"rk2_pre_sb_%d,rk2_pre_pd_%d,rk2_act_sb_%d,rk2_act_pd_%d", i, i, i, i);
+		}
+		ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+	}
+
+	/* DRS header */
+	ret += snprintf(buf + ret, PAGE_SIZE - ret,
+			"met-info [000] 0.0: emi_drs_header: ch0_RANK1_GP(%%),ch0_RANK1_SF(%%),ch0_ALL_SF(%%),ch1_RANK1_GP(%%),ch1_RANK1_SF(%%),ch1_ALL_SF(%%)\n");
+#endif
+
+	return ret;
+}
+
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+static int ondiemet_emi_print_header(char *buf, int len)
+{
+	emi_use_ondiemet = 1;
+	/* return emi_print_ondiemet_header(buf, len); */
+	return emi_print_header(buf, len);
+}
+
+
+static void MET_BM_IPI_REGISTER_CB(void)
+{
+	int ret, i;
+	unsigned int rdata;
+	unsigned int ipi_buf[4];
+
+	for (i = 0; i < 4; i++)
+		ipi_buf[i] = 0;
+
+	if (sspm_buf_available == 1) {
+		ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_REGISTER_CB;
+		ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+	}
+}
+
+
+static void MET_BM_IPI_configs(void)
+{
+	int ret, i;
+	unsigned int rdata;
+	unsigned int ipi_buf[4];
+
+	for (i = 0; i < 4; i++)
+		ipi_buf[i] = 0;
+
+	if (sspm_buf_available == 1) {
+		ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_EBM_CONFIGS1;
+		ipi_buf[1] = INTERNAL_MODE << 16;
+		ipi_buf[2] = EMI_VER_MAJOR << 24 | EMI_VER_MINOR << 16 | DRAMC_VER << 8 | 0;
+		ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, (void *)ipi_buf, 0, &rdata, 1);
+	}
+}
+
+
+static void ondiemet_emi_start(void)
+{
+	MET_BM_IPI_REGISTER_CB();
+	if (!emi_inited) {
+		if (MET_BM_Init() != 0) {
+			met_emi.mode = 0;
+			pr_notice("MET_BM_Init failed!!!\n");
+			return;
+		}
+		emi_inited = 1;
+	}
+	MET_BM_IPI_configs();
+
+	if (do_emi())
+		emi_init();
+
+	ondiemet_module[ONDIEMET_SSPM] |= ID_EMI;
+}
+
+
+static void ondiemet_emi_stop(void)
+{
+	if (!emi_inited)
+		return;
+
+	if (met_emi_regdump == 1)
+		emi_dump_reg();
+
+	if (do_emi())
+		emi_uninit();
+
+	if (met_emi_regdump == 1)
+		emi_dump_reg();
+}
+#endif
+
+
+struct metdevice met_emi = {
+	.name			= "emi",
+	.owner			= THIS_MODULE,
+	.type			= MET_TYPE_BUS,
+	.create_subfs		= met_emi_create,
+	.delete_subfs		= met_emi_delete,
+	.cpu_related		= 0,
+	.start			= met_emi_start,
+	.stop			= met_emi_stop,
+	.resume			= met_emi_resume,
+	.timed_polling		= met_emi_polling,
+	.print_help		= emi_print_help,
+	.print_header		= emi_print_header,
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+	.ondiemet_mode		= 1,
+	.ondiemet_start		= ondiemet_emi_start,
+	.ondiemet_stop		= ondiemet_emi_stop,
+	.ondiemet_print_help	= emi_print_help,
+	.ondiemet_print_header	= ondiemet_emi_print_header,
+#else
+	.ondiemet_mode		= 0,
+#endif
+};
diff --git a/src/devtools/met-driver/4.14/mt2731/emi/SEDA3_5/mtk_emi_bm.c b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3_5/mtk_emi_bm.c
new file mode 100644
index 0000000..d965349
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3_5/mtk_emi_bm.c
@@ -0,0 +1,1470 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <mt-plat/sync_write.h>
+#include <mt-plat/mtk_io.h>
+#include "mtk_typedefs.h"
+#include "plf_init.h"
+#include "mtk_emi_bm.h"
+#include "mtk_dramc_reg.h"
+#include "met_drv.h"
+#include "interface.h"
+
+#undef	DEBUG
+#undef	debug_reg
+#ifdef	debug_reg
+static inline unsigned int emi_readl(void __iomem *padr)
+{
+	unsigned int tmp;
+
+	tmp = readl(padr);
+	MET_TRACE("[MET_EMI] RD_Reg: %p: %08x\n", padr, tmp);
+	return tmp;
+}
+
+static inline void __emi_reg_sync_writel(unsigned int data, void __iomem *padr)
+{
+	unsigned int tmp;
+
+	mt_reg_sync_writel(data, padr);
+	tmp = readl(padr);
+	MET_TRACE("[MET_EMI] WR_Reg: %p: %08x, %08x\n", padr, data, tmp);
+}
+
+#define emi_reg_sync_writel(data, adr)  __emi_reg_sync_writel(data, IOMEM(adr))
+
+#else
+#define emi_readl               readl
+#define emi_reg_sync_writel     mt_reg_sync_writel
+#endif
+
+#define MASK_MASTER     0xFF
+#define MASK_TRANS_TYPE 0xFF
+
+static int dram_chann_num;
+static void __iomem *BaseAddrEMI;
+static void __iomem *BaseAddrCHN_EMI[2];
+
+static int dramc0_dcm_enable;
+static int dramc1_dcm_enable;
+
+#define CH0_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[0]) + 0x284)
+#define CH1_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[1]) + 0x284)
+const unsigned int emi_config[] = {
+	EMI_BMEN,
+	EMI_MSEL,
+	EMI_MSEL2,
+	EMI_MSEL3,
+	EMI_MSEL4,
+	EMI_MSEL5,
+	EMI_MSEL6,
+	EMI_MSEL7,
+	EMI_MSEL8,
+	EMI_MSEL9,
+	EMI_MSEL10,
+	EMI_BMID0,
+	EMI_BMID1,
+	EMI_BMID2,
+	EMI_BMID3,
+	EMI_BMID4,
+	EMI_BMID5,
+	EMI_BMID6,
+	EMI_BMID7,
+	EMI_BMID8,
+	EMI_BMID9,
+	EMI_BMID10,
+	EMI_BMEN1,
+	EMI_BMEN2,
+	EMI_BMRW0,
+	EMI_BMRW1,
+	EMI_DBWA,
+	EMI_DBWB,
+	EMI_DBWC,
+	EMI_DBWD,
+	EMI_DBWE,
+	EMI_DBWF,
+	EMI_DBWI,
+	EMI_DBWJ,
+	EMI_DBWK,
+	EMI_DBWA_2ND,
+	EMI_DBWB_2ND,
+	EMI_DBWC_2ND,
+	EMI_DBWD_2ND,
+	EMI_DBWE_2ND,
+	EMI_DBWF_2ND,
+	EMI_TTYPE1_CONA,
+	EMI_TTYPE1_CONB,
+	EMI_TTYPE2_CONA,
+	EMI_TTYPE2_CONB,
+	EMI_TTYPE3_CONA,
+	EMI_TTYPE3_CONB,
+	EMI_TTYPE4_CONA,
+	EMI_TTYPE4_CONB,
+	EMI_TTYPE5_CONA,
+	EMI_TTYPE5_CONB,
+	EMI_TTYPE6_CONA,
+	EMI_TTYPE6_CONB,
+	EMI_TTYPE7_CONA,
+	EMI_TTYPE7_CONB,
+	EMI_TTYPE8_CONA,
+	EMI_TTYPE8_CONB,
+	EMI_TTYPE9_CONA,
+	EMI_TTYPE9_CONB,
+	EMI_TTYPE10_CONA,
+	EMI_TTYPE10_CONB,
+	EMI_TTYPE11_CONA,
+	EMI_TTYPE11_CONB,
+	EMI_TTYPE12_CONA,
+	EMI_TTYPE12_CONB,
+	EMI_TTYPE13_CONA,
+	EMI_TTYPE13_CONB,
+	EMI_TTYPE14_CONA,
+	EMI_TTYPE14_CONB,
+	EMI_TTYPE15_CONA,
+	EMI_TTYPE15_CONB,
+	EMI_TTYPE16_CONA,
+	EMI_TTYPE16_CONB,
+	EMI_TTYPE17_CONA,
+	EMI_TTYPE17_CONB,
+	EMI_TTYPE18_CONA,
+	EMI_TTYPE18_CONB,
+	EMI_TTYPE19_CONA,
+	EMI_TTYPE19_CONB,
+	EMI_TTYPE20_CONA,
+	EMI_TTYPE20_CONB,
+	EMI_TTYPE21_CONA,
+	EMI_TTYPE21_CONB
+};
+#define EMI_CONFIG_MX_NR (sizeof(emi_config)/sizeof(unsigned int))
+static unsigned int emi_config_val[EMI_CONFIG_MX_NR];
+
+/*
+ *   MET_REG_BSET/MET_REG_BCLR:
+ *   reading value before set and clear
+ */
+static inline void MET_REG_BSET(unsigned long reg, u32 shift)
+{
+	unsigned int read_val = 0;
+
+	read_val = emi_readl(IOMEM(reg));
+	emi_reg_sync_writel(read_val | (1 << shift), reg);
+}
+
+
+static inline void MET_REG_BCLR(unsigned long reg, u32 shift)
+{
+	unsigned int read_val = 0;
+
+	read_val = emi_readl(IOMEM(reg));
+	emi_reg_sync_writel(read_val & (~((1 << shift) & 0xFFFFFFFF)), reg);
+}
+
+
+int MET_BM_Init(void)
+{
+	int i;
+	int idx;
+
+	/*emi*/
+	if (!mt_cen_emi_base_get_symbol) {
+		METERROR("[%d]mt_cen_emi_base_get_symbol = NULL\n", __LINE__);
+		PR_BOOTMSG_ONCE("[%d]mt_cen_emi_base_get_symbol = NULL\n", __LINE__);
+		return -1;
+	}
+
+	BaseAddrEMI = mt_cen_emi_base_get_symbol();
+	if (BaseAddrEMI == 0) {
+		METERROR("BaseAddrEMI = 0\n");
+		PR_BOOTMSG_ONCE("BaseAddrEMI = 0\n");
+		return -1;
+	}
+
+	METINFO("MET EMI: map emi to %p\n", BaseAddrEMI);
+	PR_BOOTMSG("MET EMI: map emi to %p\n", BaseAddrEMI);
+
+	/* get dram channel number */
+	dram_chann_num = MET_EMI_GetDramChannNum();
+	METINFO("[%s][%d]dram_chann_num = %d\n", __func__, __LINE__, dram_chann_num);
+
+	if (dram_chann_num > MAX_DRAMC_CHANN) {
+		METERROR("dram_chann_num %d > %d\n", dram_chann_num, MAX_DRAMC_CHANN);
+		PR_BOOTMSG("dram_chann_num %d > %d\n", dram_chann_num, MAX_DRAMC_CHANN);
+		return -1;
+	}
+
+	if (!mt_dramc_nao_chn_base_get_symbol) {
+		METERROR("mt_dramc_nao_cha_base_get = NULL\n");
+		PR_BOOTMSG_ONCE("mt_dramc_nao_cha_base_get = NULL\n");
+		return -1;
+	}
+
+	for (i = 0; i < dram_chann_num; i++) {
+		BaseAddrDRAMC[i] = mt_dramc_nao_chn_base_get_symbol(i);
+		if (BaseAddrDRAMC[i] == 0) {
+			METERROR("BaseAddrDRAMC%d = 0\n", i);
+			PR_BOOTMSG_ONCE("BaseAddrDRAMC%d = 0\n", i);
+			return -1;
+		}
+
+		METINFO("MET EMI: map nao dramc%c to %p\n",'A'+i, BaseAddrDRAMC[i]);
+		PR_BOOTMSG("MET EMI: map nao dramc%c to %p\n", 'A'+i, BaseAddrDRAMC[i]);
+	}
+
+	/*dram DRAMC_DTS_DDRPHY_AO*/
+	/* get DRS base address */
+	if (!mt_ddrphy_chn_base_get_symbol) {
+		METERROR("mt_ddrphy_chn_base_get = NULL\n");
+		PR_BOOTMSG_ONCE("mt_ddrphy_chn_base_get = NULL\n");
+		return -1;
+	}
+
+	if (!mt_chn_emi_base_get_symbol) {
+		METERROR("mt_chn_emi_base_get_symbol = NULL\n");
+		PR_BOOTMSG_ONCE("mt_chn_emi_base_get_symbol = NULL\n");
+		return -1;
+	}
+
+	for (i = 1; i <= dram_chann_num && i < 3; i++) {
+		idx = i - 1;
+		BaseAddrDDRPHY_AO[idx] = mt_ddrphy_chn_base_get_symbol(idx);
+		if (BaseAddrDDRPHY_AO[idx] == 0) {
+			METERROR("BaseAddrDDRPHY_AO[%d] = 0\n", idx);
+			PR_BOOTMSG_ONCE("BaseAddrDDRPHY_AO[%d] = 0\n", idx);
+			return -1;
+		}
+
+		METINFO("MET EMI: map ddrphy%d AO to %p\n", idx, BaseAddrDDRPHY_AO[idx]);
+		PR_BOOTMSG("MET EMI: map ddrphy%d AO to %p\n", idx, BaseAddrDDRPHY_AO[idx]);
+
+		BaseAddrCHN_EMI[idx] = mt_chn_emi_base_get_symbol(idx);
+		if (BaseAddrCHN_EMI[idx] == 0) {
+			METERROR("BaseAddrCHN_EMI[%d] = 0\n", idx);
+			PR_BOOTMSG_ONCE("BaseAddrCHN_EMI[%d] = 0\n", idx);
+			return -1;
+		}
+
+		METINFO("MET EMI: map BaseAddrCHN_EMI[%d] to %p\n", idx, BaseAddrCHN_EMI[idx]);
+		PR_BOOTMSG("MET EMI: map BaseAddrCHN_EMI[%d] to %p\n", idx, BaseAddrCHN_EMI[idx]);
+	}
+
+	/*dram DRAMC_DTS_DRAMC0_AO*/
+	if (!mt_dramc_chn_base_get_symbol) {
+		METERROR("mt_dramc_chn_base_get = NULL\n");
+		PR_BOOTMSG_ONCE("mt_dramc_chn_base_get = NULL\n");
+		return -1;
+	}
+
+	BaseAddrDRAMC0_AO = mt_dramc_chn_base_get_symbol(0);
+	if (BaseAddrDRAMC0_AO == 0) {
+		METERROR("BaseAddrDRAMC0_AO = 0\n");
+		PR_BOOTMSG_ONCE("BaseAddrDRAMC0_AO = 0\n");
+		return -1;
+	}
+
+	METINFO("MET EMI: map AO dramcA to %p\n", BaseAddrDRAMC0_AO);
+	PR_BOOTMSG("MET EMI: map AO dramcA to %p\n", BaseAddrDRAMC0_AO);
+
+	return 0;
+}
+
+
+void MET_BM_DeInit(void)
+{
+}
+
+
+void MET_BM_SaveCfg(void)
+{
+	int i;
+
+	for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+		emi_config_val[i] = emi_readl(IOMEM(ADDR_EMI + emi_config[i]));
+}
+
+
+void MET_BM_RestoreCfg(void)
+{
+	int i;
+
+	for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+		emi_reg_sync_writel(emi_config_val[i], ADDR_EMI + emi_config[i]);
+}
+
+
+void MET_BM_Clear_Start(void)
+{
+	/* Force EMI idle low */
+	MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+	/* Disable dramc dcm */
+	switch (dram_chann_num) {
+	case 1:
+		MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	case 2:
+		MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	default:
+		METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+	}
+
+	/* Disable EBM */
+	MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+
+	/* Enable EBM */
+	MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+
+	/* Enable EMI dcm */
+	MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+	/* restore dramc dcm */
+	switch (dram_chann_num) {
+	case 1:
+		if (dramc0_dcm_enable)
+			MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		else
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	case 2:
+		if (dramc0_dcm_enable)
+			MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		else
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+
+		if (dramc1_dcm_enable)
+			MET_REG_BCLR(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		else
+			MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+		break;
+	default:
+		METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+	}
+}
+
+
+void MET_BM_Enable(const unsigned int enable)
+{
+	unsigned long int value_check;
+	int i = 0;
+
+	while (i < 100) {
+		/* Force EMI idle low */
+		MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+		/* disable dramc dcm */
+		switch (dram_chann_num) {
+		case 1:
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		case 2:
+			MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		default:
+			METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+		}
+
+		if (enable == 0)
+			/* Disable EBM */
+			MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+		else
+			/* Enable EBM */
+			MET_REG_BSET(ADDR_EMI + EMI_BMEN, BUS_MON_EN_SHIFT);
+
+		/* Enable EMI dcm */
+		MET_REG_BCLR(ADDR_EMI + EMI_BMEN, BUS_MON_IDLE_SHIFT);
+
+		/* restore dramc dcm */
+		switch (dram_chann_num) {
+		case 1:
+			if (dramc0_dcm_enable)
+				MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			else
+				MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		case 2:
+			if (dramc0_dcm_enable)
+				MET_REG_BCLR(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			else
+				MET_REG_BSET(CH0_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+
+			if (dramc1_dcm_enable)
+				MET_REG_BCLR(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			else
+				MET_REG_BSET(CH1_MISC_CG_CTRL0, DRAMC_CG_SHIFT);
+			break;
+		default:
+			METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+		}
+
+		value_check = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+		if (enable == 0) {
+			/* EN == 0, IDLE == 0 when EMI RESET */
+			if (!test_bit(BUS_MON_EN_SHIFT, &value_check)
+			    && !test_bit(BUS_MON_IDLE_SHIFT, &value_check)) {
+				break;
+			}
+		} else {
+			/* EN == 1, IDLE == 0 when EMI START */
+			if (test_bit(BUS_MON_EN_SHIFT, &value_check)
+			    && !test_bit(BUS_MON_IDLE_SHIFT, &value_check)) {
+				break;
+			}
+		}
+		i++;
+	}
+
+	/*MET_TRACE("[MET_BM_ENABLE] value_check: %lx, enable = %d\n", value_check, enable); */
+
+}
+
+
+#if 0
+void BM_Disable(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	emi_reg_sync_writel(value & (~BUS_MON_EN), ADDR_EMI + EMI_BMEN);
+}
+#endif
+
+
+void MET_BM_Pause(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	emi_reg_sync_writel(value | (1 << BUS_MON_PAUSE_SHIFT), ADDR_EMI + EMI_BMEN);
+}
+
+
+void MET_BM_Continue(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	emi_reg_sync_writel(value & (~(1 << BUS_MON_PAUSE_SHIFT)), ADDR_EMI + EMI_BMEN);
+}
+
+
+unsigned int MET_BM_IsOverrun(void)
+{
+	/*
+	 * return 0 if EMI_BCNT(bus cycle counts) or
+	 * EMI_WACT(total word counts) is overrun,
+	 * otherwise return an !0 value
+	 */
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	return (value & (1 << BC_OVERRUN_SHIFT));
+}
+
+
+unsigned int MET_BM_GetReadWriteType(void)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	return ((value & 0xFFFFFFCF) >> 4);
+}
+
+
+void MET_BM_SetReadWriteType(const unsigned int ReadWriteType)
+{
+	const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+	/*
+	 * ReadWriteType: 00/11 --> both R/W
+	 *                   01 --> only R
+	 *                   10 --> only W
+	 */
+	emi_reg_sync_writel((value & 0xFFFFFFCF) | (ReadWriteType << 4), ADDR_EMI + EMI_BMEN);
+}
+
+
+int MET_BM_GetBusCycCount(void)
+{
+	return MET_BM_IsOverrun() ? BM_ERR_OVERRUN : emi_readl(IOMEM(ADDR_EMI + EMI_BCNT));	/*Bus cycle counter */
+}
+
+
+unsigned int MET_BM_GetTransAllCount(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_TACT));
+}
+
+
+int MET_BM_GetTransCount(const unsigned int counter_num)
+{
+	unsigned int iCount;
+
+	switch (counter_num) {
+	case 1:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_TSCT));
+		break;
+
+	case 2:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_TSCT2));
+		break;
+
+	case 3:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_TSCT3));
+		break;
+
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+int MET_BM_GetWordAllCount(void)
+{
+	return MET_BM_IsOverrun() ? BM_ERR_OVERRUN : emi_readl(IOMEM(ADDR_EMI + EMI_WACT));
+}
+
+
+int MET_BM_GetWordCount(const unsigned int counter_num)
+{
+	unsigned int iCount;
+
+	switch (counter_num) {
+	case 1:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT));
+		break;
+
+	case 2:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT2));
+		break;
+
+	case 3:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT3));
+		break;
+
+	case 4:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_WSCT4));
+		break;
+
+	case 5:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_DBWG));
+		break;
+
+	case 6:
+		iCount = emi_readl(IOMEM(ADDR_EMI + EMI_DBWH));
+		break;
+
+
+	default:
+		return BM_ERR_WRONG_REQ;
+	}
+
+	return iCount;
+}
+
+
+unsigned int MET_BM_GetBandwidthWordCount(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BACT));	/*Bandwidth counter for access */
+}
+
+
+unsigned int MET_BM_GetOverheadWordCount(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BSCT));	/*Overhead counter */
+}
+
+
+int MET_BM_GetTransTypeCount(const unsigned int counter_num)
+{
+	return (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+	    ? BM_ERR_WRONG_REQ : emi_readl(IOMEM(ADDR_EMI + EMI_TTYPE1 + (counter_num - 1) * 8));
+}
+
+
+int MET_BM_GetMDCT(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT));
+}
+
+
+int MET_BM_GetMDCT_2(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT_2ND));
+}
+
+
+int MET_BM_SetMDCT_MDMCU(unsigned int mdmcu_rd_buf)
+{
+	unsigned int value_origin;
+
+	value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_MDCT_2ND));
+	MET_TRACE("[MET_BM_SetMDCT_MDMCU] value_origin: %x\n", value_origin);
+
+	value_origin = value_origin & ~(0x7);
+	value_origin = value_origin | ((mdmcu_rd_buf) & 0x7);
+
+	emi_reg_sync_writel(value_origin, ADDR_EMI + EMI_MDCT_2ND);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_GetMonitorCounter(const unsigned int counter_num,
+			     unsigned int *master, unsigned int *trans_type)
+{
+	unsigned int value, addr;
+
+	if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+		return BM_ERR_WRONG_REQ;
+
+
+	if (counter_num == 1) {
+		addr = EMI_BMEN;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+		*master = (value >> 16) & MASK_MASTER;
+		*trans_type = (value >> 24) & MASK_TRANS_TYPE;
+	} else {
+		addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+		value = emi_readl(IOMEM(ADDR_EMI + addr)) >> ((counter_num % 2) * 16);
+		*master = value & MASK_MASTER;
+		*trans_type = (value >> 8) & MASK_TRANS_TYPE;
+	}
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+			     const unsigned int master, const unsigned int trans_type)
+{
+	unsigned int value, addr;
+	const unsigned int iMask = (MASK_TRANS_TYPE << 8) | MASK_MASTER;
+
+	if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+		return BM_ERR_WRONG_REQ;
+
+
+	if (counter_num == 1) {
+		addr = EMI_BMEN;
+		value = (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) |
+		    ((trans_type & MASK_TRANS_TYPE) << 24) | ((master & MASK_MASTER) << 16);
+	} else {
+		addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+		/* clear master and transaction type fields */
+		value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+		/* set master and transaction type fields */
+		value |= (((trans_type & MASK_TRANS_TYPE) << 8) |
+			  (master & MASK_MASTER)) << ((counter_num % 2) * 16);
+	}
+
+	emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val)
+{
+
+	unsigned int value_origin;
+
+	value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW0));
+	MET_TRACE("[MET_EMI_settype1] value_origin: %x\n", value_origin);
+	if (value_origin != bmrw0_val) {
+		emi_reg_sync_writel(bmrw0_val, ADDR_EMI + EMI_BMRW0);
+		MET_TRACE("[MET_EMI_settype1] bmrw0_val: %x, value_origin: %x\n", bmrw0_val,
+			   value_origin);
+	}
+
+
+	value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW1));
+	MET_TRACE("[MET_EMI_settype2] value_origin: %x\n", value_origin);
+	if (value_origin != bmrw1_val) {
+		emi_reg_sync_writel(bmrw1_val, ADDR_EMI + EMI_BMRW1);
+		MET_TRACE("[MET_EMI_settype2] bmrw0_val: %x, value_origin: %x\n", bmrw1_val,
+			   value_origin);
+
+	}
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable)
+{
+	unsigned int value;
+
+	if (counter_num > 3)
+		return BM_ERR_WRONG_REQ;
+
+	value =
+	    ((emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & (~(1 << (28 + counter_num)))) |
+	     (enable << (28 + counter_num)));
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master)
+{
+	unsigned int value, addr;
+	const unsigned int iMask = 0x7F;
+
+	if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+		return BM_ERR_WRONG_REQ;
+
+
+	if (counter_num == 1) {
+		addr = EMI_BMEN;
+		value =
+		    (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) | ((master & iMask) << 16);
+	} else {
+		addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+		/* clear master and transaction type fields */
+		value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+		/* set master and transaction type fields */
+		value |= ((master & iMask) << ((counter_num % 2) * 16));
+	}
+
+	emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID_En(const unsigned int counter_num,
+		       const unsigned int enable)
+{
+	unsigned int value;
+
+	if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+		return BM_ERR_WRONG_REQ;
+
+	if (enable == 0) {
+		/* clear  EMI ID selection Enabling   SEL_ID_EN */
+		value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+			 & ~(1 << (counter_num - 1)));
+	} else {
+		/* enable  EMI ID selection Enabling   SEL_ID_EN */
+		value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+			 | (1 << (counter_num - 1)));
+	}
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID(const unsigned int counter_num,
+		    const unsigned int id)
+{
+	unsigned int value, addr, shift_num;
+
+	if ((counter_num < 1 || counter_num > BM_COUNTER_MAX))
+		return BM_ERR_WRONG_REQ;
+
+	/* offset of EMI_BMIDx register */
+	addr = EMI_BMID0 + (counter_num - 1) / 2 * 4;
+	shift_num = ((counter_num - 1) % 2) * 16;
+	/* clear SELx_ID field */
+	value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(EMI_BMID_MASK << shift_num);
+
+	/* set SELx_ID field */
+	if (id <= 0xffff)       /*bigger then 0xff_ff : no select busid in master, reset busid as 0*/
+		value |= id << shift_num;
+
+	emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable)
+{
+	unsigned int value;
+
+	if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+		return BM_ERR_WRONG_REQ;
+
+
+	value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN1))
+		 & ~(1 << (counter_num - 1)))
+		| (enable << (counter_num - 1));
+
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN1);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetLatencyCounter(unsigned int enable)
+{
+	unsigned int value;
+
+	value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & ~(0x3 << 24);
+	/*
+	 * emi_ttype1 -- emi_ttype8 change as total latencies
+	 * for m0 -- m7,
+	 * and emi_ttype9 -- emi_ttype16 change as total transaction counts
+	 * for m0 -- m7
+	 */
+	if (enable == 1)
+		value |= (0x2 << 24);
+
+	emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_GetLatencyCycle(unsigned int *__restrict__ emi_value,
+				const unsigned int begin, const unsigned int end)
+{
+	int i, j = 0;
+
+	for (i = begin - 1; i < end; i++)
+		emi_value[j++] = emi_readl(IOMEM(ADDR_EMI + (EMI_TTYPE1 + i * 8)));
+
+	return j;
+}
+
+
+unsigned int MET_BM_GetEmiDcm(void)
+{
+	return (emi_readl(IOMEM(ADDR_EMI + EMI_CONM)) >> 24);
+}
+
+
+int MET_BM_SetEmiDcm(const unsigned int setting)
+{
+	unsigned int value;
+
+	value = emi_readl(IOMEM(ADDR_EMI + EMI_CONM));
+	emi_reg_sync_writel((value & 0x00FFFFFF) | (setting << 24), ADDR_EMI + EMI_CONM);
+
+	return BM_REQ_OK;
+}
+
+
+unsigned int MET_EMI_GetMDCT(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT));
+}
+
+
+unsigned int MET_EMI_GetMDCT_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_MDCT_2ND));
+}
+
+
+unsigned int MET_EMI_GetARBA(void)
+{
+	/* EMI_ARBA EMI Bandwidth Filter Control M0/1 */
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBA));
+}
+
+
+unsigned int MET_EMI_GetARBB(void)
+{
+	return 0;
+}
+
+
+unsigned int MET_EMI_GetARBC(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBC));
+}
+
+
+unsigned int MET_EMI_GetARBD(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBD));
+}
+
+
+unsigned int MET_EMI_GetARBE(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBE));
+}
+
+
+unsigned int MET_EMI_GetARBF(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBF));
+}
+
+
+unsigned int MET_EMI_GetARBG(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBG));
+}
+
+
+unsigned int MET_EMI_GetARBH(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_ARBH));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT0(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT0));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT1(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT1));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT2(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT2));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT3(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT3));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWCT4(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT4));
+}
+
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWST0(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWST0));
+}
+
+/* Total BW status*/
+unsigned int MET_EMI_GetBWST1(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWST1));
+}
+
+
+/* C+G BW status*/
+unsigned int MET_EMI_GetBWCT0_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT0_2ND));
+}
+
+/* C+G BW status*/
+unsigned int MET_EMI_GetBWCT1_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWCT1_2ND));
+}
+
+
+/* C+G BW status*/
+unsigned int MET_EMI_GetBWST_2ND(void)
+{
+	return emi_readl(IOMEM(ADDR_EMI + EMI_BWST_2ND));
+}
+
+
+unsigned int MET_EMI_GetBMRW0(void)
+{
+	return readl(IOMEM(ADDR_EMI + EMI_BMRW0));
+}
+
+
+void emi_dump_reg(void)
+{
+	int i;
+
+	MET_TRACE("[emi_regdump]\n");
+	for (i = 0x400; i < 0x500; i = i + 16)
+		MET_TRACE("%4x__ %8x %8x %8x %8x\n", i, readl(IOMEM(ADDR_EMI + i)),
+			   readl(IOMEM(ADDR_EMI + i + 4)), readl(IOMEM(ADDR_EMI + i + 8)),
+			   readl(IOMEM(ADDR_EMI + i + 12)));
+
+	for (i = 0xF00; i < 0xFF0; i = i + 16)
+		MET_TRACE("%4x__ %8x %8x %8x %8x\n", i, readl(IOMEM(ADDR_EMI + i)),
+			   readl(IOMEM(ADDR_EMI + i + 4)), readl(IOMEM(ADDR_EMI + i + 8)),
+			   readl(IOMEM(ADDR_EMI + i + 12)));
+
+	MET_TRACE("FF4__ %8x",readl(IOMEM(ADDR_EMI + 0xff4)));
+}
+
+
+unsigned int MET_EMI_GetDramChannNum(void)
+{
+	int num = -1;
+
+	if (BaseAddrEMI) {
+		num = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+		num = ((num >> 8) & 0x0000003);
+	} else {
+		return 1;
+	}
+
+	if (num == M0_DOUBLE_HALF_BW_1CH)
+		return 1;
+	else if (num == M0_DOUBLE_HALF_BW_2CH)
+		return 2;
+	else if (num == M0_DOUBLE_HALF_BW_4CH)
+		return 4;
+	else                    /* default return single channel */
+		return 1;
+}
+
+
+unsigned int MET_EMI_GetDramRankNum(void)
+{
+	int dual_rank = 0;
+
+	if (BaseAddrEMI) {
+		dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+		dual_rank = ((dual_rank >> 17) & RANK_MASK);
+	} else {
+		return DUAL_RANK;
+	}
+
+	if (dual_rank == DISABLE_DUAL_RANK_MODE)
+		return ONE_RANK;
+	else			/* default return dual rank */
+		return DUAL_RANK;
+}
+
+
+/*
+ * Dual Channel:
+ * Enables two rank for CHB
+ * Quad Channel:
+ * Enables two rank  for CHC and CHD
+ * 0: Disable dual rank mode
+ * 1: Enable dual rank mode
+ */
+unsigned int MET_EMI_GetDramRankNum_CHN1(void)
+{
+	int dual_rank = 0;
+
+	if (BaseAddrEMI) {
+		dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+		dual_rank = ((dual_rank >> 16) & RANK_MASK);
+	} else {
+		return DUAL_RANK;
+	}
+
+	if (dual_rank == DISABLE_DUAL_RANK_MODE)
+		return ONE_RANK;
+	else			/* default return dual rank */
+		return DUAL_RANK;
+}
+
+
+void met_get_drs_registers(uint32_t *value)
+{
+	uint32_t tmp;
+
+	memset(value, 0, sizeof(uint32_t) * 6);
+
+	if (BaseAddrCHN_EMI[0] == NULL)
+		return;
+	if (dram_chann_num > 1 && BaseAddrCHN_EMI[1] == NULL)
+		return;
+
+	tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[0] + CHN_EMI_DRS_ST2)) & ((1 << 23) - 1);
+	/* working unit:38.5ns, the counter is update every 16ms */
+	value[0] = (tmp * 3850) / 16000000;
+
+	tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[0] + CHN_EMI_DRS_ST3)) & ((1 << 23) - 1);
+	value[1] = (tmp * 3850) / 16000000;
+
+	tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[0] + CHN_EMI_DRS_ST4)) & ((1 << 23) - 1);
+	value[2] = (tmp * 3850) / 16000000;
+
+	if (dram_chann_num > 1) {
+		tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[1] + CHN_EMI_DRS_ST2)) & ((1 << 23) - 1);
+		value[3] = (tmp * 3850) / 16000000;
+
+		tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[1] + CHN_EMI_DRS_ST3)) & ((1 << 23) - 1);
+		value[4] = (tmp * 3850) / 16000000;
+
+		tmp = emi_readl(IOMEM(BaseAddrCHN_EMI[1] + CHN_EMI_DRS_ST4)) & ((1 << 23) - 1);
+		value[5] = (tmp * 3850) / 16000000;
+	}
+}
+
+
+void met_record_dramc_dcm_enable_flag(void)
+{
+	int reg_val;
+
+	switch (dram_chann_num) {
+	case 1:
+		reg_val = emi_readl(IOMEM(CH0_MISC_CG_CTRL0));
+		dramc0_dcm_enable = !((reg_val >> DRAMC_CG_SHIFT) & 0x1);
+		break;
+	case 2:
+		reg_val = emi_readl(IOMEM(CH0_MISC_CG_CTRL0));
+		dramc0_dcm_enable = !((reg_val >> DRAMC_CG_SHIFT) & 0x1);
+
+		reg_val = emi_readl(IOMEM(CH1_MISC_CG_CTRL0));
+		dramc1_dcm_enable = !((reg_val >> DRAMC_CG_SHIFT) & 0x1);
+		break;
+	default:
+		METERROR("Error: dram_chann_num = %d\n", dram_chann_num);
+	}
+}
+
+unsigned int MET_EMI_Get_BaseClock_Rate(void)
+{
+	unsigned int DRAM_TYPE;
+
+	if (get_cur_ddr_ratio_symbol)
+		return get_cur_ddr_ratio_symbol();
+	else {
+
+		if (get_ddr_type_symbol) {
+			DRAM_TYPE = get_ddr_type_symbol();
+
+			if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+				return DRAM_EMI_BASECLOCK_RATE_LP4;
+			else
+				return DRAM_EMI_BASECLOCK_RATE_LP3;
+
+		} else {
+			return DRAM_EMI_BASECLOCK_RATE_LP4;
+		}
+	}
+}
+
+/* For SEDA3.5 wsct setting*/
+/* EMI_DBWX[15:8],    X=A~F   (SEL_MASTER) */
+/* RW:    EMI_DBWX[1:0],    X=A~F */
+int MET_BM_SetWSCT_master_rw(unsigned int *master , unsigned int *rw)
+{
+	unsigned int value, addr;
+	int i;
+
+	const unsigned int Mask_master = 0xFF;
+	const unsigned int offset_master = 8;
+
+	const unsigned int Mask_rw = 0x3;
+	const unsigned int offset_rw = 0;
+
+	for (i=0; i<WSCT_AMOUNT; i++) {
+		addr = EMI_DBWA + i*4;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_master << offset_master)) | ((*(master+i) & Mask_master) << offset_master);
+		value = (value & ~(Mask_rw << offset_rw)) | ((*(rw+i) & Mask_rw) << offset_rw);
+
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+	}
+
+	return BM_REQ_OK;
+}
+
+int MET_BM_SetWSCT_high_priority(unsigned int *disable, unsigned int *select)
+{
+	unsigned int value, addr;
+	int i;
+
+	const unsigned int Mask_disable = 0x1;
+	const unsigned int offset_disable  = 2;
+
+	const unsigned int Mask_select = 0xF;
+	const unsigned int offset_select  = 28;
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		addr = EMI_DBWA + i*4;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_disable << offset_disable)) | ((*(disable+i) & Mask_disable) << offset_disable);
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+		/* ultra level setting */
+		addr = EMI_DBWA_2ND + i*4;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_select << offset_select)) | ((*(select+i) & Mask_select) << offset_select);
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+	}
+	return BM_REQ_OK;
+}
+
+/* busid enbale: EMI_DBWX[3],    X=A~F */
+/* busid sel: EMI_DBWX[28:16],    X=A~F  (SEL_ID_TMP) */
+/* busid mask : EMI_DBWY[12:0]  或 EMI_DBWY[28:16],  Y=I~K    (SEL_ID_MSK) */
+int MET_BM_SetWSCT_busid_idmask(unsigned int *busid, unsigned int *idMask)
+{
+	unsigned int value, addr;
+	unsigned int enable_tmp, busid_tmp, idmask_tmp;
+	int i;
+
+	const unsigned int Mask_busid = 0x1FFF;
+	const unsigned int offset_busid  = 16;
+
+	const unsigned int Mask_enable = 0x1;
+	const unsigned int offset_enable  = 3;
+
+	const unsigned int Mask_idMask = 0x1FFF;
+	const unsigned int offset_idMask_even  = 0;
+	const unsigned int offset_idMask_odd  = 16;
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+
+		/*enable, SEL_ID_TMP*/
+		if (*(busid+i)>0xffff) {
+			enable_tmp = 0;
+			busid_tmp = 0x1FFF;
+			idmask_tmp = 0x1FFF;
+		}
+		else {
+			enable_tmp = 1;
+			busid_tmp = *(busid+i) & Mask_busid;
+			idmask_tmp = *(idMask+i) & Mask_idMask;
+		}
+
+
+		addr = EMI_DBWA + i*4;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_busid << offset_busid)) | (busid_tmp << offset_busid);
+		value = (value & ~(Mask_enable << offset_enable)) | (enable_tmp << offset_enable);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+		/*SEL_ID_MSK*/
+		addr = EMI_DBWI + (i/2)*4;
+
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		if (i%2==0)
+			value = (value & ~(Mask_idMask << offset_idMask_even)) | (idmask_tmp << offset_idMask_even);
+		else
+			value = (value & ~(Mask_idMask << offset_idMask_odd)) | (idmask_tmp << offset_idMask_odd);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+	}
+
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetWSCT_chn_rank_sel(unsigned int *chn_rank_sel)
+{
+	unsigned int value, addr;
+	int i;
+
+	const unsigned int Mask = 0xF;
+	const unsigned int offset  = 12;
+
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+		addr = EMI_DBWA_2ND + i*4;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask << offset)) | ((*(chn_rank_sel+i) & Mask) << offset);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+	}
+	return BM_REQ_OK;
+}
+
+int MET_BM_SetWSCT_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd)
+{
+	unsigned int value, addr;
+	int i;
+
+	const unsigned int Mask_dis = 0x1, Mask_low_bnd = 0x1FF, Mask_up_bnd = 0x1FF;
+	const unsigned int offset_dis = 4, offset_low_bnd = 16 , offset_up_bnd = 0 ;
+
+
+	for (i=0;i<WSCT_AMOUNT;i++) {
+
+		addr = EMI_DBWA + i*4;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_dis << offset_dis)) | ((*(bnd_dis+i) & Mask_dis) << offset_dis);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+
+		addr = EMI_DBWA_2ND + i*4;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_low_bnd << offset_low_bnd)) | ((*(low_bnd+i) & Mask_low_bnd) << offset_low_bnd);
+		value = (value & ~(Mask_up_bnd << offset_up_bnd)) | ((*(up_bnd+i) & Mask_up_bnd) << offset_up_bnd);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+	}
+	return BM_REQ_OK;
+
+}
+
+int MET_BM_SetTSCT_busid_enable(unsigned int *enable)
+{
+	//MET_BM_Set_WsctTsct_id_sel
+
+	int i;
+
+	for (i=0;i<TSCT_AMOUNT;i++) {
+		MET_BM_Set_WsctTsct_id_sel(i, *(enable+i));
+	}
+
+	return BM_REQ_OK;
+}
+
+//use the origin together, MET_BM_SetUltraHighFilter()
+/* EMI_TTYPEN_CONA [23:20],  N=1~21   (HPRI_SEL) */
+int MET_BM_SetTtype_high_priority_sel(unsigned int _high_priority_filter, unsigned int *select)
+{
+	int i;
+	unsigned int enable;
+	unsigned int value, addr;
+
+	const unsigned int Mask_sel = 0xF;
+	const unsigned int offset_sel = 20;
+
+	for (i = 0; i < BM_COUNTER_MAX; i++) {
+		if ((_high_priority_filter & (1 << i)) == 0){
+			enable = 0;
+		}
+		else {
+			enable = 1;
+		}
+
+		MET_BM_SetUltraHighFilter(i + 1, enable);
+
+		/* ultra level select */
+		addr = EMI_TTYPE1_CONA + i*8;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_sel << offset_sel)) | ((*(select+i) & Mask_sel) << offset_sel);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	}
+
+	return BM_REQ_OK;
+}
+
+
+//always call this API to init the reg
+//related API, MET_BM_SetbusID, MET_BM_SetbusID_En
+int MET_BM_SetTtype_busid_idmask(unsigned int *busid, unsigned int *idMask, int _ttype1_16_en, int _ttype17_21_en)
+{
+	int i;
+	unsigned int value, addr;
+
+	const unsigned int Mask_idMask = 0x1FFF;
+	const unsigned int offset_idMask = 0;
+
+	if (_ttype1_16_en != BM_TTYPE1_16_ENABLE) {
+		/* mask set 0x1FFF , busid set disable*/
+		for (i = 1; i <= 16; i++) {
+			*(busid + i - 1) = 0xfffff;
+			*(idMask + i - 1) = 0x1FFF;
+		}
+	}
+
+	if (_ttype17_21_en != BM_TTYPE17_21_ENABLE) {
+		for (i = 17; i <= 21; i++) {
+			*(busid + i - 1) = 0xfffff;
+			*(idMask + i - 1) = 0x1FFF;
+		}
+	}
+
+	for (i = 1; i <= BM_COUNTER_MAX; i++) {
+		MET_BM_SetbusID(i, *(busid + i - 1));
+		MET_BM_SetbusID_En(i, ( *(busid + i - 1) > 0xffff) ? 0 : 1);
+
+		/* set idMask */
+		addr = EMI_TTYPE1_CONA + (i-1)*8;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_idMask << offset_idMask)) | ((*(idMask+i-1) & Mask_idMask) << offset_idMask);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+	}
+
+	return BM_REQ_OK;
+}
+
+
+int MET_BM_SetTtype_chn_rank_sel(unsigned int *chn_rank_sel)
+{
+	unsigned int value, addr;
+	int i;
+
+	const unsigned int Mask = 0xF;
+	const unsigned int offset  = 16;
+
+
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+		addr = EMI_TTYPE1_CONA + i*8;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask << offset)) | ((*(chn_rank_sel+i) & Mask) << offset);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+	}
+	return BM_REQ_OK;
+}
+
+int MET_BM_SetTtype_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd)
+{
+	unsigned int value, addr;
+	int i;
+
+	const unsigned int Mask_dis = 0x1, Mask_low_bnd = 0x1FF, Mask_up_bnd = 0x1FF;
+	const unsigned int offset_dis = 24, offset_low_bnd = 16 , offset_up_bnd = 0 ;
+
+
+	for (i=0;i<BM_COUNTER_MAX;i++) {
+
+		/* set dis bit */
+		addr = EMI_TTYPE1_CONA + i*8;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_dis << offset_dis)) | ((*(bnd_dis+i) & Mask_dis) << offset_dis);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+
+		addr = EMI_TTYPE1_CONB + i*8;
+		value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+		value = (value & ~(Mask_low_bnd << offset_low_bnd)) | ((*(low_bnd+i) & Mask_low_bnd) << offset_low_bnd);
+		value = (value & ~(Mask_up_bnd << offset_up_bnd)) | ((*(up_bnd+i) & Mask_up_bnd) << offset_up_bnd);
+
+		emi_reg_sync_writel(value, ADDR_EMI + addr);
+	}
+	return BM_REQ_OK;
+}
diff --git a/src/devtools/met-driver/4.14/mt2731/emi/SEDA3_5/mtk_emi_bm.h b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3_5/mtk_emi_bm.h
new file mode 100644
index 0000000..bd8dba2
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/emi/SEDA3_5/mtk_emi_bm.h
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#ifndef __MT_MET_EMI_BM_H__
+#define __MT_MET_EMI_BM_H__
+
+#define EMI_VER_MAJOR  3
+#define EMI_VER_MINOR  5
+
+#define FILE_NODE_DATA_LEN 512 
+#define WSCT_AMOUNT 6
+#define TSCT_AMOUNT 3
+
+#define DEF_BM_RW_TYPE          (BM_BOTH_READ_WRITE)
+#define NTS                     2
+#define NWSCT                   4
+#define NLATENCY                8
+#define NTRANS                  8
+#define NALL                    (3 + 2 + 1)
+#define NTTYPE                  5
+#define NIDX_EMI                (NTS + NWSCT + NLATENCY + NTRANS + NALL + NTTYPE)
+
+#define NCNT                    9
+#define NCH                     2
+#define NIDX_DRAMC              (NCNT * NCH)
+#define NIDX                            (NIDX_EMI + NIDX_DRAMC)
+
+#define NCLK                    1
+#define NARB                    8
+#define NBW                     10
+#define NIDX_BL                 (NCLK + NARB + NBW)
+
+/* 1000 To Khz and 4x freq & 2x data rate for LPDDR4 */
+/* 1000 To Khz and 2x freq & 2x data rate for LPDDR3*/
+/* TBD: calculate emi clock rate from DRAM DATA RATE */
+
+/*dram baseclock/EMI clock  :	LP4=4	LP3=2	*/
+#define DRAM_EMI_BASECLOCK_RATE_LP4     4
+#define DRAM_EMI_BASECLOCK_RATE_LP3     2
+/*dram io width  :	LP4=x16		LP3=x32 */
+#define DRAM_IO_BUS_WIDTH_LP4           16
+#define DRAM_IO_BUS_WIDTH_LP3           32
+/*dram datarate  :	DDR=double */
+#define DRAM_DATARATE   2
+
+#define ADDR_EMI        ((unsigned long)BaseAddrEMI)
+
+static const char of_emi_desc[] = "mediatek,emi";
+static const char of_chn_emi_desc[] = "mediatek,chn_emi";
+static const char of_dramc_desc[] = "mediatek,dramc";
+
+#define BM_MASTER_M0            (0x01)
+#define BM_MASTER_M1            (0x02)
+#define BM_MASTER_M2            (0x04)
+#define BM_MASTER_M3            (0x08)
+#define BM_MASTER_M4            (0x10)
+#define BM_MASTER_M5            (0x20)
+#define BM_MASTER_M6            (0x40)
+#define BM_MASTER_M7            (0x80)
+#define BM_MASTER_ALL           (0xFF)
+
+
+enum BM_RW_Type {
+	BM_BOTH_READ_WRITE,
+	BM_READ_ONLY,
+	BM_WRITE_ONLY
+};
+
+enum {
+	BM_TRANS_TYPE_1BEAT = 0x0,
+	BM_TRANS_TYPE_2BEAT,
+	BM_TRANS_TYPE_3BEAT,
+	BM_TRANS_TYPE_4BEAT,
+	BM_TRANS_TYPE_5BEAT,
+	BM_TRANS_TYPE_6BEAT,
+	BM_TRANS_TYPE_7BEAT,
+	BM_TRANS_TYPE_8BEAT,
+	BM_TRANS_TYPE_9BEAT,
+	BM_TRANS_TYPE_10BEAT,
+	BM_TRANS_TYPE_11BEAT,
+	BM_TRANS_TYPE_12BEAT,
+	BM_TRANS_TYPE_13BEAT,
+	BM_TRANS_TYPE_14BEAT,
+	BM_TRANS_TYPE_15BEAT,
+	BM_TRANS_TYPE_16BEAT,
+	BM_TRANS_TYPE_1Byte = 0 << 4,
+	BM_TRANS_TYPE_2Byte = 1 << 4,
+	BM_TRANS_TYPE_4Byte = 2 << 4,
+	BM_TRANS_TYPE_8Byte = 3 << 4,
+	BM_TRANS_TYPE_16Byte = 4 << 4,
+	BM_TRANS_TYPE_32Byte = 5 << 4,
+	BM_TRANS_TYPE_BURST_WRAP = 0 << 7,
+	BM_TRANS_TYPE_BURST_INCR = 1 << 7
+};
+
+enum {
+	BM_TRANS_RW_DEFAULT = 0x0,
+	BM_TRANS_RW_READONLY,
+	BM_TRANS_RW_WRITEONLY,
+	BM_TRANS_RW_RWBOTH
+};
+
+enum {
+	BM_WSCT_RW_DISABLE = 0x0,
+	BM_WSCT_RW_READONLY,
+	BM_WSCT_RW_WRITEONLY,
+	BM_WSCT_RW_RWBOTH
+};
+
+/*coda busid 12bit, but HW support 16 bit*/
+#define EMI_BMID_MASK				(0xFFFF)
+#define BM_COUNTER_MAX				(21)
+
+/*
+*#define BUS_MON_EN		(0x00000001)
+*#define BUS_MON_PAUSE		(0x00000002)
+*#define BUS_MON_IDLE		(0x00000008)
+*#define BC_OVERRUN		(0x00000100)
+*/
+enum {
+	BUS_MON_EN_SHIFT = 0,
+	BUS_MON_PAUSE_SHIFT = 1,
+	BUS_MON_IDLE_SHIFT = 3,
+	BC_OVERRUN_SHIFT = 8,
+	DRAMC_CG_SHIFT = 9,
+};
+
+#define BM_REQ_OK				(0)
+#define BM_ERR_WRONG_REQ			(-1)
+#define BM_ERR_OVERRUN				(-2)
+
+#define BM_WSCT_TSCT_IDSEL_ENABLE		(0)
+#define BM_WSCT_TSCT_IDSEL_DISABLE		(-1)
+#define BM_TTYPE1_16_ENABLE			(0)
+#define BM_TTYPE1_16_DISABLE			(-1)
+#define BM_TTYPE17_21_ENABLE			(0)
+#define BM_TTYPE17_21_DISABLE			(-1)
+#define BM_BW_LIMITER_ENABLE			(0)
+#define BM_BW_LIMITER_DISABLE			(-1)
+
+#define M0_DOUBLE_HALF_BW_1CH	(0x0)
+#define M0_DOUBLE_HALF_BW_2CH	(0x1)
+#define M0_DOUBLE_HALF_BW_4CH	(0x2)
+
+/* EMI Rank configuration */
+enum {
+	DISABLE_DUAL_RANK_MODE = 0,
+	ENABLE_DUAL_RANK_MODE,
+};
+
+#define RANK_MASK 0x1
+#define ONE_RANK 1
+#define DUAL_RANK 2
+
+
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+/*ondiemet emi ipi command*/
+enum BM_EMI_IPI_Type {
+	SET_BASE_EMI = 0x0,
+	SET_BASE_DRAMC0,
+	SET_BASE_DRAMC1,
+	SET_BASE_DRAMC2,
+	SET_BASE_DRAMC3,
+	SET_BASE_DDRPHY0AO,
+	SET_BASE_DRAMC0_AO,
+	SET_EBM_CONFIGS1,
+	SET_EBM_CONFIGS2,
+	SET_REGISTER_CB,
+};
+#endif
+
+
+#define	EMI_OFF			0x0000
+#define EMI_CONA		(0x000-EMI_OFF)
+#define EMI_CONH		(0x038-EMI_OFF)
+#define EMI_CONH_2ND		(0x03C-EMI_OFF)
+#define EMI_CONM		(0x060-EMI_OFF)
+#define EMI_CONO		(0x070-EMI_OFF)
+
+#define EMI_MDCT		(0x078 - EMI_OFF)
+#define EMI_MDCT_2ND		(0x07C - EMI_OFF)
+
+#define EMI_ARBA		(0x100 - EMI_OFF)
+#define EMI_ARBB		(0x108 - EMI_OFF)
+#define EMI_ARBC		(0x110 - EMI_OFF)
+#define EMI_ARBD		(0x118 - EMI_OFF)
+#define EMI_ARBE		(0x120 - EMI_OFF)
+#define EMI_ARBF		(0x128 - EMI_OFF)
+#define EMI_ARBG		(0x130 - EMI_OFF)
+#define EMI_ARBG_2ND		(0x134 - EMI_OFF)
+#define EMI_ARBH		(0x138 - EMI_OFF)
+
+#define EMI_BMEN		(0x400 - EMI_OFF)
+#define EMI_BCNT		(0x408 - EMI_OFF)
+#define EMI_TACT		(0x410 - EMI_OFF)
+#define EMI_TSCT		(0x418 - EMI_OFF)
+#define EMI_WACT		(0x420 - EMI_OFF)
+#define EMI_WSCT		(0x428 - EMI_OFF)
+#define EMI_BACT		(0x430 - EMI_OFF)
+#define EMI_BSCT		(0x438 - EMI_OFF)
+
+#define EMI_MSEL		(0x440 - EMI_OFF)
+#define EMI_TSCT2		(0x448 - EMI_OFF)
+#define EMI_TSCT3		(0x450 - EMI_OFF)
+#define EMI_WSCT2		(0x458 - EMI_OFF)
+#define EMI_WSCT3		(0x460 - EMI_OFF)
+#define EMI_WSCT4		(0x464 - EMI_OFF)
+#define EMI_MSEL2		(0x468 - EMI_OFF)
+#define EMI_MSEL3		(0x470 - EMI_OFF)
+#define EMI_MSEL4		(0x478 - EMI_OFF)
+#define EMI_MSEL5		(0x480 - EMI_OFF)
+#define EMI_MSEL6		(0x488 - EMI_OFF)
+#define EMI_MSEL7		(0x490 - EMI_OFF)
+#define EMI_MSEL8		(0x498 - EMI_OFF)
+#define EMI_MSEL9		(0x4A0 - EMI_OFF)
+#define EMI_MSEL10		(0x4A8 - EMI_OFF)
+
+#define EMI_BMID0		(0x4B0 - EMI_OFF)
+#define EMI_BMID1		(0x4B4 - EMI_OFF)
+#define EMI_BMID2		(0x4B8 - EMI_OFF)
+#define EMI_BMID3		(0x4BC - EMI_OFF)
+#define EMI_BMID4		(0x4C0 - EMI_OFF)
+#define EMI_BMID5		(0x4C4 - EMI_OFF)
+#define EMI_BMID6		(0x4C8 - EMI_OFF)
+#define EMI_BMID7		(0x4CC - EMI_OFF)
+#define EMI_BMID8		(0x4D0 - EMI_OFF)
+#define EMI_BMID9		(0x4D4 - EMI_OFF)
+#define EMI_BMID10		(0x4D8 - EMI_OFF)
+
+#define EMI_BMEN1		(0x4E0 - EMI_OFF)
+#define EMI_BMEN2		(0x4E8 - EMI_OFF)
+#define EMI_BMRW0		(0x4F8 - EMI_OFF)
+#define EMI_BMRW1		(0x4FC - EMI_OFF)
+#define EMI_TTYPE1		(0x500 - EMI_OFF)
+#define EMI_TTYPE2		(0x508 - EMI_OFF)
+#define EMI_TTYPE3		(0x510 - EMI_OFF)
+#define EMI_TTYPE4		(0x518 - EMI_OFF)
+#define EMI_TTYPE5		(0x520 - EMI_OFF)
+#define EMI_TTYPE6		(0x528 - EMI_OFF)
+#define EMI_TTYPE7		(0x530 - EMI_OFF)
+#define EMI_TTYPE8		(0x538 - EMI_OFF)
+#define EMI_TTYPE9		(0x540 - EMI_OFF)
+#define EMI_TTYPE10		(0x548 - EMI_OFF)
+#define EMI_TTYPE11		(0x550 - EMI_OFF)
+#define EMI_TTYPE12		(0x558 - EMI_OFF)
+#define EMI_TTYPE13		(0x560 - EMI_OFF)
+#define EMI_TTYPE14		(0x568 - EMI_OFF)
+#define EMI_TTYPE15		(0x570 - EMI_OFF)
+#define EMI_TTYPE16		(0x578 - EMI_OFF)
+#define EMI_TTYPE17		(0x580 - EMI_OFF)
+#define EMI_TTYPE18		(0x588 - EMI_OFF)
+#define EMI_TTYPE19		(0x590 - EMI_OFF)
+#define EMI_TTYPE20		(0x598 - EMI_OFF)
+#define EMI_TTYPE21		(0x5A0 - EMI_OFF)
+
+#define EMI_BWCT0		(0x5B0 - EMI_OFF)
+#define EMI_BWCT1		(0x5B4 - EMI_OFF)
+#define EMI_BWCT2		(0x5B8 - EMI_OFF)
+#define EMI_BWCT3		(0x5BC - EMI_OFF)
+#define EMI_BWCT4		(0x5C0 - EMI_OFF)
+#define EMI_BWST0		(0x5C4 - EMI_OFF)
+#define EMI_BWST1		(0x5C8 - EMI_OFF)
+
+#define EMI_BWCT0_2ND		(0x6A0 - EMI_OFF)
+#define EMI_BWCT1_2ND		(0x6A4 - EMI_OFF)
+#define EMI_BWST_2ND		(0x6A8 - EMI_OFF)
+
+/* SEDA 3.5 New! reg*/
+/* For WSCT setting*/
+#define EMI_DBWA (0xF00 - EMI_OFF)
+#define EMI_DBWB (0xF04 - EMI_OFF)
+#define EMI_DBWC (0xF08 - EMI_OFF)
+#define EMI_DBWD (0xF0C - EMI_OFF)
+#define EMI_DBWE (0xF10 - EMI_OFF)
+#define EMI_DBWF (0xF14 - EMI_OFF)
+
+#define EMI_DBWG (0xF18 - EMI_OFF) /* WSCT5 */
+#define EMI_DBWH (0xF1C - EMI_OFF) /* WSCT6 */
+
+#define EMI_DBWA_2ND (0xF2C - EMI_OFF)
+#define EMI_DBWB_2ND (0xF30 - EMI_OFF)
+#define EMI_DBWC_2ND (0xF34 - EMI_OFF)
+#define EMI_DBWD_2ND (0xF38 - EMI_OFF)
+#define EMI_DBWE_2ND (0xF3C - EMI_OFF)
+#define EMI_DBWF_2ND (0xF40 - EMI_OFF)
+
+#define EMI_DBWI (0xF20 - EMI_OFF) /* SEL_ID_MSK*/
+#define EMI_DBWJ (0xF24 - EMI_OFF)
+#define EMI_DBWK (0xF28 - EMI_OFF)
+
+/* For Ttype setting */
+#define EMI_TTYPE1_CONA (0xF50 - EMI_OFF)
+#define EMI_TTYPE1_CONB (0xF54 - EMI_OFF)
+#define EMI_TTYPE2_CONA (0xF58 - EMI_OFF)
+#define EMI_TTYPE2_CONB (0xF5C - EMI_OFF)
+#define EMI_TTYPE3_CONA (0xF60 - EMI_OFF)
+#define EMI_TTYPE3_CONB (0xF64 - EMI_OFF)
+#define EMI_TTYPE4_CONA (0xF68 - EMI_OFF)
+#define EMI_TTYPE4_CONB (0xF6C - EMI_OFF)
+#define EMI_TTYPE5_CONA (0xF70 - EMI_OFF)
+#define EMI_TTYPE5_CONB (0xF74 - EMI_OFF)
+#define EMI_TTYPE6_CONA (0xF78 - EMI_OFF)
+#define EMI_TTYPE6_CONB (0xF7C - EMI_OFF)
+#define EMI_TTYPE7_CONA (0xF80 - EMI_OFF)
+#define EMI_TTYPE7_CONB (0xF84 - EMI_OFF)
+#define EMI_TTYPE8_CONA (0xF88 - EMI_OFF)
+#define EMI_TTYPE8_CONB (0xF8C - EMI_OFF)
+#define EMI_TTYPE9_CONA (0xF90 - EMI_OFF)
+#define EMI_TTYPE9_CONB (0xF94 - EMI_OFF)
+#define EMI_TTYPE10_CONA (0xF98 - EMI_OFF)
+#define EMI_TTYPE10_CONB (0xF9C - EMI_OFF)
+#define EMI_TTYPE11_CONA (0xFA0 - EMI_OFF)
+#define EMI_TTYPE11_CONB (0xFA4 - EMI_OFF)
+#define EMI_TTYPE12_CONA (0xFA8 - EMI_OFF)
+#define EMI_TTYPE12_CONB (0xFAC - EMI_OFF)
+#define EMI_TTYPE13_CONA (0xFB0 - EMI_OFF)
+#define EMI_TTYPE13_CONB (0xFB4 - EMI_OFF)
+#define EMI_TTYPE14_CONA (0xFB8 - EMI_OFF)
+#define EMI_TTYPE14_CONB (0xFBC - EMI_OFF)
+#define EMI_TTYPE15_CONA (0xFC0 - EMI_OFF)
+#define EMI_TTYPE15_CONB (0xFC4 - EMI_OFF)
+#define EMI_TTYPE16_CONA (0xFC8 - EMI_OFF)
+#define EMI_TTYPE16_CONB (0xFCC - EMI_OFF)
+#define EMI_TTYPE17_CONA (0xFD0 - EMI_OFF)
+#define EMI_TTYPE17_CONB (0xFD4 - EMI_OFF)
+#define EMI_TTYPE18_CONA (0xFD8 - EMI_OFF)
+#define EMI_TTYPE18_CONB (0xFDC - EMI_OFF)
+#define EMI_TTYPE19_CONA (0xFE0 - EMI_OFF)
+#define EMI_TTYPE19_CONB (0xFE4 - EMI_OFF)
+#define EMI_TTYPE20_CONA (0xFE8 - EMI_OFF)
+#define EMI_TTYPE20_CONB (0xFEC - EMI_OFF)
+#define EMI_TTYPE21_CONA (0xFF0 - EMI_OFF)
+#define EMI_TTYPE21_CONB (0xFF4 - EMI_OFF)
+
+
+extern void emi_dump_reg(void);
+extern int MET_BM_Init(void);
+extern void MET_BM_DeInit(void);
+extern void MET_BM_SaveCfg(void);
+extern void MET_BM_RestoreCfg(void);
+extern void MET_BM_Enable(const unsigned int enable);
+extern void MET_BM_Pause(void);
+extern void MET_BM_Continue(void);
+extern unsigned int MET_BM_IsOverrun(void);
+extern unsigned int MET_BM_GetReadWriteType(void);
+extern void MET_BM_SetReadWriteType(const unsigned int ReadWriteType);
+extern int MET_BM_GetBusCycCount(void);
+extern unsigned int MET_BM_GetTransAllCount(void);
+extern int MET_BM_GetTransCount(const unsigned int counter_num);
+extern int MET_BM_GetWordAllCount(void);
+extern int MET_BM_GetWordCount(const unsigned int counter_num);
+extern unsigned int MET_BM_GetBandwidthWordCount(void);
+extern unsigned int MET_BM_GetOverheadWordCount(void);
+extern int MET_BM_GetTransTypeCount(const unsigned int counter_num);
+extern int MET_BM_GetMDCT(void);
+extern int MET_BM_GetMDCT_2(void);
+extern int MET_BM_GetMonitorCounter(const unsigned int counter_num,
+				    unsigned int *master, unsigned int *trans_type);
+extern int MET_BM_SetMDCT_MDMCU(unsigned int mdmcu_rd_buf);
+extern int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+				    const unsigned int master, const unsigned int trans_type);
+extern int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val);
+extern int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable);
+extern int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master);
+extern int MET_BM_SetbusID_En(const unsigned int counter_num,
+			      const unsigned int enable);
+extern int MET_BM_SetbusID(const unsigned int counter_num,
+			   const unsigned int id);
+extern int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable);
+extern int MET_BM_SetLatencyCounter(unsigned int enable);
+int MET_BM_GetLatencyCycle(unsigned int *__restrict__ emi_value,
+				const unsigned int begin, const unsigned int end);
+extern unsigned int MET_BM_GetEmiDcm(void);
+extern int MET_BM_SetEmiDcm(const unsigned int setting);
+extern void MET_BM_Clear_Start(void);
+extern unsigned int MET_EMI_GetDramRankNum(void);
+extern unsigned int MET_EMI_GetDramRankNum_CHN1(void);
+
+/* Config */
+unsigned int MET_EMI_GetARBA(void);
+unsigned int MET_EMI_GetARBB(void);
+unsigned int MET_EMI_GetARBC(void);
+unsigned int MET_EMI_GetARBD(void);
+unsigned int MET_EMI_GetARBE(void);
+unsigned int MET_EMI_GetARBF(void);
+unsigned int MET_EMI_GetARBG(void);
+unsigned int MET_EMI_GetARBH(void);
+
+/* Total BW status */
+extern unsigned int MET_EMI_GetBWCT0(void);
+extern unsigned int MET_EMI_GetBWCT1(void);
+extern unsigned int MET_EMI_GetBWCT2(void);
+extern unsigned int MET_EMI_GetBWCT3(void);
+extern unsigned int MET_EMI_GetBWCT4(void);
+extern unsigned int MET_EMI_GetBWST0(void);
+extern unsigned int MET_EMI_GetBWST1(void);
+/* C+G BW */
+extern unsigned int MET_EMI_GetBWCT0_2ND(void);
+extern unsigned int MET_EMI_GetBWCT1_2ND(void);
+extern unsigned int MET_EMI_GetBWST_2ND(void);
+
+unsigned int MET_EMI_GetBMRW0(void);
+unsigned int MET_EMI_GetDramChannNum(void);
+
+/* ondiemet*/
+void MET_BM_IPI_baseaddr(void);
+void met_emi_phyaddr_debug(void);
+
+extern void met_record_dramc_dcm_enable_flag(void);
+
+/* get DRS registers content */
+#define CHN_EMI_DRS_ST2 0x17C
+#define CHN_EMI_DRS_ST3 0x180
+#define CHN_EMI_DRS_ST4 0x184
+extern void met_get_drs_registers(uint32_t *value);
+
+/* SEDA 3.5 NEW */
+extern int MET_BM_SetWSCT_master_rw(unsigned int *master , unsigned int *rw);
+extern int MET_BM_SetWSCT_high_priority(unsigned int *disable, unsigned int *select);
+extern int MET_BM_SetWSCT_busid_idmask(unsigned int *busid, unsigned int *idMask);
+extern int MET_BM_SetWSCT_chn_rank_sel(unsigned int *chn_rank_sel);
+extern int MET_BM_SetWSCT_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd);
+extern int MET_BM_SetTSCT_busid_enable(unsigned int *enable);
+extern int MET_BM_SetTtype_high_priority_sel(unsigned int _high_priority_filter, unsigned int *select);
+extern int MET_BM_SetTtype_busid_idmask(unsigned int *busid, unsigned int *idMask, int _ttype1_16_en, int _ttype17_21_en);
+extern int MET_BM_SetTtype_chn_rank_sel(unsigned int *chn_rank_sel);
+extern int MET_BM_SetTtype_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd);
+extern unsigned int MET_EMI_Get_BaseClock_Rate(void);
+
+#endif                          /* !__MT_MET_EMI_BM_H__ */
diff --git a/src/devtools/met-driver/4.14/mt2731/met_dramc.h b/src/devtools/met-driver/4.14/mt2731/met_dramc.h
new file mode 100644
index 0000000..a126815
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/met_dramc.h
@@ -0,0 +1,7 @@
+#ifndef __MTK_DRAMC_H__
+#define __MTK_DRAMC_H__
+
+#define DRAMC_VER 2
+
+
+#endif /* __MTK_DRAMC_REG_H__ */
\ No newline at end of file
diff --git a/src/devtools/met-driver/4.14/mt2731/met_gpu_monitor.h b/src/devtools/met-driver/4.14/mt2731/met_gpu_monitor.h
new file mode 100644
index 0000000..3b6f7cd
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/met_gpu_monitor.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2016 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+
+#ifndef __MET_GPU_MONITOR_H__
+#define __MET_GPU_MONITOR_H__
+
+#define	MET_GPU_STALL_MONITOR
+#define IO_ADDR_GPU_STALL		0x1021c000
+#define IO_SIZE_GPU_STALL		0x1000
+#define OFFSET_STALL_GPU_M0_CHECK	0x200
+#define OFFSET_STALL_GPU_M1_CHECK	0x204
+#define OFFSET_STALL_GPU_M0_EMI_CHECK	0x208
+#define OFFSET_STALL_GPU_M1_EMI_CHECK	0x20c
+
+#endif	/* __MET_GPU_MONITOR_H__ */
diff --git a/src/devtools/met-driver/4.14/mt2731/met_sspm_rts_event.h b/src/devtools/met-driver/4.14/mt2731/met_sspm_rts_event.h
new file mode 100644
index 0000000..bcccfcd
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/met_sspm_rts_event.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2016 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ */
+MET_SSPM_RTS_EVNET(SSPM_PTPOD, "_id,voltage")
+MET_SSPM_RTS_EVNET(SSPM_MET_UNIT_TEST, "test")
+MET_SSPM_RTS_EVNET(SSPM_QOS_BOUND_STATE, "idx,state,num,event,emibw_mon_total,emibw_mon_cpu,emibw_mon_gpu,emibw_mon_mm,emibw_mon_md,emibw_req_total,emibw_req_cpu,emibw_req_gpu,emibw_req_mm,emibw_req_md,smibw_mon_venc,smibw_mon_cam,smibw_mon_img,smibw_mon_mdp,smibw_mon_gpu,smibw_mon_apu,smibw_mon_vpu0,smibw_mon_vpu1,smibw_mon_mdla,smibw_req_venc,smibw_req_cam,smibw_req_img,smibw_req_mdp,smibw_req_gpu,smibw_req_apu,smibw_req_vpu0,smibw_req_vpu1,smibw_req_mdla,lat_mon_cpu,lat_mon_vpu0,lat_mon_vpu1,lat_mon_mdla")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_NON_WFX, "non_wfx_0,non_wfx_1,non_wfx_2,non_wfx_3,non_wfx_4,non_wfx_5,non_wfx_6,non_wfx_7")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_LOADING, "ratio,cps")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_POWER, "c_up_array_0,c_up_array_1,c_down_array_0,c_down_array_1,c_up_0,c_up_1,c_down_0,c_dwon_1,c_up,c_down,v_up,v_down,v2f_0,v2f_1")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_OPP, "v_dram_opp,v_dram_opp_cur,c_opp_cur_0,c_opp_cur_1,d_times_up,d_times_down")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_RATIO, "ratio_max_0,ratio_max_1,ratio_0,ratio_1,ratio_2,ratio_3,ratio_4,ratio_5,ratio_6,ratio_7")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_BW, "total_bw")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_CP_RATIO, "up0,up1,up2,up3,down0,down1,down2,down3")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_VP_RATIO, "up0,up1,up2,up3,down0,down1,down2,down3")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_DE_TIMES, "up0,up1,up2,up3,down0,down1,down2,down3,reset")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_ACTIVE_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_IDLE_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_OFF_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_STALL_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_L3DC, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_INST_SPEC, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_CYCLES, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_NON_WFX_CTR, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DSU_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DSU_L3_BW, "L3_BW")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__MCUSYS_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__MCUSYS_EMI_BW, "cpu_emi_bw")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DVFS, "vproc2,vproc1,cpuL_freq,cpuB_freq,cpu_L_opp,cpu_B_opp,cci_volt,cci_freq,cci_opp")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__LKG_POWER, "cpu_L,cpu_B,dsu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__POWER, "cpu_L,cpu_B,dsu,mcusys")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__GPU_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__DVFS, "vgpu,gpu_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__URATE, "tex,alu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__POWER, "gpu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__CAM_STATE_RATIO, "RAW_A_active,RAW_B_active,RAW_C_active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__IMG_STATE_RATIO, "P2_active,P2_idle,MFB_active,WPE_active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__IPE_STATE_RATIO, "FDVT_active,DVP_active,DVS_active,DV_idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__MDP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__DISP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__ADSP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VENC_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VDEC_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__INFRA_STATE_RATIO, "dact,cact,idle,dcm")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VDO_CODING_TYPE, "venc,vdec")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__DVFS, "vcore,cam_freq,img_freq,ipe_freq,dpe_freq,venc_freq,vdec_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__POWER, "cam,img,ipe,mdp,disp,adsp,venc,vdec,dramc,infra_top,aphy_vcore")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__MEM_IDX, "read_bw,write_bw,srr_pct,pdir_pct,phr_pct,acc_util,mr4")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__DVFS, "ddr_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__POWER, "aphy_vddq_0p6v,aphy_vm_1p1v,aphy_vio_1p8v,dram_vddq_0p6v,dram_vdd2_1p1v,dram_vdd1_1p8v")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__VPU0_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__VPU1_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__DVFS, "vvpu,vpu0_freq,vpu1_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__POWER, "vpu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__ACTIVE_RATIO, "pool,dw,fc,conv,ewe,sb")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__TOTAL_CYCLES, "total_cycles")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__DVFS, "vmdla,mdla_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__POWER, "mdla")
+MET_SSPM_RTS_EVNET(__SSPM_APUSYS_QOS_CNT__, "bw_VPU0,bw_VPU1,bw_MDLA0,bw_MDAL1,lt_VPU0,lt_VPU1,lt_MDLA0,lt_MDLA1")
+MET_SSPM_RTS_EVNET(__SSPM_GPU_APU_SSC_CNT__, "GPU_0_R,GPU_0_W,APU_0_R,APU_0_W,GPU_1_R,GPU_1_W,APU_1_R,APU_1_W")
diff --git a/src/devtools/met-driver/4.14/mt2731/plf_init.h b/src/devtools/met-driver/4.14/mt2731/plf_init.h
new file mode 100644
index 0000000..81fde68
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/plf_init.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __PLF_INIT_H__
+#define __PLF_INIT_H__
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/kallsyms.h>
+
+/*
+ *   MET External Symbol
+ */
+extern struct miscdevice met_device;
+
+#ifdef MET_AP_EMI
+#include <mtk_dramc.h>
+extern unsigned int get_dram_data_rate(void);		/* in Mhz */
+extern int get_ddr_type(void);
+extern void *mt_cen_emi_base_get(void);
+extern void *mt_chn_emi_base_get(void);
+extern void *get_cur_ddr_ratio(void);
+
+/* New APIs for mt_dramc_nao base get */
+extern void *mt_dramc_nao_chn_base_get(int channel);
+extern void *mt_ddrphy_chn_base_get(int channel);
+extern void *mt_dramc_chn_base_get(int channel);
+
+extern unsigned int (*get_dram_data_rate_symbol)(void); /* in Mhz */
+extern unsigned int (*get_ddr_type_symbol)(void);       /* in Mhz */
+
+extern void *(*mt_cen_emi_base_get_symbol)(void);
+extern void *(*mt_chn_emi_base_get_symbol)(int chn);
+
+/* New APIs for mt_dramc_nao base get */
+extern void *(*mt_dramc_nao_chn_base_get_symbol)(int channel);
+extern void *(*mt_ddrphy_chn_base_get_symbol)(int channel);
+extern void *(*mt_dramc_chn_base_get_symbol)(int channel);
+
+extern unsigned int (*get_cur_ddr_ratio_symbol)(void);
+
+#endif
+
+/*
+ *   MET devices declaration
+ */
+
+#ifdef MET_AP_EMI
+extern struct metdevice met_emi;
+extern struct metdevice met_sspm_emi;
+#endif
+
+#endif /*__PLF_INIT_H__*/
diff --git a/src/devtools/met-driver/4.14/mt2731/plf_trace.c b/src/devtools/met-driver/4.14/mt2731/plf_trace.c
new file mode 100644
index 0000000..b3a87fd
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/plf_trace.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "met_drv.h"
+#include "interface.h"
+#include "trace.h"
+#include "plf_trace.h"
+
+
+noinline void ms_emi(const unsigned char cnt, unsigned int *value)
+{
+	char *SOB, *EOB;
+
+	MET_TRACE_GETBUF(&SOB, &EOB);
+	// coverity[var_deref_op : FALSE]
+	EOB = ms_formatH_EOL(EOB, cnt, value);
+	MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void ms_emi_ext(const unsigned char cnt, unsigned int *value)
+{
+	char *SOB, *EOB;
+
+	MET_TRACE_GETBUF(&SOB, &EOB);
+	// coverity[var_deref_op : FALSE]
+	EOB = ms_formatH_EOL(EOB, cnt, value);
+	MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void ms_emi_tsct(const unsigned char cnt, unsigned int *value)
+{
+	char *SOB, *EOB;
+
+	MET_TRACE_GETBUF(&SOB, &EOB);
+	// coverity[var_deref_op : FALSE]
+	EOB = ms_formatH_EOL(EOB, cnt, value);
+	MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void ms_emi_mdct(const unsigned char cnt, unsigned int *value)
+{
+	char *SOB, *EOB;
+
+	MET_TRACE_GETBUF(&SOB, &EOB);
+	// coverity[var_deref_op : FALSE]
+	EOB = ms_formatH_EOL(EOB, cnt, value);
+	MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+
+noinline void ms_ttype(const unsigned char cnt, unsigned int *value)
+{
+	char *SOB, *EOB;
+
+	MET_TRACE_GETBUF(&SOB, &EOB);
+	// coverity[var_deref_op : FALSE]
+	EOB = ms_formatH_EOL(EOB, cnt, value);
+	MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void ms_dramc(const unsigned char cnt, unsigned int *value)
+{
+	char *SOB, *EOB;
+
+	MET_TRACE_GETBUF(&SOB, &EOB);
+	// coverity[var_deref_op : FALSE]
+	EOB = ms_formatH_EOL(EOB, cnt, value);
+	MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void ms_bw_limiter(const unsigned char cnt, unsigned int *value)
+{
+	char *SOB, *EOB;
+
+	MET_TRACE_GETBUF(&SOB, &EOB);
+	// coverity[var_deref_op : FALSE]
+	EOB = ms_formatH_EOL(EOB, cnt, value);
+	MET_TRACE_PUTBUF(SOB, EOB);
+}
diff --git a/src/devtools/met-driver/4.14/mt2731/plf_trace.h b/src/devtools/met-driver/4.14/mt2731/plf_trace.h
new file mode 100644
index 0000000..3d7bd0c
--- /dev/null
+++ b/src/devtools/met-driver/4.14/mt2731/plf_trace.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2018 MediaTek Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _PLF_TRACE_H_
+#define _PLF_TRACE_H_
+
+#include "core_plf_trace.h"
+
+#define	HVALUE_SIZE	9	/* 8 chars (max value ffffffff) + 1 char (',' or NULL) */
+#define	DVALUE_SIZE	12	/* 10 chars (max value 4,294,967,295) + 1 char (',' or NULL) */
+
+void ms_emi(const unsigned char cnt, unsigned int *value);
+void ms_emi_tsct(const unsigned char cnt, unsigned int *value);
+void ms_emi_mdct(const unsigned char cnt, unsigned int *value);
+
+void ms_ttype(const unsigned char cnt, unsigned int *value);
+void ms_bw_limiter(const unsigned char cnt, unsigned int *value);
+
+void ms_dramc(const unsigned char cnt, unsigned int *value);
+
+void ms_emi_ext(const unsigned char cnt, unsigned int *value);
+
+#endif				/* _PLF_TRACE_H_ */