// SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2019 MediaTek Inc. */ #include #include #include #include #include #include #include #include #include #include "dvfsrc-helper.h" #include "dvfsrc-common.h" enum dvfsrc_regs { DVFSRC_BASIC_CONTROL, DVFSRC_SW_REQ1, DVFSRC_INT, DVFSRC_INT_EN, DVFSRC_SW_BW_0, DVFSRC_ISP_HRT, DVFSRC_DEBUG_STA_0, DVFSRC_VCORE_REQUEST, DVFSRC_CURRENT_LEVEL, DVFSRC_TARGET_LEVEL, DVFSRC_LAST, DVFSRC_RECORD_0, DVFSRC_DDR_REQUEST, DVSFRC_HRT_REQ_MD_URG, DVFSRC_HRT_REQ_MD_BW_0, DVFSRC_HRT_REQ_MD_BW_8, DVFSRC_MD_TURBO, DVFSRC_95MD_SCEN_BW4, DVFSRC_95MD_SCEN_BW0, DVFSRC_95MD_SCEN_BW0_T, DVFSRC_RSRV_4, DVFSRC_MD_DDR_FLOOR_REQUEST, DVFSRC_QOS_DDR_REQUEST, }; static const int mt6779_regs[] = { [DVFSRC_BASIC_CONTROL] = 0x0, [DVFSRC_SW_REQ1] = 0x4, [DVFSRC_INT] = 0xC4, [DVFSRC_INT_EN] = 0xC8, [DVFSRC_SW_BW_0] = 0x260, [DVFSRC_ISP_HRT] = 0x290, [DVFSRC_DEBUG_STA_0] = 0x700, [DVFSRC_VCORE_REQUEST] = 0x6C, [DVFSRC_CURRENT_LEVEL] = 0xD44, [DVFSRC_TARGET_LEVEL] = 0xD48, [DVFSRC_LAST] = 0xB08, [DVFSRC_RECORD_0] = 0xB14, [DVFSRC_DDR_REQUEST] = 0xA00, [DVSFRC_HRT_REQ_MD_URG] = 0xA88, [DVFSRC_HRT_REQ_MD_BW_0] = 0xA8C, [DVFSRC_HRT_REQ_MD_BW_8] = 0xACC, }; static const int mt6873_regs[] = { [DVFSRC_BASIC_CONTROL] = 0x0, [DVFSRC_SW_REQ1] = 0x4, [DVFSRC_INT] = 0xC4, [DVFSRC_INT_EN] = 0xC8, [DVFSRC_SW_BW_0] = 0x260, [DVFSRC_ISP_HRT] = 0x290, [DVFSRC_DEBUG_STA_0] = 0x700, [DVFSRC_VCORE_REQUEST] = 0x6C, [DVFSRC_CURRENT_LEVEL] = 0xD44, [DVFSRC_TARGET_LEVEL] = 0xD48, [DVFSRC_LAST] = 0xAE4, [DVFSRC_RECORD_0] = 0xAF0, [DVFSRC_DDR_REQUEST] = 0xA00, [DVSFRC_HRT_REQ_MD_URG] = 0xA64, [DVFSRC_HRT_REQ_MD_BW_0] = 0xA8C, [DVFSRC_HRT_REQ_MD_BW_8] = 0xACC, [DVFSRC_MD_TURBO] = 0xDC, [DVFSRC_95MD_SCEN_BW4] = 0x544, [DVFSRC_95MD_SCEN_BW0] = 0x524, [DVFSRC_95MD_SCEN_BW0_T] = 0x534, [DVFSRC_RSRV_4] = 0x610, }; static const int mt6983_regs[] = { [DVFSRC_BASIC_CONTROL] = 0x0, [DVFSRC_SW_REQ1] = 0x10, [DVFSRC_INT] = 0xC8, [DVFSRC_INT_EN] = 0xCC, [DVFSRC_SW_BW_0] = 0x1DC, [DVFSRC_ISP_HRT] = 0x20C, [DVFSRC_DEBUG_STA_0] = 0x29C, [DVFSRC_VCORE_REQUEST] = 0x80, [DVFSRC_CURRENT_LEVEL] = 0x5F0, [DVFSRC_TARGET_LEVEL] = 0x5F0, [DVFSRC_LAST] = 0x3AC, [DVFSRC_RECORD_0] = 0x3B8, [DVFSRC_DDR_REQUEST] = 0x2C8, [DVSFRC_HRT_REQ_MD_URG] = 0x320, [DVFSRC_HRT_REQ_MD_BW_0] = 0x324, [DVFSRC_HRT_REQ_MD_BW_8] = 0x344, [DVFSRC_MD_TURBO] = 0xE0, [DVFSRC_95MD_SCEN_BW4] = 0x278, [DVFSRC_95MD_SCEN_BW0] = 0x258, [DVFSRC_95MD_SCEN_BW0_T] = 0x268, [DVFSRC_RSRV_4] = 0x290, [DVFSRC_MD_DDR_FLOOR_REQUEST] = 0x5E4, [DVFSRC_QOS_DDR_REQUEST] = 0x5E8, }; enum dvfsrc_spm_regs { POWERON_CONFIG_EN, SPM_PC_STA, SPM_SW_FLAG, SPM_DVFS_LEVEL, SPM_DVFS_STA, SPM_DVS_DFS_LEVEL, SPM_DVFS_HISTORY_STA0, SPM_DVFS_HISTORY_STA1, SPM_DVFS_CMD0, SPM_DVFS_CMD1, SPM_DVFS_CMD2, SPM_DVFS_CMD3, SPM_DVFS_CMD4, SPM_TIMER_LATCH, }; static const int mt6873_spm_regs[] = { [POWERON_CONFIG_EN] = 0x0, [SPM_PC_STA] = 0x0194, [SPM_SW_FLAG] = 0x600, [SPM_DVFS_LEVEL] = 0x04A4, [SPM_DVFS_STA] = 0x01F8, [SPM_DVS_DFS_LEVEL] = 0x04F8, [SPM_DVFS_CMD0] = 0x710, [SPM_DVFS_CMD1] = 0x714, [SPM_DVFS_CMD2] = 0x718, [SPM_DVFS_CMD3] = 0x71C, [SPM_DVFS_CMD4] = 0x720, }; static const int mt6893_spm_regs[] = { [POWERON_CONFIG_EN] = 0x0, [SPM_PC_STA] = 0x0194, [SPM_SW_FLAG] = 0x600, [SPM_DVFS_LEVEL] = 0x04A4, [SPM_DVFS_STA] = 0x01F8, [SPM_DVS_DFS_LEVEL] = 0x04F8, [SPM_DVFS_CMD0] = 0x750, [SPM_DVFS_CMD1] = 0x754, [SPM_DVFS_CMD2] = 0x758, [SPM_DVFS_CMD3] = 0x75C, [SPM_DVFS_CMD4] = 0x760, }; static const int mt6877_spm_regs[] = { [POWERON_CONFIG_EN] = 0x0, [SPM_PC_STA] = 0x0194, [SPM_SW_FLAG] = 0x600, [SPM_DVFS_LEVEL] = 0x0390, [SPM_DVFS_STA] = 0x0388, [SPM_DVS_DFS_LEVEL] = 0x038C, [SPM_DVFS_CMD0] = 0x0310, [SPM_DVFS_CMD1] = 0x0314, [SPM_DVFS_CMD2] = 0x0318, [SPM_DVFS_CMD3] = 0x031C, [SPM_DVFS_CMD4] = 0x0320, [SPM_TIMER_LATCH] = 0x514, }; 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]); } static u32 spm_read_offset(struct mtk_dvfsrc *dvfs, u32 reg, u32 offset) { return readl(dvfs->spm_regs + dvfs->dvd->config->spm_regs[reg] + offset); } static u32 dvfsrc_get_scp_req(struct mtk_dvfsrc *dvfsrc) { /* DVFSRC_DEBUG_STA_2 */ return (dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x8) >> 14) & 0x1; } static u32 dvfsrc_get_hifi_scenario(struct mtk_dvfsrc *dvfsrc) { /* DVFSRC_DEBUG_STA_2 */ return (dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x8) >> 16) & 0xFF; } static u32 dvfsrc_get_hifi_vcore_gear(struct mtk_dvfsrc *dvfsrc) { u32 hifi_scen; hifi_scen = __builtin_ffs(dvfsrc_get_hifi_scenario(dvfsrc)); if (hifi_scen) return (dvfsrc_read(dvfsrc, DVFSRC_VCORE_REQUEST, 0xC) >> ((hifi_scen - 1) * 4)) & 0xF; else return 0; } static u32 dvfsrc_get_hifi_ddr_gear(struct mtk_dvfsrc *dvfsrc) { u32 hifi_scen; hifi_scen = __builtin_ffs(dvfsrc_get_hifi_scenario(dvfsrc)); if (hifi_scen) return (dvfsrc_read(dvfsrc, DVFSRC_DDR_REQUEST, 0x14) >> ((hifi_scen - 1) * 4)) & 0xF; else return 0; } static u32 dvfsrc_get_hifi_rising_ddr_gear(struct mtk_dvfsrc *dvfsrc) { u32 val = 0; u32 last; switch (dvfsrc->dvd->config->ip_verion) { case 0: last = dvfsrc_read(dvfsrc, DVFSRC_LAST, 0); val = dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, 0x18 + 0x1C * last); val = (val >> 15) & 0x7; break; case 2: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0); val = (val >> 22) & 0x7; break; case 3: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x20); val = (val >> 4) & 0xF; default: break; } return val; } static u32 dvfsrc_get_md_bw(struct mtk_dvfsrc *dvfsrc) { u32 val = 0; u32 is_urgent, md_scen; u32 index, shift; switch (dvfsrc->dvd->config->ip_verion) { case 0: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0); is_urgent = (val >> 16) & 0x1; md_scen = val & 0xFFFF; if (is_urgent) { val = dvfsrc_read(dvfsrc, DVSFRC_HRT_REQ_MD_URG, 0) & 0x1F; } else { index = md_scen / 3; shift = (md_scen % 3) * 10; if (index > 10) return 0; if (index < 8) { val = dvfsrc_read(dvfsrc, DVFSRC_HRT_REQ_MD_BW_0, index * 4); } else { val = dvfsrc_read(dvfsrc, DVFSRC_HRT_REQ_MD_BW_8, (index - 8) * 4); } val = (val >> shift) & 0x3FF; } break; case 2: case 3: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0xC) & 0x3FF; break; default: break; } return val; } static u32 dvfsrc_get_md_rising_ddr_gear(struct mtk_dvfsrc *dvfsrc) { u32 val = 0; u32 last; switch (dvfsrc->dvd->config->ip_verion) { case 0: /* DVFSRC_RECORD_0_6 */ last = dvfsrc_read(dvfsrc, DVFSRC_LAST, 0); val = dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, 0x18 + 0x1C * last); val = (val >> 9) & 0x7; break; case 2: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0); val = (val >> 29) & 0x7; break; case 3: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0); val = (val >> 20) & 0xF; break; default: break; } return val; } static u32 dvfsrc_get_hrt_bw_ddr_gear(struct mtk_dvfsrc *dvfsrc) { u32 val = 0; u32 last; switch (dvfsrc->dvd->config->ip_verion) { case 0: /* DVFSRC_RECORD_0_6 */ last = dvfsrc_read(dvfsrc, DVFSRC_LAST, 0); val = dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, 0x18 + 0x1C * last); val = (val >> 2) & 0x7; break; case 2: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x10); val = (val >> 16) & 0x7; break; case 3: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x24); val = (val >> 16) & 0xF; break; default: break; } return val; } static u32 dvfsrc_get_md_scen_ddr_gear(struct mtk_dvfsrc *dvfsrc) { u32 is_turbo, is_urgent, md_scen; u32 index, shift; u32 sta0; u32 val = 0; switch (dvfsrc->dvd->config->ip_verion) { case 0: val = 0; break; case 2: is_turbo = (dvfsrc_read(dvfsrc, DVFSRC_MD_TURBO, 0x0) == 0) ? 1 : 0; sta0 = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x0); is_urgent = (sta0 >> 16) & 0x1; md_scen = sta0 & 0xFFFF; if (is_urgent) val = dvfsrc_read(dvfsrc, DVFSRC_95MD_SCEN_BW4, 0x0); else { index = md_scen / 8; shift = (md_scen % 8) * 4; if (md_scen > 31) return 0; if (is_turbo) val = dvfsrc_read(dvfsrc, DVFSRC_95MD_SCEN_BW0_T , index * 4); else val = dvfsrc_read(dvfsrc, DVFSRC_95MD_SCEN_BW0 , index * 4); val = (val >> shift) & 0x7; } break; case 3: val = dvfsrc_read(dvfsrc, DVFSRC_MD_DDR_FLOOR_REQUEST, 0x0); val = val & 0xF; break; default: break; } return val; } static u32 dvfsrc_get_md_imp_ddr(struct mtk_dvfsrc *dvfsrc) { u32 val = 0; switch (dvfsrc->dvd->config->ip_verion) { case 0: val = 0; break; case 2: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x10); val = (val >> 19) & 0x7; break; case 3: val = dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x10); val = val & 0xF; break; default: break; } return val; } 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, "%-11s: %d\n", "DVFSRC_LAST", dvfsrc_read(dvfsrc, DVFSRC_LAST, 0)); if (dvfsrc->dvd->config->ip_verion > 0) rec_offset = 0x20; else rec_offset = 0x1C; for (i = 0; i < 8; i++) { offset = i * rec_offset; p += snprintf(p, buff_end - p, "[%d]%-4s:%08x,%08x,%08x,%08x\n", i, "0~3", dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x0), dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x4), dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x8), dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0xC)); if (dvfsrc->dvd->config->ip_verion > 0) { p += snprintf(p, buff_end - p, "[%d]%-4s:%08x,%08x,%08x,%08x\n", i, "4~7", dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x10), dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x14), dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x18), dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x1C)); } else { p += snprintf(p, buff_end - p, "[%d]%-4s:%08x,%08x,%08x\n", i, "4~6", dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x10), dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x14), dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x18)); } } 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, "%-12s: %08x\n", "CONTROL", dvfsrc_read(dvfsrc, DVFSRC_BASIC_CONTROL, 0x0)); p += snprintf(p, buff_end - p, "%-12s: %08x\n", "CURRENT", dvfsrc_read(dvfsrc, DVFSRC_CURRENT_LEVEL, 0x0)); p += snprintf(p, buff_end - p, "%-12s: %08x\n", "TARGET", dvfsrc_read(dvfsrc, DVFSRC_TARGET_LEVEL, 0x0)); p += snprintf(p, buff_end - p, "%-12s: %08x, %08x, %08x, %08x\n", "SW_REQ 1~4", dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0x0), dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0x4), dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0x8), dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0xC)); p += snprintf(p, buff_end - p, "%-12s: %08x, %08x, %08x, %08x\n", "SW_REQ 5~8", dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0x10), dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0x14), dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0x18), dvfsrc_read(dvfsrc, DVFSRC_SW_REQ1, 0x1C)); p += snprintf(p, buff_end - p, "%-12s: %d, %d, %d, %d, %d, %d, %d\n", "SW_BW_0~6", 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), dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0x14), dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0x18)); if (dvfsrc->dvd->config->ip_verion > 2) { p += snprintf(p, buff_end - p, "%-12s: %d, %d, %d\n", "SW_BW_7~9", dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0x1C), dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0x20), dvfsrc_read(dvfsrc, DVFSRC_SW_BW_0, 0x24)); } p += snprintf(p, buff_end - p, "%-12s: %x\n", "INT", dvfsrc_read(dvfsrc, DVFSRC_INT, 0x0)); p += snprintf(p, buff_end - p, "%-12s: %x\n", "INT_EN", dvfsrc_read(dvfsrc, DVFSRC_INT_EN, 0x0)); p += snprintf(p, buff_end - p, "%-12s: %d\n", "ISP_HRT", dvfsrc_read(dvfsrc, DVFSRC_ISP_HRT, 0x0)); p += snprintf(p, buff_end - p, "%-12s: %08x, %08x, %08x, %08x\n", "DEBUG_STA_0", dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x0), dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x4), dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x8), dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0xC)); p += snprintf(p, buff_end - p, "%-12s: %08x, %08x, %08x\n", "DEBUG_STA_4", dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x10), dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x14), dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x18)); if (dvfsrc->dvd->config->ip_verion > 2) { p += snprintf(p, buff_end - p, "%-12s: %08x, %08x, %08x\n", "DEBUG_STA_7", dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x1C), dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x20), dvfsrc_read(dvfsrc, DVFSRC_DEBUG_STA_0, 0x24)); } p += snprintf(p, buff_end - p, "%-12s: %d\n", "MD_RISING", dvfsrc_get_md_rising_ddr_gear(dvfsrc)); p += snprintf(p, buff_end - p, "%-12s: %d\n", "MD_HRT_BW", dvfsrc_get_md_bw(dvfsrc)); p += snprintf(p, buff_end - p, "%-12s: %d\n", "HRT_BW_REQ", dvfsrc_get_hrt_bw_ddr_gear(dvfsrc)); p += snprintf(p, buff_end - p, "%-12s: %d\n", "HIFI_VCORE", dvfsrc_get_hifi_vcore_gear(dvfsrc)); p += snprintf(p, buff_end - p, "%-12s: %d\n", "HIFI_DDR", dvfsrc_get_hifi_ddr_gear(dvfsrc)); p += snprintf(p, buff_end - p, "%-12s: %d\n", "HIFI_RISING", dvfsrc_get_hifi_rising_ddr_gear(dvfsrc)); p += snprintf(p, buff_end - p, "%-12s: %d, %x\n", "SCP_VCORE", dvfsrc_get_scp_req(dvfsrc), dvfsrc_read(dvfsrc, DVFSRC_VCORE_REQUEST, 0x0)); p += snprintf(p, buff_end - p, "\n"); return p; } static char *dvfsrc_dump_mt6873_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, POWERON_CONFIG_EN)); p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n", "SPM_SW_FLAG_0", spm_read(dvfsrc, SPM_SW_FLAG)); p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n", "SPM_PC_STA", spm_read(dvfsrc, SPM_PC_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_DVS_DFS_LEVEL", spm_read(dvfsrc, SPM_DVS_DFS_LEVEL)); p += snprintf(p, buff_end - p, "%-24s: 0x%08x\n", "SPM_DVFS_STA", spm_read(dvfsrc, SPM_DVFS_STA)); 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)); return p; } static char *dvfsrc_dump_mt6983_spm_cmd(struct mtk_dvfsrc *dvfsrc, char *p, u32 size) { char *buff_end = p + size; int i; if (!dvfsrc->spm_regs) return p; for (i = 0; i < 24; i++) { p += snprintf(p, buff_end - p, "CMD%d: 0x%08x\n", i, spm_read_offset(dvfsrc, SPM_DVFS_CMD0, i * 4)); } return p; } static char *dvfsrc_dump_mt6983_spm_timer_latch(struct mtk_dvfsrc *dvfsrc, char *p, u32 size) { char *buff_end = p + size; int i; unsigned int offset; if (!dvfsrc->spm_regs) return p; if (!dvfsrc->dvd->spm_stamp_en) { p += snprintf(p, buff_end - p, "stamp not support\n"); } else { for (i = 0; i < 8; i++) { offset = i * 0x10; p += snprintf(p, buff_end - p, "T[%d] :%08x,%08x,%08x,%08x\n", i, spm_read_offset(dvfsrc, SPM_TIMER_LATCH, offset + 0x0), spm_read_offset(dvfsrc, SPM_TIMER_LATCH, offset + 0x4), spm_read_offset(dvfsrc, SPM_TIMER_LATCH, offset + 0x8), spm_read_offset(dvfsrc, SPM_TIMER_LATCH, offset + 0xC)); } } return p; } #define MTK_SIP_VCOREFS_GET_VCORE_INFO 18 static int dvfsrc_dvfs_get_vcore_info_data(u32 idx) { struct arm_smccc_res ares; arm_smccc_smc(MTK_SIP_VCOREFS_CONTROL, MTK_SIP_VCOREFS_GET_VCORE_INFO, idx, 0, 0, 0, 0, 0, &ares); if (!ares.a0) return ares.a1; return 0; } static char *dvfsrc_dump_mt6873_vmode_info(struct mtk_dvfsrc *dvfsrc, char *p, u32 size) { char *buff_end = p + size; int max_info = 3; int i; for (i = 0; i < max_info; i++) p += snprintf(p, buff_end - p, "VBINFO_%d: %08x\n", i, dvfsrc_dvfs_get_vcore_info_data(i)); p += snprintf(p, buff_end - p, "%s: 0x%08x\n", "V_MODE", dvfsrc_read(dvfsrc, DVFSRC_RSRV_4, 0)); return p; } static int dvfsrc_query_request_status(struct mtk_dvfsrc *dvfsrc, u32 id) { int ret = 0; switch (id) { case DVFSRC_MD_RISING_DDR_REQ: ret = dvfsrc_get_md_rising_ddr_gear(dvfsrc); break; case DVFSRC_MD_HRT_BW: ret = dvfsrc_get_md_bw(dvfsrc); break; case DVFSRC_HIFI_VCORE_REQ: ret = dvfsrc_get_hifi_vcore_gear(dvfsrc); break; case DVFSRC_HIFI_DDR_REQ: ret = dvfsrc_get_hifi_ddr_gear(dvfsrc); break; case DVFSRC_HIFI_RISING_DDR_REQ: ret = dvfsrc_get_hifi_rising_ddr_gear(dvfsrc); break; case DVFSRC_HRT_BW_DDR_REQ: ret = dvfsrc_get_hrt_bw_ddr_gear(dvfsrc); break; case DVFSRC_MD_SCEN_DDR_REQ: ret = dvfsrc_get_md_scen_ddr_gear(dvfsrc); break; case DVFSRC_MD_IMP_DDR_REQ: ret = dvfsrc_get_md_imp_ddr(dvfsrc); break; } return ret; } static u64 dvfsrc_query_dvfs_time(struct mtk_dvfsrc *dvfsrc) { u32 last, offset; u64 time_1, time_2; u64 dvfs_time_us; last = dvfsrc_read(dvfsrc, DVFSRC_LAST, 0); offset = last * 0x20; time_1 = dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x4); time_1 = time_1 << 32; time_1 = dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x0) + time_1; last = (last + 7) % 8; offset = last * 0x20; time_2 = dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x4); time_2 = time_2 << 32; time_2 = dvfsrc_read(dvfsrc, DVFSRC_RECORD_0, offset + 0x0) + time_2; dvfs_time_us = (time_1 - time_2) / 13; return dvfs_time_us; } const struct dvfsrc_config mt6779_dvfsrc_config = { .ip_verion = 0, /*mt6779 series*/ .regs = mt6779_regs, .dump_record = dvfsrc_dump_record, .dump_reg = dvfsrc_dump_reg, .query_request = dvfsrc_query_request_status, }; const struct dvfsrc_config mt6873_dvfsrc_config = { .ip_verion = 2, /*mt6873 series*/ .regs = mt6873_regs, .spm_regs = mt6873_spm_regs, .dump_record = dvfsrc_dump_record, .dump_reg = dvfsrc_dump_reg, .dump_spm_info = dvfsrc_dump_mt6873_spm_info, .dump_vmode_info = dvfsrc_dump_mt6873_vmode_info, .query_request = dvfsrc_query_request_status, .query_dvfs_time = dvfsrc_query_dvfs_time, }; const struct dvfsrc_config mt6893_dvfsrc_config = { .ip_verion = 2, /*mt6873 series*/ .regs = mt6873_regs, .spm_regs = mt6893_spm_regs, .dump_record = dvfsrc_dump_record, .dump_reg = dvfsrc_dump_reg, .dump_spm_info = dvfsrc_dump_mt6873_spm_info, .dump_vmode_info = dvfsrc_dump_mt6873_vmode_info, .query_request = dvfsrc_query_request_status, .query_dvfs_time = dvfsrc_query_dvfs_time, }; const struct dvfsrc_config mt6877_dvfsrc_config = { .ip_verion = 2, /*mt6873 series*/ .regs = mt6873_regs, .spm_regs = mt6877_spm_regs, .dump_record = dvfsrc_dump_record, .dump_reg = dvfsrc_dump_reg, .dump_spm_info = dvfsrc_dump_mt6873_spm_info, .dump_vmode_info = dvfsrc_dump_mt6873_vmode_info, .query_request = dvfsrc_query_request_status, .query_dvfs_time = dvfsrc_query_dvfs_time, }; const struct dvfsrc_config mt6983_dvfsrc_config = { .ip_verion = 3, /*mt6983 series*/ .regs = mt6983_regs, .spm_regs = mt6877_spm_regs, .dump_record = dvfsrc_dump_record, .dump_reg = dvfsrc_dump_reg, .dump_spm_info = dvfsrc_dump_mt6873_spm_info, .dump_vmode_info = dvfsrc_dump_mt6873_vmode_info, .query_request = dvfsrc_query_request_status, .query_dvfs_time = dvfsrc_query_dvfs_time, .dump_spm_cmd = dvfsrc_dump_mt6983_spm_cmd, .dump_spm_timer_latch = dvfsrc_dump_mt6983_spm_timer_latch, };