Path: blob/master/tools/power/x86/intel-speed-select/isst-core-mbox.c
26289 views
// SPDX-License-Identifier: GPL-2.01/*2* Intel Speed Select -- Enumerate and control features for Mailbox Interface3* Copyright (c) 2023 Intel Corporation.4*/5#include "isst.h"67static int mbox_delay;8static int mbox_retries = 3;910#define MAX_TRL_LEVELS_EMR 51112static int mbox_get_disp_freq_multiplier(void)13{14return DISP_FREQ_MULTIPLIER;15}1617static int mbox_get_trl_max_levels(void)18{19if (is_emr_platform())20return MAX_TRL_LEVELS_EMR;2122return 3;23}2425static char *mbox_get_trl_level_name(int level)26{27if (is_emr_platform()) {28static char level_str[18];2930if (level >= MAX_TRL_LEVELS_EMR)31return NULL;3233snprintf(level_str, sizeof(level_str), "level-%d", level);34return level_str;35}3637switch (level) {38case 0:39return "sse";40case 1:41return "avx2";42case 2:43return "avx512";44default:45return NULL;46}47}4849static void mbox_update_platform_param(enum isst_platform_param param, int value)50{51switch (param) {52case ISST_PARAM_MBOX_DELAY:53mbox_delay = value;54break;55case ISST_PARAM_MBOX_RETRIES:56mbox_retries = value;57break;58default:59break;60}61}6263static int mbox_is_punit_valid(struct isst_id *id)64{65if (id->cpu < 0)66return 0;6768if (id->pkg < 0 || id->die < 0 || id->punit)69return 0;7071return 1;72}7374static int _send_mmio_command(unsigned int cpu, unsigned int reg, int write,75unsigned int *value)76{77struct isst_if_io_regs io_regs;78const char *pathname = "/dev/isst_interface";79int cmd;80FILE *outf = get_output_file();81int fd;8283debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);8485fd = open(pathname, O_RDWR);86if (fd < 0)87err(-1, "%s open failed", pathname);8889io_regs.req_count = 1;90io_regs.io_reg[0].logical_cpu = cpu;91io_regs.io_reg[0].reg = reg;92cmd = ISST_IF_IO_CMD;93if (write) {94io_regs.io_reg[0].read_write = 1;95io_regs.io_reg[0].value = *value;96} else {97io_regs.io_reg[0].read_write = 0;98}99100if (ioctl(fd, cmd, &io_regs) == -1) {101if (errno == ENOTTY) {102perror("ISST_IF_IO_COMMAND\n");103fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");104exit(0);105}106fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",107cpu, reg, write);108} else {109if (!write)110*value = io_regs.io_reg[0].value;111112debug_printf(113"mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",114cpu, reg, write, *value);115}116117close(fd);118119return 0;120}121122int _send_mbox_command(unsigned int cpu, unsigned char command,123unsigned char sub_command, unsigned int parameter,124unsigned int req_data, unsigned int *resp)125{126const char *pathname = "/dev/isst_interface";127int fd, retry;128struct isst_if_mbox_cmds mbox_cmds = { 0 };129130debug_printf(131"mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",132cpu, command, sub_command, parameter, req_data);133134if (!is_skx_based_platform() && command == CONFIG_CLOS &&135sub_command != CLOS_PM_QOS_CONFIG) {136unsigned int value;137int write = 0;138int clos_id, core_id, ret = 0;139140debug_printf("CPU %d\n", cpu);141142if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {143value = req_data;144write = 1;145}146147switch (sub_command) {148case CLOS_PQR_ASSOC:149core_id = parameter & 0xff;150ret = _send_mmio_command(151cpu, PQR_ASSOC_OFFSET + core_id * 4, write,152&value);153if (!ret && !write)154*resp = value;155break;156case CLOS_PM_CLOS:157clos_id = parameter & 0x03;158ret = _send_mmio_command(159cpu, PM_CLOS_OFFSET + clos_id * 4, write,160&value);161if (!ret && !write)162*resp = value;163break;164case CLOS_STATUS:165break;166default:167break;168}169return ret;170}171172mbox_cmds.cmd_count = 1;173mbox_cmds.mbox_cmd[0].logical_cpu = cpu;174mbox_cmds.mbox_cmd[0].command = command;175mbox_cmds.mbox_cmd[0].sub_command = sub_command;176mbox_cmds.mbox_cmd[0].parameter = parameter;177mbox_cmds.mbox_cmd[0].req_data = req_data;178179if (mbox_delay)180usleep(mbox_delay * 1000);181182fd = open(pathname, O_RDWR);183if (fd < 0)184err(-1, "%s open failed", pathname);185186retry = mbox_retries;187do {188if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {189if (errno == ENOTTY) {190perror("ISST_IF_MBOX_COMMAND\n");191fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");192exit(0);193}194debug_printf(195"Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",196cpu, command, sub_command, parameter, req_data, errno);197--retry;198} else {199*resp = mbox_cmds.mbox_cmd[0].resp_data;200debug_printf(201"mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",202cpu, command, sub_command, parameter, req_data, *resp);203break;204}205} while (retry);206207close(fd);208209if (!retry) {210debug_printf("Failed mbox command even after retries\n");211return -1;212213}214215return 0;216}217218static int mbox_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)219{220unsigned int resp;221int ret;222223ret = _send_mbox_command(id->cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,224&resp);225if (ret)226return ret;227228debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", id->cpu, resp);229230*cp_state = resp & BIT(16);231*cp_cap = resp & BIT(0) ? 1 : 0;232233return 0;234}235236static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)237{238unsigned int resp;239int ret;240241ret = _send_mbox_command(id->cpu, CONFIG_TDP,242CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);243if (ret) {244pkg_dev->levels = 0;245pkg_dev->locked = 1;246pkg_dev->current_level = 0;247pkg_dev->version = 0;248pkg_dev->enabled = 0;249return 0;250}251252debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);253254pkg_dev->version = resp & 0xff;255pkg_dev->levels = (resp >> 8) & 0xff;256pkg_dev->current_level = (resp >> 16) & 0xff;257pkg_dev->locked = !!(resp & BIT(24));258pkg_dev->enabled = !!(resp & BIT(31));259260return 0;261}262263static int mbox_get_ctdp_control(struct isst_id *id, int config_index,264struct isst_pkg_ctdp_level_info *ctdp_level)265{266int cp_state, cp_cap;267unsigned int resp;268int ret;269270ret = _send_mbox_command(id->cpu, CONFIG_TDP,271CONFIG_TDP_GET_TDP_CONTROL, 0,272config_index, &resp);273if (ret)274return ret;275276ctdp_level->fact_support = resp & BIT(0);277ctdp_level->pbf_support = !!(resp & BIT(1));278ctdp_level->fact_enabled = !!(resp & BIT(16));279ctdp_level->pbf_enabled = !!(resp & BIT(17));280281ret = isst_read_pm_config(id, &cp_state, &cp_cap);282if (ret) {283debug_printf("cpu:%d pm_config is not supported\n", id->cpu);284} else {285debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);286ctdp_level->sst_cp_support = cp_cap;287ctdp_level->sst_cp_enabled = cp_state;288}289290debug_printf(291"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",292id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,293ctdp_level->fact_enabled, ctdp_level->pbf_enabled);294295return 0;296}297298static void _get_uncore_p0_p1_info(struct isst_id *id, int config_index,299struct isst_pkg_ctdp_level_info *ctdp_level)300{301unsigned int resp;302int ret;303304ctdp_level->uncore_pm = 0;305ctdp_level->uncore_p0 = 0;306ctdp_level->uncore_p1 = 0;307308ret = _send_mbox_command(id->cpu, CONFIG_TDP,309CONFIG_TDP_GET_RATIO_INFO, 0,310(BIT(16) | config_index) , &resp);311if (ret) {312goto try_uncore_mbox;313}314315ctdp_level->uncore_p0 = resp & GENMASK(7, 0);316ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;317ctdp_level->uncore_pm = (resp & GENMASK(31, 24)) >> 24;318319debug_printf(320"cpu:%d ctdp:%d CONFIG_TDP_GET_RATIO_INFO resp:%x uncore p0:%d uncore p1:%d uncore pm:%d\n",321id->cpu, config_index, resp, ctdp_level->uncore_p0, ctdp_level->uncore_p1,322ctdp_level->uncore_pm);323324return;325326try_uncore_mbox:327ret = _send_mbox_command(id->cpu, CONFIG_TDP,328CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,329config_index, &resp);330if (ret) {331ctdp_level->uncore_p0 = 0;332ctdp_level->uncore_p1 = 0;333return;334}335336ctdp_level->uncore_p0 = resp & GENMASK(7, 0);337ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;338debug_printf(339"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",340id->cpu, config_index, resp, ctdp_level->uncore_p0,341ctdp_level->uncore_p1);342}343344static int _set_uncore_min_max(struct isst_id *id, int max, int freq)345{346char buffer[128], freq_str[16];347int fd, ret, len;348349if (max)350snprintf(buffer, sizeof(buffer),351"/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/max_freq_khz", id->pkg, id->die);352else353snprintf(buffer, sizeof(buffer),354"/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/min_freq_khz", id->pkg, id->die);355356fd = open(buffer, O_WRONLY);357if (fd < 0)358return fd;359360snprintf(freq_str, sizeof(freq_str), "%d", freq);361len = strlen(freq_str);362ret = write(fd, freq_str, len);363if (ret == -1) {364close(fd);365return ret;366}367close(fd);368369return 0;370}371372static void mbox_adjust_uncore_freq(struct isst_id *id, int config_index,373struct isst_pkg_ctdp_level_info *ctdp_level)374{375_get_uncore_p0_p1_info(id, config_index, ctdp_level);376if (ctdp_level->uncore_pm)377_set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);378379if (ctdp_level->uncore_p0)380_set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);381}382383static void _get_p1_info(struct isst_id *id, int config_index,384struct isst_pkg_ctdp_level_info *ctdp_level)385{386unsigned int resp;387int ret;388ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,389config_index, &resp);390if (ret) {391ctdp_level->sse_p1 = 0;392ctdp_level->avx2_p1 = 0;393ctdp_level->avx512_p1 = 0;394return;395}396397ctdp_level->sse_p1 = resp & GENMASK(7, 0);398ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;399ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;400ctdp_level->amx_p1 = (resp & GENMASK(31, 24)) >> 24;401debug_printf(402"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d amx_p1:%d\n",403id->cpu, config_index, resp, ctdp_level->sse_p1,404ctdp_level->avx2_p1, ctdp_level->avx512_p1, ctdp_level->amx_p1);405}406407static void _get_uncore_mem_freq(struct isst_id *id, int config_index,408struct isst_pkg_ctdp_level_info *ctdp_level)409{410unsigned int resp;411int ret;412413ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,4140, config_index, &resp);415if (ret) {416ctdp_level->mem_freq = 0;417return;418}419420ctdp_level->mem_freq = resp & GENMASK(7, 0);421if (is_spr_platform() || is_emr_platform()) {422ctdp_level->mem_freq *= 200;423} else if (is_icx_platform()) {424if (ctdp_level->mem_freq < 7) {425ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;426ctdp_level->mem_freq /= 10;427if (ctdp_level->mem_freq % 10 > 5)428ctdp_level->mem_freq++;429} else {430ctdp_level->mem_freq = 0;431}432} else {433ctdp_level->mem_freq = 0;434}435debug_printf(436"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",437id->cpu, config_index, resp, ctdp_level->mem_freq);438}439440static int mbox_get_tdp_info(struct isst_id *id, int config_index,441struct isst_pkg_ctdp_level_info *ctdp_level)442{443unsigned int resp;444int ret;445446ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,4470, config_index, &resp);448if (ret) {449isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);450return ret;451}452453ctdp_level->pkg_tdp = resp & GENMASK(14, 0);454ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;455456debug_printf(457"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",458id->cpu, config_index, resp, ctdp_level->tdp_ratio,459ctdp_level->pkg_tdp);460461ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,4620, config_index, &resp);463if (ret)464return ret;465466ctdp_level->t_proc_hot = resp & GENMASK(7, 0);467468_get_uncore_p0_p1_info(id, config_index, ctdp_level);469_get_p1_info(id, config_index, ctdp_level);470_get_uncore_mem_freq(id, config_index, ctdp_level);471472debug_printf(473"cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",474id->cpu, config_index, resp, ctdp_level->t_proc_hot);475476return 0;477}478479static int mbox_get_pwr_info(struct isst_id *id, int config_index,480struct isst_pkg_ctdp_level_info *ctdp_level)481{482unsigned int resp;483int ret;484485ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,4860, config_index, &resp);487if (ret)488return ret;489490ctdp_level->pkg_max_power = resp & GENMASK(14, 0);491ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;492493debug_printf(494"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",495id->cpu, config_index, resp, ctdp_level->pkg_max_power,496ctdp_level->pkg_min_power);497498return 0;499}500501static int mbox_get_coremask_info(struct isst_id *id, int config_index,502struct isst_pkg_ctdp_level_info *ctdp_level)503{504unsigned int resp;505int i, ret;506507ctdp_level->cpu_count = 0;508for (i = 0; i < 2; ++i) {509unsigned long long mask;510int cpu_count = 0;511512ret = _send_mbox_command(id->cpu, CONFIG_TDP,513CONFIG_TDP_GET_CORE_MASK, 0,514(i << 8) | config_index, &resp);515if (ret)516return ret;517518debug_printf(519"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",520id->cpu, config_index, i, resp);521522mask = (unsigned long long)resp << (32 * i);523set_cpu_mask_from_punit_coremask(id, mask,524ctdp_level->core_cpumask_size,525ctdp_level->core_cpumask,526&cpu_count);527ctdp_level->cpu_count += cpu_count;528debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,529config_index, i, ctdp_level->cpu_count);530}531532return 0;533}534535static int mbox_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)536{537unsigned int req, resp;538int ret;539540req = level | (avx_level << 16);541ret = _send_mbox_command(id->cpu, CONFIG_TDP,542CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,543&resp);544if (ret)545return ret;546547debug_printf(548"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",549id->cpu, req, resp);550551trl[0] = resp & GENMASK(7, 0);552trl[1] = (resp & GENMASK(15, 8)) >> 8;553trl[2] = (resp & GENMASK(23, 16)) >> 16;554trl[3] = (resp & GENMASK(31, 24)) >> 24;555556req = level | BIT(8) | (avx_level << 16);557ret = _send_mbox_command(id->cpu, CONFIG_TDP,558CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,559&resp);560if (ret)561return ret;562563debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,564req, resp);565566trl[4] = resp & GENMASK(7, 0);567trl[5] = (resp & GENMASK(15, 8)) >> 8;568trl[6] = (resp & GENMASK(23, 16)) >> 16;569trl[7] = (resp & GENMASK(31, 24)) >> 24;570571return 0;572}573574static int mbox_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)575{576int trl_max_levels = isst_get_trl_max_levels();577int i, ret;578579for (i = 0; i < trl_max_levels; i++) {580ret = mbox_get_get_trl(id, level, i, ctdp_level->trl_ratios[i]);581if (ret)582return ret;583}584return 0;585}586587static int mbox_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)588{589int ret;590591debug_printf("cpu:%d bucket info via MSR\n", id->cpu);592593*buckets_info = 0;594595ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info);596if (ret)597return ret;598599debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,600*buckets_info);601602return 0;603}604605static int mbox_set_tdp_level(struct isst_id *id, int tdp_level)606{607unsigned int resp;608int ret;609610611if (isst_get_config_tdp_lock_status(id)) {612isst_display_error_info_message(1, "TDP is locked", 0, 0);613return -1;614615}616617ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,618tdp_level, &resp);619if (ret) {620isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);621return ret;622}623624return 0;625}626627static int mbox_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)628{629int max_punit_core, max_mask_index;630unsigned int req, resp;631int i, ret;632633max_punit_core = get_max_punit_core_id(id);634max_mask_index = max_punit_core > 32 ? 2 : 1;635636for (i = 0; i < max_mask_index; ++i) {637unsigned long long mask;638int count;639640ret = _send_mbox_command(id->cpu, CONFIG_TDP,641CONFIG_TDP_PBF_GET_CORE_MASK_INFO,6420, (i << 8) | level, &resp);643if (ret)644break;645646debug_printf(647"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",648id->cpu, resp);649650mask = (unsigned long long)resp << (32 * i);651set_cpu_mask_from_punit_coremask(id, mask,652pbf_info->core_cpumask_size,653pbf_info->core_cpumask,654&count);655}656657req = level;658ret = _send_mbox_command(id->cpu, CONFIG_TDP,659CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,660&resp);661if (ret)662return ret;663664debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,665resp);666667pbf_info->p1_low = resp & 0xff;668pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;669670req = level;671ret = _send_mbox_command(672id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);673if (ret)674return ret;675676debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp);677678pbf_info->tdp = resp & 0xffff;679680req = level;681ret = _send_mbox_command(682id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);683if (ret)684return ret;685686debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu,687resp);688pbf_info->t_control = (resp >> 8) & 0xff;689pbf_info->t_prochot = resp & 0xff;690691return 0;692}693694static int mbox_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)695{696struct isst_pkg_ctdp pkg_dev;697struct isst_pkg_ctdp_level_info ctdp_level;698int current_level;699unsigned int req = 0, resp;700int ret;701702ret = isst_get_ctdp_levels(id, &pkg_dev);703if (ret)704debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);705706current_level = pkg_dev.current_level;707708ret = isst_get_ctdp_control(id, current_level, &ctdp_level);709if (ret)710return ret;711712if (pbf) {713if (ctdp_level.fact_enabled)714req = BIT(16);715716if (enable)717req |= BIT(17);718else719req &= ~BIT(17);720} else {721722if (enable && !ctdp_level.sst_cp_enabled)723isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);724725if (ctdp_level.pbf_enabled)726req = BIT(17);727728if (enable)729req |= BIT(16);730else731req &= ~BIT(16);732}733734ret = _send_mbox_command(id->cpu, CONFIG_TDP,735CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);736if (ret)737return ret;738739debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",740id->cpu, pbf, req);741742return 0;743}744745static int _get_fact_bucket_info(struct isst_id *id, int level,746struct isst_fact_bucket_info *bucket_info)747{748int trl_max_levels = isst_get_trl_max_levels();749unsigned int resp;750int i, k, ret;751752for (i = 0; i < 2; ++i) {753int j;754755ret = _send_mbox_command(756id->cpu, CONFIG_TDP,757CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,758(i << 8) | level, &resp);759if (ret)760return ret;761762debug_printf(763"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",764id->cpu, i, level, resp);765766for (j = 0; j < 4; ++j) {767bucket_info[j + (i * 4)].hp_cores =768(resp >> (j * 8)) & 0xff;769}770}771772for (k = 0; k < trl_max_levels; ++k) {773for (i = 0; i < 2; ++i) {774int j;775776ret = _send_mbox_command(777id->cpu, CONFIG_TDP,778CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,779(k << 16) | (i << 8) | level, &resp);780if (ret)781return ret;782783debug_printf(784"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",785id->cpu, i, level, k, resp);786787for (j = 0; j < 4; ++j) {788bucket_info[j + (i * 4)].hp_ratios[k] =789(resp >> (j * 8)) & 0xff;790}791}792}793794return 0;795}796797static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)798{799unsigned int resp;800int j, ret, print;801802ret = _send_mbox_command(id->cpu, CONFIG_TDP,803CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,804level, &resp);805if (ret)806return ret;807808debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",809id->cpu, resp);810811fact_info->lp_ratios[0] = resp & 0xff;812fact_info->lp_ratios[1] = (resp >> 8) & 0xff;813fact_info->lp_ratios[2] = (resp >> 16) & 0xff;814815ret = _get_fact_bucket_info(id, level, fact_info->bucket_info);816if (ret)817return ret;818819print = 0;820for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {821if (fact_bucket != 0xff && fact_bucket != j)822continue;823824if (!fact_info->bucket_info[j].hp_cores)825break;826827print = 1;828}829if (!print) {830isst_display_error_info_message(1, "Invalid bucket", 0, 0);831return -1;832}833834return 0;835}836837static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type)838{839unsigned int resp;840int ret;841842ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,843&resp);844if (ret)845return ret;846847debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);848849if (resp & BIT(1))850*enable = 1;851else852*enable = 0;853854if (resp & BIT(2))855*type = 1;856else857*type = 0;858859return 0;860}861862static int _write_pm_config(struct isst_id *id, int cp_state)863{864unsigned int req, resp;865int ret;866867if (cp_state)868req = BIT(16);869else870req = 0;871872ret = _send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,873&resp);874if (ret)875return ret;876877debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);878879return 0;880}881882static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)883{884unsigned int req, resp;885int ret;886887if (!enable_clos) {888struct isst_pkg_ctdp pkg_dev;889struct isst_pkg_ctdp_level_info ctdp_level;890891ret = isst_get_ctdp_levels(id, &pkg_dev);892if (ret) {893debug_printf("isst_get_ctdp_levels\n");894return ret;895}896897ret = isst_get_ctdp_control(id, pkg_dev.current_level,898&ctdp_level);899if (ret)900return ret;901902if (ctdp_level.fact_enabled) {903isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);904return -EINVAL;905}906ret = _write_pm_config(id, 0);907if (ret)908isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);909} else {910ret = _write_pm_config(id, 1);911if (ret)912isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);913}914915ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,916&resp);917if (ret) {918isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);919return ret;920}921922debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);923924req = resp;925926if (enable_clos)927req = req | BIT(1);928else929req = req & ~BIT(1);930931if (priority_type > 1)932isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);933934if (priority_type)935req = req | BIT(2);936else937req = req & ~BIT(2);938939ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,940BIT(MBOX_CMD_WRITE_BIT), req, &resp);941if (ret)942return ret;943944debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,945priority_type, req);946947return 0;948}949950static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)951{952unsigned int resp;953int ret;954955ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,956&resp);957if (ret)958return ret;959960clos_config->epp = resp & 0x0f;961clos_config->clos_prop_prio = (resp >> 4) & 0x0f;962clos_config->clos_min = (resp >> 8) & 0xff;963clos_config->clos_max = (resp >> 16) & 0xff;964clos_config->clos_desired = (resp >> 24) & 0xff;965966return 0;967}968969static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)970{971unsigned int req, resp;972unsigned int param;973int ret;974975req = clos_config->epp & 0x0f;976req |= (clos_config->clos_prop_prio & 0x0f) << 4;977req |= (clos_config->clos_min & 0xff) << 8;978req |= (clos_config->clos_max & 0xff) << 16;979req |= (clos_config->clos_desired & 0xff) << 24;980981param = BIT(MBOX_CMD_WRITE_BIT) | clos;982983ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,984&resp);985if (ret)986return ret;987988debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);989990return 0;991}992993static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id)994{995unsigned int resp;996unsigned int param;997int core_id, ret;998999core_id = find_phy_core_num(id->cpu);1000param = core_id;10011002ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,1003&resp);1004if (ret)1005return ret;10061007debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,1008resp);1009*clos_id = (resp >> 16) & 0x03;10101011return 0;1012}10131014static int mbox_clos_associate(struct isst_id *id, int clos_id)1015{1016unsigned int req, resp;1017unsigned int param;1018int core_id, ret;10191020req = (clos_id & 0x03) << 16;1021core_id = find_phy_core_num(id->cpu);1022param = BIT(MBOX_CMD_WRITE_BIT) | core_id;10231024ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,1025req, &resp);1026if (ret)1027return ret;10281029debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,1030req);10311032return 0;1033}10341035static struct isst_platform_ops mbox_ops = {1036.get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,1037.get_trl_max_levels = mbox_get_trl_max_levels,1038.get_trl_level_name = mbox_get_trl_level_name,1039.update_platform_param = mbox_update_platform_param,1040.is_punit_valid = mbox_is_punit_valid,1041.read_pm_config = mbox_read_pm_config,1042.get_config_levels = mbox_get_config_levels,1043.get_ctdp_control = mbox_get_ctdp_control,1044.get_tdp_info = mbox_get_tdp_info,1045.get_pwr_info = mbox_get_pwr_info,1046.get_coremask_info = mbox_get_coremask_info,1047.get_get_trl = mbox_get_get_trl,1048.get_get_trls = mbox_get_get_trls,1049.get_trl_bucket_info = mbox_get_trl_bucket_info,1050.set_tdp_level = mbox_set_tdp_level,1051.get_pbf_info = mbox_get_pbf_info,1052.set_pbf_fact_status = mbox_set_pbf_fact_status,1053.get_fact_info = mbox_get_fact_info,1054.adjust_uncore_freq = mbox_adjust_uncore_freq,1055.get_clos_information = mbox_get_clos_information,1056.pm_qos_config = mbox_pm_qos_config,1057.pm_get_clos = mbox_pm_get_clos,1058.set_clos = mbox_set_clos,1059.clos_get_assoc_status = mbox_clos_get_assoc_status,1060.clos_associate = mbox_clos_associate,1061};10621063struct isst_platform_ops *mbox_get_platform_ops(void)1064{1065return &mbox_ops;1066}106710681069