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 161738061cSShyam Sundar S K static int amd_pmf_set_cnqf(struct amd_pmf_dev *dev, int src, int idx, 171738061cSShyam Sundar S K struct cnqf_config *table) 181738061cSShyam Sundar S K { 191738061cSShyam Sundar S K struct power_table_control *pc; 201738061cSShyam Sundar S K 211738061cSShyam Sundar S K pc = &config_store.mode_set[src][idx].power_control; 221738061cSShyam Sundar S K 231738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_SPL, false, pc->spl, NULL); 241738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_FPPT, false, pc->fppt, NULL); 251738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_SPPT, false, pc->sppt, NULL); 261738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_SPPT_APU_ONLY, false, pc->sppt_apu_only, NULL); 271738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_STT_MIN_LIMIT, false, pc->stt_min, NULL); 281738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_STT_LIMIT_APU, false, pc->stt_skin_temp[STT_TEMP_APU], 291738061cSShyam Sundar S K NULL); 301738061cSShyam Sundar S K amd_pmf_send_cmd(dev, SET_STT_LIMIT_HS2, false, pc->stt_skin_temp[STT_TEMP_HS2], 311738061cSShyam Sundar S K NULL); 321738061cSShyam Sundar S K 331738061cSShyam Sundar S K if (is_apmf_func_supported(dev, APMF_FUNC_SET_FAN_IDX)) 341738061cSShyam Sundar S K apmf_update_fan_idx(dev, 351738061cSShyam Sundar S K config_store.mode_set[src][idx].fan_control.manual, 361738061cSShyam Sundar S K config_store.mode_set[src][idx].fan_control.fan_id); 371738061cSShyam Sundar S K 381738061cSShyam Sundar S K return 0; 391738061cSShyam Sundar S K } 401738061cSShyam Sundar S K 411738061cSShyam Sundar S K static void amd_pmf_update_power_threshold(int src) 421738061cSShyam Sundar S K { 431738061cSShyam Sundar S K struct cnqf_mode_settings *ts; 441738061cSShyam Sundar S K struct cnqf_tran_params *tp; 451738061cSShyam Sundar S K 461738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_TO_QUIET]; 471738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_BALANCE]; 48*9732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 491738061cSShyam Sundar S K 501738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_TO_TURBO]; 511738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_PERFORMANCE]; 52*9732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 531738061cSShyam Sundar S K 541738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_BALANCE_TO_PERFORMANCE]; 551738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_BALANCE]; 56*9732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 571738061cSShyam Sundar S K 581738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]; 591738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_PERFORMANCE]; 60*9732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 611738061cSShyam Sundar S K 621738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_QUIET_TO_BALANCE]; 631738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_QUIET]; 64*9732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 651738061cSShyam Sundar S K 661738061cSShyam Sundar S K tp = &config_store.trans_param[src][CNQF_TRANSITION_FROM_TURBO_TO_PERFORMANCE]; 671738061cSShyam Sundar S K ts = &config_store.mode_set[src][CNQF_MODE_TURBO]; 68*9732f9c7SShyam Sundar S K tp->power_threshold = ts->power_floor; 691738061cSShyam Sundar S K } 701738061cSShyam Sundar S K 711738061cSShyam Sundar S K static const char *state_as_str(unsigned int state) 721738061cSShyam Sundar S K { 731738061cSShyam Sundar S K switch (state) { 741738061cSShyam Sundar S K case CNQF_MODE_QUIET: 751738061cSShyam Sundar S K return "QUIET"; 761738061cSShyam Sundar S K case CNQF_MODE_BALANCE: 771738061cSShyam Sundar S K return "BALANCED"; 781738061cSShyam Sundar S K case CNQF_MODE_TURBO: 791738061cSShyam Sundar S K return "TURBO"; 801738061cSShyam Sundar S K case CNQF_MODE_PERFORMANCE: 811738061cSShyam Sundar S K return "PERFORMANCE"; 821738061cSShyam Sundar S K default: 831738061cSShyam Sundar S K return "Unknown CnQF mode"; 841738061cSShyam Sundar S K } 851738061cSShyam Sundar S K } 861738061cSShyam Sundar S K 871738061cSShyam Sundar S K static int amd_pmf_cnqf_get_power_source(struct amd_pmf_dev *dev) 881738061cSShyam Sundar S K { 891738061cSShyam Sundar S K if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) && 901738061cSShyam Sundar S K is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 911738061cSShyam Sundar S K return amd_pmf_get_power_source(); 921738061cSShyam Sundar S K else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 931738061cSShyam Sundar S K return POWER_SOURCE_DC; 941738061cSShyam Sundar S K else 951738061cSShyam Sundar S K return POWER_SOURCE_AC; 961738061cSShyam Sundar S K } 971738061cSShyam Sundar S K 981738061cSShyam Sundar S K int amd_pmf_trans_cnqf(struct amd_pmf_dev *dev, int socket_power, ktime_t time_lapsed_ms) 991738061cSShyam Sundar S K { 1001738061cSShyam Sundar S K struct cnqf_tran_params *tp; 1011738061cSShyam Sundar S K int src, i, j; 1021738061cSShyam Sundar S K u32 avg_power = 0; 1031738061cSShyam Sundar S K 1041738061cSShyam Sundar S K src = amd_pmf_cnqf_get_power_source(dev); 1051738061cSShyam Sundar S K 1061738061cSShyam Sundar S K if (dev->current_profile == PLATFORM_PROFILE_BALANCED) { 1071738061cSShyam Sundar S K amd_pmf_set_cnqf(dev, src, config_store.current_mode, NULL); 1081738061cSShyam Sundar S K } else { 1091738061cSShyam Sundar S K /* 1101738061cSShyam Sundar S K * Return from here if the platform_profile is not balanced 1111738061cSShyam Sundar S K * so that preference is given to user mode selection, rather 1121738061cSShyam Sundar S K * than enforcing CnQF to run all the time (if enabled) 1131738061cSShyam Sundar S K */ 1141738061cSShyam Sundar S K return -EINVAL; 1151738061cSShyam Sundar S K } 1161738061cSShyam Sundar S K 1171738061cSShyam Sundar S K for (i = 0; i < CNQF_TRANSITION_MAX; i++) { 1181738061cSShyam Sundar S K config_store.trans_param[src][i].timer += time_lapsed_ms; 1191738061cSShyam Sundar S K config_store.trans_param[src][i].total_power += socket_power; 1201738061cSShyam Sundar S K config_store.trans_param[src][i].count++; 1211738061cSShyam Sundar S K 1221738061cSShyam Sundar S K tp = &config_store.trans_param[src][i]; 1231738061cSShyam Sundar S K if (tp->timer >= tp->time_constant && tp->count) { 1241738061cSShyam Sundar S K avg_power = tp->total_power / tp->count; 1251738061cSShyam Sundar S K 1261738061cSShyam Sundar S K /* Reset the indices */ 1271738061cSShyam Sundar S K tp->timer = 0; 1281738061cSShyam Sundar S K tp->total_power = 0; 1291738061cSShyam Sundar S K tp->count = 0; 1301738061cSShyam Sundar S K 1311738061cSShyam Sundar S K if ((tp->shifting_up && avg_power >= tp->power_threshold) || 1321738061cSShyam Sundar S K (!tp->shifting_up && avg_power <= tp->power_threshold)) { 1331738061cSShyam Sundar S K tp->priority = true; 1341738061cSShyam Sundar S K } else { 1351738061cSShyam Sundar S K tp->priority = false; 1361738061cSShyam Sundar S K } 1371738061cSShyam Sundar S K } 1381738061cSShyam Sundar S K } 1391738061cSShyam Sundar S K 1401738061cSShyam Sundar S K dev_dbg(dev->dev, "[CNQF] Avg power: %u mW socket power: %u mW mode:%s\n", 1411738061cSShyam Sundar S K avg_power, socket_power, state_as_str(config_store.current_mode)); 1421738061cSShyam Sundar S K 1431738061cSShyam Sundar S K for (j = 0; j < CNQF_TRANSITION_MAX; j++) { 1441738061cSShyam Sundar S K /* apply the highest priority */ 1451738061cSShyam Sundar S K if (config_store.trans_param[src][j].priority) { 1461738061cSShyam Sundar S K if (config_store.current_mode != 1471738061cSShyam Sundar S K config_store.trans_param[src][j].target_mode) { 1481738061cSShyam Sundar S K config_store.current_mode = 1491738061cSShyam Sundar S K config_store.trans_param[src][j].target_mode; 1501738061cSShyam Sundar S K dev_dbg(dev->dev, "Moving to Mode :%s\n", 1511738061cSShyam Sundar S K state_as_str(config_store.current_mode)); 1521738061cSShyam Sundar S K amd_pmf_set_cnqf(dev, src, 1531738061cSShyam Sundar S K config_store.current_mode, NULL); 1541738061cSShyam Sundar S K } 1551738061cSShyam Sundar S K break; 1561738061cSShyam Sundar S K } 1571738061cSShyam Sundar S K } 1581738061cSShyam Sundar S K return 0; 1591738061cSShyam Sundar S K } 1601738061cSShyam Sundar S K 1611738061cSShyam Sundar S K static void amd_pmf_update_trans_data(int idx, struct apmf_dyn_slider_output out) 1621738061cSShyam Sundar S K { 1631738061cSShyam Sundar S K struct cnqf_tran_params *tp; 1641738061cSShyam Sundar S K 1651738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_TO_QUIET]; 1661738061cSShyam Sundar S K tp->time_constant = out.t_balanced_to_quiet; 1671738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_QUIET; 1681738061cSShyam Sundar S K tp->shifting_up = false; 1691738061cSShyam Sundar S K 1701738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_BALANCE_TO_PERFORMANCE]; 1711738061cSShyam Sundar S K tp->time_constant = out.t_balanced_to_perf; 1721738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_PERFORMANCE; 1731738061cSShyam Sundar S K tp->shifting_up = true; 1741738061cSShyam Sundar S K 1751738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_QUIET_TO_BALANCE]; 1761738061cSShyam Sundar S K tp->time_constant = out.t_quiet_to_balanced; 1771738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_BALANCE; 1781738061cSShyam Sundar S K tp->shifting_up = true; 1791738061cSShyam Sundar S K 1801738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_PERFORMANCE_TO_BALANCE]; 1811738061cSShyam Sundar S K tp->time_constant = out.t_perf_to_balanced; 1821738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_BALANCE; 1831738061cSShyam Sundar S K tp->shifting_up = false; 1841738061cSShyam Sundar S K 1851738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_FROM_TURBO_TO_PERFORMANCE]; 1861738061cSShyam Sundar S K tp->time_constant = out.t_turbo_to_perf; 1871738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_PERFORMANCE; 1881738061cSShyam Sundar S K tp->shifting_up = false; 1891738061cSShyam Sundar S K 1901738061cSShyam Sundar S K tp = &config_store.trans_param[idx][CNQF_TRANSITION_TO_TURBO]; 1911738061cSShyam Sundar S K tp->time_constant = out.t_perf_to_turbo; 1921738061cSShyam Sundar S K tp->target_mode = CNQF_MODE_TURBO; 1931738061cSShyam Sundar S K tp->shifting_up = true; 1941738061cSShyam Sundar S K } 1951738061cSShyam Sundar S K 1961738061cSShyam Sundar S K static void amd_pmf_update_mode_set(int idx, struct apmf_dyn_slider_output out) 1971738061cSShyam Sundar S K { 1981738061cSShyam Sundar S K struct cnqf_mode_settings *ms; 1991738061cSShyam Sundar S K 2001738061cSShyam Sundar S K /* Quiet Mode */ 2011738061cSShyam Sundar S K ms = &config_store.mode_set[idx][CNQF_MODE_QUIET]; 2021738061cSShyam Sundar S K ms->power_floor = out.ps[APMF_CNQF_QUIET].pfloor; 2031738061cSShyam Sundar S K ms->power_control.fppt = out.ps[APMF_CNQF_QUIET].fppt; 2041738061cSShyam Sundar S K ms->power_control.sppt = out.ps[APMF_CNQF_QUIET].sppt; 2051738061cSShyam Sundar S K ms->power_control.sppt_apu_only = out.ps[APMF_CNQF_QUIET].sppt_apu_only; 2061738061cSShyam Sundar S K ms->power_control.spl = out.ps[APMF_CNQF_QUIET].spl; 2071738061cSShyam Sundar S K ms->power_control.stt_min = out.ps[APMF_CNQF_QUIET].stt_min_limit; 2081738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_APU] = 2091738061cSShyam Sundar S K out.ps[APMF_CNQF_QUIET].stt_skintemp[STT_TEMP_APU]; 2101738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 2111738061cSShyam Sundar S K out.ps[APMF_CNQF_QUIET].stt_skintemp[STT_TEMP_HS2]; 2121738061cSShyam Sundar S K ms->fan_control.fan_id = out.ps[APMF_CNQF_QUIET].fan_id; 2131738061cSShyam Sundar S K 2141738061cSShyam Sundar S K /* Balance Mode */ 2151738061cSShyam Sundar S K ms = &config_store.mode_set[idx][CNQF_MODE_BALANCE]; 2161738061cSShyam Sundar S K ms->power_floor = out.ps[APMF_CNQF_BALANCE].pfloor; 2171738061cSShyam Sundar S K ms->power_control.fppt = out.ps[APMF_CNQF_BALANCE].fppt; 2181738061cSShyam Sundar S K ms->power_control.sppt = out.ps[APMF_CNQF_BALANCE].sppt; 2191738061cSShyam Sundar S K ms->power_control.sppt_apu_only = out.ps[APMF_CNQF_BALANCE].sppt_apu_only; 2201738061cSShyam Sundar S K ms->power_control.spl = out.ps[APMF_CNQF_BALANCE].spl; 2211738061cSShyam Sundar S K ms->power_control.stt_min = out.ps[APMF_CNQF_BALANCE].stt_min_limit; 2221738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_APU] = 2231738061cSShyam Sundar S K out.ps[APMF_CNQF_BALANCE].stt_skintemp[STT_TEMP_APU]; 2241738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 2251738061cSShyam Sundar S K out.ps[APMF_CNQF_BALANCE].stt_skintemp[STT_TEMP_HS2]; 2261738061cSShyam Sundar S K ms->fan_control.fan_id = out.ps[APMF_CNQF_BALANCE].fan_id; 2271738061cSShyam Sundar S K 2281738061cSShyam Sundar S K /* Performance Mode */ 2291738061cSShyam Sundar S K ms = &config_store.mode_set[idx][CNQF_MODE_PERFORMANCE]; 2301738061cSShyam Sundar S K ms->power_floor = out.ps[APMF_CNQF_PERFORMANCE].pfloor; 2311738061cSShyam Sundar S K ms->power_control.fppt = out.ps[APMF_CNQF_PERFORMANCE].fppt; 2321738061cSShyam Sundar S K ms->power_control.sppt = out.ps[APMF_CNQF_PERFORMANCE].sppt; 2331738061cSShyam Sundar S K ms->power_control.sppt_apu_only = out.ps[APMF_CNQF_PERFORMANCE].sppt_apu_only; 2341738061cSShyam Sundar S K ms->power_control.spl = out.ps[APMF_CNQF_PERFORMANCE].spl; 2351738061cSShyam Sundar S K ms->power_control.stt_min = out.ps[APMF_CNQF_PERFORMANCE].stt_min_limit; 2361738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_APU] = 2371738061cSShyam Sundar S K out.ps[APMF_CNQF_PERFORMANCE].stt_skintemp[STT_TEMP_APU]; 2381738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 2391738061cSShyam Sundar S K out.ps[APMF_CNQF_PERFORMANCE].stt_skintemp[STT_TEMP_HS2]; 2401738061cSShyam Sundar S K ms->fan_control.fan_id = out.ps[APMF_CNQF_PERFORMANCE].fan_id; 2411738061cSShyam Sundar S K 2421738061cSShyam Sundar S K /* Turbo Mode */ 2431738061cSShyam Sundar S K ms = &config_store.mode_set[idx][CNQF_MODE_TURBO]; 2441738061cSShyam Sundar S K ms->power_floor = out.ps[APMF_CNQF_TURBO].pfloor; 2451738061cSShyam Sundar S K ms->power_control.fppt = out.ps[APMF_CNQF_TURBO].fppt; 2461738061cSShyam Sundar S K ms->power_control.sppt = out.ps[APMF_CNQF_TURBO].sppt; 2471738061cSShyam Sundar S K ms->power_control.sppt_apu_only = out.ps[APMF_CNQF_TURBO].sppt_apu_only; 2481738061cSShyam Sundar S K ms->power_control.spl = out.ps[APMF_CNQF_TURBO].spl; 2491738061cSShyam Sundar S K ms->power_control.stt_min = out.ps[APMF_CNQF_TURBO].stt_min_limit; 2501738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_APU] = 2511738061cSShyam Sundar S K out.ps[APMF_CNQF_TURBO].stt_skintemp[STT_TEMP_APU]; 2521738061cSShyam Sundar S K ms->power_control.stt_skin_temp[STT_TEMP_HS2] = 2531738061cSShyam Sundar S K out.ps[APMF_CNQF_TURBO].stt_skintemp[STT_TEMP_HS2]; 2541738061cSShyam Sundar S K ms->fan_control.fan_id = out.ps[APMF_CNQF_TURBO].fan_id; 2551738061cSShyam Sundar S K } 2561738061cSShyam Sundar S K 2571738061cSShyam Sundar S K static int amd_pmf_check_flags(struct amd_pmf_dev *dev) 2581738061cSShyam Sundar S K { 2591738061cSShyam Sundar S K struct apmf_dyn_slider_output out = {}; 2601738061cSShyam Sundar S K 2611738061cSShyam Sundar S K if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC)) 2621738061cSShyam Sundar S K apmf_get_dyn_slider_def_ac(dev, &out); 2631738061cSShyam Sundar S K else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_DC)) 2641738061cSShyam Sundar S K apmf_get_dyn_slider_def_dc(dev, &out); 2651738061cSShyam Sundar S K 2661738061cSShyam Sundar S K return out.flags; 2671738061cSShyam Sundar S K } 2681738061cSShyam Sundar S K 2691738061cSShyam Sundar S K static int amd_pmf_load_defaults_cnqf(struct amd_pmf_dev *dev) 2701738061cSShyam Sundar S K { 2711738061cSShyam Sundar S K struct apmf_dyn_slider_output out; 2721738061cSShyam Sundar S K int i, j, ret; 2731738061cSShyam Sundar S K 2741738061cSShyam Sundar S K for (i = 0; i < POWER_SOURCE_MAX; i++) { 2751738061cSShyam Sundar S K if (!is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC + i)) 2761738061cSShyam Sundar S K continue; 2771738061cSShyam Sundar S K 2781738061cSShyam Sundar S K if (i == POWER_SOURCE_AC) 2791738061cSShyam Sundar S K ret = apmf_get_dyn_slider_def_ac(dev, &out); 2801738061cSShyam Sundar S K else 2811738061cSShyam Sundar S K ret = apmf_get_dyn_slider_def_dc(dev, &out); 2821738061cSShyam Sundar S K if (ret) { 2831738061cSShyam Sundar S K dev_err(dev->dev, "APMF apmf_get_dyn_slider_def_dc failed :%d\n", ret); 2841738061cSShyam Sundar S K return ret; 2851738061cSShyam Sundar S K } 2861738061cSShyam Sundar S K 2871738061cSShyam Sundar S K amd_pmf_update_mode_set(i, out); 2881738061cSShyam Sundar S K amd_pmf_update_trans_data(i, out); 2891738061cSShyam Sundar S K amd_pmf_update_power_threshold(i); 2901738061cSShyam Sundar S K 2911738061cSShyam Sundar S K for (j = 0; j < CNQF_MODE_MAX; j++) { 2921738061cSShyam Sundar S K if (config_store.mode_set[i][j].fan_control.fan_id == FAN_INDEX_AUTO) 2931738061cSShyam Sundar S K config_store.mode_set[i][j].fan_control.manual = false; 2941738061cSShyam Sundar S K else 2951738061cSShyam Sundar S K config_store.mode_set[i][j].fan_control.manual = true; 2961738061cSShyam Sundar S K } 2971738061cSShyam Sundar S K } 2981738061cSShyam Sundar S K 2991738061cSShyam Sundar S K /* set to initial default values */ 3001738061cSShyam Sundar S K config_store.current_mode = CNQF_MODE_BALANCE; 3011738061cSShyam Sundar S K 3021738061cSShyam Sundar S K return 0; 3031738061cSShyam Sundar S K } 3041738061cSShyam Sundar S K 3053dae5825SShyam Sundar S K static ssize_t cnqf_enable_store(struct device *dev, 3063dae5825SShyam Sundar S K struct device_attribute *attr, 3073dae5825SShyam Sundar S K const char *buf, size_t count) 3083dae5825SShyam Sundar S K { 3093dae5825SShyam Sundar S K struct amd_pmf_dev *pdev = dev_get_drvdata(dev); 3103dae5825SShyam Sundar S K int mode, result, src; 3113dae5825SShyam Sundar S K bool input; 3123dae5825SShyam Sundar S K 3133dae5825SShyam Sundar S K mode = amd_pmf_get_pprof_modes(pdev); 3143dae5825SShyam Sundar S K if (mode < 0) 3153dae5825SShyam Sundar S K return mode; 3163dae5825SShyam Sundar S K 3173dae5825SShyam Sundar S K result = kstrtobool(buf, &input); 3183dae5825SShyam Sundar S K if (result) 3193dae5825SShyam Sundar S K return result; 3203dae5825SShyam Sundar S K 3213dae5825SShyam Sundar S K src = amd_pmf_cnqf_get_power_source(pdev); 3223dae5825SShyam Sundar S K pdev->cnqf_enabled = input; 3233dae5825SShyam Sundar S K 3243dae5825SShyam Sundar S K if (pdev->cnqf_enabled && pdev->current_profile == PLATFORM_PROFILE_BALANCED) { 3253dae5825SShyam Sundar S K amd_pmf_set_cnqf(pdev, src, config_store.current_mode, NULL); 3263dae5825SShyam Sundar S K } else { 3273dae5825SShyam Sundar S K if (is_apmf_func_supported(pdev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) 3283dae5825SShyam Sundar S K amd_pmf_update_slider(pdev, SLIDER_OP_SET, mode, NULL); 3293dae5825SShyam Sundar S K } 3303dae5825SShyam Sundar S K 3313dae5825SShyam Sundar S K dev_dbg(pdev->dev, "Received CnQF %s\n", input ? "on" : "off"); 3323dae5825SShyam Sundar S K return count; 3333dae5825SShyam Sundar S K } 3343dae5825SShyam Sundar S K 3353dae5825SShyam Sundar S K static ssize_t cnqf_enable_show(struct device *dev, 3363dae5825SShyam Sundar S K struct device_attribute *attr, 3373dae5825SShyam Sundar S K char *buf) 3383dae5825SShyam Sundar S K { 3393dae5825SShyam Sundar S K struct amd_pmf_dev *pdev = dev_get_drvdata(dev); 3403dae5825SShyam Sundar S K 3413dae5825SShyam Sundar S K return sysfs_emit(buf, "%s\n", pdev->cnqf_enabled ? "on" : "off"); 3423dae5825SShyam Sundar S K } 3433dae5825SShyam Sundar S K 3443dae5825SShyam Sundar S K static DEVICE_ATTR_RW(cnqf_enable); 3453dae5825SShyam Sundar S K 3463dae5825SShyam Sundar S K static umode_t cnqf_feature_is_visible(struct kobject *kobj, 3473dae5825SShyam Sundar S K struct attribute *attr, int n) 3483dae5825SShyam Sundar S K { 3493dae5825SShyam Sundar S K struct device *dev = kobj_to_dev(kobj); 3503dae5825SShyam Sundar S K struct amd_pmf_dev *pdev = dev_get_drvdata(dev); 3513dae5825SShyam Sundar S K 3523dae5825SShyam Sundar S K return pdev->cnqf_supported ? attr->mode : 0; 3533dae5825SShyam Sundar S K } 3543dae5825SShyam Sundar S K 3553dae5825SShyam Sundar S K static struct attribute *cnqf_feature_attrs[] = { 3563dae5825SShyam Sundar S K &dev_attr_cnqf_enable.attr, 3573dae5825SShyam Sundar S K NULL 3583dae5825SShyam Sundar S K }; 3593dae5825SShyam Sundar S K 3603dae5825SShyam Sundar S K const struct attribute_group cnqf_feature_attribute_group = { 3613dae5825SShyam Sundar S K .is_visible = cnqf_feature_is_visible, 3623dae5825SShyam Sundar S K .attrs = cnqf_feature_attrs, 3633dae5825SShyam Sundar S K }; 3643dae5825SShyam Sundar S K 3651738061cSShyam Sundar S K void amd_pmf_deinit_cnqf(struct amd_pmf_dev *dev) 3661738061cSShyam Sundar S K { 3671738061cSShyam Sundar S K cancel_delayed_work_sync(&dev->work_buffer); 3681738061cSShyam Sundar S K } 3691738061cSShyam Sundar S K 3701738061cSShyam Sundar S K int amd_pmf_init_cnqf(struct amd_pmf_dev *dev) 3711738061cSShyam Sundar S K { 3721738061cSShyam Sundar S K int ret, src; 3731738061cSShyam Sundar S K 3741738061cSShyam Sundar S K /* 3751738061cSShyam Sundar S K * Note the caller of this function has already checked that both 3761738061cSShyam Sundar S K * APMF_FUNC_DYN_SLIDER_AC and APMF_FUNC_DYN_SLIDER_DC are supported. 3771738061cSShyam Sundar S K */ 3781738061cSShyam Sundar S K 3791738061cSShyam Sundar S K ret = amd_pmf_load_defaults_cnqf(dev); 3801738061cSShyam Sundar S K if (ret < 0) 3811738061cSShyam Sundar S K return ret; 3821738061cSShyam Sundar S K 3831738061cSShyam Sundar S K amd_pmf_init_metrics_table(dev); 3841738061cSShyam Sundar S K 3851738061cSShyam Sundar S K dev->cnqf_supported = true; 3861738061cSShyam Sundar S K dev->cnqf_enabled = amd_pmf_check_flags(dev); 3871738061cSShyam Sundar S K 3881738061cSShyam Sundar S K /* update the thermal for CnQF */ 3891738061cSShyam Sundar S K if (dev->cnqf_enabled && dev->current_profile == PLATFORM_PROFILE_BALANCED) { 3901738061cSShyam Sundar S K src = amd_pmf_cnqf_get_power_source(dev); 3911738061cSShyam Sundar S K amd_pmf_set_cnqf(dev, src, config_store.current_mode, NULL); 3921738061cSShyam Sundar S K } 3931738061cSShyam Sundar S K 3941738061cSShyam Sundar S K return 0; 3951738061cSShyam Sundar S K } 396