[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/devtools/met-driver/met_drv/common/met_emi.c b/src/devtools/met-driver/met_drv/common/met_emi.c
new file mode 100644
index 0000000..7f18f4a
--- /dev/null
+++ b/src/devtools/met-driver/met_drv/common/met_emi.c
@@ -0,0 +1,1107 @@
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "core_plf_init.h"
+#include "core_plf_trace.h"
+#include "mtk_emi_bm.h"
+
+extern struct miscdevice met_device;
+
+/*======================================================================*/
+/*	Global variable definitions					*/
+/*======================================================================*/
+/*ondiemet emi sampling interval in us */
+int ondiemet_emi_polling_200us;
+int emi_tsct_enable;
+int emi_mdct_enable;
+
+
+int emi_use_ondiemet;
+int metemi_func_opt;
+
+int met_emi_regdump;
+/*WSCT/TSCT id selection enable*/
+int emi_wsct_tsct_id_selection[4];
+/* Dynamic MonitorCounter selection !!!EXPERIMENT!!! */
+static int msel_enable;
+static unsigned int msel_group1 = BM_Master_GP_1_Default;
+static unsigned int msel_group2 = BM_Master_GP_2_Default;
+static unsigned int msel_group3 = BM_Master_GP_3_Default;
+
+/* 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;
+
+unsigned int fmem_divider_freq_1;
+unsigned int fmem_divider_freq_2;
+
+static int dramc_pdir_enable;
+static int dram_chann_num = 1;
+
+/*======================================================================*/
+/*	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;
+	dma_addr_t	src_addr_p;
+
+	if ((n == 0) || (buf == NULL))
+		return -EINVAL;
+	if (sscanf(buf, "%d", &times) != 1)
+		return -EINVAL;
+	if (times < 0)
+		return -EINVAL;
+
+	if (times > 5000)	/* Less than 20MB */
+		return -EINVAL;
+
+	/* dma_alloc */
+	src_addr_v = dma_alloc_coherent(met_device.this_device,
+			PAGE_SIZE,
+			&src_addr_p,
+			GFP_KERNEL);
+	if (src_addr_v == NULL) {
+	/*	met_tag_oneshot(0, "test_apmcu dma alloc fail", PAGE_SIZE); */
+		return -ENOMEM;
+	}
+	/* testing */
+	preempt_disable();
+	/* met_tag_start(0, "TEST_EMI_APMCU"); */
+	for (i = 0; i < times; i++) {
+		memset(src_addr_v, 2*i, PAGE_SIZE);
+		/* met_tag_oneshot(0, "TEST_EMI_APMCU", PAGE_SIZE); */
+	}
+	/* met_tag_end(0, "TEST_EMI_APMCU"); */
+	preempt_enable();
+
+	/* dma_free */
+	if (src_addr_v != NULL)
+		dma_free_coherent(met_device.this_device,
+				PAGE_SIZE,
+				src_addr_v,
+				src_addr_p);
+	return n;
+}
+
+/*======================================================================*/
+/*	KOBJ Declarations						*/
+/*======================================================================*/
+DECLARE_KOBJ_ATTR_INT(ondiemet_emi_polling_200us, ondiemet_emi_polling_200us)
+DECLARE_KOBJ_ATTR_INT(emi_tsct_enable, emi_tsct_enable)
+DECLARE_KOBJ_ATTR_INT(emi_mdct_enable, emi_mdct_enable)
+DECLARE_KOBJ_ATTR_INT(metemi_func_opt, metemi_func_opt)
+DECLARE_KOBJ_ATTR_INT(emi_regdump, met_emi_regdump)
+DECLARE_KOBJ_ATTR_INT(emi_wsct_tsct_id_selection1, emi_wsct_tsct_id_selection[0])
+DECLARE_KOBJ_ATTR_INT(emi_wsct_tsct_id_selection2, emi_wsct_tsct_id_selection[1])
+DECLARE_KOBJ_ATTR_INT(emi_wsct_tsct_id_selection3, emi_wsct_tsct_id_selection[2])
+DECLARE_KOBJ_ATTR_INT(emi_wsct_tsct_id_selection4, emi_wsct_tsct_id_selection[3])
+/* KOBJ: Dynamic MonitorCounter selection !!!EXPERIMENT!!! */
+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)
+{
+	return dram_data_rate_MHz/DRAM_EMI_BASECLOCK_RATE/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;
+
+	dram_data_rate_MHz = get_dram_data_rate();
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			get_emi_clock_rate(dram_data_rate_MHz));
+}
+
+DECLARE_KOBJ_ATTR_RO(emi_clock_rate)
+
+static ssize_t dram_data_rate_show(struct kobject *kobj,
+		struct kobj_attribute *attr,
+		char *buf)
+{
+	unsigned int	dram_data_rate_MHz;
+
+	dram_data_rate_MHz = get_dram_data_rate();
+	return snprintf(buf, PAGE_SIZE, "%d\n", dram_data_rate_MHz);
+}
+
+DECLARE_KOBJ_ATTR_RO(dram_data_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_SERIAL_FNODE(nr) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype##nr##_master, ttype_master_val[nr-1], ttype_master) \
+	DECLARE_KOBJ_ATTR_HEX(ttype##nr##_busid, ttype_busid_val[nr-1]) \
+	DECLARE_KOBJ_ATTR_INT_LIST(ttype##nr##_nbeat, ttype_nbeat_val[nr-1], ttype_nbeat) \
+	DECLARE_KOBJ_ATTR_INT_LIST(ttype##nr##_nbyte, ttype_nbyte_val[nr-1], ttype_nbyte) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype##nr##_burst, ttype_burst_val[nr-1], ttype_burst) \
+	DECLARE_KOBJ_ATTR_STR_LIST(ttype##nr##_rw, ttype_rw_val[nr-1], ttype_rw)
+
+DECLARE_KOBJ_SERIAL_FNODE(1)
+DECLARE_KOBJ_SERIAL_FNODE(2)
+DECLARE_KOBJ_SERIAL_FNODE(3)
+DECLARE_KOBJ_SERIAL_FNODE(4)
+DECLARE_KOBJ_SERIAL_FNODE(5)
+DECLARE_KOBJ_SERIAL_FNODE(6)
+DECLARE_KOBJ_SERIAL_FNODE(7)
+DECLARE_KOBJ_SERIAL_FNODE(8)
+DECLARE_KOBJ_SERIAL_FNODE(9)
+DECLARE_KOBJ_SERIAL_FNODE(10)
+DECLARE_KOBJ_SERIAL_FNODE(11)
+DECLARE_KOBJ_SERIAL_FNODE(12)
+DECLARE_KOBJ_SERIAL_FNODE(13)
+DECLARE_KOBJ_SERIAL_FNODE(14)
+DECLARE_KOBJ_SERIAL_FNODE(15)
+DECLARE_KOBJ_SERIAL_FNODE(16)
+DECLARE_KOBJ_SERIAL_FNODE(17)
+DECLARE_KOBJ_SERIAL_FNODE(18)
+DECLARE_KOBJ_SERIAL_FNODE(19)
+DECLARE_KOBJ_SERIAL_FNODE(20)
+DECLARE_KOBJ_SERIAL_FNODE(21)
+
+	/**/
+#define KOBJ_ATTR_ITEM_SERIAL_FNODE(nr) \
+	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) \
+
+#define KOBJ_ATTR_LIST \
+	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(ondiemet_emi_polling_200us) \
+	KOBJ_ATTR_ITEM(emi_regdump) \
+	KOBJ_ATTR_ITEM(emi_wsct_tsct_id_selection1) \
+	KOBJ_ATTR_ITEM(emi_wsct_tsct_id_selection2) \
+	KOBJ_ATTR_ITEM(emi_wsct_tsct_id_selection3) \
+	KOBJ_ATTR_ITEM(emi_wsct_tsct_id_selection4) \
+	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(dram_data_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) \
+
+/*======================================================================*/
+/*	EMI Operations							*/
+/*======================================================================*/
+static void emi_init(void)
+{
+	unsigned int bmrw0_val, bmrw1_val, i, enable;
+	unsigned int msel_group1_val, msel_group2_val, msel_group3_val;
+
+	/* get dram channel number */
+	dram_chann_num = MET_EMI_GetDramChannNum();
+
+	/* Init. EMI bus monitor */
+	MET_BM_SetReadWriteType(rwtype);
+
+	/* MSEL1: ALL */
+	MET_BM_SetMonitorCounter(1,
+		BM_MASTER_ALL,
+		BM_TRANS_TYPE_4BEAT |
+		BM_TRANS_TYPE_8Byte |
+		BM_TRANS_TYPE_BURST_WRAP);
+	if (msel_enable) {
+		msel_group1_val = msel_group1;
+		msel_group2_val = msel_group2;
+		msel_group3_val = msel_group3;
+	} else {
+		msel_group1_val = BM_Master_GP_1_Default;
+		msel_group2_val = BM_Master_GP_2_Default;
+		msel_group3_val = BM_Master_GP_3_Default;
+	}
+
+	/* MSEL2: msel_group1 */
+	MET_BM_SetMonitorCounter(2,
+		msel_group1_val & BM_MASTER_ALL,
+		BM_TRANS_TYPE_4BEAT |
+		BM_TRANS_TYPE_8Byte |
+		BM_TRANS_TYPE_BURST_WRAP);
+	/* MSEL3: msel_group2 */
+	MET_BM_SetMonitorCounter(3,
+		msel_group2_val & BM_MASTER_ALL,
+		BM_TRANS_TYPE_4BEAT |
+		BM_TRANS_TYPE_8Byte |
+		BM_TRANS_TYPE_BURST_WRAP);
+	/* MSEL4: msel_group3 */
+	MET_BM_SetMonitorCounter(4,
+		msel_group3_val & BM_MASTER_ALL,
+		BM_TRANS_TYPE_4BEAT |
+		BM_TRANS_TYPE_8Byte |
+		BM_TRANS_TYPE_BURST_WRAP);
+
+
+	if (ttype1_16_en == BM_TTYPE1_16_ENABLE)	{
+		MET_BM_SetLatencyCounter(0);
+
+		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_SetIDSelect(i, ttype_busid_val[i - 1], (ttype_busid_val[i - 1] >= 0xffff) ? 0 : 1);
+		}
+	} else {
+		MET_BM_SetLatencyCounter(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]);
+			MET_BM_SetIDSelect(i, ttype_busid_val[i - 1], (ttype_busid_val[i - 1] >= 0xffff) ? 0 : 1);
+		}
+	}
+
+	bmrw0_val = (
+			(ttype_rw_val[0] << 0) | (ttype_rw_val[1] << 2) |
+			(ttype_rw_val[2] << 4) | (ttype_rw_val[3] << 6) |
+			(ttype_rw_val[4] << 8) | (ttype_rw_val[5] << 10) |
+			(ttype_rw_val[6] << 12) | (ttype_rw_val[7] << 14) |
+			(ttype_rw_val[8] << 16) | (ttype_rw_val[9] << 18) |
+			(ttype_rw_val[10] << 20) | (ttype_rw_val[11] << 22) |
+			(ttype_rw_val[12] << 24) | (ttype_rw_val[13] << 26) |
+			(ttype_rw_val[14] << 28) | (ttype_rw_val[15] << 30));
+
+	bmrw1_val = (
+			(ttype_rw_val[16] << 0) | (ttype_rw_val[17] << 2) |
+			(ttype_rw_val[18] << 4) | (ttype_rw_val[19] << 6) |
+			(ttype_rw_val[20] << 8));
+
+	MET_BM_SetTtypeCounterRW(bmrw0_val, bmrw1_val);
+
+	for (i = 0; i < 4; i++)
+		MET_BM_Set_WsctTsct_id_sel(i, emi_wsct_tsct_id_selection[i]);
+
+	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);
+	}
+
+	if (met_emi_regdump == 1)
+		emi_dump_reg();
+}
+
+static void emi_uninit(void)
+{
+}
+
+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;
+
+	dram_data_rate_MHz = get_dram_data_rate();
+
+	/* 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();
+
+	if (ttype1_16_en != BM_TTYPE1_16_ENABLE) {	/*1~21 NOT for ttype*/
+
+		/* 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 */
+
+
+		/* Get Latency */
+		emi_value[j++] = MET_BM_GetLatencyCycle(1);
+		emi_value[j++] = MET_BM_GetLatencyCycle(2);
+		emi_value[j++] = MET_BM_GetLatencyCycle(3);
+		emi_value[j++] = MET_BM_GetLatencyCycle(4);
+		emi_value[j++] = MET_BM_GetLatencyCycle(5);
+		emi_value[j++] = MET_BM_GetLatencyCycle(6);
+		emi_value[j++] = MET_BM_GetLatencyCycle(7);
+		emi_value[j++] = MET_BM_GetLatencyCycle(8);
+
+		/* Get Trans. */
+		emi_value[j++] = MET_BM_GetLatencyCycle(9);
+		emi_value[j++] = MET_BM_GetLatencyCycle(10);
+		emi_value[j++] = MET_BM_GetLatencyCycle(11);
+		emi_value[j++] = MET_BM_GetLatencyCycle(12);
+		emi_value[j++] = MET_BM_GetLatencyCycle(13);
+		emi_value[j++] = MET_BM_GetLatencyCycle(14);
+		emi_value[j++] = MET_BM_GetLatencyCycle(15);
+		emi_value[j++] = MET_BM_GetLatencyCycle(16);
+	} else {
+		for (n = 0; n < 20; n++)
+			emi_value[n] = 0;
+		j = 20;
+
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(1);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(2);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(3);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(4);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(5);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(6);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(7);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(8);
+
+		/* Get Trans. */
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(9);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(10);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(11);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(12);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(13);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(14);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(15);
+		emi_ttype_value[i++] = MET_BM_GetLatencyCycle(16);
+	}
+
+	/* Get BACT/BSCT/BCNT */
+	emi_value[j++] = MET_BM_GetBandwidthWordCount();
+	emi_value[j++] = MET_BM_GetOverheadWordCount();
+	emi_value[j++] = MET_BM_GetBusCycCount();
+	/* Get PageHist/PageMiss/InterBank/Idle */
+	for (n = 0; n < dram_chann_num; n++) {
+#if 1
+		/* TBD */
+		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);
+		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);
+#else
+		emi_value[j++] = 0;
+		emi_value[j++] = 0;
+		emi_value[j++] = 0;
+		emi_value[j++] = 0;
+		emi_value[j++] = 0;
+		emi_value[j++] = 0;
+		emi_value[j++] = 0;
+		emi_value[j++] = 0;
+		emi_value[j++] = 0;
+#endif
+	}
+	/* TTYPE */
+	if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {	/*17~21 for ttype*/
+		emi_ttype_value[16] = MET_BM_GetLatencyCycle(17);
+		emi_ttype_value[17] = MET_BM_GetLatencyCycle(18);
+		emi_ttype_value[18] = MET_BM_GetLatencyCycle(19);
+		emi_ttype_value[19] = MET_BM_GetLatencyCycle(20);
+		emi_ttype_value[20] = MET_BM_GetLatencyCycle(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)
+		_ms_dramc(dramc_pdir_value, dram_chann_num);
+
+	MET_BM_Continue();
+	MET_BM_Enable(0);
+	MET_BM_Enable(1);
+
+	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] = 0xffff;
+		ttype_rw_val[i] =  BM_TRANS_RW_DEFAULT;
+	}
+
+	ret = MET_BM_Init();
+	if (ret != 0) {
+		pr_err("MET_BM_Init failed!!!\n");
+		ret = 0;	/* will retry later */
+	} else {
+		emi_inited = 1;
+	}
+
+	kobj_emi = parent;
+
+#define	KOBJ_ATTR_ITEM(attr_name) \
+	ret = sysfs_create_file(kobj_emi, &attr_name##_attr.attr); \
+	if (ret != 0) { \
+		pr_err("Failed to create " #attr_name " in sysfs\n"); \
+		return ret; \
+	}
+	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_err("MET_BM_Init failed!!!\n");
+			return;
+		}
+		emi_inited = 1;
+	}
+
+	if (do_emi()) {
+		emi_init();
+		emi_stop();
+		emi_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];
+
+	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)
+		ms_dramc(DRAMC_Debug_MAX_CNT*dram_chann_num, dramc_pdir_value);
+
+	/* output ms_ttype */
+	if ((ttype1_16_en == BM_TTYPE1_16_ENABLE) && (ttype17_21_en == BM_TTYPE17_21_ENABLE))
+		ms_ttype(21, emi_ttype_value);
+	else if (ttype17_21_en == BM_TTYPE17_21_ENABLE)
+		ms_ttype(5, (emi_ttype_value + 16));
+
+	/* adjust MDMCU buffer */
+	if (mdmcu_sel_enable == 1)
+		MET_BM_SetMDCT_MDMCU(rd_mdmcu_rsv_num);
+}
+
+static 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;
+
+	/*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, "ttyp%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, "ttyp%d_%s",
+					i+1, "unknown");
+		} else {
+			ret_m[i] = snprintf(ttype_name[i], TTYPE_NAME_STR_LEN, "ttyp%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*/
+		}
+	}
+
+	dram_chann_num = MET_EMI_GetDramChannNum();
+	/* met_dram_chann_num_header */
+	/* TBD: what is VID */
+	ret = snprintf(buf, PAGE_SIZE, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d,%d\n",
+			dram_chann_num, DRAM_EMI_BASECLOCK_RATE, DRAM_IO_BUS_WIDTH, DRAM_DATARATE, 0);
+
+	/* 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);
+
+	dram_data_rate_MHz = get_dram_data_rate();
+	ret += snprintf(buf+ret, PAGE_SIZE-ret,
+			"met-info [000] 0.0: met_dram_clockrate: %u\n",
+			dram_data_rate_MHz);
+
+	/*master port mapping*/
+	ret += snprintf(buf+ret, PAGE_SIZE-ret,
+			"met-info [000] 0.0: met_emi_mport_map: %s,%s,%s,%s,%s,%s,%s,%s\n",
+			BM_Master_M0_name, BM_Master_M1_name, BM_Master_M2_name, BM_Master_M3_name,
+			BM_Master_M4_name, BM_Master_M5_name, BM_Master_M6_name, BM_Master_M7_name);
+
+	/* not to change by default master port sequency */
+	ret += snprintf(buf+ret, PAGE_SIZE-ret,
+			"met-info [000] 0.0: met_emi_mgroup_map: %x,%x,%x,%x\n",
+			BM_Master_GP_AP, BM_Master_GP_MM, BM_Master_GP_GPU, BM_Master_GP_PERI);
+
+	/* 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);
+
+	/* msel 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_GP_1_Default & BM_MASTER_ALL,
+				BM_Master_GP_2_Default & BM_MASTER_ALL,
+				BM_Master_GP_3_Default & BM_MASTER_ALL);
+	}
+
+	/* ms_emi */
+	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,");
+
+	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,");
+
+	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_ud_sys_header: ms_emi_tsct,");
+		ret += snprintf(buf+ret, PAGE_SIZE-ret,
+				"tsct1,tsct2,tsct3,x,x,x\n");
+	}
+
+
+	/*MDCT header*/
+	if (emi_mdct_enable == 1) {
+		ret += snprintf(buf+ret, PAGE_SIZE-ret,
+				"met-info [000] 0.0: ms_ud_sys_header: ms_emi_mdct,");
+		ret += snprintf(buf+ret, PAGE_SIZE-ret,
+				"RD_ULTRA,RD_MDMCU,d,d\n");
+		ret += snprintf(buf+ret, PAGE_SIZE-ret,
+				"met-info [000] 0.0: ms_ud_sys_description: ms_emi_mdct:");
+		ret += snprintf(buf+ret, PAGE_SIZE-ret,
+				"CHART_TYPE=histogram_edge;STATISTICS_METHOD=histogram_edge;CHART_RESAMPLE_METHOD=del_dup\n");
+	}
+
+	/*ttype header*/
+	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");
+	}
+
+	/* 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 */
+	ret += snprintf(buf+ret, PAGE_SIZE-ret,
+			"met-info [000] 0.0: ms_ud_sys_header: DRAM_DVFS,datarate(MHz),d\n");
+	ret += snprintf(buf+ret, PAGE_SIZE-ret,
+			"met-info [000] 0.0: ms_ud_sys_description: DRAM_DVFS:");
+	ret += snprintf(buf+ret, PAGE_SIZE-ret,
+			"CHART_TYPE=histogram_edge;STATISTICS_METHOD=histogram_edge;CHART_RESAMPLE_METHOD=del_dup\n");
+
+	/*PDIR met_dramc_header*/
+	if (dramc_pdir_enable == 1) {
+		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,
+				"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");
+	}
+	return ret;
+}
+
+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,
+	.timed_polling	= met_emi_polling,
+	.print_help		= emi_print_help,
+	.print_header	= emi_print_header,
+};