/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (c) 2019 MediaTek Inc. */ #include #ifdef CONFIG_MEDIATEK_DRAMC #include #endif #ifdef CONFIG_MTK_DRAMC #include #endif #ifdef CONFIG_MTK_EMI #include #endif #include #include "helio-dvfsrc-ip-v2.h" #include #include #include #include #include "mmdvfs_pmqos.h" #include #include #include #include #ifdef CONFIG_MTK_WATCHDOG #include #endif #define dvfsrc_rmw(offset, val, mask, shift) \ dvfsrc_write(offset, (dvfsrc_read(offset) & ~(mask << shift)) \ | (val << shift)) #define DVFSRC_1600_FLOOR #if defined(CONFIG_MTK_DVFSRC_MT6781_PRETEST) static struct reg_config dvfsrc_init_configs[][128] = { { { DVFSRC_TIMEOUT_NEXTREQ, 0x0000002B }, { DVFSRC_INT_EN, 0x00000002 }, { DVFSRC_QOS_EN, 0x0000407C }, { DVFSRC_VCORE_REQUEST4, 0x21110000 }, #ifdef DVFSRC_1600_FLOOR { DVFSRC_DDR_REQUEST, 0x00004322 }, #else { DVFSRC_DDR_REQUEST, 0x00004321 }, #endif { DVFSRC_DDR_REQUEST3, 0x00000055 }, #ifdef DVFSRC_1600_FLOOR { DVFSRC_DDR_REQUEST5, 0x00322000 }, #else { DVFSRC_DDR_REQUEST5, 0x00321000 }, #endif { DVFSRC_DDR_REQUEST7, 0x54000000 }, { DVFSRC_DDR_REQUEST8, 0x55000000 }, { DVFSRC_DDR_QOS0, 0x00000019 }, { DVFSRC_DDR_QOS1, 0x00000026 }, { DVFSRC_DDR_QOS2, 0x00000033 }, { DVFSRC_DDR_QOS3, 0x0000004C }, { DVFSRC_DDR_QOS4, 0x00000066 }, { DVFSRC_DDR_QOS5, 0x00000077 }, { DVFSRC_DDR_QOS6, 0x00000077 }, { DVFSRC_95MD_SCEN_BW0_T, 0x22222220 }, { DVFSRC_95MD_SCEN_BW1_T, 0x22222222 }, { DVFSRC_95MD_SCEN_BW2_T, 0x22222222 }, { DVFSRC_95MD_SCEN_BW3_T, 0x52222222 }, { DVFSRC_95MD_SCEN_BW4, 0x00000005 }, { DVFSRC_HRT_REQ_UNIT, 0x0000011E }, { DVSFRC_HRT_REQ_MD_URG, 0x0000D3D3 }, { DVFSRC_HRT_REQ_MD_BW_0, 0x00200802 }, { DVFSRC_HRT_REQ_MD_BW_1, 0x00200800 }, { DVFSRC_HRT_REQ_MD_BW_2, 0x00200002 }, { DVFSRC_HRT_REQ_MD_BW_3, 0x00200802 }, { DVFSRC_HRT_REQ_MD_BW_4, 0x00400802 }, { DVFSRC_HRT_REQ_MD_BW_5, 0x00601404 }, { DVFSRC_HRT_REQ_MD_BW_6, 0x00902008 }, { DVFSRC_HRT_REQ_MD_BW_7, 0x00E0380E }, { DVFSRC_HRT_REQ_MD_BW_8, 0x00000000 }, { DVFSRC_HRT_REQ_MD_BW_9, 0x00000000 }, { DVFSRC_HRT_REQ_MD_BW_10, 0x00034C00 }, { DVFSRC_HRT1_REQ_MD_BW_0, 0x0360D836 }, { DVFSRC_HRT1_REQ_MD_BW_1, 0x0360D800 }, { DVFSRC_HRT1_REQ_MD_BW_2, 0x03600036 }, { DVFSRC_HRT1_REQ_MD_BW_3, 0x0360D836 }, { DVFSRC_HRT1_REQ_MD_BW_4, 0x0360D836 }, { DVFSRC_HRT1_REQ_MD_BW_5, 0x0360D836 }, { DVFSRC_HRT1_REQ_MD_BW_6, 0x0360D836 }, { DVFSRC_HRT1_REQ_MD_BW_7, 0x0360D836 }, { DVFSRC_HRT1_REQ_MD_BW_8, 0x00000000 }, { DVFSRC_HRT1_REQ_MD_BW_9, 0x00000000 }, { DVFSRC_HRT1_REQ_MD_BW_10, 0x00034C00 }, { DVFSRC_HRT_HIGH, 0x070804B0 }, { DVFSRC_HRT_HIGH_1, 0x11830B80 }, { DVFSRC_HRT_HIGH_2, 0x18A618A6 }, { DVFSRC_HRT_HIGH_3, 0x000018A6 }, { DVFSRC_HRT_LOW, 0x070704AF }, { DVFSRC_HRT_LOW_1, 0x11820B7F }, { DVFSRC_HRT_LOW_2, 0x18A518A5 }, { DVFSRC_HRT_LOW_3, 0x000018A5 }, #ifdef DVFSRC_1600_FLOOR { DVFSRC_HRT_REQUEST, 0x05554322 }, #else { DVFSRC_HRT_REQUEST, 0x05554321 }, #endif { DVFSRC_EMI_MON_DEBOUNCE_TIME, 0x4C4C0AB0 }, { DVFSRC_DDR_ADD_REQUEST, 0x05543210 }, { DVFSRC_EMI_ADD_REQUEST, 0x03333210 }, { DVFSRC_LEVEL_LABEL_0_1, 0x40225032 }, { DVFSRC_LEVEL_LABEL_2_3, 0x20223012 }, { DVFSRC_LEVEL_LABEL_4_5, 0x40211012 }, { DVFSRC_LEVEL_LABEL_6_7, 0x20213011 }, { DVFSRC_LEVEL_LABEL_8_9, 0x30101011 }, { DVFSRC_LEVEL_LABEL_10_11, 0x10102000 }, { DVFSRC_LEVEL_LABEL_12_13, 0x00000000 }, { DVFSRC_LEVEL_LABEL_14_15, 0x00000000 }, { DVFSRC_CURRENT_FORCE, 0x00000001 }, { DVFSRC_BASIC_CONTROL, 0x7599404B }, { DVFSRC_BASIC_CONTROL, 0x7599014B }, { DVFSRC_CURRENT_FORCE, 0x00000000 }, { -1, 0 }, }, /* NULL */ { { -1, 0 }, }, }; #else static struct reg_config dvfsrc_init_configs[][128] = { { { DVFSRC_HRT_REQ_UNIT, 0x0000001E }, { DVFSRC_DEBOUNCE_TIME, 0x00001965 }, { DVFSRC_TIMEOUT_NEXTREQ, 0x0000002B }, { DVFSRC_VCORE_REQUEST4, 0x21110000 }, { DVFSRC_DDR_QOS0, 0x00000019 }, { DVFSRC_DDR_QOS1, 0x00000026 }, { DVFSRC_DDR_QOS2, 0x00000033 }, { DVFSRC_DDR_QOS3, 0x0000004C }, { DVFSRC_DDR_QOS4, 0x00000066 }, { DVFSRC_DDR_QOS5, 0x00000077 }, { DVFSRC_DDR_QOS6, 0x00000077 }, { DVFSRC_LEVEL_LABEL_0_1, 0x40225032 }, { DVFSRC_LEVEL_LABEL_2_3, 0x20223012 }, { DVFSRC_LEVEL_LABEL_4_5, 0x40211012 }, { DVFSRC_LEVEL_LABEL_6_7, 0x20213011 }, { DVFSRC_LEVEL_LABEL_8_9, 0x30101011 }, { DVFSRC_LEVEL_LABEL_10_11, 0x10102000 }, { DVFSRC_LEVEL_LABEL_12_13, 0x00000000 }, { DVFSRC_LEVEL_LABEL_14_15, 0x00000000 }, { DVFSRC_MD_LATENCY_IMPROVE, 0x00000040 }, { DVFSRC_HRT_BW_BASE, 0x00000004 }, { DVSFRC_HRT_REQ_MD_URG, 0x0000D3D3 }, { DVFSRC_HRT_REQ_MD_BW_0, 0x00501405 }, { DVFSRC_HRT_REQ_MD_BW_1, 0x00501400 }, { DVFSRC_HRT_REQ_MD_BW_2, 0x00500005 }, { DVFSRC_HRT_REQ_MD_BW_3, 0x00601405 }, { DVFSRC_HRT_REQ_MD_BW_4, 0x00B01806 }, { DVFSRC_HRT_REQ_MD_BW_5, 0x00F0300C }, { DVFSRC_HRT_REQ_MD_BW_6, 0x00000014 }, { DVFSRC_HRT_REQ_MD_BW_7, 0x00000000 }, { DVFSRC_HRT_REQ_MD_BW_8, 0x00000000 }, { DVFSRC_HRT_REQ_MD_BW_9, 0x00000000 }, { DVFSRC_HRT_REQ_MD_BW_10, 0x00034C00 }, { DVFSRC_HRT1_REQ_MD_BW_0, 0x03D0F43D }, { DVFSRC_HRT1_REQ_MD_BW_1, 0x03D0F400 }, { DVFSRC_HRT1_REQ_MD_BW_2, 0x03D0003D }, { DVFSRC_HRT1_REQ_MD_BW_3, 0x03D0F43D }, { DVFSRC_HRT1_REQ_MD_BW_4, 0x03D0F43D }, { DVFSRC_HRT1_REQ_MD_BW_5, 0x03D0F43D }, { DVFSRC_HRT1_REQ_MD_BW_6, 0x0000003D }, { DVFSRC_HRT1_REQ_MD_BW_7, 0x00000000 }, { DVFSRC_HRT1_REQ_MD_BW_8, 0x00000000 }, { DVFSRC_HRT1_REQ_MD_BW_9, 0x00000000 }, { DVFSRC_HRT1_REQ_MD_BW_10, 0x00034C00 }, { DVFSRC_95MD_SCEN_BW0_T, 0x22222220 }, { DVFSRC_95MD_SCEN_BW1_T, 0x22222222 }, { DVFSRC_95MD_SCEN_BW2_T, 0x22222222 }, { DVFSRC_95MD_SCEN_BW3_T, 0x52222222 }, { DVFSRC_95MD_SCEN_BW4, 0x00000005 }, { DVFSRC_RSRV_5, 0x00000001 }, #ifdef DVFSRC_1600_FLOOR { DVFSRC_DDR_REQUEST, 0x00000022 }, #else { DVFSRC_DDR_REQUEST, 0x00000021 }, #endif { DVFSRC_DDR_REQUEST3, 0x00654300 }, { DVFSRC_DDR_ADD_REQUEST, 0x66543210 }, #ifdef DVFSRC_1600_FLOOR { DVFSRC_DDR_REQUEST5, 0x54322000 }, #else { DVFSRC_DDR_REQUEST5, 0x54321000 }, #endif { DVFSRC_DDR_REQUEST7, 0x55000000 }, { DVFSRC_EMI_MON_DEBOUNCE_TIME, 0x4C2D0000 }, { DVFSRC_VCORE_USER_REQ, 0x00010A29 }, { DVFSRC_HRT_HIGH, 0x070804B0 }, { DVFSRC_HRT_HIGH_1, 0x11830B80 }, { DVFSRC_HRT_HIGH_2, 0x18A618A6 }, { DVFSRC_HRT_HIGH_3, 0x18A618A6 }, { DVFSRC_HRT_LOW, 0x070704AF }, { DVFSRC_HRT_LOW_1, 0x11820B7F }, { DVFSRC_HRT_LOW_2, 0x18A518A5 }, { DVFSRC_HRT_LOW_3, 0x18A518A5 }, #ifdef DVFSRC_1600_FLOOR { DVFSRC_HRT_REQUEST, 0x55554322 }, #else { DVFSRC_HRT_REQUEST, 0x55554321 }, #endif { DVFSRC_BASIC_CONTROL_3, 0x00000006 }, { DVFSRC_INT_EN, 0x00000002 }, { DVFSRC_QOS_EN, 0x0000407C }, { DVFSRC_CURRENT_FORCE, 0x00000001 }, { DVFSRC_BASIC_CONTROL, 0x6598444B }, { DVFSRC_BASIC_CONTROL, 0x6598054B }, { DVFSRC_CURRENT_FORCE, 0x00000000 }, { -1, 0 }, }, /* NULL */ { { -1, 0 }, }, }; #endif static ssize_t dvfsrc_vcore_settle_time_show(struct device *dev, struct device_attribute *attr, char *buf) { /* DE's comment: settle time was hard code in fw (15,30) */ return sprintf(buf, "rising 15 uS, falling 30 uS for mt6781\n"); } static DEVICE_ATTR(dvfsrc_vcore_settle_time, 0444, dvfsrc_vcore_settle_time_show, NULL); static struct attribute *mt6781_helio_dvfsrc_attrs[] = { &dev_attr_dvfsrc_vcore_settle_time.attr, NULL, }; static struct attribute_group mt6781_helio_dvfsrc_attr_group = { .name = "helio-dvfsrc", .attrs = mt6781_helio_dvfsrc_attrs, }; #define dvfsrc_rmw(offset, val, mask, shift) \ dvfsrc_write(offset, (dvfsrc_read(offset) & ~(mask << shift)) \ | (val << shift)) u32 dvfsrc_get_ddr_qos(void) { unsigned int qos_total_bw = dvfsrc_read(DVFSRC_SW_BW_0) + dvfsrc_read(DVFSRC_SW_BW_1) + dvfsrc_read(DVFSRC_SW_BW_2) + dvfsrc_read(DVFSRC_SW_BW_3) + dvfsrc_read(DVFSRC_SW_BW_4); if (qos_total_bw < 0x19) return 0; #ifdef DVFSRC_1600_FLOOR else if (qos_total_bw < 0x26) return 2; #else else if (qos_total_bw < 0x26) return 1; #endif else if (qos_total_bw < 0x33) return 2; else if (qos_total_bw < 0x4c) return 3; else if (qos_total_bw < 0x66) return 4; else return 5; } static int dvfsrc_get_emi_mon_gear(void) { unsigned int val, total_bw_status; int i; val = vcorefs_get_total_emi_status(); total_bw_status = (val & 0x3) | ((val & 0x3C0) >> 4); for (i = 4; i >= 0 ; i--) { if ((total_bw_status >> i) > 0) { #ifdef DVFSRC_1600_FLOOR if (i == 0) return i + 2; else return i + 1; #else return i + 1; #endif } } return 0; } static u32 dvfsrc_calc_hrt_opp(int data) { if (data < 0x04B0) return DDR_OPP_5; #ifdef DVFSRC_1600_FLOOR else if (data < 0x0708) return DDR_OPP_3; #else else if (data < 0x0708) return DDR_OPP_4; #endif else if (data < 0x0B80) return DDR_OPP_3; else if (data < 0x1183) return DDR_OPP_2; else if (data < 0x18A6) return DDR_OPP_1; else return DDR_OPP_0; } void dvfsrc_set_isp_hrt_bw(int data) { data = (data + 29) / 30; if (data > 0x3FF) data = 0x3FF; dvfsrc_write(DVFSRC_ISP_HRT, data); } u32 dvfsrc_calc_isp_hrt_opp(int data) { return dvfsrc_calc_hrt_opp(((data + 29) / 30) * 30); } struct regulator *dvfsrc_vcore_requlator(struct device *dev) { return regulator_get(dev, "vcore"); } #ifdef AUTOK_ENABLE __weak int emmc_autok(void) { pr_info("NOT SUPPORT EMMC AUTOK\n"); return 0; } __weak int sd_autok(void) { pr_info("NOT SUPPORT SD AUTOK\n"); return 0; } __weak int sdio_autok(void) { pr_info("NOT SUPPORT SDIO AUTOK\n"); return 0; } void begin_autok_task(void) { /* notify MM DVFS for msdc autok start */ mmdvfs_prepare_action(MMDVFS_PREPARE_CALIBRATION_START); } void finish_autok_task(void) { /* check if dvfs force is released */ int force = mtk_pm_qos_request(MTK_PM_QOS_VCORE_DVFS_FORCE_OPP); /* notify MM DVFS for msdc autok finish */ mmdvfs_prepare_action(MMDVFS_PREPARE_CALIBRATION_END); if (force >= 0 && force < VCORE_DVFS_OPP_NUM) pr_info("autok task not release force opp: %d\n", force); } static void dvfsrc_autok_manager(void) { int r = 0; begin_autok_task(); r = emmc_autok(); pr_info("EMMC autok done: %s\n", (r == 0) ? "Yes" : "No"); r = sd_autok(); pr_info("SD autok done: %s\n", (r == 0) ? "Yes" : "No"); r = sdio_autok(); pr_info("SDIO autok done: %s\n", (r == 0) ? "Yes" : "No"); finish_autok_task(); } #endif void helio_dvfsrc_platform_pre_init(struct helio_dvfsrc *dvfsrc) { #if !defined(CONFIG_MTK_DVFSRC_MT6781_PRETEST) struct platform_device *pdev = to_platform_device(dvfsrc->dev); struct resource *res; res = platform_get_resource(pdev, IORESOURCE_MEM, 1); dvfsrc->spm_regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (IS_ERR(dvfsrc->spm_regs)) pr_info("not get spm register\n"); #endif } __weak void mtk_pm_qos_trace_dbg_dump(int mtk_pm_qos_class) { } void dvfsrc_suspend_cb(struct helio_dvfsrc *dvfsrc) { int sw_req; sw_req = dvfsrc_read(DVFSRC_SW_REQ3); pr_info("[DVFSRC] V:%d, F_OPP:%d, RG:%08x, %08x, %08x, %08x\n", get_cur_vcore_uv(), mtk_pm_qos_request(MTK_PM_QOS_VCORE_DVFS_FORCE_OPP), dvfsrc_read(DVFSRC_CURRENT_LEVEL), dvfsrc_read(DVFSRC_SW_REQ2), sw_req, dvfsrc_read(DVFSRC_DEBUG_STA_0)); if (sw_req & (DDR_SW_AP_MASK << DDR_SW_AP_SHIFT)) mtk_pm_qos_trace_dbg_dump(MTK_PM_QOS_DDR_OPP); if (sw_req & (VCORE_SW_AP_MASK << VCORE_SW_AP_SHIFT)) mtk_pm_qos_trace_dbg_dump(MTK_PM_QOS_VCORE_OPP); } void dvfsrc_resume_cb(struct helio_dvfsrc *dvfsrc) { } void helio_dvfsrc_platform_init(struct helio_dvfsrc *dvfsrc) { int spmfw_idx = 0; struct reg_config *config; int idx = 0; sysfs_merge_group(&dvfsrc->dev->kobj, &mt6781_helio_dvfsrc_attr_group); config = dvfsrc_init_configs[spmfw_idx]; while (config[idx].offset != -1) { dvfsrc_write(config[idx].offset, config[idx].val); idx++; } #ifdef AUTOK_ENABLE dvfsrc_autok_manager(); #endif } int vcore_pmic_to_uv(int pmic_val) { return __vcore_pmic_to_uv(pmic_val); } int vcore_uv_to_pmic(int vcore_uv) { return __vcore_uv_to_pmic(vcore_uv); } #if !defined(CONFIG_MTK_DVFSRC_MT6781_PRETEST) void get_spm_reg(char *p) { p += sprintf(p, "%-24s: 0x%08x\n", "POWERON_CONFIG_EN", spm_reg_read(POWERON_CONFIG_EN)); p += sprintf(p, "%-24s: 0x%08x\n", "SPM_SW_FLAG_0", spm_reg_read(SPM_SW_FLAG_0)); p += sprintf(p, "%-24s: 0x%08x\n", "SPM_PC_STA", spm_reg_read(SPM_PC_STA)); p += sprintf(p, "%-24s: 0x%08x\n", "SPM_DVFS_LEVEL", spm_reg_read(SPM_DVFS_LEVEL)); p += sprintf(p, "%-24s: 0x%08x\n", "SPM_DVS_DFS_LEVEL", spm_reg_read(SPM_DVS_DFS_LEVEL)); p += sprintf(p, "%-24s: 0x%08x\n", "SPM_DVFS_STA", spm_reg_read(SPM_DVFS_STA)); p += sprintf(p, "%-24s: 0x%08x\n", "SPM_DVFS_MISC", spm_reg_read(SPM_DVFS_MISC)); p += sprintf(p, "%-24s: 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", "SPM_DVFS_CMD0~4", spm_reg_read(SPM_DVFS_CMD0), spm_reg_read(SPM_DVFS_CMD1), spm_reg_read(SPM_DVFS_CMD2), spm_reg_read(SPM_DVFS_CMD3), spm_reg_read(SPM_DVFS_CMD4)); p += sprintf(p, "%-24s: 0x%08x, 0x%08x\n", "SPM_DVFS_CMD7~8", spm_reg_read(SPM_DVFS_CMD7), spm_reg_read(SPM_DVFS_CMD8)); } #endif void get_opp_info(char *p) { #if defined(CONFIG_FPGA_EARLY_PORTING) || !defined(CONFIG_MTK_PMIC_COMMON) \ || !defined(CONFIG_MTK_PMIC_NEW_ARCH) int pmic_val = 0; int vsram_val = 0; #else int pmic_val = pmic_get_register_value(PMIC_VCORE_ADDR); int vsram_val = pmic_get_register_value(PMIC_VSRAM_OTHERS_ADDR); #endif #if defined(CONFIG_MTK_DRAMC) int ddr_khz = get_dram_data_rate() * 1000; #elif defined(CONFIG_MEDIATEK_DRAMC) int ddr_khz = mtk_dramc_get_data_rate() * 1000; #else int ddr_khz = 0; #endif int vcore_uv = vcore_pmic_to_uv(pmic_val); int vsram_uv = vsram_pmic_to_uv(vsram_val); p += sprintf(p, "%-10s: %-8u uv (PMIC: 0x%x)\n", "Vcore", vcore_uv, vcore_uv_to_pmic(vcore_uv)); p += sprintf(p, "%-10s: %-8u uv (PMIC: 0x%x)\n", "Vsram", vsram_uv, vsram_uv_to_pmic(vsram_uv)); p += sprintf(p, "%-10s: %-8u khz\n", "DDR", ddr_khz); } /* met profile table */ static unsigned int met_vcorefs_src[SRC_MAX]; static char *met_src_name[SRC_MAX] = { "MD2SPM", "SRC_DDR_OPP", "DDR__SW_REQ1_SPM", "DDR__SW_REQ2_CM", "DDR__SW_REQ3_PMQOS", #if defined(CONFIG_MTK_DVFSRC_MT6781_PRETEST) "DDR__SW_REQ4_MD", "DDR__SW_REQ8_MCUSYS", #endif "DDR__QOS_BW", "DDR__EMI_TOTAL", "DDR__HRT_BW", "DDR__HIFI", "DDR__HIFI_LATENCY", "DDR__MD_LATENCY", "DDR__MD_DDR", "DDR__MD_LEVEL_MASK", "SRC_VCORE_OPP", "VCORE__SW_REQ3_PMQOS", "VCORE__SCP", "VCORE__HIFI", "SCP_REQ", "PMQOS_TATOL", "PMQOS_BW0", "PMQOS_BW1", "PMQOS_BW2", "PMQOS_BW3", "PMQOS_BW4", "TOTAL_EMI_BW", "HRT_MD_BW", "HRT_DISP_BW", "HRT_ISP_BW", "MD_SCENARIO", "HIFI_SCENARIO_IDX", "MD_EMI_LATENCY", }; /* met profile function */ int vcorefs_get_src_req_num(void) { return SRC_MAX; } EXPORT_SYMBOL(vcorefs_get_src_req_num); char **vcorefs_get_src_req_name(void) { return met_src_name; } EXPORT_SYMBOL(vcorefs_get_src_req_name); static u32 vcorefs_get_md_level_mask_ddr(void) { #if !defined(CONFIG_MTK_DVFSRC_MT6781_PRETEST) int md_srclk, vopp; if (dvfsrc_read(DVFSRC_BASIC_CONTROL_3) & 0x8) { md_srclk = dvfsrc_read(DVFSRC_DEBUG_STA_0); vopp = get_cur_vcore_opp(); md_srclk = (md_srclk >> MD_SRC_CLK_DEBUG_SHIFT) & MD_SRC_CLK_DEBUG_MASK; if (vopp != 3 && md_srclk == 1) return 2; } #endif return 0; } static void vcorefs_get_src_ddr_req(void) { unsigned int sw_req; met_vcorefs_src[DDR_OPP_IDX] = get_cur_ddr_opp(); sw_req = dvfsrc_read(DVFSRC_SW_REQ1); met_vcorefs_src[DDR_SW_REQ1_SPM_IDX] = (sw_req >> DDR_SW_AP_SHIFT) & DDR_SW_AP_MASK; sw_req = dvfsrc_read(DVFSRC_SW_REQ2); met_vcorefs_src[DDR_SW_REQ2_CM_IDX] = (sw_req >> DDR_SW_AP_SHIFT) & DDR_SW_AP_MASK; sw_req = dvfsrc_read(DVFSRC_SW_REQ3); met_vcorefs_src[DDR_SW_REQ3_PMQOS_IDX] = (sw_req >> DDR_SW_AP_SHIFT) & DDR_SW_AP_MASK; #if defined(CONFIG_MTK_DVFSRC_MT6781_PRETEST) sw_req = dvfsrc_read(DVFSRC_SW_REQ4); met_vcorefs_src[DDR_SW_REQ4_MD_IDX] = (sw_req >> DDR_SW_AP_SHIFT) & DDR_SW_AP_MASK; sw_req = dvfsrc_read(DVFSRC_SW_REQ8); met_vcorefs_src[DDR_SW_REQ8_MCUSYS_IDX] = (sw_req >> DDR_SW_AP_SHIFT) & DDR_SW_AP_MASK; #endif met_vcorefs_src[DDR_QOS_BW_IDX] = dvfsrc_get_ddr_qos(); met_vcorefs_src[DDR_EMI_TOTAL_IDX] = dvfsrc_get_emi_mon_gear(); met_vcorefs_src[DDR_HRT_BW_IDX] = vcorefs_get_hrt_bw_ddr(); met_vcorefs_src[DDR_HIFI_IDX] = vcorefs_get_hifi_ddr_status(); met_vcorefs_src[DDR_HIFI_LATENCY_IDX] = vcorefs_get_hifi_rising_ddr(); #if defined(CONFIG_MTK_DVFSRC_MT6781_PRETEST) met_vcorefs_src[DDR_MD_LATENCY_IDX] = vcorefs_get_md_rising_ddr(); #else met_vcorefs_src[DDR_MD_LATENCY_IDX] = vcorefs_get_md_imp_ddr(); #endif met_vcorefs_src[DDR_MD_DDR_IDX] = vcorefs_get_md_scenario_ddr(); met_vcorefs_src[DDR_MD_SRCLK_IDX] = vcorefs_get_md_level_mask_ddr(); } static void vcorefs_get_src_vcore_req(void) { u32 sw_req; u32 scp_en; scp_en = vcorefs_get_scp_req_status(); met_vcorefs_src[VCORE_OPP_IDX] = get_cur_vcore_opp(); sw_req = dvfsrc_read(DVFSRC_SW_REQ3); met_vcorefs_src[VCORE_SW_REQ3_PMQOS_IDX] = (sw_req >> VCORE_SW_AP_SHIFT) & VCORE_SW_AP_MASK; if (scp_en) { sw_req = dvfsrc_read(DVFSRC_VCORE_REQUEST); met_vcorefs_src[VCORE_SCP_IDX] = (sw_req >> VCORE_SCP_GEAR_SHIFT) & VCORE_SCP_GEAR_MASK; } else met_vcorefs_src[VCORE_SCP_IDX] = 0; met_vcorefs_src[VCORE_HIFI_IDX] = vcorefs_get_hifi_vcore_status(); } static void vcorefs_get_src_misc_info(void) { u32 qos_bw0, qos_bw1, qos_bw2, qos_bw3, qos_bw4; #if defined(CONFIG_MTK_DVFSRC_MT6781_PRETEST) #ifdef CONFIG_MTK_EMI unsigned int total_bw_last = (get_emi_bwvl(0) & 0x7F) * 813; met_vcorefs_src[SRC_TOTAL_EMI_BW_IDX] = total_bw_last; met_vcorefs_src[SRC_MD2SPM_IDX] = vcorefs_get_md_scenario(); #endif #else met_vcorefs_src[SRC_MD2SPM_IDX] = vcorefs_get_md_scenario() & 0x1FFFF; #endif qos_bw0 = dvfsrc_read(DVFSRC_SW_BW_0); qos_bw1 = dvfsrc_read(DVFSRC_SW_BW_1); qos_bw2 = dvfsrc_read(DVFSRC_SW_BW_2); qos_bw3 = dvfsrc_read(DVFSRC_SW_BW_3); qos_bw4 = dvfsrc_read(DVFSRC_SW_BW_4); met_vcorefs_src[SRC_SCP_REQ_IDX] = vcorefs_get_scp_req_status(); met_vcorefs_src[SRC_PMQOS_TATOL_IDX] = qos_bw0 + qos_bw1 + qos_bw2 + qos_bw3 + qos_bw4; met_vcorefs_src[SRC_PMQOS_BW0_IDX] = qos_bw0; met_vcorefs_src[SRC_PMQOS_BW1_IDX] = qos_bw1; met_vcorefs_src[SRC_PMQOS_BW2_IDX] = qos_bw2; met_vcorefs_src[SRC_PMQOS_BW3_IDX] = qos_bw3; met_vcorefs_src[SRC_PMQOS_BW4_IDX] = qos_bw4; met_vcorefs_src[SRC_HRT_MD_BW_IDX] = dvfsrc_get_md_bw(); met_vcorefs_src[SRC_HRT_ISP_BW_IDX] = dvfsrc_read(DVFSRC_ISP_HRT); met_vcorefs_src[SRC_MD_SCENARIO_IDX] = vcorefs_get_md_scenario(); met_vcorefs_src[SRC_HIFI_SCENARIO_IDX] = vcorefs_get_hifi_scenario(); met_vcorefs_src[SRC_MD_EMI_LATENCY_IDX] = vcorefs_get_md_emi_latency_status(); } int dvfsrc_latch_register(int enable) { #ifdef CONFIG_MTK_WATCHDOG return mtk_rgu_cfg_dvfsrc(enable); #endif return 0; } unsigned int *vcorefs_get_src_req(void) { vcorefs_get_src_ddr_req(); vcorefs_get_src_vcore_req(); vcorefs_get_src_misc_info(); vcorefs_trace_qos(); return met_vcorefs_src; } EXPORT_SYMBOL(vcorefs_get_src_req); int get_cur_ddr_ratio(void) { int idx; if (!is_dvfsrc_enabled()) return 0; idx = get_cur_vcore_dvfs_opp(); if (idx >= VCORE_DVFS_OPP_NUM) return 0; if ((get_ddr_opp(idx) < DDR_OPP_3) || (idx == 10)) return 8; else return 4; } EXPORT_SYMBOL(get_cur_ddr_ratio);