1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Intel Speed Select -- Enumerate and control features for Mailbox Interface 4 * Copyright (c) 2023 Intel Corporation. 5 */ 6 #include "isst.h" 7 8 static int mbox_get_disp_freq_multiplier(void) 9 { 10 return DISP_FREQ_MULTIPLIER; 11 } 12 13 static int mbox_get_trl_max_levels(void) 14 { 15 return 3; 16 } 17 18 static char *mbox_get_trl_level_name(int level) 19 { 20 switch (level) { 21 case 0: 22 return "sse"; 23 case 1: 24 return "avx2"; 25 case 2: 26 return "avx512"; 27 default: 28 return NULL; 29 } 30 } 31 32 static int mbox_is_punit_valid(struct isst_id *id) 33 { 34 if (id->cpu < 0) 35 return 0; 36 37 if (id->pkg < 0 || id->die < 0 || id->punit) 38 return 0; 39 40 return 1; 41 } 42 43 static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev) 44 { 45 unsigned int resp; 46 int ret; 47 48 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 49 CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp); 50 if (ret) { 51 pkg_dev->levels = 0; 52 pkg_dev->locked = 1; 53 pkg_dev->current_level = 0; 54 pkg_dev->version = 0; 55 pkg_dev->enabled = 0; 56 return 0; 57 } 58 59 debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp); 60 61 pkg_dev->version = resp & 0xff; 62 pkg_dev->levels = (resp >> 8) & 0xff; 63 pkg_dev->current_level = (resp >> 16) & 0xff; 64 pkg_dev->locked = !!(resp & BIT(24)); 65 pkg_dev->enabled = !!(resp & BIT(31)); 66 67 return 0; 68 } 69 70 static int mbox_get_ctdp_control(struct isst_id *id, int config_index, 71 struct isst_pkg_ctdp_level_info *ctdp_level) 72 { 73 int cp_state, cp_cap; 74 unsigned int resp; 75 int ret; 76 77 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 78 CONFIG_TDP_GET_TDP_CONTROL, 0, 79 config_index, &resp); 80 if (ret) 81 return ret; 82 83 ctdp_level->fact_support = resp & BIT(0); 84 ctdp_level->pbf_support = !!(resp & BIT(1)); 85 ctdp_level->fact_enabled = !!(resp & BIT(16)); 86 ctdp_level->pbf_enabled = !!(resp & BIT(17)); 87 88 ret = isst_read_pm_config(id, &cp_state, &cp_cap); 89 if (ret) { 90 debug_printf("cpu:%d pm_config is not supported\n", id->cpu); 91 } else { 92 debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap); 93 ctdp_level->sst_cp_support = cp_cap; 94 ctdp_level->sst_cp_enabled = cp_state; 95 } 96 97 debug_printf( 98 "cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n", 99 id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support, 100 ctdp_level->fact_enabled, ctdp_level->pbf_enabled); 101 102 return 0; 103 } 104 105 static int mbox_get_tdp_info(struct isst_id *id, int config_index, 106 struct isst_pkg_ctdp_level_info *ctdp_level) 107 { 108 unsigned int resp; 109 int ret; 110 111 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO, 112 0, config_index, &resp); 113 if (ret) { 114 isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index); 115 return ret; 116 } 117 118 ctdp_level->pkg_tdp = resp & GENMASK(14, 0); 119 ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16; 120 121 debug_printf( 122 "cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n", 123 id->cpu, config_index, resp, ctdp_level->tdp_ratio, 124 ctdp_level->pkg_tdp); 125 126 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO, 127 0, config_index, &resp); 128 if (ret) 129 return ret; 130 131 ctdp_level->t_proc_hot = resp & GENMASK(7, 0); 132 133 debug_printf( 134 "cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n", 135 id->cpu, config_index, resp, ctdp_level->t_proc_hot); 136 137 return 0; 138 } 139 140 static int mbox_get_pwr_info(struct isst_id *id, int config_index, 141 struct isst_pkg_ctdp_level_info *ctdp_level) 142 { 143 unsigned int resp; 144 int ret; 145 146 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO, 147 0, config_index, &resp); 148 if (ret) 149 return ret; 150 151 ctdp_level->pkg_max_power = resp & GENMASK(14, 0); 152 ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16; 153 154 debug_printf( 155 "cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n", 156 id->cpu, config_index, resp, ctdp_level->pkg_max_power, 157 ctdp_level->pkg_min_power); 158 159 return 0; 160 } 161 162 static int mbox_get_coremask_info(struct isst_id *id, int config_index, 163 struct isst_pkg_ctdp_level_info *ctdp_level) 164 { 165 unsigned int resp; 166 int i, ret; 167 168 ctdp_level->cpu_count = 0; 169 for (i = 0; i < 2; ++i) { 170 unsigned long long mask; 171 int cpu_count = 0; 172 173 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 174 CONFIG_TDP_GET_CORE_MASK, 0, 175 (i << 8) | config_index, &resp); 176 if (ret) 177 return ret; 178 179 debug_printf( 180 "cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n", 181 id->cpu, config_index, i, resp); 182 183 mask = (unsigned long long)resp << (32 * i); 184 set_cpu_mask_from_punit_coremask(id, mask, 185 ctdp_level->core_cpumask_size, 186 ctdp_level->core_cpumask, 187 &cpu_count); 188 ctdp_level->cpu_count += cpu_count; 189 debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu, 190 config_index, i, ctdp_level->cpu_count); 191 } 192 193 return 0; 194 } 195 196 static int mbox_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl) 197 { 198 unsigned int req, resp; 199 int ret; 200 201 req = level | (avx_level << 16); 202 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 203 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req, 204 &resp); 205 if (ret) 206 return ret; 207 208 debug_printf( 209 "cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n", 210 id->cpu, req, resp); 211 212 trl[0] = resp & GENMASK(7, 0); 213 trl[1] = (resp & GENMASK(15, 8)) >> 8; 214 trl[2] = (resp & GENMASK(23, 16)) >> 16; 215 trl[3] = (resp & GENMASK(31, 24)) >> 24; 216 217 req = level | BIT(8) | (avx_level << 16); 218 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 219 CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req, 220 &resp); 221 if (ret) 222 return ret; 223 224 debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu, 225 req, resp); 226 227 trl[4] = resp & GENMASK(7, 0); 228 trl[5] = (resp & GENMASK(15, 8)) >> 8; 229 trl[6] = (resp & GENMASK(23, 16)) >> 16; 230 trl[7] = (resp & GENMASK(31, 24)) >> 24; 231 232 return 0; 233 } 234 235 static int mbox_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info) 236 { 237 int ret; 238 239 debug_printf("cpu:%d bucket info via MSR\n", id->cpu); 240 241 *buckets_info = 0; 242 243 ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info); 244 if (ret) 245 return ret; 246 247 debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu, 248 *buckets_info); 249 250 return 0; 251 } 252 253 static int mbox_set_tdp_level(struct isst_id *id, int tdp_level) 254 { 255 unsigned int resp; 256 int ret; 257 258 259 if (isst_get_config_tdp_lock_status(id)) { 260 isst_display_error_info_message(1, "TDP is locked", 0, 0); 261 return -1; 262 263 } 264 265 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0, 266 tdp_level, &resp); 267 if (ret) { 268 isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level); 269 return ret; 270 } 271 272 return 0; 273 } 274 275 static int mbox_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info) 276 { 277 int max_punit_core, max_mask_index; 278 unsigned int req, resp; 279 int i, ret; 280 281 max_punit_core = get_max_punit_core_id(id); 282 max_mask_index = max_punit_core > 32 ? 2 : 1; 283 284 for (i = 0; i < max_mask_index; ++i) { 285 unsigned long long mask; 286 int count; 287 288 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 289 CONFIG_TDP_PBF_GET_CORE_MASK_INFO, 290 0, (i << 8) | level, &resp); 291 if (ret) 292 break; 293 294 debug_printf( 295 "cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n", 296 id->cpu, resp); 297 298 mask = (unsigned long long)resp << (32 * i); 299 set_cpu_mask_from_punit_coremask(id, mask, 300 pbf_info->core_cpumask_size, 301 pbf_info->core_cpumask, 302 &count); 303 } 304 305 req = level; 306 ret = isst_send_mbox_command(id->cpu, CONFIG_TDP, 307 CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req, 308 &resp); 309 if (ret) 310 return ret; 311 312 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu, 313 resp); 314 315 pbf_info->p1_low = resp & 0xff; 316 pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8; 317 318 req = level; 319 ret = isst_send_mbox_command( 320 id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp); 321 if (ret) 322 return ret; 323 324 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp); 325 326 pbf_info->tdp = resp & 0xffff; 327 328 req = level; 329 ret = isst_send_mbox_command( 330 id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp); 331 if (ret) 332 return ret; 333 334 debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu, 335 resp); 336 pbf_info->t_control = (resp >> 8) & 0xff; 337 pbf_info->t_prochot = resp & 0xff; 338 339 return 0; 340 } 341 342 static struct isst_platform_ops mbox_ops = { 343 .get_disp_freq_multiplier = mbox_get_disp_freq_multiplier, 344 .get_trl_max_levels = mbox_get_trl_max_levels, 345 .get_trl_level_name = mbox_get_trl_level_name, 346 .is_punit_valid = mbox_is_punit_valid, 347 .get_config_levels = mbox_get_config_levels, 348 .get_ctdp_control = mbox_get_ctdp_control, 349 .get_tdp_info = mbox_get_tdp_info, 350 .get_pwr_info = mbox_get_pwr_info, 351 .get_coremask_info = mbox_get_coremask_info, 352 .get_get_trl = mbox_get_get_trl, 353 .get_trl_bucket_info = mbox_get_trl_bucket_info, 354 .set_tdp_level = mbox_set_tdp_level, 355 .get_pbf_info = mbox_get_pbf_info, 356 }; 357 358 struct isst_platform_ops *mbox_get_platform_ops(void) 359 { 360 return &mbox_ops; 361 } 362