1d0d1a603SZhang Rui // SPDX-License-Identifier: GPL-2.0
2d0d1a603SZhang Rui /*
3d0d1a603SZhang Rui * Intel Speed Select -- Enumerate and control features for Mailbox Interface
4d0d1a603SZhang Rui * Copyright (c) 2023 Intel Corporation.
5d0d1a603SZhang Rui */
6d0d1a603SZhang Rui #include "isst.h"
7d0d1a603SZhang Rui
82b86ed22SZhang Rui static int mbox_delay;
92b86ed22SZhang Rui static int mbox_retries = 3;
102b86ed22SZhang Rui
11*2c00056fSSrinivas Pandruvada #define MAX_TRL_LEVELS_EMR 5
12*2c00056fSSrinivas Pandruvada
mbox_get_disp_freq_multiplier(void)13d0d1a603SZhang Rui static int mbox_get_disp_freq_multiplier(void)
14d0d1a603SZhang Rui {
15d0d1a603SZhang Rui return DISP_FREQ_MULTIPLIER;
16d0d1a603SZhang Rui }
17d0d1a603SZhang Rui
mbox_get_trl_max_levels(void)18d0d1a603SZhang Rui static int mbox_get_trl_max_levels(void)
19d0d1a603SZhang Rui {
20*2c00056fSSrinivas Pandruvada if (is_emr_platform())
21*2c00056fSSrinivas Pandruvada return MAX_TRL_LEVELS_EMR;
22*2c00056fSSrinivas Pandruvada
23d0d1a603SZhang Rui return 3;
24d0d1a603SZhang Rui }
25d0d1a603SZhang Rui
mbox_get_trl_level_name(int level)26d0d1a603SZhang Rui static char *mbox_get_trl_level_name(int level)
27d0d1a603SZhang Rui {
28*2c00056fSSrinivas Pandruvada if (is_emr_platform()) {
29*2c00056fSSrinivas Pandruvada static char level_str[18];
30*2c00056fSSrinivas Pandruvada
31*2c00056fSSrinivas Pandruvada if (level >= MAX_TRL_LEVELS_EMR)
32*2c00056fSSrinivas Pandruvada return NULL;
33*2c00056fSSrinivas Pandruvada
34*2c00056fSSrinivas Pandruvada snprintf(level_str, sizeof(level_str), "level-%d", level);
35*2c00056fSSrinivas Pandruvada return level_str;
36*2c00056fSSrinivas Pandruvada }
37*2c00056fSSrinivas Pandruvada
38d0d1a603SZhang Rui switch (level) {
39d0d1a603SZhang Rui case 0:
40d0d1a603SZhang Rui return "sse";
41d0d1a603SZhang Rui case 1:
42d0d1a603SZhang Rui return "avx2";
43d0d1a603SZhang Rui case 2:
44d0d1a603SZhang Rui return "avx512";
45d0d1a603SZhang Rui default:
46d0d1a603SZhang Rui return NULL;
47d0d1a603SZhang Rui }
48d0d1a603SZhang Rui }
49d0d1a603SZhang Rui
mbox_update_platform_param(enum isst_platform_param param,int value)502b86ed22SZhang Rui static void mbox_update_platform_param(enum isst_platform_param param, int value)
512b86ed22SZhang Rui {
522b86ed22SZhang Rui switch (param) {
532b86ed22SZhang Rui case ISST_PARAM_MBOX_DELAY:
542b86ed22SZhang Rui mbox_delay = value;
552b86ed22SZhang Rui break;
562b86ed22SZhang Rui case ISST_PARAM_MBOX_RETRIES:
572b86ed22SZhang Rui mbox_retries = value;
582b86ed22SZhang Rui break;
592b86ed22SZhang Rui default:
602b86ed22SZhang Rui break;
612b86ed22SZhang Rui }
622b86ed22SZhang Rui }
632b86ed22SZhang Rui
mbox_is_punit_valid(struct isst_id * id)64143584e8SZhang Rui static int mbox_is_punit_valid(struct isst_id *id)
65143584e8SZhang Rui {
66143584e8SZhang Rui if (id->cpu < 0)
67143584e8SZhang Rui return 0;
68d0d1a603SZhang Rui
69143584e8SZhang Rui if (id->pkg < 0 || id->die < 0 || id->punit)
70143584e8SZhang Rui return 0;
71143584e8SZhang Rui
72143584e8SZhang Rui return 1;
73143584e8SZhang Rui }
74d0d1a603SZhang Rui
_send_mmio_command(unsigned int cpu,unsigned int reg,int write,unsigned int * value)752b86ed22SZhang Rui static int _send_mmio_command(unsigned int cpu, unsigned int reg, int write,
762b86ed22SZhang Rui unsigned int *value)
772b86ed22SZhang Rui {
782b86ed22SZhang Rui struct isst_if_io_regs io_regs;
792b86ed22SZhang Rui const char *pathname = "/dev/isst_interface";
802b86ed22SZhang Rui int cmd;
812b86ed22SZhang Rui FILE *outf = get_output_file();
822b86ed22SZhang Rui int fd;
832b86ed22SZhang Rui
842b86ed22SZhang Rui debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
852b86ed22SZhang Rui
862b86ed22SZhang Rui fd = open(pathname, O_RDWR);
872b86ed22SZhang Rui if (fd < 0)
882b86ed22SZhang Rui err(-1, "%s open failed", pathname);
892b86ed22SZhang Rui
902b86ed22SZhang Rui io_regs.req_count = 1;
912b86ed22SZhang Rui io_regs.io_reg[0].logical_cpu = cpu;
922b86ed22SZhang Rui io_regs.io_reg[0].reg = reg;
932b86ed22SZhang Rui cmd = ISST_IF_IO_CMD;
942b86ed22SZhang Rui if (write) {
952b86ed22SZhang Rui io_regs.io_reg[0].read_write = 1;
962b86ed22SZhang Rui io_regs.io_reg[0].value = *value;
972b86ed22SZhang Rui } else {
982b86ed22SZhang Rui io_regs.io_reg[0].read_write = 0;
992b86ed22SZhang Rui }
1002b86ed22SZhang Rui
1012b86ed22SZhang Rui if (ioctl(fd, cmd, &io_regs) == -1) {
1022b86ed22SZhang Rui if (errno == ENOTTY) {
1032b86ed22SZhang Rui perror("ISST_IF_IO_COMMAND\n");
1042b86ed22SZhang Rui fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
1052b86ed22SZhang Rui exit(0);
1062b86ed22SZhang Rui }
1072b86ed22SZhang Rui fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
1082b86ed22SZhang Rui cpu, reg, write);
1092b86ed22SZhang Rui } else {
1102b86ed22SZhang Rui if (!write)
1112b86ed22SZhang Rui *value = io_regs.io_reg[0].value;
1122b86ed22SZhang Rui
1132b86ed22SZhang Rui debug_printf(
1142b86ed22SZhang Rui "mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
1152b86ed22SZhang Rui cpu, reg, write, *value);
1162b86ed22SZhang Rui }
1172b86ed22SZhang Rui
1182b86ed22SZhang Rui close(fd);
1192b86ed22SZhang Rui
1202b86ed22SZhang Rui return 0;
1212b86ed22SZhang Rui }
1222b86ed22SZhang Rui
_send_mbox_command(unsigned int cpu,unsigned char command,unsigned char sub_command,unsigned int parameter,unsigned int req_data,unsigned int * resp)1232b86ed22SZhang Rui int _send_mbox_command(unsigned int cpu, unsigned char command,
1242b86ed22SZhang Rui unsigned char sub_command, unsigned int parameter,
1252b86ed22SZhang Rui unsigned int req_data, unsigned int *resp)
1262b86ed22SZhang Rui {
1272b86ed22SZhang Rui const char *pathname = "/dev/isst_interface";
1282b86ed22SZhang Rui int fd, retry;
1292b86ed22SZhang Rui struct isst_if_mbox_cmds mbox_cmds = { 0 };
1302b86ed22SZhang Rui
1312b86ed22SZhang Rui debug_printf(
1322b86ed22SZhang Rui "mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
1332b86ed22SZhang Rui cpu, command, sub_command, parameter, req_data);
1342b86ed22SZhang Rui
1352b86ed22SZhang Rui if (!is_skx_based_platform() && command == CONFIG_CLOS &&
1362b86ed22SZhang Rui sub_command != CLOS_PM_QOS_CONFIG) {
1372b86ed22SZhang Rui unsigned int value;
1382b86ed22SZhang Rui int write = 0;
1392b86ed22SZhang Rui int clos_id, core_id, ret = 0;
1402b86ed22SZhang Rui
1412b86ed22SZhang Rui debug_printf("CPU %d\n", cpu);
1422b86ed22SZhang Rui
1432b86ed22SZhang Rui if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
1442b86ed22SZhang Rui value = req_data;
1452b86ed22SZhang Rui write = 1;
1462b86ed22SZhang Rui }
1472b86ed22SZhang Rui
1482b86ed22SZhang Rui switch (sub_command) {
1492b86ed22SZhang Rui case CLOS_PQR_ASSOC:
1502b86ed22SZhang Rui core_id = parameter & 0xff;
1512b86ed22SZhang Rui ret = _send_mmio_command(
1522b86ed22SZhang Rui cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
1532b86ed22SZhang Rui &value);
1542b86ed22SZhang Rui if (!ret && !write)
1552b86ed22SZhang Rui *resp = value;
1562b86ed22SZhang Rui break;
1572b86ed22SZhang Rui case CLOS_PM_CLOS:
1582b86ed22SZhang Rui clos_id = parameter & 0x03;
1592b86ed22SZhang Rui ret = _send_mmio_command(
1602b86ed22SZhang Rui cpu, PM_CLOS_OFFSET + clos_id * 4, write,
1612b86ed22SZhang Rui &value);
1622b86ed22SZhang Rui if (!ret && !write)
1632b86ed22SZhang Rui *resp = value;
1642b86ed22SZhang Rui break;
1652b86ed22SZhang Rui case CLOS_STATUS:
1662b86ed22SZhang Rui break;
1672b86ed22SZhang Rui default:
1682b86ed22SZhang Rui break;
1692b86ed22SZhang Rui }
1702b86ed22SZhang Rui return ret;
1712b86ed22SZhang Rui }
1722b86ed22SZhang Rui
1732b86ed22SZhang Rui mbox_cmds.cmd_count = 1;
1742b86ed22SZhang Rui mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
1752b86ed22SZhang Rui mbox_cmds.mbox_cmd[0].command = command;
1762b86ed22SZhang Rui mbox_cmds.mbox_cmd[0].sub_command = sub_command;
1772b86ed22SZhang Rui mbox_cmds.mbox_cmd[0].parameter = parameter;
1782b86ed22SZhang Rui mbox_cmds.mbox_cmd[0].req_data = req_data;
1792b86ed22SZhang Rui
1802b86ed22SZhang Rui if (mbox_delay)
1812b86ed22SZhang Rui usleep(mbox_delay * 1000);
1822b86ed22SZhang Rui
1832b86ed22SZhang Rui fd = open(pathname, O_RDWR);
1842b86ed22SZhang Rui if (fd < 0)
1852b86ed22SZhang Rui err(-1, "%s open failed", pathname);
1862b86ed22SZhang Rui
1872b86ed22SZhang Rui retry = mbox_retries;
1882b86ed22SZhang Rui do {
1892b86ed22SZhang Rui if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
1902b86ed22SZhang Rui if (errno == ENOTTY) {
1912b86ed22SZhang Rui perror("ISST_IF_MBOX_COMMAND\n");
1922b86ed22SZhang Rui fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
1932b86ed22SZhang Rui exit(0);
1942b86ed22SZhang Rui }
1952b86ed22SZhang Rui debug_printf(
1962b86ed22SZhang Rui "Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
1972b86ed22SZhang Rui cpu, command, sub_command, parameter, req_data, errno);
1982b86ed22SZhang Rui --retry;
1992b86ed22SZhang Rui } else {
2002b86ed22SZhang Rui *resp = mbox_cmds.mbox_cmd[0].resp_data;
2012b86ed22SZhang Rui debug_printf(
2022b86ed22SZhang Rui "mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
2032b86ed22SZhang Rui cpu, command, sub_command, parameter, req_data, *resp);
2042b86ed22SZhang Rui break;
2052b86ed22SZhang Rui }
2062b86ed22SZhang Rui } while (retry);
2072b86ed22SZhang Rui
2082b86ed22SZhang Rui close(fd);
2092b86ed22SZhang Rui
2102b86ed22SZhang Rui if (!retry) {
2112b86ed22SZhang Rui debug_printf("Failed mbox command even after retries\n");
2122b86ed22SZhang Rui return -1;
2132b86ed22SZhang Rui
2142b86ed22SZhang Rui }
2152b86ed22SZhang Rui
2162b86ed22SZhang Rui return 0;
2172b86ed22SZhang Rui }
2182b86ed22SZhang Rui
mbox_read_pm_config(struct isst_id * id,int * cp_state,int * cp_cap)2198f54104fSZhang Rui static int mbox_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
2208f54104fSZhang Rui {
2218f54104fSZhang Rui unsigned int resp;
2228f54104fSZhang Rui int ret;
2238f54104fSZhang Rui
2242b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
2258f54104fSZhang Rui &resp);
2268f54104fSZhang Rui if (ret)
2278f54104fSZhang Rui return ret;
2288f54104fSZhang Rui
2298f54104fSZhang Rui debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", id->cpu, resp);
2308f54104fSZhang Rui
2318f54104fSZhang Rui *cp_state = resp & BIT(16);
2328f54104fSZhang Rui *cp_cap = resp & BIT(0) ? 1 : 0;
2338f54104fSZhang Rui
2348f54104fSZhang Rui return 0;
2358f54104fSZhang Rui }
2368f54104fSZhang Rui
mbox_get_config_levels(struct isst_id * id,struct isst_pkg_ctdp * pkg_dev)23772438744SZhang Rui static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
23872438744SZhang Rui {
23972438744SZhang Rui unsigned int resp;
24072438744SZhang Rui int ret;
24172438744SZhang Rui
2422b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
24372438744SZhang Rui CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
24472438744SZhang Rui if (ret) {
24572438744SZhang Rui pkg_dev->levels = 0;
24672438744SZhang Rui pkg_dev->locked = 1;
24772438744SZhang Rui pkg_dev->current_level = 0;
24872438744SZhang Rui pkg_dev->version = 0;
24972438744SZhang Rui pkg_dev->enabled = 0;
25072438744SZhang Rui return 0;
25172438744SZhang Rui }
25272438744SZhang Rui
25372438744SZhang Rui debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);
25472438744SZhang Rui
25572438744SZhang Rui pkg_dev->version = resp & 0xff;
25672438744SZhang Rui pkg_dev->levels = (resp >> 8) & 0xff;
25772438744SZhang Rui pkg_dev->current_level = (resp >> 16) & 0xff;
25872438744SZhang Rui pkg_dev->locked = !!(resp & BIT(24));
25972438744SZhang Rui pkg_dev->enabled = !!(resp & BIT(31));
26072438744SZhang Rui
26172438744SZhang Rui return 0;
26272438744SZhang Rui }
26372438744SZhang Rui
mbox_get_ctdp_control(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)264bbe32d87SZhang Rui static int mbox_get_ctdp_control(struct isst_id *id, int config_index,
265bbe32d87SZhang Rui struct isst_pkg_ctdp_level_info *ctdp_level)
266bbe32d87SZhang Rui {
267bbe32d87SZhang Rui int cp_state, cp_cap;
268bbe32d87SZhang Rui unsigned int resp;
269bbe32d87SZhang Rui int ret;
270bbe32d87SZhang Rui
2712b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
272bbe32d87SZhang Rui CONFIG_TDP_GET_TDP_CONTROL, 0,
273bbe32d87SZhang Rui config_index, &resp);
274bbe32d87SZhang Rui if (ret)
275bbe32d87SZhang Rui return ret;
276bbe32d87SZhang Rui
277bbe32d87SZhang Rui ctdp_level->fact_support = resp & BIT(0);
278bbe32d87SZhang Rui ctdp_level->pbf_support = !!(resp & BIT(1));
279bbe32d87SZhang Rui ctdp_level->fact_enabled = !!(resp & BIT(16));
280bbe32d87SZhang Rui ctdp_level->pbf_enabled = !!(resp & BIT(17));
281bbe32d87SZhang Rui
282bbe32d87SZhang Rui ret = isst_read_pm_config(id, &cp_state, &cp_cap);
283bbe32d87SZhang Rui if (ret) {
284bbe32d87SZhang Rui debug_printf("cpu:%d pm_config is not supported\n", id->cpu);
285bbe32d87SZhang Rui } else {
286bbe32d87SZhang Rui debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);
287bbe32d87SZhang Rui ctdp_level->sst_cp_support = cp_cap;
288bbe32d87SZhang Rui ctdp_level->sst_cp_enabled = cp_state;
289bbe32d87SZhang Rui }
290bbe32d87SZhang Rui
291bbe32d87SZhang Rui debug_printf(
292bbe32d87SZhang Rui "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
293bbe32d87SZhang Rui id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
294bbe32d87SZhang Rui ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
295bbe32d87SZhang Rui
296bbe32d87SZhang Rui return 0;
297bbe32d87SZhang Rui }
298bbe32d87SZhang Rui
_get_uncore_p0_p1_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)29973452cccSZhang Rui static void _get_uncore_p0_p1_info(struct isst_id *id, int config_index,
30000c26c1fSZhang Rui struct isst_pkg_ctdp_level_info *ctdp_level)
30100c26c1fSZhang Rui {
30200c26c1fSZhang Rui unsigned int resp;
30300c26c1fSZhang Rui int ret;
30400c26c1fSZhang Rui
30500c26c1fSZhang Rui ctdp_level->uncore_pm = 0;
30600c26c1fSZhang Rui ctdp_level->uncore_p0 = 0;
30700c26c1fSZhang Rui ctdp_level->uncore_p1 = 0;
30800c26c1fSZhang Rui
3092b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
31000c26c1fSZhang Rui CONFIG_TDP_GET_RATIO_INFO, 0,
31100c26c1fSZhang Rui (BIT(16) | config_index) , &resp);
31200c26c1fSZhang Rui if (ret) {
31300c26c1fSZhang Rui goto try_uncore_mbox;
31400c26c1fSZhang Rui }
31500c26c1fSZhang Rui
31600c26c1fSZhang Rui ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
31700c26c1fSZhang Rui ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
31800c26c1fSZhang Rui ctdp_level->uncore_pm = (resp & GENMASK(31, 24)) >> 24;
31900c26c1fSZhang Rui
32000c26c1fSZhang Rui debug_printf(
32100c26c1fSZhang Rui "cpu:%d ctdp:%d CONFIG_TDP_GET_RATIO_INFO resp:%x uncore p0:%d uncore p1:%d uncore pm:%d\n",
32200c26c1fSZhang Rui id->cpu, config_index, resp, ctdp_level->uncore_p0, ctdp_level->uncore_p1,
32300c26c1fSZhang Rui ctdp_level->uncore_pm);
32400c26c1fSZhang Rui
32500c26c1fSZhang Rui return;
32600c26c1fSZhang Rui
32700c26c1fSZhang Rui try_uncore_mbox:
3282b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
32900c26c1fSZhang Rui CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
33000c26c1fSZhang Rui config_index, &resp);
33100c26c1fSZhang Rui if (ret) {
33200c26c1fSZhang Rui ctdp_level->uncore_p0 = 0;
33300c26c1fSZhang Rui ctdp_level->uncore_p1 = 0;
33400c26c1fSZhang Rui return;
33500c26c1fSZhang Rui }
33600c26c1fSZhang Rui
33700c26c1fSZhang Rui ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
33800c26c1fSZhang Rui ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
33900c26c1fSZhang Rui debug_printf(
34000c26c1fSZhang Rui "cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
34100c26c1fSZhang Rui id->cpu, config_index, resp, ctdp_level->uncore_p0,
34200c26c1fSZhang Rui ctdp_level->uncore_p1);
34300c26c1fSZhang Rui }
34400c26c1fSZhang Rui
_set_uncore_min_max(struct isst_id * id,int max,int freq)34573452cccSZhang Rui static int _set_uncore_min_max(struct isst_id *id, int max, int freq)
34673452cccSZhang Rui {
34773452cccSZhang Rui char buffer[128], freq_str[16];
34873452cccSZhang Rui int fd, ret, len;
34973452cccSZhang Rui
35073452cccSZhang Rui if (max)
35173452cccSZhang Rui snprintf(buffer, sizeof(buffer),
35273452cccSZhang Rui "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/max_freq_khz", id->pkg, id->die);
35373452cccSZhang Rui else
35473452cccSZhang Rui snprintf(buffer, sizeof(buffer),
35573452cccSZhang Rui "/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/min_freq_khz", id->pkg, id->die);
35673452cccSZhang Rui
35773452cccSZhang Rui fd = open(buffer, O_WRONLY);
35873452cccSZhang Rui if (fd < 0)
35973452cccSZhang Rui return fd;
36073452cccSZhang Rui
36173452cccSZhang Rui snprintf(freq_str, sizeof(freq_str), "%d", freq);
36273452cccSZhang Rui len = strlen(freq_str);
36373452cccSZhang Rui ret = write(fd, freq_str, len);
36473452cccSZhang Rui if (ret == -1) {
36573452cccSZhang Rui close(fd);
36673452cccSZhang Rui return ret;
36773452cccSZhang Rui }
36873452cccSZhang Rui close(fd);
36973452cccSZhang Rui
37073452cccSZhang Rui return 0;
37173452cccSZhang Rui }
37273452cccSZhang Rui
mbox_adjust_uncore_freq(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)37373452cccSZhang Rui static void mbox_adjust_uncore_freq(struct isst_id *id, int config_index,
37473452cccSZhang Rui struct isst_pkg_ctdp_level_info *ctdp_level)
37573452cccSZhang Rui {
37673452cccSZhang Rui _get_uncore_p0_p1_info(id, config_index, ctdp_level);
37773452cccSZhang Rui if (ctdp_level->uncore_pm)
37873452cccSZhang Rui _set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
37973452cccSZhang Rui
38073452cccSZhang Rui if (ctdp_level->uncore_p0)
38173452cccSZhang Rui _set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
38273452cccSZhang Rui }
38373452cccSZhang Rui
_get_p1_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)38485593283SZhang Rui static void _get_p1_info(struct isst_id *id, int config_index,
38585593283SZhang Rui struct isst_pkg_ctdp_level_info *ctdp_level)
38685593283SZhang Rui {
38785593283SZhang Rui unsigned int resp;
38885593283SZhang Rui int ret;
3892b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
39085593283SZhang Rui config_index, &resp);
39185593283SZhang Rui if (ret) {
39285593283SZhang Rui ctdp_level->sse_p1 = 0;
39385593283SZhang Rui ctdp_level->avx2_p1 = 0;
39485593283SZhang Rui ctdp_level->avx512_p1 = 0;
39585593283SZhang Rui return;
39685593283SZhang Rui }
39785593283SZhang Rui
39885593283SZhang Rui ctdp_level->sse_p1 = resp & GENMASK(7, 0);
39985593283SZhang Rui ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
40085593283SZhang Rui ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
401a835ff56SSrinivas Pandruvada ctdp_level->amx_p1 = (resp & GENMASK(31, 24)) >> 24;
40285593283SZhang Rui debug_printf(
403a835ff56SSrinivas Pandruvada "cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d amx_p1:%d\n",
40485593283SZhang Rui id->cpu, config_index, resp, ctdp_level->sse_p1,
405a835ff56SSrinivas Pandruvada ctdp_level->avx2_p1, ctdp_level->avx512_p1, ctdp_level->amx_p1);
40685593283SZhang Rui }
40785593283SZhang Rui
_get_uncore_mem_freq(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)40885593283SZhang Rui static void _get_uncore_mem_freq(struct isst_id *id, int config_index,
40985593283SZhang Rui struct isst_pkg_ctdp_level_info *ctdp_level)
41085593283SZhang Rui {
41185593283SZhang Rui unsigned int resp;
41285593283SZhang Rui int ret;
41385593283SZhang Rui
4142b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
41585593283SZhang Rui 0, config_index, &resp);
41685593283SZhang Rui if (ret) {
41785593283SZhang Rui ctdp_level->mem_freq = 0;
41885593283SZhang Rui return;
41985593283SZhang Rui }
42085593283SZhang Rui
42185593283SZhang Rui ctdp_level->mem_freq = resp & GENMASK(7, 0);
4221d54b139SSrinivas Pandruvada if (is_spr_platform() || is_emr_platform()) {
42385593283SZhang Rui ctdp_level->mem_freq *= 200;
42485593283SZhang Rui } else if (is_icx_platform()) {
42585593283SZhang Rui if (ctdp_level->mem_freq < 7) {
42685593283SZhang Rui ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
42785593283SZhang Rui ctdp_level->mem_freq /= 10;
42885593283SZhang Rui if (ctdp_level->mem_freq % 10 > 5)
42985593283SZhang Rui ctdp_level->mem_freq++;
43085593283SZhang Rui } else {
43185593283SZhang Rui ctdp_level->mem_freq = 0;
43285593283SZhang Rui }
43385593283SZhang Rui } else {
43485593283SZhang Rui ctdp_level->mem_freq = 0;
43585593283SZhang Rui }
43685593283SZhang Rui debug_printf(
43785593283SZhang Rui "cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
43885593283SZhang Rui id->cpu, config_index, resp, ctdp_level->mem_freq);
43985593283SZhang Rui }
44085593283SZhang Rui
mbox_get_tdp_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)441645b6605SZhang Rui static int mbox_get_tdp_info(struct isst_id *id, int config_index,
442645b6605SZhang Rui struct isst_pkg_ctdp_level_info *ctdp_level)
443645b6605SZhang Rui {
444645b6605SZhang Rui unsigned int resp;
445645b6605SZhang Rui int ret;
446645b6605SZhang Rui
4472b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
448645b6605SZhang Rui 0, config_index, &resp);
449645b6605SZhang Rui if (ret) {
450645b6605SZhang Rui isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
451645b6605SZhang Rui return ret;
452645b6605SZhang Rui }
453645b6605SZhang Rui
454645b6605SZhang Rui ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
455645b6605SZhang Rui ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
456645b6605SZhang Rui
457645b6605SZhang Rui debug_printf(
458645b6605SZhang Rui "cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
459645b6605SZhang Rui id->cpu, config_index, resp, ctdp_level->tdp_ratio,
460645b6605SZhang Rui ctdp_level->pkg_tdp);
461a30cbd22SZhang Rui
4622b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
463a30cbd22SZhang Rui 0, config_index, &resp);
464a30cbd22SZhang Rui if (ret)
465a30cbd22SZhang Rui return ret;
466a30cbd22SZhang Rui
467a30cbd22SZhang Rui ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
468a30cbd22SZhang Rui
46973452cccSZhang Rui _get_uncore_p0_p1_info(id, config_index, ctdp_level);
47085593283SZhang Rui _get_p1_info(id, config_index, ctdp_level);
47185593283SZhang Rui _get_uncore_mem_freq(id, config_index, ctdp_level);
47285593283SZhang Rui
473a30cbd22SZhang Rui debug_printf(
474a30cbd22SZhang Rui "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
475a30cbd22SZhang Rui id->cpu, config_index, resp, ctdp_level->t_proc_hot);
476a30cbd22SZhang Rui
477645b6605SZhang Rui return 0;
478645b6605SZhang Rui }
479645b6605SZhang Rui
mbox_get_pwr_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)480e107dec9SZhang Rui static int mbox_get_pwr_info(struct isst_id *id, int config_index,
481e107dec9SZhang Rui struct isst_pkg_ctdp_level_info *ctdp_level)
482e107dec9SZhang Rui {
483e107dec9SZhang Rui unsigned int resp;
484e107dec9SZhang Rui int ret;
485e107dec9SZhang Rui
4862b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
487e107dec9SZhang Rui 0, config_index, &resp);
488e107dec9SZhang Rui if (ret)
489e107dec9SZhang Rui return ret;
490e107dec9SZhang Rui
491e107dec9SZhang Rui ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
492e107dec9SZhang Rui ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
493e107dec9SZhang Rui
494e107dec9SZhang Rui debug_printf(
495e107dec9SZhang Rui "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
496e107dec9SZhang Rui id->cpu, config_index, resp, ctdp_level->pkg_max_power,
497e107dec9SZhang Rui ctdp_level->pkg_min_power);
498e107dec9SZhang Rui
499e107dec9SZhang Rui return 0;
500e107dec9SZhang Rui }
501e107dec9SZhang Rui
mbox_get_coremask_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)502668cc16cSZhang Rui static int mbox_get_coremask_info(struct isst_id *id, int config_index,
503668cc16cSZhang Rui struct isst_pkg_ctdp_level_info *ctdp_level)
504668cc16cSZhang Rui {
505668cc16cSZhang Rui unsigned int resp;
506668cc16cSZhang Rui int i, ret;
507668cc16cSZhang Rui
508668cc16cSZhang Rui ctdp_level->cpu_count = 0;
509668cc16cSZhang Rui for (i = 0; i < 2; ++i) {
510668cc16cSZhang Rui unsigned long long mask;
511668cc16cSZhang Rui int cpu_count = 0;
512668cc16cSZhang Rui
5132b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
514668cc16cSZhang Rui CONFIG_TDP_GET_CORE_MASK, 0,
515668cc16cSZhang Rui (i << 8) | config_index, &resp);
516668cc16cSZhang Rui if (ret)
517668cc16cSZhang Rui return ret;
518668cc16cSZhang Rui
519668cc16cSZhang Rui debug_printf(
520668cc16cSZhang Rui "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
521668cc16cSZhang Rui id->cpu, config_index, i, resp);
522668cc16cSZhang Rui
523668cc16cSZhang Rui mask = (unsigned long long)resp << (32 * i);
524668cc16cSZhang Rui set_cpu_mask_from_punit_coremask(id, mask,
525668cc16cSZhang Rui ctdp_level->core_cpumask_size,
526668cc16cSZhang Rui ctdp_level->core_cpumask,
527668cc16cSZhang Rui &cpu_count);
528668cc16cSZhang Rui ctdp_level->cpu_count += cpu_count;
529668cc16cSZhang Rui debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,
530668cc16cSZhang Rui config_index, i, ctdp_level->cpu_count);
531668cc16cSZhang Rui }
532668cc16cSZhang Rui
533668cc16cSZhang Rui return 0;
534668cc16cSZhang Rui }
535668cc16cSZhang Rui
mbox_get_get_trl(struct isst_id * id,int level,int avx_level,int * trl)53639f768c3SZhang Rui static int mbox_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
53739f768c3SZhang Rui {
53839f768c3SZhang Rui unsigned int req, resp;
53939f768c3SZhang Rui int ret;
54039f768c3SZhang Rui
54139f768c3SZhang Rui req = level | (avx_level << 16);
5422b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
54339f768c3SZhang Rui CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
54439f768c3SZhang Rui &resp);
54539f768c3SZhang Rui if (ret)
54639f768c3SZhang Rui return ret;
54739f768c3SZhang Rui
54839f768c3SZhang Rui debug_printf(
54939f768c3SZhang Rui "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
55039f768c3SZhang Rui id->cpu, req, resp);
55139f768c3SZhang Rui
55239f768c3SZhang Rui trl[0] = resp & GENMASK(7, 0);
55339f768c3SZhang Rui trl[1] = (resp & GENMASK(15, 8)) >> 8;
55439f768c3SZhang Rui trl[2] = (resp & GENMASK(23, 16)) >> 16;
55539f768c3SZhang Rui trl[3] = (resp & GENMASK(31, 24)) >> 24;
55639f768c3SZhang Rui
55739f768c3SZhang Rui req = level | BIT(8) | (avx_level << 16);
5582b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
55939f768c3SZhang Rui CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
56039f768c3SZhang Rui &resp);
56139f768c3SZhang Rui if (ret)
56239f768c3SZhang Rui return ret;
56339f768c3SZhang Rui
56439f768c3SZhang Rui debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,
56539f768c3SZhang Rui req, resp);
56639f768c3SZhang Rui
56739f768c3SZhang Rui trl[4] = resp & GENMASK(7, 0);
56839f768c3SZhang Rui trl[5] = (resp & GENMASK(15, 8)) >> 8;
56939f768c3SZhang Rui trl[6] = (resp & GENMASK(23, 16)) >> 16;
57039f768c3SZhang Rui trl[7] = (resp & GENMASK(31, 24)) >> 24;
57139f768c3SZhang Rui
57239f768c3SZhang Rui return 0;
57339f768c3SZhang Rui }
57439f768c3SZhang Rui
mbox_get_get_trls(struct isst_id * id,int level,struct isst_pkg_ctdp_level_info * ctdp_level)5754a17b291SZhang Rui static int mbox_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)
5764a17b291SZhang Rui {
5774a17b291SZhang Rui int trl_max_levels = isst_get_trl_max_levels();
5784a17b291SZhang Rui int i, ret;
5794a17b291SZhang Rui
5804a17b291SZhang Rui for (i = 0; i < trl_max_levels; i++) {
5814a17b291SZhang Rui ret = mbox_get_get_trl(id, level, i, ctdp_level->trl_ratios[i]);
5824a17b291SZhang Rui if (ret)
5834a17b291SZhang Rui return ret;
5844a17b291SZhang Rui }
5854a17b291SZhang Rui return 0;
5864a17b291SZhang Rui }
5874a17b291SZhang Rui
mbox_get_trl_bucket_info(struct isst_id * id,int level,unsigned long long * buckets_info)5881e37f1b2SZhang Rui static int mbox_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)
5891e37f1b2SZhang Rui {
5901e37f1b2SZhang Rui int ret;
5911e37f1b2SZhang Rui
5921e37f1b2SZhang Rui debug_printf("cpu:%d bucket info via MSR\n", id->cpu);
5931e37f1b2SZhang Rui
5941e37f1b2SZhang Rui *buckets_info = 0;
5951e37f1b2SZhang Rui
5961e37f1b2SZhang Rui ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info);
5971e37f1b2SZhang Rui if (ret)
5981e37f1b2SZhang Rui return ret;
5991e37f1b2SZhang Rui
6001e37f1b2SZhang Rui debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,
6011e37f1b2SZhang Rui *buckets_info);
6021e37f1b2SZhang Rui
6031e37f1b2SZhang Rui return 0;
6041e37f1b2SZhang Rui }
6051e37f1b2SZhang Rui
mbox_set_tdp_level(struct isst_id * id,int tdp_level)606f88c3c4bSZhang Rui static int mbox_set_tdp_level(struct isst_id *id, int tdp_level)
607f88c3c4bSZhang Rui {
608f88c3c4bSZhang Rui unsigned int resp;
609f88c3c4bSZhang Rui int ret;
610f88c3c4bSZhang Rui
611f88c3c4bSZhang Rui
612f88c3c4bSZhang Rui if (isst_get_config_tdp_lock_status(id)) {
613f88c3c4bSZhang Rui isst_display_error_info_message(1, "TDP is locked", 0, 0);
614f88c3c4bSZhang Rui return -1;
615f88c3c4bSZhang Rui
616f88c3c4bSZhang Rui }
617f88c3c4bSZhang Rui
6182b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
619f88c3c4bSZhang Rui tdp_level, &resp);
620f88c3c4bSZhang Rui if (ret) {
621f88c3c4bSZhang Rui isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
622f88c3c4bSZhang Rui return ret;
623f88c3c4bSZhang Rui }
624f88c3c4bSZhang Rui
625f88c3c4bSZhang Rui return 0;
626f88c3c4bSZhang Rui }
627f88c3c4bSZhang Rui
mbox_get_pbf_info(struct isst_id * id,int level,struct isst_pbf_info * pbf_info)6287a196290SZhang Rui static int mbox_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
6297a196290SZhang Rui {
6307a196290SZhang Rui int max_punit_core, max_mask_index;
6317a196290SZhang Rui unsigned int req, resp;
6327a196290SZhang Rui int i, ret;
6337a196290SZhang Rui
6347a196290SZhang Rui max_punit_core = get_max_punit_core_id(id);
6357a196290SZhang Rui max_mask_index = max_punit_core > 32 ? 2 : 1;
6367a196290SZhang Rui
6377a196290SZhang Rui for (i = 0; i < max_mask_index; ++i) {
6387a196290SZhang Rui unsigned long long mask;
6397a196290SZhang Rui int count;
6407a196290SZhang Rui
6412b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
6427a196290SZhang Rui CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
6437a196290SZhang Rui 0, (i << 8) | level, &resp);
6447a196290SZhang Rui if (ret)
6457a196290SZhang Rui break;
6467a196290SZhang Rui
6477a196290SZhang Rui debug_printf(
6487a196290SZhang Rui "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
6497a196290SZhang Rui id->cpu, resp);
6507a196290SZhang Rui
6517a196290SZhang Rui mask = (unsigned long long)resp << (32 * i);
6527a196290SZhang Rui set_cpu_mask_from_punit_coremask(id, mask,
6537a196290SZhang Rui pbf_info->core_cpumask_size,
6547a196290SZhang Rui pbf_info->core_cpumask,
6557a196290SZhang Rui &count);
6567a196290SZhang Rui }
6577a196290SZhang Rui
6587a196290SZhang Rui req = level;
6592b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
6607a196290SZhang Rui CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
6617a196290SZhang Rui &resp);
6627a196290SZhang Rui if (ret)
6637a196290SZhang Rui return ret;
6647a196290SZhang Rui
6657a196290SZhang Rui debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,
6667a196290SZhang Rui resp);
6677a196290SZhang Rui
6687a196290SZhang Rui pbf_info->p1_low = resp & 0xff;
6697a196290SZhang Rui pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
6707a196290SZhang Rui
6717a196290SZhang Rui req = level;
6722b86ed22SZhang Rui ret = _send_mbox_command(
6737a196290SZhang Rui id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
6747a196290SZhang Rui if (ret)
6757a196290SZhang Rui return ret;
6767a196290SZhang Rui
6777a196290SZhang Rui debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp);
6787a196290SZhang Rui
6797a196290SZhang Rui pbf_info->tdp = resp & 0xffff;
6807a196290SZhang Rui
6817a196290SZhang Rui req = level;
6822b86ed22SZhang Rui ret = _send_mbox_command(
6837a196290SZhang Rui id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
6847a196290SZhang Rui if (ret)
6857a196290SZhang Rui return ret;
6867a196290SZhang Rui
6877a196290SZhang Rui debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu,
6887a196290SZhang Rui resp);
6897a196290SZhang Rui pbf_info->t_control = (resp >> 8) & 0xff;
6907a196290SZhang Rui pbf_info->t_prochot = resp & 0xff;
6917a196290SZhang Rui
6927a196290SZhang Rui return 0;
6937a196290SZhang Rui }
6947a196290SZhang Rui
mbox_set_pbf_fact_status(struct isst_id * id,int pbf,int enable)6955843f217SZhang Rui static int mbox_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
6965843f217SZhang Rui {
6975843f217SZhang Rui struct isst_pkg_ctdp pkg_dev;
6985843f217SZhang Rui struct isst_pkg_ctdp_level_info ctdp_level;
6995843f217SZhang Rui int current_level;
7005843f217SZhang Rui unsigned int req = 0, resp;
7015843f217SZhang Rui int ret;
7025843f217SZhang Rui
7035843f217SZhang Rui ret = isst_get_ctdp_levels(id, &pkg_dev);
7045843f217SZhang Rui if (ret)
7055843f217SZhang Rui debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
7065843f217SZhang Rui
7075843f217SZhang Rui current_level = pkg_dev.current_level;
7085843f217SZhang Rui
7095843f217SZhang Rui ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
7105843f217SZhang Rui if (ret)
7115843f217SZhang Rui return ret;
7125843f217SZhang Rui
7135843f217SZhang Rui if (pbf) {
7145843f217SZhang Rui if (ctdp_level.fact_enabled)
7155843f217SZhang Rui req = BIT(16);
7165843f217SZhang Rui
7175843f217SZhang Rui if (enable)
7185843f217SZhang Rui req |= BIT(17);
7195843f217SZhang Rui else
7205843f217SZhang Rui req &= ~BIT(17);
7215843f217SZhang Rui } else {
7225843f217SZhang Rui
7235843f217SZhang Rui if (enable && !ctdp_level.sst_cp_enabled)
7245843f217SZhang Rui isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
7255843f217SZhang Rui
7265843f217SZhang Rui if (ctdp_level.pbf_enabled)
7275843f217SZhang Rui req = BIT(17);
7285843f217SZhang Rui
7295843f217SZhang Rui if (enable)
7305843f217SZhang Rui req |= BIT(16);
7315843f217SZhang Rui else
7325843f217SZhang Rui req &= ~BIT(16);
7335843f217SZhang Rui }
7345843f217SZhang Rui
7352b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
7365843f217SZhang Rui CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
7375843f217SZhang Rui if (ret)
7385843f217SZhang Rui return ret;
7395843f217SZhang Rui
7405843f217SZhang Rui debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
7415843f217SZhang Rui id->cpu, pbf, req);
7425843f217SZhang Rui
7435843f217SZhang Rui return 0;
7445843f217SZhang Rui }
7455843f217SZhang Rui
_get_fact_bucket_info(struct isst_id * id,int level,struct isst_fact_bucket_info * bucket_info)7467b5f586dSZhang Rui static int _get_fact_bucket_info(struct isst_id *id, int level,
7477b5f586dSZhang Rui struct isst_fact_bucket_info *bucket_info)
7487b5f586dSZhang Rui {
7497b5f586dSZhang Rui unsigned int resp;
7507b5f586dSZhang Rui int i, k, ret;
7517b5f586dSZhang Rui
7527b5f586dSZhang Rui for (i = 0; i < 2; ++i) {
7537b5f586dSZhang Rui int j;
7547b5f586dSZhang Rui
7552b86ed22SZhang Rui ret = _send_mbox_command(
7567b5f586dSZhang Rui id->cpu, CONFIG_TDP,
7577b5f586dSZhang Rui CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
7587b5f586dSZhang Rui (i << 8) | level, &resp);
7597b5f586dSZhang Rui if (ret)
7607b5f586dSZhang Rui return ret;
7617b5f586dSZhang Rui
7627b5f586dSZhang Rui debug_printf(
7637b5f586dSZhang Rui "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
7647b5f586dSZhang Rui id->cpu, i, level, resp);
7657b5f586dSZhang Rui
7667b5f586dSZhang Rui for (j = 0; j < 4; ++j) {
7677b5f586dSZhang Rui bucket_info[j + (i * 4)].hp_cores =
7687b5f586dSZhang Rui (resp >> (j * 8)) & 0xff;
7697b5f586dSZhang Rui }
7707b5f586dSZhang Rui }
7717b5f586dSZhang Rui
7727b5f586dSZhang Rui for (k = 0; k < 3; ++k) {
7737b5f586dSZhang Rui for (i = 0; i < 2; ++i) {
7747b5f586dSZhang Rui int j;
7757b5f586dSZhang Rui
7762b86ed22SZhang Rui ret = _send_mbox_command(
7777b5f586dSZhang Rui id->cpu, CONFIG_TDP,
7787b5f586dSZhang Rui CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
7797b5f586dSZhang Rui (k << 16) | (i << 8) | level, &resp);
7807b5f586dSZhang Rui if (ret)
7817b5f586dSZhang Rui return ret;
7827b5f586dSZhang Rui
7837b5f586dSZhang Rui debug_printf(
7847b5f586dSZhang Rui "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
7857b5f586dSZhang Rui id->cpu, i, level, k, resp);
7867b5f586dSZhang Rui
7877b5f586dSZhang Rui for (j = 0; j < 4; ++j) {
7887b5f586dSZhang Rui bucket_info[j + (i * 4)].hp_ratios[k] =
7897b5f586dSZhang Rui (resp >> (j * 8)) & 0xff;
7907b5f586dSZhang Rui }
7917b5f586dSZhang Rui }
7927b5f586dSZhang Rui }
7937b5f586dSZhang Rui
7947b5f586dSZhang Rui return 0;
7957b5f586dSZhang Rui }
7967b5f586dSZhang Rui
mbox_get_fact_info(struct isst_id * id,int level,int fact_bucket,struct isst_fact_info * fact_info)7977b5f586dSZhang Rui static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
7987b5f586dSZhang Rui {
7997b5f586dSZhang Rui unsigned int resp;
8007b5f586dSZhang Rui int j, ret, print;
8017b5f586dSZhang Rui
8022b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_TDP,
8037b5f586dSZhang Rui CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
8047b5f586dSZhang Rui level, &resp);
8057b5f586dSZhang Rui if (ret)
8067b5f586dSZhang Rui return ret;
8077b5f586dSZhang Rui
8087b5f586dSZhang Rui debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
8097b5f586dSZhang Rui id->cpu, resp);
8107b5f586dSZhang Rui
8117b5f586dSZhang Rui fact_info->lp_ratios[0] = resp & 0xff;
8127b5f586dSZhang Rui fact_info->lp_ratios[1] = (resp >> 8) & 0xff;
8137b5f586dSZhang Rui fact_info->lp_ratios[2] = (resp >> 16) & 0xff;
8147b5f586dSZhang Rui
8157b5f586dSZhang Rui ret = _get_fact_bucket_info(id, level, fact_info->bucket_info);
8167b5f586dSZhang Rui if (ret)
8177b5f586dSZhang Rui return ret;
8187b5f586dSZhang Rui
8197b5f586dSZhang Rui print = 0;
8207b5f586dSZhang Rui for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
8217b5f586dSZhang Rui if (fact_bucket != 0xff && fact_bucket != j)
8227b5f586dSZhang Rui continue;
8237b5f586dSZhang Rui
8247b5f586dSZhang Rui if (!fact_info->bucket_info[j].hp_cores)
8257b5f586dSZhang Rui break;
8267b5f586dSZhang Rui
8277b5f586dSZhang Rui print = 1;
8287b5f586dSZhang Rui }
8297b5f586dSZhang Rui if (!print) {
8307b5f586dSZhang Rui isst_display_error_info_message(1, "Invalid bucket", 0, 0);
8317b5f586dSZhang Rui return -1;
8327b5f586dSZhang Rui }
8337b5f586dSZhang Rui
8347b5f586dSZhang Rui return 0;
8357b5f586dSZhang Rui }
8367b5f586dSZhang Rui
mbox_get_clos_information(struct isst_id * id,int * enable,int * type)837a07bdb81SZhang Rui static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type)
838a07bdb81SZhang Rui {
839a07bdb81SZhang Rui unsigned int resp;
840a07bdb81SZhang Rui int ret;
841a07bdb81SZhang Rui
8422b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
843a07bdb81SZhang Rui &resp);
844a07bdb81SZhang Rui if (ret)
845a07bdb81SZhang Rui return ret;
846a07bdb81SZhang Rui
847a07bdb81SZhang Rui debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
848a07bdb81SZhang Rui
849a07bdb81SZhang Rui if (resp & BIT(1))
850a07bdb81SZhang Rui *enable = 1;
851a07bdb81SZhang Rui else
852a07bdb81SZhang Rui *enable = 0;
853a07bdb81SZhang Rui
854a07bdb81SZhang Rui if (resp & BIT(2))
855a07bdb81SZhang Rui *type = 1;
856a07bdb81SZhang Rui else
857a07bdb81SZhang Rui *type = 0;
858a07bdb81SZhang Rui
859a07bdb81SZhang Rui return 0;
860a07bdb81SZhang Rui }
861904d2baaSZhang Rui
_write_pm_config(struct isst_id * id,int cp_state)862904d2baaSZhang Rui static int _write_pm_config(struct isst_id *id, int cp_state)
863904d2baaSZhang Rui {
864904d2baaSZhang Rui unsigned int req, resp;
865904d2baaSZhang Rui int ret;
866904d2baaSZhang Rui
867904d2baaSZhang Rui if (cp_state)
868904d2baaSZhang Rui req = BIT(16);
869904d2baaSZhang Rui else
870904d2baaSZhang Rui req = 0;
871904d2baaSZhang Rui
8722b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
873904d2baaSZhang Rui &resp);
874904d2baaSZhang Rui if (ret)
875904d2baaSZhang Rui return ret;
876904d2baaSZhang Rui
877904d2baaSZhang Rui debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
878904d2baaSZhang Rui
879904d2baaSZhang Rui return 0;
880904d2baaSZhang Rui }
881904d2baaSZhang Rui
mbox_pm_qos_config(struct isst_id * id,int enable_clos,int priority_type)882904d2baaSZhang Rui static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
883904d2baaSZhang Rui {
884904d2baaSZhang Rui unsigned int req, resp;
885904d2baaSZhang Rui int ret;
886904d2baaSZhang Rui
887904d2baaSZhang Rui if (!enable_clos) {
888904d2baaSZhang Rui struct isst_pkg_ctdp pkg_dev;
889904d2baaSZhang Rui struct isst_pkg_ctdp_level_info ctdp_level;
890904d2baaSZhang Rui
891904d2baaSZhang Rui ret = isst_get_ctdp_levels(id, &pkg_dev);
892904d2baaSZhang Rui if (ret) {
893904d2baaSZhang Rui debug_printf("isst_get_ctdp_levels\n");
894904d2baaSZhang Rui return ret;
895904d2baaSZhang Rui }
896904d2baaSZhang Rui
897904d2baaSZhang Rui ret = isst_get_ctdp_control(id, pkg_dev.current_level,
898904d2baaSZhang Rui &ctdp_level);
899904d2baaSZhang Rui if (ret)
900904d2baaSZhang Rui return ret;
901904d2baaSZhang Rui
902904d2baaSZhang Rui if (ctdp_level.fact_enabled) {
903904d2baaSZhang Rui isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
904904d2baaSZhang Rui return -EINVAL;
905904d2baaSZhang Rui }
906904d2baaSZhang Rui ret = _write_pm_config(id, 0);
907904d2baaSZhang Rui if (ret)
908904d2baaSZhang Rui isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
909904d2baaSZhang Rui } else {
910904d2baaSZhang Rui ret = _write_pm_config(id, 1);
911904d2baaSZhang Rui if (ret)
912904d2baaSZhang Rui isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
913904d2baaSZhang Rui }
914904d2baaSZhang Rui
9152b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
916904d2baaSZhang Rui &resp);
917904d2baaSZhang Rui if (ret) {
918904d2baaSZhang Rui isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
919904d2baaSZhang Rui return ret;
920904d2baaSZhang Rui }
921904d2baaSZhang Rui
922904d2baaSZhang Rui debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
923904d2baaSZhang Rui
924904d2baaSZhang Rui req = resp;
925904d2baaSZhang Rui
926904d2baaSZhang Rui if (enable_clos)
927904d2baaSZhang Rui req = req | BIT(1);
928904d2baaSZhang Rui else
929904d2baaSZhang Rui req = req & ~BIT(1);
930904d2baaSZhang Rui
931904d2baaSZhang Rui if (priority_type > 1)
932904d2baaSZhang Rui isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
933904d2baaSZhang Rui
934904d2baaSZhang Rui if (priority_type)
935904d2baaSZhang Rui req = req | BIT(2);
936904d2baaSZhang Rui else
937904d2baaSZhang Rui req = req & ~BIT(2);
938904d2baaSZhang Rui
9392b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
940904d2baaSZhang Rui BIT(MBOX_CMD_WRITE_BIT), req, &resp);
941904d2baaSZhang Rui if (ret)
942904d2baaSZhang Rui return ret;
943904d2baaSZhang Rui
944904d2baaSZhang Rui debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
945904d2baaSZhang Rui priority_type, req);
946904d2baaSZhang Rui
947904d2baaSZhang Rui return 0;
948904d2baaSZhang Rui }
949904d2baaSZhang Rui
mbox_pm_get_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)95043314e79SZhang Rui static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
95143314e79SZhang Rui {
95243314e79SZhang Rui unsigned int resp;
95343314e79SZhang Rui int ret;
95443314e79SZhang Rui
9552b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
95643314e79SZhang Rui &resp);
95743314e79SZhang Rui if (ret)
95843314e79SZhang Rui return ret;
95943314e79SZhang Rui
96043314e79SZhang Rui clos_config->epp = resp & 0x0f;
96143314e79SZhang Rui clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
96243314e79SZhang Rui clos_config->clos_min = (resp >> 8) & 0xff;
96343314e79SZhang Rui clos_config->clos_max = (resp >> 16) & 0xff;
96443314e79SZhang Rui clos_config->clos_desired = (resp >> 24) & 0xff;
96543314e79SZhang Rui
96643314e79SZhang Rui return 0;
96743314e79SZhang Rui }
96843314e79SZhang Rui
mbox_set_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)96933dbf360SZhang Rui static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
97033dbf360SZhang Rui {
97133dbf360SZhang Rui unsigned int req, resp;
97233dbf360SZhang Rui unsigned int param;
97333dbf360SZhang Rui int ret;
97433dbf360SZhang Rui
97533dbf360SZhang Rui req = clos_config->epp & 0x0f;
97633dbf360SZhang Rui req |= (clos_config->clos_prop_prio & 0x0f) << 4;
97733dbf360SZhang Rui req |= (clos_config->clos_min & 0xff) << 8;
97833dbf360SZhang Rui req |= (clos_config->clos_max & 0xff) << 16;
97933dbf360SZhang Rui req |= (clos_config->clos_desired & 0xff) << 24;
98033dbf360SZhang Rui
98133dbf360SZhang Rui param = BIT(MBOX_CMD_WRITE_BIT) | clos;
98233dbf360SZhang Rui
9832b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
98433dbf360SZhang Rui &resp);
98533dbf360SZhang Rui if (ret)
98633dbf360SZhang Rui return ret;
98733dbf360SZhang Rui
98833dbf360SZhang Rui debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
98933dbf360SZhang Rui
99033dbf360SZhang Rui return 0;
99133dbf360SZhang Rui }
99233dbf360SZhang Rui
mbox_clos_get_assoc_status(struct isst_id * id,int * clos_id)993b161bbadSZhang Rui static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id)
994b161bbadSZhang Rui {
995b161bbadSZhang Rui unsigned int resp;
996b161bbadSZhang Rui unsigned int param;
997b161bbadSZhang Rui int core_id, ret;
998b161bbadSZhang Rui
999b161bbadSZhang Rui core_id = find_phy_core_num(id->cpu);
1000b161bbadSZhang Rui param = core_id;
1001b161bbadSZhang Rui
10022b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
1003b161bbadSZhang Rui &resp);
1004b161bbadSZhang Rui if (ret)
1005b161bbadSZhang Rui return ret;
1006b161bbadSZhang Rui
1007b161bbadSZhang Rui debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
1008b161bbadSZhang Rui resp);
1009b161bbadSZhang Rui *clos_id = (resp >> 16) & 0x03;
1010b161bbadSZhang Rui
1011b161bbadSZhang Rui return 0;
1012b161bbadSZhang Rui }
1013a59a6c0cSZhang Rui
mbox_clos_associate(struct isst_id * id,int clos_id)1014a59a6c0cSZhang Rui static int mbox_clos_associate(struct isst_id *id, int clos_id)
1015a59a6c0cSZhang Rui {
1016a59a6c0cSZhang Rui unsigned int req, resp;
1017a59a6c0cSZhang Rui unsigned int param;
1018a59a6c0cSZhang Rui int core_id, ret;
1019a59a6c0cSZhang Rui
1020a59a6c0cSZhang Rui req = (clos_id & 0x03) << 16;
1021a59a6c0cSZhang Rui core_id = find_phy_core_num(id->cpu);
1022a59a6c0cSZhang Rui param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
1023a59a6c0cSZhang Rui
10242b86ed22SZhang Rui ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
1025a59a6c0cSZhang Rui req, &resp);
1026a59a6c0cSZhang Rui if (ret)
1027a59a6c0cSZhang Rui return ret;
1028a59a6c0cSZhang Rui
1029a59a6c0cSZhang Rui debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
1030a59a6c0cSZhang Rui req);
1031a59a6c0cSZhang Rui
1032a59a6c0cSZhang Rui return 0;
1033a59a6c0cSZhang Rui }
1034a59a6c0cSZhang Rui
1035d0d1a603SZhang Rui static struct isst_platform_ops mbox_ops = {
1036d0d1a603SZhang Rui .get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,
1037d0d1a603SZhang Rui .get_trl_max_levels = mbox_get_trl_max_levels,
1038d0d1a603SZhang Rui .get_trl_level_name = mbox_get_trl_level_name,
10392b86ed22SZhang Rui .update_platform_param = mbox_update_platform_param,
1040143584e8SZhang Rui .is_punit_valid = mbox_is_punit_valid,
10418f54104fSZhang Rui .read_pm_config = mbox_read_pm_config,
104272438744SZhang Rui .get_config_levels = mbox_get_config_levels,
1043bbe32d87SZhang Rui .get_ctdp_control = mbox_get_ctdp_control,
1044645b6605SZhang Rui .get_tdp_info = mbox_get_tdp_info,
1045e107dec9SZhang Rui .get_pwr_info = mbox_get_pwr_info,
1046668cc16cSZhang Rui .get_coremask_info = mbox_get_coremask_info,
104739f768c3SZhang Rui .get_get_trl = mbox_get_get_trl,
10484a17b291SZhang Rui .get_get_trls = mbox_get_get_trls,
10491e37f1b2SZhang Rui .get_trl_bucket_info = mbox_get_trl_bucket_info,
1050f88c3c4bSZhang Rui .set_tdp_level = mbox_set_tdp_level,
10517a196290SZhang Rui .get_pbf_info = mbox_get_pbf_info,
10525843f217SZhang Rui .set_pbf_fact_status = mbox_set_pbf_fact_status,
10537b5f586dSZhang Rui .get_fact_info = mbox_get_fact_info,
105473452cccSZhang Rui .adjust_uncore_freq = mbox_adjust_uncore_freq,
1055a07bdb81SZhang Rui .get_clos_information = mbox_get_clos_information,
1056904d2baaSZhang Rui .pm_qos_config = mbox_pm_qos_config,
105743314e79SZhang Rui .pm_get_clos = mbox_pm_get_clos,
105833dbf360SZhang Rui .set_clos = mbox_set_clos,
1059b161bbadSZhang Rui .clos_get_assoc_status = mbox_clos_get_assoc_status,
1060a59a6c0cSZhang Rui .clos_associate = mbox_clos_associate,
1061d0d1a603SZhang Rui };
1062d0d1a603SZhang Rui
mbox_get_platform_ops(void)1063d0d1a603SZhang Rui struct isst_platform_ops *mbox_get_platform_ops(void)
1064d0d1a603SZhang Rui {
1065d0d1a603SZhang Rui return &mbox_ops;
1066d0d1a603SZhang Rui }
1067