1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Intel Speed Select -- Enumerate and control features for TPMI Interface
4 * Copyright (c) 2022 Intel Corporation.
5 */
6
7 #include <linux/isst_if.h>
8 #include "isst.h"
9
tpmi_process_ioctl(int ioctl_no,void * info)10 int tpmi_process_ioctl(int ioctl_no, void *info)
11 {
12 const char *pathname = "/dev/isst_interface";
13 int fd;
14
15 if (is_debug_enabled()) {
16 debug_printf("Issue IOCTL: ");
17 switch (ioctl_no) {
18 case ISST_IF_CORE_POWER_STATE:
19 debug_printf("ISST_IF_CORE_POWER_STATE\n");
20 break;
21 case ISST_IF_CLOS_PARAM:
22 debug_printf("ISST_IF_CLOS_PARAM\n");
23 break;
24 case ISST_IF_CLOS_ASSOC:
25 debug_printf("ISST_IF_CLOS_ASSOC\n");
26 break;
27 case ISST_IF_PERF_LEVELS:
28 debug_printf("ISST_IF_PERF_LEVELS\n");
29 break;
30 case ISST_IF_PERF_SET_LEVEL:
31 debug_printf("ISST_IF_PERF_SET_LEVEL\n");
32 break;
33 case ISST_IF_PERF_SET_FEATURE:
34 debug_printf("ISST_IF_PERF_SET_FEATURE\n");
35 break;
36 case ISST_IF_GET_PERF_LEVEL_INFO:
37 debug_printf("ISST_IF_GET_PERF_LEVEL_INFO\n");
38 break;
39 case ISST_IF_GET_PERF_LEVEL_CPU_MASK:
40 debug_printf("ISST_IF_GET_PERF_LEVEL_CPU_MASK\n");
41 break;
42 case ISST_IF_GET_BASE_FREQ_INFO:
43 debug_printf("ISST_IF_GET_BASE_FREQ_INFO\n");
44 break;
45 case ISST_IF_GET_BASE_FREQ_CPU_MASK:
46 debug_printf("ISST_IF_GET_BASE_FREQ_CPU_MASK\n");
47 break;
48 case ISST_IF_GET_TURBO_FREQ_INFO:
49 debug_printf("ISST_IF_GET_TURBO_FREQ_INFO\n");
50 break;
51 case ISST_IF_COUNT_TPMI_INSTANCES:
52 debug_printf("ISST_IF_COUNT_TPMI_INSTANCES\n");
53 break;
54 default:
55 debug_printf("%d\n", ioctl_no);
56 break;
57 }
58 }
59
60 fd = open(pathname, O_RDWR);
61 if (fd < 0)
62 return -1;
63
64 if (ioctl(fd, ioctl_no, info) == -1) {
65 debug_printf("IOCTL %d Failed\n", ioctl_no);
66 close(fd);
67 return -1;
68 }
69
70 close(fd);
71
72 return 0;
73 }
74
tpmi_get_disp_freq_multiplier(void)75 static int tpmi_get_disp_freq_multiplier(void)
76 {
77 return 1;
78 }
79
tpmi_get_trl_max_levels(void)80 static int tpmi_get_trl_max_levels(void)
81 {
82 return TRL_MAX_LEVELS;
83 }
84
tpmi_get_trl_level_name(int level)85 static char *tpmi_get_trl_level_name(int level)
86 {
87 switch (level) {
88 case 0:
89 return "level-0";
90 case 1:
91 return "level-1";
92 case 2:
93 return "level-2";
94 case 3:
95 return "level-3";
96 case 4:
97 return "level-4";
98 case 5:
99 return "level-5";
100 case 6:
101 return "level-6";
102 case 7:
103 return "level-7";
104 default:
105 return NULL;
106 }
107 }
108
109
tpmi_update_platform_param(enum isst_platform_param param,int value)110 static void tpmi_update_platform_param(enum isst_platform_param param, int value)
111 {
112 /* No params need to be updated for now */
113 }
114
tpmi_is_punit_valid(struct isst_id * id)115 static int tpmi_is_punit_valid(struct isst_id *id)
116 {
117 struct isst_tpmi_instance_count info;
118 int ret;
119
120 if (id->punit < 0)
121 return 0;
122
123 info.socket_id = id->pkg;
124 ret = tpmi_process_ioctl(ISST_IF_COUNT_TPMI_INSTANCES, &info);
125 if (ret == -1)
126 return 0;
127
128 if (info.valid_mask & BIT(id->punit))
129 return 1;
130
131 return 0;
132 }
133
tpmi_read_pm_config(struct isst_id * id,int * cp_state,int * cp_cap)134 static int tpmi_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
135 {
136 struct isst_core_power info;
137 int ret;
138
139 info.get_set = 0;
140 info.socket_id = id->pkg;
141 info.power_domain_id = id->punit;
142 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
143 if (ret == -1)
144 return ret;
145
146 *cp_state = info.enable;
147 *cp_cap = info.supported;
148
149 return 0;
150 }
151
tpmi_get_config_levels(struct isst_id * id,struct isst_pkg_ctdp * pkg_dev)152 int tpmi_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
153 {
154 struct isst_perf_level_info info;
155 int ret;
156
157 info.socket_id = id->pkg;
158 info.power_domain_id = id->punit;
159
160 ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
161 if (ret == -1)
162 return ret;
163
164 pkg_dev->version = info.feature_rev;
165 pkg_dev->levels = info.max_level;
166 pkg_dev->locked = info.locked;
167 pkg_dev->current_level = info.current_level;
168 pkg_dev->locked = info.locked;
169 pkg_dev->enabled = info.enabled;
170
171 return 0;
172 }
173
tpmi_get_ctdp_control(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)174 static int tpmi_get_ctdp_control(struct isst_id *id, int config_index,
175 struct isst_pkg_ctdp_level_info *ctdp_level)
176 {
177 struct isst_core_power core_power_info;
178 struct isst_perf_level_info info;
179 int level_mask;
180 int ret;
181
182 info.socket_id = id->pkg;
183 info.power_domain_id = id->punit;
184
185 ret = tpmi_process_ioctl(ISST_IF_PERF_LEVELS, &info);
186 if (ret == -1)
187 return -1;
188
189 if (config_index != 0xff)
190 level_mask = 1 << config_index;
191 else
192 level_mask = config_index;
193
194 if (!(info.level_mask & level_mask))
195 return -1;
196
197 ctdp_level->fact_support = info.sst_tf_support;
198 ctdp_level->pbf_support = info.sst_bf_support;
199 ctdp_level->fact_enabled = !!(info.feature_state & BIT(1));
200 ctdp_level->pbf_enabled = !!(info.feature_state & BIT(0));
201
202 core_power_info.get_set = 0;
203 core_power_info.socket_id = id->pkg;
204 core_power_info.power_domain_id = id->punit;
205
206 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &core_power_info);
207 if (ret == -1)
208 return ret;
209
210 ctdp_level->sst_cp_support = core_power_info.supported;
211 ctdp_level->sst_cp_enabled = core_power_info.enable;
212
213 debug_printf
214 ("cpu:%d CONFIG_TDP_GET_TDP_CONTROL fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
215 id->cpu, ctdp_level->fact_support, ctdp_level->pbf_support,
216 ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
217
218 return 0;
219 }
220
tpmi_get_tdp_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)221 static int tpmi_get_tdp_info(struct isst_id *id, int config_index,
222 struct isst_pkg_ctdp_level_info *ctdp_level)
223 {
224 struct isst_perf_level_data_info info;
225 int ret;
226
227 info.socket_id = id->pkg;
228 info.power_domain_id = id->punit;
229 info.level = config_index;
230
231 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
232 if (ret == -1)
233 return ret;
234
235 ctdp_level->pkg_tdp = info.thermal_design_power_w;
236 ctdp_level->tdp_ratio = info.tdp_ratio;
237 ctdp_level->sse_p1 = info.base_freq_mhz;
238 ctdp_level->avx2_p1 = info.base_freq_avx2_mhz;
239 ctdp_level->avx512_p1 = info.base_freq_avx512_mhz;
240 ctdp_level->amx_p1 = info.base_freq_amx_mhz;
241
242 ctdp_level->t_proc_hot = info.tjunction_max_c;
243 ctdp_level->mem_freq = info.max_memory_freq_mhz;
244 ctdp_level->cooling_type = info.cooling_type;
245
246 ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
247 ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
248 ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
249
250 debug_printf
251 ("cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO tdp_ratio:%d pkg_tdp:%d ctdp_level->t_proc_hot:%d\n",
252 id->cpu, config_index, ctdp_level->tdp_ratio, ctdp_level->pkg_tdp,
253 ctdp_level->t_proc_hot);
254
255 return 0;
256 }
257
tpmi_get_pwr_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)258 static int tpmi_get_pwr_info(struct isst_id *id, int config_index,
259 struct isst_pkg_ctdp_level_info *ctdp_level)
260 {
261 /* TBD */
262 ctdp_level->pkg_max_power = 0;
263 ctdp_level->pkg_min_power = 0;
264
265 debug_printf
266 ("cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO pkg_max_power:%d pkg_min_power:%d\n",
267 id->cpu, config_index, ctdp_level->pkg_max_power,
268 ctdp_level->pkg_min_power);
269
270 return 0;
271 }
272
tpmi_get_coremask_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)273 int tpmi_get_coremask_info(struct isst_id *id, int config_index,
274 struct isst_pkg_ctdp_level_info *ctdp_level)
275 {
276 struct isst_perf_level_cpu_mask info;
277 int ret, cpu_count;
278
279 info.socket_id = id->pkg;
280 info.power_domain_id = id->punit;
281 info.level = config_index;
282 info.punit_cpu_map = 1;
283
284 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_CPU_MASK, &info);
285 if (ret == -1)
286 return ret;
287
288 set_cpu_mask_from_punit_coremask(id, info.mask,
289 ctdp_level->core_cpumask_size,
290 ctdp_level->core_cpumask, &cpu_count);
291 ctdp_level->cpu_count = cpu_count;
292
293 debug_printf("cpu:%d ctdp:%d core_mask ino cpu count:%d\n",
294 id->cpu, config_index, ctdp_level->cpu_count);
295
296 return 0;
297 }
298
tpmi_get_get_trls(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)299 static int tpmi_get_get_trls(struct isst_id *id, int config_index,
300 struct isst_pkg_ctdp_level_info *ctdp_level)
301 {
302 struct isst_perf_level_data_info info;
303 int ret, i, j;
304
305 info.socket_id = id->pkg;
306 info.power_domain_id = id->punit;
307 info.level = config_index;
308
309 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
310 if (ret == -1)
311 return ret;
312
313 if (info.max_buckets > TRL_MAX_BUCKETS)
314 info.max_buckets = TRL_MAX_BUCKETS;
315
316 if (info.max_trl_levels > TRL_MAX_LEVELS)
317 info.max_trl_levels = TRL_MAX_LEVELS;
318
319 for (i = 0; i < info.max_trl_levels; ++i)
320 for (j = 0; j < info.max_buckets; ++j)
321 ctdp_level->trl_ratios[i][j] = info.trl_freq_mhz[i][j];
322
323 return 0;
324 }
325
tpmi_get_get_trl(struct isst_id * id,int level,int config_index,int * trl)326 static int tpmi_get_get_trl(struct isst_id *id, int level, int config_index,
327 int *trl)
328 {
329 struct isst_pkg_ctdp_level_info ctdp_level;
330 int ret, i;
331
332 ret = tpmi_get_get_trls(id, config_index, &ctdp_level);
333 if (ret)
334 return ret;
335
336 /* FIX ME: Just return for level 0 */
337 for (i = 0; i < 8; ++i)
338 trl[i] = ctdp_level.trl_ratios[0][i];
339
340 return 0;
341 }
342
tpmi_get_trl_bucket_info(struct isst_id * id,int config_index,unsigned long long * buckets_info)343 static int tpmi_get_trl_bucket_info(struct isst_id *id, int config_index,
344 unsigned long long *buckets_info)
345 {
346 struct isst_perf_level_data_info info;
347 unsigned char *mask = (unsigned char *)buckets_info;
348 int ret, i;
349
350 info.socket_id = id->pkg;
351 info.power_domain_id = id->punit;
352 info.level = config_index;
353
354 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
355 if (ret == -1)
356 return ret;
357
358 if (info.max_buckets > TRL_MAX_BUCKETS)
359 info.max_buckets = TRL_MAX_BUCKETS;
360
361 for (i = 0; i < info.max_buckets; ++i)
362 mask[i] = info.bucket_core_counts[i];
363
364 debug_printf("cpu:%d TRL bucket info: 0x%llx\n", id->cpu,
365 *buckets_info);
366
367 return 0;
368 }
369
tpmi_set_tdp_level(struct isst_id * id,int tdp_level)370 static int tpmi_set_tdp_level(struct isst_id *id, int tdp_level)
371 {
372 struct isst_perf_level_control info;
373 int ret;
374
375 info.socket_id = id->pkg;
376 info.power_domain_id = id->punit;
377 info.level = tdp_level;
378
379 ret = tpmi_process_ioctl(ISST_IF_PERF_SET_LEVEL, &info);
380 if (ret == -1)
381 return ret;
382
383 return 0;
384 }
385
_pbf_get_coremask_info(struct isst_id * id,int config_index,struct isst_pbf_info * pbf_info)386 static int _pbf_get_coremask_info(struct isst_id *id, int config_index,
387 struct isst_pbf_info *pbf_info)
388 {
389 struct isst_perf_level_cpu_mask info;
390 int ret, cpu_count;
391
392 info.socket_id = id->pkg;
393 info.power_domain_id = id->punit;
394 info.level = config_index;
395 info.punit_cpu_map = 1;
396
397 ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_CPU_MASK, &info);
398 if (ret == -1)
399 return ret;
400
401 set_cpu_mask_from_punit_coremask(id, info.mask,
402 pbf_info->core_cpumask_size,
403 pbf_info->core_cpumask, &cpu_count);
404
405 debug_printf("cpu:%d ctdp:%d pbf core_mask info cpu count:%d\n",
406 id->cpu, config_index, cpu_count);
407
408 return 0;
409 }
410
tpmi_get_pbf_info(struct isst_id * id,int level,struct isst_pbf_info * pbf_info)411 static int tpmi_get_pbf_info(struct isst_id *id, int level,
412 struct isst_pbf_info *pbf_info)
413 {
414 struct isst_base_freq_info info;
415 int ret;
416
417 info.socket_id = id->pkg;
418 info.power_domain_id = id->punit;
419 info.level = level;
420
421 ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_INFO, &info);
422 if (ret == -1)
423 return ret;
424
425 pbf_info->p1_low = info.low_base_freq_mhz;
426 pbf_info->p1_high = info.high_base_freq_mhz;
427 pbf_info->tdp = info.thermal_design_power_w;
428 pbf_info->t_prochot = info.tjunction_max_c;
429
430 debug_printf("cpu:%d ctdp:%d pbf info:%d:%d:%d:%d\n",
431 id->cpu, level, pbf_info->p1_low, pbf_info->p1_high,
432 pbf_info->tdp, pbf_info->t_prochot);
433
434 return _pbf_get_coremask_info(id, level, pbf_info);
435 }
436
tpmi_set_pbf_fact_status(struct isst_id * id,int pbf,int enable)437 static int tpmi_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
438 {
439 struct isst_pkg_ctdp pkg_dev;
440 struct isst_pkg_ctdp_level_info ctdp_level;
441 int current_level;
442 struct isst_perf_feature_control info;
443 int ret;
444
445 ret = isst_get_ctdp_levels(id, &pkg_dev);
446 if (ret)
447 debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
448
449 current_level = pkg_dev.current_level;
450
451 ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
452 if (ret)
453 return ret;
454
455 info.socket_id = id->pkg;
456 info.power_domain_id = id->punit;
457
458 info.feature = 0;
459
460 if (pbf) {
461 if (ctdp_level.fact_enabled)
462 info.feature |= BIT(1);
463
464 if (enable)
465 info.feature |= BIT(0);
466 else
467 info.feature &= ~BIT(0);
468 } else {
469
470 if (enable && !ctdp_level.sst_cp_enabled)
471 isst_display_error_info_message(0,
472 "Make sure to execute before: core-power enable",
473 0, 0);
474
475 if (ctdp_level.pbf_enabled)
476 info.feature |= BIT(0);
477
478 if (enable)
479 info.feature |= BIT(1);
480 else
481 info.feature &= ~BIT(1);
482 }
483
484 ret = tpmi_process_ioctl(ISST_IF_PERF_SET_FEATURE, &info);
485 if (ret == -1)
486 return ret;
487
488 return 0;
489 }
490
tpmi_get_fact_info(struct isst_id * id,int level,int fact_bucket,struct isst_fact_info * fact_info)491 static int tpmi_get_fact_info(struct isst_id *id, int level, int fact_bucket,
492 struct isst_fact_info *fact_info)
493 {
494 struct isst_turbo_freq_info info;
495 int i, j;
496 int ret;
497
498 info.socket_id = id->pkg;
499 info.power_domain_id = id->punit;
500 info.level = level;
501
502 ret = tpmi_process_ioctl(ISST_IF_GET_TURBO_FREQ_INFO, &info);
503 if (ret == -1)
504 return ret;
505
506 for (i = 0; i < info.max_clip_freqs; ++i)
507 fact_info->lp_ratios[i] = info.lp_clip_freq_mhz[i];
508
509 if (info.max_buckets > TRL_MAX_BUCKETS)
510 info.max_buckets = TRL_MAX_BUCKETS;
511
512 if (info.max_trl_levels > TRL_MAX_LEVELS)
513 info.max_trl_levels = TRL_MAX_LEVELS;
514
515 for (i = 0; i < info.max_trl_levels; ++i) {
516 for (j = 0; j < info.max_buckets; ++j)
517 fact_info->bucket_info[j].hp_ratios[i] =
518 info.trl_freq_mhz[i][j];
519 }
520
521 for (i = 0; i < info.max_buckets; ++i)
522 fact_info->bucket_info[i].hp_cores = info.bucket_core_counts[i];
523
524 return 0;
525 }
526
_set_uncore_min_max(struct isst_id * id,int max,int freq)527 static void _set_uncore_min_max(struct isst_id *id, int max, int freq)
528 {
529 DIR *dir;
530 FILE *filep;
531 struct dirent *entry;
532 char buffer[512];
533 unsigned int tmp_id;
534 int ret;
535
536 dir = opendir("/sys/devices/system/cpu/intel_uncore_frequency/");
537 if (!dir)
538 return;
539
540 while ((entry = readdir(dir)) != NULL ) {
541 /* Check domain_id */
542 snprintf(buffer, sizeof(buffer),
543 "/sys/devices/system/cpu/intel_uncore_frequency/%s/domain_id", entry->d_name);
544
545 filep = fopen(buffer, "r");
546 if (!filep)
547 goto end;
548
549 ret = fscanf(filep, "%u", &tmp_id);
550 fclose(filep);
551 if (ret != 1)
552 goto end;
553
554 if (tmp_id != id->punit)
555 continue;
556
557 /* Check package_id */
558 snprintf(buffer, sizeof(buffer),
559 "/sys/devices/system/cpu/intel_uncore_frequency/%s/package_id", entry->d_name);
560
561 filep = fopen(buffer, "r");
562 if (!filep)
563 goto end;
564
565 ret = fscanf(filep, "%u", &tmp_id);
566 fclose(filep);
567
568 if (ret != 1)
569 goto end;
570
571 if (tmp_id != id->pkg)
572 continue;
573
574 /* Found the right sysfs path, adjust and quit */
575 if (max)
576 snprintf(buffer, sizeof(buffer),
577 "/sys/devices/system/cpu/intel_uncore_frequency/%s/max_freq_khz", entry->d_name);
578 else
579 snprintf(buffer, sizeof(buffer),
580 "/sys/devices/system/cpu/intel_uncore_frequency/%s/min_freq_khz", entry->d_name);
581
582 filep = fopen(buffer, "w");
583 if (!filep)
584 goto end;
585
586 fprintf(filep, "%d\n", freq);
587 fclose(filep);
588 break;
589 }
590
591 end:
592 closedir(dir);
593 }
594
tpmi_adjust_uncore_freq(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)595 static void tpmi_adjust_uncore_freq(struct isst_id *id, int config_index,
596 struct isst_pkg_ctdp_level_info *ctdp_level)
597 {
598 struct isst_perf_level_data_info info;
599 int ret;
600
601 info.socket_id = id->pkg;
602 info.power_domain_id = id->punit;
603 info.level = config_index;
604
605 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
606 if (ret == -1)
607 return;
608
609 ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
610 ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
611 ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
612
613 if (ctdp_level->uncore_pm)
614 _set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
615
616 if (ctdp_level->uncore_p0)
617 _set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
618
619 return;
620 }
621
tpmi_get_clos_information(struct isst_id * id,int * enable,int * type)622 static int tpmi_get_clos_information(struct isst_id *id, int *enable, int *type)
623 {
624 struct isst_core_power info;
625 int ret;
626
627 info.get_set = 0;
628 info.socket_id = id->pkg;
629 info.power_domain_id = id->punit;
630 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
631 if (ret == -1)
632 return ret;
633
634 *enable = info.enable;
635 *type = info.priority_type;
636
637 return 0;
638 }
639
tpmi_pm_qos_config(struct isst_id * id,int enable_clos,int priority_type)640 static int tpmi_pm_qos_config(struct isst_id *id, int enable_clos,
641 int priority_type)
642 {
643 struct isst_core_power info;
644 int i, ret, saved_punit;
645
646 info.get_set = 1;
647 info.socket_id = id->pkg;
648 info.power_domain_id = id->punit;
649 info.enable = enable_clos;
650 info.priority_type = priority_type;
651
652 saved_punit = id->punit;
653
654 /* Set for all other dies also. This is per package setting */
655 for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
656 id->punit = i;
657 if (isst_is_punit_valid(id)) {
658 info.power_domain_id = i;
659 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
660 if (ret == -1) {
661 id->punit = saved_punit;
662 return ret;
663 }
664 }
665 }
666
667 id->punit = saved_punit;
668
669 return 0;
670 }
671
tpmi_pm_get_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)672 int tpmi_pm_get_clos(struct isst_id *id, int clos,
673 struct isst_clos_config *clos_config)
674 {
675 struct isst_clos_param info;
676 int ret;
677
678 info.get_set = 0;
679 info.socket_id = id->pkg;
680 info.power_domain_id = id->punit;
681 info.clos = clos;
682
683 ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
684 if (ret == -1)
685 return ret;
686
687 clos_config->epp = 0;
688 clos_config->clos_prop_prio = info.prop_prio;
689 clos_config->clos_min = info.min_freq_mhz;
690 clos_config->clos_max = info.max_freq_mhz;
691 clos_config->clos_desired = 0;
692
693 debug_printf("cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
694 clos_config->clos_min, clos_config->clos_max);
695
696 return 0;
697 }
698
tpmi_set_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)699 int tpmi_set_clos(struct isst_id *id, int clos,
700 struct isst_clos_config *clos_config)
701 {
702 struct isst_clos_param info;
703 int i, ret, saved_punit;
704
705 info.get_set = 1;
706 info.socket_id = id->pkg;
707 info.power_domain_id = id->punit;
708 info.clos = clos;
709 info.prop_prio = clos_config->clos_prop_prio;
710
711 info.min_freq_mhz = clos_config->clos_min;
712 info.max_freq_mhz = clos_config->clos_max;
713
714 if (info.min_freq_mhz <= 0xff)
715 info.min_freq_mhz *= 100;
716 if (info.max_freq_mhz <= 0xff)
717 info.max_freq_mhz *= 100;
718
719 saved_punit = id->punit;
720
721 /* Set for all other dies also. This is per package setting */
722 for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
723 id->punit = i;
724 if (isst_is_punit_valid(id)) {
725 info.power_domain_id = i;
726 ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
727 if (ret == -1) {
728 id->punit = saved_punit;
729 return ret;
730 }
731 }
732 }
733
734 id->punit = saved_punit;
735
736 debug_printf("set cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
737 clos_config->clos_min, clos_config->clos_max);
738
739 return 0;
740 }
741
tpmi_clos_get_assoc_status(struct isst_id * id,int * clos_id)742 static int tpmi_clos_get_assoc_status(struct isst_id *id, int *clos_id)
743 {
744 struct isst_if_clos_assoc_cmds assoc_cmds;
745 int ret;
746
747 assoc_cmds.cmd_count = 1;
748 assoc_cmds.get_set = 0;
749 assoc_cmds.punit_cpu_map = 1;
750 assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
751 assoc_cmds.assoc_info[0].socket_id = id->pkg;
752 assoc_cmds.assoc_info[0].power_domain_id = id->punit;
753
754 ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
755 if (ret == -1)
756 return ret;
757
758 *clos_id = assoc_cmds.assoc_info[0].clos;
759
760 return 0;
761 }
762
tpmi_clos_associate(struct isst_id * id,int clos_id)763 static int tpmi_clos_associate(struct isst_id *id, int clos_id)
764 {
765 struct isst_if_clos_assoc_cmds assoc_cmds;
766 int ret;
767
768 assoc_cmds.cmd_count = 1;
769 assoc_cmds.get_set = 1;
770 assoc_cmds.punit_cpu_map = 1;
771 assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
772 assoc_cmds.assoc_info[0].clos = clos_id;
773 assoc_cmds.assoc_info[0].socket_id = id->pkg;
774 assoc_cmds.assoc_info[0].power_domain_id = id->punit;
775
776 ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
777 if (ret == -1)
778 return ret;
779
780 return 0;
781 }
782
783 static struct isst_platform_ops tpmi_ops = {
784 .get_disp_freq_multiplier = tpmi_get_disp_freq_multiplier,
785 .get_trl_max_levels = tpmi_get_trl_max_levels,
786 .get_trl_level_name = tpmi_get_trl_level_name,
787 .update_platform_param = tpmi_update_platform_param,
788 .is_punit_valid = tpmi_is_punit_valid,
789 .read_pm_config = tpmi_read_pm_config,
790 .get_config_levels = tpmi_get_config_levels,
791 .get_ctdp_control = tpmi_get_ctdp_control,
792 .get_tdp_info = tpmi_get_tdp_info,
793 .get_pwr_info = tpmi_get_pwr_info,
794 .get_coremask_info = tpmi_get_coremask_info,
795 .get_get_trl = tpmi_get_get_trl,
796 .get_get_trls = tpmi_get_get_trls,
797 .get_trl_bucket_info = tpmi_get_trl_bucket_info,
798 .set_tdp_level = tpmi_set_tdp_level,
799 .get_pbf_info = tpmi_get_pbf_info,
800 .set_pbf_fact_status = tpmi_set_pbf_fact_status,
801 .get_fact_info = tpmi_get_fact_info,
802 .adjust_uncore_freq = tpmi_adjust_uncore_freq,
803 .get_clos_information = tpmi_get_clos_information,
804 .pm_qos_config = tpmi_pm_qos_config,
805 .pm_get_clos = tpmi_pm_get_clos,
806 .set_clos = tpmi_set_clos,
807 .clos_get_assoc_status = tpmi_clos_get_assoc_status,
808 .clos_associate = tpmi_clos_associate,
809 };
810
tpmi_get_platform_ops(void)811 struct isst_platform_ops *tpmi_get_platform_ops(void)
812 {
813 return &tpmi_ops;
814 }
815