Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/power/x86/intel-speed-select/isst-core-mbox.c
26289 views
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_delay;
9
static int mbox_retries = 3;
10
11
#define MAX_TRL_LEVELS_EMR 5
12
13
static int mbox_get_disp_freq_multiplier(void)
14
{
15
return DISP_FREQ_MULTIPLIER;
16
}
17
18
static int mbox_get_trl_max_levels(void)
19
{
20
if (is_emr_platform())
21
return MAX_TRL_LEVELS_EMR;
22
23
return 3;
24
}
25
26
static char *mbox_get_trl_level_name(int level)
27
{
28
if (is_emr_platform()) {
29
static char level_str[18];
30
31
if (level >= MAX_TRL_LEVELS_EMR)
32
return NULL;
33
34
snprintf(level_str, sizeof(level_str), "level-%d", level);
35
return level_str;
36
}
37
38
switch (level) {
39
case 0:
40
return "sse";
41
case 1:
42
return "avx2";
43
case 2:
44
return "avx512";
45
default:
46
return NULL;
47
}
48
}
49
50
static void mbox_update_platform_param(enum isst_platform_param param, int value)
51
{
52
switch (param) {
53
case ISST_PARAM_MBOX_DELAY:
54
mbox_delay = value;
55
break;
56
case ISST_PARAM_MBOX_RETRIES:
57
mbox_retries = value;
58
break;
59
default:
60
break;
61
}
62
}
63
64
static int mbox_is_punit_valid(struct isst_id *id)
65
{
66
if (id->cpu < 0)
67
return 0;
68
69
if (id->pkg < 0 || id->die < 0 || id->punit)
70
return 0;
71
72
return 1;
73
}
74
75
static int _send_mmio_command(unsigned int cpu, unsigned int reg, int write,
76
unsigned int *value)
77
{
78
struct isst_if_io_regs io_regs;
79
const char *pathname = "/dev/isst_interface";
80
int cmd;
81
FILE *outf = get_output_file();
82
int fd;
83
84
debug_printf("mmio_cmd cpu:%d reg:%d write:%d\n", cpu, reg, write);
85
86
fd = open(pathname, O_RDWR);
87
if (fd < 0)
88
err(-1, "%s open failed", pathname);
89
90
io_regs.req_count = 1;
91
io_regs.io_reg[0].logical_cpu = cpu;
92
io_regs.io_reg[0].reg = reg;
93
cmd = ISST_IF_IO_CMD;
94
if (write) {
95
io_regs.io_reg[0].read_write = 1;
96
io_regs.io_reg[0].value = *value;
97
} else {
98
io_regs.io_reg[0].read_write = 0;
99
}
100
101
if (ioctl(fd, cmd, &io_regs) == -1) {
102
if (errno == ENOTTY) {
103
perror("ISST_IF_IO_COMMAND\n");
104
fprintf(stderr, "Check presence of kernel modules: isst_if_mmio\n");
105
exit(0);
106
}
107
fprintf(outf, "Error: mmio_cmd cpu:%d reg:%x read_write:%x\n",
108
cpu, reg, write);
109
} else {
110
if (!write)
111
*value = io_regs.io_reg[0].value;
112
113
debug_printf(
114
"mmio_cmd response: cpu:%d reg:%x rd_write:%x resp:%x\n",
115
cpu, reg, write, *value);
116
}
117
118
close(fd);
119
120
return 0;
121
}
122
123
int _send_mbox_command(unsigned int cpu, unsigned char command,
124
unsigned char sub_command, unsigned int parameter,
125
unsigned int req_data, unsigned int *resp)
126
{
127
const char *pathname = "/dev/isst_interface";
128
int fd, retry;
129
struct isst_if_mbox_cmds mbox_cmds = { 0 };
130
131
debug_printf(
132
"mbox_send: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x\n",
133
cpu, command, sub_command, parameter, req_data);
134
135
if (!is_skx_based_platform() && command == CONFIG_CLOS &&
136
sub_command != CLOS_PM_QOS_CONFIG) {
137
unsigned int value;
138
int write = 0;
139
int clos_id, core_id, ret = 0;
140
141
debug_printf("CPU %d\n", cpu);
142
143
if (parameter & BIT(MBOX_CMD_WRITE_BIT)) {
144
value = req_data;
145
write = 1;
146
}
147
148
switch (sub_command) {
149
case CLOS_PQR_ASSOC:
150
core_id = parameter & 0xff;
151
ret = _send_mmio_command(
152
cpu, PQR_ASSOC_OFFSET + core_id * 4, write,
153
&value);
154
if (!ret && !write)
155
*resp = value;
156
break;
157
case CLOS_PM_CLOS:
158
clos_id = parameter & 0x03;
159
ret = _send_mmio_command(
160
cpu, PM_CLOS_OFFSET + clos_id * 4, write,
161
&value);
162
if (!ret && !write)
163
*resp = value;
164
break;
165
case CLOS_STATUS:
166
break;
167
default:
168
break;
169
}
170
return ret;
171
}
172
173
mbox_cmds.cmd_count = 1;
174
mbox_cmds.mbox_cmd[0].logical_cpu = cpu;
175
mbox_cmds.mbox_cmd[0].command = command;
176
mbox_cmds.mbox_cmd[0].sub_command = sub_command;
177
mbox_cmds.mbox_cmd[0].parameter = parameter;
178
mbox_cmds.mbox_cmd[0].req_data = req_data;
179
180
if (mbox_delay)
181
usleep(mbox_delay * 1000);
182
183
fd = open(pathname, O_RDWR);
184
if (fd < 0)
185
err(-1, "%s open failed", pathname);
186
187
retry = mbox_retries;
188
do {
189
if (ioctl(fd, ISST_IF_MBOX_COMMAND, &mbox_cmds) == -1) {
190
if (errno == ENOTTY) {
191
perror("ISST_IF_MBOX_COMMAND\n");
192
fprintf(stderr, "Check presence of kernel modules: isst_if_mbox_pci or isst_if_mbox_msr\n");
193
exit(0);
194
}
195
debug_printf(
196
"Error: mbox_cmd cpu:%d command:%x sub_command:%x parameter:%x req_data:%x errorno:%d\n",
197
cpu, command, sub_command, parameter, req_data, errno);
198
--retry;
199
} else {
200
*resp = mbox_cmds.mbox_cmd[0].resp_data;
201
debug_printf(
202
"mbox_cmd response: cpu:%d command:%x sub_command:%x parameter:%x req_data:%x resp:%x\n",
203
cpu, command, sub_command, parameter, req_data, *resp);
204
break;
205
}
206
} while (retry);
207
208
close(fd);
209
210
if (!retry) {
211
debug_printf("Failed mbox command even after retries\n");
212
return -1;
213
214
}
215
216
return 0;
217
}
218
219
static int mbox_read_pm_config(struct isst_id *id, int *cp_state, int *cp_cap)
220
{
221
unsigned int resp;
222
int ret;
223
224
ret = _send_mbox_command(id->cpu, READ_PM_CONFIG, PM_FEATURE, 0, 0,
225
&resp);
226
if (ret)
227
return ret;
228
229
debug_printf("cpu:%d READ_PM_CONFIG resp:%x\n", id->cpu, resp);
230
231
*cp_state = resp & BIT(16);
232
*cp_cap = resp & BIT(0) ? 1 : 0;
233
234
return 0;
235
}
236
237
static int mbox_get_config_levels(struct isst_id *id, struct isst_pkg_ctdp *pkg_dev)
238
{
239
unsigned int resp;
240
int ret;
241
242
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
243
CONFIG_TDP_GET_LEVELS_INFO, 0, 0, &resp);
244
if (ret) {
245
pkg_dev->levels = 0;
246
pkg_dev->locked = 1;
247
pkg_dev->current_level = 0;
248
pkg_dev->version = 0;
249
pkg_dev->enabled = 0;
250
return 0;
251
}
252
253
debug_printf("cpu:%d CONFIG_TDP_GET_LEVELS_INFO resp:%x\n", id->cpu, resp);
254
255
pkg_dev->version = resp & 0xff;
256
pkg_dev->levels = (resp >> 8) & 0xff;
257
pkg_dev->current_level = (resp >> 16) & 0xff;
258
pkg_dev->locked = !!(resp & BIT(24));
259
pkg_dev->enabled = !!(resp & BIT(31));
260
261
return 0;
262
}
263
264
static int mbox_get_ctdp_control(struct isst_id *id, int config_index,
265
struct isst_pkg_ctdp_level_info *ctdp_level)
266
{
267
int cp_state, cp_cap;
268
unsigned int resp;
269
int ret;
270
271
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
272
CONFIG_TDP_GET_TDP_CONTROL, 0,
273
config_index, &resp);
274
if (ret)
275
return ret;
276
277
ctdp_level->fact_support = resp & BIT(0);
278
ctdp_level->pbf_support = !!(resp & BIT(1));
279
ctdp_level->fact_enabled = !!(resp & BIT(16));
280
ctdp_level->pbf_enabled = !!(resp & BIT(17));
281
282
ret = isst_read_pm_config(id, &cp_state, &cp_cap);
283
if (ret) {
284
debug_printf("cpu:%d pm_config is not supported\n", id->cpu);
285
} else {
286
debug_printf("cpu:%d pm_config SST-CP state:%d cap:%d\n", id->cpu, cp_state, cp_cap);
287
ctdp_level->sst_cp_support = cp_cap;
288
ctdp_level->sst_cp_enabled = cp_state;
289
}
290
291
debug_printf(
292
"cpu:%d CONFIG_TDP_GET_TDP_CONTROL resp:%x fact_support:%d pbf_support: %d fact_enabled:%d pbf_enabled:%d\n",
293
id->cpu, resp, ctdp_level->fact_support, ctdp_level->pbf_support,
294
ctdp_level->fact_enabled, ctdp_level->pbf_enabled);
295
296
return 0;
297
}
298
299
static void _get_uncore_p0_p1_info(struct isst_id *id, int config_index,
300
struct isst_pkg_ctdp_level_info *ctdp_level)
301
{
302
unsigned int resp;
303
int ret;
304
305
ctdp_level->uncore_pm = 0;
306
ctdp_level->uncore_p0 = 0;
307
ctdp_level->uncore_p1 = 0;
308
309
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
310
CONFIG_TDP_GET_RATIO_INFO, 0,
311
(BIT(16) | config_index) , &resp);
312
if (ret) {
313
goto try_uncore_mbox;
314
}
315
316
ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
317
ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
318
ctdp_level->uncore_pm = (resp & GENMASK(31, 24)) >> 24;
319
320
debug_printf(
321
"cpu:%d ctdp:%d CONFIG_TDP_GET_RATIO_INFO resp:%x uncore p0:%d uncore p1:%d uncore pm:%d\n",
322
id->cpu, config_index, resp, ctdp_level->uncore_p0, ctdp_level->uncore_p1,
323
ctdp_level->uncore_pm);
324
325
return;
326
327
try_uncore_mbox:
328
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
329
CONFIG_TDP_GET_UNCORE_P0_P1_INFO, 0,
330
config_index, &resp);
331
if (ret) {
332
ctdp_level->uncore_p0 = 0;
333
ctdp_level->uncore_p1 = 0;
334
return;
335
}
336
337
ctdp_level->uncore_p0 = resp & GENMASK(7, 0);
338
ctdp_level->uncore_p1 = (resp & GENMASK(15, 8)) >> 8;
339
debug_printf(
340
"cpu:%d ctdp:%d CONFIG_TDP_GET_UNCORE_P0_P1_INFO resp:%x uncore p0:%d uncore p1:%d\n",
341
id->cpu, config_index, resp, ctdp_level->uncore_p0,
342
ctdp_level->uncore_p1);
343
}
344
345
static int _set_uncore_min_max(struct isst_id *id, int max, int freq)
346
{
347
char buffer[128], freq_str[16];
348
int fd, ret, len;
349
350
if (max)
351
snprintf(buffer, sizeof(buffer),
352
"/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/max_freq_khz", id->pkg, id->die);
353
else
354
snprintf(buffer, sizeof(buffer),
355
"/sys/devices/system/cpu/intel_uncore_frequency/package_%02d_die_%02d/min_freq_khz", id->pkg, id->die);
356
357
fd = open(buffer, O_WRONLY);
358
if (fd < 0)
359
return fd;
360
361
snprintf(freq_str, sizeof(freq_str), "%d", freq);
362
len = strlen(freq_str);
363
ret = write(fd, freq_str, len);
364
if (ret == -1) {
365
close(fd);
366
return ret;
367
}
368
close(fd);
369
370
return 0;
371
}
372
373
static void mbox_adjust_uncore_freq(struct isst_id *id, int config_index,
374
struct isst_pkg_ctdp_level_info *ctdp_level)
375
{
376
_get_uncore_p0_p1_info(id, config_index, ctdp_level);
377
if (ctdp_level->uncore_pm)
378
_set_uncore_min_max(id, 0, ctdp_level->uncore_pm * 100000);
379
380
if (ctdp_level->uncore_p0)
381
_set_uncore_min_max(id, 1, ctdp_level->uncore_p0 * 100000);
382
}
383
384
static void _get_p1_info(struct isst_id *id, int config_index,
385
struct isst_pkg_ctdp_level_info *ctdp_level)
386
{
387
unsigned int resp;
388
int ret;
389
ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_P1_INFO, 0,
390
config_index, &resp);
391
if (ret) {
392
ctdp_level->sse_p1 = 0;
393
ctdp_level->avx2_p1 = 0;
394
ctdp_level->avx512_p1 = 0;
395
return;
396
}
397
398
ctdp_level->sse_p1 = resp & GENMASK(7, 0);
399
ctdp_level->avx2_p1 = (resp & GENMASK(15, 8)) >> 8;
400
ctdp_level->avx512_p1 = (resp & GENMASK(23, 16)) >> 16;
401
ctdp_level->amx_p1 = (resp & GENMASK(31, 24)) >> 24;
402
debug_printf(
403
"cpu:%d ctdp:%d CONFIG_TDP_GET_P1_INFO resp:%x sse_p1:%d avx2_p1:%d avx512_p1:%d amx_p1:%d\n",
404
id->cpu, config_index, resp, ctdp_level->sse_p1,
405
ctdp_level->avx2_p1, ctdp_level->avx512_p1, ctdp_level->amx_p1);
406
}
407
408
static void _get_uncore_mem_freq(struct isst_id *id, int config_index,
409
struct isst_pkg_ctdp_level_info *ctdp_level)
410
{
411
unsigned int resp;
412
int ret;
413
414
ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_MEM_FREQ,
415
0, config_index, &resp);
416
if (ret) {
417
ctdp_level->mem_freq = 0;
418
return;
419
}
420
421
ctdp_level->mem_freq = resp & GENMASK(7, 0);
422
if (is_spr_platform() || is_emr_platform()) {
423
ctdp_level->mem_freq *= 200;
424
} else if (is_icx_platform()) {
425
if (ctdp_level->mem_freq < 7) {
426
ctdp_level->mem_freq = (12 - ctdp_level->mem_freq) * 133.33 * 2 * 10;
427
ctdp_level->mem_freq /= 10;
428
if (ctdp_level->mem_freq % 10 > 5)
429
ctdp_level->mem_freq++;
430
} else {
431
ctdp_level->mem_freq = 0;
432
}
433
} else {
434
ctdp_level->mem_freq = 0;
435
}
436
debug_printf(
437
"cpu:%d ctdp:%d CONFIG_TDP_GET_MEM_FREQ resp:%x uncore mem_freq:%d\n",
438
id->cpu, config_index, resp, ctdp_level->mem_freq);
439
}
440
441
static int mbox_get_tdp_info(struct isst_id *id, int config_index,
442
struct isst_pkg_ctdp_level_info *ctdp_level)
443
{
444
unsigned int resp;
445
int ret;
446
447
ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TDP_INFO,
448
0, config_index, &resp);
449
if (ret) {
450
isst_display_error_info_message(1, "Invalid level, Can't get TDP information at level", 1, config_index);
451
return ret;
452
}
453
454
ctdp_level->pkg_tdp = resp & GENMASK(14, 0);
455
ctdp_level->tdp_ratio = (resp & GENMASK(23, 16)) >> 16;
456
457
debug_printf(
458
"cpu:%d ctdp:%d CONFIG_TDP_GET_TDP_INFO resp:%x tdp_ratio:%d pkg_tdp:%d\n",
459
id->cpu, config_index, resp, ctdp_level->tdp_ratio,
460
ctdp_level->pkg_tdp);
461
462
ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_TJMAX_INFO,
463
0, config_index, &resp);
464
if (ret)
465
return ret;
466
467
ctdp_level->t_proc_hot = resp & GENMASK(7, 0);
468
469
_get_uncore_p0_p1_info(id, config_index, ctdp_level);
470
_get_p1_info(id, config_index, ctdp_level);
471
_get_uncore_mem_freq(id, config_index, ctdp_level);
472
473
debug_printf(
474
"cpu:%d ctdp:%d CONFIG_TDP_GET_TJMAX_INFO resp:%x t_proc_hot:%d\n",
475
id->cpu, config_index, resp, ctdp_level->t_proc_hot);
476
477
return 0;
478
}
479
480
static int mbox_get_pwr_info(struct isst_id *id, int config_index,
481
struct isst_pkg_ctdp_level_info *ctdp_level)
482
{
483
unsigned int resp;
484
int ret;
485
486
ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_GET_PWR_INFO,
487
0, config_index, &resp);
488
if (ret)
489
return ret;
490
491
ctdp_level->pkg_max_power = resp & GENMASK(14, 0);
492
ctdp_level->pkg_min_power = (resp & GENMASK(30, 16)) >> 16;
493
494
debug_printf(
495
"cpu:%d ctdp:%d CONFIG_TDP_GET_PWR_INFO resp:%x pkg_max_power:%d pkg_min_power:%d\n",
496
id->cpu, config_index, resp, ctdp_level->pkg_max_power,
497
ctdp_level->pkg_min_power);
498
499
return 0;
500
}
501
502
static int mbox_get_coremask_info(struct isst_id *id, int config_index,
503
struct isst_pkg_ctdp_level_info *ctdp_level)
504
{
505
unsigned int resp;
506
int i, ret;
507
508
ctdp_level->cpu_count = 0;
509
for (i = 0; i < 2; ++i) {
510
unsigned long long mask;
511
int cpu_count = 0;
512
513
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
514
CONFIG_TDP_GET_CORE_MASK, 0,
515
(i << 8) | config_index, &resp);
516
if (ret)
517
return ret;
518
519
debug_printf(
520
"cpu:%d ctdp:%d mask:%d CONFIG_TDP_GET_CORE_MASK resp:%x\n",
521
id->cpu, config_index, i, resp);
522
523
mask = (unsigned long long)resp << (32 * i);
524
set_cpu_mask_from_punit_coremask(id, mask,
525
ctdp_level->core_cpumask_size,
526
ctdp_level->core_cpumask,
527
&cpu_count);
528
ctdp_level->cpu_count += cpu_count;
529
debug_printf("cpu:%d ctdp:%d mask:%d cpu count:%d\n", id->cpu,
530
config_index, i, ctdp_level->cpu_count);
531
}
532
533
return 0;
534
}
535
536
static int mbox_get_get_trl(struct isst_id *id, int level, int avx_level, int *trl)
537
{
538
unsigned int req, resp;
539
int ret;
540
541
req = level | (avx_level << 16);
542
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
543
CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
544
&resp);
545
if (ret)
546
return ret;
547
548
debug_printf(
549
"cpu:%d CONFIG_TDP_GET_TURBO_LIMIT_RATIOS req:%x resp:%x\n",
550
id->cpu, req, resp);
551
552
trl[0] = resp & GENMASK(7, 0);
553
trl[1] = (resp & GENMASK(15, 8)) >> 8;
554
trl[2] = (resp & GENMASK(23, 16)) >> 16;
555
trl[3] = (resp & GENMASK(31, 24)) >> 24;
556
557
req = level | BIT(8) | (avx_level << 16);
558
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
559
CONFIG_TDP_GET_TURBO_LIMIT_RATIOS, 0, req,
560
&resp);
561
if (ret)
562
return ret;
563
564
debug_printf("cpu:%d CONFIG_TDP_GET_TURBO_LIMIT req:%x resp:%x\n", id->cpu,
565
req, resp);
566
567
trl[4] = resp & GENMASK(7, 0);
568
trl[5] = (resp & GENMASK(15, 8)) >> 8;
569
trl[6] = (resp & GENMASK(23, 16)) >> 16;
570
trl[7] = (resp & GENMASK(31, 24)) >> 24;
571
572
return 0;
573
}
574
575
static int mbox_get_get_trls(struct isst_id *id, int level, struct isst_pkg_ctdp_level_info *ctdp_level)
576
{
577
int trl_max_levels = isst_get_trl_max_levels();
578
int i, ret;
579
580
for (i = 0; i < trl_max_levels; i++) {
581
ret = mbox_get_get_trl(id, level, i, ctdp_level->trl_ratios[i]);
582
if (ret)
583
return ret;
584
}
585
return 0;
586
}
587
588
static int mbox_get_trl_bucket_info(struct isst_id *id, int level, unsigned long long *buckets_info)
589
{
590
int ret;
591
592
debug_printf("cpu:%d bucket info via MSR\n", id->cpu);
593
594
*buckets_info = 0;
595
596
ret = isst_send_msr_command(id->cpu, 0x1ae, 0, buckets_info);
597
if (ret)
598
return ret;
599
600
debug_printf("cpu:%d bucket info via MSR successful 0x%llx\n", id->cpu,
601
*buckets_info);
602
603
return 0;
604
}
605
606
static int mbox_set_tdp_level(struct isst_id *id, int tdp_level)
607
{
608
unsigned int resp;
609
int ret;
610
611
612
if (isst_get_config_tdp_lock_status(id)) {
613
isst_display_error_info_message(1, "TDP is locked", 0, 0);
614
return -1;
615
616
}
617
618
ret = _send_mbox_command(id->cpu, CONFIG_TDP, CONFIG_TDP_SET_LEVEL, 0,
619
tdp_level, &resp);
620
if (ret) {
621
isst_display_error_info_message(1, "Set TDP level failed for level", 1, tdp_level);
622
return ret;
623
}
624
625
return 0;
626
}
627
628
static int mbox_get_pbf_info(struct isst_id *id, int level, struct isst_pbf_info *pbf_info)
629
{
630
int max_punit_core, max_mask_index;
631
unsigned int req, resp;
632
int i, ret;
633
634
max_punit_core = get_max_punit_core_id(id);
635
max_mask_index = max_punit_core > 32 ? 2 : 1;
636
637
for (i = 0; i < max_mask_index; ++i) {
638
unsigned long long mask;
639
int count;
640
641
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
642
CONFIG_TDP_PBF_GET_CORE_MASK_INFO,
643
0, (i << 8) | level, &resp);
644
if (ret)
645
break;
646
647
debug_printf(
648
"cpu:%d CONFIG_TDP_PBF_GET_CORE_MASK_INFO resp:%x\n",
649
id->cpu, resp);
650
651
mask = (unsigned long long)resp << (32 * i);
652
set_cpu_mask_from_punit_coremask(id, mask,
653
pbf_info->core_cpumask_size,
654
pbf_info->core_cpumask,
655
&count);
656
}
657
658
req = level;
659
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
660
CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO, 0, req,
661
&resp);
662
if (ret)
663
return ret;
664
665
debug_printf("cpu:%d CONFIG_TDP_PBF_GET_P1HI_P1LO_INFO resp:%x\n", id->cpu,
666
resp);
667
668
pbf_info->p1_low = resp & 0xff;
669
pbf_info->p1_high = (resp & GENMASK(15, 8)) >> 8;
670
671
req = level;
672
ret = _send_mbox_command(
673
id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TDP_INFO, 0, req, &resp);
674
if (ret)
675
return ret;
676
677
debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TDP_INFO resp:%x\n", id->cpu, resp);
678
679
pbf_info->tdp = resp & 0xffff;
680
681
req = level;
682
ret = _send_mbox_command(
683
id->cpu, CONFIG_TDP, CONFIG_TDP_PBF_GET_TJ_MAX_INFO, 0, req, &resp);
684
if (ret)
685
return ret;
686
687
debug_printf("cpu:%d CONFIG_TDP_PBF_GET_TJ_MAX_INFO resp:%x\n", id->cpu,
688
resp);
689
pbf_info->t_control = (resp >> 8) & 0xff;
690
pbf_info->t_prochot = resp & 0xff;
691
692
return 0;
693
}
694
695
static int mbox_set_pbf_fact_status(struct isst_id *id, int pbf, int enable)
696
{
697
struct isst_pkg_ctdp pkg_dev;
698
struct isst_pkg_ctdp_level_info ctdp_level;
699
int current_level;
700
unsigned int req = 0, resp;
701
int ret;
702
703
ret = isst_get_ctdp_levels(id, &pkg_dev);
704
if (ret)
705
debug_printf("cpu:%d No support for dynamic ISST\n", id->cpu);
706
707
current_level = pkg_dev.current_level;
708
709
ret = isst_get_ctdp_control(id, current_level, &ctdp_level);
710
if (ret)
711
return ret;
712
713
if (pbf) {
714
if (ctdp_level.fact_enabled)
715
req = BIT(16);
716
717
if (enable)
718
req |= BIT(17);
719
else
720
req &= ~BIT(17);
721
} else {
722
723
if (enable && !ctdp_level.sst_cp_enabled)
724
isst_display_error_info_message(0, "Make sure to execute before: core-power enable", 0, 0);
725
726
if (ctdp_level.pbf_enabled)
727
req = BIT(17);
728
729
if (enable)
730
req |= BIT(16);
731
else
732
req &= ~BIT(16);
733
}
734
735
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
736
CONFIG_TDP_SET_TDP_CONTROL, 0, req, &resp);
737
if (ret)
738
return ret;
739
740
debug_printf("cpu:%d CONFIG_TDP_SET_TDP_CONTROL pbf/fact:%d req:%x\n",
741
id->cpu, pbf, req);
742
743
return 0;
744
}
745
746
static int _get_fact_bucket_info(struct isst_id *id, int level,
747
struct isst_fact_bucket_info *bucket_info)
748
{
749
int trl_max_levels = isst_get_trl_max_levels();
750
unsigned int resp;
751
int i, k, ret;
752
753
for (i = 0; i < 2; ++i) {
754
int j;
755
756
ret = _send_mbox_command(
757
id->cpu, CONFIG_TDP,
758
CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
759
(i << 8) | level, &resp);
760
if (ret)
761
return ret;
762
763
debug_printf(
764
"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
765
id->cpu, i, level, resp);
766
767
for (j = 0; j < 4; ++j) {
768
bucket_info[j + (i * 4)].hp_cores =
769
(resp >> (j * 8)) & 0xff;
770
}
771
}
772
773
for (k = 0; k < trl_max_levels; ++k) {
774
for (i = 0; i < 2; ++i) {
775
int j;
776
777
ret = _send_mbox_command(
778
id->cpu, CONFIG_TDP,
779
CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
780
(k << 16) | (i << 8) | level, &resp);
781
if (ret)
782
return ret;
783
784
debug_printf(
785
"cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
786
id->cpu, i, level, k, resp);
787
788
for (j = 0; j < 4; ++j) {
789
bucket_info[j + (i * 4)].hp_ratios[k] =
790
(resp >> (j * 8)) & 0xff;
791
}
792
}
793
}
794
795
return 0;
796
}
797
798
static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
799
{
800
unsigned int resp;
801
int j, ret, print;
802
803
ret = _send_mbox_command(id->cpu, CONFIG_TDP,
804
CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
805
level, &resp);
806
if (ret)
807
return ret;
808
809
debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
810
id->cpu, resp);
811
812
fact_info->lp_ratios[0] = resp & 0xff;
813
fact_info->lp_ratios[1] = (resp >> 8) & 0xff;
814
fact_info->lp_ratios[2] = (resp >> 16) & 0xff;
815
816
ret = _get_fact_bucket_info(id, level, fact_info->bucket_info);
817
if (ret)
818
return ret;
819
820
print = 0;
821
for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
822
if (fact_bucket != 0xff && fact_bucket != j)
823
continue;
824
825
if (!fact_info->bucket_info[j].hp_cores)
826
break;
827
828
print = 1;
829
}
830
if (!print) {
831
isst_display_error_info_message(1, "Invalid bucket", 0, 0);
832
return -1;
833
}
834
835
return 0;
836
}
837
838
static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type)
839
{
840
unsigned int resp;
841
int ret;
842
843
ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
844
&resp);
845
if (ret)
846
return ret;
847
848
debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
849
850
if (resp & BIT(1))
851
*enable = 1;
852
else
853
*enable = 0;
854
855
if (resp & BIT(2))
856
*type = 1;
857
else
858
*type = 0;
859
860
return 0;
861
}
862
863
static int _write_pm_config(struct isst_id *id, int cp_state)
864
{
865
unsigned int req, resp;
866
int ret;
867
868
if (cp_state)
869
req = BIT(16);
870
else
871
req = 0;
872
873
ret = _send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
874
&resp);
875
if (ret)
876
return ret;
877
878
debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
879
880
return 0;
881
}
882
883
static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
884
{
885
unsigned int req, resp;
886
int ret;
887
888
if (!enable_clos) {
889
struct isst_pkg_ctdp pkg_dev;
890
struct isst_pkg_ctdp_level_info ctdp_level;
891
892
ret = isst_get_ctdp_levels(id, &pkg_dev);
893
if (ret) {
894
debug_printf("isst_get_ctdp_levels\n");
895
return ret;
896
}
897
898
ret = isst_get_ctdp_control(id, pkg_dev.current_level,
899
&ctdp_level);
900
if (ret)
901
return ret;
902
903
if (ctdp_level.fact_enabled) {
904
isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
905
return -EINVAL;
906
}
907
ret = _write_pm_config(id, 0);
908
if (ret)
909
isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
910
} else {
911
ret = _write_pm_config(id, 1);
912
if (ret)
913
isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
914
}
915
916
ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
917
&resp);
918
if (ret) {
919
isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
920
return ret;
921
}
922
923
debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
924
925
req = resp;
926
927
if (enable_clos)
928
req = req | BIT(1);
929
else
930
req = req & ~BIT(1);
931
932
if (priority_type > 1)
933
isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
934
935
if (priority_type)
936
req = req | BIT(2);
937
else
938
req = req & ~BIT(2);
939
940
ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
941
BIT(MBOX_CMD_WRITE_BIT), req, &resp);
942
if (ret)
943
return ret;
944
945
debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
946
priority_type, req);
947
948
return 0;
949
}
950
951
static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
952
{
953
unsigned int resp;
954
int ret;
955
956
ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
957
&resp);
958
if (ret)
959
return ret;
960
961
clos_config->epp = resp & 0x0f;
962
clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
963
clos_config->clos_min = (resp >> 8) & 0xff;
964
clos_config->clos_max = (resp >> 16) & 0xff;
965
clos_config->clos_desired = (resp >> 24) & 0xff;
966
967
return 0;
968
}
969
970
static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
971
{
972
unsigned int req, resp;
973
unsigned int param;
974
int ret;
975
976
req = clos_config->epp & 0x0f;
977
req |= (clos_config->clos_prop_prio & 0x0f) << 4;
978
req |= (clos_config->clos_min & 0xff) << 8;
979
req |= (clos_config->clos_max & 0xff) << 16;
980
req |= (clos_config->clos_desired & 0xff) << 24;
981
982
param = BIT(MBOX_CMD_WRITE_BIT) | clos;
983
984
ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
985
&resp);
986
if (ret)
987
return ret;
988
989
debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
990
991
return 0;
992
}
993
994
static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id)
995
{
996
unsigned int resp;
997
unsigned int param;
998
int core_id, ret;
999
1000
core_id = find_phy_core_num(id->cpu);
1001
param = core_id;
1002
1003
ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
1004
&resp);
1005
if (ret)
1006
return ret;
1007
1008
debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
1009
resp);
1010
*clos_id = (resp >> 16) & 0x03;
1011
1012
return 0;
1013
}
1014
1015
static int mbox_clos_associate(struct isst_id *id, int clos_id)
1016
{
1017
unsigned int req, resp;
1018
unsigned int param;
1019
int core_id, ret;
1020
1021
req = (clos_id & 0x03) << 16;
1022
core_id = find_phy_core_num(id->cpu);
1023
param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
1024
1025
ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
1026
req, &resp);
1027
if (ret)
1028
return ret;
1029
1030
debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
1031
req);
1032
1033
return 0;
1034
}
1035
1036
static struct isst_platform_ops mbox_ops = {
1037
.get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,
1038
.get_trl_max_levels = mbox_get_trl_max_levels,
1039
.get_trl_level_name = mbox_get_trl_level_name,
1040
.update_platform_param = mbox_update_platform_param,
1041
.is_punit_valid = mbox_is_punit_valid,
1042
.read_pm_config = mbox_read_pm_config,
1043
.get_config_levels = mbox_get_config_levels,
1044
.get_ctdp_control = mbox_get_ctdp_control,
1045
.get_tdp_info = mbox_get_tdp_info,
1046
.get_pwr_info = mbox_get_pwr_info,
1047
.get_coremask_info = mbox_get_coremask_info,
1048
.get_get_trl = mbox_get_get_trl,
1049
.get_get_trls = mbox_get_get_trls,
1050
.get_trl_bucket_info = mbox_get_trl_bucket_info,
1051
.set_tdp_level = mbox_set_tdp_level,
1052
.get_pbf_info = mbox_get_pbf_info,
1053
.set_pbf_fact_status = mbox_set_pbf_fact_status,
1054
.get_fact_info = mbox_get_fact_info,
1055
.adjust_uncore_freq = mbox_adjust_uncore_freq,
1056
.get_clos_information = mbox_get_clos_information,
1057
.pm_qos_config = mbox_pm_qos_config,
1058
.pm_get_clos = mbox_pm_get_clos,
1059
.set_clos = mbox_set_clos,
1060
.clos_get_assoc_status = mbox_clos_get_assoc_status,
1061
.clos_associate = mbox_clos_associate,
1062
};
1063
1064
struct isst_platform_ops *mbox_get_platform_ops(void)
1065
{
1066
return &mbox_ops;
1067
}
1068
1069