kernel_samsung_a34x-permissive/drivers/misc/mediatek/dvfsrc/dvfsrc-debug-v61.c
2024-04-28 15:51:13 +02:00

336 lines
8.3 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
*/
#include <linux/arm-smccc.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/soc/mediatek/mtk_dvfsrc.h>
#include <linux/soc/mediatek/mtk_sip_svc.h>
#include "dvfsrc-debug.h"
#include "dvfsrc-common.h"
#if IS_ENABLED(CONFIG_MTK_DRAMC_LEGACY)
#include <mtk_dramc.h>
#endif
enum dvfsrc_regs {
DVFSRC_BASIC_CONTROL,
DVFSRC_SW_REQ1,
DVFSRC_INT,
DVFSRC_INT_EN,
DVFSRC_SW_BW_0,
DVFSRC_VCORE_REQUEST,
DVFSRC_LEVEL,
DVFSRC_LAST,
DVFSRC_MD_SCENARIO,
DVFSRC_RECORD_0,
DVFSRC_RSRV_0,
};
static const int mt6761_regs[] = {
[DVFSRC_BASIC_CONTROL] = 0x0,
[DVFSRC_SW_REQ1] = 0x4,
[DVFSRC_INT] = 0x98,
[DVFSRC_INT_EN] = 0x9C,
[DVFSRC_SW_BW_0] = 0x160,
[DVFSRC_VCORE_REQUEST] = 0x48,
[DVFSRC_LEVEL] = 0xDC,
[DVFSRC_LAST] = 0x308,
[DVFSRC_MD_SCENARIO] = 0x310,
[DVFSRC_RECORD_0] = 0x400,
[DVFSRC_RSRV_0] = 0x600,
};
enum dvfsrc_spm_regs {
SPM_POWERON_CONFIG_EN,
SPM_PCM_IM_PTR,
SPM_MD2SPM_DVFS_CON,
SPM_SW_FLAG,
SPM_SW_RSV_9,
SPM_DVFS_EVENT_STA,
SPM_DVFS_LEVEL,
SPM_DFS_LEVEL,
SPM_DVS_LEVEL,
SPM_DVFS_CMD0,
SPM_DVFS_CMD1,
SPM_DVFS_CMD2,
SPM_DVFS_CMD3,
SPM_DVFS_CMD4,
};
static const int mt6761_spm_regs[] = {
[SPM_POWERON_CONFIG_EN] = 0x0,
[SPM_PCM_IM_PTR] = 0x020,
[SPM_MD2SPM_DVFS_CON] = 0x43C,
[SPM_SW_FLAG] = 0x600,
[SPM_SW_RSV_9] = 0x658,
[SPM_DVFS_EVENT_STA] = 0x69C,
[SPM_DVFS_LEVEL] = 0x6A4,
[SPM_DFS_LEVEL] = 0x6B0,
[SPM_DVS_LEVEL] = 0x6B4,
[SPM_DVFS_CMD0] = 0x710,
[SPM_DVFS_CMD1] = 0x714,
[SPM_DVFS_CMD2] = 0x718,
[SPM_DVFS_CMD3] = 0x71C,
[SPM_DVFS_CMD4] = 0x720,
};
#define DVFSRC_TARGET_LEVEL(x) (((x) >> 0) & 0x0000ffff)
#define DVFSRC_CURRENT_LEVEL(x) (((x) >> 16) & 0x0000ffff)
static u32 dvfsrc_read(struct mtk_dvfsrc *dvfs, u32 reg, u32 offset)
{
return readl(dvfs->regs + dvfs->dvd->config->regs[reg] + offset);
}
static u32 spm_read(struct mtk_dvfsrc *dvfs, u32 reg)
{
return readl(dvfs->spm_regs + dvfs->dvd->config->spm_regs[reg]);
}
#if defined(CONFIG_MACH_MT6761) || defined(CONFIG_MACH_MT6765)
#define MTK_SIP_VCOREFS_DVFS_HOPPING_STATE 20
static int dvfsrc_dvfs_hopping_status(void)
{
struct arm_smccc_res ares;
arm_smccc_smc(MTK_SIP_VCOREFS_CONTROL,
MTK_SIP_VCOREFS_DVFS_HOPPING_STATE,
0, 0, 0, 0, 0, 0,
&ares);
if (!ares.a0)
return ares.a1;
return 0;
}
#endif
#if defined(CONFIG_MACH_MT6761) || defined(CONFIG_MACH_MT6765)
#define MTK_SIP_VCOREFS_GET_EFUSE 18
static int dvfsrc_dvfs_get_efuse_data(u32 idx)
{
struct arm_smccc_res ares;
arm_smccc_smc(MTK_SIP_VCOREFS_CONTROL,
MTK_SIP_VCOREFS_GET_EFUSE,
idx, 0, 0, 0, 0, 0,
&ares);
if (!ares.a0)
return ares.a1;
return 0;
}
#endif
static char *dvfsrc_dump_info(struct mtk_dvfsrc *dvfsrc,
char *p, u32 size)
{
int vcore_uv = 0;
char *buff_end = p + size;
if (dvfsrc->vcore_power)
vcore_uv = regulator_get_voltage(dvfsrc->vcore_power);
p += snprintf(p, buff_end - p, "%-10s: %-8u uv\n",
"Vcore", vcore_uv);
#if IS_ENABLED(CONFIG_MTK_DRAMC_LEGACY)
p += snprintf(p, buff_end - p, "%-10s: %-8u khz\n",
"DDR", get_dram_data_rate() * 1000);
#endif
#if defined(CONFIG_MACH_MT6761) || defined(CONFIG_MACH_MT6765)
p += snprintf(p, buff_end - p, "%-10s: %d\n",
"GPS_HOPPING", dvfsrc_dvfs_hopping_status());
#endif
#if defined(CONFIG_MACH_MT6761)
p += snprintf(p, buff_end - p, "%-10s: %08x\n",
"EFUSE_0", dvfsrc_dvfs_get_efuse_data(0));
#endif
#if defined(CONFIG_MACH_MT6765)
p += snprintf(p, buff_end - p, "%-10s: %08x\n",
"PTPOD_0", dvfsrc_dvfs_get_efuse_data(0));
p += snprintf(p, buff_end - p, "%-10s: %08x\n",
"PTPOD_10", dvfsrc_dvfs_get_efuse_data(1));
p += snprintf(p, buff_end - p, "%-10s: %08x\n",
"INFO2", dvfsrc_dvfs_get_efuse_data(2));
#endif
p += snprintf(p, buff_end - p, "\n");
return p;
}
static char *dvfsrc_dump_record(struct mtk_dvfsrc *dvfsrc,
char *p, u32 size)
{
int i, rec_offset, offset;
char *buff_end = p + size;
p += sprintf(p, "%-17s: 0x%08x\n",
"DVFSRC_LAST",
dvfsrc_read(dvfsrc, DVFSRC_LAST, 0));
rec_offset = 0xC;
for (i = 0; i < 8; i++) {
offset = i * rec_offset;
p += snprintf(p, buff_end - p,
"[%d]%-14s: %08x,%08x,%08x\n",
i,
"DVFSRC_REC 0~2",
dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x0),
dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x4),
dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x8));
}
p += snprintf(p, buff_end - p, "\n");
return p;
}
static char *dvfsrc_dump_reg(struct mtk_dvfsrc *dvfsrc, char *p, u32 size)
{
char *buff_end = p + size;
p += snprintf(p, buff_end - p, "%-16s: 0x%08x\n",
"BASIC_CONTROL",
dvfsrc_read(dvfsrc, DVFSRC_BASIC_CONTROL, 0x0));
p += snprintf(p, buff_end - p,
"%-16s: %08x, %08x\n",
"SW_REQ 1~2",
dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0x0),
dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0x4));
p += snprintf(p, buff_end - p, "%-16s: %d, %d, %d, %d, %d\n",
"SW_BW_0~4",
dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0x0),
dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0x4),
dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0x8),
dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0xC),
dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0x10));
p += snprintf(p, buff_end - p, "%-16s: 0x%08x\n",
"INT",
dvfsrc_read(dvfsrc, DVFSRC_INT, 0x0));
p += snprintf(p, buff_end - p, "%-16s: 0x%08x\n",
"INT_EN",
dvfsrc_read(dvfsrc, DVFSRC_INT_EN, 0x0));
p += snprintf(p, buff_end - p, "%-16s: 0x%08x\n",
"MD_SCENARIO",
dvfsrc_read(dvfsrc, DVFSRC_MD_SCENARIO, 0x0));
p += snprintf(p, buff_end - p, "%-16s: 0x%08x\n",
"MD_RSV0",
dvfsrc_read(dvfsrc, DVFSRC_RSRV_0, 0x0));
p += snprintf(p, buff_end - p, "%-16s: 0x%08x\n",
"SCP_VCORE_REQ",
dvfsrc_read(dvfsrc, DVFSRC_VCORE_REQUEST, 0x0));
p += snprintf(p, buff_end - p, "%-16s: 0x%08x\n",
"CURRENT_LEVEL",
dvfsrc_read(dvfsrc, DVFSRC_LEVEL, 0x0));
p += snprintf(p, buff_end - p, "%-16s: %d\n",
"FORCE_OPP_IDX",
dvfsrc->force_opp_idx);
p += snprintf(p, buff_end - p, "%-16s: %d\n",
"CURR_DVFS_OPP",
mtk_dvfsrc_query_opp_info(MTK_DVFSRC_CURR_DVFS_OPP));
p += snprintf(p, buff_end - p, "%-16s: %d\n",
"CURR_VCORE_OPP",
mtk_dvfsrc_query_opp_info(MTK_DVFSRC_CURR_VCORE_OPP));
p += snprintf(p, buff_end - p, "%-16s: %d\n",
"CURR_DRAM_OPP",
mtk_dvfsrc_query_opp_info(MTK_DVFSRC_CURR_DRAM_OPP));
p += snprintf(p, buff_end - p, "\n");
return p;
}
static char *dvfsrc_dump_spm_info(struct mtk_dvfsrc *dvfsrc,
char *p, u32 size)
{
char *buff_end = p + size;
if (!dvfsrc->spm_regs)
return p;
p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n",
"POWERON_CONFIG_EN",
spm_read(dvfsrc, SPM_POWERON_CONFIG_EN));
p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n",
"SPM_SW_FLAG",
spm_read(dvfsrc, SPM_SW_FLAG));
p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n",
"SPM_SW_RSV_9",
spm_read(dvfsrc, SPM_SW_RSV_9));
p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n",
"MD2SPM_DVFS_CON",
spm_read(dvfsrc, SPM_MD2SPM_DVFS_CON));
p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n",
"SPM_DVFS_EVENT_STA",
spm_read(dvfsrc, SPM_DVFS_EVENT_STA));
p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n",
"SPM_DVFS_LEVEL",
spm_read(dvfsrc, SPM_DVFS_LEVEL));
p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n",
"SPM_DFS_LEVEL",
spm_read(dvfsrc, SPM_DFS_LEVEL));
p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n",
"SPM_DVS_LEVEL",
spm_read(dvfsrc, SPM_DVS_LEVEL));
p += snprintf(p, buff_end - p,
"%-24s: 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
"SPM_DVFS_CMD0~4",
spm_read(dvfsrc, SPM_DVFS_CMD0),
spm_read(dvfsrc, SPM_DVFS_CMD1),
spm_read(dvfsrc, SPM_DVFS_CMD2),
spm_read(dvfsrc, SPM_DVFS_CMD3),
spm_read(dvfsrc, SPM_DVFS_CMD4));
p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n",
"PCM_IM_PTR",
spm_read(dvfsrc, SPM_PCM_IM_PTR));
p += snprintf(p, buff_end - p, "\n");
return p;
}
static int dvfsrc_query_request_status(struct mtk_dvfsrc *dvfsrc, u32 id)
{
return 0;
}
static void dvfsrc_force_opp(struct mtk_dvfsrc *dvfsrc, u32 opp)
{
dvfsrc->force_opp_idx = opp;
mtk_dvfsrc_send_request(dvfsrc->dev->parent,
MTK_DVFSRC_CMD_FORCE_OPP_REQUEST,
opp);
}
const struct dvfsrc_config mt6761_dvfsrc_config = {
.regs = mt6761_regs,
.spm_regs = mt6761_spm_regs,
.dump_info = dvfsrc_dump_info,
.dump_record = dvfsrc_dump_record,
.dump_reg = dvfsrc_dump_reg,
.dump_spm_info = dvfsrc_dump_spm_info,
.force_opp = dvfsrc_force_opp,
.query_request = dvfsrc_query_request_status,
};