arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / tools / power / x86 / intel-speed-select / isst-core-mbox.c
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         unsigned int resp;
750         int i, k, ret;
751
752         for (i = 0; i < 2; ++i) {
753                 int j;
754
755                 ret = _send_mbox_command(
756                         id->cpu, CONFIG_TDP,
757                         CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES, 0,
758                         (i << 8) | level, &resp);
759                 if (ret)
760                         return ret;
761
762                 debug_printf(
763                         "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_NUMCORES index:%d level:%d resp:%x\n",
764                         id->cpu, i, level, resp);
765
766                 for (j = 0; j < 4; ++j) {
767                         bucket_info[j + (i * 4)].hp_cores =
768                                 (resp >> (j * 8)) & 0xff;
769                 }
770         }
771
772         for (k = 0; k < 3; ++k) {
773                 for (i = 0; i < 2; ++i) {
774                         int j;
775
776                         ret = _send_mbox_command(
777                                 id->cpu, CONFIG_TDP,
778                                 CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS, 0,
779                                 (k << 16) | (i << 8) | level, &resp);
780                         if (ret)
781                                 return ret;
782
783                         debug_printf(
784                                 "cpu:%d CONFIG_TDP_GET_FACT_HP_TURBO_LIMIT_RATIOS index:%d level:%d avx:%d resp:%x\n",
785                                 id->cpu, i, level, k, resp);
786
787                         for (j = 0; j < 4; ++j) {
788                                 bucket_info[j + (i * 4)].hp_ratios[k] =
789                                         (resp >> (j * 8)) & 0xff;
790                         }
791                 }
792         }
793
794         return 0;
795 }
796
797 static int mbox_get_fact_info(struct isst_id *id, int level, int fact_bucket, struct isst_fact_info *fact_info)
798 {
799         unsigned int resp;
800         int j, ret, print;
801
802         ret = _send_mbox_command(id->cpu, CONFIG_TDP,
803                                      CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO, 0,
804                                      level, &resp);
805         if (ret)
806                 return ret;
807
808         debug_printf("cpu:%d CONFIG_TDP_GET_FACT_LP_CLIPPING_RATIO resp:%x\n",
809                      id->cpu, resp);
810
811         fact_info->lp_ratios[0] = resp & 0xff;
812         fact_info->lp_ratios[1] = (resp >> 8) & 0xff;
813         fact_info->lp_ratios[2] = (resp >> 16) & 0xff;
814
815         ret = _get_fact_bucket_info(id, level, fact_info->bucket_info);
816         if (ret)
817                 return ret;
818
819         print = 0;
820         for (j = 0; j < ISST_FACT_MAX_BUCKETS; ++j) {
821                 if (fact_bucket != 0xff && fact_bucket != j)
822                         continue;
823
824                 if (!fact_info->bucket_info[j].hp_cores)
825                         break;
826
827                 print = 1;
828         }
829         if (!print) {
830                 isst_display_error_info_message(1, "Invalid bucket", 0, 0);
831                 return -1;
832         }
833
834         return 0;
835 }
836
837 static int mbox_get_clos_information(struct isst_id *id, int *enable, int *type)
838 {
839         unsigned int resp;
840         int ret;
841
842         ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
843                                      &resp);
844         if (ret)
845                 return ret;
846
847         debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
848
849         if (resp & BIT(1))
850                 *enable = 1;
851         else
852                 *enable = 0;
853
854         if (resp & BIT(2))
855                 *type = 1;
856         else
857                 *type = 0;
858
859         return 0;
860 }
861
862 static int _write_pm_config(struct isst_id *id, int cp_state)
863 {
864         unsigned int req, resp;
865         int ret;
866
867         if (cp_state)
868                 req = BIT(16);
869         else
870                 req = 0;
871
872         ret = _send_mbox_command(id->cpu, WRITE_PM_CONFIG, PM_FEATURE, 0, req,
873                                      &resp);
874         if (ret)
875                 return ret;
876
877         debug_printf("cpu:%d WRITE_PM_CONFIG resp:%x\n", id->cpu, resp);
878
879         return 0;
880 }
881
882 static int mbox_pm_qos_config(struct isst_id *id, int enable_clos, int priority_type)
883 {
884         unsigned int req, resp;
885         int ret;
886
887         if (!enable_clos) {
888                 struct isst_pkg_ctdp pkg_dev;
889                 struct isst_pkg_ctdp_level_info ctdp_level;
890
891                 ret = isst_get_ctdp_levels(id, &pkg_dev);
892                 if (ret) {
893                         debug_printf("isst_get_ctdp_levels\n");
894                         return ret;
895                 }
896
897                 ret = isst_get_ctdp_control(id, pkg_dev.current_level,
898                                             &ctdp_level);
899                 if (ret)
900                         return ret;
901
902                 if (ctdp_level.fact_enabled) {
903                         isst_display_error_info_message(1, "Ignoring request, turbo-freq feature is still enabled", 0, 0);
904                         return -EINVAL;
905                 }
906                 ret = _write_pm_config(id, 0);
907                 if (ret)
908                         isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
909         } else {
910                 ret = _write_pm_config(id, 1);
911                 if (ret)
912                         isst_display_error_info_message(0, "WRITE_PM_CONFIG command failed, ignoring error", 0, 0);
913         }
914
915         ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG, 0, 0,
916                                      &resp);
917         if (ret) {
918                 isst_display_error_info_message(1, "CLOS_PM_QOS_CONFIG command failed", 0, 0);
919                 return ret;
920         }
921
922         debug_printf("cpu:%d CLOS_PM_QOS_CONFIG resp:%x\n", id->cpu, resp);
923
924         req = resp;
925
926         if (enable_clos)
927                 req = req | BIT(1);
928         else
929                 req = req & ~BIT(1);
930
931         if (priority_type > 1)
932                 isst_display_error_info_message(1, "Invalid priority type: Changing type to ordered", 0, 0);
933
934         if (priority_type)
935                 req = req | BIT(2);
936         else
937                 req = req & ~BIT(2);
938
939         ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_QOS_CONFIG,
940                                      BIT(MBOX_CMD_WRITE_BIT), req, &resp);
941         if (ret)
942                 return ret;
943
944         debug_printf("cpu:%d CLOS_PM_QOS_CONFIG priority type:%d req:%x\n", id->cpu,
945                      priority_type, req);
946
947         return 0;
948 }
949
950 static int mbox_pm_get_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
951 {
952         unsigned int resp;
953         int ret;
954
955         ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, clos, 0,
956                                      &resp);
957         if (ret)
958                 return ret;
959
960         clos_config->epp = resp & 0x0f;
961         clos_config->clos_prop_prio = (resp >> 4) & 0x0f;
962         clos_config->clos_min = (resp >> 8) & 0xff;
963         clos_config->clos_max = (resp >> 16) & 0xff;
964         clos_config->clos_desired = (resp >> 24) & 0xff;
965
966         return 0;
967 }
968
969 static int mbox_set_clos(struct isst_id *id, int clos, struct isst_clos_config *clos_config)
970 {
971         unsigned int req, resp;
972         unsigned int param;
973         int ret;
974
975         req = clos_config->epp & 0x0f;
976         req |= (clos_config->clos_prop_prio & 0x0f) << 4;
977         req |= (clos_config->clos_min & 0xff) << 8;
978         req |= (clos_config->clos_max & 0xff) << 16;
979         req |= (clos_config->clos_desired & 0xff) << 24;
980
981         param = BIT(MBOX_CMD_WRITE_BIT) | clos;
982
983         ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PM_CLOS, param, req,
984                                      &resp);
985         if (ret)
986                 return ret;
987
988         debug_printf("cpu:%d CLOS_PM_CLOS param:%x req:%x\n", id->cpu, param, req);
989
990         return 0;
991 }
992
993 static int mbox_clos_get_assoc_status(struct isst_id *id, int *clos_id)
994 {
995         unsigned int resp;
996         unsigned int param;
997         int core_id, ret;
998
999         core_id = find_phy_core_num(id->cpu);
1000         param = core_id;
1001
1002         ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param, 0,
1003                                      &resp);
1004         if (ret)
1005                 return ret;
1006
1007         debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x resp:%x\n", id->cpu, param,
1008                      resp);
1009         *clos_id = (resp >> 16) & 0x03;
1010
1011         return 0;
1012 }
1013
1014 static int mbox_clos_associate(struct isst_id *id, int clos_id)
1015 {
1016         unsigned int req, resp;
1017         unsigned int param;
1018         int core_id, ret;
1019
1020         req = (clos_id & 0x03) << 16;
1021         core_id = find_phy_core_num(id->cpu);
1022         param = BIT(MBOX_CMD_WRITE_BIT) | core_id;
1023
1024         ret = _send_mbox_command(id->cpu, CONFIG_CLOS, CLOS_PQR_ASSOC, param,
1025                                      req, &resp);
1026         if (ret)
1027                 return ret;
1028
1029         debug_printf("cpu:%d CLOS_PQR_ASSOC param:%x req:%x\n", id->cpu, param,
1030                      req);
1031
1032         return 0;
1033 }
1034
1035 static struct isst_platform_ops mbox_ops = {
1036         .get_disp_freq_multiplier = mbox_get_disp_freq_multiplier,
1037         .get_trl_max_levels = mbox_get_trl_max_levels,
1038         .get_trl_level_name = mbox_get_trl_level_name,
1039         .update_platform_param = mbox_update_platform_param,
1040         .is_punit_valid = mbox_is_punit_valid,
1041         .read_pm_config = mbox_read_pm_config,
1042         .get_config_levels = mbox_get_config_levels,
1043         .get_ctdp_control = mbox_get_ctdp_control,
1044         .get_tdp_info = mbox_get_tdp_info,
1045         .get_pwr_info = mbox_get_pwr_info,
1046         .get_coremask_info = mbox_get_coremask_info,
1047         .get_get_trl = mbox_get_get_trl,
1048         .get_get_trls = mbox_get_get_trls,
1049         .get_trl_bucket_info = mbox_get_trl_bucket_info,
1050         .set_tdp_level = mbox_set_tdp_level,
1051         .get_pbf_info = mbox_get_pbf_info,
1052         .set_pbf_fact_status = mbox_set_pbf_fact_status,
1053         .get_fact_info = mbox_get_fact_info,
1054         .adjust_uncore_freq = mbox_adjust_uncore_freq,
1055         .get_clos_information = mbox_get_clos_information,
1056         .pm_qos_config = mbox_pm_qos_config,
1057         .pm_get_clos = mbox_pm_get_clos,
1058         .set_clos = mbox_set_clos,
1059         .clos_get_assoc_status = mbox_clos_get_assoc_status,
1060         .clos_associate = mbox_clos_associate,
1061 };
1062
1063 struct isst_platform_ops *mbox_get_platform_ops(void)
1064 {
1065         return &mbox_ops;
1066 }