[Feature]add MT2731_MP2_MR2_SVN388 baseline version
Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/devtools/met-driver/4.14/common/met_emi_35.c b/src/devtools/met-driver/4.14/common/met_emi_35.c
new file mode 100644
index 0000000..411fc1a
--- /dev/null
+++ b/src/devtools/met-driver/4.14/common/met_emi_35.c
@@ -0,0 +1,2244 @@
+/*
+ * 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/dma-mapping.h>
+#include <linux/string.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "core_plf_init.h"
+#include "mtk_emi_bm_35.h"
+#include "interface.h"
+#include "met_dramc.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 = 1;
+int emi_mdct_enable = 1;
+int emi_TP_busfiltr_enable;
+
+
+/* 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;
+
+
+/* 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
+};
+
+
+
+/*======================================================================*/
+/* KOBJ Declarations */
+/*======================================================================*/
+
+
+DECLARE_KOBJ_ATTR_INT(emi_TP_busfiltr_enable, emi_TP_busfiltr_enable);
+
+
+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);
+
+
+
+/* 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)
+{
+ 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: 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" }
+ )
+ );
+
+
+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_TP_busfiltr_enable = 0;
+
+ high_priority_filter = 0x0;
+ rwtype = BM_BOTH_READ_WRITE;
+ dramc_pdir_enable = 1;
+
+
+ msel_enable = 0;
+ msel_group1 = BM_MASTER_ALL;
+ msel_group2 = BM_MASTER_ALL;
+ msel_group3 = BM_MASTER_ALL;
+
+
+ bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+ ttype1_16_en = BM_TTYPE1_16_DISABLE;
+ ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+}
+
+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(emi_TP_busfiltr_enable); \
+ KOBJ_ATTR_ITEM(msel_enable); \
+ KOBJ_ATTR_ITEM(msel_group1); \
+ KOBJ_ATTR_ITEM(msel_group2); \
+ KOBJ_ATTR_ITEM(msel_group3); \
+ 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(bw_limiter_enable); \
+ KOBJ_ATTR_ITEM(dramc_pdir_enable); \
+ 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);
+
+ /*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);
+
+}
+
+
+static void emi_uninit(void)
+{
+ MET_BM_RestoreCfg();
+}
+
+
+static inline int do_emi(void)
+{
+ return met_sspm_emi.mode;
+}
+
+
+
+
+
+
+
+/*======================================================================*/
+/* 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_resume(void)
+{
+ if (!do_emi())
+ return;
+
+ emi_init();
+}
+
+
+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
+
+
+ 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 */
+
+ dram_chann_num = MET_EMI_GetDramChannNum();
+
+ 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__);
+
+
+ /* 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);
+
+
+ /*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;
+}
+
+
+
+static int ondiemet_emi_print_header(char *buf, int 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[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_sspm_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();
+}
+
+
+
+struct metdevice met_sspm_emi = {
+ .name = "emi",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_emi_create,
+ .delete_subfs = met_emi_delete,
+ .resume = met_emi_resume,
+#if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+ .ondiemet_start = ondiemet_emi_start,
+ .ondiemet_stop = ondiemet_emi_stop,
+ .ondiemet_print_help = emi_print_help,
+ .ondiemet_print_header = ondiemet_emi_print_header,
+#endif
+ .ondiemet_mode = 1,
+};
+EXPORT_SYMBOL(met_sspm_emi);
\ No newline at end of file