blob: 411fc1a19648bdcf9aad1f8d64a94755bb0d089e [file] [log] [blame]
/*
* 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);