11738061cSShyam Sundar S K // SPDX-License-Identifier: GPL-2.0 21738061cSShyam Sundar S K /* 31738061cSShyam Sundar S K * AMD Platform Management Framework Driver 41738061cSShyam Sundar S K * 51738061cSShyam Sundar S K * Copyright (c) 2022, Advanced Micro Devices, Inc. 61738061cSShyam Sundar S K * All Rights Reserved. 71738061cSShyam Sundar S K * 81738061cSShyam Sundar S K * Author: Shyam Sundar S K <Shyam-sundar.S-k@amd.com> 91738061cSShyam Sundar S K */ 101738061cSShyam Sundar S K 111738061cSShyam Sundar S K #include <linux/workqueue.h> 121738061cSShyam Sundar S K #include "pmf.h" 131738061cSShyam Sundar S K 141738061cSShyam Sundar S K static struct cnqf_config config_store; 151738061cSShyam Sundar S K 16*a82ebb3dSShyam Sundar S K #ifdef CONFIG_AMD_PMF_DEBUG 17*a82ebb3dSShyam Sundar S K static const char *state_as_str_cnqf(unsigned int state) 18*a82ebb3dSShyam Sundar S K { 19*a82ebb3dSShyam Sundar S K switch (state) { 20*a82ebb3dSShyam Sundar S K case APMF_CNQF_TURBO: 21*a82ebb3dSShyam Sundar S K return "turbo"; 22*a82ebb3dSShyam Sundar S K case APMF_CNQF_PERFORMANCE: 23*a82ebb3dSShyam Sundar S K return "performance"; 24*a82ebb3dSShyam Sundar S K case APMF_CNQF_BALANCE: 25*a82ebb3dSShyam Sundar S K return "balance"; 26*a82ebb3dSShyam Sundar S K case APMF_CNQF_QUIET: 27*a82ebb3dSShyam Sundar S K return "quiet"; 28*a82ebb3dSShyam Sundar S K default: 29*a82ebb3dSShyam Sundar S K return "Unknown CnQF State"; 30*a82ebb3dSShyam Sundar S K } 31*a82ebb3dSShyam Sundar S K } 32*a82ebb3dSShyam Sundar S K 33*a82ebb3dSShyam Sundar S K static void amd_pmf_cnqf_dump_defaults(struct apmf_dyn_slider_output *data, int idx) 34*a82ebb3dSShyam Sundar S K { 35*a82ebb3dSShyam Sundar S K int i; 36*a82ebb3dSShyam Sundar S K 37*a82ebb3dSShyam Sundar S K pr_debug("Dynamic Slider %s Defaults - BEGIN\n", idx ? "DC" : "AC"); 38*a82ebb3dSShyam Sundar S K pr_debug("size: %u\n", data->size); 39*a82ebb3dSShyam Sundar S K pr_debug("flags: 0x%x\n", data->flags); 40*a82ebb3dSShyam Sundar S K 41*a82ebb3dSShyam Sundar S K /* Time constants */ 42*a82ebb3dSShyam Sundar S K pr_debug("t_perf_to_turbo: %u ms\n", data->t_perf_to_turbo); 43*a82ebb3dSShyam Sundar S K pr_debug("t_balanced_to_perf: %u ms\n", data->t_balanced_to_perf); 44*a82ebb3dSShyam Sundar S K pr_debug("t_quiet_to_balanced: %u ms\n", data->t_quiet_to_balanced); 45*a82ebb3dSShyam Sundar S K pr_debug("t_balanced_to_quiet: %u ms\n", data->t_balanced_to_quiet); 46*a82ebb3dSShyam Sundar S K pr_debug("t_perf_to_balanced: %u ms\n", data->t_perf_to_balanced); 47*a82ebb3dSShyam Sundar S K pr_debug("t_turbo_to_perf: %u ms\n", data->t_turbo_to_perf); 48*a82ebb3dSShyam Sundar S K 49*a82ebb3dSShyam Sundar S K for (i = 0 ; i < CNQF_MODE_MAX ; i++) { 50*a82ebb3dSShyam Sundar S K pr_debug("pfloor_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].pfloor); 51*a82ebb3dSShyam Sundar S K pr_debug("fppt_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].fppt); 52*a82ebb3dSShyam Sundar S K pr_debug("sppt_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].sppt); 53*a82ebb3dSShyam Sundar S K pr_debug("sppt_apuonly_%s: %u mW\n", 54*a82ebb3dSShyam Sundar S K state_as_str_cnqf(i), data->ps[i].sppt_apu_only); 55*a82ebb3dSShyam Sundar S K pr_debug("spl_%s: %u mW\n", state_as_str_cnqf(i), data->ps[i].spl); 56*a82ebb3dSShyam Sundar S K pr_debug("stt_minlimit_%s: %u mW\n", 57*a82ebb3dSShyam Sundar S K state_as_str_cnqf(i), data->ps[i].stt_min_limit); 58*a82ebb3dSShyam Sundar S K pr_debug("stt_skintemp_apu_%s: %u C\n", state_as_str_cnqf(i), 59*a82ebb3dSShyam Sundar S K data->ps[i].stt_skintemp[STT_TEMP_APU]); 60*a82ebb3dSShyam Sundar S K pr_debug("stt_skintemp_hs2_%s: %u C\n", state_as_str_cnqf(i), 61*a82ebb3dSShyam Sundar S K data->ps[i].stt_skintemp[STT_TEMP_HS2]); 62*a82ebb3dSShyam Sundar S K pr_debug("fan_id_%s: %u\n", state_as_str_cnqf(i), data->ps[i].fan_id); 63*a82ebb3dSShyam Sundar S K } 64*a82ebb3dSShyam Sundar S K 65*a82ebb3dSShyam Sundar S K pr_debug("Dynamic Slider %s Defaults - END\n", idx ? "DC" : "AC"); 66*a82ebb3dSShyam Sundar S K } 67*a82ebb3dSShyam Sundar S K #else 68*a82ebb3dSShyam Sundar S K static void amd_pmf_cnqf_dump_defaults(struct apmf_dyn_slider_output *data, int idx) {} 69*a82ebb3dSShyam Sundar S K #endif 70*a82ebb3dSShyam Sundar S K 711738061cSShyam Sundar S K static int amd_pmf_set_cnqf(struct amd_pmf_dev *dev, int src, int idx, 721738061cSShyam Sundar S K struct cnqf_config *table) 731738061cSShyam Sundar S K { 741738061cSShyam Sundar S K struct power_table_control *pc; 751738061cSShyam Sundar S K 761738061cSShyam Sundar S K pc = &config_store.mode_set[src][idx].power_control; 771738061cSShyam Sundar S K 781738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_SPL, false, pc->spl, NULL); 791738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_FPPT, false, pc->fppt, NULL); 801738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_SPPT, false, pc->sppt, NULL); 811738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pc->sppt_apu_only, NULL); 821738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pc->stt_min, NULL); 831738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, pc->stt_skin_temp[STT_TEMP_APU], 841738061cSShyam Sundar S K NULL); 851738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, pc->stt_skin_temp[STT_TEMP_HS2], 861738061cSShyam Sundar S K NULL); 871738061cSShyam Sundar S K 881738061cSShyam Sundar S K if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX)) 891738061cSShyam Sundar S K apmf_update_fan_idx(dev, 901738061cSShyam Sundar S K config_store.mode_set[src][idx].fan_control.manual, 911738061cSShyam Sundar S K config_store.mode_set[src][idx].fan_control.fan_id); 921738061cSShyam Sundar S K 931738061cSShyam Sundar S K return 0; 941738061cSShyam Sundar S K } 951738061cSShyam Sundar S K 961738061cSShyam Sundar S K static void amd_pmf_update_power_threshold(int src) 971738061cSShyam Sundar S K { 981738061cSShyam Sundar S K struct cnqf_mode_settings *ts; 991738061cSShyam Sundar S K struct cnqf_tran_params *tp; 1001738061cSShyam Sundar S K 1011738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_TO_QUIET]; 1021738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_BALANCE]; 1039732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 1041738061cSShyam Sundar S K 1051738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_TO_TURBO]; 1061738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_PERFORMANCE]; 1079732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 1081738061cSShyam Sundar S K 1091738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_BALANCE_TO_PERFORMANCE]; 1101738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_BALANCE]; 1119732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 1121738061cSShyam Sundar S K 1131738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]; 1141738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_PERFORMANCE]; 1159732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 1161738061cSShyam Sundar S K 1171738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_QUIET_TO_BALANCE]; 1181738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_QUIET]; 1199732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 1201738061cSShyam Sundar S K 1211738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_TURBO_TO_PERFORMANCE]; 1221738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_TURBO]; 1239732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 1241738061cSShyam Sundar S K } 1251738061cSShyam Sundar S K 1261738061cSShyam Sundar S K static const char *state_as_str(unsigned int state) 1271738061cSShyam Sundar S K { 1281738061cSShyam Sundar S K switch (state) { 1291738061cSShyam Sundar S K case CNQF_MODE_QUIET: 1301738061cSShyam Sundar S K return "QUIET"; 1311738061cSShyam Sundar S K case CNQF_MODE_BALANCE: 1321738061cSShyam Sundar S K return "BALANCED"; 1331738061cSShyam Sundar S K case CNQF_MODE_TURBO: 1341738061cSShyam Sundar S K return "TURBO"; 1351738061cSShyam Sundar S K case CNQF_MODE_PERFORMANCE: 1361738061cSShyam Sundar S K return "PERFORMANCE"; 1371738061cSShyam Sundar S K default: 1381738061cSShyam Sundar S K return "Unknown CnQF mode"; 1391738061cSShyam Sundar S K } 1401738061cSShyam Sundar S K } 1411738061cSShyam Sundar S K 1421738061cSShyam Sundar S K static int amd_pmf_cnqf_get_power_source(struct amd_pmf_dev *dev) 1431738061cSShyam Sundar S K { 1441738061cSShyam Sundar S K if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) && 1451738061cSShyam Sundar S K is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 1461738061cSShyam Sundar S K return amd_pmf_get_power_source(); 1471738061cSShyam Sundar S K else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 1481738061cSShyam Sundar S K return POWER_SOURCE_DC; 1491738061cSShyam Sundar S K else 1501738061cSShyam Sundar S K return POWER_SOURCE_AC; 1511738061cSShyam Sundar S K } 1521738061cSShyam Sundar S K 1531738061cSShyam Sundar S K int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms) 1541738061cSShyam Sundar S K { 1551738061cSShyam Sundar S K struct cnqf_tran_params *tp; 1561738061cSShyam Sundar S K int src, i, j; 1571738061cSShyam Sundar S K u32 avg_power = 0; 1581738061cSShyam Sundar S K 1591738061cSShyam Sundar S K src = amd_pmf_cnqf_get_power_source(dev); 1601738061cSShyam Sundar S K 16116909aa8SShyam Sundar S K if (is_pprof_balanced(dev)) { 1621738061cSShyam Sundar S K amd_pmf_set_cnqf(dev, src, config_store.current_mode, NULL); 1631738061cSShyam Sundar S K } else { 1641738061cSShyam Sundar S K /* 1651738061cSShyam Sundar S K * Return from here if the platform_profile is not balanced 1661738061cSShyam Sundar S K * so that preference is given to user mode selection, rather 1671738061cSShyam Sundar S K * than enforcing CnQF to run all the time (if enabled) 1681738061cSShyam Sundar S K */ 1691738061cSShyam Sundar S K return -EINVAL; 1701738061cSShyam Sundar S K } 1711738061cSShyam Sundar S K 1721738061cSShyam Sundar S K for (i = 0; i < CNQF_TRANSITION_MAX; i++) { 1731738061cSShyam Sundar S K config_store.trans_param[src][i].timer += time_lapsed_ms; 1741738061cSShyam Sundar S K config_store.trans_param[src][i].total_power += socket_power; 1751738061cSShyam Sundar S K config_store.trans_param[src][i].count++; 1761738061cSShyam Sundar S K 1771738061cSShyam Sundar S K tp = &config_store.trans_param[src][i]; 1781738061cSShyam Sundar S K if (tp->timer >= tp->time_constant && tp->count) { 1791738061cSShyam Sundar S K avg_power = tp->total_power / tp->count; 1801738061cSShyam Sundar S K 1811738061cSShyam Sundar S K /* Reset the indices */ 1821738061cSShyam Sundar S K tp->timer = 0; 1831738061cSShyam Sundar S K tp->total_power = 0; 1841738061cSShyam Sundar S K tp->count = 0; 1851738061cSShyam Sundar S K 1861738061cSShyam Sundar S K if ((tp->shifting_up && avg_power >= tp->power_threshold) || 1871738061cSShyam Sundar S K (!tp->shifting_up && avg_power <= tp->power_threshold)) { 1881738061cSShyam Sundar S K tp->priority = true; 1891738061cSShyam Sundar S K } else { 1901738061cSShyam Sundar S K tp->priority = false; 1911738061cSShyam Sundar S K } 1921738061cSShyam Sundar S K } 1931738061cSShyam Sundar S K } 1941738061cSShyam Sundar S K 1951738061cSShyam Sundar S K dev_dbg(dev->dev, "[CNQF] Avg power: %u mW socket power: %u mW mode:%s\n", 1961738061cSShyam Sundar S K avg_power, socket_power, state_as_str(config_store.current_mode)); 1971738061cSShyam Sundar S K 1981738061cSShyam Sundar S K for (j = 0; j < CNQF_TRANSITION_MAX; j++) { 1991738061cSShyam Sundar S K /* apply the highest priority */ 2001738061cSShyam Sundar S K if (config_store.trans_param[src][j].priority) { 2011738061cSShyam Sundar S K if (config_store.current_mode != 2021738061cSShyam Sundar S K config_store.trans_param[src][j].target_mode) { 2031738061cSShyam Sundar S K config_store.current_mode = 2041738061cSShyam Sundar S K config_store.trans_param[src][j].target_mode; 2051738061cSShyam Sundar S K dev_dbg(dev->dev, "Moving to Mode :%s\n", 2061738061cSShyam Sundar S K state_as_str(config_store.current_mode)); 2071738061cSShyam Sundar S K amd_pmf_set_cnqf(dev, src, 2081738061cSShyam Sundar S K config_store.current_mode, NULL); 2091738061cSShyam Sundar S K } 2101738061cSShyam Sundar S K break; 2111738061cSShyam Sundar S K } 2121738061cSShyam Sundar S K } 2131738061cSShyam Sundar S K return 0; 2141738061cSShyam Sundar S K } 2151738061cSShyam Sundar S K 21619c8b524SMuhammad Usama Anjum static void amd_pmf_update_trans_data(int idx, struct apmf_dyn_slider_output *out) 2171738061cSShyam Sundar S K { 2181738061cSShyam Sundar S K struct cnqf_tran_params *tp; 2191738061cSShyam Sundar S K 2201738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_TO_QUIET]; 22119c8b524SMuhammad Usama Anjum tp->time_constant = out->t_balanced_to_quiet; 2221738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_QUIET; 2231738061cSShyam Sundar S K tp->shifting_up = false; 2241738061cSShyam Sundar S K 2251738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_BALANCE_TO_PERFORMANCE]; 22619c8b524SMuhammad Usama Anjum tp->time_constant = out->t_balanced_to_perf; 2271738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_PERFORMANCE; 2281738061cSShyam Sundar S K tp->shifting_up = true; 2291738061cSShyam Sundar S K 2301738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_QUIET_TO_BALANCE]; 23119c8b524SMuhammad Usama Anjum tp->time_constant = out->t_quiet_to_balanced; 2321738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_BALANCE; 2331738061cSShyam Sundar S K tp->shifting_up = true; 2341738061cSShyam Sundar S K 2351738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]; 23619c8b524SMuhammad Usama Anjum tp->time_constant = out->t_perf_to_balanced; 2371738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_BALANCE; 2381738061cSShyam Sundar S K tp->shifting_up = false; 2391738061cSShyam Sundar S K 2401738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_TURBO_TO_PERFORMANCE]; 24119c8b524SMuhammad Usama Anjum tp->time_constant = out->t_turbo_to_perf; 2421738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_PERFORMANCE; 2431738061cSShyam Sundar S K tp->shifting_up = false; 2441738061cSShyam Sundar S K 2451738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_TO_TURBO]; 24619c8b524SMuhammad Usama Anjum tp->time_constant = out->t_perf_to_turbo; 2471738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_TURBO; 2481738061cSShyam Sundar S K tp->shifting_up = true; 2491738061cSShyam Sundar S K } 2501738061cSShyam Sundar S K 25119c8b524SMuhammad Usama Anjum static void amd_pmf_update_mode_set(int idx, struct apmf_dyn_slider_output *out) 2521738061cSShyam Sundar S K { 2531738061cSShyam Sundar S K struct cnqf_mode_settings *ms; 2541738061cSShyam Sundar S K 2551738061cSShyam Sundar S K /* Quiet Mode */ 2561738061cSShyam Sundar S K ms = &config_store.mode_set[idx][CNQF_MODE_QUIET]; 25719c8b524SMuhammad Usama Anjum ms->power_floor = out->ps[APMF_CNQF_QUIET].pfloor; 25819c8b524SMuhammad Usama Anjum ms->power_control.fppt = out->ps[APMF_CNQF_QUIET].fppt; 25919c8b524SMuhammad Usama Anjum ms->power_control.sppt = out->ps[APMF_CNQF_QUIET].sppt; 26019c8b524SMuhammad Usama Anjum ms->power_control.sppt_apu_only = out->ps[APMF_CNQF_QUIET].sppt_apu_only; 26119c8b524SMuhammad Usama Anjum ms->power_control.spl = out->ps[APMF_CNQF_QUIET].spl; 26219c8b524SMuhammad Usama Anjum ms->power_control.stt_min = out->ps[APMF_CNQF_QUIET].stt_min_limit; 2631738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_APU] = 26419c8b524SMuhammad Usama Anjum out->ps[APMF_CNQF_QUIET].stt_skintemp[STT_TEMP_APU]; 2651738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 26619c8b524SMuhammad Usama Anjum out->ps[APMF_CNQF_QUIET].stt_skintemp[STT_TEMP_HS2]; 26719c8b524SMuhammad Usama Anjum ms->fan_control.fan_id = out->ps[APMF_CNQF_QUIET].fan_id; 2681738061cSShyam Sundar S K 2691738061cSShyam Sundar S K /* Balance Mode */ 2701738061cSShyam Sundar S K ms = &config_store.mode_set[idx][CNQF_MODE_BALANCE]; 27119c8b524SMuhammad Usama Anjum ms->power_floor = out->ps[APMF_CNQF_BALANCE].pfloor; 27219c8b524SMuhammad Usama Anjum ms->power_control.fppt = out->ps[APMF_CNQF_BALANCE].fppt; 27319c8b524SMuhammad Usama Anjum ms->power_control.sppt = out->ps[APMF_CNQF_BALANCE].sppt; 27419c8b524SMuhammad Usama Anjum ms->power_control.sppt_apu_only = out->ps[APMF_CNQF_BALANCE].sppt_apu_only; 27519c8b524SMuhammad Usama Anjum ms->power_control.spl = out->ps[APMF_CNQF_BALANCE].spl; 27619c8b524SMuhammad Usama Anjum ms->power_control.stt_min = out->ps[APMF_CNQF_BALANCE].stt_min_limit; 2771738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_APU] = 27819c8b524SMuhammad Usama Anjum out->ps[APMF_CNQF_BALANCE].stt_skintemp[STT_TEMP_APU]; 2791738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 28019c8b524SMuhammad Usama Anjum out->ps[APMF_CNQF_BALANCE].stt_skintemp[STT_TEMP_HS2]; 28119c8b524SMuhammad Usama Anjum ms->fan_control.fan_id = out->ps[APMF_CNQF_BALANCE].fan_id; 2821738061cSShyam Sundar S K 2831738061cSShyam Sundar S K /* Performance Mode */ 2841738061cSShyam Sundar S K ms = &config_store.mode_set[idx][CNQF_MODE_PERFORMANCE]; 28519c8b524SMuhammad Usama Anjum ms->power_floor = out->ps[APMF_CNQF_PERFORMANCE].pfloor; 28619c8b524SMuhammad Usama Anjum ms->power_control.fppt = out->ps[APMF_CNQF_PERFORMANCE].fppt; 28719c8b524SMuhammad Usama Anjum ms->power_control.sppt = out->ps[APMF_CNQF_PERFORMANCE].sppt; 28819c8b524SMuhammad Usama Anjum ms->power_control.sppt_apu_only = out->ps[APMF_CNQF_PERFORMANCE].sppt_apu_only; 28919c8b524SMuhammad Usama Anjum ms->power_control.spl = out->ps[APMF_CNQF_PERFORMANCE].spl; 29019c8b524SMuhammad Usama Anjum ms->power_control.stt_min = out->ps[APMF_CNQF_PERFORMANCE].stt_min_limit; 2911738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_APU] = 29219c8b524SMuhammad Usama Anjum out->ps[APMF_CNQF_PERFORMANCE].stt_skintemp[STT_TEMP_APU]; 2931738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 29419c8b524SMuhammad Usama Anjum out->ps[APMF_CNQF_PERFORMANCE].stt_skintemp[STT_TEMP_HS2]; 29519c8b524SMuhammad Usama Anjum ms->fan_control.fan_id = out->ps[APMF_CNQF_PERFORMANCE].fan_id; 2961738061cSShyam Sundar S K 2971738061cSShyam Sundar S K /* Turbo Mode */ 2981738061cSShyam Sundar S K ms = &config_store.mode_set[idx][CNQF_MODE_TURBO]; 29919c8b524SMuhammad Usama Anjum ms->power_floor = out->ps[APMF_CNQF_TURBO].pfloor; 30019c8b524SMuhammad Usama Anjum ms->power_control.fppt = out->ps[APMF_CNQF_TURBO].fppt; 30119c8b524SMuhammad Usama Anjum ms->power_control.sppt = out->ps[APMF_CNQF_TURBO].sppt; 30219c8b524SMuhammad Usama Anjum ms->power_control.sppt_apu_only = out->ps[APMF_CNQF_TURBO].sppt_apu_only; 30319c8b524SMuhammad Usama Anjum ms->power_control.spl = out->ps[APMF_CNQF_TURBO].spl; 30419c8b524SMuhammad Usama Anjum ms->power_control.stt_min = out->ps[APMF_CNQF_TURBO].stt_min_limit; 3051738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_APU] = 30619c8b524SMuhammad Usama Anjum out->ps[APMF_CNQF_TURBO].stt_skintemp[STT_TEMP_APU]; 3071738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 30819c8b524SMuhammad Usama Anjum out->ps[APMF_CNQF_TURBO].stt_skintemp[STT_TEMP_HS2]; 30919c8b524SMuhammad Usama Anjum ms->fan_control.fan_id = out->ps[APMF_CNQF_TURBO].fan_id; 3101738061cSShyam Sundar S K } 3111738061cSShyam Sundar S K 3121738061cSShyam Sundar S K static int amd_pmf_check_flags(struct amd_pmf_dev *dev) 3131738061cSShyam Sundar S K { 3141738061cSShyam Sundar S K struct apmf_dyn_slider_output out = {}; 3151738061cSShyam Sundar S K 3161738061cSShyam Sundar S K if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC)) 3171738061cSShyam Sundar S K apmf_get_dyn_slider_def_ac(dev, &out); 3181738061cSShyam Sundar S K else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 3191738061cSShyam Sundar S K apmf_get_dyn_slider_def_dc(dev, &out); 3201738061cSShyam Sundar S K 3211738061cSShyam Sundar S K return out.flags; 3221738061cSShyam Sundar S K } 3231738061cSShyam Sundar S K 3241738061cSShyam Sundar S K static int amd_pmf_load_defaults_cnqf(struct amd_pmf_dev *dev) 3251738061cSShyam Sundar S K { 3261738061cSShyam Sundar S K struct apmf_dyn_slider_output out; 3271738061cSShyam Sundar S K int i, j, ret; 3281738061cSShyam Sundar S K 3291738061cSShyam Sundar S K for (i = 0; i < POWER_SOURCE_MAX; i++) { 3301738061cSShyam Sundar S K if (!is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC + i)) 3311738061cSShyam Sundar S K continue; 3321738061cSShyam Sundar S K 3331738061cSShyam Sundar S K if (i == POWER_SOURCE_AC) 3341738061cSShyam Sundar S K ret = apmf_get_dyn_slider_def_ac(dev, &out); 3351738061cSShyam Sundar S K else 3361738061cSShyam Sundar S K ret = apmf_get_dyn_slider_def_dc(dev, &out); 3371738061cSShyam Sundar S K if (ret) { 3381738061cSShyam Sundar S K dev_err(dev->dev, "APMF apmf_get_dyn_slider_def_dc failed :%d\n", ret); 3391738061cSShyam Sundar S K return ret; 3401738061cSShyam Sundar S K } 3411738061cSShyam Sundar S K 342*a82ebb3dSShyam Sundar S K amd_pmf_cnqf_dump_defaults(&out, i); 34319c8b524SMuhammad Usama Anjum amd_pmf_update_mode_set(i, &out); 34419c8b524SMuhammad Usama Anjum amd_pmf_update_trans_data(i, &out); 3451738061cSShyam Sundar S K amd_pmf_update_power_threshold(i); 3461738061cSShyam Sundar S K 3471738061cSShyam Sundar S K for (j = 0; j < CNQF_MODE_MAX; j++) { 3481738061cSShyam Sundar S K if (config_store.mode_set[i][j].fan_control.fan_id == FAN_INDEX_AUTO) 3491738061cSShyam Sundar S K config_store.mode_set[i][j].fan_control.manual = false; 3501738061cSShyam Sundar S K else 3511738061cSShyam Sundar S K config_store.mode_set[i][j].fan_control.manual = true; 3521738061cSShyam Sundar S K } 3531738061cSShyam Sundar S K } 3541738061cSShyam Sundar S K 3551738061cSShyam Sundar S K /* set to initial default values */ 3561738061cSShyam Sundar S K config_store.current_mode = CNQF_MODE_BALANCE; 3571738061cSShyam Sundar S K 3581738061cSShyam Sundar S K return 0; 3591738061cSShyam Sundar S K } 3601738061cSShyam Sundar S K 3613dae5825SShyam Sundar S K static ssize_t cnqf_enable_store(struct device *dev, 3623dae5825SShyam Sundar S K struct device_attribute *attr, 3633dae5825SShyam Sundar S K const char *buf, size_t count) 3643dae5825SShyam Sundar S K { 3653dae5825SShyam Sundar S K struct amd_pmf_dev *pdev = dev_get_drvdata(dev); 366c5258d39SShyam Sundar S K int result, src; 3673dae5825SShyam Sundar S K bool input; 3683dae5825SShyam Sundar S K 3693dae5825SShyam Sundar S K result = kstrtobool(buf, &input); 3703dae5825SShyam Sundar S K if (result) 3713dae5825SShyam Sundar S K return result; 3723dae5825SShyam Sundar S K 3733dae5825SShyam Sundar S K src = amd_pmf_cnqf_get_power_source(pdev); 3743dae5825SShyam Sundar S K pdev->cnqf_enabled = input; 3753dae5825SShyam Sundar S K 37616909aa8SShyam Sundar S K if (pdev->cnqf_enabled && is_pprof_balanced(pdev)) { 3773dae5825SShyam Sundar S K amd_pmf_set_cnqf(pdev, src, config_store.current_mode, NULL); 3783dae5825SShyam Sundar S K } else { 3793dae5825SShyam Sundar S K if (is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) 380c5258d39SShyam Sundar S K amd_pmf_set_sps_power_limits(pdev); 3813dae5825SShyam Sundar S K } 3823dae5825SShyam Sundar S K 3833dae5825SShyam Sundar S K dev_dbg(pdev->dev, "Received CnQF %s\n", input ? "on" : "off"); 3843dae5825SShyam Sundar S K return count; 3853dae5825SShyam Sundar S K } 3863dae5825SShyam Sundar S K 3873dae5825SShyam Sundar S K static ssize_t cnqf_enable_show(struct device *dev, 3883dae5825SShyam Sundar S K struct device_attribute *attr, 3893dae5825SShyam Sundar S K char *buf) 3903dae5825SShyam Sundar S K { 3913dae5825SShyam Sundar S K struct amd_pmf_dev *pdev = dev_get_drvdata(dev); 3923dae5825SShyam Sundar S K 3933dae5825SShyam Sundar S K return sysfs_emit(buf, "%s\n", pdev->cnqf_enabled ? "on" : "off"); 3943dae5825SShyam Sundar S K } 3953dae5825SShyam Sundar S K 3963dae5825SShyam Sundar S K static DEVICE_ATTR_RW(cnqf_enable); 3973dae5825SShyam Sundar S K 3983dae5825SShyam Sundar S K static umode_t cnqf_feature_is_visible(struct kobject *kobj, 3993dae5825SShyam Sundar S K struct attribute *attr, int n) 4003dae5825SShyam Sundar S K { 4013dae5825SShyam Sundar S K struct device *dev = kobj_to_dev(kobj); 4023dae5825SShyam Sundar S K struct amd_pmf_dev *pdev = dev_get_drvdata(dev); 4033dae5825SShyam Sundar S K 4043dae5825SShyam Sundar S K return pdev->cnqf_supported ? attr->mode : 0; 4053dae5825SShyam Sundar S K } 4063dae5825SShyam Sundar S K 4073dae5825SShyam Sundar S K static struct attribute *cnqf_feature_attrs[] = { 4083dae5825SShyam Sundar S K &dev_attr_cnqf_enable.attr, 4093dae5825SShyam Sundar S K NULL 4103dae5825SShyam Sundar S K }; 4113dae5825SShyam Sundar S K 4123dae5825SShyam Sundar S K const struct attribute_group cnqf_feature_attribute_group = { 4133dae5825SShyam Sundar S K .is_visible = cnqf_feature_is_visible, 4143dae5825SShyam Sundar S K .attrs = cnqf_feature_attrs, 4153dae5825SShyam Sundar S K }; 4163dae5825SShyam Sundar S K 4171738061cSShyam Sundar S K void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev) 4181738061cSShyam Sundar S K { 4191738061cSShyam Sundar S K cancel_delayed_work_sync(&dev->work_buffer); 4201738061cSShyam Sundar S K } 4211738061cSShyam Sundar S K 4221738061cSShyam Sundar S K int amd_pmf_init_cnqf(struct amd_pmf_dev *dev) 4231738061cSShyam Sundar S K { 4241738061cSShyam Sundar S K int ret, src; 4251738061cSShyam Sundar S K 4261738061cSShyam Sundar S K /* 4271738061cSShyam Sundar S K * Note the caller of this function has already checked that both 4281738061cSShyam Sundar S K * APMF_FUNC_DYN_SLIDER_AC and APMF_FUNC_DYN_SLIDER_DC are supported. 4291738061cSShyam Sundar S K */ 4301738061cSShyam Sundar S K 4311738061cSShyam Sundar S K ret = amd_pmf_load_defaults_cnqf(dev); 4321738061cSShyam Sundar S K if (ret < 0) 4331738061cSShyam Sundar S K return ret; 4341738061cSShyam Sundar S K 4351738061cSShyam Sundar S K amd_pmf_init_metrics_table(dev); 4361738061cSShyam Sundar S K 4371738061cSShyam Sundar S K dev->cnqf_supported = true; 4381738061cSShyam Sundar S K dev->cnqf_enabled = amd_pmf_check_flags(dev); 4391738061cSShyam Sundar S K 4401738061cSShyam Sundar S K /* update the thermal for CnQF */ 44116909aa8SShyam Sundar S K if (dev->cnqf_enabled && is_pprof_balanced(dev)) { 4421738061cSShyam Sundar S K src = amd_pmf_cnqf_get_power_source(dev); 4431738061cSShyam Sundar S K amd_pmf_set_cnqf(dev, src, config_store.current_mode, NULL); 4441738061cSShyam Sundar S K } 4451738061cSShyam Sundar S K 4461738061cSShyam Sundar S K return 0; 4471738061cSShyam Sundar S K } 448