本篇主要介绍在SDM450 Android9平台MMC子系统添加接口来获取金士顿EMMC数据写入量方案。
1、金士顿数据写入量获取流程
2、数据写入量结果计算方式
从金士顿提供的文档来看,整体流程如下:
1、首先发生CMD16设置blocklen为512字节
2、CMD16发送成功后,发送CMD56用于获取数据写入量
3、CMD56获取到的数据信息:
bit15~bit12:written data unit size
bit19~bit16:written data sector size
SDM450 Android10平台添加接口代码如下:
1、kernel/msm-4.9/drivers/mmc/core/mmc_ops.c文件添加获取写入量接口
#define HEX_STR_STEP (3)
#define HEX_STR_SPLIT_DSPACE (' ')
#define HEX_STR_SPLIT_SEMICOLON (':')
#define HEX_STR_SPLIT_COMMA (',')
static int starce_hex2str(uint8_t *byte, int byte_len, uint8_t *str, long str_len,uint8_t split_c)
{
int i = 0;
char *pos = (char*)str;
long tmp_len = 0;
tmp_len = HEX_STR_STEP*byte_len + 1;
if(str_len < tmp_len){
pr_err("ERROR: len error %ld,%ld\n",str_len,tmp_len);
return -1;
}
for(i = 0; i < byte_len -1; i += 1){
pos += sprintf(pos, "%02X%c", byte[i],split_c);
}
pos += sprintf(pos, "%02X", byte[byte_len - 1]);
if(str_len != ((uint8_t *)pos - str + HEX_STR_STEP)){
pr_err("ERROR: starce_hex2str str_len =%ld, sp len =%ld\n",str_len,((uint8_t *)pos - str + HEX_STR_STEP));
return -1;
}
return 0;
}
uint8_t * trace_byte_to_str(uint8_t* trace_byte_data,int len)
{
int trace_str_len = len*3+2;
uint8_t *trace_str_data = NULL;
int ret = 0;
if(NULL == trace_byte_data){
pr_err("tarce data is NULL\n");
goto error;
}
pr_err("malloc trace_str_len=%d\n",trace_str_len);
trace_str_data = (uint8_t *)kmalloc(trace_str_len,GFP_KERNEL);
if(NULL != trace_str_data){
memset(trace_str_data,0,trace_str_len);
ret = starce_hex2str(trace_byte_data,len,trace_str_data,trace_str_len,HEX_STR_SPLIT_DSPACE);
if(0 != ret){
pr_err("error starce_hex2str fail %d\n",ret);
goto error;
}
}else{
pr_err("tarce str malloc trace_str_len=%d fail\n",trace_str_len);
goto error;
}
return trace_str_data;
error:
return NULL;
}
int mmc_get_wr_data(struct mmc_card *card, struct mmc_host *host, u32 *unit, u32 *sector)
{
struct mmc_request mrq;
struct mmc_command cmd;
struct mmc_data data;
struct scatterlist sg;
char *data_buf;
char* buf = NULL;
int err = 0;
err = mmc_set_blocklen(card, 512);
pr_err("%s:%d: send CMD16 err = %d\n", __func__, __LINE__, err);
memset(&mrq, 0, sizeof(struct mmc_request));
memset(&cmd, 0, sizeof(struct mmc_command));
memset(&data, 0, sizeof(struct mmc_data));
data_buf = kmalloc(512, GFP_KERNEL);
if (data_buf == NULL)
return -ENOMEM;
mrq.cmd = &cmd;
mrq.data = &data;
cmd.opcode = MMC_GEN_CMD;
cmd.arg = 0x8D;
cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC;
data.blksz = 512;
data.blocks = 1;
data.flags = MMC_DATA_READ;
data.sg = &sg;
data.sg_len = 1;
sg_init_one(&sg, data_buf, 512);
mmc_wait_for_req(host, &mrq);
pr_err("%s:%d: send CMD56 err = %d\n", __func__, __LINE__, cmd.error);
if (cmd.error) {
err = cmd.error;
}
else {
buf = (char*)trace_byte_to_str(data_buf,512);
if(NULL != buf){
pr_err("data=%s\n",buf);
}
pr_err("%02x %02x %02x %02x\n",data_buf[15],data_buf[14],data_buf[13],data_buf[12]);
pr_err("%02x %02x %02x %02x\n",data_buf[19],data_buf[18],data_buf[17],data_buf[16]);
*unit = data_buf[15];
*unit = *unit << 8 | data_buf[14];
*unit = *unit << 8 | data_buf[13];
*unit = *unit << 8 | data_buf[12];
*sector = data_buf[19];
*sector = *sector << 8 | data_buf[18];
*sector = *sector << 8 | data_buf[17];
*sector = *sector << 8 | data_buf[16];
}
kfree(data_buf);
return err;
}
2、 kernel/msm-4.9 / drivers/mmc/core/mmc_ops.h
int mmc_get_wr_data(struct mmc_card *card, struct mmc_host *host, u32 *unit, u32 *sector);
3、 kernel/msm-4.9 / include/linux/mmc/card.h
struct mmc_card {
......
u32 unit;
u32 sector;
}
4、 kernel/msm-4.9 / drivers/mmc/core/mmc.c
static ssize_t mmc_wr_data_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct mmc_card *card = mmc_dev_to_card(dev);
return sprintf(buf, "unit=0x%x\nsector=0x%x\n", card->unit, card->sector);
}
static DEVICE_ATTR(data_size, S_IRUGO, mmc_wr_data_show, NULL);
static struct attribute *mmc_std_attrs[] = {
......
&dev_attr_data_size.attr,
}
static int mmc_init_card(struct mmc_host *host, u32 ocr,
struct mmc_card *oldcard)
{
......
u32 unit = 0;
u32 sector = 0;
err = mmc_get_wr_data(card, host, &unit, §or);
if (err == 0) {
card->unit = unit;
card->sector = sector;
}
pr_err("%s:%d:unit = 0x%x, sector = 0x%x\n", __func__, __LINE__, unit, sector);
}
最终在/sys/bus/mmc/devices/mmc0:0001下生成data_size节点,用于查看数据写入量:如下
数据写入量计算结果:
数据写入量 = (unit*128 + sector)512/1024/1024/1024 = (90313128 + 913) * 512/1024/1024/1024 = 5.5GB