[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, ×) != 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, ×) != 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, ×) != 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_ */