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 if (api_version() > 2) {
198 ctdp_level->fact_support = info.sst_tf_support & BIT(config_index);
199 ctdp_level->pbf_support = info.sst_bf_support & BIT(config_index);
200 } else {
201 ctdp_level->fact_support = info.sst_tf_support;
202 ctdp_level->pbf_support = info.sst_bf_support;
203 }
204
205 ctdp_level->fact_enabled = !!(info.feature_state & BIT(1));
206 ctdp_level->pbf_enabled = !!(info.feature_state & BIT(0));
207
208 core_power_info.get_set = 0;
209 core_power_info.socket_id = id->pkg;
210 core_power_info.power_domain_id = id->punit;
211
212 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &core_power_info);
213 if (ret == -1)
214 return ret;
215
216 ctdp_level->sst_cp_support = core_power_info.supported;
217 ctdp_level->sst_cp_enabled = core_power_info.enable;
218
219 debug_printf
220 ("cpu:%d CONFIG_TDP_GET_TDP_CONTROL fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
221 id->cpu, ctdp_level->fact_support, ctdp_level->pbf_support,
222 ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
223
224 return 0;
225 }
226
tpmi_get_tdp_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)227 static int tpmi_get_tdp_info(struct isst_id *id, int config_index,
228 struct isst_pkg_ctdp_level_info *ctdp_level)
229 {
230 struct isst_perf_level_data_info info;
231 int ret;
232
233 info.socket_id = id->pkg;
234 info.power_domain_id = id->punit;
235 info.level = config_index;
236
237 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
238 if (ret == -1)
239 return ret;
240
241 ctdp_level->pkg_tdp = info.thermal_design_power_w;
242 ctdp_level->tdp_ratio = info.tdp_ratio;
243 ctdp_level->sse_p1 = info.base_freq_mhz;
244 ctdp_level->avx2_p1 = info.base_freq_avx2_mhz;
245 ctdp_level->avx512_p1 = info.base_freq_avx512_mhz;
246 ctdp_level->amx_p1 = info.base_freq_amx_mhz;
247
248 ctdp_level->t_proc_hot = info.tjunction_max_c;
249 ctdp_level->mem_freq = info.max_memory_freq_mhz;
250 ctdp_level->cooling_type = info.cooling_type;
251
252 ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
253 ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
254 ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
255
256 debug_printf
257 ("cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO tdp_ratio:%d pkg_tdp:%d ctdp_level->t_proc_hot:%d\n",
258 id->cpu, config_index, ctdp_level->tdp_ratio, ctdp_level->pkg_tdp,
259 ctdp_level->t_proc_hot);
260
261 return 0;
262 }
263
tpmi_get_pwr_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)264 static int tpmi_get_pwr_info(struct isst_id *id, int config_index,
265 struct isst_pkg_ctdp_level_info *ctdp_level)
266 {
267 /* TBD */
268 ctdp_level->pkg_max_power = 0;
269 ctdp_level->pkg_min_power = 0;
270
271 debug_printf
272 ("cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO pkg_max_power:%d pkg_min_power:%d\n",
273 id->cpu, config_index, ctdp_level->pkg_max_power,
274 ctdp_level->pkg_min_power);
275
276 return 0;
277 }
278
tpmi_get_coremask_info(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)279 int tpmi_get_coremask_info(struct isst_id *id, int config_index,
280 struct isst_pkg_ctdp_level_info *ctdp_level)
281 {
282 struct isst_perf_level_cpu_mask info;
283 int ret, cpu_count;
284
285 info.socket_id = id->pkg;
286 info.power_domain_id = id->punit;
287 info.level = config_index;
288 info.punit_cpu_map = 1;
289
290 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_CPU_MASK, &info);
291 if (ret == -1)
292 return ret;
293
294 set_cpu_mask_from_punit_coremask(id, info.mask,
295 ctdp_level->core_cpumask_size,
296 ctdp_level->core_cpumask, &cpu_count);
297 ctdp_level->cpu_count = cpu_count;
298
299 debug_printf("cpu:%d ctdp:%d core_mask ino cpu count:%d\n",
300 id->cpu, config_index, ctdp_level->cpu_count);
301
302 return 0;
303 }
304
tpmi_get_get_trls(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)305 static int tpmi_get_get_trls(struct isst_id *id, int config_index,
306 struct isst_pkg_ctdp_level_info *ctdp_level)
307 {
308 struct isst_perf_level_data_info info;
309 int ret, i, j;
310
311 info.socket_id = id->pkg;
312 info.power_domain_id = id->punit;
313 info.level = config_index;
314
315 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
316 if (ret == -1)
317 return ret;
318
319 if (info.max_buckets > TRL_MAX_BUCKETS)
320 info.max_buckets = TRL_MAX_BUCKETS;
321
322 if (info.max_trl_levels > TRL_MAX_LEVELS)
323 info.max_trl_levels = TRL_MAX_LEVELS;
324
325 for (i = 0; i < info.max_trl_levels; ++i)
326 for (j = 0; j < info.max_buckets; ++j)
327 ctdp_level->trl_ratios[i][j] = info.trl_freq_mhz[i][j];
328
329 return 0;
330 }
331
tpmi_get_get_trl(struct isst_id * id,int level,int config_index,int * trl)332 static int tpmi_get_get_trl(struct isst_id *id, int level, int config_index,
333 int *trl)
334 {
335 struct isst_pkg_ctdp_level_info ctdp_level;
336 int ret, i;
337
338 ret = tpmi_get_get_trls(id, config_index, &ctdp_level);
339 if (ret)
340 return ret;
341
342 /* FIX ME: Just return for level 0 */
343 for (i = 0; i < 8; ++i)
344 trl[i] = ctdp_level.trl_ratios[0][i];
345
346 return 0;
347 }
348
tpmi_get_trl_bucket_info(struct isst_id * id,int config_index,unsigned long long * buckets_info)349 static int tpmi_get_trl_bucket_info(struct isst_id *id, int config_index,
350 unsigned long long *buckets_info)
351 {
352 struct isst_perf_level_data_info info;
353 unsigned char *mask = (unsigned char *)buckets_info;
354 int ret, i;
355
356 info.socket_id = id->pkg;
357 info.power_domain_id = id->punit;
358 info.level = config_index;
359
360 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
361 if (ret == -1)
362 return ret;
363
364 if (info.max_buckets > TRL_MAX_BUCKETS)
365 info.max_buckets = TRL_MAX_BUCKETS;
366
367 for (i = 0; i < info.max_buckets; ++i)
368 mask[i] = info.bucket_core_counts[i];
369
370 debug_printf("cpu:%d TRL bucket info: 0x%llx\n", id->cpu,
371 *buckets_info);
372
373 return 0;
374 }
375
tpmi_set_tdp_level(struct isst_id * id,int tdp_level)376 static int tpmi_set_tdp_level(struct isst_id *id, int tdp_level)
377 {
378 struct isst_perf_level_control info;
379 int ret;
380
381 info.socket_id = id->pkg;
382 info.power_domain_id = id->punit;
383 info.level = tdp_level;
384
385 ret = tpmi_process_ioctl(ISST_IF_PERF_SET_LEVEL, &info);
386 if (ret == -1)
387 return ret;
388
389 return 0;
390 }
391
_pbf_get_coremask_info(struct isst_id * id,int config_index,struct isst_pbf_info * pbf_info)392 static int _pbf_get_coremask_info(struct isst_id *id, int config_index,
393 struct isst_pbf_info *pbf_info)
394 {
395 struct isst_perf_level_cpu_mask info;
396 int ret, cpu_count;
397
398 info.socket_id = id->pkg;
399 info.power_domain_id = id->punit;
400 info.level = config_index;
401 info.punit_cpu_map = 1;
402
403 ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_CPU_MASK, &info);
404 if (ret == -1)
405 return ret;
406
407 set_cpu_mask_from_punit_coremask(id, info.mask,
408 pbf_info->core_cpumask_size,
409 pbf_info->core_cpumask, &cpu_count);
410
411 debug_printf("cpu:%d ctdp:%d pbf core_mask info cpu count:%d\n",
412 id->cpu, config_index, cpu_count);
413
414 return 0;
415 }
416
tpmi_get_pbf_info(struct isst_id * id,int level,struct isst_pbf_info * pbf_info)417 static int tpmi_get_pbf_info(struct isst_id *id, int level,
418 struct isst_pbf_info *pbf_info)
419 {
420 struct isst_base_freq_info info;
421 int ret;
422
423 info.socket_id = id->pkg;
424 info.power_domain_id = id->punit;
425 info.level = level;
426
427 ret = tpmi_process_ioctl(ISST_IF_GET_BASE_FREQ_INFO, &info);
428 if (ret == -1)
429 return ret;
430
431 pbf_info->p1_low = info.low_base_freq_mhz;
432 pbf_info->p1_high = info.high_base_freq_mhz;
433 pbf_info->tdp = info.thermal_design_power_w;
434 pbf_info->t_prochot = info.tjunction_max_c;
435
436 debug_printf("cpu:%d ctdp:%d pbf info:%d:%d:%d:%d\n",
437 id->cpu, level, pbf_info->p1_low, pbf_info->p1_high,
438 pbf_info->tdp, pbf_info->t_prochot);
439
440 return _pbf_get_coremask_info(id, level, pbf_info);
441 }
442
tpmi_set_pbf_fact_status(struct isst_id * id,int pbf,int enable)443 static int tpmi_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
444 {
445 struct isst_pkg_ctdp pkg_dev;
446 struct isst_pkg_ctdp_level_info ctdp_level;
447 int current_level;
448 struct isst_perf_feature_control info;
449 int ret;
450
451 ret = isst_get_ctdp_levels(id, &pkg_dev);
452 if (ret)
453 debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
454
455 current_level = pkg_dev.current_level;
456
457 ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
458 if (ret)
459 return ret;
460
461 info.socket_id = id->pkg;
462 info.power_domain_id = id->punit;
463
464 info.feature = 0;
465
466 if (pbf) {
467 if (ctdp_level.fact_enabled)
468 info.feature |= BIT(1);
469
470 if (enable)
471 info.feature |= BIT(0);
472 else
473 info.feature &= ~BIT(0);
474 } else {
475
476 if (enable && !ctdp_level.sst_cp_enabled)
477 isst_display_error_info_message(0,
478 "Make sure to execute before: core-power enable",
479 0, 0);
480
481 if (ctdp_level.pbf_enabled)
482 info.feature |= BIT(0);
483
484 if (enable)
485 info.feature |= BIT(1);
486 else
487 info.feature &= ~BIT(1);
488 }
489
490 ret = tpmi_process_ioctl(ISST_IF_PERF_SET_FEATURE, &info);
491 if (ret == -1)
492 return ret;
493
494 return 0;
495 }
496
tpmi_get_fact_info(struct isst_id * id,int level,int fact_bucket,struct isst_fact_info * fact_info)497 static int tpmi_get_fact_info(struct isst_id *id, int level, int fact_bucket,
498 struct isst_fact_info *fact_info)
499 {
500 struct isst_turbo_freq_info info;
501 int i, j;
502 int ret;
503
504 info.socket_id = id->pkg;
505 info.power_domain_id = id->punit;
506 info.level = level;
507
508 ret = tpmi_process_ioctl(ISST_IF_GET_TURBO_FREQ_INFO, &info);
509 if (ret == -1)
510 return ret;
511
512 for (i = 0; i < info.max_clip_freqs; ++i)
513 fact_info->lp_ratios[i] = info.lp_clip_freq_mhz[i];
514
515 if (info.max_buckets > TRL_MAX_BUCKETS)
516 info.max_buckets = TRL_MAX_BUCKETS;
517
518 if (info.max_trl_levels > TRL_MAX_LEVELS)
519 info.max_trl_levels = TRL_MAX_LEVELS;
520
521 for (i = 0; i < info.max_trl_levels; ++i) {
522 for (j = 0; j < info.max_buckets; ++j)
523 fact_info->bucket_info[j].hp_ratios[i] =
524 info.trl_freq_mhz[i][j];
525 }
526
527 for (i = 0; i < info.max_buckets; ++i)
528 fact_info->bucket_info[i].hp_cores = info.bucket_core_counts[i];
529
530 return 0;
531 }
532
_set_uncore_min_max(struct isst_id * id,int max,int freq)533 static void _set_uncore_min_max(struct isst_id *id, int max, int freq)
534 {
535 DIR *dir;
536 FILE *filep;
537 struct dirent *entry;
538 char buffer[512];
539 unsigned int tmp_id;
540 int ret;
541
542 dir = opendir("/sys/devices/system/cpu/intel_uncore_frequency/");
543 if (!dir)
544 return;
545
546 while ((entry = readdir(dir)) != NULL ) {
547 /* Check domain_id */
548 snprintf(buffer, sizeof(buffer),
549 "/sys/devices/system/cpu/intel_uncore_frequency/%s/domain_id", entry->d_name);
550
551 filep = fopen(buffer, "r");
552 if (!filep)
553 goto end;
554
555 ret = fscanf(filep, "%u", &tmp_id);
556 fclose(filep);
557 if (ret != 1)
558 goto end;
559
560 if (tmp_id != id->punit)
561 continue;
562
563 /* Check package_id */
564 snprintf(buffer, sizeof(buffer),
565 "/sys/devices/system/cpu/intel_uncore_frequency/%s/package_id", entry->d_name);
566
567 filep = fopen(buffer, "r");
568 if (!filep)
569 goto end;
570
571 ret = fscanf(filep, "%u", &tmp_id);
572 fclose(filep);
573
574 if (ret != 1)
575 goto end;
576
577 if (tmp_id != id->pkg)
578 continue;
579
580 /* Found the right sysfs path, adjust and quit */
581 if (max)
582 snprintf(buffer, sizeof(buffer),
583 "/sys/devices/system/cpu/intel_uncore_frequency/%s/max_freq_khz", entry->d_name);
584 else
585 snprintf(buffer, sizeof(buffer),
586 "/sys/devices/system/cpu/intel_uncore_frequency/%s/min_freq_khz", entry->d_name);
587
588 filep = fopen(buffer, "w");
589 if (!filep)
590 goto end;
591
592 fprintf(filep, "%d\n", freq);
593 fclose(filep);
594 break;
595 }
596
597 end:
598 closedir(dir);
599 }
600
tpmi_adjust_uncore_freq(struct isst_id * id,int config_index,struct isst_pkg_ctdp_level_info * ctdp_level)601 static void tpmi_adjust_uncore_freq(struct isst_id *id, int config_index,
602 struct isst_pkg_ctdp_level_info *ctdp_level)
603 {
604 struct isst_perf_level_data_info info;
605 int ret;
606
607 info.socket_id = id->pkg;
608 info.power_domain_id = id->punit;
609 info.level = config_index;
610
611 ret = tpmi_process_ioctl(ISST_IF_GET_PERF_LEVEL_INFO, &info);
612 if (ret == -1)
613 return;
614
615 ctdp_level->uncore_p0 = info.p0_fabric_freq_mhz;
616 ctdp_level->uncore_p1 = info.p1_fabric_freq_mhz;
617 ctdp_level->uncore_pm = info.pm_fabric_freq_mhz;
618
619 if (ctdp_level->uncore_pm)
620 _set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
621
622 if (ctdp_level->uncore_p0)
623 _set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
624
625 return;
626 }
627
tpmi_get_clos_information(struct isst_id * id,int * enable,int * type)628 static int tpmi_get_clos_information(struct isst_id *id, int *enable, int *type)
629 {
630 struct isst_core_power info;
631 int ret;
632
633 info.get_set = 0;
634 info.socket_id = id->pkg;
635 info.power_domain_id = id->punit;
636 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
637 if (ret == -1)
638 return ret;
639
640 *enable = info.enable;
641 *type = info.priority_type;
642
643 return 0;
644 }
645
tpmi_pm_qos_config(struct isst_id * id,int enable_clos,int priority_type)646 static int tpmi_pm_qos_config(struct isst_id *id, int enable_clos,
647 int priority_type)
648 {
649 struct isst_core_power info;
650 int i, ret, saved_punit;
651
652 info.get_set = 1;
653 info.socket_id = id->pkg;
654 info.power_domain_id = id->punit;
655 info.enable = enable_clos;
656 info.priority_type = priority_type;
657
658 saved_punit = id->punit;
659
660 /* Set for all other dies also. This is per package setting */
661 for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
662 id->punit = i;
663 if (isst_is_punit_valid(id)) {
664 info.power_domain_id = i;
665 ret = tpmi_process_ioctl(ISST_IF_CORE_POWER_STATE, &info);
666 if (ret == -1) {
667 id->punit = saved_punit;
668 return ret;
669 }
670 }
671 }
672
673 id->punit = saved_punit;
674
675 return 0;
676 }
677
tpmi_pm_get_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)678 int tpmi_pm_get_clos(struct isst_id *id, int clos,
679 struct isst_clos_config *clos_config)
680 {
681 struct isst_clos_param info;
682 int ret;
683
684 info.get_set = 0;
685 info.socket_id = id->pkg;
686 info.power_domain_id = id->punit;
687 info.clos = clos;
688
689 ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
690 if (ret == -1)
691 return ret;
692
693 clos_config->epp = 0;
694 clos_config->clos_prop_prio = info.prop_prio;
695 clos_config->clos_min = info.min_freq_mhz;
696 clos_config->clos_max = info.max_freq_mhz;
697 clos_config->clos_desired = 0;
698
699 debug_printf("cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
700 clos_config->clos_min, clos_config->clos_max);
701
702 return 0;
703 }
704
tpmi_set_clos(struct isst_id * id,int clos,struct isst_clos_config * clos_config)705 int tpmi_set_clos(struct isst_id *id, int clos,
706 struct isst_clos_config *clos_config)
707 {
708 struct isst_clos_param info;
709 int i, ret, saved_punit;
710
711 info.get_set = 1;
712 info.socket_id = id->pkg;
713 info.power_domain_id = id->punit;
714 info.clos = clos;
715 info.prop_prio = clos_config->clos_prop_prio;
716
717 info.min_freq_mhz = clos_config->clos_min;
718 info.max_freq_mhz = clos_config->clos_max;
719
720 if (info.min_freq_mhz <= 0xff)
721 info.min_freq_mhz *= 100;
722 if (info.max_freq_mhz <= 0xff)
723 info.max_freq_mhz *= 100;
724
725 saved_punit = id->punit;
726
727 /* Set for all other dies also. This is per package setting */
728 for (i = 0; i < MAX_PUNIT_PER_DIE; i++) {
729 id->punit = i;
730 if (isst_is_punit_valid(id)) {
731 info.power_domain_id = i;
732 ret = tpmi_process_ioctl(ISST_IF_CLOS_PARAM, &info);
733 if (ret == -1) {
734 id->punit = saved_punit;
735 return ret;
736 }
737 }
738 }
739
740 id->punit = saved_punit;
741
742 debug_printf("set cpu:%d clos:%d min:%d max:%d\n", id->cpu, clos,
743 clos_config->clos_min, clos_config->clos_max);
744
745 return 0;
746 }
747
tpmi_clos_get_assoc_status(struct isst_id * id,int * clos_id)748 static int tpmi_clos_get_assoc_status(struct isst_id *id, int *clos_id)
749 {
750 struct isst_if_clos_assoc_cmds assoc_cmds;
751 int ret;
752
753 assoc_cmds.cmd_count = 1;
754 assoc_cmds.get_set = 0;
755 assoc_cmds.punit_cpu_map = 1;
756 assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
757 assoc_cmds.assoc_info[0].socket_id = id->pkg;
758 assoc_cmds.assoc_info[0].power_domain_id = id->punit;
759
760 ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
761 if (ret == -1)
762 return ret;
763
764 *clos_id = assoc_cmds.assoc_info[0].clos;
765
766 return 0;
767 }
768
tpmi_clos_associate(struct isst_id * id,int clos_id)769 static int tpmi_clos_associate(struct isst_id *id, int clos_id)
770 {
771 struct isst_if_clos_assoc_cmds assoc_cmds;
772 int ret;
773
774 assoc_cmds.cmd_count = 1;
775 assoc_cmds.get_set = 1;
776 assoc_cmds.punit_cpu_map = 1;
777 assoc_cmds.assoc_info[0].logical_cpu = find_phy_core_num(id->cpu);
778 assoc_cmds.assoc_info[0].clos = clos_id;
779 assoc_cmds.assoc_info[0].socket_id = id->pkg;
780 assoc_cmds.assoc_info[0].power_domain_id = id->punit;
781
782 ret = tpmi_process_ioctl(ISST_IF_CLOS_ASSOC, &assoc_cmds);
783 if (ret == -1)
784 return ret;
785
786 return 0;
787 }
788
789 static struct isst_platform_ops tpmi_ops = {
790 .get_disp_freq_multiplier = tpmi_get_disp_freq_multiplier,
791 .get_trl_max_levels = tpmi_get_trl_max_levels,
792 .get_trl_level_name = tpmi_get_trl_level_name,
793 .update_platform_param = tpmi_update_platform_param,
794 .is_punit_valid = tpmi_is_punit_valid,
795 .read_pm_config = tpmi_read_pm_config,
796 .get_config_levels = tpmi_get_config_levels,
797 .get_ctdp_control = tpmi_get_ctdp_control,
798 .get_tdp_info = tpmi_get_tdp_info,
799 .get_pwr_info = tpmi_get_pwr_info,
800 .get_coremask_info = tpmi_get_coremask_info,
801 .get_get_trl = tpmi_get_get_trl,
802 .get_get_trls = tpmi_get_get_trls,
803 .get_trl_bucket_info = tpmi_get_trl_bucket_info,
804 .set_tdp_level = tpmi_set_tdp_level,
805 .get_pbf_info = tpmi_get_pbf_info,
806 .set_pbf_fact_status = tpmi_set_pbf_fact_status,
807 .get_fact_info = tpmi_get_fact_info,
808 .adjust_uncore_freq = tpmi_adjust_uncore_freq,
809 .get_clos_information = tpmi_get_clos_information,
810 .pm_qos_config = tpmi_pm_qos_config,
811 .pm_get_clos = tpmi_pm_get_clos,
812 .set_clos = tpmi_set_clos,
813 .clos_get_assoc_status = tpmi_clos_get_assoc_status,
814 .clos_associate = tpmi_clos_associate,
815 };
816
tpmi_get_platform_ops(void)817 struct isst_platform_ops *tpmi_get_platform_ops(void)
818 {
819 return &tpmi_ops;
820 }
821