kernel_samsung_a34x-permissive/drivers/misc/mediatek/cmdq/v2/cmdq_prof.c
2024-04-28 15:51:13 +02:00

158 lines
3.5 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc.
*/
#include "cmdq_prof.h"
#include "cmdq_core.h"
/* expect no EMI latency, GCE spends 80 ns per 4 cycle*/
#define CMDQ_HW_EXEC_NS(hw_cycle) (hw_cycle * (80 / 4))
enum CMDQ_OP_STATISTIC_ENUM {
CMDQ_STA_READ = 0,
CMDQ_STA_MOVE,
CMDQ_STA_WRI,
CMDQ_STA_WRI_WITH_MASK,
CMDQ_STA_POLL,
CMDQ_STA_JUMP,
CMDQ_STA_WFE, /* wait for event */
CMDQ_STA_SYNC, /* sync op and no wait for event */
CMDQ_STA_EOC,
CMDQ_STA_MAX_COUNT, /* always keep at the end */
};
const char *cmdq_prof_get_statistic_id_name(
const enum CMDQ_OP_STATISTIC_ENUM statisticId)
{
const char *IDName = "UNKNOWN";
#undef DECLARE_CMDQ_INSTR_CYCLE
#define DECLARE_CMDQ_INSTR_CYCLE(id, hw_op, cycle, name) \
{ if (id == statisticId) {IDName = #name; break; } }
do {
#include "cmdq_instr_cycle.h"
} while (0);
#undef DECLARE_CMDQ_INSTR_CYCLE
return IDName;
}
uint32_t cmdq_prof_get_statistic_id(const uint32_t *pCmd)
{
const uint32_t arg_b = pCmd[0];
const uint32_t arg_a = pCmd[1];
const uint32_t op = arg_a >> 24;
uint32_t addr;
uint32_t maskEn = 0;
switch (op) {
case CMDQ_CODE_WRITE:
/* check address */
if (arg_a & (1 << 23)) {
/* address is GPR */
return CMDQ_STA_WRI;
}
addr = cmdq_core_subsys_to_reg_addr(arg_a);
maskEn = (addr & 0x1);
if (maskEn)
return CMDQ_STA_WRI_WITH_MASK;
else
return CMDQ_STA_WRI;
case CMDQ_CODE_WFE:
/* check waiting flag */
if ((arg_b >> 15) & 0x1)
return CMDQ_STA_WFE;
else
return CMDQ_STA_SYNC;
case CMDQ_CODE_READ:
return CMDQ_STA_READ;
case CMDQ_CODE_MOVE:
return CMDQ_STA_MOVE;
case CMDQ_CODE_POLL:
return CMDQ_STA_POLL;
case CMDQ_CODE_JUMP:
return CMDQ_STA_JUMP;
case CMDQ_CODE_EOC:
return CMDQ_STA_EOC;
default:
CMDQ_ERR("unknown op, arg_a: 0x%08x\n", arg_a);
return 0;
}
CMDQ_ERR("unknown op, arg_a: 0x%08x\n", arg_a);
return 0;
}
uint32_t cmdq_prof_calculate_HW_cycle(
const enum CMDQ_OP_STATISTIC_ENUM statisticId,
const uint32_t count)
{
uint32_t hwCycle = -1;
#undef DECLARE_CMDQ_INSTR_CYCLE
#define DECLARE_CMDQ_INSTR_CYCLE(id, hw_op, cycle, name) { \
if (id == statisticId) { \
hwCycle = (count * cycle); \
break; \
} \
}
do {
#include "cmdq_instr_cycle.h"
} while (0);
#undef DECLARE_CMDQ_INSTR_CYCLE
if (-1 == hwCycle) {
/* Error message dump */
CMDQ_ERR("unknown statisticId: %d\n", statisticId);
}
return hwCycle;
}
int32_t cmdq_prof_estimate_command_exe_time(const uint32_t *pCmd,
uint32_t commandSize)
{
uint32_t statistic[CMDQ_STA_MAX_COUNT] = { 0 };
int i;
uint32_t statisticId = 0;
uint32_t cycle = 0;
uint32_t totalCycle = 0;
uint32_t totalNS = 0;
if (pCmd == NULL)
return -EFAULT;
/* gather statistic */
for (i = 0; i < commandSize; i += CMDQ_INST_SIZE, pCmd += 2) {
statisticId = cmdq_prof_get_statistic_id(pCmd);
statistic[statisticId] += 1;
}
CMDQ_LOG("NAME, COUNT, least HW exec cycle\n");
/* calculate execution time */
for (i = 0; i < CMDQ_STA_MAX_COUNT; i++) {
cycle = cmdq_prof_calculate_HW_cycle(i, statistic[i]);
totalCycle += cycle;
CMDQ_LOG("%d:%11s, %d, %3d\n",
i, cmdq_prof_get_statistic_id_name(i),
statistic[i], cycle);
}
totalNS = CMDQ_HW_EXEC_NS(totalCycle);
CMDQ_LOG("=====================================\n");
CMDQ_LOG("estimated least HW exec time(ns): %6d\n", totalNS);
CMDQ_LOG("***each HW cycle spends time(ns): %6d\n",
CMDQ_HW_EXEC_NS(1));
/* ***Real exec time will be longer when POLL/WAIT */
/* instr cannot pass their condition immediately. */
return totalNS;
}